diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2011-08-16 12:49:28 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2011-09-06 09:17:15 -0400 |
commit | 73f507171cfa407b19f254aef95cbb058c8180cf (patch) | |
tree | 18456029c1b723669232e1ed45895f9d65853927 /fs/9p | |
parent | f88657ce3f9713a0c62101dffb0e972a979e77b9 (diff) |
fs/9p: Always ask new inode in lookup for cache mode disabled
This make sure we don't end up reusing the unlinked inode object.
The ideal way is to use inode i_generation. But i_generation is
not available in userspace always.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Diffstat (limited to 'fs/9p')
-rw-r--r-- | fs/9p/vfs_inode.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 9e3ea6ce695..e3c03db3c78 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -825,6 +825,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
825 | struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | 825 | struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, |
826 | struct nameidata *nameidata) | 826 | struct nameidata *nameidata) |
827 | { | 827 | { |
828 | struct dentry *res; | ||
828 | struct super_block *sb; | 829 | struct super_block *sb; |
829 | struct v9fs_session_info *v9ses; | 830 | struct v9fs_session_info *v9ses; |
830 | struct p9_fid *dfid, *fid; | 831 | struct p9_fid *dfid, *fid; |
@@ -856,22 +857,35 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
856 | 857 | ||
857 | return ERR_PTR(result); | 858 | return ERR_PTR(result); |
858 | } | 859 | } |
859 | 860 | /* | |
860 | inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); | 861 | * Make sure we don't use a wrong inode due to parallel |
862 | * unlink. For cached mode create calls request for new | ||
863 | * inode. But with cache disabled, lookup should do this. | ||
864 | */ | ||
865 | if (v9ses->cache) | ||
866 | inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); | ||
867 | else | ||
868 | inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); | ||
861 | if (IS_ERR(inode)) { | 869 | if (IS_ERR(inode)) { |
862 | result = PTR_ERR(inode); | 870 | result = PTR_ERR(inode); |
863 | inode = NULL; | 871 | inode = NULL; |
864 | goto error; | 872 | goto error; |
865 | } | 873 | } |
866 | |||
867 | result = v9fs_fid_add(dentry, fid); | 874 | result = v9fs_fid_add(dentry, fid); |
868 | if (result < 0) | 875 | if (result < 0) |
869 | goto error_iput; | 876 | goto error_iput; |
870 | |||
871 | inst_out: | 877 | inst_out: |
872 | d_add(dentry, inode); | 878 | /* |
873 | return NULL; | 879 | * If we had a rename on the server and a parallel lookup |
874 | 880 | * for the new name, then make sure we instantiate with | |
881 | * the new name. ie look up for a/b, while on server somebody | ||
882 | * moved b under k and client parallely did a lookup for | ||
883 | * k/b. | ||
884 | */ | ||
885 | res = d_materialise_unique(dentry, inode); | ||
886 | if (!IS_ERR(res)) | ||
887 | return res; | ||
888 | result = PTR_ERR(res); | ||
875 | error_iput: | 889 | error_iput: |
876 | iput(inode); | 890 | iput(inode); |
877 | error: | 891 | error: |