Skip to content

Commit a2ece08

Browse files
author
Al Viro
committed
exportfs_decode_fh(): negative pinned may become positive without the parent locked
Signed-off-by: Al Viro <[email protected]>
1 parent 630faf8 commit a2ece08

File tree

1 file changed

+19
-12
lines changed

1 file changed

+19
-12
lines changed

fs/exportfs/expfs.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -519,26 +519,33 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
519519
* inode is actually connected to the parent.
520520
*/
521521
err = exportfs_get_name(mnt, target_dir, nbuf, result);
522-
if (!err) {
523-
inode_lock(target_dir->d_inode);
524-
nresult = lookup_one_len(nbuf, target_dir,
525-
strlen(nbuf));
526-
inode_unlock(target_dir->d_inode);
527-
if (!IS_ERR(nresult)) {
528-
if (nresult->d_inode) {
529-
dput(result);
530-
result = nresult;
531-
} else
532-
dput(nresult);
533-
}
522+
if (err) {
523+
dput(target_dir);
524+
goto err_result;
534525
}
535526

527+
inode_lock(target_dir->d_inode);
528+
nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf));
529+
if (!IS_ERR(nresult)) {
530+
if (unlikely(nresult->d_inode != result->d_inode)) {
531+
dput(nresult);
532+
nresult = ERR_PTR(-ESTALE);
533+
}
534+
}
535+
inode_unlock(target_dir->d_inode);
536536
/*
537537
* At this point we are done with the parent, but it's pinned
538538
* by the child dentry anyway.
539539
*/
540540
dput(target_dir);
541541

542+
if (IS_ERR(nresult)) {
543+
err = PTR_ERR(nresult);
544+
goto err_result;
545+
}
546+
dput(result);
547+
result = nresult;
548+
542549
/*
543550
* And finally make sure the dentry is actually acceptable
544551
* to NFSD.

0 commit comments

Comments
 (0)