Skip to content

Commit 1f01845

Browse files
Trond MyklebustTrond Myklebust
authored andcommitted
NFS: Fix calls to drop_nlink()
It is almost always wrong for NFS to call drop_nlink() after removing a file. What we really want is to mark the inode's attributes for revalidation, and we want to ensure that the VFS drops it if we're reasonably sure that this is the final unlink(). Do the former using the usual cache validity flags, and the latter by testing if inode->i_nlink == 1, and clearing it in that case. This also fixes the following warning reported by Neil Brown and Jeff Layton (among others). [634155.004438] WARNING: at /home/abuild/rpmbuild/BUILD/kernel-desktop-3.5.0/lin [634155.004442] Hardware name: Latitude E6510 [634155.004577] crc_itu_t crc32c_intel snd_hwdep snd_pcm snd_timer snd soundcor [634155.004609] Pid: 13402, comm: bash Tainted: G W 3.5.0-36-desktop # [634155.004611] Call Trace: [634155.004630] [<ffffffff8100444a>] dump_trace+0xaa/0x2b0 [634155.004641] [<ffffffff815a23dc>] dump_stack+0x69/0x6f [634155.004653] [<ffffffff81041a0b>] warn_slowpath_common+0x7b/0xc0 [634155.004662] [<ffffffff811832e4>] drop_nlink+0x34/0x40 [634155.004687] [<ffffffffa05bb6c3>] nfs_dentry_iput+0x33/0x70 [nfs] [634155.004714] [<ffffffff8118049e>] dput+0x12e/0x230 [634155.004726] [<ffffffff8116b230>] __fput+0x170/0x230 [634155.004735] [<ffffffff81167c0f>] filp_close+0x5f/0x90 [634155.004743] [<ffffffff81167cd7>] sys_close+0x97/0x100 [634155.004754] [<ffffffff815c3b39>] system_call_fastpath+0x16/0x1b [634155.004767] [<00007f2a73a0d110>] 0x7f2a73a0d10f Signed-off-by: Trond Myklebust <[email protected]> Cc: [email protected] [3.3+]
1 parent eed9935 commit 1f01845

File tree

1 file changed

+6
-5
lines changed

1 file changed

+6
-5
lines changed

fs/nfs/dir.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,11 +1155,14 @@ static int nfs_dentry_delete(const struct dentry *dentry)
11551155

11561156
}
11571157

1158+
/* Ensure that we revalidate inode->i_nlink */
11581159
static void nfs_drop_nlink(struct inode *inode)
11591160
{
11601161
spin_lock(&inode->i_lock);
1161-
if (inode->i_nlink > 0)
1162-
drop_nlink(inode);
1162+
/* drop the inode if we're reasonably sure this is the last link */
1163+
if (inode->i_nlink == 1)
1164+
clear_nlink(inode);
1165+
NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR;
11631166
spin_unlock(&inode->i_lock);
11641167
}
11651168

@@ -1174,8 +1177,8 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
11741177
NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA;
11751178

11761179
if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
1177-
drop_nlink(inode);
11781180
nfs_complete_unlink(dentry, inode);
1181+
nfs_drop_nlink(inode);
11791182
}
11801183
iput(inode);
11811184
}
@@ -1646,10 +1649,8 @@ static int nfs_safe_remove(struct dentry *dentry)
16461649
if (inode != NULL) {
16471650
NFS_PROTO(inode)->return_delegation(inode);
16481651
error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
1649-
/* The VFS may want to delete this inode */
16501652
if (error == 0)
16511653
nfs_drop_nlink(inode);
1652-
nfs_mark_for_revalidate(inode);
16531654
} else
16541655
error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
16551656
if (error == -ENOENT)

0 commit comments

Comments
 (0)