From: NeilBrown Date: Fri, 2 Jul 2010 23:29:34 +0000 (+1000) Subject: Close segments properly when we get to the end. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=5741cd613a397acbfcd30fdb56fa3c8addcf862d;p=LaFS.git Close segments properly when we get to the end. Passing -1 to new_segment was just *wrong*. Do it right, and make sure to close all segments, and release refcounts, at unmount. Signed-off-by: NeilBrown --- diff --git a/cluster.c b/cluster.c index 5569205..526fb9d 100644 --- a/cluster.c +++ b/cluster.c @@ -396,26 +396,46 @@ static void cluster_reset(struct fs *fs, struct wc *wc) } -static int new_segment(struct fs *fs, int cnum) +static void close_segment(struct fs *fs, int cnum) { - /* new_segment can fail if cnum > 0 and there is no - * clean_reserved - */ - struct wc *wc = fs->wc + cnum; - unsigned int dev; - u32 seg; - /* Release old segment */ /* FIXME I need lafs_seg_{de,}ref for every snapshot, * don't I ??? */ + struct wc *wc = fs->wc + cnum; if (wc->seg.dev >= 0) { + if (cnum) { + spin_lock(&fs->lock); + fs->clean_reserved -= seg_remainder(fs, &wc->seg); + spin_unlock(&fs->lock); + } lafs_seg_forget(fs, wc->seg.dev, wc->seg.num); wc->seg.dev = -1; } +} - if (cnum < 0 || - (cnum && fs->clean_reserved < fs->max_segment)) +void lafs_close_all_segments(struct fs *fs) +{ + int cnum; + for (cnum = 0; cnum < WC_NUM; cnum++) + close_segment(fs, cnum); +} + +static int new_segment(struct fs *fs, int cnum) +{ + /* new_segment can fail if cnum > 0 and there is no + * clean_reserved + */ + struct wc *wc = fs->wc + cnum; + unsigned int dev; + u32 seg; + + 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; /* This gets a reference on the 'segsum' */ lafs_free_get(fs, &dev, &seg, 0); @@ -1194,7 +1214,7 @@ static void cluster_flush(struct fs *fs, int cnum) if (cnum == 0) new_segment(fs, cnum); else - new_segment(fs, -1); + close_segment(fs, cnum); } /* Fill in the cluster header */ diff --git a/lafs.h b/lafs.h index 78cadfd..7c9928a 100644 --- a/lafs.h +++ b/lafs.h @@ -648,6 +648,7 @@ int lafs_calc_cluster_csum(struct cluster_head *head); int lafs_cluster_init(struct fs *fs, int cnum, u64 addr, u64 prev, u64 seq); void lafs_clusters_done(struct fs *fs); void lafs_done_work(struct work_struct *ws); +void lafs_close_all_segments(struct fs *fs); /* index.c */ void lafs_pin_block_ph(struct block *b, int ph); diff --git a/super.c b/super.c index 71f5098..efc2071 100644 --- a/super.c +++ b/super.c @@ -732,6 +732,7 @@ lafs_put_super(struct super_block *sb) set_bit(FinalCheckpoint, &fs->fsstate); lafs_checkpoint_unlock_wait(fs); lafs_cluster_wait_all(fs); + lafs_close_all_segments(fs); lafs_empty_segment_table(fs); lafs_seg_put_all(fs);