summaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2016-07-20 16:16:06 -0400
committerJ. Bruce Fields <bfields@redhat.com>2016-08-04 17:11:49 -0400
commitb44061d0b914c11fb8f8a747c91d111973f56d76 (patch)
treecc94f0ce9201a9d70c5330ce55d4ec30421dfb67 /fs/nfsd/vfs.c
parente75b23f9e323b1e0759619c39d5a9f7a3a5d9d2c (diff)
nfsd: reorganize nfsd_create
There's some odd logic in nfsd_create() that allows it to be called with the parent directory either locked or unlocked. The only already-locked caller is NFSv2's nfsd_proc_create(). It's less confusing to split out the unlocked case into a separate function which the NFSv2 code can call directly. Also fix some comments while we're here. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c109
1 files changed, 56 insertions, 53 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index cf14e394a1b0..d21d0827cac4 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1135,16 +1135,9 @@ nfsd_check_ignore_resizing(struct iattr *iap)
1135 iap->ia_valid &= ~ATTR_SIZE; 1135 iap->ia_valid &= ~ATTR_SIZE;
1136} 1136}
1137 1137
1138/* 1138/* The parent directory should already be locked: */
1139 * Create a file (regular, directory, device, fifo); UNIX sockets
1140 * not yet implemented.
1141 * If the response fh has been verified, the parent directory should
1142 * already be locked. Note that the parent directory is left locked.
1143 *
1144 * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp
1145 */
1146__be32 1139__be32
1147nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, 1140nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
1148 char *fname, int flen, struct iattr *iap, 1141 char *fname, int flen, struct iattr *iap,
1149 int type, dev_t rdev, struct svc_fh *resfhp) 1142 int type, dev_t rdev, struct svc_fh *resfhp)
1150{ 1143{
@@ -1154,50 +1147,15 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1154 __be32 err2; 1147 __be32 err2;
1155 int host_err; 1148 int host_err;
1156 1149
1157 err = nfserr_exist;
1158 if (isdotent(fname, flen))
1159 goto out;
1160
1161 /*
1162 * Even though it is a create, first let's see if we are even allowed
1163 * to peek inside the parent
1164 */
1165 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
1166 if (err)
1167 goto out;
1168
1169 dentry = fhp->fh_dentry; 1150 dentry = fhp->fh_dentry;
1170 dirp = d_inode(dentry); 1151 dirp = d_inode(dentry);
1171 1152
1172 /* 1153 dchild = dget(resfhp->fh_dentry);
1173 * Check whether the response file handle has been verified yet. 1154 if (!fhp->fh_locked) {
1174 * If it has, the parent directory should already be locked. 1155 WARN_ONCE(1, "nfsd_create: parent %pd2 not locked!\n",
1175 */
1176 if (!resfhp->fh_dentry) {
1177 host_err = fh_want_write(fhp);
1178 if (host_err)
1179 goto out_nfserr;
1180
1181 /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
1182 fh_lock_nested(fhp, I_MUTEX_PARENT);
1183 dchild = lookup_one_len(fname, dentry, flen);
1184 host_err = PTR_ERR(dchild);
1185 if (IS_ERR(dchild))
1186 goto out_nfserr;
1187 err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
1188 if (err)
1189 goto out;
1190 } else {
1191 /* called from nfsd_proc_create */
1192 dchild = dget(resfhp->fh_dentry);
1193 if (!fhp->fh_locked) {
1194 /* not actually possible */
1195 printk(KERN_ERR
1196 "nfsd_create: parent %pd2 not locked!\n",
1197 dentry); 1156 dentry);
1198 err = nfserr_io; 1157 err = nfserr_io;
1199 goto out; 1158 goto out;
1200 }
1201 } 1159 }
1202 /* 1160 /*
1203 * Make sure the child dentry is still negative ... 1161 * Make sure the child dentry is still negative ...
@@ -1225,9 +1183,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1225 goto out; 1183 goto out;
1226 } 1184 }
1227 1185
1228 /*
1229 * Get the dir op function pointer.
1230 */
1231 err = 0; 1186 err = 0;
1232 host_err = 0; 1187 host_err = 0;
1233 switch (type) { 1188 switch (type) {
@@ -1254,7 +1209,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1254 /* 1209 /*
1255 * nfsd_create_setattr already committed the child. Transactional 1210 * nfsd_create_setattr already committed the child. Transactional
1256 * filesystems had a chance to commit changes for both parent and 1211 * filesystems had a chance to commit changes for both parent and
1257 * child * simultaneously making the following commit_metadata a 1212 * child simultaneously making the following commit_metadata a
1258 * noop. 1213 * noop.
1259 */ 1214 */
1260 err2 = nfserrno(commit_metadata(fhp)); 1215 err2 = nfserrno(commit_metadata(fhp));
@@ -1275,6 +1230,54 @@ out_nfserr:
1275 goto out; 1230 goto out;
1276} 1231}
1277 1232
1233/*
1234 * Create a filesystem object (regular, directory, special).
1235 * Note that the parent directory is left locked.
1236 *
1237 * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp
1238 */
1239__be32
1240nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1241 char *fname, int flen, struct iattr *iap,
1242 int type, dev_t rdev, struct svc_fh *resfhp)
1243{
1244 struct dentry *dentry, *dchild = NULL;
1245 struct inode *dirp;
1246 __be32 err;
1247 int host_err;
1248
1249 if (isdotent(fname, flen))
1250 return nfserr_exist;
1251
1252 /*
1253 * Even though it is a create, first let's see if we are even allowed
1254 * to peek inside the parent
1255 */
1256 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
1257 if (err)
1258 return err;
1259
1260 dentry = fhp->fh_dentry;
1261 dirp = d_inode(dentry);
1262
1263 host_err = fh_want_write(fhp);
1264 if (host_err)
1265 return nfserrno(host_err);
1266
1267 fh_lock_nested(fhp, I_MUTEX_PARENT);
1268 dchild = lookup_one_len(fname, dentry, flen);
1269 host_err = PTR_ERR(dchild);
1270 if (IS_ERR(dchild))
1271 return nfserrno(host_err);
1272 err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
1273 if (err) {
1274 dput(dchild);
1275 return err;
1276 }
1277 return nfsd_create_locked(rqstp, fhp, fname, flen, iap, type,
1278 rdev, resfhp);
1279}
1280
1278#ifdef CONFIG_NFSD_V3 1281#ifdef CONFIG_NFSD_V3
1279 1282
1280/* 1283/*