Received: by 2002:a6b:fb09:0:0:0:0:0 with SMTP id h9csp2931481iog; Mon, 20 Jun 2022 07:44:40 -0700 (PDT) X-Google-Smtp-Source: AGRyM1v8Mf1FbEF1oH8w8yIW75q5/n7o/knO7OHcmId2X2y+g7H0KXLy9fKawP3hlHfyn21nfEYP X-Received: by 2002:a63:551e:0:b0:3fe:3f58:7ffb with SMTP id j30-20020a63551e000000b003fe3f587ffbmr22045323pgb.248.1655736280613; Mon, 20 Jun 2022 07:44:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655736280; cv=none; d=google.com; s=arc-20160816; b=aEqrBMeOIAWbFPhVP3VzEr7Lo2OpKE+4hf5ADq8869pxf9Wr4HFkGkF1EXFv8ZWncI 3IpMoP0Zv4cqG9i5wrowyF0JEX6a1t/ke2knSRlUfF9ER6Z/EfG3xK1K7E/9DTU6N0ud Lcz9bG8mUB3bCmz+njlLjWM5PdbSLfglIFuPMNKNYJLzJM61DnnrzGjDgkZJZv4SuprS cZqfzOtcdyGIygLc28x6Dz0zsLP6l0wFRpoVP0bTQkZmAlYTBdIDTe7ubVALkM/EKFr2 ZOuiAzqzZiX3TwVfPm5EV/tquBWcSuz4/AaXgjpZTKHweUSUg5n5xeI0qjV4GPmFx8vI +IEw== 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:subject:cc:to :from:dkim-signature; bh=GcRxc3ZdGqm/kjAqfGs+BJpQH7KRHbjQjdHNp55FIns=; b=rUsOsVCJWW6VLj6tfULB4i4QYZwQ/maUIlLzbXU/pRimklEX2hL801oWDJVffpfK/2 uRic6ZW4YJPaGFOcCKCEN65rU1V50hHPjxcvIoOaTiiaew/AWNSBVSJ++n6znbfsLeT6 Dost0XPtzdDyVp411s8zeObaFNMfqGOb9u3Nzz61GHMhkKqeMoFEiCHzGFuvCFr/m+AD Tl2zs4uBho4RVN7fj+uTmvjsEwzjUIHt7k89711YuN9NxbDK4EBtp3peML6cYTokhLaU dfD33/TkjLnKQhQkhdrMIuvOBWsdp5J1mXG3eA6ARIhwaM0j/u6SkQE2BznGGOxRJVJd D8eg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="zGJDz/Lz"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id t1-20020a170902e84100b00163e05df91asi20078236plg.37.2022.06.20.07.44.26; Mon, 20 Jun 2022 07:44:40 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-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; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="zGJDz/Lz"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243142AbiFTNVn (ORCPT + 99 others); Mon, 20 Jun 2022 09:21:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54500 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344635AbiFTNTP (ORCPT ); Mon, 20 Jun 2022 09:19:15 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CBD6662F6; Mon, 20 Jun 2022 06:08:05 -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 ams.source.kernel.org (Postfix) with ESMTPS id 5DDB5B811A5; Mon, 20 Jun 2022 13:05:33 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A625BC3411B; Mon, 20 Jun 2022 13:05:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1655730332; bh=/UQsAmbFVIpuvPOcEckSNMGt6DUFGPH1Xmq0UyI8F0M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=zGJDz/LzHpQ9deEcoTXF9uJudO8zVcUbWZNydsfTXmV6rDeSHoOSrSYC4wUdrGDWJ f7PiwK5XjO6wCrtUBb+Pg6Ho7xHAdGKNxeFHQ3+cg00NFUxL5iO30kcwkloP49gKAB jzRuvzdZLkcYyDKjOiTfi8tx6HBqSVAfmAyPPQms= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Trond Myklebust , Chuck Lever , Leah Rumancik Subject: [PATCH 5.15 002/106] nfsd: Replace use of rwsem with errseq_t Date: Mon, 20 Jun 2022 14:50:21 +0200 Message-Id: <20220620124724.456433227@linuxfoundation.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220620124724.380838401@linuxfoundation.org> References: <20220620124724.380838401@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE 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-kernel@vger.kernel.org From: Trond Myklebust commit 555dbf1a9aac6d3150c8b52fa35f768a692f4eeb upstream. The nfsd_file nf_rwsem is currently being used to separate file write and commit instances to ensure that we catch errors and apply them to the correct write/commit. We can improve scalability at the expense of a little accuracy (some extra false positives) by replacing the nf_rwsem with more careful use of the errseq_t mechanism to track errors across the different operations. Signed-off-by: Trond Myklebust Signed-off-by: Chuck Lever [ cel: rebased on zero-verifier fix ] Signed-off-by: Leah Rumancik Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/filecache.c | 1 - fs/nfsd/filecache.h | 1 - fs/nfsd/nfs4proc.c | 16 +++++++++------- fs/nfsd/vfs.c | 40 +++++++++++++++------------------------- 4 files changed, 24 insertions(+), 34 deletions(-) --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -194,7 +194,6 @@ nfsd_file_alloc(struct inode *inode, uns __set_bit(NFSD_FILE_BREAK_READ, &nf->nf_flags); } nf->nf_mark = NULL; - init_rwsem(&nf->nf_rwsem); trace_nfsd_file_alloc(nf); } return nf; --- a/fs/nfsd/filecache.h +++ b/fs/nfsd/filecache.h @@ -46,7 +46,6 @@ struct nfsd_file { refcount_t nf_ref; unsigned char nf_may; struct nfsd_file_mark *nf_mark; - struct rw_semaphore nf_rwsem; }; int nfsd_file_cache_init(void); --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1515,6 +1515,9 @@ static void nfsd4_init_copy_res(struct n static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy) { + struct file *dst = copy->nf_dst->nf_file; + struct file *src = copy->nf_src->nf_file; + errseq_t since; ssize_t bytes_copied = 0; u64 bytes_total = copy->cp_count; u64 src_pos = copy->cp_src_pos; @@ -1527,9 +1530,8 @@ static ssize_t _nfsd_copy_file_range(str do { if (kthread_should_stop()) break; - bytes_copied = nfsd_copy_file_range(copy->nf_src->nf_file, - src_pos, copy->nf_dst->nf_file, dst_pos, - bytes_total); + bytes_copied = nfsd_copy_file_range(src, src_pos, dst, dst_pos, + bytes_total); if (bytes_copied <= 0) break; bytes_total -= bytes_copied; @@ -1539,11 +1541,11 @@ static ssize_t _nfsd_copy_file_range(str } while (bytes_total > 0 && !copy->cp_synchronous); /* for a non-zero asynchronous copy do a commit of data */ if (!copy->cp_synchronous && copy->cp_res.wr_bytes_written > 0) { - down_write(©->nf_dst->nf_rwsem); - status = vfs_fsync_range(copy->nf_dst->nf_file, - copy->cp_dst_pos, + since = READ_ONCE(dst->f_wb_err); + status = vfs_fsync_range(dst, copy->cp_dst_pos, copy->cp_res.wr_bytes_written, 0); - up_write(©->nf_dst->nf_rwsem); + if (!status) + status = filemap_check_wb_err(dst->f_mapping, since); if (!status) copy->committed = true; } --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -525,10 +525,11 @@ __be32 nfsd4_clone_file_range(struct nfs { struct file *src = nf_src->nf_file; struct file *dst = nf_dst->nf_file; + errseq_t since; loff_t cloned; __be32 ret = 0; - down_write(&nf_dst->nf_rwsem); + since = READ_ONCE(dst->f_wb_err); cloned = vfs_clone_file_range(src, src_pos, dst, dst_pos, count, 0); if (cloned < 0) { ret = nfserrno(cloned); @@ -543,6 +544,8 @@ __be32 nfsd4_clone_file_range(struct nfs int status = vfs_fsync_range(dst, dst_pos, dst_end, 0); if (!status) + status = filemap_check_wb_err(dst->f_mapping, since); + if (!status) status = commit_inode_metadata(file_inode(src)); if (status < 0) { nfsd_reset_boot_verifier(net_generic(nf_dst->nf_net, @@ -551,7 +554,6 @@ __be32 nfsd4_clone_file_range(struct nfs } } out_err: - up_write(&nf_dst->nf_rwsem); return ret; } @@ -954,6 +956,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s struct super_block *sb = file_inode(file)->i_sb; struct svc_export *exp; struct iov_iter iter; + errseq_t since; __be32 nfserr; int host_err; int use_wgather; @@ -991,8 +994,8 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s flags |= RWF_SYNC; iov_iter_kvec(&iter, WRITE, vec, vlen, *cnt); + since = READ_ONCE(file->f_wb_err); if (flags & RWF_SYNC) { - down_write(&nf->nf_rwsem); if (verf) nfsd_copy_boot_verifier(verf, net_generic(SVC_NET(rqstp), @@ -1001,15 +1004,12 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s if (host_err < 0) nfsd_reset_boot_verifier(net_generic(SVC_NET(rqstp), nfsd_net_id)); - up_write(&nf->nf_rwsem); } else { - down_read(&nf->nf_rwsem); if (verf) nfsd_copy_boot_verifier(verf, net_generic(SVC_NET(rqstp), nfsd_net_id)); host_err = vfs_iter_write(file, &iter, &pos, flags); - up_read(&nf->nf_rwsem); } if (host_err < 0) { nfsd_reset_boot_verifier(net_generic(SVC_NET(rqstp), @@ -1019,6 +1019,9 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s *cnt = host_err; nfsd_stats_io_write_add(exp, *cnt); fsnotify_modify(file); + host_err = filemap_check_wb_err(file->f_mapping, since); + if (host_err < 0) + goto out_nfserr; if (stable && use_wgather) { host_err = wait_for_concurrent_writes(file); @@ -1099,19 +1102,6 @@ out: } #ifdef CONFIG_NFSD_V3 -static int -nfsd_filemap_write_and_wait_range(struct nfsd_file *nf, loff_t offset, - loff_t end) -{ - struct address_space *mapping = nf->nf_file->f_mapping; - int ret = filemap_fdatawrite_range(mapping, offset, end); - - if (ret) - return ret; - filemap_fdatawait_range_keep_errors(mapping, offset, end); - return 0; -} - /* * Commit all pending writes to stable storage. * @@ -1142,25 +1132,25 @@ nfsd_commit(struct svc_rqst *rqstp, stru if (err) goto out; if (EX_ISSYNC(fhp->fh_export)) { - int err2 = nfsd_filemap_write_and_wait_range(nf, offset, end); + errseq_t since = READ_ONCE(nf->nf_file->f_wb_err); + int err2; - down_write(&nf->nf_rwsem); - if (!err2) - err2 = vfs_fsync_range(nf->nf_file, offset, end, 0); + err2 = vfs_fsync_range(nf->nf_file, offset, end, 0); switch (err2) { case 0: nfsd_copy_boot_verifier(verf, net_generic(nf->nf_net, nfsd_net_id)); + err2 = filemap_check_wb_err(nf->nf_file->f_mapping, + since); break; case -EINVAL: err = nfserr_notsupp; break; default: - err = nfserrno(err2); nfsd_reset_boot_verifier(net_generic(nf->nf_net, nfsd_net_id)); } - up_write(&nf->nf_rwsem); + err = nfserrno(err2); } else nfsd_copy_boot_verifier(verf, net_generic(nf->nf_net, nfsd_net_id));