All of lore.kernel.org
 help / color / mirror / Atom feed
From: bfields@fieldses.org (J. Bruce Fields)
To: Chuck Lever <chuck.lever@oracle.com>
Cc: linux-nfs@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH RFC 4/8] NFSD: Refactor NFSv3 CREATE
Date: Wed, 20 Apr 2022 15:10:42 -0400	[thread overview]
Message-ID: <20220420191042.GA27805@fieldses.org> (raw)
In-Reply-To: <165047934027.1829.4170855794285748158.stgit@manet.1015granger.net>

On Wed, Apr 20, 2022 at 02:29:00PM -0400, Chuck Lever wrote:
> The NFSv3 CREATE and NFSv4 OPEN(CREATE) use cases are about to
> diverge such that it makes sense to split do_nfsd_create() into one
> version for NFSv3 and one for NFSv4.
> 
> As a first step, copy do_nfsd_create() to nfs3proc.c and remove
> NFSv4-specific logic.
> 
> One immediate legibility benefit is that the logic for handling
> NFSv3 createhow is now quite straightforward. NFSv4 createhow
> has some subtleties that IMO do not belong in generic code.

That makes sense to me, though just eyeballing the two resulting
functions, you end up with a *lot* of duplication.  I wonder if it'd be
possible to keep the two paths free of complications from each other
while sharing more code, e.g. if there are logical blocks of code that
could now be pulled out into common helpers.

--b.

> 
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
>  fs/nfsd/nfs3proc.c |  127 ++++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 121 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
> index 981a2a71c5af..981a3a7a6e16 100644
> --- a/fs/nfsd/nfs3proc.c
> +++ b/fs/nfsd/nfs3proc.c
> @@ -8,6 +8,7 @@
>  #include <linux/fs.h>
>  #include <linux/ext2_fs.h>
>  #include <linux/magic.h>
> +#include <linux/namei.h>
>  
>  #include "cache.h"
>  #include "xdr3.h"
> @@ -220,10 +221,126 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
>  }
>  
>  /*
> - * With NFSv3, CREATE processing is a lot easier than with NFSv2.
> - * At least in theory; we'll see how it fares in practice when the
> - * first reports about SunOS compatibility problems start to pour in...
> + * Implement NFSv3's unchecked, guarded, and exclusive CREATE
> + * semantics for regular files. Except for the created file,
> + * this operation is stateless on the server.
> + *
> + * Upon return, caller must release @fhp and @resfhp.
>   */
> +static __be32
> +nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
> +		  struct svc_fh *resfhp, struct nfsd3_createargs *argp)
> +{
> +	struct iattr *iap = &argp->attrs;
> +	struct dentry *parent, *child;
> +	__u32 v_mtime, v_atime;
> +	struct inode *inode;
> +	__be32 status;
> +	int host_err;
> +
> +	if (isdotent(argp->name, argp->len))
> +		return nfserr_exist;
> +	if (!(iap->ia_valid & ATTR_MODE))
> +		iap->ia_mode = 0;
> +
> +	status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
> +	if (status != nfs_ok)
> +		return status;
> +
> +	parent = fhp->fh_dentry;
> +	inode = d_inode(parent);
> +
> +	host_err = fh_want_write(fhp);
> +	if (host_err)
> +		return nfserrno(host_err);
> +
> +	fh_lock_nested(fhp, I_MUTEX_PARENT);
> +
> +	child = lookup_one_len(argp->name, parent, argp->len);
> +	if (IS_ERR(child)) {
> +		status = nfserrno(PTR_ERR(child));
> +		goto out;
> +	}
> +
> +	if (d_really_is_negative(child)) {
> +		status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
> +		if (status != nfs_ok)
> +			goto out;
> +	}
> +
> +	status = fh_compose(resfhp, fhp->fh_export, child, fhp);
> +	if (status != nfs_ok)
> +		goto out;
> +
> +	v_mtime = 0;
> +	v_atime = 0;
> +	if (argp->createmode == NFS3_CREATE_EXCLUSIVE) {
> +		u32 *verifier = (u32 *)argp->verf;
> +
> +		/*
> +		 * Solaris 7 gets confused (bugid 4218508) if these have
> +		 * the high bit set, as do xfs filesystems without the
> +		 * "bigtime" feature. So just clear the high bits.
> +		 */
> +		v_mtime = verifier[0] & 0x7fffffff;
> +		v_atime = verifier[1] & 0x7fffffff;
> +	}
> +
> +	if (d_really_is_positive(child)) {
> +		status = nfs_ok;
> +
> +		switch (argp->createmode) {
> +		case NFS3_CREATE_UNCHECKED:
> +			if (!d_is_reg(child))
> +				break;
> +			iap->ia_valid &= ATTR_SIZE;
> +			goto set_attr;
> +		case NFS3_CREATE_GUARDED:
> +			status = nfserr_exist;
> +			break;
> +		case NFS3_CREATE_EXCLUSIVE:
> +			if (d_inode(child)->i_mtime.tv_sec == v_mtime &&
> +			    d_inode(child)->i_atime.tv_sec == v_atime &&
> +			    d_inode(child)->i_size == 0) {
> +				break;
> +			}
> +			status = nfserr_exist;
> +		}
> +		goto out;
> +	}
> +
> +	if (!IS_POSIXACL(inode))
> +		iap->ia_mode &= ~current_umask();
> +
> +	host_err = vfs_create(&init_user_ns, inode, child, iap->ia_mode, true);
> +	if (host_err < 0) {
> +		status = nfserrno(host_err);
> +		goto out;
> +	}
> +
> +	/* A newly created file already has a file size of zero. */
> +	if ((iap->ia_valid & ATTR_SIZE) && (iap->ia_size == 0))
> +		iap->ia_valid &= ~ATTR_SIZE;
> +	if (argp->createmode == NFS3_CREATE_EXCLUSIVE) {
> +		iap->ia_valid = ATTR_MTIME | ATTR_ATIME |
> +				ATTR_MTIME_SET | ATTR_ATIME_SET;
> +		iap->ia_mtime.tv_sec = v_mtime;
> +		iap->ia_atime.tv_sec = v_atime;
> +		iap->ia_mtime.tv_nsec = 0;
> +		iap->ia_atime.tv_nsec = 0;
> +	}
> +
> +set_attr:
> +	status = nfsd_create_setattr(rqstp, fhp, resfhp, iap);
> +
> +out:
> +	fh_unlock(fhp);
> +	if (child && !IS_ERR(child))
> +		dput(child);
> +	fh_drop_write(fhp);
> +	return status;
> +}
> +
>  static __be32
>  nfsd3_proc_create(struct svc_rqst *rqstp)
>  {
> @@ -239,9 +356,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp)
>  	dirfhp = fh_copy(&resp->dirfh, &argp->fh);
>  	newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
>  
> -	resp->status = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
> -				      &argp->attrs, newfhp, argp->createmode,
> -				      (u32 *)argp->verf, NULL, NULL);
> +	resp->status = nfsd3_create_file(rqstp, dirfhp, newfhp, argp);
>  	return rpc_success;
>  }
>  
> 

  reply	other threads:[~2022-04-20 19:10 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-20 18:28 [PATCH RFC 0/8] Make NFSv4 OPEN(CREATE) less brittle Chuck Lever
2022-04-20 18:28 ` [PATCH RFC 1/8] NFSD: Clean up nfsd3_proc_create() Chuck Lever
2022-04-20 18:28 ` [PATCH RFC 2/8] NFSD: Avoid calling fh_drop_write() twice in do_nfsd_create() Chuck Lever
2022-04-20 18:28 ` [PATCH RFC 3/8] NFSD: Refactor nfsd_create_setattr() Chuck Lever
2022-04-20 18:29 ` [PATCH RFC 4/8] NFSD: Refactor NFSv3 CREATE Chuck Lever
2022-04-20 19:10   ` J. Bruce Fields [this message]
2022-04-20 19:31     ` Chuck Lever III
2022-04-21 16:37       ` Bruce Fields
2022-04-20 18:29 ` [PATCH RFC 5/8] NFSD: Refactor NFSv4 OPEN(CREATE) Chuck Lever
2022-04-20 18:29 ` [PATCH RFC 6/8] NFSD: Remove do_nfsd_create() Chuck Lever
2022-04-20 18:29 ` [PATCH RFC 7/8] NFSD: Clean up nfsd_open_verified() Chuck Lever
2022-04-20 18:29 ` [PATCH RFC 8/8] NFSD: Instantiate a struct file when creating a regular NFSv4 file Chuck Lever
2022-04-20 19:24 ` [PATCH RFC 0/8] Make NFSv4 OPEN(CREATE) less brittle J. Bruce Fields

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220420191042.GA27805@fieldses.org \
    --to=bfields@fieldses.org \
    --cc=chuck.lever@oracle.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.