summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-02-28 07:50:20 +0100
committerAl Viro <viro@zeniv.linux.org.uk>2013-02-28 07:50:20 +0100
commit5e608671dfbfd6a9556c31df65a4f147439eed59 (patch)
treebb708c0bec27822d68defc54d8c79289b29d21fb
parent9p: make sure ->lookup() adds fid to the right dentry (diff)
downloadlinux-5e608671dfbfd6a9556c31df65a4f147439eed59.tar.xz
linux-5e608671dfbfd6a9556c31df65a4f147439eed59.zip
9p: if v9fs_fid_lookup() gets to asking server, it'd better have hashed dentry
... otherwise the path we'd built isn't worth much. Don't accept such fids obtained from paths unless dentry is still alived by the end of the work. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/9p/fid.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 73ca55042cb0..616abaf1c6cd 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -41,10 +41,15 @@
*
*/
+static inline void __add_fid(struct dentry *dentry, struct p9_fid *fid)
+{
+ hlist_add_head(&fid->dlist, (struct hlist_head *)&dentry->d_fsdata);
+}
+
void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
{
spin_lock(&dentry->d_lock);
- hlist_add_head(&fid->dlist, (struct hlist_head *)&dentry->d_fsdata);
+ __add_fid(dentry, fid);
spin_unlock(&dentry->d_lock);
}
@@ -198,8 +203,17 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
}
kfree(wnames);
fid_out:
- if (!IS_ERR(fid))
- v9fs_fid_add(dentry, fid);
+ if (!IS_ERR(fid)) {
+ spin_lock(&dentry->d_lock);
+ if (d_unhashed(dentry)) {
+ spin_unlock(&dentry->d_lock);
+ p9_client_clunk(fid);
+ fid = ERR_PTR(-ENOENT);
+ } else {
+ __add_fid(dentry, fid);
+ spin_unlock(&dentry->d_lock);
+ }
+ }
err_out:
up_read(&v9ses->rename_sem);
return fid;