]> git.neil.brown.name Git - LaFS.git/commitdiff
Refinements for triggering checkpoint when we are low on space.
authorNeilBrown <neilb@suse.de>
Mon, 13 Sep 2010 04:39:18 +0000 (14:39 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 13 Sep 2010 05:16:00 +0000 (15:16 +1000)
This is getting messy but seems to work.

Not sure now on the difference between CleanerBlocks and
EmergencyPending.
I guess the one makes sure the cleaner does what it can and then
triggers a checkpoint.
The other prepares for EmergencyClean to be set after the next
checkpoint.

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

index f0b08c253cd02fa2d3c88abd3197b520788c00d2..90624551ee6f47e8a9869b40e902d7c9fa190b0e 100644 (file)
@@ -505,8 +505,10 @@ static void finish_checkpoint(struct fs *fs, int youth)
        if (!test_bit(FinalCheckpoint, &fs->fsstate))
                lafs_seg_apply_all(fs);
        lafs_clean_free(fs);
-       if (test_bit(EmergencyPending, &fs->fsstate))
+       if (test_bit(EmergencyPending, &fs->fsstate)) {
                set_bit(EmergencyClean, &fs->fsstate);
+               clear_bit(EmergencyPending, &fs->fsstate);
+       }
 
        lafs_write_state(fs);
        dprintk("State written, all done %d\n", fs->seq);
diff --git a/clean.c b/clean.c
index dfc8b1d217b7dc81ba606a24a1dcdd9515553995..e85ae28e70038115d19964f908f31ace47e59ca3 100644 (file)
--- a/clean.c
+++ b/clean.c
@@ -670,8 +670,8 @@ unsigned long lafs_do_clean(struct fs *fs)
                        if (!tc->have_addr) {
                                dprintk("CLEANER: Nothing found to clean at %d :-(\n",
                                        i);
-                               if (i == 0 && test_bit(EmergencyPending, &fs->fsstate)
-                                   && !test_bit(EmergencyClean, &fs->fsstate))
+                               if (i == 0 && (test_bit(EmergencyPending, &fs->fsstate) ||
+                                              test_bit(CleanerBlocks, &fs->fsstate)))
                                        lafs_checkpoint_start(fs);
                                break;
                        }
@@ -714,12 +714,20 @@ unsigned long lafs_do_clean(struct fs *fs)
        if (test_bit(CleanerBlocks, &fs->fsstate)) {
                int any_clean;
                int clean = lafs_clean_count(fs, &any_clean);
-               dprintk("clean=%d max_seg=%d need=%d\n", (int)clean,
-                       (int)fs->max_segment, (int)fs->cleaner.need);
-               if (any_clean &&
-                   clean * fs->max_segment >=
-                   fs->allocated_blocks + fs->cleaner.need)
+               dprintk("clean=%d max_seg=%d need=%d act=%d any=%d\n", (int)clean,
+                      (int)fs->max_segment, (int)fs->cleaner.need, fs->cleaner.active, any_clean);
+               if (any_clean) {
+                       /* If there is enough clean space for everything to move
+                        * forward, or the cleaner has done all it can, then
+                        * push out a checkpoint so threads waiting on the cleaner
+                        * can proceed
+                        */
+                       if (clean * fs->max_segment >=
+                           fs->allocated_blocks + fs->cleaner.need
+                           ||
+                           !fs->cleaner.active)
                        lafs_checkpoint_start(fs);
+               }
        }
        return MAX_SCHEDULE_TIMEOUT;
 }
index 0ad73884fba88f1f54f49bb9136c7763fed72ac1..8f68aef1779d4d54e6d234ed908ea98a0ac92120 100644 (file)
@@ -650,14 +650,15 @@ int lafs_space_alloc(struct fs *fs, int credits, int why)
        }
 
        if (credits == 0) {
-               if (why == NewSpace)
+               if (why == NewSpace && !test_bit(EmergencyClean, &fs->fsstate))
                        set_bit(EmergencyPending, &fs->fsstate);
-               if (!test_bit(CleanerBlocks, &fs->fsstate) ||
-                   fs->cleaner.need > watermark + fs->max_segment) {
-                       fs->cleaner.need = watermark + fs->max_segment;
-                       set_bit(CleanerBlocks, &fs->fsstate);
-                       lafs_wake_thread(fs);
-               }
+               if (why >= ReleaseSpace || !test_bit(EmergencyClean, &fs->fsstate))
+                       if (!test_bit(CleanerBlocks, &fs->fsstate) ||
+                           fs->cleaner.need > watermark + fs->max_segment) {
+                               fs->cleaner.need = watermark + fs->max_segment;
+                               set_bit(CleanerBlocks, &fs->fsstate);
+                               lafs_wake_thread(fs);
+                       }
        } else if (why == NewSpace)
                if (test_bit(EmergencyClean, &fs->fsstate) ||
                    test_bit(EmergencyPending, &fs->fsstate)) {