From: NeilBrown Date: Tue, 14 Sep 2010 01:10:25 +0000 (+1000) Subject: Make sure checkpoint happens after a timeout. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=b299ed4d5ba239710a6894b1e175137a3d214098;p=LaFS.git Make sure checkpoint happens after a timeout. If anything has been written since last check point, ensure another checkpoint happens within 30 seconds. This is partly to ensure that index block don't remain dirty forever. Signed-off-by: NeilBrown --- diff --git a/checkpoint.c b/checkpoint.c index 32ab345..93e5082 100644 --- a/checkpoint.c +++ b/checkpoint.c @@ -539,9 +539,18 @@ unsigned long lafs_do_checkpoint(struct fs *fs) if (fs->cleaner.active == 0 && fs->newsegments > fs->max_newsegs) set_bit(CheckpointNeeded, &fs->fsstate); + else if (test_bit(CheckpointOpen, &fs->fsstate)) { + unsigned long j = jiffies; + if (time_after_eq(j, fs->next_checkpoint)) + set_bit(CheckpointNeeded, &fs->fsstate); + else + return fs->next_checkpoint - j; + } else + return MAX_SCHEDULE_TIMEOUT; } if (!test_bit(CheckpointNeeded, &fs->fsstate)) + /* Must have done final checkpoint */ return MAX_SCHEDULE_TIMEOUT; if (fs->cleaner.active || ! fs->scan.done) diff --git a/cluster.c b/cluster.c index e663391..1f317c1 100644 --- a/cluster.c +++ b/cluster.c @@ -1140,6 +1140,14 @@ static void cluster_flush(struct fs *fs, int cnum) int vtype; int cluster_size; + if (!test_bit(CheckpointOpen, &fs->fsstate)) { + /* First cluster since a checkpoint, make sure + * we do another checkpoint within 30 seconds + */ + fs->next_checkpoint = jiffies + 30 * HZ; + set_bit(CheckpointOpen, &fs->fsstate); + lafs_wake_thread(fs); + } /* set the writecluster size as this will guide layout in * some cases */ @@ -1212,9 +1220,10 @@ static void cluster_flush(struct fs *fs, int cnum) if (fs->checkpointing) { spin_lock(&fs->lock); wc->chead->flags = cpu_to_le32(fs->checkpointing); - if (fs->checkpointing & CH_CheckpointEnd) + if (fs->checkpointing & CH_CheckpointEnd) { fs->checkpointing = 0; - else if (fs->checkpointing & CH_CheckpointStart) { + clear_bit(CheckpointOpen, &fs->fsstate); + } else if (fs->checkpointing & CH_CheckpointStart) { fs->checkpointcluster = head_addr[0]; fs->checkpointing &= ~CH_CheckpointStart; } diff --git a/index.c b/index.c index 79bca85..65d36c8 100644 --- a/index.c +++ b/index.c @@ -97,9 +97,6 @@ static int lafs_shrinker(int nr_to_scan, /*gfp_t*/unsigned int gfp_mask) list_del(&ib->b.lru); lafs_iblock_free(ib); } - /* FIXME - * while (nr_to_scan) trigger some flushing - */ } return freelist.freecnt; } diff --git a/state.h b/state.h index 589a56e..57bdddf 100644 --- a/state.h +++ b/state.h @@ -119,6 +119,13 @@ struct fs { * should be after the next checkpoint unless that * releases lots of space */ +#define CheckpointOpen 11 /* Some data has been written since the last checkpoint, + * so 'next_checkpoint' is a valid timestamp + */ + + unsigned long next_checkpoint; /* Valid when CheckpointOpen is set, holds + * jiffie time by when we need to do a checkpoint + */ struct work_struct done_work; /* used for handling * refile after write completes */