diff options
author | J. Bruce Fields <bfields@redhat.com> | 2016-07-20 16:16:06 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2016-08-04 17:11:49 -0400 |
commit | b44061d0b914c11fb8f8a747c91d111973f56d76 (patch) | |
tree | cc94f0ce9201a9d70c5330ce55d4ec30421dfb67 /fs/nfsd/vfs.c | |
parent | e75b23f9e323b1e0759619c39d5a9f7a3a5d9d2c (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.c | 109 |
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 |
1147 | nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | 1140 | nfsd_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 | ||
1240 | nfsd_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 | /* |