|
@@ -1135,16 +1135,9 @@ nfsd_check_ignore_resizing(struct iattr *iap)
|
|
|
iap->ia_valid &= ~ATTR_SIZE;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Create a file (regular, directory, device, fifo); UNIX sockets
|
|
|
- * not yet implemented.
|
|
|
- * If the response fh has been verified, the parent directory should
|
|
|
- * already be locked. Note that the parent directory is left locked.
|
|
|
- *
|
|
|
- * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp
|
|
|
- */
|
|
|
+/* The parent directory should already be locked: */
|
|
|
__be32
|
|
|
-nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|
|
+nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|
|
char *fname, int flen, struct iattr *iap,
|
|
|
int type, dev_t rdev, struct svc_fh *resfhp)
|
|
|
{
|
|
@@ -1154,50 +1147,15 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|
|
__be32 err2;
|
|
|
int host_err;
|
|
|
|
|
|
- err = nfserr_exist;
|
|
|
- if (isdotent(fname, flen))
|
|
|
- goto out;
|
|
|
-
|
|
|
- /*
|
|
|
- * Even though it is a create, first let's see if we are even allowed
|
|
|
- * to peek inside the parent
|
|
|
- */
|
|
|
- err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
|
|
|
- if (err)
|
|
|
- goto out;
|
|
|
-
|
|
|
dentry = fhp->fh_dentry;
|
|
|
dirp = d_inode(dentry);
|
|
|
|
|
|
- /*
|
|
|
- * Check whether the response file handle has been verified yet.
|
|
|
- * If it has, the parent directory should already be locked.
|
|
|
- */
|
|
|
- if (!resfhp->fh_dentry) {
|
|
|
- host_err = fh_want_write(fhp);
|
|
|
- if (host_err)
|
|
|
- goto out_nfserr;
|
|
|
-
|
|
|
- /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
|
|
|
- fh_lock_nested(fhp, I_MUTEX_PARENT);
|
|
|
- dchild = lookup_one_len(fname, dentry, flen);
|
|
|
- host_err = PTR_ERR(dchild);
|
|
|
- if (IS_ERR(dchild))
|
|
|
- goto out_nfserr;
|
|
|
- err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
|
|
|
- if (err)
|
|
|
- goto out;
|
|
|
- } else {
|
|
|
- /* called from nfsd_proc_create */
|
|
|
- dchild = dget(resfhp->fh_dentry);
|
|
|
- if (!fhp->fh_locked) {
|
|
|
- /* not actually possible */
|
|
|
- printk(KERN_ERR
|
|
|
- "nfsd_create: parent %pd2 not locked!\n",
|
|
|
+ dchild = dget(resfhp->fh_dentry);
|
|
|
+ if (!fhp->fh_locked) {
|
|
|
+ WARN_ONCE(1, "nfsd_create: parent %pd2 not locked!\n",
|
|
|
dentry);
|
|
|
- err = nfserr_io;
|
|
|
- goto out;
|
|
|
- }
|
|
|
+ err = nfserr_io;
|
|
|
+ goto out;
|
|
|
}
|
|
|
/*
|
|
|
* Make sure the child dentry is still negative ...
|
|
@@ -1225,9 +1183,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Get the dir op function pointer.
|
|
|
- */
|
|
|
err = 0;
|
|
|
host_err = 0;
|
|
|
switch (type) {
|
|
@@ -1254,7 +1209,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|
|
/*
|
|
|
* nfsd_create_setattr already committed the child. Transactional
|
|
|
* filesystems had a chance to commit changes for both parent and
|
|
|
- * child * simultaneously making the following commit_metadata a
|
|
|
+ * child simultaneously making the following commit_metadata a
|
|
|
* noop.
|
|
|
*/
|
|
|
err2 = nfserrno(commit_metadata(fhp));
|
|
@@ -1275,6 +1230,54 @@ out_nfserr:
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Create a filesystem object (regular, directory, special).
|
|
|
+ * Note that the parent directory is left locked.
|
|
|
+ *
|
|
|
+ * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp
|
|
|
+ */
|
|
|
+__be32
|
|
|
+nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|
|
+ char *fname, int flen, struct iattr *iap,
|
|
|
+ int type, dev_t rdev, struct svc_fh *resfhp)
|
|
|
+{
|
|
|
+ struct dentry *dentry, *dchild = NULL;
|
|
|
+ struct inode *dirp;
|
|
|
+ __be32 err;
|
|
|
+ int host_err;
|
|
|
+
|
|
|
+ if (isdotent(fname, flen))
|
|
|
+ return nfserr_exist;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Even though it is a create, first let's see if we are even allowed
|
|
|
+ * to peek inside the parent
|
|
|
+ */
|
|
|
+ err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ dentry = fhp->fh_dentry;
|
|
|
+ dirp = d_inode(dentry);
|
|
|
+
|
|
|
+ host_err = fh_want_write(fhp);
|
|
|
+ if (host_err)
|
|
|
+ return nfserrno(host_err);
|
|
|
+
|
|
|
+ fh_lock_nested(fhp, I_MUTEX_PARENT);
|
|
|
+ dchild = lookup_one_len(fname, dentry, flen);
|
|
|
+ host_err = PTR_ERR(dchild);
|
|
|
+ if (IS_ERR(dchild))
|
|
|
+ return nfserrno(host_err);
|
|
|
+ err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
|
|
|
+ if (err) {
|
|
|
+ dput(dchild);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+ return nfsd_create_locked(rqstp, fhp, fname, flen, iap, type,
|
|
|
+ rdev, resfhp);
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_NFSD_V3
|
|
|
|
|
|
/*
|