}
-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);
if (cnum == 0)
new_segment(fs, cnum);
else
- new_segment(fs, -1);
+ close_segment(fs, cnum);
}
/* Fill in the cluster header */
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);
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);