Received: by 2002:a05:6a10:6d10:0:0:0:0 with SMTP id gq16csp216153pxb; Wed, 20 Apr 2022 20:37:31 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwC8c/A6FozKLiy+NdpBvaQ1ZT1pQSBX1HiM4tmwPTqYoFgwzYyZDdEp4LuW5M/CbsjpuzT X-Received: by 2002:a17:906:7947:b0:6da:892f:2503 with SMTP id l7-20020a170906794700b006da892f2503mr20912378ejo.710.1650512251066; Wed, 20 Apr 2022 20:37:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1650512251; cv=none; d=google.com; s=arc-20160816; b=jUy2dGKMXS3HbBy47QxB4sdRakorAh2yy4qw5/lI6zk0aoz3zo768NRtXtTwXwtSXg jcHtJJjYOt0nZVfAgXvJErVv4uAsWlGXqMUpyG+PNGYKv5GpkLKedjy25G3kyTOaVlhM aTVvXp5XBsnQh3NVb4AL0zXEZXDiEhX+hNP9OBACHauLZs2tFqNUHXOV68pwMtbdDw65 badhFpEbilerLfTapwPSWO4vtfmgyp0ta56r54mgmAcFOij4JbX2G1KxVDScdOIDbUY5 UKH8PGoKsuj3OZHHD9w5fJMTSD1t15p8kHoODFi4r3DhEiW3hbPg42BpvmmXLkZzNYF1 mIfQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:to:from:subject; bh=qv5Li3iPJUPEkuY7OMz+n4KfhjkiZQGU/chztt3Sk1Y=; b=lDx/liuZ7XNEKq4mRIMOSuhP4YllIWmvXX1BC2/avbmcyP7zRnkCPG42vjbeDjRetB Hv8HsEqKzFzCA3mJIt48xXEqdWmXDFkXfqfj5Td5x/BbadUCWas26xcifJPuWcvXv27d P441+eqrvQTialinSna6sarH2PvIZOKaLtdnlPgDIsglRIdM5eLnlcz3Irhp3GgdHMRV vnc9HZ/lmW9XLf1l+bUZHPp714U6p/5SKZ+AtKc+YFmLx1mnjntcI7shvV7PgFaSvIlp E4ypAhWZueQIUdSfb9bbrFkMBd7+GrjiVCBNzmqil5p9OoNgKpdg5JgspaeDxQoWLD0r lihA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=oracle.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id jx1-20020a170907760100b006e89691632bsi3132056ejc.919.2022.04.20.20.36.32; Wed, 20 Apr 2022 20:37:31 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=oracle.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1381496AbiDTSby (ORCPT + 99 others); Wed, 20 Apr 2022 14:31:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52870 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238853AbiDTSbt (ORCPT ); Wed, 20 Apr 2022 14:31:49 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7963B1F60E; Wed, 20 Apr 2022 11:29:02 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 156D761B60; Wed, 20 Apr 2022 18:29:02 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5248DC385A8; Wed, 20 Apr 2022 18:29:01 +0000 (UTC) Subject: [PATCH RFC 4/8] NFSD: Refactor NFSv3 CREATE From: Chuck Lever To: linux-nfs@vger.kernel.org, linux-fsdevel@vger.kernel.org Date: Wed, 20 Apr 2022 14:29:00 -0400 Message-ID: <165047934027.1829.4170855794285748158.stgit@manet.1015granger.net> In-Reply-To: <165047903719.1829.18357114060053600197.stgit@manet.1015granger.net> References: <165047903719.1829.18357114060053600197.stgit@manet.1015granger.net> User-Agent: StGit/1.5 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-6.7 required=5.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,RCVD_IN_DNSWL_HI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org 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. Signed-off-by: Chuck Lever --- 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 #include #include +#include #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; }