]> git.neil.brown.name Git - LaFS.git/commitdiff
Pin inode data blocks when dirtying them.
authorNeilBrown <neilb@suse.de>
Wed, 23 Jun 2010 01:25:17 +0000 (11:25 +1000)
committerNeilBrown <neilb@suse.de>
Wed, 23 Jun 2010 01:57:21 +0000 (11:57 +1000)
Two places we were dirtying an inode data block that might
not have been pinned.  Fix them.

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

index 8f68e556445832ffeb159ef6d9b5dfc4644a895e..2af96514b015b9ce1e1156d95add82676e0deb41 100644 (file)
--- a/cluster.c
+++ b/cluster.c
@@ -444,6 +444,8 @@ static int flush_data_to_inode(struct block *b)
                    lafs_leaf_next(lai->iblock, 1) != 0xffffffff)
                        goto give_up;
        }
+       /* Need checkpoint lock to pin the dblock */
+       lafs_checkpoint_lock(fs);
        if (test_and_clear_bit(B_Dirty, &b->flags)) {
                int credits = 1;
                /* Check size again, just in case it changed */
@@ -453,6 +455,7 @@ static int flush_data_to_inode(struct block *b)
                        if (test_and_set_bit(B_Dirty, &b->flags))
                                if (test_and_set_bit(B_Credit, &b->flags))
                                        lafs_space_return(fs, 1);
+                       lafs_checkpoint_unlock(fs);
                        goto give_up;
                }
                if (!test_and_set_bit(B_Credit, &lai->dblock->b.flags))
@@ -462,6 +465,11 @@ static int flush_data_to_inode(struct block *b)
                if (!test_and_set_bit(B_ICredit, &lai->dblock->b.flags))
                        credits--;
                lafs_space_return(fs, credits);
+               /* FIXME do I need to get a SegRef ?? */
+               if (test_bit(B_Pinned, &b->flags))
+                       lafs_pin_block_ph(&lai->dblock->b, !!test_bit(B_Phase1, &b->flags));
+               else
+                       lafs_pin_block(&lai->dblock->b);
                lafs_dirty_dblock(lai->dblock);
        } else if (test_and_clear_bit(B_Realloc, &b->flags)) {
                int credits = 1;
@@ -479,6 +487,7 @@ static int flush_data_to_inode(struct block *b)
                printk("Wasn't dirty or realloc: %s\n", strblk(b));
                LAFS_BUG(1, b);
        }
+       lafs_checkpoint_unlock(fs);
        lai->depth = 0;
        lai->iblock->depth = 0;
        clear_bit(B_Valid, &lai->iblock->b.flags);
diff --git a/inode.c b/inode.c
index a78991e7a0ebdc797acca259554e3dabeb0940e3..29974d53b877fcaf55b3501d0753e84a797faf99 100644 (file)
--- a/inode.c
+++ b/inode.c
@@ -858,6 +858,7 @@ void lafs_dirty_inode(struct inode *ino)
 
        BUG_ON(b==NULL);
 
+       lafs_checkpoint_lock(fs);
        if (test_bit(B_Pinned, &db->b.flags))
                ino_phase = !!test_bit(B_Phase1, &db->b.flags);
        else if (test_bit(B_Pinned, &b->flags))
@@ -869,10 +870,17 @@ void lafs_dirty_inode(struct inode *ino)
 
        if (ino_phase == fs->phase) {
                lafs_inode_fillblock(ino);
-               if (!nodirty)
+               if (!nodirty) {
+                       /* Pin to phase is safe as if it isn't
+                        * pinned already, then InoIdx is Pinned,
+                        * so all the prealloc is done
+                        */
+                       lafs_pin_block(&db->b);
                        lafs_dirty_dblock(db);
+               }
        } else
                set_bit(I_Dirty, &LAFSI(ino)->iflags);
+       lafs_checkpoint_unlock(fs);
        putref(b, MKREF(dirty_inode));
 }