From: NeilBrown Date: Sun, 10 Oct 2010 23:47:33 +0000 (+1100) Subject: While truncating, hold ref on superblock as well as inode. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=6c2ff96dfb857fab2dde256afc383c8694a375ac;p=LaFS.git While truncating, hold ref on superblock as well as inode. An unmount of a subsect filesystem could happen while still truncating a file on the filesystem. So hold a ref to the superblock so that it doesn't go away. When deleting, we cannot grab the inode, so we need to modify lafs_iput_fs to not do an iput in that case. Signed-off-by: NeilBrown --- diff --git a/inode.c b/inode.c index 1c65172..acc9261 100644 --- a/inode.c +++ b/inode.c @@ -705,9 +705,10 @@ void lafs_delete_inode(struct inode *ino) i_size_write(ino, 0); truncate_inode_pages(&ino->i_data, 0); LAFSI(ino)->trunc_next = 0; + set_bit(I_Deleting, &LAFSI(ino)->iflags); set_bit(I_Trunc, &LAFSI(ino)->iflags); + lafs_igrab_fs(ino); - set_bit(I_Deleting, &LAFSI(ino)->iflags); if (!IS_ERR(b)) { set_bit(B_Claimed, &b->b.flags); lafs_add_orphan(fs, b); @@ -851,8 +852,7 @@ 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); + lafs_iput_fs(ino); wake_up(&fs->trunc_wait); err = -ERESTARTSYS; goto out2; @@ -894,8 +894,7 @@ int lafs_inode_handle_orphan(struct datablock *b) /* Must be all done */ spin_unlock(&ib->b.inode->i_data.private_lock); clear_bit(I_Trunc, &LAFSI(ino)->iflags); - if (!test_bit(I_Deleting, &LAFSI(ino)->iflags)) - iput(ino); + lafs_iput_fs(ino); wake_up(&fs->trunc_wait); err = -ERESTARTSYS; goto out2; @@ -966,8 +965,7 @@ 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); + lafs_iput_fs(ino); if (test_bit(B_Pinned, &ib->b.flags)) /* Need to move the dirtiness which keeps this * pinned to the data block. @@ -1748,7 +1746,7 @@ void lafs_truncate(struct inode *ino) lafs_make_orphan(fs, db); if (!test_and_set_bit(I_Trunc, &LAFSI(ino)->iflags)) - igrab(ino); + lafs_igrab_fs(ino); if (trunc_block == 0) LAFSI(ino)->trunc_gen++; LAFSI(ino)->trunc_next = trunc_block; diff --git a/lafs.h b/lafs.h index c6c0bb2..42198fa 100644 --- a/lafs.h +++ b/lafs.h @@ -156,13 +156,16 @@ int lafs_inode_handle_orphan(struct datablock *b); static inline void lafs_iput_fs(struct inode *ino) { struct super_block *sb = ino->i_sb; - iput(ino); + if (!test_bit(I_Deleting, &LAFSI(ino)->iflags)) + iput(ino); deactivate_super(sb); } static inline void lafs_igrab_fs(struct inode *ino) { - igrab(ino); + if (igrab(ino) == NULL && + !test_bit(I_Deleting, &LAFSI(ino)->iflags)) + BUG(); atomic_inc(&ino->i_sb->s_active); }