]> git.neil.brown.name Git - LaFS.git/commitdiff
Reserve space for cleaner segments.
authorNeilBrown <neilb@suse.de>
Mon, 28 Jun 2010 09:40:32 +0000 (19:40 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 28 Jun 2010 22:22:55 +0000 (08:22 +1000)
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 <neilb@suse.de>
clean.c
lafs.h
segments.c

diff --git a/clean.c b/clean.c
index cd387065d7534549ecf31fc16db3f02fda87d057..885927bdcf0b16d1478931bffc27eee117d02880 100644 (file)
--- 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 93b7dd3f1c59f6188df9448c77867e8c8729c2b7..6adfb369444f0eaa7d81a122fac022ce11aaab97 100644 (file)
--- 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);
index 85e91ad5171e4a738e25a479a7f3423f829fae21..929b3b2fc8e17ab4c53744a35bf572407b44995f 100644 (file)
@@ -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.