Skip to content

Commit b44061d

Browse files
author
J. Bruce Fields
committed
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>
1 parent e75b23f commit b44061d

File tree

3 files changed

+61
-55
lines changed

3 files changed

+61
-55
lines changed

fs/nfsd/nfsproc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,8 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
359359
nfserr = 0;
360360
if (!inode) {
361361
/* File doesn't exist. Create it and set attrs */
362-
nfserr = nfsd_create(rqstp, dirfhp, argp->name, argp->len,
363-
attr, type, rdev, newfhp);
362+
nfserr = nfsd_create_locked(rqstp, dirfhp, argp->name,
363+
argp->len, attr, type, rdev, newfhp);
364364
} else if (type == S_IFREG) {
365365
dprintk("nfsd: existing %s, valid=%x, size=%ld\n",
366366
argp->name, attr->ia_valid, (long) attr->ia_size);

fs/nfsd/vfs.c

Lines changed: 56 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,16 +1135,9 @@ nfsd_check_ignore_resizing(struct iattr *iap)
11351135
iap->ia_valid &= ~ATTR_SIZE;
11361136
}
11371137

1138-
/*
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-
*/
1138+
/* The parent directory should already be locked: */
11461139
__be32
1147-
nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1140+
nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
11481141
char *fname, int flen, struct iattr *iap,
11491142
int type, dev_t rdev, struct svc_fh *resfhp)
11501143
{
@@ -1154,50 +1147,15 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
11541147
__be32 err2;
11551148
int host_err;
11561149

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-
11691150
dentry = fhp->fh_dentry;
11701151
dirp = d_inode(dentry);
11711152

1172-
/*
1173-
* Check whether the response file handle has been verified yet.
1174-
* If it has, the parent directory should already be locked.
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",
1153+
dchild = dget(resfhp->fh_dentry);
1154+
if (!fhp->fh_locked) {
1155+
WARN_ONCE(1, "nfsd_create: parent %pd2 not locked!\n",
11971156
dentry);
1198-
err = nfserr_io;
1199-
goto out;
1200-
}
1157+
err = nfserr_io;
1158+
goto out;
12011159
}
12021160
/*
12031161
* Make sure the child dentry is still negative ...
@@ -1225,9 +1183,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
12251183
goto out;
12261184
}
12271185

1228-
/*
1229-
* Get the dir op function pointer.
1230-
*/
12311186
err = 0;
12321187
host_err = 0;
12331188
switch (type) {
@@ -1254,7 +1209,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
12541209
/*
12551210
* nfsd_create_setattr already committed the child. Transactional
12561211
* 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
12581213
* noop.
12591214
*/
12601215
err2 = nfserrno(commit_metadata(fhp));
@@ -1275,6 +1230,54 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
12751230
goto out;
12761231
}
12771232

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+
12781281
#ifdef CONFIG_NFSD_V3
12791282

12801283
/*

fs/nfsd/vfs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ __be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *,
5959
__be32 nfsd4_clone_file_range(struct file *, u64, struct file *,
6060
u64, u64);
6161
#endif /* CONFIG_NFSD_V4 */
62+
__be32 nfsd_create_locked(struct svc_rqst *, struct svc_fh *,
63+
char *name, int len, struct iattr *attrs,
64+
int type, dev_t rdev, struct svc_fh *res);
6265
__be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
6366
char *name, int len, struct iattr *attrs,
6467
int type, dev_t rdev, struct svc_fh *res);

0 commit comments

Comments
 (0)