From a196a317636dd09d9ef2b3bf3ed8fde6aa736fa6 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 1 Aug 2010 12:46:48 +1000 Subject: [PATCH] Hold ref on inode while truncating. If I_Trunc is set and I_Deleting is not, then we hold a reference to the inode and must drop it when clearing I_Trunc. This ensure that delete_inode won't get called while truncate is happening, and the inode won't otherwise disappear. Signed-off-by: NeilBrown --- inode.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/inode.c b/inode.c index 9ca882e..b209ca2 100644 --- a/inode.c +++ b/inode.c @@ -626,8 +626,10 @@ void lafs_delete_inode(struct inode *ino) } dprintk("DELETE INODE %d\n", (int)ino->i_ino); - wait_event(fs->trunc_wait, - !test_bit(I_Trunc, &LAFSI(ino)->iflags)); + /* Normal truncation holds an igrab, so we cannot be + * deleted until any truncation finishes + */ + BUG_ON(test_bit(I_Trunc, &LAFSI(ino)->iflags)); spin_lock(&ino->i_data.private_lock); b = LAFSI(ino)->dblock; @@ -786,6 +788,8 @@ int lafs_inode_handle_orphan(struct datablock *b) /* must be finished */ LAFS_BUG(test_bit(B_Dirty, &ib->b.flags), &ib->b); clear_bit(I_Trunc, &LAFSI(ino)->iflags); + if (!test_bit(I_Deleting, &LAFSI(ino)->iflags)) + iput(ino); wake_up(&fs->trunc_wait); err = -ERESTARTSYS; goto out2; @@ -828,6 +832,8 @@ int lafs_inode_handle_orphan(struct datablock *b) if (ib2->b.fileaddr < lastaddr) { /* Must be all done */ clear_bit(I_Trunc, &LAFSI(ino)->iflags); + if (!test_bit(I_Deleting, &LAFSI(ino)->iflags)) + iput(ino); wake_up(&fs->trunc_wait); err = -ERESTARTSYS; goto out2; @@ -897,6 +903,8 @@ int lafs_inode_handle_orphan(struct datablock *b) if (LAFSI(ino)->depth == 0) { /* Nothing to truncate */ clear_bit(I_Trunc, &LAFSI(ino)->iflags); + if (!test_bit(I_Deleting, &LAFSI(ino)->iflags)) + iput(ino); if (test_bit(B_Pinned, &ib->b.flags)) /* Need to move the dirtiness which keeps this * pinned to the data block. @@ -1615,6 +1623,8 @@ void lafs_truncate(struct inode *ino) /* FIXME there is nothing I can do with an error here */ lafs_make_orphan(fs, db); + if (!test_and_set_bit(I_Trunc, &LAFSI(ino)->iflags)) + igrab(ino); LAFSI(ino)->trunc_next = trunc_block; putdref(db, MKREF(trunc)); } -- 2.39.5