From: NeilBrown Date: Mon, 28 Jun 2010 09:40:32 +0000 (+1000) Subject: Reserve space for cleaner segments. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=bfbb56906a02ff5bce4389de4ad2d27380dd48b0;p=LaFS.git Reserve space for cleaner segments. Now that we can reserve space specifically for cleaner segments, do so and limit the number of cleaned segments to the available number of cleaner segments. Signed-off-by: NeilBrown --- diff --git a/clean.c b/clean.c index cd38706..885927b 100644 --- a/clean.c +++ b/clean.c @@ -584,7 +584,7 @@ static unsigned long do_clean(struct fs *fs) * * For now, clean up to 4 segments at a time. */ - int i; + int i, max_segs; u64 T = 0; for (i = 0; i < fs->devices; i++) @@ -593,9 +593,16 @@ static unsigned long do_clean(struct fs *fs) /* adjust to unusable space FIXME adjust F too? */ T -= 4 * fs->max_segment; - for (i = 0; i < 4; i++) { + max_segs = lafs_alloc_cleaner_segs(fs, 4); + if (max_segs < 1) + /* if we can only clean to main segment, do it + * but only do one segment at a time + */ + max_segs = 1; + for (i = 0; i < max_segs; i++) { struct toclean *tc = &fs->cleaner.seg[i]; - u64 C = fs->free_blocks + fs->cleaner.cleaning; + u64 C = fs->free_blocks + fs->clean_reserved + + fs->cleaner.cleaning; u64 F = max(fs->total_free, fs->total_free_prev); if (4 * fs->max_segment < C) diff --git a/lafs.h b/lafs.h index 93b7dd3..6adfb36 100644 --- a/lafs.h +++ b/lafs.h @@ -629,6 +629,7 @@ void lafs_free_get(struct fs *fs, unsigned int *dev, u32 *seg, int lafs_get_cleanable(struct fs *fs, u16 *dev, u32 *seg); void lafs_space_return(struct fs *fs, int credits); +int lafs_alloc_cleaner_segs(struct fs *fs, int max); int lafs_space_alloc(struct fs *fs, int credits, int why); unsigned long lafs_scan_seg(struct fs *fs); int lafs_clean_count(struct fs *fs); diff --git a/segments.c b/segments.c index 85e91ad..929b3b2 100644 --- a/segments.c +++ b/segments.c @@ -569,6 +569,27 @@ void lafs_space_use(struct fs *fs, int credits) check_credits(fs); } +int lafs_alloc_cleaner_segs(struct fs *fs, int max) +{ + /* cleaner is about to start. + * See how many segments of space can safely + * be reserved for its use. + */ + int watermark = fs->max_segment * 4; + int rv = 0; + spin_lock(&fs->alloc_lock); + fs->free_blocks += fs->clean_reserved; + fs->clean_reserved = 0; + while (fs->clean_reserved < max * fs->max_segment && + fs->free_blocks > fs->allocated_blocks + watermark) { + fs->clean_reserved += fs->max_segment; + fs->free_blocks -= fs->max_segment; + rv++; + } + spin_unlock(&fs->alloc_lock); + return rv; +} + int lafs_space_alloc(struct fs *fs, int credits, int why) { /* 'why's for space reservation.