aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p/vfs_inode.c
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2010-06-30 09:48:50 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2010-08-02 15:28:35 -0400
commita534c8d15b1f1d0f861fc2bb9e0529bd8486ec3f (patch)
tree0451da7a61bd7e3eb5968d65beee3243f7f51b5d /fs/9p/vfs_inode.c
parentebf46264a004818fe5b23f0ac18ac7336897d807 (diff)
fs/9p: Prevent parallel rename when doing fid_lookup
During fid lookup we need to make sure that the dentry->d_parent doesn't change so that we can safely walk the parent dentries. To ensure that we need to prevent cross directory rename during fid_lookup. Add a per superblock rename_sem rw_semaphore to prevent parallel fid lookup and rename. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r--fs/9p/vfs_inode.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 39352ef954d..75c261fdc7b 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -948,6 +948,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
948 948
949 sb = dir->i_sb; 949 sb = dir->i_sb;
950 v9ses = v9fs_inode2v9ses(dir); 950 v9ses = v9fs_inode2v9ses(dir);
951 /* We can walk d_parent because we hold the dir->i_mutex */
951 dfid = v9fs_fid_lookup(dentry->d_parent); 952 dfid = v9fs_fid_lookup(dentry->d_parent);
952 if (IS_ERR(dfid)) 953 if (IS_ERR(dfid))
953 return ERR_CAST(dfid); 954 return ERR_CAST(dfid);
@@ -1055,27 +1056,33 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1055 goto clunk_olddir; 1056 goto clunk_olddir;
1056 } 1057 }
1057 1058
1059 down_write(&v9ses->rename_sem);
1058 if (v9fs_proto_dotl(v9ses)) { 1060 if (v9fs_proto_dotl(v9ses)) {
1059 retval = p9_client_rename(oldfid, newdirfid, 1061 retval = p9_client_rename(oldfid, newdirfid,
1060 (char *) new_dentry->d_name.name); 1062 (char *) new_dentry->d_name.name);
1061 if (retval != -ENOSYS) 1063 if (retval != -ENOSYS)
1062 goto clunk_newdir; 1064 goto clunk_newdir;
1063 } 1065 }
1066 if (old_dentry->d_parent != new_dentry->d_parent) {
1067 /*
1068 * 9P .u can only handle file rename in the same directory
1069 */
1064 1070
1065 /* 9P can only handle file rename in the same directory */
1066 if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) {
1067 P9_DPRINTK(P9_DEBUG_ERROR, 1071 P9_DPRINTK(P9_DEBUG_ERROR,
1068 "old dir and new dir are different\n"); 1072 "old dir and new dir are different\n");
1069 retval = -EXDEV; 1073 retval = -EXDEV;
1070 goto clunk_newdir; 1074 goto clunk_newdir;
1071 } 1075 }
1072
1073 v9fs_blank_wstat(&wstat); 1076 v9fs_blank_wstat(&wstat);
1074 wstat.muid = v9ses->uname; 1077 wstat.muid = v9ses->uname;
1075 wstat.name = (char *) new_dentry->d_name.name; 1078 wstat.name = (char *) new_dentry->d_name.name;
1076 retval = p9_client_wstat(oldfid, &wstat); 1079 retval = p9_client_wstat(oldfid, &wstat);
1077 1080
1078clunk_newdir: 1081clunk_newdir:
1082 if (!retval)
1083 /* successful rename */
1084 d_move(old_dentry, new_dentry);
1085 up_write(&v9ses->rename_sem);
1079 p9_client_clunk(newdirfid); 1086 p9_client_clunk(newdirfid);
1080 1087
1081clunk_olddir: 1088clunk_olddir: