From: NeilBrown Date: Wed, 23 Jun 2010 01:25:17 +0000 (+1000) Subject: Pin inode data blocks when dirtying them. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=09688e3c70b1b9bdb8029f3e3083825718364560;p=LaFS.git Pin inode data blocks when dirtying them. Two places we were dirtying an inode data block that might not have been pinned. Fix them. Signed-off-by: NeilBrown --- diff --git a/cluster.c b/cluster.c index 8f68e55..2af9651 100644 --- 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 a78991e..29974d5 100644 --- 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)); }