]> git.neil.brown.name Git - LaFS.git/commitdiff
Retard cleaner more when space is tight.
authorNeilBrown <neilb@suse.de>
Fri, 9 Jul 2010 06:18:56 +0000 (16:18 +1000)
committerNeilBrown <neilb@suse.de>
Fri, 9 Jul 2010 06:18:56 +0000 (16:18 +1000)
If there is no space in any 'cleaner segment' to clean to, then
only clean if there are no 'clean' (but not 'free') segments.
As soon as we make a clean segment, we should stop cleaning and
allow a checkpoint to make the clean segment free so maybe more
progress can be made.

Signed-off-by: NeilBrown <neilb@suse.de>
clean.c
cluster.c

diff --git a/clean.c b/clean.c
index d59dc428a4c747208136cfad3c2f6dc2ce89aadc..54405d4370a73f303507c31b0c1a7ef75940c46a 100644 (file)
--- a/clean.c
+++ b/clean.c
@@ -597,11 +597,20 @@ static unsigned long do_clean(struct fs *fs)
                T -= 4 * fs->max_segment;
 
                max_segs = lafs_alloc_cleaner_segs(fs, 4);
-               if (max_segs < 1)
-                       /* if we can only clean to main segment, do it
-                        * but only do one segment at a time
+               if (max_segs < 1) {
+                       /* If we can only clean to main segment, we may
+                        * have to.  However:
+                        *  - only do one segment at a time
+                        *  - if there is any clean_reserved, then use it
+                        *  - if there are no 'clean' segments, then clean.
+                        *  - if CleanerBlocks, then clean.
+                        *  otherwise don't.
                         */
-                       max_segs = 1;
+                       if (fs->clean_reserved
+                           || fs->segtrack->clean.cnt == 0
+                           || test_bit(CleanerBlocks, &fs->fsstate))
+                               max_segs = 1;
+               }
                for (i = 0; i < max_segs; i++) {
                        struct toclean *tc = &fs->cleaner.seg[i];
                        u64 C = fs->free_blocks + fs->clean_reserved
index 526fb9d1fd9ff2b8006cb69aee425d8b7568bdb4..96b9afa7bc2c89182b58f1ba3c0320083cb9233d 100644 (file)
--- a/cluster.c
+++ b/cluster.c
@@ -432,11 +432,19 @@ static int new_segment(struct fs *fs, int cnum)
 
        close_segment(fs, cnum);
 
-       /* FIXME if clean_reserve is too small, maybe
-        * clear it completely.
-        */
-       if ((cnum && fs->clean_reserved < fs->max_segment))
-                       return -ENOSPC;
+       if (cnum && fs->clean_reserved < fs->max_segment) {
+               /* we have reached the end of the last cleaner
+                * segment.  The remainder of clean_reserved
+                * is of no value (if there even is any
+                */
+               if (fs->clean_reserved) {
+                       spin_lock(&fs->alloc_lock);
+                       fs->free_blocks += fs->clean_reserved;
+                       fs->clean_reserved = 0;
+                       spin_unlock(&fs->alloc_lock);
+               }
+               return -ENOSPC;
+       }
        /* This gets a reference on the 'segsum' */
        lafs_free_get(fs, &dev, &seg, 0);
        seg_setpos(fs, &wc->seg, segtovirt(fs, dev, seg));