From: NeilBrown Date: Mon, 13 Sep 2010 04:39:18 +0000 (+1000) Subject: Refinements for triggering checkpoint when we are low on space. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=9b6358524bc7ddacd5d27840994008369a77b6fe;p=LaFS.git Refinements for triggering checkpoint when we are low on space. 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 --- diff --git a/checkpoint.c b/checkpoint.c index f0b08c2..9062455 100644 --- a/checkpoint.c +++ b/checkpoint.c @@ -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 dfc8b1d..e85ae28 100644 --- 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; } diff --git a/segments.c b/segments.c index 0ad7388..8f68aef 100644 --- a/segments.c +++ b/segments.c @@ -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)) {