]> git.neil.brown.name Git - LaFS.git/commitdiff
Be Careful about cleaning PinPending blocks.
authorNeilBrown <neilb@suse.de>
Sat, 26 Jun 2010 01:26:46 +0000 (11:26 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 27 Jun 2010 23:15:02 +0000 (09:15 +1000)
PinPending blocks must never be written to the cleaner segment
as they might still get dirtied and need to be written in this phase,
but the cleaner will have taken their uninc credit.

So if we need to clean a PinPending block, just mark it dirty and
wait for it to be unpinned or written normally.

Signed-off-by: NeilBrown <neilb@suse.de>
clean.c

diff --git a/clean.c b/clean.c
index 80d9d3ccbff8d9ac95e0cd2d6bdbd84ecf6a431f..4cbc41a005f005a8288cc2a6f74bcc9d066a886c 100644 (file)
--- a/clean.c
+++ b/clean.c
@@ -231,6 +231,17 @@ static void cleaner_flush(struct fs *fs)
 
                dprintk("cleaning %s\n", strblk(b));
 
+               if (test_bit(B_PinPending, &b->flags)) {
+                       /* Cannot safely clean this now.  Just make
+                        * it Dirty (it probably will be soon anyway)
+                        * so it gets written to the new-data segment
+                        * which will effectively clean it.
+                        */
+                       if (!test_and_set_bit(B_Dirty, &b->flags))
+                               if (!test_and_clear_bit(B_Realloc, &b->flags))
+                                       if (!test_and_clear_bit(B_Credit, &b->flags))
+                                               LAFS_BUG(1, b);
+               }
                if (test_bit(B_Dirty, &b->flags)) {
                        /* Ignore this, checkpoint will take it */
                        if (test_and_clear_bit(B_Realloc, &b->flags))