From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 433A7C433EF for ; Thu, 10 Mar 2022 16:15:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241303AbiCJQQQ (ORCPT ); Thu, 10 Mar 2022 11:16:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34638 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241260AbiCJQQI (ORCPT ); Thu, 10 Mar 2022 11:16:08 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id EF4B0190B6A for ; Thu, 10 Mar 2022 08:15:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646928906; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZjMIkmSkSKNxxAK97GvGjCGudJAQ3QXr9JiQLk1+Op0=; b=hxW5vKBUH3Va7URo13qSZn4HrW20MmkJRPd0SLkqfqCcRWRgYLXY9b1GgX5GfImFO1KcZV euJwB60LDMAguO6NbD9ygPi2/o1jaIXZMhfzYYIa8EqVAcY03A04Wu368yXDmQmMXdIlSI RPbsiGM+HpHpnSYdpQTXh+O1LUE7vPg= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-593-EB-cpjySNlOtJ_NGiXKktQ-1; Thu, 10 Mar 2022 11:15:03 -0500 X-MC-Unique: EB-cpjySNlOtJ_NGiXKktQ-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id DFDE0180FD75; Thu, 10 Mar 2022 16:15:00 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id C39DF83585; Thu, 10 Mar 2022 16:14:44 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 01/20] fscache: export fscache_end_operation() From: David Howells To: linux-cachefs@redhat.com Cc: Jeffle Xu , Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:14:43 +0000 Message-ID: <164692888334.2099075.5166283293894267365.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jeffle Xu Export fscache_end_operation() to avoid code duplication. Besides, considering the paired fscache_begin_read_operation() is already exported, it shall make sense to also export fscache_end_operation(). Signed-off-by: Jeffle Xu Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/20220302125134.131039-2-jefflexu@linux.alib= aba.com/ # Jeffle's v4 Link: https://lore.kernel.org/r/164622971432.3564931.12184135678781328146.s= tgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678190346.1200972.7453733431978569479.st= git@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/cifs/fscache.c | 8 -------- fs/fscache/internal.h | 11 ----------- fs/nfs/fscache.c | 8 -------- include/linux/fscache.h | 14 ++++++++++++++ 4 files changed, 14 insertions(+), 27 deletions(-) diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index 33af72e0ac0c..b47c2011ce5b 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c @@ -134,14 +134,6 @@ void cifs_fscache_release_inode_cookie(struct inode *i= node) } } =20 -static inline void fscache_end_operation(struct netfs_cache_resources *cre= s) -{ - const struct netfs_cache_ops *ops =3D fscache_operation_valid(cres); - - if (ops) - ops->end_operation(cres); -} - /* * Fallback page reading interface. */ diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index f121c21590dc..ed1c9ed737f2 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h @@ -70,17 +70,6 @@ static inline void fscache_see_cookie(struct fscache_coo= kie *cookie, where); } =20 -/* - * io.c - */ -static inline void fscache_end_operation(struct netfs_cache_resources *cre= s) -{ - const struct netfs_cache_ops *ops =3D fscache_operation_valid(cres); - - if (ops) - ops->end_operation(cres); -} - /* * main.c */ diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index cfe901650ab0..39654ca72d3d 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c @@ -249,14 +249,6 @@ void nfs_fscache_release_file(struct inode *inode, str= uct file *filp) } } =20 -static inline void fscache_end_operation(struct netfs_cache_resources *cre= s) -{ - const struct netfs_cache_ops *ops =3D fscache_operation_valid(cres); - - if (ops) - ops->end_operation(cres); -} - /* * Fallback page reading interface. */ diff --git a/include/linux/fscache.h b/include/linux/fscache.h index 296c5f1d9f35..d2430da8aa67 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -456,6 +456,20 @@ int fscache_begin_read_operation(struct netfs_cache_re= sources *cres, return -ENOBUFS; } =20 +/** + * fscache_end_operation - End the read operation for the netfs lib + * @cres: The cache resources for the read operation + * + * Clean up the resources at the end of the read request. + */ +static inline void fscache_end_operation(struct netfs_cache_resources *cre= s) +{ + const struct netfs_cache_ops *ops =3D fscache_operation_valid(cres); + + if (ops) + ops->end_operation(cres); +} + /** * fscache_read - Start a read from the cache. * @cres: The cache resources to use From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 97A22C433EF for ; Thu, 10 Mar 2022 16:15:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239783AbiCJQQZ (ORCPT ); Thu, 10 Mar 2022 11:16:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34778 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241260AbiCJQQS (ORCPT ); Thu, 10 Mar 2022 11:16:18 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D50FD190B74 for ; Thu, 10 Mar 2022 08:15:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646928916; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MOU92AtAA9qHsfo63bZdgdy40p1yYB+s0ukXBIMsfoE=; b=WA+1Pq18ZNndSeUqnBx6cnu8GRX4DWmbmMua9dob8+FvT2Gn7TFOiT9l6np2eu5+qV7P6y kRxtdFsB7Z4M7ixMrTaaAwoEdKUJSERuHtIw0s7B4Kj08PneNxGwf+rBilNi09Tn3OlPkK F3/n9Mnv4aXdDZrz/Y8sjYPkCV+6wvA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-298-GV3YzLnwN--QaPPEMualfg-1; Thu, 10 Mar 2022 11:15:13 -0500 X-MC-Unique: GV3YzLnwN--QaPPEMualfg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 213BE1006AA6; Thu, 10 Mar 2022 16:15:10 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1D01386599; Thu, 10 Mar 2022 16:15:06 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 02/20] netfs: Generate enums from trace symbol mapping lists From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:15:06 +0000 Message-ID: <164692890614.2099075.12960653141802151575.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org netfs has a number of lists of symbols for use in tracing, listed in an enum and then listed again in a symbol->string mapping for use with __print_symbolic(). This is, however, redundant. Instead, use the symbol->string mapping list to also generate the enum where the enum is in the same file. Changes =3D=3D=3D=3D=3D=3D=3D ver #3) - #undef EM and E_ at the end of the trace file[1]. Signed-off-by: David Howells Acked-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/c2f4b3dc107b106e04c48f54945a12715cccfdf3.ca= mel@redhat.com/ [1] Link: https://lore.kernel.org/r/164622980839.3564931.5673300162465266909.st= git@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678192454.1200972.4428834328108580460.st= git@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/CALF+zOkB38_MB5QwNUtqTU4WjMaLUJ5+Piwsn3pMxk= O3d4J7Kg@mail.gmail.com/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- include/trace/events/netfs.h | 59 +++++++++++---------------------------= ---- 1 file changed, 16 insertions(+), 43 deletions(-) diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index e6f4ebbb4c69..4d0bf02d490a 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -15,49 +15,6 @@ /* * Define enums for tracing information. */ -#ifndef __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY -#define __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY - -enum netfs_read_trace { - netfs_read_trace_expanded, - netfs_read_trace_readahead, - netfs_read_trace_readpage, - netfs_read_trace_write_begin, -}; - -enum netfs_rreq_trace { - netfs_rreq_trace_assess, - netfs_rreq_trace_done, - netfs_rreq_trace_free, - netfs_rreq_trace_resubmit, - netfs_rreq_trace_unlock, - netfs_rreq_trace_unmark, - netfs_rreq_trace_write, -}; - -enum netfs_sreq_trace { - netfs_sreq_trace_download_instead, - netfs_sreq_trace_free, - netfs_sreq_trace_prepare, - netfs_sreq_trace_resubmit_short, - netfs_sreq_trace_submit, - netfs_sreq_trace_terminated, - netfs_sreq_trace_write, - netfs_sreq_trace_write_skip, - netfs_sreq_trace_write_term, -}; - -enum netfs_failure { - netfs_fail_check_write_begin, - netfs_fail_copy_to_cache, - netfs_fail_read, - netfs_fail_short_readpage, - netfs_fail_short_write_begin, - netfs_fail_prepare_write, -}; - -#endif - #define netfs_read_traces \ EM(netfs_read_trace_expanded, "EXPANDED ") \ EM(netfs_read_trace_readahead, "READAHEAD") \ @@ -98,6 +55,20 @@ enum netfs_failure { EM(netfs_fail_short_write_begin, "short-write-begin") \ E_(netfs_fail_prepare_write, "prep-write") =20 +#ifndef __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY +#define __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY + +#undef EM +#undef E_ +#define EM(a, b) a, +#define E_(a, b) a + +enum netfs_read_trace { netfs_read_traces } __mode(byte); +enum netfs_rreq_trace { netfs_rreq_traces } __mode(byte); +enum netfs_sreq_trace { netfs_sreq_traces } __mode(byte); +enum netfs_failure { netfs_failures } __mode(byte); + +#endif =20 /* * Export enum symbols via userspace. @@ -258,6 +229,8 @@ TRACE_EVENT(netfs_failure, __entry->error) ); =20 +#undef EM +#undef E_ #endif /* _TRACE_NETFS_H */ =20 /* This part must be outside protection */ From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 092FFC4321E for ; Thu, 10 Mar 2022 16:15:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241371AbiCJQQj (ORCPT ); Thu, 10 Mar 2022 11:16:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35282 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241473AbiCJQQe (ORCPT ); Thu, 10 Mar 2022 11:16:34 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 0B45C191406 for ; Thu, 10 Mar 2022 08:15:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646928926; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=mNYnzPwF/W1EEadaIfirFng79KpXCXLNJYWScniVotg=; b=LleYfxqPx8wq+Z2HuyynWpCO0qmFepq9LNUbTZ9zApIb8K+BPhYEFpXIp1ZbY+AO5RRg0L 2D+eVLisgFIJYlMc641xau5TCriGCyP+KC6ZtheY7cudUS/inn+ZvqKVDCEVLehSO3XQ9y fR0Px/nexdIG1rL8+2PxYpmpw1LSOeU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-670-IPIn8APWMxGBk7NN_SnDfw-1; Thu, 10 Mar 2022 11:15:22 -0500 X-MC-Unique: IPIn8APWMxGBk7NN_SnDfw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6C9CB51EA; Thu, 10 Mar 2022 16:15:20 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3586586591; Thu, 10 Mar 2022 16:15:16 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 03/20] netfs: Rename netfs_read_*request to netfs_io_*request From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:15:15 +0000 Message-ID: <164692891535.2099075.18435198075367420588.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Rename netfs_read_*request to netfs_io_*request so that the same structures can be used for the write helpers too. perl -p -i -e 's/netfs_read_(request|subrequest)/netfs_io_$1/g' \ `git grep -l 'netfs_read_\(sub\|\)request'` perl -p -i -e 's/nr_rd_ops/nr_outstanding/g' \ `git grep -l nr_rd_ops` perl -p -i -e 's/nr_wr_ops/nr_copy_ops/g' \ `git grep -l nr_wr_ops` perl -p -i -e 's/netfs_read_source/netfs_io_source/g' \ `git grep -l 'netfs_read_source'` perl -p -i -e 's/netfs_io_request_ops/netfs_request_ops/g' \ `git grep -l 'netfs_io_request_ops'` perl -p -i -e 's/init_rreq/init_request/g' \ `git grep -l 'init_rreq'` Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164622988070.3564931.7089670190434315183.st= git@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678195157.1200972.366609966927368090.stg= it@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- Documentation/filesystems/netfs_library.rst | 40 +++--- fs/9p/vfs_addr.c | 16 +- fs/afs/file.c | 12 +- fs/afs/internal.h | 4 - fs/cachefiles/io.c | 6 - fs/ceph/addr.c | 16 +- fs/ceph/cache.h | 4 - fs/netfs/read_helper.c | 194 ++++++++++++++---------= ---- include/linux/netfs.h | 42 +++--- include/trace/events/cachefiles.h | 6 - include/trace/events/netfs.h | 14 +- 11 files changed, 177 insertions(+), 177 deletions(-) diff --git a/Documentation/filesystems/netfs_library.rst b/Documentation/fi= lesystems/netfs_library.rst index 4f373a8ec47b..a997e2d4321d 100644 --- a/Documentation/filesystems/netfs_library.rst +++ b/Documentation/filesystems/netfs_library.rst @@ -71,11 +71,11 @@ Read Helper Functions Three read helpers are provided:: =20 void netfs_readahead(struct readahead_control *ractl, - const struct netfs_read_request_ops *ops, + const struct netfs_request_ops *ops, void *netfs_priv); int netfs_readpage(struct file *file, struct folio *folio, - const struct netfs_read_request_ops *ops, + const struct netfs_request_ops *ops, void *netfs_priv); int netfs_write_begin(struct file *file, struct address_space *mapping, @@ -84,7 +84,7 @@ Three read helpers are provided:: unsigned int flags, struct folio **_folio, void **_fsdata, - const struct netfs_read_request_ops *ops, + const struct netfs_request_ops *ops, void *netfs_priv); =20 Each corresponds to a VM operation, with the addition of a couple of param= eters @@ -116,7 +116,7 @@ occurs, the request will get partially completed if suf= ficient data is read. =20 Additionally, there is:: =20 - * void netfs_subreq_terminated(struct netfs_read_subrequest *subreq, + * void netfs_subreq_terminated(struct netfs_io_subrequest *subreq, ssize_t transferred_or_error, bool was_async); =20 @@ -132,7 +132,7 @@ Read Helper Structures The read helpers make use of a couple of structures to maintain the state = of the read. The first is a structure that manages a read request as a whole= :: =20 - struct netfs_read_request { + struct netfs_io_request { struct inode *inode; struct address_space *mapping; struct netfs_cache_resources cache_resources; @@ -140,7 +140,7 @@ the read. The first is a structure that manages a read= request as a whole:: loff_t start; size_t len; loff_t i_size; - const struct netfs_read_request_ops *netfs_ops; + const struct netfs_request_ops *netfs_ops; unsigned int debug_id; ... }; @@ -187,8 +187,8 @@ The above fields are the ones the netfs can use. They = are: The second structure is used to manage individual slices of the overall re= ad request:: =20 - struct netfs_read_subrequest { - struct netfs_read_request *rreq; + struct netfs_io_subrequest { + struct netfs_io_request *rreq; loff_t start; size_t len; size_t transferred; @@ -244,23 +244,23 @@ Read Helper Operations The network filesystem must provide the read helpers with a table of opera= tions through which it can issue requests and negotiate:: =20 - struct netfs_read_request_ops { - void (*init_rreq)(struct netfs_read_request *rreq, struct file *file); + struct netfs_request_ops { + void (*init_request)(struct netfs_io_request *rreq, struct file *file); bool (*is_cache_enabled)(struct inode *inode); - int (*begin_cache_operation)(struct netfs_read_request *rreq); - void (*expand_readahead)(struct netfs_read_request *rreq); - bool (*clamp_length)(struct netfs_read_subrequest *subreq); - void (*issue_op)(struct netfs_read_subrequest *subreq); - bool (*is_still_valid)(struct netfs_read_request *rreq); + int (*begin_cache_operation)(struct netfs_io_request *rreq); + void (*expand_readahead)(struct netfs_io_request *rreq); + bool (*clamp_length)(struct netfs_io_subrequest *subreq); + void (*issue_op)(struct netfs_io_subrequest *subreq); + bool (*is_still_valid)(struct netfs_io_request *rreq); int (*check_write_begin)(struct file *file, loff_t pos, unsigned len, struct folio *folio, void **_fsdata); - void (*done)(struct netfs_read_request *rreq); + void (*done)(struct netfs_io_request *rreq); void (*cleanup)(struct address_space *mapping, void *netfs_priv); }; =20 The operations are as follows: =20 - * ``init_rreq()`` + * ``init_request()`` =20 [Optional] This is called to initialise the request structure. It is g= iven the file for reference and can modify the ->netfs_priv value. @@ -420,12 +420,12 @@ The network filesystem's ->begin_cache_operation() me= thod is called to set up a cache and this must call into the cache to do the work. If using fscache,= for example, the cache would call:: =20 - int fscache_begin_read_operation(struct netfs_read_request *rreq, + int fscache_begin_read_operation(struct netfs_io_request *rreq, struct fscache_cookie *cookie); =20 passing in the request pointer and the cookie corresponding to the file. =20 -The netfs_read_request object contains a place for the cache to hang its +The netfs_io_request object contains a place for the cache to hang its state:: =20 struct netfs_cache_resources { @@ -443,7 +443,7 @@ operation table looks like the following:: void (*expand_readahead)(struct netfs_cache_resources *cres, loff_t *_start, size_t *_len, loff_t i_size); =20 - enum netfs_read_source (*prepare_read)(struct netfs_read_subrequest *sub= req, + enum netfs_io_source (*prepare_read)(struct netfs_io_subrequest *subreq, loff_t i_size); =20 int (*read)(struct netfs_cache_resources *cres, diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 9a10e68c5f30..7b79fabe7593 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -31,9 +31,9 @@ * v9fs_req_issue_op - Issue a read from 9P * @subreq: The read to make */ -static void v9fs_req_issue_op(struct netfs_read_subrequest *subreq) +static void v9fs_req_issue_op(struct netfs_io_subrequest *subreq) { - struct netfs_read_request *rreq =3D subreq->rreq; + struct netfs_io_request *rreq =3D subreq->rreq; struct p9_fid *fid =3D rreq->netfs_priv; struct iov_iter to; loff_t pos =3D subreq->start + subreq->transferred; @@ -52,11 +52,11 @@ static void v9fs_req_issue_op(struct netfs_read_subrequ= est *subreq) } =20 /** - * v9fs_init_rreq - Initialise a read request + * v9fs_init_request - Initialise a read request * @rreq: The read request * @file: The file being read from */ -static void v9fs_init_rreq(struct netfs_read_request *rreq, struct file *f= ile) +static void v9fs_init_request(struct netfs_io_request *rreq, struct file *= file) { struct p9_fid *fid =3D file->private_data; =20 @@ -65,7 +65,7 @@ static void v9fs_init_rreq(struct netfs_read_request *rre= q, struct file *file) } =20 /** - * v9fs_req_cleanup - Cleanup request initialized by v9fs_init_rreq + * v9fs_req_cleanup - Cleanup request initialized by v9fs_init_request * @mapping: unused mapping of request to cleanup * @priv: private data to cleanup, a fid, guaranted non-null. */ @@ -91,7 +91,7 @@ static bool v9fs_is_cache_enabled(struct inode *inode) * v9fs_begin_cache_operation - Begin a cache operation for a read * @rreq: The read request */ -static int v9fs_begin_cache_operation(struct netfs_read_request *rreq) +static int v9fs_begin_cache_operation(struct netfs_io_request *rreq) { #ifdef CONFIG_9P_FSCACHE struct fscache_cookie *cookie =3D v9fs_inode_cookie(V9FS_I(rreq->inode)); @@ -102,8 +102,8 @@ static int v9fs_begin_cache_operation(struct netfs_read= _request *rreq) #endif } =20 -static const struct netfs_read_request_ops v9fs_req_ops =3D { - .init_rreq =3D v9fs_init_rreq, +static const struct netfs_request_ops v9fs_req_ops =3D { + .init_request =3D v9fs_init_request, .is_cache_enabled =3D v9fs_is_cache_enabled, .begin_cache_operation =3D v9fs_begin_cache_operation, .issue_op =3D v9fs_req_issue_op, diff --git a/fs/afs/file.c b/fs/afs/file.c index 720818a7c166..e55761f8858c 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -240,7 +240,7 @@ void afs_put_read(struct afs_read *req) static void afs_fetch_data_notify(struct afs_operation *op) { struct afs_read *req =3D op->fetch.req; - struct netfs_read_subrequest *subreq =3D req->subreq; + struct netfs_io_subrequest *subreq =3D req->subreq; int error =3D op->error; =20 if (error =3D=3D -ECONNABORTED) @@ -310,7 +310,7 @@ int afs_fetch_data(struct afs_vnode *vnode, struct afs_= read *req) return afs_do_sync_operation(op); } =20 -static void afs_req_issue_op(struct netfs_read_subrequest *subreq) +static void afs_req_issue_op(struct netfs_io_subrequest *subreq) { struct afs_vnode *vnode =3D AFS_FS_I(subreq->rreq->inode); struct afs_read *fsreq; @@ -359,7 +359,7 @@ static int afs_symlink_readpage(struct file *file, stru= ct page *page) return ret; } =20 -static void afs_init_rreq(struct netfs_read_request *rreq, struct file *fi= le) +static void afs_init_request(struct netfs_io_request *rreq, struct file *f= ile) { rreq->netfs_priv =3D key_get(afs_file_key(file)); } @@ -371,7 +371,7 @@ static bool afs_is_cache_enabled(struct inode *inode) return fscache_cookie_enabled(cookie) && cookie->cache_priv; } =20 -static int afs_begin_cache_operation(struct netfs_read_request *rreq) +static int afs_begin_cache_operation(struct netfs_io_request *rreq) { #ifdef CONFIG_AFS_FSCACHE struct afs_vnode *vnode =3D AFS_FS_I(rreq->inode); @@ -396,8 +396,8 @@ static void afs_priv_cleanup(struct address_space *mapp= ing, void *netfs_priv) key_put(netfs_priv); } =20 -const struct netfs_read_request_ops afs_req_ops =3D { - .init_rreq =3D afs_init_rreq, +const struct netfs_request_ops afs_req_ops =3D { + .init_request =3D afs_init_request, .is_cache_enabled =3D afs_is_cache_enabled, .begin_cache_operation =3D afs_begin_cache_operation, .check_write_begin =3D afs_check_write_begin, diff --git a/fs/afs/internal.h b/fs/afs/internal.h index b6f02321fc09..c56a0e1719ae 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -207,7 +207,7 @@ struct afs_read { loff_t file_size; /* File size returned by server */ struct key *key; /* The key to use to reissue the read */ struct afs_vnode *vnode; /* The file being read into. */ - struct netfs_read_subrequest *subreq; /* Fscache helper read request this= belongs to */ + struct netfs_io_subrequest *subreq; /* Fscache helper read request this b= elongs to */ afs_dataversion_t data_version; /* Version number returned by server */ refcount_t usage; unsigned int call_debug_id; @@ -1063,7 +1063,7 @@ extern const struct address_space_operations afs_file= _aops; extern const struct address_space_operations afs_symlink_aops; extern const struct inode_operations afs_file_inode_operations; extern const struct file_operations afs_file_operations; -extern const struct netfs_read_request_ops afs_req_ops; +extern const struct netfs_request_ops afs_req_ops; =20 extern int afs_cache_wb_key(struct afs_vnode *, struct afs_file *); extern void afs_put_wb_key(struct afs_wb_key *); diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c index 753986ea1583..6ac6fdbc70d3 100644 --- a/fs/cachefiles/io.c +++ b/fs/cachefiles/io.c @@ -382,18 +382,18 @@ static int cachefiles_write(struct netfs_cache_resour= ces *cres, * Prepare a read operation, shortening it to a cached/uncached * boundary as appropriate. */ -static enum netfs_read_source cachefiles_prepare_read(struct netfs_read_su= brequest *subreq, +static enum netfs_io_source cachefiles_prepare_read(struct netfs_io_subreq= uest *subreq, loff_t i_size) { enum cachefiles_prepare_read_trace why; - struct netfs_read_request *rreq =3D subreq->rreq; + struct netfs_io_request *rreq =3D subreq->rreq; struct netfs_cache_resources *cres =3D &rreq->cache_resources; struct cachefiles_object *object; struct cachefiles_cache *cache; struct fscache_cookie *cookie =3D fscache_cres_cookie(cres); const struct cred *saved_cred; struct file *file =3D cachefiles_cres_file(cres); - enum netfs_read_source ret =3D NETFS_DOWNLOAD_FROM_SERVER; + enum netfs_io_source ret =3D NETFS_DOWNLOAD_FROM_SERVER; loff_t off, to; ino_t ino =3D file ? file_inode(file)->i_ino : 0; =20 diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 46e0881ae8b2..9d995f351079 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -183,7 +183,7 @@ static int ceph_releasepage(struct page *page, gfp_t gf= p) return 1; } =20 -static void ceph_netfs_expand_readahead(struct netfs_read_request *rreq) +static void ceph_netfs_expand_readahead(struct netfs_io_request *rreq) { struct inode *inode =3D rreq->inode; struct ceph_inode_info *ci =3D ceph_inode(inode); @@ -200,7 +200,7 @@ static void ceph_netfs_expand_readahead(struct netfs_re= ad_request *rreq) rreq->len =3D roundup(rreq->len, lo->stripe_unit); } =20 -static bool ceph_netfs_clamp_length(struct netfs_read_subrequest *subreq) +static bool ceph_netfs_clamp_length(struct netfs_io_subrequest *subreq) { struct inode *inode =3D subreq->rreq->inode; struct ceph_fs_client *fsc =3D ceph_inode_to_client(inode); @@ -219,7 +219,7 @@ static void finish_netfs_read(struct ceph_osd_request *= req) { struct ceph_fs_client *fsc =3D ceph_inode_to_client(req->r_inode); struct ceph_osd_data *osd_data =3D osd_req_op_extent_osd_data(req, 0); - struct netfs_read_subrequest *subreq =3D req->r_priv; + struct netfs_io_subrequest *subreq =3D req->r_priv; int num_pages; int err =3D req->r_result; =20 @@ -245,9 +245,9 @@ static void finish_netfs_read(struct ceph_osd_request *= req) iput(req->r_inode); } =20 -static bool ceph_netfs_issue_op_inline(struct netfs_read_subrequest *subre= q) +static bool ceph_netfs_issue_op_inline(struct netfs_io_subrequest *subreq) { - struct netfs_read_request *rreq =3D subreq->rreq; + struct netfs_io_request *rreq =3D subreq->rreq; struct inode *inode =3D rreq->inode; struct ceph_mds_reply_info_parsed *rinfo; struct ceph_mds_reply_info_in *iinfo; @@ -298,9 +298,9 @@ static bool ceph_netfs_issue_op_inline(struct netfs_rea= d_subrequest *subreq) return true; } =20 -static void ceph_netfs_issue_op(struct netfs_read_subrequest *subreq) +static void ceph_netfs_issue_op(struct netfs_io_subrequest *subreq) { - struct netfs_read_request *rreq =3D subreq->rreq; + struct netfs_io_request *rreq =3D subreq->rreq; struct inode *inode =3D rreq->inode; struct ceph_inode_info *ci =3D ceph_inode(inode); struct ceph_fs_client *fsc =3D ceph_inode_to_client(inode); @@ -364,7 +364,7 @@ static void ceph_readahead_cleanup(struct address_space= *mapping, void *priv) ceph_put_cap_refs(ci, got); } =20 -static const struct netfs_read_request_ops ceph_netfs_read_ops =3D { +static const struct netfs_request_ops ceph_netfs_read_ops =3D { .is_cache_enabled =3D ceph_is_cache_enabled, .begin_cache_operation =3D ceph_begin_cache_operation, .issue_op =3D ceph_netfs_issue_op, diff --git a/fs/ceph/cache.h b/fs/ceph/cache.h index 09164389fa66..b8b3b5cb6438 100644 --- a/fs/ceph/cache.h +++ b/fs/ceph/cache.h @@ -62,7 +62,7 @@ static inline int ceph_fscache_set_page_dirty(struct page= *page) return fscache_set_page_dirty(page, ceph_fscache_cookie(ci)); } =20 -static inline int ceph_begin_cache_operation(struct netfs_read_request *rr= eq) +static inline int ceph_begin_cache_operation(struct netfs_io_request *rreq) { struct fscache_cookie *cookie =3D ceph_fscache_cookie(ceph_inode(rreq->in= ode)); =20 @@ -143,7 +143,7 @@ static inline bool ceph_is_cache_enabled(struct inode *= inode) return false; } =20 -static inline int ceph_begin_cache_operation(struct netfs_read_request *rr= eq) +static inline int ceph_begin_cache_operation(struct netfs_io_request *rreq) { return -ENOBUFS; } diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index 501da990c259..50035d93f1dc 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -28,23 +28,23 @@ module_param_named(debug, netfs_debug, uint, S_IWUSR | = S_IRUGO); MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask"); =20 static void netfs_rreq_work(struct work_struct *); -static void __netfs_put_subrequest(struct netfs_read_subrequest *, bool); +static void __netfs_put_subrequest(struct netfs_io_subrequest *, bool); =20 -static void netfs_put_subrequest(struct netfs_read_subrequest *subreq, +static void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_async) { if (refcount_dec_and_test(&subreq->usage)) __netfs_put_subrequest(subreq, was_async); } =20 -static struct netfs_read_request *netfs_alloc_read_request( - const struct netfs_read_request_ops *ops, void *netfs_priv, +static struct netfs_io_request *netfs_alloc_read_request( + const struct netfs_request_ops *ops, void *netfs_priv, struct file *file) { static atomic_t debug_ids; - struct netfs_read_request *rreq; + struct netfs_io_request *rreq; =20 - rreq =3D kzalloc(sizeof(struct netfs_read_request), GFP_KERNEL); + rreq =3D kzalloc(sizeof(struct netfs_io_request), GFP_KERNEL); if (rreq) { rreq->netfs_ops =3D ops; rreq->netfs_priv =3D netfs_priv; @@ -55,27 +55,27 @@ static struct netfs_read_request *netfs_alloc_read_requ= est( INIT_WORK(&rreq->work, netfs_rreq_work); refcount_set(&rreq->usage, 1); __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); - if (ops->init_rreq) - ops->init_rreq(rreq, file); + if (ops->init_request) + ops->init_request(rreq, file); netfs_stat(&netfs_n_rh_rreq); } =20 return rreq; } =20 -static void netfs_get_read_request(struct netfs_read_request *rreq) +static void netfs_get_read_request(struct netfs_io_request *rreq) { refcount_inc(&rreq->usage); } =20 -static void netfs_rreq_clear_subreqs(struct netfs_read_request *rreq, +static void netfs_rreq_clear_subreqs(struct netfs_io_request *rreq, bool was_async) { - struct netfs_read_subrequest *subreq; + struct netfs_io_subrequest *subreq; =20 while (!list_empty(&rreq->subrequests)) { subreq =3D list_first_entry(&rreq->subrequests, - struct netfs_read_subrequest, rreq_link); + struct netfs_io_subrequest, rreq_link); list_del(&subreq->rreq_link); netfs_put_subrequest(subreq, was_async); } @@ -83,8 +83,8 @@ static void netfs_rreq_clear_subreqs(struct netfs_read_re= quest *rreq, =20 static void netfs_free_read_request(struct work_struct *work) { - struct netfs_read_request *rreq =3D - container_of(work, struct netfs_read_request, work); + struct netfs_io_request *rreq =3D + container_of(work, struct netfs_io_request, work); netfs_rreq_clear_subreqs(rreq, false); if (rreq->netfs_priv) rreq->netfs_ops->cleanup(rreq->mapping, rreq->netfs_priv); @@ -95,7 +95,7 @@ static void netfs_free_read_request(struct work_struct *w= ork) netfs_stat_d(&netfs_n_rh_rreq); } =20 -static void netfs_put_read_request(struct netfs_read_request *rreq, bool w= as_async) +static void netfs_put_read_request(struct netfs_io_request *rreq, bool was= _async) { if (refcount_dec_and_test(&rreq->usage)) { if (was_async) { @@ -111,12 +111,12 @@ static void netfs_put_read_request(struct netfs_read_= request *rreq, bool was_asy /* * Allocate and partially initialise an I/O request structure. */ -static struct netfs_read_subrequest *netfs_alloc_subrequest( - struct netfs_read_request *rreq) +static struct netfs_io_subrequest *netfs_alloc_subrequest( + struct netfs_io_request *rreq) { - struct netfs_read_subrequest *subreq; + struct netfs_io_subrequest *subreq; =20 - subreq =3D kzalloc(sizeof(struct netfs_read_subrequest), GFP_KERNEL); + subreq =3D kzalloc(sizeof(struct netfs_io_subrequest), GFP_KERNEL); if (subreq) { INIT_LIST_HEAD(&subreq->rreq_link); refcount_set(&subreq->usage, 2); @@ -128,15 +128,15 @@ static struct netfs_read_subrequest *netfs_alloc_subr= equest( return subreq; } =20 -static void netfs_get_read_subrequest(struct netfs_read_subrequest *subreq) +static void netfs_get_read_subrequest(struct netfs_io_subrequest *subreq) { refcount_inc(&subreq->usage); } =20 -static void __netfs_put_subrequest(struct netfs_read_subrequest *subreq, +static void __netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_async) { - struct netfs_read_request *rreq =3D subreq->rreq; + struct netfs_io_request *rreq =3D subreq->rreq; =20 trace_netfs_sreq(subreq, netfs_sreq_trace_free); kfree(subreq); @@ -147,7 +147,7 @@ static void __netfs_put_subrequest(struct netfs_read_su= brequest *subreq, /* * Clear the unread part of an I/O request. */ -static void netfs_clear_unread(struct netfs_read_subrequest *subreq) +static void netfs_clear_unread(struct netfs_io_subrequest *subreq) { struct iov_iter iter; =20 @@ -160,7 +160,7 @@ static void netfs_clear_unread(struct netfs_read_subreq= uest *subreq) static void netfs_cache_read_terminated(void *priv, ssize_t transferred_or= _error, bool was_async) { - struct netfs_read_subrequest *subreq =3D priv; + struct netfs_io_subrequest *subreq =3D priv; =20 netfs_subreq_terminated(subreq, transferred_or_error, was_async); } @@ -169,8 +169,8 @@ static void netfs_cache_read_terminated(void *priv, ssi= ze_t transferred_or_error * Issue a read against the cache. * - Eats the caller's ref on subreq. */ -static void netfs_read_from_cache(struct netfs_read_request *rreq, - struct netfs_read_subrequest *subreq, +static void netfs_read_from_cache(struct netfs_io_request *rreq, + struct netfs_io_subrequest *subreq, enum netfs_read_from_hole read_hole) { struct netfs_cache_resources *cres =3D &rreq->cache_resources; @@ -188,8 +188,8 @@ static void netfs_read_from_cache(struct netfs_read_req= uest *rreq, /* * Fill a subrequest region with zeroes. */ -static void netfs_fill_with_zeroes(struct netfs_read_request *rreq, - struct netfs_read_subrequest *subreq) +static void netfs_fill_with_zeroes(struct netfs_io_request *rreq, + struct netfs_io_subrequest *subreq) { netfs_stat(&netfs_n_rh_zero); __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); @@ -212,8 +212,8 @@ static void netfs_fill_with_zeroes(struct netfs_read_re= quest *rreq, * - NETFS_SREQ_CLEAR_TAIL: A short read - the rest of the buffer will be * cleared. */ -static void netfs_read_from_server(struct netfs_read_request *rreq, - struct netfs_read_subrequest *subreq) +static void netfs_read_from_server(struct netfs_io_request *rreq, + struct netfs_io_subrequest *subreq) { netfs_stat(&netfs_n_rh_download); rreq->netfs_ops->issue_op(subreq); @@ -222,7 +222,7 @@ static void netfs_read_from_server(struct netfs_read_re= quest *rreq, /* * Release those waiting. */ -static void netfs_rreq_completed(struct netfs_read_request *rreq, bool was= _async) +static void netfs_rreq_completed(struct netfs_io_request *rreq, bool was_a= sync) { trace_netfs_rreq(rreq, netfs_rreq_trace_done); netfs_rreq_clear_subreqs(rreq, was_async); @@ -235,10 +235,10 @@ static void netfs_rreq_completed(struct netfs_read_re= quest *rreq, bool was_async * * May be called in softirq mode and we inherit a ref from the caller. */ -static void netfs_rreq_unmark_after_write(struct netfs_read_request *rreq, +static void netfs_rreq_unmark_after_write(struct netfs_io_request *rreq, bool was_async) { - struct netfs_read_subrequest *subreq; + struct netfs_io_subrequest *subreq; struct folio *folio; pgoff_t unlocked =3D 0; bool have_unlocked =3D false; @@ -267,8 +267,8 @@ static void netfs_rreq_unmark_after_write(struct netfs_= read_request *rreq, static void netfs_rreq_copy_terminated(void *priv, ssize_t transferred_or_= error, bool was_async) { - struct netfs_read_subrequest *subreq =3D priv; - struct netfs_read_request *rreq =3D subreq->rreq; + struct netfs_io_subrequest *subreq =3D priv; + struct netfs_io_request *rreq =3D subreq->rreq; =20 if (IS_ERR_VALUE(transferred_or_error)) { netfs_stat(&netfs_n_rh_write_failed); @@ -280,8 +280,8 @@ static void netfs_rreq_copy_terminated(void *priv, ssiz= e_t transferred_or_error, =20 trace_netfs_sreq(subreq, netfs_sreq_trace_write_term); =20 - /* If we decrement nr_wr_ops to 0, the ref belongs to us. */ - if (atomic_dec_and_test(&rreq->nr_wr_ops)) + /* If we decrement nr_copy_ops to 0, the ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_copy_ops)) netfs_rreq_unmark_after_write(rreq, was_async); =20 netfs_put_subrequest(subreq, was_async); @@ -291,10 +291,10 @@ static void netfs_rreq_copy_terminated(void *priv, ss= ize_t transferred_or_error, * Perform any outstanding writes to the cache. We inherit a ref from the * caller. */ -static void netfs_rreq_do_write_to_cache(struct netfs_read_request *rreq) +static void netfs_rreq_do_write_to_cache(struct netfs_io_request *rreq) { struct netfs_cache_resources *cres =3D &rreq->cache_resources; - struct netfs_read_subrequest *subreq, *next, *p; + struct netfs_io_subrequest *subreq, *next, *p; struct iov_iter iter; int ret; =20 @@ -303,7 +303,7 @@ static void netfs_rreq_do_write_to_cache(struct netfs_r= ead_request *rreq) /* We don't want terminating writes trying to wake us up whilst we're * still going through the list. */ - atomic_inc(&rreq->nr_wr_ops); + atomic_inc(&rreq->nr_copy_ops); =20 list_for_each_entry_safe(subreq, p, &rreq->subrequests, rreq_link) { if (!test_bit(NETFS_SREQ_WRITE_TO_CACHE, &subreq->flags)) { @@ -334,7 +334,7 @@ static void netfs_rreq_do_write_to_cache(struct netfs_r= ead_request *rreq) iov_iter_xarray(&iter, WRITE, &rreq->mapping->i_pages, subreq->start, subreq->len); =20 - atomic_inc(&rreq->nr_wr_ops); + atomic_inc(&rreq->nr_copy_ops); netfs_stat(&netfs_n_rh_write); netfs_get_read_subrequest(subreq); trace_netfs_sreq(subreq, netfs_sreq_trace_write); @@ -342,20 +342,20 @@ static void netfs_rreq_do_write_to_cache(struct netfs= _read_request *rreq) netfs_rreq_copy_terminated, subreq); } =20 - /* If we decrement nr_wr_ops to 0, the usage ref belongs to us. */ - if (atomic_dec_and_test(&rreq->nr_wr_ops)) + /* If we decrement nr_copy_ops to 0, the usage ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_copy_ops)) netfs_rreq_unmark_after_write(rreq, false); } =20 static void netfs_rreq_write_to_cache_work(struct work_struct *work) { - struct netfs_read_request *rreq =3D - container_of(work, struct netfs_read_request, work); + struct netfs_io_request *rreq =3D + container_of(work, struct netfs_io_request, work); =20 netfs_rreq_do_write_to_cache(rreq); } =20 -static void netfs_rreq_write_to_cache(struct netfs_read_request *rreq) +static void netfs_rreq_write_to_cache(struct netfs_io_request *rreq) { rreq->work.func =3D netfs_rreq_write_to_cache_work; if (!queue_work(system_unbound_wq, &rreq->work)) @@ -366,9 +366,9 @@ static void netfs_rreq_write_to_cache(struct netfs_read= _request *rreq) * Unlock the folios in a read operation. We need to set PG_fscache on any * folios we're going to write back before we unlock them. */ -static void netfs_rreq_unlock(struct netfs_read_request *rreq) +static void netfs_rreq_unlock(struct netfs_io_request *rreq) { - struct netfs_read_subrequest *subreq; + struct netfs_io_subrequest *subreq; struct folio *folio; unsigned int iopos, account =3D 0; pgoff_t start_page =3D rreq->start / PAGE_SIZE; @@ -391,7 +391,7 @@ static void netfs_rreq_unlock(struct netfs_read_request= *rreq) * mixture inside. */ subreq =3D list_first_entry(&rreq->subrequests, - struct netfs_read_subrequest, rreq_link); + struct netfs_io_subrequest, rreq_link); iopos =3D 0; subreq_failed =3D (subreq->error < 0); =20 @@ -450,8 +450,8 @@ static void netfs_rreq_unlock(struct netfs_read_request= *rreq) /* * Handle a short read. */ -static void netfs_rreq_short_read(struct netfs_read_request *rreq, - struct netfs_read_subrequest *subreq) +static void netfs_rreq_short_read(struct netfs_io_request *rreq, + struct netfs_io_subrequest *subreq) { __clear_bit(NETFS_SREQ_SHORT_READ, &subreq->flags); __set_bit(NETFS_SREQ_SEEK_DATA_READ, &subreq->flags); @@ -460,7 +460,7 @@ static void netfs_rreq_short_read(struct netfs_read_req= uest *rreq, trace_netfs_sreq(subreq, netfs_sreq_trace_resubmit_short); =20 netfs_get_read_subrequest(subreq); - atomic_inc(&rreq->nr_rd_ops); + atomic_inc(&rreq->nr_outstanding); if (subreq->source =3D=3D NETFS_READ_FROM_CACHE) netfs_read_from_cache(rreq, subreq, NETFS_READ_HOLE_CLEAR); else @@ -471,9 +471,9 @@ static void netfs_rreq_short_read(struct netfs_read_req= uest *rreq, * Resubmit any short or failed operations. Returns true if we got the rr= eq * ref back. */ -static bool netfs_rreq_perform_resubmissions(struct netfs_read_request *rr= eq) +static bool netfs_rreq_perform_resubmissions(struct netfs_io_request *rreq) { - struct netfs_read_subrequest *subreq; + struct netfs_io_subrequest *subreq; =20 WARN_ON(in_interrupt()); =20 @@ -482,7 +482,7 @@ static bool netfs_rreq_perform_resubmissions(struct net= fs_read_request *rreq) /* We don't want terminating submissions trying to wake us up whilst * we're still going through the list. */ - atomic_inc(&rreq->nr_rd_ops); + atomic_inc(&rreq->nr_outstanding); =20 __clear_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags); list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { @@ -494,27 +494,27 @@ static bool netfs_rreq_perform_resubmissions(struct n= etfs_read_request *rreq) netfs_stat(&netfs_n_rh_download_instead); trace_netfs_sreq(subreq, netfs_sreq_trace_download_instead); netfs_get_read_subrequest(subreq); - atomic_inc(&rreq->nr_rd_ops); + atomic_inc(&rreq->nr_outstanding); netfs_read_from_server(rreq, subreq); } else if (test_bit(NETFS_SREQ_SHORT_READ, &subreq->flags)) { netfs_rreq_short_read(rreq, subreq); } } =20 - /* If we decrement nr_rd_ops to 0, the usage ref belongs to us. */ - if (atomic_dec_and_test(&rreq->nr_rd_ops)) + /* If we decrement nr_outstanding to 0, the usage ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_outstanding)) return true; =20 - wake_up_var(&rreq->nr_rd_ops); + wake_up_var(&rreq->nr_outstanding); return false; } =20 /* * Check to see if the data read is still valid. */ -static void netfs_rreq_is_still_valid(struct netfs_read_request *rreq) +static void netfs_rreq_is_still_valid(struct netfs_io_request *rreq) { - struct netfs_read_subrequest *subreq; + struct netfs_io_subrequest *subreq; =20 if (!rreq->netfs_ops->is_still_valid || rreq->netfs_ops->is_still_valid(rreq)) @@ -534,7 +534,7 @@ static void netfs_rreq_is_still_valid(struct netfs_read= _request *rreq) * Note that we could be in an ordinary kernel thread, on a workqueue or in * softirq context at this point. We inherit a ref from the caller. */ -static void netfs_rreq_assess(struct netfs_read_request *rreq, bool was_as= ync) +static void netfs_rreq_assess(struct netfs_io_request *rreq, bool was_asyn= c) { trace_netfs_rreq(rreq, netfs_rreq_trace_assess); =20 @@ -561,8 +561,8 @@ static void netfs_rreq_assess(struct netfs_read_request= *rreq, bool was_async) =20 static void netfs_rreq_work(struct work_struct *work) { - struct netfs_read_request *rreq =3D - container_of(work, struct netfs_read_request, work); + struct netfs_io_request *rreq =3D + container_of(work, struct netfs_io_request, work); netfs_rreq_assess(rreq, false); } =20 @@ -570,7 +570,7 @@ static void netfs_rreq_work(struct work_struct *work) * Handle the completion of all outstanding I/O operations on a read reque= st. * We inherit a ref from the caller. */ -static void netfs_rreq_terminated(struct netfs_read_request *rreq, +static void netfs_rreq_terminated(struct netfs_io_request *rreq, bool was_async) { if (test_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags) && @@ -600,11 +600,11 @@ static void netfs_rreq_terminated(struct netfs_read_r= equest *rreq, * If @was_async is true, the caller might be running in softirq or interr= upt * context and we can't sleep. */ -void netfs_subreq_terminated(struct netfs_read_subrequest *subreq, +void netfs_subreq_terminated(struct netfs_io_subrequest *subreq, ssize_t transferred_or_error, bool was_async) { - struct netfs_read_request *rreq =3D subreq->rreq; + struct netfs_io_request *rreq =3D subreq->rreq; int u; =20 _enter("[%u]{%llx,%lx},%zd", @@ -648,12 +648,12 @@ void netfs_subreq_terminated(struct netfs_read_subreq= uest *subreq, out: trace_netfs_sreq(subreq, netfs_sreq_trace_terminated); =20 - /* If we decrement nr_rd_ops to 0, the ref belongs to us. */ - u =3D atomic_dec_return(&rreq->nr_rd_ops); + /* If we decrement nr_outstanding to 0, the ref belongs to us. */ + u =3D atomic_dec_return(&rreq->nr_outstanding); if (u =3D=3D 0) netfs_rreq_terminated(rreq, was_async); else if (u =3D=3D 1) - wake_up_var(&rreq->nr_rd_ops); + wake_up_var(&rreq->nr_outstanding); =20 netfs_put_subrequest(subreq, was_async); return; @@ -691,10 +691,10 @@ void netfs_subreq_terminated(struct netfs_read_subreq= uest *subreq, } EXPORT_SYMBOL(netfs_subreq_terminated); =20 -static enum netfs_read_source netfs_cache_prepare_read(struct netfs_read_s= ubrequest *subreq, +static enum netfs_io_source netfs_cache_prepare_read(struct netfs_io_subre= quest *subreq, loff_t i_size) { - struct netfs_read_request *rreq =3D subreq->rreq; + struct netfs_io_request *rreq =3D subreq->rreq; struct netfs_cache_resources *cres =3D &rreq->cache_resources; =20 if (cres->ops) @@ -707,11 +707,11 @@ static enum netfs_read_source netfs_cache_prepare_rea= d(struct netfs_read_subrequ /* * Work out what sort of subrequest the next one will be. */ -static enum netfs_read_source -netfs_rreq_prepare_read(struct netfs_read_request *rreq, - struct netfs_read_subrequest *subreq) +static enum netfs_io_source +netfs_rreq_prepare_read(struct netfs_io_request *rreq, + struct netfs_io_subrequest *subreq) { - enum netfs_read_source source; + enum netfs_io_source source; =20 _enter("%llx-%llx,%llx", subreq->start, subreq->start + subreq->len, rreq= ->i_size); =20 @@ -748,11 +748,11 @@ netfs_rreq_prepare_read(struct netfs_read_request *rr= eq, /* * Slice off a piece of a read request and submit an I/O request for it. */ -static bool netfs_rreq_submit_slice(struct netfs_read_request *rreq, +static bool netfs_rreq_submit_slice(struct netfs_io_request *rreq, unsigned int *_debug_index) { - struct netfs_read_subrequest *subreq; - enum netfs_read_source source; + struct netfs_io_subrequest *subreq; + enum netfs_io_source source; =20 subreq =3D netfs_alloc_subrequest(rreq); if (!subreq) @@ -777,7 +777,7 @@ static bool netfs_rreq_submit_slice(struct netfs_read_r= equest *rreq, if (source =3D=3D NETFS_INVALID_READ) goto subreq_failed; =20 - atomic_inc(&rreq->nr_rd_ops); + atomic_inc(&rreq->nr_outstanding); =20 rreq->submitted +=3D subreq->len; =20 @@ -804,7 +804,7 @@ static bool netfs_rreq_submit_slice(struct netfs_read_r= equest *rreq, return false; } =20 -static void netfs_cache_expand_readahead(struct netfs_read_request *rreq, +static void netfs_cache_expand_readahead(struct netfs_io_request *rreq, loff_t *_start, size_t *_len, loff_t i_size) { struct netfs_cache_resources *cres =3D &rreq->cache_resources; @@ -813,7 +813,7 @@ static void netfs_cache_expand_readahead(struct netfs_r= ead_request *rreq, cres->ops->expand_readahead(cres, _start, _len, i_size); } =20 -static void netfs_rreq_expand(struct netfs_read_request *rreq, +static void netfs_rreq_expand(struct netfs_io_request *rreq, struct readahead_control *ractl) { /* Give the cache a chance to change the request parameters. The @@ -866,10 +866,10 @@ static void netfs_rreq_expand(struct netfs_read_reque= st *rreq, * This is usable whether or not caching is enabled. */ void netfs_readahead(struct readahead_control *ractl, - const struct netfs_read_request_ops *ops, + const struct netfs_request_ops *ops, void *netfs_priv) { - struct netfs_read_request *rreq; + struct netfs_io_request *rreq; unsigned int debug_index =3D 0; int ret; =20 @@ -897,7 +897,7 @@ void netfs_readahead(struct readahead_control *ractl, =20 netfs_rreq_expand(rreq, ractl); =20 - atomic_set(&rreq->nr_rd_ops, 1); + atomic_set(&rreq->nr_outstanding, 1); do { if (!netfs_rreq_submit_slice(rreq, &debug_index)) break; @@ -910,8 +910,8 @@ void netfs_readahead(struct readahead_control *ractl, while (readahead_folio(ractl)) ; =20 - /* If we decrement nr_rd_ops to 0, the ref belongs to us. */ - if (atomic_dec_and_test(&rreq->nr_rd_ops)) + /* If we decrement nr_outstanding to 0, the ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_outstanding)) netfs_rreq_assess(rreq, false); return; =20 @@ -944,10 +944,10 @@ EXPORT_SYMBOL(netfs_readahead); */ int netfs_readpage(struct file *file, struct folio *folio, - const struct netfs_read_request_ops *ops, + const struct netfs_request_ops *ops, void *netfs_priv) { - struct netfs_read_request *rreq; + struct netfs_io_request *rreq; unsigned int debug_index =3D 0; int ret; =20 @@ -977,19 +977,19 @@ int netfs_readpage(struct file *file, =20 netfs_get_read_request(rreq); =20 - atomic_set(&rreq->nr_rd_ops, 1); + atomic_set(&rreq->nr_outstanding, 1); do { if (!netfs_rreq_submit_slice(rreq, &debug_index)) break; =20 } while (rreq->submitted < rreq->len); =20 - /* Keep nr_rd_ops incremented so that the ref always belongs to us, and + /* Keep nr_outstanding incremented so that the ref always belongs to us, = and * the service code isn't punted off to a random thread pool to * process. */ do { - wait_var_event(&rreq->nr_rd_ops, atomic_read(&rreq->nr_rd_ops) =3D=3D 1); + wait_var_event(&rreq->nr_outstanding, atomic_read(&rreq->nr_outstanding)= =3D=3D 1); netfs_rreq_assess(rreq, false); } while (test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)); =20 @@ -1076,10 +1076,10 @@ static bool netfs_skip_folio_read(struct folio *fol= io, loff_t pos, size_t len) int netfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int aop_flags, struct folio **_folio, void **_fsdata, - const struct netfs_read_request_ops *ops, + const struct netfs_request_ops *ops, void *netfs_priv) { - struct netfs_read_request *rreq; + struct netfs_io_request *rreq; struct folio *folio; struct inode *inode =3D file_inode(file); unsigned int debug_index =3D 0, fgp_flags; @@ -1153,19 +1153,19 @@ int netfs_write_begin(struct file *file, struct add= ress_space *mapping, while (readahead_folio(&ractl)) ; =20 - atomic_set(&rreq->nr_rd_ops, 1); + atomic_set(&rreq->nr_outstanding, 1); do { if (!netfs_rreq_submit_slice(rreq, &debug_index)) break; =20 } while (rreq->submitted < rreq->len); =20 - /* Keep nr_rd_ops incremented so that the ref always belongs to us, and + /* Keep nr_outstanding incremented so that the ref always belongs to us, = and * the service code isn't punted off to a random thread pool to * process. */ for (;;) { - wait_var_event(&rreq->nr_rd_ops, atomic_read(&rreq->nr_rd_ops) =3D=3D 1); + wait_var_event(&rreq->nr_outstanding, atomic_read(&rreq->nr_outstanding)= =3D=3D 1); netfs_rreq_assess(rreq, false); if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) break; diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 614f22213e21..a2ca91cb7a68 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -106,7 +106,7 @@ static inline int wait_on_page_fscache_killable(struct = page *page) return folio_wait_private_2_killable(page_folio(page)); } =20 -enum netfs_read_source { +enum netfs_io_source { NETFS_FILL_WITH_ZEROES, NETFS_DOWNLOAD_FROM_SERVER, NETFS_READ_FROM_CACHE, @@ -130,8 +130,8 @@ struct netfs_cache_resources { /* * Descriptor for a single component subrequest. */ -struct netfs_read_subrequest { - struct netfs_read_request *rreq; /* Supervising read request */ +struct netfs_io_subrequest { + struct netfs_io_request *rreq; /* Supervising read request */ struct list_head rreq_link; /* Link in rreq->subrequests */ loff_t start; /* Where to start the I/O */ size_t len; /* Size of the I/O */ @@ -139,7 +139,7 @@ struct netfs_read_subrequest { refcount_t usage; short error; /* 0 or error that occurred */ unsigned short debug_index; /* Index in list (for debugging output) */ - enum netfs_read_source source; /* Where to read from */ + enum netfs_io_source source; /* Where to read from */ unsigned long flags; #define NETFS_SREQ_WRITE_TO_CACHE 0 /* Set if should write to cache */ #define NETFS_SREQ_CLEAR_TAIL 1 /* Set if the rest of the read should be = cleared */ @@ -152,7 +152,7 @@ struct netfs_read_subrequest { * Descriptor for a read helper request. This is used to make multiple I/O * requests on a variety of sources and then stitch the result together. */ -struct netfs_read_request { +struct netfs_io_request { struct work_struct work; struct inode *inode; /* The file being accessed */ struct address_space *mapping; /* The mapping being accessed */ @@ -160,8 +160,8 @@ struct netfs_read_request { struct list_head subrequests; /* Requests to fetch I/O from disk or net */ void *netfs_priv; /* Private data for the netfs */ unsigned int debug_id; - atomic_t nr_rd_ops; /* Number of read ops in progress */ - atomic_t nr_wr_ops; /* Number of write ops in progress */ + atomic_t nr_outstanding; /* Number of read ops in progress */ + atomic_t nr_copy_ops; /* Number of write ops in progress */ size_t submitted; /* Amount submitted for I/O so far */ size_t len; /* Length of the request */ short error; /* 0 or error that occurred */ @@ -176,23 +176,23 @@ struct netfs_read_request { #define NETFS_RREQ_DONT_UNLOCK_FOLIOS 3 /* Don't unlock the folios on comp= letion */ #define NETFS_RREQ_FAILED 4 /* The request failed */ #define NETFS_RREQ_IN_PROGRESS 5 /* Unlocked when the request completes */ - const struct netfs_read_request_ops *netfs_ops; + const struct netfs_request_ops *netfs_ops; }; =20 /* * Operations the network filesystem can/must provide to the helpers. */ -struct netfs_read_request_ops { +struct netfs_request_ops { bool (*is_cache_enabled)(struct inode *inode); - void (*init_rreq)(struct netfs_read_request *rreq, struct file *file); - int (*begin_cache_operation)(struct netfs_read_request *rreq); - void (*expand_readahead)(struct netfs_read_request *rreq); - bool (*clamp_length)(struct netfs_read_subrequest *subreq); - void (*issue_op)(struct netfs_read_subrequest *subreq); - bool (*is_still_valid)(struct netfs_read_request *rreq); + void (*init_request)(struct netfs_io_request *rreq, struct file *file); + int (*begin_cache_operation)(struct netfs_io_request *rreq); + void (*expand_readahead)(struct netfs_io_request *rreq); + bool (*clamp_length)(struct netfs_io_subrequest *subreq); + void (*issue_op)(struct netfs_io_subrequest *subreq); + bool (*is_still_valid)(struct netfs_io_request *rreq); int (*check_write_begin)(struct file *file, loff_t pos, unsigned len, struct folio *folio, void **_fsdata); - void (*done)(struct netfs_read_request *rreq); + void (*done)(struct netfs_io_request *rreq); void (*cleanup)(struct address_space *mapping, void *netfs_priv); }; =20 @@ -235,7 +235,7 @@ struct netfs_cache_ops { /* Prepare a read operation, shortening it to a cached/uncached * boundary as appropriate. */ - enum netfs_read_source (*prepare_read)(struct netfs_read_subrequest *subr= eq, + enum netfs_io_source (*prepare_read)(struct netfs_io_subrequest *subreq, loff_t i_size); =20 /* Prepare a write operation, working out what part of the write we can @@ -255,19 +255,19 @@ struct netfs_cache_ops { =20 struct readahead_control; extern void netfs_readahead(struct readahead_control *, - const struct netfs_read_request_ops *, + const struct netfs_request_ops *, void *); extern int netfs_readpage(struct file *, struct folio *, - const struct netfs_read_request_ops *, + const struct netfs_request_ops *, void *); extern int netfs_write_begin(struct file *, struct address_space *, loff_t, unsigned int, unsigned int, struct folio **, void **, - const struct netfs_read_request_ops *, + const struct netfs_request_ops *, void *); =20 -extern void netfs_subreq_terminated(struct netfs_read_subrequest *, ssize_= t, bool); +extern void netfs_subreq_terminated(struct netfs_io_subrequest *, ssize_t,= bool); extern void netfs_stats_show(struct seq_file *); =20 #endif /* _LINUX_NETFS_H */ diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cache= files.h index c6f5aa74db89..002d0ae4f9bc 100644 --- a/include/trace/events/cachefiles.h +++ b/include/trace/events/cachefiles.h @@ -424,8 +424,8 @@ TRACE_EVENT(cachefiles_vol_coherency, ); =20 TRACE_EVENT(cachefiles_prep_read, - TP_PROTO(struct netfs_read_subrequest *sreq, - enum netfs_read_source source, + TP_PROTO(struct netfs_io_subrequest *sreq, + enum netfs_io_source source, enum cachefiles_prepare_read_trace why, ino_t cache_inode), =20 @@ -435,7 +435,7 @@ TRACE_EVENT(cachefiles_prep_read, __field(unsigned int, rreq ) __field(unsigned short, index ) __field(unsigned short, flags ) - __field(enum netfs_read_source, source ) + __field(enum netfs_io_source, source ) __field(enum cachefiles_prepare_read_trace, why ) __field(size_t, len ) __field(loff_t, start ) diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 4d0bf02d490a..b40809c0bd74 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -94,7 +94,7 @@ netfs_failures; #define E_(a, b) { a, b } =20 TRACE_EVENT(netfs_read, - TP_PROTO(struct netfs_read_request *rreq, + TP_PROTO(struct netfs_io_request *rreq, loff_t start, size_t len, enum netfs_read_trace what), =20 @@ -127,7 +127,7 @@ TRACE_EVENT(netfs_read, ); =20 TRACE_EVENT(netfs_rreq, - TP_PROTO(struct netfs_read_request *rreq, + TP_PROTO(struct netfs_io_request *rreq, enum netfs_rreq_trace what), =20 TP_ARGS(rreq, what), @@ -151,7 +151,7 @@ TRACE_EVENT(netfs_rreq, ); =20 TRACE_EVENT(netfs_sreq, - TP_PROTO(struct netfs_read_subrequest *sreq, + TP_PROTO(struct netfs_io_subrequest *sreq, enum netfs_sreq_trace what), =20 TP_ARGS(sreq, what), @@ -161,7 +161,7 @@ TRACE_EVENT(netfs_sreq, __field(unsigned short, index ) __field(short, error ) __field(unsigned short, flags ) - __field(enum netfs_read_source, source ) + __field(enum netfs_io_source, source ) __field(enum netfs_sreq_trace, what ) __field(size_t, len ) __field(size_t, transferred ) @@ -190,8 +190,8 @@ TRACE_EVENT(netfs_sreq, ); =20 TRACE_EVENT(netfs_failure, - TP_PROTO(struct netfs_read_request *rreq, - struct netfs_read_subrequest *sreq, + TP_PROTO(struct netfs_io_request *rreq, + struct netfs_io_subrequest *sreq, int error, enum netfs_failure what), =20 TP_ARGS(rreq, sreq, error, what), @@ -201,7 +201,7 @@ TRACE_EVENT(netfs_failure, __field(unsigned short, index ) __field(short, error ) __field(unsigned short, flags ) - __field(enum netfs_read_source, source ) + __field(enum netfs_io_source, source ) __field(enum netfs_failure, what ) __field(size_t, len ) __field(size_t, transferred ) From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D2CFCC433EF for ; Thu, 10 Mar 2022 16:16:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241678AbiCJQRI (ORCPT ); Thu, 10 Mar 2022 11:17:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35990 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241473AbiCJQRB (ORCPT ); Thu, 10 Mar 2022 11:17:01 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 171E1192C94 for ; Thu, 10 Mar 2022 08:15:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646928947; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/Jeg55nGpocEqBCPEYW6HB05EqO8SCxNjvmmy3uzn3Y=; b=csy0GyepU0dzHrpd0x9SYndxz0wgAASuDOfglGMnvPdPgVAiZIZLb7M7DaJCOD/YMsdGSv oLZh13LQxoEolVqIU5+K54x9ZSazxG833EMcqKSpSbRnWpYGs8ys19Km047R8Ats1LSo3Q aDhJDhcSA9V4q3lY3zL1pIEe10fIygA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-647-TJ_EGa4lO_-0A5fI8ibVdw-1; Thu, 10 Mar 2022 11:15:43 -0500 X-MC-Unique: TJ_EGa4lO_-0A5fI8ibVdw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id AD5F451DF; Thu, 10 Mar 2022 16:15:41 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6EA017AC6B; Thu, 10 Mar 2022 16:15:26 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 04/20] netfs: Finish off rename of netfs_read_request to netfs_io_request From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:15:25 +0000 Message-ID: <164692892567.2099075.13895804222087028813.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Adjust helper function names and comments after mass rename of struct netfs_read_*request to struct netfs_io_*request. Changes =3D=3D=3D=3D=3D=3D=3D ver #2) - Make the changes in the docs also. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164622992433.3564931.6684311087845150271.st= git@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678196111.1200972.5001114956865989528.st= git@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- Documentation/filesystems/netfs_library.rst | 4 + fs/9p/vfs_addr.c | 6 +- fs/afs/file.c | 4 + fs/cachefiles/io.c | 4 + fs/ceph/addr.c | 6 +- fs/netfs/read_helper.c | 83 ++++++++++++++---------= ---- include/linux/netfs.h | 22 ++++--- 7 files changed, 65 insertions(+), 64 deletions(-) diff --git a/Documentation/filesystems/netfs_library.rst b/Documentation/fi= lesystems/netfs_library.rst index a997e2d4321d..4eb7e7b7b0fc 100644 --- a/Documentation/filesystems/netfs_library.rst +++ b/Documentation/filesystems/netfs_library.rst @@ -250,7 +250,7 @@ through which it can issue requests and negotiate:: int (*begin_cache_operation)(struct netfs_io_request *rreq); void (*expand_readahead)(struct netfs_io_request *rreq); bool (*clamp_length)(struct netfs_io_subrequest *subreq); - void (*issue_op)(struct netfs_io_subrequest *subreq); + void (*issue_read)(struct netfs_io_subrequest *subreq); bool (*is_still_valid)(struct netfs_io_request *rreq); int (*check_write_begin)(struct file *file, loff_t pos, unsigned len, struct folio *folio, void **_fsdata); @@ -305,7 +305,7 @@ The operations are as follows: =20 This should return 0 on success and an error code on error. =20 - * ``issue_op()`` + * ``issue_read()`` =20 [Required] The helpers use this to dispatch a subrequest to the server = for reading. In the subrequest, ->start, ->len and ->transferred indicate = what diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 7b79fabe7593..fdc1033a1546 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -28,10 +28,10 @@ #include "fid.h" =20 /** - * v9fs_req_issue_op - Issue a read from 9P + * v9fs_issue_read - Issue a read from 9P * @subreq: The read to make */ -static void v9fs_req_issue_op(struct netfs_io_subrequest *subreq) +static void v9fs_issue_read(struct netfs_io_subrequest *subreq) { struct netfs_io_request *rreq =3D subreq->rreq; struct p9_fid *fid =3D rreq->netfs_priv; @@ -106,7 +106,7 @@ static const struct netfs_request_ops v9fs_req_ops =3D { .init_request =3D v9fs_init_request, .is_cache_enabled =3D v9fs_is_cache_enabled, .begin_cache_operation =3D v9fs_begin_cache_operation, - .issue_op =3D v9fs_req_issue_op, + .issue_read =3D v9fs_issue_read, .cleanup =3D v9fs_req_cleanup, }; =20 diff --git a/fs/afs/file.c b/fs/afs/file.c index e55761f8858c..b19d635eed12 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -310,7 +310,7 @@ int afs_fetch_data(struct afs_vnode *vnode, struct afs_= read *req) return afs_do_sync_operation(op); } =20 -static void afs_req_issue_op(struct netfs_io_subrequest *subreq) +static void afs_issue_read(struct netfs_io_subrequest *subreq) { struct afs_vnode *vnode =3D AFS_FS_I(subreq->rreq->inode); struct afs_read *fsreq; @@ -401,7 +401,7 @@ const struct netfs_request_ops afs_req_ops =3D { .is_cache_enabled =3D afs_is_cache_enabled, .begin_cache_operation =3D afs_begin_cache_operation, .check_write_begin =3D afs_check_write_begin, - .issue_op =3D afs_req_issue_op, + .issue_read =3D afs_issue_read, .cleanup =3D afs_priv_cleanup, }; =20 diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c index 6ac6fdbc70d3..b19f496db9ad 100644 --- a/fs/cachefiles/io.c +++ b/fs/cachefiles/io.c @@ -406,7 +406,7 @@ static enum netfs_io_source cachefiles_prepare_read(str= uct netfs_io_subrequest * } =20 if (test_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags)) { - __set_bit(NETFS_SREQ_WRITE_TO_CACHE, &subreq->flags); + __set_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); why =3D cachefiles_trace_read_no_data; goto out_no_object; } @@ -475,7 +475,7 @@ static enum netfs_io_source cachefiles_prepare_read(str= uct netfs_io_subrequest * goto out; =20 download_and_store: - __set_bit(NETFS_SREQ_WRITE_TO_CACHE, &subreq->flags); + __set_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); out: cachefiles_end_secure(cache, saved_cred); out_no_object: diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 9d995f351079..9189257476f8 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -259,7 +259,7 @@ static bool ceph_netfs_issue_op_inline(struct netfs_io_= subrequest *subreq) size_t len; =20 __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); - __clear_bit(NETFS_SREQ_WRITE_TO_CACHE, &subreq->flags); + __clear_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); =20 if (subreq->start >=3D inode->i_size) goto out; @@ -298,7 +298,7 @@ static bool ceph_netfs_issue_op_inline(struct netfs_io_= subrequest *subreq) return true; } =20 -static void ceph_netfs_issue_op(struct netfs_io_subrequest *subreq) +static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq) { struct netfs_io_request *rreq =3D subreq->rreq; struct inode *inode =3D rreq->inode; @@ -367,7 +367,7 @@ static void ceph_readahead_cleanup(struct address_space= *mapping, void *priv) static const struct netfs_request_ops ceph_netfs_read_ops =3D { .is_cache_enabled =3D ceph_is_cache_enabled, .begin_cache_operation =3D ceph_begin_cache_operation, - .issue_op =3D ceph_netfs_issue_op, + .issue_read =3D ceph_netfs_issue_read, .expand_readahead =3D ceph_netfs_expand_readahead, .clamp_length =3D ceph_netfs_clamp_length, .check_write_begin =3D ceph_netfs_check_write_begin, diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index 50035d93f1dc..26d54055b17e 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -37,7 +37,7 @@ static void netfs_put_subrequest(struct netfs_io_subreque= st *subreq, __netfs_put_subrequest(subreq, was_async); } =20 -static struct netfs_io_request *netfs_alloc_read_request( +static struct netfs_io_request *netfs_alloc_request( const struct netfs_request_ops *ops, void *netfs_priv, struct file *file) { @@ -63,13 +63,12 @@ static struct netfs_io_request *netfs_alloc_read_reques= t( return rreq; } =20 -static void netfs_get_read_request(struct netfs_io_request *rreq) +static void netfs_get_request(struct netfs_io_request *rreq) { refcount_inc(&rreq->usage); } =20 -static void netfs_rreq_clear_subreqs(struct netfs_io_request *rreq, - bool was_async) +static void netfs_clear_subrequests(struct netfs_io_request *rreq, bool wa= s_async) { struct netfs_io_subrequest *subreq; =20 @@ -81,11 +80,11 @@ static void netfs_rreq_clear_subreqs(struct netfs_io_re= quest *rreq, } } =20 -static void netfs_free_read_request(struct work_struct *work) +static void netfs_free_request(struct work_struct *work) { struct netfs_io_request *rreq =3D container_of(work, struct netfs_io_request, work); - netfs_rreq_clear_subreqs(rreq, false); + netfs_clear_subrequests(rreq, false); if (rreq->netfs_priv) rreq->netfs_ops->cleanup(rreq->mapping, rreq->netfs_priv); trace_netfs_rreq(rreq, netfs_rreq_trace_free); @@ -95,15 +94,15 @@ static void netfs_free_read_request(struct work_struct = *work) netfs_stat_d(&netfs_n_rh_rreq); } =20 -static void netfs_put_read_request(struct netfs_io_request *rreq, bool was= _async) +static void netfs_put_request(struct netfs_io_request *rreq, bool was_asyn= c) { if (refcount_dec_and_test(&rreq->usage)) { if (was_async) { - rreq->work.func =3D netfs_free_read_request; + rreq->work.func =3D netfs_free_request; if (!queue_work(system_unbound_wq, &rreq->work)) BUG(); } else { - netfs_free_read_request(&rreq->work); + netfs_free_request(&rreq->work); } } } @@ -121,14 +120,14 @@ static struct netfs_io_subrequest *netfs_alloc_subreq= uest( INIT_LIST_HEAD(&subreq->rreq_link); refcount_set(&subreq->usage, 2); subreq->rreq =3D rreq; - netfs_get_read_request(rreq); + netfs_get_request(rreq); netfs_stat(&netfs_n_rh_sreq); } =20 return subreq; } =20 -static void netfs_get_read_subrequest(struct netfs_io_subrequest *subreq) +static void netfs_get_subrequest(struct netfs_io_subrequest *subreq) { refcount_inc(&subreq->usage); } @@ -141,7 +140,7 @@ static void __netfs_put_subrequest(struct netfs_io_subr= equest *subreq, trace_netfs_sreq(subreq, netfs_sreq_trace_free); kfree(subreq); netfs_stat_d(&netfs_n_rh_sreq); - netfs_put_read_request(rreq, was_async); + netfs_put_request(rreq, was_async); } =20 /* @@ -216,7 +215,7 @@ static void netfs_read_from_server(struct netfs_io_requ= est *rreq, struct netfs_io_subrequest *subreq) { netfs_stat(&netfs_n_rh_download); - rreq->netfs_ops->issue_op(subreq); + rreq->netfs_ops->issue_read(subreq); } =20 /* @@ -225,8 +224,8 @@ static void netfs_read_from_server(struct netfs_io_requ= est *rreq, static void netfs_rreq_completed(struct netfs_io_request *rreq, bool was_a= sync) { trace_netfs_rreq(rreq, netfs_rreq_trace_done); - netfs_rreq_clear_subreqs(rreq, was_async); - netfs_put_read_request(rreq, was_async); + netfs_clear_subrequests(rreq, was_async); + netfs_put_request(rreq, was_async); } =20 /* @@ -306,7 +305,7 @@ static void netfs_rreq_do_write_to_cache(struct netfs_i= o_request *rreq) atomic_inc(&rreq->nr_copy_ops); =20 list_for_each_entry_safe(subreq, p, &rreq->subrequests, rreq_link) { - if (!test_bit(NETFS_SREQ_WRITE_TO_CACHE, &subreq->flags)) { + if (!test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) { list_del_init(&subreq->rreq_link); netfs_put_subrequest(subreq, false); } @@ -336,7 +335,7 @@ static void netfs_rreq_do_write_to_cache(struct netfs_i= o_request *rreq) =20 atomic_inc(&rreq->nr_copy_ops); netfs_stat(&netfs_n_rh_write); - netfs_get_read_subrequest(subreq); + netfs_get_subrequest(subreq); trace_netfs_sreq(subreq, netfs_sreq_trace_write); cres->ops->write(cres, subreq->start, &iter, netfs_rreq_copy_terminated, subreq); @@ -378,9 +377,9 @@ static void netfs_rreq_unlock(struct netfs_io_request *= rreq) XA_STATE(xas, &rreq->mapping->i_pages, start_page); =20 if (test_bit(NETFS_RREQ_FAILED, &rreq->flags)) { - __clear_bit(NETFS_RREQ_WRITE_TO_CACHE, &rreq->flags); + __clear_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags); list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { - __clear_bit(NETFS_SREQ_WRITE_TO_CACHE, &subreq->flags); + __clear_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); } } =20 @@ -408,7 +407,7 @@ static void netfs_rreq_unlock(struct netfs_io_request *= rreq) pg_failed =3D true; break; } - if (test_bit(NETFS_SREQ_WRITE_TO_CACHE, &subreq->flags)) + if (test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) folio_start_fscache(folio); pg_failed |=3D subreq_failed; if (pgend < iopos + subreq->len) @@ -453,13 +452,13 @@ static void netfs_rreq_unlock(struct netfs_io_request= *rreq) static void netfs_rreq_short_read(struct netfs_io_request *rreq, struct netfs_io_subrequest *subreq) { - __clear_bit(NETFS_SREQ_SHORT_READ, &subreq->flags); + __clear_bit(NETFS_SREQ_SHORT_IO, &subreq->flags); __set_bit(NETFS_SREQ_SEEK_DATA_READ, &subreq->flags); =20 netfs_stat(&netfs_n_rh_short_read); trace_netfs_sreq(subreq, netfs_sreq_trace_resubmit_short); =20 - netfs_get_read_subrequest(subreq); + netfs_get_subrequest(subreq); atomic_inc(&rreq->nr_outstanding); if (subreq->source =3D=3D NETFS_READ_FROM_CACHE) netfs_read_from_cache(rreq, subreq, NETFS_READ_HOLE_CLEAR); @@ -493,10 +492,10 @@ static bool netfs_rreq_perform_resubmissions(struct n= etfs_io_request *rreq) subreq->error =3D 0; netfs_stat(&netfs_n_rh_download_instead); trace_netfs_sreq(subreq, netfs_sreq_trace_download_instead); - netfs_get_read_subrequest(subreq); + netfs_get_subrequest(subreq); atomic_inc(&rreq->nr_outstanding); netfs_read_from_server(rreq, subreq); - } else if (test_bit(NETFS_SREQ_SHORT_READ, &subreq->flags)) { + } else if (test_bit(NETFS_SREQ_SHORT_IO, &subreq->flags)) { netfs_rreq_short_read(rreq, subreq); } } @@ -553,7 +552,7 @@ static void netfs_rreq_assess(struct netfs_io_request *= rreq, bool was_async) clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &rreq->flags); wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS); =20 - if (test_bit(NETFS_RREQ_WRITE_TO_CACHE, &rreq->flags)) + if (test_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags)) return netfs_rreq_write_to_cache(rreq); =20 netfs_rreq_completed(rreq, was_async); @@ -642,8 +641,8 @@ void netfs_subreq_terminated(struct netfs_io_subrequest= *subreq, =20 complete: __clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags); - if (test_bit(NETFS_SREQ_WRITE_TO_CACHE, &subreq->flags)) - set_bit(NETFS_RREQ_WRITE_TO_CACHE, &rreq->flags); + if (test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) + set_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags); =20 out: trace_netfs_sreq(subreq, netfs_sreq_trace_terminated); @@ -674,7 +673,7 @@ void netfs_subreq_terminated(struct netfs_io_subrequest= *subreq, __clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags); } =20 - __set_bit(NETFS_SREQ_SHORT_READ, &subreq->flags); + __set_bit(NETFS_SREQ_SHORT_IO, &subreq->flags); set_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags); goto out; =20 @@ -878,7 +877,7 @@ void netfs_readahead(struct readahead_control *ractl, if (readahead_count(ractl) =3D=3D 0) goto cleanup; =20 - rreq =3D netfs_alloc_read_request(ops, netfs_priv, ractl->file); + rreq =3D netfs_alloc_request(ops, netfs_priv, ractl->file); if (!rreq) goto cleanup; rreq->mapping =3D ractl->mapping; @@ -916,7 +915,7 @@ void netfs_readahead(struct readahead_control *ractl, return; =20 cleanup_free: - netfs_put_read_request(rreq, false); + netfs_put_request(rreq, false); return; cleanup: if (netfs_priv) @@ -953,7 +952,7 @@ int netfs_readpage(struct file *file, =20 _enter("%lx", folio_index(folio)); =20 - rreq =3D netfs_alloc_read_request(ops, netfs_priv, file); + rreq =3D netfs_alloc_request(ops, netfs_priv, file); if (!rreq) { if (netfs_priv) ops->cleanup(folio_file_mapping(folio), netfs_priv); @@ -975,7 +974,7 @@ int netfs_readpage(struct file *file, netfs_stat(&netfs_n_rh_readpage); trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage); =20 - netfs_get_read_request(rreq); + netfs_get_request(rreq); =20 atomic_set(&rreq->nr_outstanding, 1); do { @@ -989,7 +988,8 @@ int netfs_readpage(struct file *file, * process. */ do { - wait_var_event(&rreq->nr_outstanding, atomic_read(&rreq->nr_outstanding)= =3D=3D 1); + wait_var_event(&rreq->nr_outstanding, + atomic_read(&rreq->nr_outstanding) =3D=3D 1); netfs_rreq_assess(rreq, false); } while (test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)); =20 @@ -999,7 +999,7 @@ int netfs_readpage(struct file *file, ret =3D -EIO; } out: - netfs_put_read_request(rreq, false); + netfs_put_request(rreq, false); return ret; } EXPORT_SYMBOL(netfs_readpage); @@ -1122,7 +1122,7 @@ int netfs_write_begin(struct file *file, struct addre= ss_space *mapping, } =20 ret =3D -ENOMEM; - rreq =3D netfs_alloc_read_request(ops, netfs_priv, file); + rreq =3D netfs_alloc_request(ops, netfs_priv, file); if (!rreq) goto error; rreq->mapping =3D folio_file_mapping(folio); @@ -1146,7 +1146,7 @@ int netfs_write_begin(struct file *file, struct addre= ss_space *mapping, */ ractl._nr_pages =3D folio_nr_pages(folio); netfs_rreq_expand(rreq, &ractl); - netfs_get_read_request(rreq); + netfs_get_request(rreq); =20 /* We hold the folio locks, so we can drop the references */ folio_get(folio); @@ -1160,12 +1160,13 @@ int netfs_write_begin(struct file *file, struct add= ress_space *mapping, =20 } while (rreq->submitted < rreq->len); =20 - /* Keep nr_outstanding incremented so that the ref always belongs to us, = and - * the service code isn't punted off to a random thread pool to + /* Keep nr_outstanding incremented so that the ref always belongs to + * us, and the service code isn't punted off to a random thread pool to * process. */ for (;;) { - wait_var_event(&rreq->nr_outstanding, atomic_read(&rreq->nr_outstanding)= =3D=3D 1); + wait_var_event(&rreq->nr_outstanding, + atomic_read(&rreq->nr_outstanding) =3D=3D 1); netfs_rreq_assess(rreq, false); if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) break; @@ -1177,7 +1178,7 @@ int netfs_write_begin(struct file *file, struct addre= ss_space *mapping, trace_netfs_failure(rreq, NULL, ret, netfs_fail_short_write_begin); ret =3D -EIO; } - netfs_put_read_request(rreq, false); + netfs_put_request(rreq, false); if (ret < 0) goto error; =20 @@ -1193,7 +1194,7 @@ int netfs_write_begin(struct file *file, struct addre= ss_space *mapping, return 0; =20 error_put: - netfs_put_read_request(rreq, false); + netfs_put_request(rreq, false); error: folio_unlock(folio); folio_put(folio); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index a2ca91cb7a68..f63de27d6f29 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -131,7 +131,7 @@ struct netfs_cache_resources { * Descriptor for a single component subrequest. */ struct netfs_io_subrequest { - struct netfs_io_request *rreq; /* Supervising read request */ + struct netfs_io_request *rreq; /* Supervising I/O request */ struct list_head rreq_link; /* Link in rreq->subrequests */ loff_t start; /* Where to start the I/O */ size_t len; /* Size of the I/O */ @@ -139,29 +139,29 @@ struct netfs_io_subrequest { refcount_t usage; short error; /* 0 or error that occurred */ unsigned short debug_index; /* Index in list (for debugging output) */ - enum netfs_io_source source; /* Where to read from */ + enum netfs_io_source source; /* Where to read from/write to */ unsigned long flags; -#define NETFS_SREQ_WRITE_TO_CACHE 0 /* Set if should write to cache */ +#define NETFS_SREQ_COPY_TO_CACHE 0 /* Set if should copy the data to the c= ache */ #define NETFS_SREQ_CLEAR_TAIL 1 /* Set if the rest of the read should be = cleared */ -#define NETFS_SREQ_SHORT_READ 2 /* Set if there was a short read from the= cache */ +#define NETFS_SREQ_SHORT_IO 2 /* Set if the I/O was short */ #define NETFS_SREQ_SEEK_DATA_READ 3 /* Set if ->read() should SEEK_DATA fi= rst */ #define NETFS_SREQ_NO_PROGRESS 4 /* Set if we didn't manage to read any d= ata */ }; =20 /* - * Descriptor for a read helper request. This is used to make multiple I/O - * requests on a variety of sources and then stitch the result together. + * Descriptor for an I/O helper request. This is used to make multiple I/O + * operations to a variety of data stores and then stitch the result toget= her. */ struct netfs_io_request { struct work_struct work; struct inode *inode; /* The file being accessed */ struct address_space *mapping; /* The mapping being accessed */ struct netfs_cache_resources cache_resources; - struct list_head subrequests; /* Requests to fetch I/O from disk or net */ + struct list_head subrequests; /* Contributory I/O operations */ void *netfs_priv; /* Private data for the netfs */ unsigned int debug_id; - atomic_t nr_outstanding; /* Number of read ops in progress */ - atomic_t nr_copy_ops; /* Number of write ops in progress */ + atomic_t nr_outstanding; /* Number of ops in progress */ + atomic_t nr_copy_ops; /* Number of copy-to-cache ops in progress */ size_t submitted; /* Amount submitted for I/O so far */ size_t len; /* Length of the request */ short error; /* 0 or error that occurred */ @@ -171,7 +171,7 @@ struct netfs_io_request { refcount_t usage; unsigned long flags; #define NETFS_RREQ_INCOMPLETE_IO 0 /* Some ioreqs terminated short or with= error */ -#define NETFS_RREQ_WRITE_TO_CACHE 1 /* Need to write to the cache */ +#define NETFS_RREQ_COPY_TO_CACHE 1 /* Need to write to the cache */ #define NETFS_RREQ_NO_UNLOCK_FOLIO 2 /* Don't unlock no_unlock_folio on co= mpletion */ #define NETFS_RREQ_DONT_UNLOCK_FOLIOS 3 /* Don't unlock the folios on comp= letion */ #define NETFS_RREQ_FAILED 4 /* The request failed */ @@ -188,7 +188,7 @@ struct netfs_request_ops { int (*begin_cache_operation)(struct netfs_io_request *rreq); void (*expand_readahead)(struct netfs_io_request *rreq); bool (*clamp_length)(struct netfs_io_subrequest *subreq); - void (*issue_op)(struct netfs_io_subrequest *subreq); + void (*issue_read)(struct netfs_io_subrequest *subreq); bool (*is_still_valid)(struct netfs_io_request *rreq); int (*check_write_begin)(struct file *file, loff_t pos, unsigned len, struct folio *folio, void **_fsdata); From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 756D9C4332F for ; Thu, 10 Mar 2022 16:16:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241617AbiCJQRp (ORCPT ); Thu, 10 Mar 2022 11:17:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37118 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233486AbiCJQRk (ORCPT ); Thu, 10 Mar 2022 11:17:40 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id AD420190C15 for ; Thu, 10 Mar 2022 08:16:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646928986; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=nLnoMDsXAZhvceWKXXrKOjeeVt8EWF9LQHtKfhIe5YE=; b=diRZFWm/PV8IIpsHUcjRr8LKLTnasNh0ZEYUZ3ETQYEIJ2wYy05E633UskVuTJ/kA2JA9Z TUHNrvPyfgxl7euqgigRbWMlmnzfjPQ0/rxSnbcGuuUTkqRF3Khqnyaq6EbwaPxt8owCKq G9lLTccYvhk0urhZ0HuaCXIbvdj06WM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-593-k09c7HqCMmKzHwBJDIG-XA-1; Thu, 10 Mar 2022 11:16:23 -0500 X-MC-Unique: k09c7HqCMmKzHwBJDIG-XA-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 97F4951DC; Thu, 10 Mar 2022 16:16:21 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 21B7126E51; Thu, 10 Mar 2022 16:15:47 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 05/20] netfs: Split netfs_io_* object handling out From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:15:46 +0000 Message-ID: <164692894693.2099075.7831091294248735173.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Split netfs_io_* object handling out into a file that's going to contain object allocation, get and put routines. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164622995118.3564931.6089530629052064470.st= git@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678197044.1200972.11511937252083343775.s= tgit@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/netfs/Makefile | 6 ++ fs/netfs/internal.h | 18 +++++++ fs/netfs/objects.c | 123 ++++++++++++++++++++++++++++++++++++++++++++= ++++ fs/netfs/read_helper.c | 118 --------------------------------------------= -- 4 files changed, 147 insertions(+), 118 deletions(-) create mode 100644 fs/netfs/objects.c diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index c15bfc966d96..939fd00a1fc9 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -1,5 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 =20 -netfs-y :=3D read_helper.o stats.o +netfs-y :=3D \ + objects.o \ + read_helper.o + +netfs-$(CONFIG_NETFS_STATS) +=3D stats.o =20 obj-$(CONFIG_NETFS_SUPPORT) :=3D netfs.o diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index b7f2c4459f33..cf7a3ddb16a4 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -5,17 +5,35 @@ * Written by David Howells (dhowells@redhat.com) */ =20 +#include +#include + #ifdef pr_fmt #undef pr_fmt #endif =20 #define pr_fmt(fmt) "netfs: " fmt =20 +/* + * objects.c + */ +struct netfs_io_request *netfs_alloc_request(const struct netfs_request_op= s *ops, + void *netfs_priv, + struct file *file); +void netfs_get_request(struct netfs_io_request *rreq); +void netfs_clear_subrequests(struct netfs_io_request *rreq, bool was_async= ); +void netfs_put_request(struct netfs_io_request *rreq, bool was_async); +struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request= *rreq); +void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_asy= nc); +void netfs_get_subrequest(struct netfs_io_subrequest *subreq); + /* * read_helper.c */ extern unsigned int netfs_debug; =20 +void netfs_rreq_work(struct work_struct *work); + /* * stats.c */ diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c new file mode 100644 index 000000000000..f7383c28dc6e --- /dev/null +++ b/fs/netfs/objects.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Object lifetime handling and tracing. + * + * Copyright (C) 2022 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include +#include "internal.h" + +/* + * Allocate an I/O request and initialise it. + */ +struct netfs_io_request *netfs_alloc_request( + const struct netfs_request_ops *ops, void *netfs_priv, + struct file *file) +{ + static atomic_t debug_ids; + struct netfs_io_request *rreq; + + rreq =3D kzalloc(sizeof(struct netfs_io_request), GFP_KERNEL); + if (rreq) { + rreq->netfs_ops =3D ops; + rreq->netfs_priv =3D netfs_priv; + rreq->inode =3D file_inode(file); + rreq->i_size =3D i_size_read(rreq->inode); + rreq->debug_id =3D atomic_inc_return(&debug_ids); + INIT_LIST_HEAD(&rreq->subrequests); + INIT_WORK(&rreq->work, netfs_rreq_work); + refcount_set(&rreq->usage, 1); + __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); + if (ops->init_request) + ops->init_request(rreq, file); + netfs_stat(&netfs_n_rh_rreq); + } + + return rreq; +} + +void netfs_get_request(struct netfs_io_request *rreq) +{ + refcount_inc(&rreq->usage); +} + +void netfs_clear_subrequests(struct netfs_io_request *rreq, bool was_async) +{ + struct netfs_io_subrequest *subreq; + + while (!list_empty(&rreq->subrequests)) { + subreq =3D list_first_entry(&rreq->subrequests, + struct netfs_io_subrequest, rreq_link); + list_del(&subreq->rreq_link); + netfs_put_subrequest(subreq, was_async); + } +} + +static void netfs_free_request(struct work_struct *work) +{ + struct netfs_io_request *rreq =3D + container_of(work, struct netfs_io_request, work); + netfs_clear_subrequests(rreq, false); + if (rreq->netfs_priv) + rreq->netfs_ops->cleanup(rreq->mapping, rreq->netfs_priv); + trace_netfs_rreq(rreq, netfs_rreq_trace_free); + if (rreq->cache_resources.ops) + rreq->cache_resources.ops->end_operation(&rreq->cache_resources); + kfree(rreq); + netfs_stat_d(&netfs_n_rh_rreq); +} + +void netfs_put_request(struct netfs_io_request *rreq, bool was_async) +{ + if (refcount_dec_and_test(&rreq->usage)) { + if (was_async) { + rreq->work.func =3D netfs_free_request; + if (!queue_work(system_unbound_wq, &rreq->work)) + BUG(); + } else { + netfs_free_request(&rreq->work); + } + } +} + +/* + * Allocate and partially initialise an I/O request structure. + */ +struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request= *rreq) +{ + struct netfs_io_subrequest *subreq; + + subreq =3D kzalloc(sizeof(struct netfs_io_subrequest), GFP_KERNEL); + if (subreq) { + INIT_LIST_HEAD(&subreq->rreq_link); + refcount_set(&subreq->usage, 2); + subreq->rreq =3D rreq; + netfs_get_request(rreq); + netfs_stat(&netfs_n_rh_sreq); + } + + return subreq; +} + +void netfs_get_subrequest(struct netfs_io_subrequest *subreq) +{ + refcount_inc(&subreq->usage); +} + +static void __netfs_put_subrequest(struct netfs_io_subrequest *subreq, + bool was_async) +{ + struct netfs_io_request *rreq =3D subreq->rreq; + + trace_netfs_sreq(subreq, netfs_sreq_trace_free); + kfree(subreq); + netfs_stat_d(&netfs_n_rh_sreq); + netfs_put_request(rreq, was_async); +} + +void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_asy= nc) +{ + if (refcount_dec_and_test(&subreq->usage)) + __netfs_put_subrequest(subreq, was_async); +} diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index 26d54055b17e..ef23ef9889d5 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -27,122 +27,6 @@ unsigned netfs_debug; module_param_named(debug, netfs_debug, uint, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask"); =20 -static void netfs_rreq_work(struct work_struct *); -static void __netfs_put_subrequest(struct netfs_io_subrequest *, bool); - -static void netfs_put_subrequest(struct netfs_io_subrequest *subreq, - bool was_async) -{ - if (refcount_dec_and_test(&subreq->usage)) - __netfs_put_subrequest(subreq, was_async); -} - -static struct netfs_io_request *netfs_alloc_request( - const struct netfs_request_ops *ops, void *netfs_priv, - struct file *file) -{ - static atomic_t debug_ids; - struct netfs_io_request *rreq; - - rreq =3D kzalloc(sizeof(struct netfs_io_request), GFP_KERNEL); - if (rreq) { - rreq->netfs_ops =3D ops; - rreq->netfs_priv =3D netfs_priv; - rreq->inode =3D file_inode(file); - rreq->i_size =3D i_size_read(rreq->inode); - rreq->debug_id =3D atomic_inc_return(&debug_ids); - INIT_LIST_HEAD(&rreq->subrequests); - INIT_WORK(&rreq->work, netfs_rreq_work); - refcount_set(&rreq->usage, 1); - __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); - if (ops->init_request) - ops->init_request(rreq, file); - netfs_stat(&netfs_n_rh_rreq); - } - - return rreq; -} - -static void netfs_get_request(struct netfs_io_request *rreq) -{ - refcount_inc(&rreq->usage); -} - -static void netfs_clear_subrequests(struct netfs_io_request *rreq, bool wa= s_async) -{ - struct netfs_io_subrequest *subreq; - - while (!list_empty(&rreq->subrequests)) { - subreq =3D list_first_entry(&rreq->subrequests, - struct netfs_io_subrequest, rreq_link); - list_del(&subreq->rreq_link); - netfs_put_subrequest(subreq, was_async); - } -} - -static void netfs_free_request(struct work_struct *work) -{ - struct netfs_io_request *rreq =3D - container_of(work, struct netfs_io_request, work); - netfs_clear_subrequests(rreq, false); - if (rreq->netfs_priv) - rreq->netfs_ops->cleanup(rreq->mapping, rreq->netfs_priv); - trace_netfs_rreq(rreq, netfs_rreq_trace_free); - if (rreq->cache_resources.ops) - rreq->cache_resources.ops->end_operation(&rreq->cache_resources); - kfree(rreq); - netfs_stat_d(&netfs_n_rh_rreq); -} - -static void netfs_put_request(struct netfs_io_request *rreq, bool was_asyn= c) -{ - if (refcount_dec_and_test(&rreq->usage)) { - if (was_async) { - rreq->work.func =3D netfs_free_request; - if (!queue_work(system_unbound_wq, &rreq->work)) - BUG(); - } else { - netfs_free_request(&rreq->work); - } - } -} - -/* - * Allocate and partially initialise an I/O request structure. - */ -static struct netfs_io_subrequest *netfs_alloc_subrequest( - struct netfs_io_request *rreq) -{ - struct netfs_io_subrequest *subreq; - - subreq =3D kzalloc(sizeof(struct netfs_io_subrequest), GFP_KERNEL); - if (subreq) { - INIT_LIST_HEAD(&subreq->rreq_link); - refcount_set(&subreq->usage, 2); - subreq->rreq =3D rreq; - netfs_get_request(rreq); - netfs_stat(&netfs_n_rh_sreq); - } - - return subreq; -} - -static void netfs_get_subrequest(struct netfs_io_subrequest *subreq) -{ - refcount_inc(&subreq->usage); -} - -static void __netfs_put_subrequest(struct netfs_io_subrequest *subreq, - bool was_async) -{ - struct netfs_io_request *rreq =3D subreq->rreq; - - trace_netfs_sreq(subreq, netfs_sreq_trace_free); - kfree(subreq); - netfs_stat_d(&netfs_n_rh_sreq); - netfs_put_request(rreq, was_async); -} - /* * Clear the unread part of an I/O request. */ @@ -558,7 +442,7 @@ static void netfs_rreq_assess(struct netfs_io_request *= rreq, bool was_async) netfs_rreq_completed(rreq, was_async); } =20 -static void netfs_rreq_work(struct work_struct *work) +void netfs_rreq_work(struct work_struct *work) { struct netfs_io_request *rreq =3D container_of(work, struct netfs_io_request, work); From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60FB1C433F5 for ; Thu, 10 Mar 2022 16:18:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243213AbiCJQTB (ORCPT ); Thu, 10 Mar 2022 11:19:01 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37398 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241737AbiCJQRw (ORCPT ); Thu, 10 Mar 2022 11:17:52 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2DBDE190C16 for ; Thu, 10 Mar 2022 08:16:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929009; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=m0zrrGDSu3YpWsafJE6HK4NAMWnjg+E7bcoPNDsGgLA=; b=hu8P5O0Skx4PX12blbhmF6redb+3kaqVoS0YSHlvmhoqKY9HBtcDihBfyIZegXUfH5FxEw dm+hLZwtM2YNs5zkx1aQcJYOYDuJEja2tNkvButg18Uu5RC/EtFjaE7U94gyQpQNhpvulj mgErQkJ47N+AD/Ca6y4RGnlBgwEQ+Rk= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-593-oBrO6CweM-uyQIPhsOA3Gw-1; Thu, 10 Mar 2022 11:16:46 -0500 X-MC-Unique: oBrO6CweM-uyQIPhsOA3Gw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id EDF78824FA7; Thu, 10 Mar 2022 16:16:43 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id B11CC86C33; Thu, 10 Mar 2022 16:16:27 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 06/20] netfs: Adjust the netfs_rreq tracepoint slightly From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:16:26 +0000 Message-ID: <164692898684.2099075.12153225958137716567.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Adjust the netfs_rreq tracepoint to include the origin of the request and to increase the size of the "what trace" output strings by a character so that "ENCRYPT" and "DECRYPT" will fit without abbreviation. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164622996715.3564931.4252319907990358129.st= git@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678199468.1200972.17275585970238114726.s= tgit@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/netfs/read_helper.c | 2 +- include/trace/events/netfs.h | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index ef23ef9889d5..181aeda32649 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -181,7 +181,7 @@ static void netfs_rreq_do_write_to_cache(struct netfs_i= o_request *rreq) struct iov_iter iter; int ret; =20 - trace_netfs_rreq(rreq, netfs_rreq_trace_write); + trace_netfs_rreq(rreq, netfs_rreq_trace_copy); =20 /* We don't want terminating writes trying to wake us up whilst we're * still going through the list. diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index b40809c0bd74..0c7a26c4d11c 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -22,13 +22,13 @@ E_(netfs_read_trace_write_begin, "WRITEBEGN") =20 #define netfs_rreq_traces \ - EM(netfs_rreq_trace_assess, "ASSESS") \ - EM(netfs_rreq_trace_done, "DONE ") \ - EM(netfs_rreq_trace_free, "FREE ") \ - EM(netfs_rreq_trace_resubmit, "RESUBM") \ - EM(netfs_rreq_trace_unlock, "UNLOCK") \ - EM(netfs_rreq_trace_unmark, "UNMARK") \ - E_(netfs_rreq_trace_write, "WRITE ") + EM(netfs_rreq_trace_assess, "ASSESS ") \ + EM(netfs_rreq_trace_copy, "COPY ") \ + EM(netfs_rreq_trace_done, "DONE ") \ + EM(netfs_rreq_trace_free, "FREE ") \ + EM(netfs_rreq_trace_resubmit, "RESUBMT") \ + EM(netfs_rreq_trace_unlock, "UNLOCK ") \ + E_(netfs_rreq_trace_unmark, "UNMARK ") =20 #define netfs_sreq_sources \ EM(NETFS_FILL_WITH_ZEROES, "ZERO") \ @@ -134,7 +134,7 @@ TRACE_EVENT(netfs_rreq, =20 TP_STRUCT__entry( __field(unsigned int, rreq ) - __field(unsigned short, flags ) + __field(unsigned int, flags ) __field(enum netfs_rreq_trace, what ) ), =20 @@ -182,8 +182,8 @@ TRACE_EVENT(netfs_sreq, =20 TP_printk("R=3D%08x[%u] %s %s f=3D%02x s=3D%llx %zx/%zx e=3D%d", __entry->rreq, __entry->index, - __print_symbolic(__entry->what, netfs_sreq_traces), __print_symbolic(__entry->source, netfs_sreq_sources), + __print_symbolic(__entry->what, netfs_sreq_traces), __entry->flags, __entry->start, __entry->transferred, __entry->len, __entry->error) From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C2A9AC433EF for ; Thu, 10 Mar 2022 16:17:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242053AbiCJQSq (ORCPT ); Thu, 10 Mar 2022 11:18:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37662 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242157AbiCJQSF (ORCPT ); Thu, 10 Mar 2022 11:18:05 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B81D1191411 for ; Thu, 10 Mar 2022 08:16:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929018; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8cfGxYB8njuOkQO17893uLOX/1s/bBn62z9nmWYRuKs=; b=bBLXAbJjUawhOwBdLPyDHZHEs9i6CtdWOA1TBxlT9VUECdv1FuCFHshEhgW27w3GDMY7gr nX2A4YQsJPyJB+mucGslMheHqBlkNUGkS2WJfvvdY7hRwkz03F6QHFvSdvmV8YoyOxLlXR Wn5mE9KqyyCh6Hu4CYe6bDV7wmHDPmM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-674-QdzTfoPGN_-AwGmAAkQoyg-1; Thu, 10 Mar 2022 11:16:55 -0500 X-MC-Unique: QdzTfoPGN_-AwGmAAkQoyg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5C85B1006AAA; Thu, 10 Mar 2022 16:16:53 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1AB5086593; Thu, 10 Mar 2022 16:16:49 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 07/20] netfs: Trace refcounting on the netfs_io_request struct From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:16:49 +0000 Message-ID: <164692900920.2099075.11847712419940675791.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add refcount tracing for the netfs_io_request structure. Changes =3D=3D=3D=3D=3D=3D=3D ver #3) - Switch 'W=3D' to 'R=3D' in the traceline to match other request debug ID= s. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164622997668.3564931.14456171619219324968.s= tgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678200943.1200972.7241495532327787765.st= git@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/netfs/internal.h | 11 +++++++++-- fs/netfs/objects.c | 24 +++++++++++++++++------- fs/netfs/read_helper.c | 14 +++++++------- include/linux/netfs.h | 2 +- include/trace/events/netfs.h | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 17 deletions(-) diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index cf7a3ddb16a4..89b02357500d 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -20,13 +20,20 @@ struct netfs_io_request *netfs_alloc_request(const struct netfs_request_op= s *ops, void *netfs_priv, struct file *file); -void netfs_get_request(struct netfs_io_request *rreq); +void netfs_get_request(struct netfs_io_request *rreq, enum netfs_rreq_ref_= trace what); void netfs_clear_subrequests(struct netfs_io_request *rreq, bool was_async= ); -void netfs_put_request(struct netfs_io_request *rreq, bool was_async); +void netfs_put_request(struct netfs_io_request *rreq, bool was_async, + enum netfs_rreq_ref_trace what); struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request= *rreq); void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_asy= nc); void netfs_get_subrequest(struct netfs_io_subrequest *subreq); =20 +static inline void netfs_see_request(struct netfs_io_request *rreq, + enum netfs_rreq_ref_trace what) +{ + trace_netfs_rreq_ref(rreq->debug_id, refcount_read(&rreq->ref), what); +} + /* * read_helper.c */ diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index f7383c28dc6e..4e29c3bb6e5a 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -27,7 +27,7 @@ struct netfs_io_request *netfs_alloc_request( rreq->debug_id =3D atomic_inc_return(&debug_ids); INIT_LIST_HEAD(&rreq->subrequests); INIT_WORK(&rreq->work, netfs_rreq_work); - refcount_set(&rreq->usage, 1); + refcount_set(&rreq->ref, 1); __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); if (ops->init_request) ops->init_request(rreq, file); @@ -37,9 +37,12 @@ struct netfs_io_request *netfs_alloc_request( return rreq; } =20 -void netfs_get_request(struct netfs_io_request *rreq) +void netfs_get_request(struct netfs_io_request *rreq, enum netfs_rreq_ref_= trace what) { - refcount_inc(&rreq->usage); + int r; + + __refcount_inc(&rreq->ref, &r); + trace_netfs_rreq_ref(rreq->debug_id, r + 1, what); } =20 void netfs_clear_subrequests(struct netfs_io_request *rreq, bool was_async) @@ -68,9 +71,16 @@ static void netfs_free_request(struct work_struct *work) netfs_stat_d(&netfs_n_rh_rreq); } =20 -void netfs_put_request(struct netfs_io_request *rreq, bool was_async) +void netfs_put_request(struct netfs_io_request *rreq, bool was_async, + enum netfs_rreq_ref_trace what) { - if (refcount_dec_and_test(&rreq->usage)) { + unsigned int debug_id =3D rreq->debug_id; + bool dead; + int r; + + dead =3D __refcount_dec_and_test(&rreq->ref, &r); + trace_netfs_rreq_ref(debug_id, r - 1, what); + if (dead) { if (was_async) { rreq->work.func =3D netfs_free_request; if (!queue_work(system_unbound_wq, &rreq->work)) @@ -93,7 +103,7 @@ struct netfs_io_subrequest *netfs_alloc_subrequest(struc= t netfs_io_request *rreq INIT_LIST_HEAD(&subreq->rreq_link); refcount_set(&subreq->usage, 2); subreq->rreq =3D rreq; - netfs_get_request(rreq); + netfs_get_request(rreq, netfs_rreq_trace_get_subreq); netfs_stat(&netfs_n_rh_sreq); } =20 @@ -113,7 +123,7 @@ static void __netfs_put_subrequest(struct netfs_io_subr= equest *subreq, trace_netfs_sreq(subreq, netfs_sreq_trace_free); kfree(subreq); netfs_stat_d(&netfs_n_rh_sreq); - netfs_put_request(rreq, was_async); + netfs_put_request(rreq, was_async, netfs_rreq_trace_put_subreq); } =20 void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_asy= nc) diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index 181aeda32649..620c3be5ec0a 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -109,7 +109,7 @@ static void netfs_rreq_completed(struct netfs_io_reques= t *rreq, bool was_async) { trace_netfs_rreq(rreq, netfs_rreq_trace_done); netfs_clear_subrequests(rreq, was_async); - netfs_put_request(rreq, was_async); + netfs_put_request(rreq, was_async, netfs_rreq_trace_put_complete); } =20 /* @@ -799,7 +799,7 @@ void netfs_readahead(struct readahead_control *ractl, return; =20 cleanup_free: - netfs_put_request(rreq, false); + netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); return; cleanup: if (netfs_priv) @@ -858,7 +858,7 @@ int netfs_readpage(struct file *file, netfs_stat(&netfs_n_rh_readpage); trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage); =20 - netfs_get_request(rreq); + netfs_get_request(rreq, netfs_rreq_trace_get_hold); =20 atomic_set(&rreq->nr_outstanding, 1); do { @@ -883,7 +883,7 @@ int netfs_readpage(struct file *file, ret =3D -EIO; } out: - netfs_put_request(rreq, false); + netfs_put_request(rreq, false, netfs_rreq_trace_put_hold); return ret; } EXPORT_SYMBOL(netfs_readpage); @@ -1030,13 +1030,13 @@ int netfs_write_begin(struct file *file, struct add= ress_space *mapping, */ ractl._nr_pages =3D folio_nr_pages(folio); netfs_rreq_expand(rreq, &ractl); - netfs_get_request(rreq); =20 /* We hold the folio locks, so we can drop the references */ folio_get(folio); while (readahead_folio(&ractl)) ; =20 + netfs_get_request(rreq, netfs_rreq_trace_get_hold); atomic_set(&rreq->nr_outstanding, 1); do { if (!netfs_rreq_submit_slice(rreq, &debug_index)) @@ -1062,7 +1062,7 @@ int netfs_write_begin(struct file *file, struct addre= ss_space *mapping, trace_netfs_failure(rreq, NULL, ret, netfs_fail_short_write_begin); ret =3D -EIO; } - netfs_put_request(rreq, false); + netfs_put_request(rreq, false, netfs_rreq_trace_put_hold); if (ret < 0) goto error; =20 @@ -1078,7 +1078,7 @@ int netfs_write_begin(struct file *file, struct addre= ss_space *mapping, return 0; =20 error_put: - netfs_put_request(rreq, false); + netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); error: folio_unlock(folio); folio_put(folio); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index f63de27d6f29..541aebe828f3 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -168,7 +168,7 @@ struct netfs_io_request { loff_t i_size; /* Size of the file */ loff_t start; /* Start position */ pgoff_t no_unlock_folio; /* Don't unlock this folio after read */ - refcount_t usage; + refcount_t ref; unsigned long flags; #define NETFS_RREQ_INCOMPLETE_IO 0 /* Some ioreqs terminated short or with= error */ #define NETFS_RREQ_COPY_TO_CACHE 1 /* Need to write to the cache */ diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 0c7a26c4d11c..e35a5ce52eb5 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -55,6 +55,15 @@ EM(netfs_fail_short_write_begin, "short-write-begin") \ E_(netfs_fail_prepare_write, "prep-write") =20 +#define netfs_rreq_ref_traces \ + EM(netfs_rreq_trace_get_hold, "GET HOLD ") \ + EM(netfs_rreq_trace_get_subreq, "GET SUBREQ ") \ + EM(netfs_rreq_trace_put_complete, "PUT COMPLT ") \ + EM(netfs_rreq_trace_put_failed, "PUT FAILED ") \ + EM(netfs_rreq_trace_put_hold, "PUT HOLD ") \ + EM(netfs_rreq_trace_put_subreq, "PUT SUBREQ ") \ + E_(netfs_rreq_trace_new, "NEW ") + #ifndef __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY #define __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY =20 @@ -67,6 +76,7 @@ enum netfs_read_trace { netfs_read_traces } __mode(byte); enum netfs_rreq_trace { netfs_rreq_traces } __mode(byte); enum netfs_sreq_trace { netfs_sreq_traces } __mode(byte); enum netfs_failure { netfs_failures } __mode(byte); +enum netfs_rreq_ref_trace { netfs_rreq_ref_traces } __mode(byte); =20 #endif =20 @@ -83,6 +93,7 @@ netfs_rreq_traces; netfs_sreq_sources; netfs_sreq_traces; netfs_failures; +netfs_rreq_ref_traces; =20 /* * Now redefine the EM() and E_() macros to map the enums to the strings t= hat @@ -229,6 +240,30 @@ TRACE_EVENT(netfs_failure, __entry->error) ); =20 +TRACE_EVENT(netfs_rreq_ref, + TP_PROTO(unsigned int rreq_debug_id, int ref, + enum netfs_rreq_ref_trace what), + + TP_ARGS(rreq_debug_id, ref, what), + + TP_STRUCT__entry( + __field(unsigned int, rreq ) + __field(int, ref ) + __field(enum netfs_rreq_ref_trace, what ) + ), + + TP_fast_assign( + __entry->rreq =3D rreq_debug_id; + __entry->ref =3D ref; + __entry->what =3D what; + ), + + TP_printk("R=3D%08x %s r=3D%u", + __entry->rreq, + __print_symbolic(__entry->what, netfs_rreq_ref_traces), + __entry->ref) + ); + #undef EM #undef E_ #endif /* _TRACE_NETFS_H */ From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 12DB8C433EF for ; Thu, 10 Mar 2022 16:17:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243097AbiCJQS5 (ORCPT ); Thu, 10 Mar 2022 11:18:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37782 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242400AbiCJQSO (ORCPT ); Thu, 10 Mar 2022 11:18:14 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 77F0D190C16 for ; Thu, 10 Mar 2022 08:17:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929031; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=IdTqqPUoe91n3yafXJ9ND30dPaE+5rnymp9Pdr4PMTA=; b=a/1FFF6i6cLFAbJD8UmjgdUktE6DK+3L3/vEZElgyjfLVkRUX5BcLY8yV56gwC0o/REVgE NVsRAjjAoVM4kHFG6RTV6c+eOJC/GIQEaWjMozAVYuUfkUZpaifg2QPFlRD2ibaCWoK5y/ zvjpUGCwJHvpJTdnsxLWFJfVy0aOVoo= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-220-c-lOPo6qMCmOhixK_YuXBw-1; Thu, 10 Mar 2022 11:17:09 -0500 X-MC-Unique: c-lOPo6qMCmOhixK_YuXBw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1AFA41091DA1; Thu, 10 Mar 2022 16:17:07 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 706947AC6B; Thu, 10 Mar 2022 16:16:59 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 08/20] netfs: Trace refcounting on the netfs_io_subrequest struct From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:16:58 +0000 Message-ID: <164692901860.2099075.4845820886851239935.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add refcount tracing for the netfs_io_subrequest structure. Changes =3D=3D=3D=3D=3D=3D=3D ver #3) - Switch 'W=3D' to 'R=3D' in the traceline to match other request debug ID= s. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164622998584.3564931.5052255990645723639.st= git@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678202603.1200972.14726007419792315578.s= tgit@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/netfs/internal.h | 2 -- fs/netfs/objects.c | 32 +++++++++++++++++++++++--------- fs/netfs/read_helper.c | 20 +++++++++++--------- include/linux/netfs.h | 8 +++++++- include/trace/events/netfs.h | 40 ++++++++++++++++++++++++++++++++++++++= ++ 5 files changed, 81 insertions(+), 21 deletions(-) diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 89b02357500d..a0b7d1bf9f3d 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -25,8 +25,6 @@ void netfs_clear_subrequests(struct netfs_io_request *rre= q, bool was_async); void netfs_put_request(struct netfs_io_request *rreq, bool was_async, enum netfs_rreq_ref_trace what); struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request= *rreq); -void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_asy= nc); -void netfs_get_subrequest(struct netfs_io_subrequest *subreq); =20 static inline void netfs_see_request(struct netfs_io_request *rreq, enum netfs_rreq_ref_trace what) diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 4e29c3bb6e5a..39097893e847 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -53,7 +53,8 @@ void netfs_clear_subrequests(struct netfs_io_request *rre= q, bool was_async) subreq =3D list_first_entry(&rreq->subrequests, struct netfs_io_subrequest, rreq_link); list_del(&subreq->rreq_link); - netfs_put_subrequest(subreq, was_async); + netfs_put_subrequest(subreq, was_async, + netfs_sreq_trace_put_clear); } } =20 @@ -101,7 +102,7 @@ struct netfs_io_subrequest *netfs_alloc_subrequest(stru= ct netfs_io_request *rreq subreq =3D kzalloc(sizeof(struct netfs_io_subrequest), GFP_KERNEL); if (subreq) { INIT_LIST_HEAD(&subreq->rreq_link); - refcount_set(&subreq->usage, 2); + refcount_set(&subreq->ref, 2); subreq->rreq =3D rreq; netfs_get_request(rreq, netfs_rreq_trace_get_subreq); netfs_stat(&netfs_n_rh_sreq); @@ -110,13 +111,18 @@ struct netfs_io_subrequest *netfs_alloc_subrequest(st= ruct netfs_io_request *rreq return subreq; } =20 -void netfs_get_subrequest(struct netfs_io_subrequest *subreq) +void netfs_get_subrequest(struct netfs_io_subrequest *subreq, + enum netfs_sreq_ref_trace what) { - refcount_inc(&subreq->usage); + int r; + + __refcount_inc(&subreq->ref, &r); + trace_netfs_sreq_ref(subreq->rreq->debug_id, subreq->debug_index, r + 1, + what); } =20 -static void __netfs_put_subrequest(struct netfs_io_subrequest *subreq, - bool was_async) +static void netfs_free_subrequest(struct netfs_io_subrequest *subreq, + bool was_async) { struct netfs_io_request *rreq =3D subreq->rreq; =20 @@ -126,8 +132,16 @@ static void __netfs_put_subrequest(struct netfs_io_sub= request *subreq, netfs_put_request(rreq, was_async, netfs_rreq_trace_put_subreq); } =20 -void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_asy= nc) +void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_asy= nc, + enum netfs_sreq_ref_trace what) { - if (refcount_dec_and_test(&subreq->usage)) - __netfs_put_subrequest(subreq, was_async); + unsigned int debug_index =3D subreq->debug_index; + unsigned int debug_id =3D subreq->rreq->debug_id; + bool dead; + int r; + + dead =3D __refcount_dec_and_test(&subreq->ref, &r); + trace_netfs_sreq_ref(debug_id, debug_index, r - 1, what); + if (dead) + netfs_free_subrequest(subreq, was_async); } diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index 620c3be5ec0a..8f277da487b6 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -167,7 +167,7 @@ static void netfs_rreq_copy_terminated(void *priv, ssiz= e_t transferred_or_error, if (atomic_dec_and_test(&rreq->nr_copy_ops)) netfs_rreq_unmark_after_write(rreq, was_async); =20 - netfs_put_subrequest(subreq, was_async); + netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated); } =20 /* @@ -191,7 +191,8 @@ static void netfs_rreq_do_write_to_cache(struct netfs_i= o_request *rreq) list_for_each_entry_safe(subreq, p, &rreq->subrequests, rreq_link) { if (!test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) { list_del_init(&subreq->rreq_link); - netfs_put_subrequest(subreq, false); + netfs_put_subrequest(subreq, false, + netfs_sreq_trace_put_no_copy); } } =20 @@ -203,7 +204,8 @@ static void netfs_rreq_do_write_to_cache(struct netfs_i= o_request *rreq) break; subreq->len +=3D next->len; list_del_init(&next->rreq_link); - netfs_put_subrequest(next, false); + netfs_put_subrequest(next, false, + netfs_sreq_trace_put_merged); } =20 ret =3D cres->ops->prepare_write(cres, &subreq->start, &subreq->len, @@ -219,7 +221,7 @@ static void netfs_rreq_do_write_to_cache(struct netfs_i= o_request *rreq) =20 atomic_inc(&rreq->nr_copy_ops); netfs_stat(&netfs_n_rh_write); - netfs_get_subrequest(subreq); + netfs_get_subrequest(subreq, netfs_sreq_trace_get_copy_to_cache); trace_netfs_sreq(subreq, netfs_sreq_trace_write); cres->ops->write(cres, subreq->start, &iter, netfs_rreq_copy_terminated, subreq); @@ -342,7 +344,7 @@ static void netfs_rreq_short_read(struct netfs_io_reque= st *rreq, netfs_stat(&netfs_n_rh_short_read); trace_netfs_sreq(subreq, netfs_sreq_trace_resubmit_short); =20 - netfs_get_subrequest(subreq); + netfs_get_subrequest(subreq, netfs_sreq_trace_get_short_read); atomic_inc(&rreq->nr_outstanding); if (subreq->source =3D=3D NETFS_READ_FROM_CACHE) netfs_read_from_cache(rreq, subreq, NETFS_READ_HOLE_CLEAR); @@ -376,7 +378,7 @@ static bool netfs_rreq_perform_resubmissions(struct net= fs_io_request *rreq) subreq->error =3D 0; netfs_stat(&netfs_n_rh_download_instead); trace_netfs_sreq(subreq, netfs_sreq_trace_download_instead); - netfs_get_subrequest(subreq); + netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); atomic_inc(&rreq->nr_outstanding); netfs_read_from_server(rreq, subreq); } else if (test_bit(NETFS_SREQ_SHORT_IO, &subreq->flags)) { @@ -538,7 +540,7 @@ void netfs_subreq_terminated(struct netfs_io_subrequest= *subreq, else if (u =3D=3D 1) wake_up_var(&rreq->nr_outstanding); =20 - netfs_put_subrequest(subreq, was_async); + netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated); return; =20 incomplete: @@ -683,7 +685,7 @@ static bool netfs_rreq_submit_slice(struct netfs_io_req= uest *rreq, =20 subreq_failed: rreq->error =3D subreq->error; - netfs_put_subrequest(subreq, false); + netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_failed); return false; } =20 @@ -1030,13 +1032,13 @@ int netfs_write_begin(struct file *file, struct add= ress_space *mapping, */ ractl._nr_pages =3D folio_nr_pages(folio); netfs_rreq_expand(rreq, &ractl); + netfs_get_request(rreq, netfs_rreq_trace_get_hold); =20 /* We hold the folio locks, so we can drop the references */ folio_get(folio); while (readahead_folio(&ractl)) ; =20 - netfs_get_request(rreq, netfs_rreq_trace_get_hold); atomic_set(&rreq->nr_outstanding, 1); do { if (!netfs_rreq_submit_slice(rreq, &debug_index)) diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 541aebe828f3..c702bd8ea8da 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -18,6 +18,8 @@ #include #include =20 +enum netfs_sreq_ref_trace; + /* * Overload PG_private_2 to give us PG_fscache - this is used to indicate = that * a page is currently backed by a local disk cache @@ -136,7 +138,7 @@ struct netfs_io_subrequest { loff_t start; /* Where to start the I/O */ size_t len; /* Size of the I/O */ size_t transferred; /* Amount of data transferred */ - refcount_t usage; + refcount_t ref; short error; /* 0 or error that occurred */ unsigned short debug_index; /* Index in list (for debugging output) */ enum netfs_io_source source; /* Where to read from/write to */ @@ -268,6 +270,10 @@ extern int netfs_write_begin(struct file *, struct add= ress_space *, void *); =20 extern void netfs_subreq_terminated(struct netfs_io_subrequest *, ssize_t,= bool); +extern void netfs_get_subrequest(struct netfs_io_subrequest *subreq, + enum netfs_sreq_ref_trace what); +extern void netfs_put_subrequest(struct netfs_io_subrequest *subreq, + bool was_async, enum netfs_sreq_ref_trace what); extern void netfs_stats_show(struct seq_file *); =20 #endif /* _LINUX_NETFS_H */ diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index e35a5ce52eb5..dcea5e888fd0 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -64,6 +64,17 @@ EM(netfs_rreq_trace_put_subreq, "PUT SUBREQ ") \ E_(netfs_rreq_trace_new, "NEW ") =20 +#define netfs_sreq_ref_traces \ + EM(netfs_sreq_trace_get_copy_to_cache, "GET COPY2C ") \ + EM(netfs_sreq_trace_get_resubmit, "GET RESUBMIT") \ + EM(netfs_sreq_trace_get_short_read, "GET SHORTRD") \ + EM(netfs_sreq_trace_new, "NEW ") \ + EM(netfs_sreq_trace_put_clear, "PUT CLEAR ") \ + EM(netfs_sreq_trace_put_failed, "PUT FAILED ") \ + EM(netfs_sreq_trace_put_merged, "PUT MERGED ") \ + EM(netfs_sreq_trace_put_no_copy, "PUT NO COPY") \ + E_(netfs_sreq_trace_put_terminated, "PUT TERM ") + #ifndef __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY #define __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY =20 @@ -77,6 +88,7 @@ enum netfs_rreq_trace { netfs_rreq_traces } __mode(byte); enum netfs_sreq_trace { netfs_sreq_traces } __mode(byte); enum netfs_failure { netfs_failures } __mode(byte); enum netfs_rreq_ref_trace { netfs_rreq_ref_traces } __mode(byte); +enum netfs_sreq_ref_trace { netfs_sreq_ref_traces } __mode(byte); =20 #endif =20 @@ -94,6 +106,7 @@ netfs_sreq_sources; netfs_sreq_traces; netfs_failures; netfs_rreq_ref_traces; +netfs_sreq_ref_traces; =20 /* * Now redefine the EM() and E_() macros to map the enums to the strings t= hat @@ -264,6 +277,33 @@ TRACE_EVENT(netfs_rreq_ref, __entry->ref) ); =20 +TRACE_EVENT(netfs_sreq_ref, + TP_PROTO(unsigned int rreq_debug_id, unsigned int subreq_debug_index, + int ref, enum netfs_sreq_ref_trace what), + + TP_ARGS(rreq_debug_id, subreq_debug_index, ref, what), + + TP_STRUCT__entry( + __field(unsigned int, rreq ) + __field(unsigned int, subreq ) + __field(int, ref ) + __field(enum netfs_sreq_ref_trace, what ) + ), + + TP_fast_assign( + __entry->rreq =3D rreq_debug_id; + __entry->subreq =3D subreq_debug_index; + __entry->ref =3D ref; + __entry->what =3D what; + ), + + TP_printk("R=3D%08x[%x] %s r=3D%u", + __entry->rreq, + __entry->subreq, + __print_symbolic(__entry->what, netfs_sreq_ref_traces), + __entry->ref) + ); + #undef EM #undef E_ #endif /* _TRACE_NETFS_H */ From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1FF12C433EF for ; Thu, 10 Mar 2022 16:17:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242348AbiCJQSv (ORCPT ); Thu, 10 Mar 2022 11:18:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37868 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242862AbiCJQSY (ORCPT ); Thu, 10 Mar 2022 11:18:24 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 8665B190B6A for ; Thu, 10 Mar 2022 08:17:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929041; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+5rw8zSPtNYHlJz50ggoUHurB2GiVXScpwkdQ7wos44=; b=JU6H8Tknhryc/C12iJWT0Dzl6Uk+GyNwJMwbtuZV3fCYRjiza2gDvgJcqEg26UL6NAWPRe cV1Cu3+1oW8G36zWfKrZt9KqpINQNnyNpCdU3VzNtUpvdIM9VL1dz+s2tcQ/KuFSNvqfwZ fSe8fGRkWGE7/ljN2CGXEFqRwAVdnQ8= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-551-KgVhwZz1OrS_G-xw4bYWdQ-1; Thu, 10 Mar 2022 11:17:18 -0500 X-MC-Unique: KgVhwZz1OrS_G-xw4bYWdQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4ED86180FD71; Thu, 10 Mar 2022 16:17:16 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2EBAC8379E; Thu, 10 Mar 2022 16:17:13 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 09/20] netfs: Adjust the netfs_failure tracepoint to indicate non-subreq lines From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:17:12 +0000 Message-ID: <164692903233.2099075.15414355147237641274.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Adjust the netfs_failure tracepoint to indicate a subrequest number of -1 when it's a full-request failure unrelated to any particular subrequest, such as a failure to encrypt its data buffer. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164623001948.3564931.2353852999649380059.st= git@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678204587.1200972.14893513018190383961.s= tgit@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- include/trace/events/netfs.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index dcea5e888fd0..556859b0f107 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -222,7 +222,7 @@ TRACE_EVENT(netfs_failure, =20 TP_STRUCT__entry( __field(unsigned int, rreq ) - __field(unsigned short, index ) + __field(short, index ) __field(short, error ) __field(unsigned short, flags ) __field(enum netfs_io_source, source ) @@ -234,17 +234,17 @@ TRACE_EVENT(netfs_failure, =20 TP_fast_assign( __entry->rreq =3D rreq->debug_id; - __entry->index =3D sreq ? sreq->debug_index : 0; + __entry->index =3D sreq ? sreq->debug_index : -1; __entry->error =3D error; __entry->flags =3D sreq ? sreq->flags : 0; __entry->source =3D sreq ? sreq->source : NETFS_INVALID_READ; __entry->what =3D what; - __entry->len =3D sreq ? sreq->len : 0; + __entry->len =3D sreq ? sreq->len : rreq->len; __entry->transferred =3D sreq ? sreq->transferred : 0; __entry->start =3D sreq ? sreq->start : 0; ), =20 - TP_printk("R=3D%08x[%u] %s f=3D%02x s=3D%llx %zx/%zx %s e=3D%d", + TP_printk("R=3D%08x[%d] %s f=3D%02x s=3D%llx %zx/%zx %s e=3D%d", __entry->rreq, __entry->index, __print_symbolic(__entry->source, netfs_sreq_sources), __entry->flags, From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EC28BC433EF for ; Thu, 10 Mar 2022 16:18:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242231AbiCJQTI (ORCPT ); Thu, 10 Mar 2022 11:19:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38022 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241819AbiCJQSj (ORCPT ); Thu, 10 Mar 2022 11:18:39 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id BA71588784 for ; Thu, 10 Mar 2022 08:17:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929054; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qXbsOXzkyN9JgejgqHvAKCfU0+Q+YRouEiup8jS1dlo=; b=bCX6o7aFuXcovfB/02kS6jXqyLGdAbyrphuyxUujjSMAliIpvweOaZ+P/i15+jam3fNakg xxPSMPYzvyvhTLNrnO/leRK24nSXMO60zlfyW+n0Du41hRd/P+ukSWKVnNGu9nr3PI1rNV JjDElb7B+ESPu3wL6UOVQapYk1rlZZw= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-616-0vYNfF2iPAmUbqj8UFxF8w-1; Thu, 10 Mar 2022 11:17:30 -0500 X-MC-Unique: 0vYNfF2iPAmUbqj8UFxF8w-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id B9D7C51DC; Thu, 10 Mar 2022 16:17:28 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 61BC97F0D9; Thu, 10 Mar 2022 16:17:22 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 10/20] netfs: Refactor arguments for netfs_alloc_read_request From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:17:21 +0000 Message-ID: <164692904155.2099075.14717645623034355995.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Pass start and len to the rreq allocator. This should ensure that the fields are set so that ->init_request() can use them. Also add a parameter to indicates the origin of the request. Ceph can use this to tell whether to get caps. Changes =3D=3D=3D=3D=3D=3D=3D ver #3) - Change the author to me as Jeff feels that most of the patch is my changes now. ver #2) - Show the request origin in the netfs_rreq tracepoint. Signed-off-by: Jeff Layton Co-developed-by: David Howells Signed-off-by: David Howells cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164622989020.3564931.17517006047854958747.s= tgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678208569.1200972.12153682697842916557.s= tgit@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/netfs/internal.h | 7 +++++-- fs/netfs/objects.c | 13 ++++++++++--- fs/netfs/read_helper.c | 23 +++++++++++------------ include/linux/netfs.h | 7 +++++++ include/trace/events/netfs.h | 11 ++++++++++- 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index a0b7d1bf9f3d..89837e904fa7 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -17,9 +17,12 @@ /* * objects.c */ -struct netfs_io_request *netfs_alloc_request(const struct netfs_request_op= s *ops, +struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, + struct file *file, + const struct netfs_request_ops *ops, void *netfs_priv, - struct file *file); + loff_t start, size_t len, + enum netfs_io_origin origin); void netfs_get_request(struct netfs_io_request *rreq, enum netfs_rreq_ref_= trace what); void netfs_clear_subrequests(struct netfs_io_request *rreq, bool was_async= ); void netfs_put_request(struct netfs_io_request *rreq, bool was_async, diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 39097893e847..986d7a9d25dd 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -11,17 +11,24 @@ /* * Allocate an I/O request and initialise it. */ -struct netfs_io_request *netfs_alloc_request( - const struct netfs_request_ops *ops, void *netfs_priv, - struct file *file) +struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, + struct file *file, + const struct netfs_request_ops *ops, + void *netfs_priv, + loff_t start, size_t len, + enum netfs_io_origin origin) { static atomic_t debug_ids; struct netfs_io_request *rreq; =20 rreq =3D kzalloc(sizeof(struct netfs_io_request), GFP_KERNEL); if (rreq) { + rreq->start =3D start; + rreq->len =3D len; + rreq->origin =3D origin; rreq->netfs_ops =3D ops; rreq->netfs_priv =3D netfs_priv; + rreq->mapping =3D mapping; rreq->inode =3D file_inode(file); rreq->i_size =3D i_size_read(rreq->inode); rreq->debug_id =3D atomic_inc_return(&debug_ids); diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index 8f277da487b6..dea085715286 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -763,12 +763,13 @@ void netfs_readahead(struct readahead_control *ractl, if (readahead_count(ractl) =3D=3D 0) goto cleanup; =20 - rreq =3D netfs_alloc_request(ops, netfs_priv, ractl->file); + rreq =3D netfs_alloc_request(ractl->mapping, ractl->file, + ops, netfs_priv, + readahead_pos(ractl), + readahead_length(ractl), + NETFS_READAHEAD); if (!rreq) goto cleanup; - rreq->mapping =3D ractl->mapping; - rreq->start =3D readahead_pos(ractl); - rreq->len =3D readahead_length(ractl); =20 if (ops->begin_cache_operation) { ret =3D ops->begin_cache_operation(rreq); @@ -838,16 +839,15 @@ int netfs_readpage(struct file *file, =20 _enter("%lx", folio_index(folio)); =20 - rreq =3D netfs_alloc_request(ops, netfs_priv, file); + rreq =3D netfs_alloc_request(folio->mapping, file, ops, netfs_priv, + folio_file_pos(folio), folio_size(folio), + NETFS_READPAGE); if (!rreq) { if (netfs_priv) ops->cleanup(folio_file_mapping(folio), netfs_priv); folio_unlock(folio); return -ENOMEM; } - rreq->mapping =3D folio_file_mapping(folio); - rreq->start =3D folio_file_pos(folio); - rreq->len =3D folio_size(folio); =20 if (ops->begin_cache_operation) { ret =3D ops->begin_cache_operation(rreq); @@ -1008,12 +1008,11 @@ int netfs_write_begin(struct file *file, struct add= ress_space *mapping, } =20 ret =3D -ENOMEM; - rreq =3D netfs_alloc_request(ops, netfs_priv, file); + rreq =3D netfs_alloc_request(mapping, file, ops, netfs_priv, + folio_file_pos(folio), folio_size(folio), + NETFS_READ_FOR_WRITE); if (!rreq) goto error; - rreq->mapping =3D folio_file_mapping(folio); - rreq->start =3D folio_file_pos(folio); - rreq->len =3D folio_size(folio); rreq->no_unlock_folio =3D folio_index(folio); __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); netfs_priv =3D NULL; diff --git a/include/linux/netfs.h b/include/linux/netfs.h index c702bd8ea8da..7dc741d9b21b 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -150,6 +150,12 @@ struct netfs_io_subrequest { #define NETFS_SREQ_NO_PROGRESS 4 /* Set if we didn't manage to read any d= ata */ }; =20 +enum netfs_io_origin { + NETFS_READAHEAD, /* This read was triggered by readahead */ + NETFS_READPAGE, /* This read is a synchronous read */ + NETFS_READ_FOR_WRITE, /* This read is to prepare a write */ +} __mode(byte); + /* * Descriptor for an I/O helper request. This is used to make multiple I/O * operations to a variety of data stores and then stitch the result toget= her. @@ -167,6 +173,7 @@ struct netfs_io_request { size_t submitted; /* Amount submitted for I/O so far */ size_t len; /* Length of the request */ short error; /* 0 or error that occurred */ + enum netfs_io_origin origin; /* Origin of the request */ loff_t i_size; /* Size of the file */ loff_t start; /* Start position */ pgoff_t no_unlock_folio; /* Don't unlock this folio after read */ diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 556859b0f107..f00e3e1821c8 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -21,6 +21,11 @@ EM(netfs_read_trace_readpage, "READPAGE ") \ E_(netfs_read_trace_write_begin, "WRITEBEGN") =20 +#define netfs_rreq_origins \ + EM(NETFS_READAHEAD, "RA") \ + EM(NETFS_READPAGE, "RP") \ + E_(NETFS_READ_FOR_WRITE, "RW") + #define netfs_rreq_traces \ EM(netfs_rreq_trace_assess, "ASSESS ") \ EM(netfs_rreq_trace_copy, "COPY ") \ @@ -101,6 +106,7 @@ enum netfs_sreq_ref_trace { netfs_sreq_ref_traces } __m= ode(byte); #define E_(a, b) TRACE_DEFINE_ENUM(a); =20 netfs_read_traces; +netfs_rreq_origins; netfs_rreq_traces; netfs_sreq_sources; netfs_sreq_traces; @@ -159,17 +165,20 @@ TRACE_EVENT(netfs_rreq, TP_STRUCT__entry( __field(unsigned int, rreq ) __field(unsigned int, flags ) + __field(enum netfs_io_origin, origin ) __field(enum netfs_rreq_trace, what ) ), =20 TP_fast_assign( __entry->rreq =3D rreq->debug_id; __entry->flags =3D rreq->flags; + __entry->origin =3D rreq->origin; __entry->what =3D what; ), =20 - TP_printk("R=3D%08x %s f=3D%02x", + TP_printk("R=3D%08x %s %s f=3D%02x", __entry->rreq, + __print_symbolic(__entry->origin, netfs_rreq_origins), __print_symbolic(__entry->what, netfs_rreq_traces), __entry->flags) ); From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E2266C433F5 for ; Thu, 10 Mar 2022 16:21:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240091AbiCJQWA (ORCPT ); Thu, 10 Mar 2022 11:22:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41254 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242855AbiCJQUo (ORCPT ); Thu, 10 Mar 2022 11:20:44 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 328A219416C for ; Thu, 10 Mar 2022 08:19:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929171; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Hj8bAINGHaG2GF71IxEolwOwG7LzctTbX0iZeo0PTB4=; b=XXHDIEdSxLfqpHIY4O7Jg00D5for3kg8dd6oDJBeGXEP4w11B/gsz7oxnW7V0zQqvnxU+Z 2VHWdMjnDM7Tgau7YXwMzQeBeiozB2pUoFew+BqAJmmDzmdASyG2DAYwIBcs37D5jJITsr hkhdlut4T9CHa0sRp8GpDjedOSnh6wU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-36-yZLQgkHPNIaYe5MYKaT8UA-1; Thu, 10 Mar 2022 11:19:15 -0500 X-MC-Unique: yZLQgkHPNIaYe5MYKaT8UA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id AF33D51E6; Thu, 10 Mar 2022 16:17:51 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 814D3106F979; Thu, 10 Mar 2022 16:17:34 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 11/20] netfs: Change ->init_request() to return an error code From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:17:34 +0000 Message-ID: <164692905398.2099075.5238033621684646524.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Change the request initialisation function to return an error code so that the network filesystem can return a failure (ENOMEM, for example). This will also allow ceph to abort a ->readahead() op if the server refuses to give it a cap allowing local caching from within the netfslib framework (errors aren't passed back through ->readahead(), so returning, say, -ENOBUFS will cause the op to be aborted). Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164678212401.1200972.16537041523832944934.s= tgit@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/9p/vfs_addr.c | 3 ++- fs/afs/file.c | 3 ++- fs/netfs/objects.c | 41 ++++++++++++++++++++++++----------------- fs/netfs/read_helper.c | 20 ++++++++++++-------- include/linux/netfs.h | 2 +- 5 files changed, 41 insertions(+), 28 deletions(-) diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index fdc1033a1546..91d3926c9559 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -56,12 +56,13 @@ static void v9fs_issue_read(struct netfs_io_subrequest = *subreq) * @rreq: The read request * @file: The file being read from */ -static void v9fs_init_request(struct netfs_io_request *rreq, struct file *= file) +static int v9fs_init_request(struct netfs_io_request *rreq, struct file *f= ile) { struct p9_fid *fid =3D file->private_data; =20 refcount_inc(&fid->count); rreq->netfs_priv =3D fid; + return 0; } =20 /** diff --git a/fs/afs/file.c b/fs/afs/file.c index b19d635eed12..6469d7f98ef5 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -359,9 +359,10 @@ static int afs_symlink_readpage(struct file *file, str= uct page *page) return ret; } =20 -static void afs_init_request(struct netfs_io_request *rreq, struct file *f= ile) +static int afs_init_request(struct netfs_io_request *rreq, struct file *fi= le) { rreq->netfs_priv =3D key_get(afs_file_key(file)); + return 0; } =20 static bool afs_is_cache_enabled(struct inode *inode) diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 986d7a9d25dd..ae18827e156b 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -20,27 +20,34 @@ struct netfs_io_request *netfs_alloc_request(struct add= ress_space *mapping, { static atomic_t debug_ids; struct netfs_io_request *rreq; + int ret; =20 rreq =3D kzalloc(sizeof(struct netfs_io_request), GFP_KERNEL); - if (rreq) { - rreq->start =3D start; - rreq->len =3D len; - rreq->origin =3D origin; - rreq->netfs_ops =3D ops; - rreq->netfs_priv =3D netfs_priv; - rreq->mapping =3D mapping; - rreq->inode =3D file_inode(file); - rreq->i_size =3D i_size_read(rreq->inode); - rreq->debug_id =3D atomic_inc_return(&debug_ids); - INIT_LIST_HEAD(&rreq->subrequests); - INIT_WORK(&rreq->work, netfs_rreq_work); - refcount_set(&rreq->ref, 1); - __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); - if (ops->init_request) - ops->init_request(rreq, file); - netfs_stat(&netfs_n_rh_rreq); + if (!rreq) + return ERR_PTR(-ENOMEM); + + rreq->start =3D start; + rreq->len =3D len; + rreq->origin =3D origin; + rreq->netfs_ops =3D ops; + rreq->netfs_priv =3D netfs_priv; + rreq->mapping =3D mapping; + rreq->inode =3D file_inode(file); + rreq->i_size =3D i_size_read(rreq->inode); + rreq->debug_id =3D atomic_inc_return(&debug_ids); + INIT_LIST_HEAD(&rreq->subrequests); + INIT_WORK(&rreq->work, netfs_rreq_work); + refcount_set(&rreq->ref, 1); + __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); + if (rreq->netfs_ops->init_request) { + ret =3D rreq->netfs_ops->init_request(rreq, file); + if (ret < 0) { + kfree(rreq); + return ERR_PTR(ret); + } } =20 + netfs_stat(&netfs_n_rh_rreq); return rreq; } =20 diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index dea085715286..b5176f4320f4 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -768,7 +768,7 @@ void netfs_readahead(struct readahead_control *ractl, readahead_pos(ractl), readahead_length(ractl), NETFS_READAHEAD); - if (!rreq) + if (IS_ERR(rreq)) goto cleanup; =20 if (ops->begin_cache_operation) { @@ -842,11 +842,9 @@ int netfs_readpage(struct file *file, rreq =3D netfs_alloc_request(folio->mapping, file, ops, netfs_priv, folio_file_pos(folio), folio_size(folio), NETFS_READPAGE); - if (!rreq) { - if (netfs_priv) - ops->cleanup(folio_file_mapping(folio), netfs_priv); - folio_unlock(folio); - return -ENOMEM; + if (IS_ERR(rreq)) { + ret =3D PTR_ERR(rreq); + goto alloc_error; } =20 if (ops->begin_cache_operation) { @@ -887,6 +885,11 @@ int netfs_readpage(struct file *file, out: netfs_put_request(rreq, false, netfs_rreq_trace_put_hold); return ret; +alloc_error: + if (netfs_priv) + ops->cleanup(folio_file_mapping(folio), netfs_priv); + folio_unlock(folio); + return ret; } EXPORT_SYMBOL(netfs_readpage); =20 @@ -1007,12 +1010,13 @@ int netfs_write_begin(struct file *file, struct add= ress_space *mapping, goto have_folio_no_wait; } =20 - ret =3D -ENOMEM; rreq =3D netfs_alloc_request(mapping, file, ops, netfs_priv, folio_file_pos(folio), folio_size(folio), NETFS_READ_FOR_WRITE); - if (!rreq) + if (IS_ERR(rreq)) { + ret =3D PTR_ERR(rreq); goto error; + } rreq->no_unlock_folio =3D folio_index(folio); __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); netfs_priv =3D NULL; diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 7dc741d9b21b..4b99e38f73d9 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -193,7 +193,7 @@ struct netfs_io_request { */ struct netfs_request_ops { bool (*is_cache_enabled)(struct inode *inode); - void (*init_request)(struct netfs_io_request *rreq, struct file *file); + int (*init_request)(struct netfs_io_request *rreq, struct file *file); int (*begin_cache_operation)(struct netfs_io_request *rreq); void (*expand_readahead)(struct netfs_io_request *rreq); bool (*clamp_length)(struct netfs_io_subrequest *subreq); From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A08D8C433EF for ; Thu, 10 Mar 2022 16:20:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242341AbiCJQVB (ORCPT ); Thu, 10 Mar 2022 11:21:01 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39564 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242547AbiCJQUZ (ORCPT ); Thu, 10 Mar 2022 11:20:25 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id BA1D5199D49 for ; Thu, 10 Mar 2022 08:18:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929099; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=yBPK8CspGb1y+c3hE8EUfpnQvHO/Br5Ffw6ncR1/NAw=; b=WlW1/LLFNtepyqABivISAvzLCkZo3nGA7ARvINKtJC74p1S38MEfnKRNPeTnUw74MIPHKN didJgSo51+/BhZJDHRm3TiPpLjBM64/5Rg7qCYHVREdbSD3J09bAlyEzt7JLNG1Moxzc16 sg9egT04TqbqjeXZ0Gsy3Ik5KJzoIok= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-248-JS7KWOs7Or626loUa-PHuw-1; Thu, 10 Mar 2022 11:18:15 -0500 X-MC-Unique: JS7KWOs7Or626loUa-PHuw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4FD741091DA0; Thu, 10 Mar 2022 16:18:13 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id C9AA278C1B; Thu, 10 Mar 2022 16:17:57 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 12/20] ceph: Make ceph_init_request() check caps on readahead From: David Howells To: linux-cachefs@redhat.com Cc: ceph-devel@vger.kernel.org, dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:17:56 +0000 Message-ID: <164692907694.2099075.10081819855690054094.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Move the caps check from ceph_readahead() to ceph_init_request(), conditional on the origin being NETFS_READAHEAD so that in a future patch, ceph can point its ->readahead() vector directly at netfs_readahead(). Changes =3D=3D=3D=3D=3D=3D=3D ver #3) - Split from the patch to add a netfs inode context[1]. - Need to store the caps got in rreq->netfs_priv for later freeing. Signed-off-by: David Howells cc: ceph-devel@vger.kernel.org cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/8af0d47f17d89c06bbf602496dd845f2b0bf25b3.ca= mel@kernel.org/ [1] Reviewed-by: Jeff Layton Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/ceph/addr.c | 69 +++++++++++++++++++++++++++++++++-------------------= ---- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 9189257476f8..6d056db41f50 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -354,6 +354,45 @@ static void ceph_netfs_issue_read(struct netfs_io_subr= equest *subreq) dout("%s: result %d\n", __func__, err); } =20 +static int ceph_init_request(struct netfs_io_request *rreq, struct file *f= ile) +{ + struct inode *inode =3D rreq->inode; + int got =3D 0, want =3D CEPH_CAP_FILE_CACHE; + int ret =3D 0; + + if (file) { + struct ceph_rw_context *rw_ctx; + struct ceph_file_info *fi =3D file->private_data; + + rw_ctx =3D ceph_find_rw_context(fi); + if (rw_ctx) + return 0; + } + + if (rreq->origin !=3D NETFS_READAHEAD) + return 0; + + /* + * readahead callers do not necessarily hold Fcb caps + * (e.g. fadvise, madvise). + */ + ret =3D ceph_try_get_caps(inode, CEPH_CAP_FILE_RD, want, true, &got); + if (ret < 0) { + dout("start_read %p, error getting cap\n", inode); + return ret; + } + + if (!(got & want)) { + dout("start_read %p, no cache cap\n", inode); + return -EACCES; + } + if (ret =3D=3D 0) + return -EACCES; + + rreq->netfs_priv =3D (void *)(uintptr_t)got; + return 0; +} + static void ceph_readahead_cleanup(struct address_space *mapping, void *pr= iv) { struct inode *inode =3D mapping->host; @@ -365,7 +404,7 @@ static void ceph_readahead_cleanup(struct address_space= *mapping, void *priv) } =20 static const struct netfs_request_ops ceph_netfs_read_ops =3D { - .is_cache_enabled =3D ceph_is_cache_enabled, + .init_request =3D ceph_init_request, .begin_cache_operation =3D ceph_begin_cache_operation, .issue_read =3D ceph_netfs_issue_read, .expand_readahead =3D ceph_netfs_expand_readahead, @@ -393,33 +432,7 @@ static int ceph_readpage(struct file *file, struct pag= e *subpage) =20 static void ceph_readahead(struct readahead_control *ractl) { - struct inode *inode =3D file_inode(ractl->file); - struct ceph_file_info *fi =3D ractl->file->private_data; - struct ceph_rw_context *rw_ctx; - int got =3D 0; - int ret =3D 0; - - if (ceph_inode(inode)->i_inline_version !=3D CEPH_INLINE_NONE) - return; - - rw_ctx =3D ceph_find_rw_context(fi); - if (!rw_ctx) { - /* - * readahead callers do not necessarily hold Fcb caps - * (e.g. fadvise, madvise). - */ - int want =3D CEPH_CAP_FILE_CACHE; - - ret =3D ceph_try_get_caps(inode, CEPH_CAP_FILE_RD, want, true, &got); - if (ret < 0) - dout("start_read %p, error getting cap\n", inode); - else if (!(got & want)) - dout("start_read %p, no cache cap\n", inode); - - if (ret <=3D 0) - return; - } - netfs_readahead(ractl, &ceph_netfs_read_ops, (void *)(uintptr_t)got); + netfs_readahead(ractl, &ceph_netfs_read_ops, NULL); } =20 #ifdef CONFIG_CEPH_FSCACHE From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 516A9C43217 for ; Thu, 10 Mar 2022 16:19:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243180AbiCJQUt (ORCPT ); Thu, 10 Mar 2022 11:20:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44710 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241454AbiCJQUk (ORCPT ); Thu, 10 Mar 2022 11:20:40 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id C56BC192C90 for ; Thu, 10 Mar 2022 08:18:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929111; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fC+mRweQLNvWSrTjqqWRgiMoOB+n42941i0bGOm553A=; b=ad9HUCnLFKONmYeUQ6+JKdVAk98MiJdq7YatSnCrAWgiGt/imvSrcr2Dy9RkBMEvnRl2dC GxVjTTDZmlPqsAL6N3DIaxU0gpTKP1bS44UAnylquStqz2u1jOEMlA/xKjiyCTHqLeo+0/ cY4yVzrOF6L2l16L7L6vrjevuDvWhOU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-646-BdOWiMVsOKySfFqQbg9fxw-1; Thu, 10 Mar 2022 11:18:27 -0500 X-MC-Unique: BdOWiMVsOKySfFqQbg9fxw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id DCC2E801AB2; Thu, 10 Mar 2022 16:18:25 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6EA4C7AC6B; Thu, 10 Mar 2022 16:18:19 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 13/20] netfs: Add a netfs inode context From: David Howells To: linux-cachefs@redhat.com Cc: dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:18:18 +0000 Message-ID: <164692909854.2099075.9535537286264248057.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add a netfs_i_context struct that should be included in the network filesystem's own inode struct wrapper, directly after the VFS's inode struct, e.g.: struct my_inode { struct { /* These must be contiguous */ struct inode vfs_inode; struct netfs_i_context netfs_ctx; }; }; The netfs_i_context struct so far contains a single field for the network filesystem to use - the cache cookie: struct netfs_i_context { ... struct fscache_cookie *cache; }; Three functions are provided to help with this: (1) void netfs_i_context_init(struct inode *inode, const struct netfs_request_ops *ops); Initialise the netfs context and set the operations. (2) struct netfs_i_context *netfs_i_context(struct inode *inode); Find the netfs context from the VFS inode. (3) struct inode *netfs_inode(struct netfs_i_context *ctx); Find the VFS inode from the netfs context. Changes =3D=3D=3D=3D=3D=3D=3D ver #3) - Split out the bit to move ceph cap-getting on readahead into ceph_init_request()[1]. - Stick in a comment to the netfs inode structs indicating the contiguity requirements[2]. ver #2) - Adjust documentation to match. - Use "#if IS_ENABLED()" in netfs_i_cookie(), not "#ifdef". - Move the cap check from ceph_readahead() to ceph_init_request() to be called from netfslib. - Remove ceph_readahead() and use netfs_readahead() directly instead. Signed-off-by: David Howells cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/8af0d47f17d89c06bbf602496dd845f2b0bf25b3.ca= mel@kernel.org/ [1] Link: https://lore.kernel.org/r/beaf4f6a6c2575ed489adb14b257253c868f9a5c.ca= mel@kernel.org/ [2] Link: https://lore.kernel.org/r/164622984545.3564931.15691742939278418580.s= tgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678213320.1200972.16807551936267647470.s= tgit@warthog.procyon.org.uk/ # v2 Acked-by: Jeff Layton Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- Documentation/filesystems/netfs_library.rst | 101 +++++++++++++++++++----= ---- fs/9p/cache.c | 10 +-- fs/9p/v9fs.c | 4 - fs/9p/v9fs.h | 13 ++- fs/9p/vfs_addr.c | 43 +---------- fs/9p/vfs_inode.c | 13 +++ fs/afs/dynroot.c | 1=20 fs/afs/file.c | 26 +------ fs/afs/inode.c | 31 +++++--- fs/afs/internal.h | 19 ++++- fs/afs/super.c | 4 - fs/afs/write.c | 3 - fs/ceph/addr.c | 31 +------- fs/ceph/cache.c | 28 ++++--- fs/ceph/cache.h | 11 --- fs/ceph/inode.c | 6 +- fs/ceph/super.h | 17 ++--- fs/cifs/cifsglob.h | 10 ++- fs/cifs/fscache.c | 11 ++- fs/cifs/fscache.h | 2 - fs/netfs/internal.h | 17 ++++- fs/netfs/objects.c | 12 ++- fs/netfs/read_helper.c | 100 ++++++++++++-----------= ---- fs/netfs/stats.c | 1=20 include/linux/netfs.h | 81 +++++++++++++++++++--- 25 files changed, 317 insertions(+), 278 deletions(-) diff --git a/Documentation/filesystems/netfs_library.rst b/Documentation/fi= lesystems/netfs_library.rst index 4eb7e7b7b0fc..9c8bc5666b46 100644 --- a/Documentation/filesystems/netfs_library.rst +++ b/Documentation/filesystems/netfs_library.rst @@ -7,6 +7,8 @@ Network Filesystem Helper Library .. Contents: =20 - Overview. + - Per-inode context. + - Inode context helper functions. - Buffered read helpers. - Read helper functions. - Read helper structures. @@ -28,6 +30,69 @@ Note that the library module doesn't link against local = caching directly, so access must be provided by the netfs. =20 =20 +Per-Inode Context +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The network filesystem helper library needs a place to store a bit of stat= e for +its use on each netfs inode it is helping to manage. To this end, a conte= xt +structure is defined:: + + struct netfs_i_context { + const struct netfs_request_ops *ops; + struct fscache_cookie *cache; + }; + +A network filesystem that wants to use netfs lib must place one of these +directly after the VFS ``struct inode`` it allocates, usually as part of i= ts +own struct. This can be done in a way similar to the following:: + + struct my_inode { + struct { + /* These must be contiguous */ + struct inode vfs_inode; + struct netfs_i_context netfs_ctx; + }; + ... + }; + +This allows netfslib to find its state by simple offset from the inode poi= nter, +thereby allowing the netfslib helper functions to be pointed to directly b= y the +VFS/VM operation tables. + +The structure contains the following fields: + + * ``ops`` + + The set of operations provided by the network filesystem to netfslib. + + * ``cache`` + + Local caching cookie, or NULL if no caching is enabled. This field doe= s not + exist if fscache is disabled. + + +Inode Context Helper Functions +------------------------------ + +To help deal with the per-inode context, a number helper functions are +provided. Firstly, a function to perform basic initialisation on a contex= t and +set the operations table pointer:: + + void netfs_i_context_init(struct inode *inode, + const struct netfs_request_ops *ops); + +then two functions to cast between the VFS inode structure and the netfs +context:: + + struct netfs_i_context *netfs_i_context(struct inode *inode); + struct inode *netfs_inode(struct netfs_i_context *ctx); + +and finally, a function to get the cache cookie pointer from the context +attached to an inode (or NULL if fscache is disabled):: + + struct fscache_cookie *netfs_i_cookie(struct inode *inode); + + Buffered Read Helpers =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 @@ -70,38 +135,22 @@ Read Helper Functions =20 Three read helpers are provided:: =20 - void netfs_readahead(struct readahead_control *ractl, - const struct netfs_request_ops *ops, - void *netfs_priv); + void netfs_readahead(struct readahead_control *ractl); int netfs_readpage(struct file *file, - struct folio *folio, - const struct netfs_request_ops *ops, - void *netfs_priv); + struct page *page); int netfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int flags, struct folio **_folio, - void **_fsdata, - const struct netfs_request_ops *ops, - void *netfs_priv); - -Each corresponds to a VM operation, with the addition of a couple of param= eters -for the use of the read helpers: + void **_fsdata); =20 - * ``ops`` - - A table of operations through which the helpers can talk to the filesys= tem. - - * ``netfs_priv`` +Each corresponds to a VM address space operation. These operations use the +state in the per-inode context. =20 - Filesystem private data (can be NULL). - -Both of these values will be stored into the read request structure. - -For ->readahead() and ->readpage(), the network filesystem should just jump -into the corresponding read helper; whereas for ->write_begin(), it may be= a +For ->readahead() and ->readpage(), the network filesystem just point dire= ctly +at the corresponding read helper; whereas for ->write_begin(), it may be a little more complicated as the network filesystem might want to flush conflicting writes or track dirty data and needs to put the acquired folio= if an error occurs after calling the helper. @@ -246,7 +295,6 @@ through which it can issue requests and negotiate:: =20 struct netfs_request_ops { void (*init_request)(struct netfs_io_request *rreq, struct file *file); - bool (*is_cache_enabled)(struct inode *inode); int (*begin_cache_operation)(struct netfs_io_request *rreq); void (*expand_readahead)(struct netfs_io_request *rreq); bool (*clamp_length)(struct netfs_io_subrequest *subreq); @@ -265,11 +313,6 @@ The operations are as follows: [Optional] This is called to initialise the request structure. It is g= iven the file for reference and can modify the ->netfs_priv value. =20 - * ``is_cache_enabled()`` - - [Required] This is called by netfs_write_begin() to ask if the file is = being - cached. It should return true if it is being cached and false otherwis= e. - * ``begin_cache_operation()`` =20 [Optional] This is called to ask the network filesystem to call into the diff --git a/fs/9p/cache.c b/fs/9p/cache.c index 55e108e5e133..1c8dc696d516 100644 --- a/fs/9p/cache.c +++ b/fs/9p/cache.c @@ -49,22 +49,20 @@ int v9fs_cache_session_get_cookie(struct v9fs_session_i= nfo *v9ses, =20 void v9fs_cache_inode_get_cookie(struct inode *inode) { - struct v9fs_inode *v9inode; + struct v9fs_inode *v9inode =3D V9FS_I(inode); struct v9fs_session_info *v9ses; __le32 version; __le64 path; =20 if (!S_ISREG(inode->i_mode)) return; - - v9inode =3D V9FS_I(inode); - if (WARN_ON(v9inode->fscache)) + if (WARN_ON(v9fs_inode_cookie(v9inode))) return; =20 version =3D cpu_to_le32(v9inode->qid.version); path =3D cpu_to_le64(v9inode->qid.path); v9ses =3D v9fs_inode2v9ses(inode); - v9inode->fscache =3D + v9inode->netfs_ctx.cache =3D fscache_acquire_cookie(v9fs_session_cache(v9ses), 0, &path, sizeof(path), @@ -72,5 +70,5 @@ void v9fs_cache_inode_get_cookie(struct inode *inode) i_size_read(&v9inode->vfs_inode)); =20 p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n", - inode, v9inode->fscache); + inode, v9fs_inode_cookie(v9inode)); } diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 08f65c40af4f..e28ddf763b3b 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -623,9 +623,7 @@ static void v9fs_sysfs_cleanup(void) static void v9fs_inode_init_once(void *foo) { struct v9fs_inode *v9inode =3D (struct v9fs_inode *)foo; -#ifdef CONFIG_9P_FSCACHE - v9inode->fscache =3D NULL; -#endif + memset(&v9inode->qid, 0, sizeof(v9inode->qid)); inode_init_once(&v9inode->vfs_inode); } diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index bc8b30205d36..ec0e8df3b2eb 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -9,6 +9,7 @@ #define FS_9P_V9FS_H =20 #include +#include =20 /** * enum p9_session_flags - option flags for each 9P session @@ -108,14 +109,15 @@ struct v9fs_session_info { #define V9FS_INO_INVALID_ATTR 0x01 =20 struct v9fs_inode { -#ifdef CONFIG_9P_FSCACHE - struct fscache_cookie *fscache; -#endif + struct { + /* These must be contiguous */ + struct inode vfs_inode; /* the VFS's inode record */ + struct netfs_i_context netfs_ctx; /* Netfslib context */ + }; struct p9_qid qid; unsigned int cache_validity; struct p9_fid *writeback_fid; struct mutex v_mutex; - struct inode vfs_inode; }; =20 static inline struct v9fs_inode *V9FS_I(const struct inode *inode) @@ -126,7 +128,7 @@ static inline struct v9fs_inode *V9FS_I(const struct in= ode *inode) static inline struct fscache_cookie *v9fs_inode_cookie(struct v9fs_inode *= v9inode) { #ifdef CONFIG_9P_FSCACHE - return v9inode->fscache; + return netfs_i_cookie(&v9inode->vfs_inode); #else return NULL; #endif @@ -163,6 +165,7 @@ extern struct inode *v9fs_inode_from_fid(struct v9fs_se= ssion_info *v9ses, extern const struct inode_operations v9fs_dir_inode_operations_dotl; extern const struct inode_operations v9fs_file_inode_operations_dotl; extern const struct inode_operations v9fs_symlink_inode_operations_dotl; +extern const struct netfs_request_ops v9fs_req_ops; extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9= ses, struct p9_fid *fid, struct super_block *sb, int new); diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 91d3926c9559..ed06f3c34e98 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -77,17 +77,6 @@ static void v9fs_req_cleanup(struct address_space *mappi= ng, void *priv) p9_client_clunk(fid); } =20 -/** - * v9fs_is_cache_enabled - Determine if caching is enabled for an inode - * @inode: The inode to check - */ -static bool v9fs_is_cache_enabled(struct inode *inode) -{ - struct fscache_cookie *cookie =3D v9fs_inode_cookie(V9FS_I(inode)); - - return fscache_cookie_enabled(cookie) && cookie->cache_priv; -} - /** * v9fs_begin_cache_operation - Begin a cache operation for a read * @rreq: The read request @@ -103,36 +92,13 @@ static int v9fs_begin_cache_operation(struct netfs_io_= request *rreq) #endif } =20 -static const struct netfs_request_ops v9fs_req_ops =3D { +const struct netfs_request_ops v9fs_req_ops =3D { .init_request =3D v9fs_init_request, - .is_cache_enabled =3D v9fs_is_cache_enabled, .begin_cache_operation =3D v9fs_begin_cache_operation, .issue_read =3D v9fs_issue_read, .cleanup =3D v9fs_req_cleanup, }; =20 -/** - * v9fs_vfs_readpage - read an entire page in from 9P - * @file: file being read - * @page: structure to page - * - */ -static int v9fs_vfs_readpage(struct file *file, struct page *page) -{ - struct folio *folio =3D page_folio(page); - - return netfs_readpage(file, folio, &v9fs_req_ops, NULL); -} - -/** - * v9fs_vfs_readahead - read a set of pages from 9P - * @ractl: The readahead parameters - */ -static void v9fs_vfs_readahead(struct readahead_control *ractl) -{ - netfs_readahead(ractl, &v9fs_req_ops, NULL); -} - /** * v9fs_release_page - release the private state associated with a page * @page: The page to be released @@ -326,8 +292,7 @@ static int v9fs_write_begin(struct file *filp, struct a= ddress_space *mapping, * file. We need to do this before we get a lock on the page in case * there's more than one writer competing for the same cache block. */ - retval =3D netfs_write_begin(filp, mapping, pos, len, flags, &folio, fsda= ta, - &v9fs_req_ops, NULL); + retval =3D netfs_write_begin(filp, mapping, pos, len, flags, &folio, fsda= ta); if (retval < 0) return retval; =20 @@ -388,8 +353,8 @@ static int v9fs_set_page_dirty(struct page *page) #endif =20 const struct address_space_operations v9fs_addr_operations =3D { - .readpage =3D v9fs_vfs_readpage, - .readahead =3D v9fs_vfs_readahead, + .readpage =3D netfs_readpage, + .readahead =3D netfs_readahead, .set_page_dirty =3D v9fs_set_page_dirty, .writepage =3D v9fs_vfs_writepage, .write_begin =3D v9fs_write_begin, diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 2a10242c79c7..a7dc6781a622 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -231,9 +231,6 @@ struct inode *v9fs_alloc_inode(struct super_block *sb) v9inode =3D kmem_cache_alloc(v9fs_inode_cache, GFP_KERNEL); if (!v9inode) return NULL; -#ifdef CONFIG_9P_FSCACHE - v9inode->fscache =3D NULL; -#endif v9inode->writeback_fid =3D NULL; v9inode->cache_validity =3D 0; mutex_init(&v9inode->v_mutex); @@ -250,6 +247,14 @@ void v9fs_free_inode(struct inode *inode) kmem_cache_free(v9fs_inode_cache, V9FS_I(inode)); } =20 +/* + * Set parameters for the netfs library + */ +static void v9fs_set_netfs_context(struct inode *inode) +{ + netfs_i_context_init(inode, &v9fs_req_ops); +} + int v9fs_init_inode(struct v9fs_session_info *v9ses, struct inode *inode, umode_t mode, dev_t rdev) { @@ -338,6 +343,8 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses, err =3D -EINVAL; goto error; } + + v9fs_set_netfs_context(inode); error: return err; =20 diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c index db832cc931c8..f120bcb8bf73 100644 --- a/fs/afs/dynroot.c +++ b/fs/afs/dynroot.c @@ -76,6 +76,7 @@ struct inode *afs_iget_pseudo_dir(struct super_block *sb,= bool root) /* there shouldn't be an existing inode */ BUG_ON(!(inode->i_state & I_NEW)); =20 + netfs_i_context_init(inode, NULL); inode->i_size =3D 0; inode->i_mode =3D S_IFDIR | S_IRUGO | S_IXUGO; if (root) { diff --git a/fs/afs/file.c b/fs/afs/file.c index 6469d7f98ef5..2b68b2070248 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -19,13 +19,11 @@ #include "internal.h" =20 static int afs_file_mmap(struct file *file, struct vm_area_struct *vma); -static int afs_readpage(struct file *file, struct page *page); static int afs_symlink_readpage(struct file *file, struct page *page); static void afs_invalidatepage(struct page *page, unsigned int offset, unsigned int length); static int afs_releasepage(struct page *page, gfp_t gfp_flags); =20 -static void afs_readahead(struct readahead_control *ractl); static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *ite= r); static void afs_vm_open(struct vm_area_struct *area); static void afs_vm_close(struct vm_area_struct *area); @@ -52,8 +50,8 @@ const struct inode_operations afs_file_inode_operations = =3D { }; =20 const struct address_space_operations afs_file_aops =3D { - .readpage =3D afs_readpage, - .readahead =3D afs_readahead, + .readpage =3D netfs_readpage, + .readahead =3D netfs_readahead, .set_page_dirty =3D afs_set_page_dirty, .launder_page =3D afs_launder_page, .releasepage =3D afs_releasepage, @@ -365,13 +363,6 @@ static int afs_init_request(struct netfs_io_request *r= req, struct file *file) return 0; } =20 -static bool afs_is_cache_enabled(struct inode *inode) -{ - struct fscache_cookie *cookie =3D afs_vnode_cache(AFS_FS_I(inode)); - - return fscache_cookie_enabled(cookie) && cookie->cache_priv; -} - static int afs_begin_cache_operation(struct netfs_io_request *rreq) { #ifdef CONFIG_AFS_FSCACHE @@ -399,25 +390,12 @@ static void afs_priv_cleanup(struct address_space *ma= pping, void *netfs_priv) =20 const struct netfs_request_ops afs_req_ops =3D { .init_request =3D afs_init_request, - .is_cache_enabled =3D afs_is_cache_enabled, .begin_cache_operation =3D afs_begin_cache_operation, .check_write_begin =3D afs_check_write_begin, .issue_read =3D afs_issue_read, .cleanup =3D afs_priv_cleanup, }; =20 -static int afs_readpage(struct file *file, struct page *page) -{ - struct folio *folio =3D page_folio(page); - - return netfs_readpage(file, folio, &afs_req_ops, NULL); -} - -static void afs_readahead(struct readahead_control *ractl) -{ - netfs_readahead(ractl, &afs_req_ops, NULL); -} - int afs_write_inode(struct inode *inode, struct writeback_control *wbc) { fscache_unpin_writeback(wbc, afs_vnode_cache(AFS_FS_I(inode))); diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 5964f8aee090..5b5e40197655 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -53,6 +53,14 @@ static noinline void dump_vnode(struct afs_vnode *vnode,= struct afs_vnode *paren dump_stack(); } =20 +/* + * Set parameters for the netfs library + */ +static void afs_set_netfs_context(struct afs_vnode *vnode) +{ + netfs_i_context_init(&vnode->vfs_inode, &afs_req_ops); +} + /* * Initialise an inode from the vnode status. */ @@ -128,6 +136,7 @@ static int afs_inode_init_from_status(struct afs_operat= ion *op, } =20 afs_set_i_size(vnode, status->size); + afs_set_netfs_context(vnode); =20 vnode->invalid_before =3D status->data_version; inode_set_iversion_raw(&vnode->vfs_inode, status->data_version); @@ -420,7 +429,7 @@ static void afs_get_inode_cache(struct afs_vnode *vnode) struct afs_vnode_cache_aux aux; =20 if (vnode->status.type !=3D AFS_FTYPE_FILE) { - vnode->cache =3D NULL; + vnode->netfs_ctx.cache =3D NULL; return; } =20 @@ -430,12 +439,14 @@ static void afs_get_inode_cache(struct afs_vnode *vno= de) key.vnode_id_ext[1] =3D htonl(vnode->fid.vnode_hi); afs_set_cache_aux(vnode, &aux); =20 - vnode->cache =3D fscache_acquire_cookie( - vnode->volume->cache, - vnode->status.type =3D=3D AFS_FTYPE_FILE ? 0 : FSCACHE_ADV_SINGLE_CHUNK, - &key, sizeof(key), - &aux, sizeof(aux), - vnode->status.size); + afs_vnode_set_cache(vnode, + fscache_acquire_cookie( + vnode->volume->cache, + vnode->status.type =3D=3D AFS_FTYPE_FILE ? + 0 : FSCACHE_ADV_SINGLE_CHUNK, + &key, sizeof(key), + &aux, sizeof(aux), + vnode->status.size)); #endif } =20 @@ -528,6 +539,7 @@ struct inode *afs_root_iget(struct super_block *sb, str= uct key *key) =20 vnode =3D AFS_FS_I(inode); vnode->cb_v_break =3D as->volume->cb_v_break, + afs_set_netfs_context(vnode); =20 op =3D afs_alloc_operation(key, as->volume); if (IS_ERR(op)) { @@ -786,11 +798,8 @@ void afs_evict_inode(struct inode *inode) afs_put_wb_key(wbk); } =20 -#ifdef CONFIG_AFS_FSCACHE - fscache_relinquish_cookie(vnode->cache, + fscache_relinquish_cookie(afs_vnode_cache(vnode), test_bit(AFS_VNODE_DELETED, &vnode->flags)); - vnode->cache =3D NULL; -#endif =20 afs_prune_wb_keys(vnode); afs_put_permits(rcu_access_pointer(vnode->permit_cache)); diff --git a/fs/afs/internal.h b/fs/afs/internal.h index c56a0e1719ae..75ca3026457e 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -619,15 +619,16 @@ enum afs_lock_state { * leak from one inode to another. */ struct afs_vnode { - struct inode vfs_inode; /* the VFS's inode record */ + struct { + /* These must be contiguous */ + struct inode vfs_inode; /* the VFS's inode record */ + struct netfs_i_context netfs_ctx; /* Netfslib context */ + }; =20 struct afs_volume *volume; /* volume on which vnode resides */ struct afs_fid fid; /* the file identifier for this inode */ struct afs_file_status status; /* AFS status info for this file */ afs_dataversion_t invalid_before; /* Child dentries are invalid before th= is */ -#ifdef CONFIG_AFS_FSCACHE - struct fscache_cookie *cache; /* caching cookie */ -#endif struct afs_permits __rcu *permit_cache; /* cache of permits so far obtain= ed */ struct mutex io_lock; /* Lock for serialising I/O on this mutex */ struct rw_semaphore validate_lock; /* lock for validating this vnode */ @@ -674,12 +675,20 @@ struct afs_vnode { static inline struct fscache_cookie *afs_vnode_cache(struct afs_vnode *vno= de) { #ifdef CONFIG_AFS_FSCACHE - return vnode->cache; + return netfs_i_cookie(&vnode->vfs_inode); #else return NULL; #endif } =20 +static inline void afs_vnode_set_cache(struct afs_vnode *vnode, + struct fscache_cookie *cookie) +{ +#ifdef CONFIG_AFS_FSCACHE + vnode->netfs_ctx.cache =3D cookie; +#endif +} + /* * cached security record for one user's attempt to access a vnode */ diff --git a/fs/afs/super.c b/fs/afs/super.c index 5ec9fd97eccc..e66c6f54ac8e 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -688,13 +688,11 @@ static struct inode *afs_alloc_inode(struct super_blo= ck *sb) /* Reset anything that shouldn't leak from one inode to the next. */ memset(&vnode->fid, 0, sizeof(vnode->fid)); memset(&vnode->status, 0, sizeof(vnode->status)); + afs_vnode_set_cache(vnode, NULL); =20 vnode->volume =3D NULL; vnode->lock_key =3D NULL; vnode->permit_cache =3D NULL; -#ifdef CONFIG_AFS_FSCACHE - vnode->cache =3D NULL; -#endif =20 vnode->flags =3D 1 << AFS_VNODE_UNSET; vnode->lock_state =3D AFS_VNODE_LOCK_NONE; diff --git a/fs/afs/write.c b/fs/afs/write.c index 5e9157d0da29..e4b47f67a408 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -59,8 +59,7 @@ int afs_write_begin(struct file *file, struct address_spa= ce *mapping, * file. We need to do this before we get a lock on the page in case * there's more than one writer competing for the same cache block. */ - ret =3D netfs_write_begin(file, mapping, pos, len, flags, &folio, fsdata, - &afs_req_ops, NULL); + ret =3D netfs_write_begin(file, mapping, pos, len, flags, &folio, fsdata); if (ret < 0) return ret; =20 diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 6d056db41f50..97ae65c7bed1 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -403,7 +403,7 @@ static void ceph_readahead_cleanup(struct address_space= *mapping, void *priv) ceph_put_cap_refs(ci, got); } =20 -static const struct netfs_request_ops ceph_netfs_read_ops =3D { +const struct netfs_request_ops ceph_netfs_ops =3D { .init_request =3D ceph_init_request, .begin_cache_operation =3D ceph_begin_cache_operation, .issue_read =3D ceph_netfs_issue_read, @@ -413,28 +413,6 @@ static const struct netfs_request_ops ceph_netfs_read_= ops =3D { .cleanup =3D ceph_readahead_cleanup, }; =20 -/* read a single page, without unlocking it. */ -static int ceph_readpage(struct file *file, struct page *subpage) -{ - struct folio *folio =3D page_folio(subpage); - struct inode *inode =3D file_inode(file); - struct ceph_inode_info *ci =3D ceph_inode(inode); - struct ceph_vino vino =3D ceph_vino(inode); - size_t len =3D folio_size(folio); - u64 off =3D folio_file_pos(folio); - - dout("readpage ino %llx.%llx file %p off %llu len %zu folio %p index %lu\= n inline %d", - vino.ino, vino.snap, file, off, len, folio, folio_index(folio), - ci->i_inline_version !=3D CEPH_INLINE_NONE); - - return netfs_readpage(file, folio, &ceph_netfs_read_ops, NULL); -} - -static void ceph_readahead(struct readahead_control *ractl) -{ - netfs_readahead(ractl, &ceph_netfs_read_ops, NULL); -} - #ifdef CONFIG_CEPH_FSCACHE static void ceph_set_page_fscache(struct page *page) { @@ -1333,8 +1311,7 @@ static int ceph_write_begin(struct file *file, struct= address_space *mapping, struct folio *folio =3D NULL; int r; =20 - r =3D netfs_write_begin(file, inode->i_mapping, pos, len, 0, &folio, NULL, - &ceph_netfs_read_ops, NULL); + r =3D netfs_write_begin(file, inode->i_mapping, pos, len, 0, &folio, NULL= ); if (r =3D=3D 0) folio_wait_fscache(folio); if (r < 0) { @@ -1388,8 +1365,8 @@ static int ceph_write_end(struct file *file, struct a= ddress_space *mapping, } =20 const struct address_space_operations ceph_aops =3D { - .readpage =3D ceph_readpage, - .readahead =3D ceph_readahead, + .readpage =3D netfs_readpage, + .readahead =3D netfs_readahead, .writepage =3D ceph_writepage, .writepages =3D ceph_writepages_start, .write_begin =3D ceph_write_begin, diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c index 7d22850623ef..ddea99922073 100644 --- a/fs/ceph/cache.c +++ b/fs/ceph/cache.c @@ -29,26 +29,25 @@ void ceph_fscache_register_inode_cookie(struct inode *i= node) if (!(inode->i_state & I_NEW)) return; =20 - WARN_ON_ONCE(ci->fscache); + WARN_ON_ONCE(ci->netfs_ctx.cache); =20 - ci->fscache =3D fscache_acquire_cookie(fsc->fscache, 0, - &ci->i_vino, sizeof(ci->i_vino), - &ci->i_version, sizeof(ci->i_version), - i_size_read(inode)); + ci->netfs_ctx.cache =3D + fscache_acquire_cookie(fsc->fscache, 0, + &ci->i_vino, sizeof(ci->i_vino), + &ci->i_version, sizeof(ci->i_version), + i_size_read(inode)); } =20 -void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci) +void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info *ci) { - struct fscache_cookie *cookie =3D ci->fscache; - - fscache_relinquish_cookie(cookie, false); + fscache_relinquish_cookie(ceph_fscache_cookie(ci), false); } =20 void ceph_fscache_use_cookie(struct inode *inode, bool will_modify) { struct ceph_inode_info *ci =3D ceph_inode(inode); =20 - fscache_use_cookie(ci->fscache, will_modify); + fscache_use_cookie(ceph_fscache_cookie(ci), will_modify); } =20 void ceph_fscache_unuse_cookie(struct inode *inode, bool update) @@ -58,9 +57,10 @@ void ceph_fscache_unuse_cookie(struct inode *inode, bool= update) if (update) { loff_t i_size =3D i_size_read(inode); =20 - fscache_unuse_cookie(ci->fscache, &ci->i_version, &i_size); + fscache_unuse_cookie(ceph_fscache_cookie(ci), + &ci->i_version, &i_size); } else { - fscache_unuse_cookie(ci->fscache, NULL, NULL); + fscache_unuse_cookie(ceph_fscache_cookie(ci), NULL, NULL); } } =20 @@ -69,14 +69,14 @@ void ceph_fscache_update(struct inode *inode) struct ceph_inode_info *ci =3D ceph_inode(inode); loff_t i_size =3D i_size_read(inode); =20 - fscache_update_cookie(ci->fscache, &ci->i_version, &i_size); + fscache_update_cookie(ceph_fscache_cookie(ci), &ci->i_version, &i_size); } =20 void ceph_fscache_invalidate(struct inode *inode, bool dio_write) { struct ceph_inode_info *ci =3D ceph_inode(inode); =20 - fscache_invalidate(ceph_inode(inode)->fscache, + fscache_invalidate(ceph_fscache_cookie(ci), &ci->i_version, i_size_read(inode), dio_write ? FSCACHE_INVAL_DIO_WRITE : 0); } diff --git a/fs/ceph/cache.h b/fs/ceph/cache.h index b8b3b5cb6438..c20e43cade94 100644 --- a/fs/ceph/cache.h +++ b/fs/ceph/cache.h @@ -26,14 +26,9 @@ void ceph_fscache_unuse_cookie(struct inode *inode, bool= update); void ceph_fscache_update(struct inode *inode); void ceph_fscache_invalidate(struct inode *inode, bool dio_write); =20 -static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci) -{ - ci->fscache =3D NULL; -} - static inline struct fscache_cookie *ceph_fscache_cookie(struct ceph_inode= _info *ci) { - return ci->fscache; + return netfs_i_cookie(&ci->vfs_inode); } =20 static inline void ceph_fscache_resize(struct inode *inode, loff_t to) @@ -91,10 +86,6 @@ static inline void ceph_fscache_unregister_fs(struct cep= h_fs_client* fsc) { } =20 -static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci) -{ -} - static inline void ceph_fscache_register_inode_cookie(struct inode *inode) { } diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 7b1e93c8a0d2..6a176d9d394a 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -453,6 +453,9 @@ struct inode *ceph_alloc_inode(struct super_block *sb) =20 dout("alloc_inode %p\n", &ci->vfs_inode); =20 + /* Set parameters for the netfs library */ + netfs_i_context_init(&ci->vfs_inode, &ceph_netfs_ops); + spin_lock_init(&ci->i_ceph_lock); =20 ci->i_version =3D 0; @@ -538,9 +541,6 @@ struct inode *ceph_alloc_inode(struct super_block *sb) INIT_WORK(&ci->i_work, ceph_inode_work); ci->i_work_mask =3D 0; memset(&ci->i_btime, '\0', sizeof(ci->i_btime)); - - ceph_fscache_inode_init(ci); - return &ci->vfs_inode; } =20 diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 0b4b519682f1..e1c65aa8d3b6 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -17,13 +17,11 @@ #include #include #include +#include +#include =20 #include =20 -#ifdef CONFIG_CEPH_FSCACHE -#include -#endif - /* large granularity for statfs utilization stats to facilitate * large volume sizes on 32-bit machines. */ #define CEPH_BLOCK_SHIFT 22 /* 4 MB */ @@ -317,6 +315,11 @@ struct ceph_inode_xattrs_info { * Ceph inode. */ struct ceph_inode_info { + struct { + /* These must be contiguous */ + struct inode vfs_inode; + struct netfs_i_context netfs_ctx; /* Netfslib context */ + }; struct ceph_vino i_vino; /* ceph ino + snap */ =20 spinlock_t i_ceph_lock; @@ -427,11 +430,6 @@ struct ceph_inode_info { =20 struct work_struct i_work; unsigned long i_work_mask; - -#ifdef CONFIG_CEPH_FSCACHE - struct fscache_cookie *fscache; -#endif - struct inode vfs_inode; /* at end */ }; =20 static inline struct ceph_inode_info * @@ -1215,6 +1213,7 @@ extern void __ceph_touch_fmode(struct ceph_inode_info= *ci, =20 /* addr.c */ extern const struct address_space_operations ceph_aops; +extern const struct netfs_request_ops ceph_netfs_ops; extern int ceph_mmap(struct file *file, struct vm_area_struct *vma); extern int ceph_uninline_data(struct file *file); extern int ceph_pool_perm_check(struct inode *inode, int need); diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 48b343d03430..0a4085ced40f 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "cifs_fs_sb.h" #include "cifsacl.h" #include @@ -1402,6 +1403,11 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file= ); */ =20 struct cifsInodeInfo { + struct { + /* These must be contiguous */ + struct inode vfs_inode; /* the VFS's inode record */ + struct netfs_i_context netfs_ctx; /* Netfslib context */ + }; bool can_cache_brlcks; struct list_head llist; /* locks helb by this inode */ /* @@ -1432,10 +1438,6 @@ struct cifsInodeInfo { u64 uniqueid; /* server inode number */ u64 createtime; /* creation time on server */ __u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for this inode */ -#ifdef CONFIG_CIFS_FSCACHE - struct fscache_cookie *fscache; -#endif - struct inode vfs_inode; struct list_head deferred_closes; /* list of deferred closes */ spinlock_t deferred_lock; /* protection on deferred list */ bool lease_granted; /* Flag to indicate whether lease or oplock is grante= d. */ diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index b47c2011ce5b..a638b29e9062 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c @@ -103,7 +103,7 @@ void cifs_fscache_get_inode_cookie(struct inode *inode) =20 cifs_fscache_fill_coherency(&cifsi->vfs_inode, &cd); =20 - cifsi->fscache =3D + cifsi->netfs_ctx.cache =3D fscache_acquire_cookie(tcon->fscache, 0, &cifsi->uniqueid, sizeof(cifsi->uniqueid), &cd, sizeof(cd), @@ -126,11 +126,12 @@ void cifs_fscache_unuse_inode_cookie(struct inode *in= ode, bool update) void cifs_fscache_release_inode_cookie(struct inode *inode) { struct cifsInodeInfo *cifsi =3D CIFS_I(inode); + struct fscache_cookie *cookie =3D cifs_inode_cookie(inode); =20 - if (cifsi->fscache) { - cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache); - fscache_relinquish_cookie(cifsi->fscache, false); - cifsi->fscache =3D NULL; + if (cookie) { + cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cookie); + fscache_relinquish_cookie(cookie, false); + cifsi->netfs_ctx.cache =3D NULL; } } =20 diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h index 55129908e2c1..52355c0912ae 100644 --- a/fs/cifs/fscache.h +++ b/fs/cifs/fscache.h @@ -61,7 +61,7 @@ void cifs_fscache_fill_coherency(struct inode *inode, =20 static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) { - return CIFS_I(inode)->fscache; + return netfs_i_cookie(inode); } =20 static inline void cifs_invalidate_cache(struct inode *inode, unsigned int= flags) diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 89837e904fa7..5f9719409f21 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -6,6 +6,7 @@ */ =20 #include +#include #include =20 #ifdef pr_fmt @@ -19,8 +20,6 @@ */ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, struct file *file, - const struct netfs_request_ops *ops, - void *netfs_priv, loff_t start, size_t len, enum netfs_io_origin origin); void netfs_get_request(struct netfs_io_request *rreq, enum netfs_rreq_ref_= trace what); @@ -81,6 +80,20 @@ static inline void netfs_stat_d(atomic_t *stat) #define netfs_stat_d(x) do {} while(0) #endif =20 +/* + * Miscellaneous functions. + */ +static inline bool netfs_is_cache_enabled(struct netfs_i_context *ctx) +{ +#if IS_ENABLED(CONFIG_FSCACHE) + struct fscache_cookie *cookie =3D ctx->cache; + + return fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie); +#else + return false; +#endif +} + /*************************************************************************= ****/ /* * debug tracing diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index ae18827e156b..657b19e60118 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -13,12 +13,12 @@ */ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, struct file *file, - const struct netfs_request_ops *ops, - void *netfs_priv, loff_t start, size_t len, enum netfs_io_origin origin) { static atomic_t debug_ids; + struct inode *inode =3D file ? file_inode(file) : mapping->host; + struct netfs_i_context *ctx =3D netfs_i_context(inode); struct netfs_io_request *rreq; int ret; =20 @@ -29,11 +29,10 @@ struct netfs_io_request *netfs_alloc_request(struct add= ress_space *mapping, rreq->start =3D start; rreq->len =3D len; rreq->origin =3D origin; - rreq->netfs_ops =3D ops; - rreq->netfs_priv =3D netfs_priv; + rreq->netfs_ops =3D ctx->ops; rreq->mapping =3D mapping; - rreq->inode =3D file_inode(file); - rreq->i_size =3D i_size_read(rreq->inode); + rreq->inode =3D inode; + rreq->i_size =3D i_size_read(inode); rreq->debug_id =3D atomic_inc_return(&debug_ids); INIT_LIST_HEAD(&rreq->subrequests); INIT_WORK(&rreq->work, netfs_rreq_work); @@ -76,6 +75,7 @@ static void netfs_free_request(struct work_struct *work) { struct netfs_io_request *rreq =3D container_of(work, struct netfs_io_request, work); + netfs_clear_subrequests(rreq, false); if (rreq->netfs_priv) rreq->netfs_ops->cleanup(rreq->mapping, rreq->netfs_priv); diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index b5176f4320f4..73be06c409bb 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -14,7 +14,6 @@ #include #include #include -#include #include "internal.h" #define CREATE_TRACE_POINTS #include @@ -735,8 +734,6 @@ static void netfs_rreq_expand(struct netfs_io_request *= rreq, /** * netfs_readahead - Helper to manage a read request * @ractl: The description of the readahead request - * @ops: The network filesystem's operations for the helper to use - * @netfs_priv: Private netfs data to be retained in the request * * Fulfil a readahead request by drawing data from the cache if possible, = or * the netfs if not. Space beyond the EOF is zero-filled. Multiple I/O @@ -744,35 +741,32 @@ static void netfs_rreq_expand(struct netfs_io_request= *rreq, * readahead window can be expanded in either direction to a more convenie= nt * alighment for RPC efficiency or to make storage in the cache feasible. * - * The calling netfs must provide a table of operations, only one of which, - * issue_op, is mandatory. It may also be passed a private token, which w= ill - * be retained in rreq->netfs_priv and will be cleaned up by ops->cleanup(= ). + * The calling netfs must initialise a netfs context contiguous to the vfs + * inode before calling this. * * This is usable whether or not caching is enabled. */ -void netfs_readahead(struct readahead_control *ractl, - const struct netfs_request_ops *ops, - void *netfs_priv) +void netfs_readahead(struct readahead_control *ractl) { struct netfs_io_request *rreq; + struct netfs_i_context *ctx =3D netfs_i_context(ractl->mapping->host); unsigned int debug_index =3D 0; int ret; =20 _enter("%lx,%x", readahead_index(ractl), readahead_count(ractl)); =20 if (readahead_count(ractl) =3D=3D 0) - goto cleanup; + return; =20 rreq =3D netfs_alloc_request(ractl->mapping, ractl->file, - ops, netfs_priv, readahead_pos(ractl), readahead_length(ractl), NETFS_READAHEAD); if (IS_ERR(rreq)) - goto cleanup; + return; =20 - if (ops->begin_cache_operation) { - ret =3D ops->begin_cache_operation(rreq); + if (ctx->ops->begin_cache_operation) { + ret =3D ctx->ops->begin_cache_operation(rreq); if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) goto cleanup_free; } @@ -804,42 +798,35 @@ void netfs_readahead(struct readahead_control *ractl, cleanup_free: netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); return; -cleanup: - if (netfs_priv) - ops->cleanup(ractl->mapping, netfs_priv); - return; } EXPORT_SYMBOL(netfs_readahead); =20 /** * netfs_readpage - Helper to manage a readpage request * @file: The file to read from - * @folio: The folio to read - * @ops: The network filesystem's operations for the helper to use - * @netfs_priv: Private netfs data to be retained in the request + * @subpage: A subpage of the folio to read * * Fulfil a readpage request by drawing data from the cache if possible, o= r the * netfs if not. Space beyond the EOF is zero-filled. Multiple I/O reque= sts * from different sources will get munged together. * - * The calling netfs must provide a table of operations, only one of which, - * issue_op, is mandatory. It may also be passed a private token, which w= ill - * be retained in rreq->netfs_priv and will be cleaned up by ops->cleanup(= ). + * The calling netfs must initialise a netfs context contiguous to the vfs + * inode before calling this. * * This is usable whether or not caching is enabled. */ -int netfs_readpage(struct file *file, - struct folio *folio, - const struct netfs_request_ops *ops, - void *netfs_priv) +int netfs_readpage(struct file *file, struct page *subpage) { + struct folio *folio =3D page_folio(subpage); + struct address_space *mapping =3D folio->mapping; struct netfs_io_request *rreq; + struct netfs_i_context *ctx =3D netfs_i_context(mapping->host); unsigned int debug_index =3D 0; int ret; =20 _enter("%lx", folio_index(folio)); =20 - rreq =3D netfs_alloc_request(folio->mapping, file, ops, netfs_priv, + rreq =3D netfs_alloc_request(mapping, file, folio_file_pos(folio), folio_size(folio), NETFS_READPAGE); if (IS_ERR(rreq)) { @@ -847,8 +834,8 @@ int netfs_readpage(struct file *file, goto alloc_error; } =20 - if (ops->begin_cache_operation) { - ret =3D ops->begin_cache_operation(rreq); + if (ctx->ops->begin_cache_operation) { + ret =3D ctx->ops->begin_cache_operation(rreq); if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) { folio_unlock(folio); goto out; @@ -886,8 +873,6 @@ int netfs_readpage(struct file *file, netfs_put_request(rreq, false, netfs_rreq_trace_put_hold); return ret; alloc_error: - if (netfs_priv) - ops->cleanup(folio_file_mapping(folio), netfs_priv); folio_unlock(folio); return ret; } @@ -898,6 +883,7 @@ EXPORT_SYMBOL(netfs_readpage); * @folio: The folio being prepared * @pos: starting position for the write * @len: length of write + * @always_fill: T if the folio should always be completely filled/cleared * * In some cases, write_begin doesn't need to read at all: * - full folio write @@ -907,17 +893,27 @@ EXPORT_SYMBOL(netfs_readpage); * If any of these criteria are met, then zero out the unwritten parts * of the folio and return true. Otherwise, return false. */ -static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t = len) +static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t = len, + bool always_fill) { struct inode *inode =3D folio_inode(folio); loff_t i_size =3D i_size_read(inode); size_t offset =3D offset_in_folio(folio, pos); + size_t plen =3D folio_size(folio); + + if (unlikely(always_fill)) { + if (pos - offset + len <=3D i_size) + return false; /* Page entirely before EOF */ + zero_user_segment(&folio->page, 0, plen); + folio_mark_uptodate(folio); + return true; + } =20 /* Full folio write */ - if (offset =3D=3D 0 && len >=3D folio_size(folio)) + if (offset =3D=3D 0 && len >=3D plen) return true; =20 - /* pos beyond last folio in the file */ + /* Page entirely beyond the end of the file */ if (pos - offset >=3D i_size) goto zero_out; =20 @@ -927,7 +923,7 @@ static bool netfs_skip_folio_read(struct folio *folio, = loff_t pos, size_t len) =20 return false; zero_out: - zero_user_segments(&folio->page, 0, offset, offset + len, folio_size(foli= o)); + zero_user_segments(&folio->page, 0, offset, offset + len, len); return true; } =20 @@ -940,8 +936,6 @@ static bool netfs_skip_folio_read(struct folio *folio, = loff_t pos, size_t len) * @aop_flags: AOP_* flags * @_folio: Where to put the resultant folio * @_fsdata: Place for the netfs to store a cookie - * @ops: The network filesystem's operations for the helper to use - * @netfs_priv: Private netfs data to be retained in the request * * Pre-read data for a write-begin request by drawing data from the cache = if * possible, or the netfs if not. Space beyond the EOF is zero-filled. @@ -960,17 +954,18 @@ static bool netfs_skip_folio_read(struct folio *folio= , loff_t pos, size_t len) * should go ahead; unlock the folio and return -EAGAIN to cause the folio= to * be regot; or return an error. * + * The calling netfs must initialise a netfs context contiguous to the vfs + * inode before calling this. + * * This is usable whether or not caching is enabled. */ int netfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int aop_flags, - struct folio **_folio, void **_fsdata, - const struct netfs_request_ops *ops, - void *netfs_priv) + struct folio **_folio, void **_fsdata) { struct netfs_io_request *rreq; + struct netfs_i_context *ctx =3D netfs_i_context(file_inode(file )); struct folio *folio; - struct inode *inode =3D file_inode(file); unsigned int debug_index =3D 0, fgp_flags; pgoff_t index =3D pos >> PAGE_SHIFT; int ret; @@ -986,9 +981,9 @@ int netfs_write_begin(struct file *file, struct address= _space *mapping, if (!folio) return -ENOMEM; =20 - if (ops->check_write_begin) { + if (ctx->ops->check_write_begin) { /* Allow the netfs (eg. ceph) to flush conflicts. */ - ret =3D ops->check_write_begin(file, pos, len, folio, _fsdata); + ret =3D ctx->ops->check_write_begin(file, pos, len, folio, _fsdata); if (ret < 0) { trace_netfs_failure(NULL, NULL, ret, netfs_fail_check_write_begin); if (ret =3D=3D -EAGAIN) @@ -1004,13 +999,13 @@ int netfs_write_begin(struct file *file, struct addr= ess_space *mapping, * within the cache granule containing the EOF, in which case we need * to preload the granule. */ - if (!ops->is_cache_enabled(inode) && - netfs_skip_folio_read(folio, pos, len)) { + if (!netfs_is_cache_enabled(ctx) && + netfs_skip_folio_read(folio, pos, len, false)) { netfs_stat(&netfs_n_rh_write_zskip); goto have_folio_no_wait; } =20 - rreq =3D netfs_alloc_request(mapping, file, ops, netfs_priv, + rreq =3D netfs_alloc_request(mapping, file, folio_file_pos(folio), folio_size(folio), NETFS_READ_FOR_WRITE); if (IS_ERR(rreq)) { @@ -1019,10 +1014,9 @@ int netfs_write_begin(struct file *file, struct addr= ess_space *mapping, } rreq->no_unlock_folio =3D folio_index(folio); __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); - netfs_priv =3D NULL; =20 - if (ops->begin_cache_operation) { - ret =3D ops->begin_cache_operation(rreq); + if (ctx->ops->begin_cache_operation) { + ret =3D ctx->ops->begin_cache_operation(rreq); if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) goto error_put; } @@ -1076,8 +1070,6 @@ int netfs_write_begin(struct file *file, struct addre= ss_space *mapping, if (ret < 0) goto error; have_folio_no_wait: - if (netfs_priv) - ops->cleanup(mapping, netfs_priv); *_folio =3D folio; _leave(" =3D 0"); return 0; @@ -1087,8 +1079,6 @@ int netfs_write_begin(struct file *file, struct addre= ss_space *mapping, error: folio_unlock(folio); folio_put(folio); - if (netfs_priv) - ops->cleanup(mapping, netfs_priv); _leave(" =3D %d", ret); return ret; } diff --git a/fs/netfs/stats.c b/fs/netfs/stats.c index 9ae538c85378..5510a7a14a40 100644 --- a/fs/netfs/stats.c +++ b/fs/netfs/stats.c @@ -7,7 +7,6 @@ =20 #include #include -#include #include "internal.h" =20 atomic_t netfs_n_rh_readahead; diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 4b99e38f73d9..8458b30172a5 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -118,6 +118,16 @@ enum netfs_io_source { typedef void (*netfs_io_terminated_t)(void *priv, ssize_t transferred_or_e= rror, bool was_async); =20 +/* + * Per-inode description. This must be directly after the inode struct. + */ +struct netfs_i_context { + const struct netfs_request_ops *ops; +#if IS_ENABLED(CONFIG_FSCACHE) + struct fscache_cookie *cache; +#endif +}; + /* * Resources required to do operations on a cache. */ @@ -192,7 +202,6 @@ struct netfs_io_request { * Operations the network filesystem can/must provide to the helpers. */ struct netfs_request_ops { - bool (*is_cache_enabled)(struct inode *inode); int (*init_request)(struct netfs_io_request *rreq, struct file *file); int (*begin_cache_operation)(struct netfs_io_request *rreq); void (*expand_readahead)(struct netfs_io_request *rreq); @@ -263,18 +272,11 @@ struct netfs_cache_ops { }; =20 struct readahead_control; -extern void netfs_readahead(struct readahead_control *, - const struct netfs_request_ops *, - void *); -extern int netfs_readpage(struct file *, - struct folio *, - const struct netfs_request_ops *, - void *); +extern void netfs_readahead(struct readahead_control *); +extern int netfs_readpage(struct file *, struct page *); extern int netfs_write_begin(struct file *, struct address_space *, loff_t, unsigned int, unsigned int, struct folio **, - void **, - const struct netfs_request_ops *, - void *); + void **); =20 extern void netfs_subreq_terminated(struct netfs_io_subrequest *, ssize_t,= bool); extern void netfs_get_subrequest(struct netfs_io_subrequest *subreq, @@ -283,4 +285,61 @@ extern void netfs_put_subrequest(struct netfs_io_subre= quest *subreq, bool was_async, enum netfs_sreq_ref_trace what); extern void netfs_stats_show(struct seq_file *); =20 +/** + * netfs_i_context - Get the netfs inode context from the inode + * @inode: The inode to query + * + * Get the netfs lib inode context from the network filesystem's inode. T= he + * context struct is expected to directly follow on from the VFS inode str= uct. + */ +static inline struct netfs_i_context *netfs_i_context(struct inode *inode) +{ + return (struct netfs_i_context *)(inode + 1); +} + +/** + * netfs_inode - Get the netfs inode from the inode context + * @ctx: The context to query + * + * Get the netfs inode from the netfs library's inode context. The VFS in= ode + * is expected to directly precede the context struct. + */ +static inline struct inode *netfs_inode(struct netfs_i_context *ctx) +{ + return ((struct inode *)ctx) - 1; +} + +/** + * netfs_i_context_init - Initialise a netfs lib context + * @inode: The inode with which the context is associated + * @ops: The netfs's operations list + * + * Initialise the netfs library context struct. This is expected to follo= w on + * directly from the VFS inode struct. + */ +static inline void netfs_i_context_init(struct inode *inode, + const struct netfs_request_ops *ops) +{ + struct netfs_i_context *ctx =3D netfs_i_context(inode); + + memset(ctx, 0, sizeof(*ctx)); + ctx->ops =3D ops; +} + +/** + * netfs_i_cookie - Get the cache cookie from the inode + * @inode: The inode to query + * + * Get the caching cookie (if enabled) from the network filesystem's inode. + */ +static inline struct fscache_cookie *netfs_i_cookie(struct inode *inode) +{ +#if IS_ENABLED(CONFIG_FSCACHE) + struct netfs_i_context *ctx =3D netfs_i_context(inode); + return ctx->cache; +#else + return NULL; +#endif +} + #endif /* _LINUX_NETFS_H */ From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 21EEBC433FE for ; Thu, 10 Mar 2022 16:20:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242547AbiCJQVL (ORCPT ); Thu, 10 Mar 2022 11:21:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42094 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241402AbiCJQUl (ORCPT ); Thu, 10 Mar 2022 11:20:41 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id C5B58192CB3 for ; Thu, 10 Mar 2022 08:19:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929128; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UV+Xt03K95r9yXtehuKM0Hf1AJlIHc0XyIgFU5k/aLA=; b=eiM5hFX1wC7ixka7WHMVQycvPEbTYcoALFkpIyQUkYWd3F8bbvXW/P1lIWMYgVBUV7ouIv CRKSdpFFje1GlgInEoyVtfEXqFKGY0Gg9qBfniFPEiIclhcGsvKUbvwistBzfWLUfXzGnX VCEMb04RSCsgIC04dz+xbUGWrbtMl/w= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-348-m5pJVoO-NlafZCFGbNUn9Q-1; Thu, 10 Mar 2022 11:18:43 -0500 X-MC-Unique: m5pJVoO-NlafZCFGbNUn9Q-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D45EA824FA8; Thu, 10 Mar 2022 16:18:41 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0545A2619D; Thu, 10 Mar 2022 16:18:31 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 14/20] netfs: Add a function to consolidate beginning a read From: David Howells To: linux-cachefs@redhat.com Cc: dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:18:31 +0000 Message-ID: <164692911113.2099075.1060868473229451371.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add a function to do the steps needed to begin a read request, allowing this code to be removed from several other functions and consolidated. Changes =3D=3D=3D=3D=3D=3D=3D ver #2) - Move before the unstaticking patch so that some functions can be left static. - Set uninitialised return code in netfs_begin_read()[1][2]. - Fixed a refleak caused by non-removal of a get from netfs_write_begin() when the request submission code got moved to netfs_begin_read(). - Use INIT_WORK() to (re-)init the request work_struct[3]. Signed-off-by: David Howells cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/20220303163826.1120936-1-nathan@kernel.org/= [1] Link: https://lore.kernel.org/r/20220303235647.1297171-1-colin.i.king@gmail= .com/ [2] Link: https://lore.kernel.org/r/9d69be49081bccff44260e4c6e0049c63d6d04a1.ca= mel@redhat.com/ [3] Link: https://lore.kernel.org/r/164623004355.3564931.7275693529042495641.st= git@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678214287.1200972.16734134007649832160.s= tgit@warthog.procyon.org.uk/ # v2 Reviewed-by: Jeff Layton Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/netfs/internal.h | 2 - fs/netfs/objects.c | 1=20 fs/netfs/read_helper.c | 144 +++++++++++++++++++++-----------------= ---- include/trace/events/netfs.h | 5 + 4 files changed, 76 insertions(+), 76 deletions(-) diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 5f9719409f21..937c2465943f 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -39,7 +39,7 @@ static inline void netfs_see_request(struct netfs_io_requ= est *rreq, */ extern unsigned int netfs_debug; =20 -void netfs_rreq_work(struct work_struct *work); +int netfs_begin_read(struct netfs_io_request *rreq, bool sync); =20 /* * stats.c diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 657b19e60118..e86107b30ba4 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -35,7 +35,6 @@ struct netfs_io_request *netfs_alloc_request(struct addre= ss_space *mapping, rreq->i_size =3D i_size_read(inode); rreq->debug_id =3D atomic_inc_return(&debug_ids); INIT_LIST_HEAD(&rreq->subrequests); - INIT_WORK(&rreq->work, netfs_rreq_work); refcount_set(&rreq->ref, 1); __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); if (rreq->netfs_ops->init_request) { diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index 73be06c409bb..6864716cfcac 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -443,7 +443,7 @@ static void netfs_rreq_assess(struct netfs_io_request *= rreq, bool was_async) netfs_rreq_completed(rreq, was_async); } =20 -void netfs_rreq_work(struct work_struct *work) +static void netfs_rreq_work(struct work_struct *work) { struct netfs_io_request *rreq =3D container_of(work, struct netfs_io_request, work); @@ -688,6 +688,69 @@ static bool netfs_rreq_submit_slice(struct netfs_io_re= quest *rreq, return false; } =20 +/* + * Begin the process of reading in a chunk of data, where that data may be + * stitched together from multiple sources, including multiple servers and= the + * local cache. + */ +int netfs_begin_read(struct netfs_io_request *rreq, bool sync) +{ + unsigned int debug_index =3D 0; + int ret; + + _enter("R=3D%x %llx-%llx", + rreq->debug_id, rreq->start, rreq->start + rreq->len - 1); + + if (rreq->len =3D=3D 0) { + pr_err("Zero-sized read [R=3D%x]\n", rreq->debug_id); + netfs_put_request(rreq, false, netfs_rreq_trace_put_zero_len); + return -EIO; + } + + INIT_WORK(&rreq->work, netfs_rreq_work); + + if (sync) + netfs_get_request(rreq, netfs_rreq_trace_get_hold); + + /* Chop the read into slices according to what the cache and the netfs + * want and submit each one. + */ + atomic_set(&rreq->nr_outstanding, 1); + do { + if (!netfs_rreq_submit_slice(rreq, &debug_index)) + break; + + } while (rreq->submitted < rreq->len); + + if (sync) { + /* Keep nr_outstanding incremented so that the ref always belongs to + * us, and the service code isn't punted off to a random thread pool to + * process. + */ + for (;;) { + wait_var_event(&rreq->nr_outstanding, + atomic_read(&rreq->nr_outstanding) =3D=3D 1); + netfs_rreq_assess(rreq, false); + if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) + break; + cond_resched(); + } + + ret =3D rreq->error; + if (ret =3D=3D 0 && rreq->submitted < rreq->len) { + trace_netfs_failure(rreq, NULL, ret, netfs_fail_short_read); + ret =3D -EIO; + } + netfs_put_request(rreq, false, netfs_rreq_trace_put_hold); + } else { + /* If we decrement nr_outstanding to 0, the ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_outstanding)) + netfs_rreq_assess(rreq, false); + ret =3D 0; + } + return ret; +} + static void netfs_cache_expand_readahead(struct netfs_io_request *rreq, loff_t *_start, size_t *_len, loff_t i_size) { @@ -750,7 +813,6 @@ void netfs_readahead(struct readahead_control *ractl) { struct netfs_io_request *rreq; struct netfs_i_context *ctx =3D netfs_i_context(ractl->mapping->host); - unsigned int debug_index =3D 0; int ret; =20 _enter("%lx,%x", readahead_index(ractl), readahead_count(ractl)); @@ -777,22 +839,13 @@ void netfs_readahead(struct readahead_control *ractl) =20 netfs_rreq_expand(rreq, ractl); =20 - atomic_set(&rreq->nr_outstanding, 1); - do { - if (!netfs_rreq_submit_slice(rreq, &debug_index)) - break; - - } while (rreq->submitted < rreq->len); - /* Drop the refs on the folios here rather than in the cache or * filesystem. The locks will be dropped in netfs_rreq_unlock(). */ while (readahead_folio(ractl)) ; =20 - /* If we decrement nr_outstanding to 0, the ref belongs to us. */ - if (atomic_dec_and_test(&rreq->nr_outstanding)) - netfs_rreq_assess(rreq, false); + netfs_begin_read(rreq, false); return; =20 cleanup_free: @@ -821,7 +874,6 @@ int netfs_readpage(struct file *file, struct page *subp= age) struct address_space *mapping =3D folio->mapping; struct netfs_io_request *rreq; struct netfs_i_context *ctx =3D netfs_i_context(mapping->host); - unsigned int debug_index =3D 0; int ret; =20 _enter("%lx", folio_index(folio)); @@ -836,42 +888,16 @@ int netfs_readpage(struct file *file, struct page *su= bpage) =20 if (ctx->ops->begin_cache_operation) { ret =3D ctx->ops->begin_cache_operation(rreq); - if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) { - folio_unlock(folio); - goto out; - } + if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) + goto discard; } =20 netfs_stat(&netfs_n_rh_readpage); trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage); + return netfs_begin_read(rreq, true); =20 - netfs_get_request(rreq, netfs_rreq_trace_get_hold); - - atomic_set(&rreq->nr_outstanding, 1); - do { - if (!netfs_rreq_submit_slice(rreq, &debug_index)) - break; - - } while (rreq->submitted < rreq->len); - - /* Keep nr_outstanding incremented so that the ref always belongs to us, = and - * the service code isn't punted off to a random thread pool to - * process. - */ - do { - wait_var_event(&rreq->nr_outstanding, - atomic_read(&rreq->nr_outstanding) =3D=3D 1); - netfs_rreq_assess(rreq, false); - } while (test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)); - - ret =3D rreq->error; - if (ret =3D=3D 0 && rreq->submitted < rreq->len) { - trace_netfs_failure(rreq, NULL, ret, netfs_fail_short_readpage); - ret =3D -EIO; - } -out: - netfs_put_request(rreq, false, netfs_rreq_trace_put_hold); - return ret; +discard: + netfs_put_request(rreq, false, netfs_rreq_trace_put_discard); alloc_error: folio_unlock(folio); return ret; @@ -966,7 +992,7 @@ int netfs_write_begin(struct file *file, struct address= _space *mapping, struct netfs_io_request *rreq; struct netfs_i_context *ctx =3D netfs_i_context(file_inode(file )); struct folio *folio; - unsigned int debug_index =3D 0, fgp_flags; + unsigned int fgp_flags; pgoff_t index =3D pos >> PAGE_SHIFT; int ret; =20 @@ -1029,39 +1055,13 @@ int netfs_write_begin(struct file *file, struct add= ress_space *mapping, */ ractl._nr_pages =3D folio_nr_pages(folio); netfs_rreq_expand(rreq, &ractl); - netfs_get_request(rreq, netfs_rreq_trace_get_hold); =20 /* We hold the folio locks, so we can drop the references */ folio_get(folio); while (readahead_folio(&ractl)) ; =20 - atomic_set(&rreq->nr_outstanding, 1); - do { - if (!netfs_rreq_submit_slice(rreq, &debug_index)) - break; - - } while (rreq->submitted < rreq->len); - - /* Keep nr_outstanding incremented so that the ref always belongs to - * us, and the service code isn't punted off to a random thread pool to - * process. - */ - for (;;) { - wait_var_event(&rreq->nr_outstanding, - atomic_read(&rreq->nr_outstanding) =3D=3D 1); - netfs_rreq_assess(rreq, false); - if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) - break; - cond_resched(); - } - - ret =3D rreq->error; - if (ret =3D=3D 0 && rreq->submitted < rreq->len) { - trace_netfs_failure(rreq, NULL, ret, netfs_fail_short_write_begin); - ret =3D -EIO; - } - netfs_put_request(rreq, false, netfs_rreq_trace_put_hold); + ret =3D netfs_begin_read(rreq, true); if (ret < 0) goto error; =20 diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index f00e3e1821c8..beec534cbaab 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -56,17 +56,18 @@ EM(netfs_fail_check_write_begin, "check-write-begin") \ EM(netfs_fail_copy_to_cache, "copy-to-cache") \ EM(netfs_fail_read, "read") \ - EM(netfs_fail_short_readpage, "short-readpage") \ - EM(netfs_fail_short_write_begin, "short-write-begin") \ + EM(netfs_fail_short_read, "short-read") \ E_(netfs_fail_prepare_write, "prep-write") =20 #define netfs_rreq_ref_traces \ EM(netfs_rreq_trace_get_hold, "GET HOLD ") \ EM(netfs_rreq_trace_get_subreq, "GET SUBREQ ") \ EM(netfs_rreq_trace_put_complete, "PUT COMPLT ") \ + EM(netfs_rreq_trace_put_discard, "PUT DISCARD") \ EM(netfs_rreq_trace_put_failed, "PUT FAILED ") \ EM(netfs_rreq_trace_put_hold, "PUT HOLD ") \ EM(netfs_rreq_trace_put_subreq, "PUT SUBREQ ") \ + EM(netfs_rreq_trace_put_zero_len, "PUT ZEROLEN") \ E_(netfs_rreq_trace_new, "NEW ") =20 #define netfs_sreq_ref_traces \ From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0A6E7C433EF for ; Thu, 10 Mar 2022 16:21:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242456AbiCJQWP (ORCPT ); Thu, 10 Mar 2022 11:22:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42144 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243413AbiCJQV2 (ORCPT ); Thu, 10 Mar 2022 11:21:28 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B555819142E for ; Thu, 10 Mar 2022 08:19:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929183; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EVBPDsgUrkmnW1iIuL47y+dS63RMYVXBGzQs9vGVOQM=; b=GRszjRCye2BkgThwCrXNX4JLYD4N4ECJoUK4kDcFHz0qB/efJbau6nlJTulhS1u0vT/Z3x hzsQZjCeBN9vfe27lgC9Ci8DXPWXzqNPrpK8Nbd/x4rPzfZAyxmOi+kKBhaynoVeNMdNOx bmOAbwygf1ym2rgrBzxsfed5NouTWDY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-339-JkUy8IYoPAWIMjR5r2EPow-1; Thu, 10 Mar 2022 11:19:37 -0500 X-MC-Unique: JkUy8IYoPAWIMjR5r2EPow-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 853EF51E6; Thu, 10 Mar 2022 16:19:35 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id EFD8B838DA; Thu, 10 Mar 2022 16:18:47 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 15/20] netfs: Prepare to split read_helper.c From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:18:47 +0000 Message-ID: <164692912709.2099075.4349905992838317797.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Rename netfs_rreq_unlock() to netfs_rreq_unlock_folios() to make it sound less like it's dropping a lock on an netfs_io_request struct. Remove the 'static' marker on netfs_rreq_unlock_folios() and declaring it in internal.h preparatory to splitting the file. Changes =3D=3D=3D=3D=3D=3D=3D ver #2) - Slide this patch to after the one adding netfs_begin_read(). - As a consequence, don't need to unstatic so many functions. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164623002861.3564931.17340149482236413375.s= tgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678215208.1200972.9761906209395002182.st= git@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/netfs/internal.h | 5 +++++ fs/netfs/read_helper.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 937c2465943f..11c0c9ef9299 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -15,6 +15,11 @@ =20 #define pr_fmt(fmt) "netfs: " fmt =20 +/* + * buffered_read.c + */ +void netfs_rreq_unlock_folios(struct netfs_io_request *rreq); + /* * objects.c */ diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index 6864716cfcac..d448dc4f1010 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -250,7 +250,7 @@ static void netfs_rreq_write_to_cache(struct netfs_io_r= equest *rreq) * Unlock the folios in a read operation. We need to set PG_fscache on any * folios we're going to write back before we unlock them. */ -static void netfs_rreq_unlock(struct netfs_io_request *rreq) +void netfs_rreq_unlock_folios(struct netfs_io_request *rreq) { struct netfs_io_subrequest *subreq; struct folio *folio; @@ -432,7 +432,7 @@ static void netfs_rreq_assess(struct netfs_io_request *= rreq, bool was_async) return; } =20 - netfs_rreq_unlock(rreq); + netfs_rreq_unlock_folios(rreq); =20 clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &rreq->flags); wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS); From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9905FC43219 for ; Thu, 10 Mar 2022 16:21:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243878AbiCJQW3 (ORCPT ); Thu, 10 Mar 2022 11:22:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39564 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243120AbiCJQWI (ORCPT ); Thu, 10 Mar 2022 11:22:08 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 7ACE5197B7E for ; Thu, 10 Mar 2022 08:19:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929198; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=25XiMvaw3SfDAHc+xhjMQ5KfAgC9ZZA74BDkj4paP7g=; b=dwRX9H3NsOLtBkGlgB2OCpE+JNO+Sz7ammzLPuQ7ehr90bmEU9ziHyYTEF2wx7JOPlorUx pKr8/glku6f+5eHDU2YW95lX2Jx6hf7c4c9n6kRMTyJpvWPmW1Ubzp/kRuyl6nRYZg0w/S 0tfAWrI9TjNNPRVyUsfP8Aq9lMaIStA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-564-ZaPTBmVsNwKFEXjMKyTKFQ-1; Thu, 10 Mar 2022 11:19:56 -0500 X-MC-Unique: ZaPTBmVsNwKFEXjMKyTKFQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4D4B9180FD74; Thu, 10 Mar 2022 16:19:54 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id A61B6106D5D1; Thu, 10 Mar 2022 16:19:41 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 16/20] netfs: Rename read_helper.c to io.c From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:19:40 +0000 Message-ID: <164692918076.2099075.8120961172717347610.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Rename the read_helper.c file to io.c before splitting out the buffered read functions and some other bits. Changes =3D=3D=3D=3D=3D=3D=3D ver #2) - Rename read_helper.c before splitting. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164678216109.1200972.16567696909952495832.s= tgit@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- Documentation/filesystems/netfs_library.rst | 3=20 fs/netfs/Makefile | 4=20 fs/netfs/internal.h | 14=20 fs/netfs/io.c | 1085 +++++++++++++++++++++++= ++++ fs/netfs/read_helper.c | 1085 -----------------------= ---- 5 files changed, 1096 insertions(+), 1095 deletions(-) create mode 100644 fs/netfs/io.c delete mode 100644 fs/netfs/read_helper.c diff --git a/Documentation/filesystems/netfs_library.rst b/Documentation/fi= lesystems/netfs_library.rst index 9c8bc5666b46..69f00179fdfe 100644 --- a/Documentation/filesystems/netfs_library.rst +++ b/Documentation/filesystems/netfs_library.rst @@ -605,4 +605,5 @@ API Function Reference =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 .. kernel-doc:: include/linux/netfs.h -.. kernel-doc:: fs/netfs/read_helper.c +.. kernel-doc:: fs/netfs/buffered_read.c +.. kernel-doc:: fs/netfs/io.c diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index 939fd00a1fc9..51ece4f7bc77 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 =20 netfs-y :=3D \ - objects.o \ - read_helper.o + io.o \ + objects.o =20 netfs-$(CONFIG_NETFS_STATS) +=3D stats.o =20 diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 11c0c9ef9299..1cd2778bfa7d 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -20,6 +20,13 @@ */ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq); =20 +/* + * io.c + */ +extern unsigned int netfs_debug; + +int netfs_begin_read(struct netfs_io_request *rreq, bool sync); + /* * objects.c */ @@ -39,13 +46,6 @@ static inline void netfs_see_request(struct netfs_io_req= uest *rreq, trace_netfs_rreq_ref(rreq->debug_id, refcount_read(&rreq->ref), what); } =20 -/* - * read_helper.c - */ -extern unsigned int netfs_debug; - -int netfs_begin_read(struct netfs_io_request *rreq, bool sync); - /* * stats.c */ diff --git a/fs/netfs/io.c b/fs/netfs/io.c new file mode 100644 index 000000000000..d448dc4f1010 --- /dev/null +++ b/fs/netfs/io.c @@ -0,0 +1,1085 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Network filesystem high-level read support. + * + * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" +#define CREATE_TRACE_POINTS +#include + +MODULE_DESCRIPTION("Network fs support"); +MODULE_AUTHOR("Red Hat, Inc."); +MODULE_LICENSE("GPL"); + +unsigned netfs_debug; +module_param_named(debug, netfs_debug, uint, S_IWUSR | S_IRUGO); +MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask"); + +/* + * Clear the unread part of an I/O request. + */ +static void netfs_clear_unread(struct netfs_io_subrequest *subreq) +{ + struct iov_iter iter; + + iov_iter_xarray(&iter, READ, &subreq->rreq->mapping->i_pages, + subreq->start + subreq->transferred, + subreq->len - subreq->transferred); + iov_iter_zero(iov_iter_count(&iter), &iter); +} + +static void netfs_cache_read_terminated(void *priv, ssize_t transferred_or= _error, + bool was_async) +{ + struct netfs_io_subrequest *subreq =3D priv; + + netfs_subreq_terminated(subreq, transferred_or_error, was_async); +} + +/* + * Issue a read against the cache. + * - Eats the caller's ref on subreq. + */ +static void netfs_read_from_cache(struct netfs_io_request *rreq, + struct netfs_io_subrequest *subreq, + enum netfs_read_from_hole read_hole) +{ + struct netfs_cache_resources *cres =3D &rreq->cache_resources; + struct iov_iter iter; + + netfs_stat(&netfs_n_rh_read); + iov_iter_xarray(&iter, READ, &rreq->mapping->i_pages, + subreq->start + subreq->transferred, + subreq->len - subreq->transferred); + + cres->ops->read(cres, subreq->start, &iter, read_hole, + netfs_cache_read_terminated, subreq); +} + +/* + * Fill a subrequest region with zeroes. + */ +static void netfs_fill_with_zeroes(struct netfs_io_request *rreq, + struct netfs_io_subrequest *subreq) +{ + netfs_stat(&netfs_n_rh_zero); + __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); + netfs_subreq_terminated(subreq, 0, false); +} + +/* + * Ask the netfs to issue a read request to the server for us. + * + * The netfs is expected to read from subreq->pos + subreq->transferred to + * subreq->pos + subreq->len - 1. It may not backtrack and write data int= o the + * buffer prior to the transferred point as it might clobber dirty data + * obtained from the cache. + * + * Alternatively, the netfs is allowed to indicate one of two things: + * + * - NETFS_SREQ_SHORT_READ: A short read - it will get called again to try= and + * make progress. + * + * - NETFS_SREQ_CLEAR_TAIL: A short read - the rest of the buffer will be + * cleared. + */ +static void netfs_read_from_server(struct netfs_io_request *rreq, + struct netfs_io_subrequest *subreq) +{ + netfs_stat(&netfs_n_rh_download); + rreq->netfs_ops->issue_read(subreq); +} + +/* + * Release those waiting. + */ +static void netfs_rreq_completed(struct netfs_io_request *rreq, bool was_a= sync) +{ + trace_netfs_rreq(rreq, netfs_rreq_trace_done); + netfs_clear_subrequests(rreq, was_async); + netfs_put_request(rreq, was_async, netfs_rreq_trace_put_complete); +} + +/* + * Deal with the completion of writing the data to the cache. We have to = clear + * the PG_fscache bits on the folios involved and release the caller's ref. + * + * May be called in softirq mode and we inherit a ref from the caller. + */ +static void netfs_rreq_unmark_after_write(struct netfs_io_request *rreq, + bool was_async) +{ + struct netfs_io_subrequest *subreq; + struct folio *folio; + pgoff_t unlocked =3D 0; + bool have_unlocked =3D false; + + rcu_read_lock(); + + list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { + XA_STATE(xas, &rreq->mapping->i_pages, subreq->start / PAGE_SIZE); + + xas_for_each(&xas, folio, (subreq->start + subreq->len - 1) / PAGE_SIZE)= { + /* We might have multiple writes from the same huge + * folio, but we mustn't unlock a folio more than once. + */ + if (have_unlocked && folio_index(folio) <=3D unlocked) + continue; + unlocked =3D folio_index(folio); + folio_end_fscache(folio); + have_unlocked =3D true; + } + } + + rcu_read_unlock(); + netfs_rreq_completed(rreq, was_async); +} + +static void netfs_rreq_copy_terminated(void *priv, ssize_t transferred_or_= error, + bool was_async) +{ + struct netfs_io_subrequest *subreq =3D priv; + struct netfs_io_request *rreq =3D subreq->rreq; + + if (IS_ERR_VALUE(transferred_or_error)) { + netfs_stat(&netfs_n_rh_write_failed); + trace_netfs_failure(rreq, subreq, transferred_or_error, + netfs_fail_copy_to_cache); + } else { + netfs_stat(&netfs_n_rh_write_done); + } + + trace_netfs_sreq(subreq, netfs_sreq_trace_write_term); + + /* If we decrement nr_copy_ops to 0, the ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_copy_ops)) + netfs_rreq_unmark_after_write(rreq, was_async); + + netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated); +} + +/* + * Perform any outstanding writes to the cache. We inherit a ref from the + * caller. + */ +static void netfs_rreq_do_write_to_cache(struct netfs_io_request *rreq) +{ + struct netfs_cache_resources *cres =3D &rreq->cache_resources; + struct netfs_io_subrequest *subreq, *next, *p; + struct iov_iter iter; + int ret; + + trace_netfs_rreq(rreq, netfs_rreq_trace_copy); + + /* We don't want terminating writes trying to wake us up whilst we're + * still going through the list. + */ + atomic_inc(&rreq->nr_copy_ops); + + list_for_each_entry_safe(subreq, p, &rreq->subrequests, rreq_link) { + if (!test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) { + list_del_init(&subreq->rreq_link); + netfs_put_subrequest(subreq, false, + netfs_sreq_trace_put_no_copy); + } + } + + list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { + /* Amalgamate adjacent writes */ + while (!list_is_last(&subreq->rreq_link, &rreq->subrequests)) { + next =3D list_next_entry(subreq, rreq_link); + if (next->start !=3D subreq->start + subreq->len) + break; + subreq->len +=3D next->len; + list_del_init(&next->rreq_link); + netfs_put_subrequest(next, false, + netfs_sreq_trace_put_merged); + } + + ret =3D cres->ops->prepare_write(cres, &subreq->start, &subreq->len, + rreq->i_size, true); + if (ret < 0) { + trace_netfs_failure(rreq, subreq, ret, netfs_fail_prepare_write); + trace_netfs_sreq(subreq, netfs_sreq_trace_write_skip); + continue; + } + + iov_iter_xarray(&iter, WRITE, &rreq->mapping->i_pages, + subreq->start, subreq->len); + + atomic_inc(&rreq->nr_copy_ops); + netfs_stat(&netfs_n_rh_write); + netfs_get_subrequest(subreq, netfs_sreq_trace_get_copy_to_cache); + trace_netfs_sreq(subreq, netfs_sreq_trace_write); + cres->ops->write(cres, subreq->start, &iter, + netfs_rreq_copy_terminated, subreq); + } + + /* If we decrement nr_copy_ops to 0, the usage ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_copy_ops)) + netfs_rreq_unmark_after_write(rreq, false); +} + +static void netfs_rreq_write_to_cache_work(struct work_struct *work) +{ + struct netfs_io_request *rreq =3D + container_of(work, struct netfs_io_request, work); + + netfs_rreq_do_write_to_cache(rreq); +} + +static void netfs_rreq_write_to_cache(struct netfs_io_request *rreq) +{ + rreq->work.func =3D netfs_rreq_write_to_cache_work; + if (!queue_work(system_unbound_wq, &rreq->work)) + BUG(); +} + +/* + * Unlock the folios in a read operation. We need to set PG_fscache on any + * folios we're going to write back before we unlock them. + */ +void netfs_rreq_unlock_folios(struct netfs_io_request *rreq) +{ + struct netfs_io_subrequest *subreq; + struct folio *folio; + unsigned int iopos, account =3D 0; + pgoff_t start_page =3D rreq->start / PAGE_SIZE; + pgoff_t last_page =3D ((rreq->start + rreq->len) / PAGE_SIZE) - 1; + bool subreq_failed =3D false; + + XA_STATE(xas, &rreq->mapping->i_pages, start_page); + + if (test_bit(NETFS_RREQ_FAILED, &rreq->flags)) { + __clear_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags); + list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { + __clear_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); + } + } + + /* Walk through the pagecache and the I/O request lists simultaneously. + * We may have a mixture of cached and uncached sections and we only + * really want to write out the uncached sections. This is slightly + * complicated by the possibility that we might have huge pages with a + * mixture inside. + */ + subreq =3D list_first_entry(&rreq->subrequests, + struct netfs_io_subrequest, rreq_link); + iopos =3D 0; + subreq_failed =3D (subreq->error < 0); + + trace_netfs_rreq(rreq, netfs_rreq_trace_unlock); + + rcu_read_lock(); + xas_for_each(&xas, folio, last_page) { + unsigned int pgpos =3D (folio_index(folio) - start_page) * PAGE_SIZE; + unsigned int pgend =3D pgpos + folio_size(folio); + bool pg_failed =3D false; + + for (;;) { + if (!subreq) { + pg_failed =3D true; + break; + } + if (test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) + folio_start_fscache(folio); + pg_failed |=3D subreq_failed; + if (pgend < iopos + subreq->len) + break; + + account +=3D subreq->transferred; + iopos +=3D subreq->len; + if (!list_is_last(&subreq->rreq_link, &rreq->subrequests)) { + subreq =3D list_next_entry(subreq, rreq_link); + subreq_failed =3D (subreq->error < 0); + } else { + subreq =3D NULL; + subreq_failed =3D false; + } + if (pgend =3D=3D iopos) + break; + } + + if (!pg_failed) { + flush_dcache_folio(folio); + folio_mark_uptodate(folio); + } + + if (!test_bit(NETFS_RREQ_DONT_UNLOCK_FOLIOS, &rreq->flags)) { + if (folio_index(folio) =3D=3D rreq->no_unlock_folio && + test_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags)) + _debug("no unlock"); + else + folio_unlock(folio); + } + } + rcu_read_unlock(); + + task_io_account_read(account); + if (rreq->netfs_ops->done) + rreq->netfs_ops->done(rreq); +} + +/* + * Handle a short read. + */ +static void netfs_rreq_short_read(struct netfs_io_request *rreq, + struct netfs_io_subrequest *subreq) +{ + __clear_bit(NETFS_SREQ_SHORT_IO, &subreq->flags); + __set_bit(NETFS_SREQ_SEEK_DATA_READ, &subreq->flags); + + netfs_stat(&netfs_n_rh_short_read); + trace_netfs_sreq(subreq, netfs_sreq_trace_resubmit_short); + + netfs_get_subrequest(subreq, netfs_sreq_trace_get_short_read); + atomic_inc(&rreq->nr_outstanding); + if (subreq->source =3D=3D NETFS_READ_FROM_CACHE) + netfs_read_from_cache(rreq, subreq, NETFS_READ_HOLE_CLEAR); + else + netfs_read_from_server(rreq, subreq); +} + +/* + * Resubmit any short or failed operations. Returns true if we got the rr= eq + * ref back. + */ +static bool netfs_rreq_perform_resubmissions(struct netfs_io_request *rreq) +{ + struct netfs_io_subrequest *subreq; + + WARN_ON(in_interrupt()); + + trace_netfs_rreq(rreq, netfs_rreq_trace_resubmit); + + /* We don't want terminating submissions trying to wake us up whilst + * we're still going through the list. + */ + atomic_inc(&rreq->nr_outstanding); + + __clear_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags); + list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { + if (subreq->error) { + if (subreq->source !=3D NETFS_READ_FROM_CACHE) + break; + subreq->source =3D NETFS_DOWNLOAD_FROM_SERVER; + subreq->error =3D 0; + netfs_stat(&netfs_n_rh_download_instead); + trace_netfs_sreq(subreq, netfs_sreq_trace_download_instead); + netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); + atomic_inc(&rreq->nr_outstanding); + netfs_read_from_server(rreq, subreq); + } else if (test_bit(NETFS_SREQ_SHORT_IO, &subreq->flags)) { + netfs_rreq_short_read(rreq, subreq); + } + } + + /* If we decrement nr_outstanding to 0, the usage ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_outstanding)) + return true; + + wake_up_var(&rreq->nr_outstanding); + return false; +} + +/* + * Check to see if the data read is still valid. + */ +static void netfs_rreq_is_still_valid(struct netfs_io_request *rreq) +{ + struct netfs_io_subrequest *subreq; + + if (!rreq->netfs_ops->is_still_valid || + rreq->netfs_ops->is_still_valid(rreq)) + return; + + list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { + if (subreq->source =3D=3D NETFS_READ_FROM_CACHE) { + subreq->error =3D -ESTALE; + __set_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags); + } + } +} + +/* + * Assess the state of a read request and decide what to do next. + * + * Note that we could be in an ordinary kernel thread, on a workqueue or in + * softirq context at this point. We inherit a ref from the caller. + */ +static void netfs_rreq_assess(struct netfs_io_request *rreq, bool was_asyn= c) +{ + trace_netfs_rreq(rreq, netfs_rreq_trace_assess); + +again: + netfs_rreq_is_still_valid(rreq); + + if (!test_bit(NETFS_RREQ_FAILED, &rreq->flags) && + test_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags)) { + if (netfs_rreq_perform_resubmissions(rreq)) + goto again; + return; + } + + netfs_rreq_unlock_folios(rreq); + + clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &rreq->flags); + wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS); + + if (test_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags)) + return netfs_rreq_write_to_cache(rreq); + + netfs_rreq_completed(rreq, was_async); +} + +static void netfs_rreq_work(struct work_struct *work) +{ + struct netfs_io_request *rreq =3D + container_of(work, struct netfs_io_request, work); + netfs_rreq_assess(rreq, false); +} + +/* + * Handle the completion of all outstanding I/O operations on a read reque= st. + * We inherit a ref from the caller. + */ +static void netfs_rreq_terminated(struct netfs_io_request *rreq, + bool was_async) +{ + if (test_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags) && + was_async) { + if (!queue_work(system_unbound_wq, &rreq->work)) + BUG(); + } else { + netfs_rreq_assess(rreq, was_async); + } +} + +/** + * netfs_subreq_terminated - Note the termination of an I/O operation. + * @subreq: The I/O request that has terminated. + * @transferred_or_error: The amount of data transferred or an error code. + * @was_async: The termination was asynchronous + * + * This tells the read helper that a contributory I/O operation has termin= ated, + * one way or another, and that it should integrate the results. + * + * The caller indicates in @transferred_or_error the outcome of the operat= ion, + * supplying a positive value to indicate the number of bytes transferred,= 0 to + * indicate a failure to transfer anything that should be retried or a neg= ative + * error code. The helper will look after reissuing I/O operations as + * appropriate and writing downloaded data to the cache. + * + * If @was_async is true, the caller might be running in softirq or interr= upt + * context and we can't sleep. + */ +void netfs_subreq_terminated(struct netfs_io_subrequest *subreq, + ssize_t transferred_or_error, + bool was_async) +{ + struct netfs_io_request *rreq =3D subreq->rreq; + int u; + + _enter("[%u]{%llx,%lx},%zd", + subreq->debug_index, subreq->start, subreq->flags, + transferred_or_error); + + switch (subreq->source) { + case NETFS_READ_FROM_CACHE: + netfs_stat(&netfs_n_rh_read_done); + break; + case NETFS_DOWNLOAD_FROM_SERVER: + netfs_stat(&netfs_n_rh_download_done); + break; + default: + break; + } + + if (IS_ERR_VALUE(transferred_or_error)) { + subreq->error =3D transferred_or_error; + trace_netfs_failure(rreq, subreq, transferred_or_error, + netfs_fail_read); + goto failed; + } + + if (WARN(transferred_or_error > subreq->len - subreq->transferred, + "Subreq overread: R%x[%x] %zd > %zu - %zu", + rreq->debug_id, subreq->debug_index, + transferred_or_error, subreq->len, subreq->transferred)) + transferred_or_error =3D subreq->len - subreq->transferred; + + subreq->error =3D 0; + subreq->transferred +=3D transferred_or_error; + if (subreq->transferred < subreq->len) + goto incomplete; + +complete: + __clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags); + if (test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) + set_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags); + +out: + trace_netfs_sreq(subreq, netfs_sreq_trace_terminated); + + /* If we decrement nr_outstanding to 0, the ref belongs to us. */ + u =3D atomic_dec_return(&rreq->nr_outstanding); + if (u =3D=3D 0) + netfs_rreq_terminated(rreq, was_async); + else if (u =3D=3D 1) + wake_up_var(&rreq->nr_outstanding); + + netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated); + return; + +incomplete: + if (test_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags)) { + netfs_clear_unread(subreq); + subreq->transferred =3D subreq->len; + goto complete; + } + + if (transferred_or_error =3D=3D 0) { + if (__test_and_set_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags)) { + subreq->error =3D -ENODATA; + goto failed; + } + } else { + __clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags); + } + + __set_bit(NETFS_SREQ_SHORT_IO, &subreq->flags); + set_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags); + goto out; + +failed: + if (subreq->source =3D=3D NETFS_READ_FROM_CACHE) { + netfs_stat(&netfs_n_rh_read_failed); + set_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags); + } else { + netfs_stat(&netfs_n_rh_download_failed); + set_bit(NETFS_RREQ_FAILED, &rreq->flags); + rreq->error =3D subreq->error; + } + goto out; +} +EXPORT_SYMBOL(netfs_subreq_terminated); + +static enum netfs_io_source netfs_cache_prepare_read(struct netfs_io_subre= quest *subreq, + loff_t i_size) +{ + struct netfs_io_request *rreq =3D subreq->rreq; + struct netfs_cache_resources *cres =3D &rreq->cache_resources; + + if (cres->ops) + return cres->ops->prepare_read(subreq, i_size); + if (subreq->start >=3D rreq->i_size) + return NETFS_FILL_WITH_ZEROES; + return NETFS_DOWNLOAD_FROM_SERVER; +} + +/* + * Work out what sort of subrequest the next one will be. + */ +static enum netfs_io_source +netfs_rreq_prepare_read(struct netfs_io_request *rreq, + struct netfs_io_subrequest *subreq) +{ + enum netfs_io_source source; + + _enter("%llx-%llx,%llx", subreq->start, subreq->start + subreq->len, rreq= ->i_size); + + source =3D netfs_cache_prepare_read(subreq, rreq->i_size); + if (source =3D=3D NETFS_INVALID_READ) + goto out; + + if (source =3D=3D NETFS_DOWNLOAD_FROM_SERVER) { + /* Call out to the netfs to let it shrink the request to fit + * its own I/O sizes and boundaries. If it shinks it here, it + * will be called again to make simultaneous calls; if it wants + * to make serial calls, it can indicate a short read and then + * we will call it again. + */ + if (subreq->len > rreq->i_size - subreq->start) + subreq->len =3D rreq->i_size - subreq->start; + + if (rreq->netfs_ops->clamp_length && + !rreq->netfs_ops->clamp_length(subreq)) { + source =3D NETFS_INVALID_READ; + goto out; + } + } + + if (WARN_ON(subreq->len =3D=3D 0)) + source =3D NETFS_INVALID_READ; + +out: + subreq->source =3D source; + trace_netfs_sreq(subreq, netfs_sreq_trace_prepare); + return source; +} + +/* + * Slice off a piece of a read request and submit an I/O request for it. + */ +static bool netfs_rreq_submit_slice(struct netfs_io_request *rreq, + unsigned int *_debug_index) +{ + struct netfs_io_subrequest *subreq; + enum netfs_io_source source; + + subreq =3D netfs_alloc_subrequest(rreq); + if (!subreq) + return false; + + subreq->debug_index =3D (*_debug_index)++; + subreq->start =3D rreq->start + rreq->submitted; + subreq->len =3D rreq->len - rreq->submitted; + + _debug("slice %llx,%zx,%zx", subreq->start, subreq->len, rreq->submitted); + list_add_tail(&subreq->rreq_link, &rreq->subrequests); + + /* Call out to the cache to find out what it can do with the remaining + * subset. It tells us in subreq->flags what it decided should be done + * and adjusts subreq->len down if the subset crosses a cache boundary. + * + * Then when we hand the subset, it can choose to take a subset of that + * (the starts must coincide), in which case, we go around the loop + * again and ask it to download the next piece. + */ + source =3D netfs_rreq_prepare_read(rreq, subreq); + if (source =3D=3D NETFS_INVALID_READ) + goto subreq_failed; + + atomic_inc(&rreq->nr_outstanding); + + rreq->submitted +=3D subreq->len; + + trace_netfs_sreq(subreq, netfs_sreq_trace_submit); + switch (source) { + case NETFS_FILL_WITH_ZEROES: + netfs_fill_with_zeroes(rreq, subreq); + break; + case NETFS_DOWNLOAD_FROM_SERVER: + netfs_read_from_server(rreq, subreq); + break; + case NETFS_READ_FROM_CACHE: + netfs_read_from_cache(rreq, subreq, NETFS_READ_HOLE_IGNORE); + break; + default: + BUG(); + } + + return true; + +subreq_failed: + rreq->error =3D subreq->error; + netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_failed); + return false; +} + +/* + * Begin the process of reading in a chunk of data, where that data may be + * stitched together from multiple sources, including multiple servers and= the + * local cache. + */ +int netfs_begin_read(struct netfs_io_request *rreq, bool sync) +{ + unsigned int debug_index =3D 0; + int ret; + + _enter("R=3D%x %llx-%llx", + rreq->debug_id, rreq->start, rreq->start + rreq->len - 1); + + if (rreq->len =3D=3D 0) { + pr_err("Zero-sized read [R=3D%x]\n", rreq->debug_id); + netfs_put_request(rreq, false, netfs_rreq_trace_put_zero_len); + return -EIO; + } + + INIT_WORK(&rreq->work, netfs_rreq_work); + + if (sync) + netfs_get_request(rreq, netfs_rreq_trace_get_hold); + + /* Chop the read into slices according to what the cache and the netfs + * want and submit each one. + */ + atomic_set(&rreq->nr_outstanding, 1); + do { + if (!netfs_rreq_submit_slice(rreq, &debug_index)) + break; + + } while (rreq->submitted < rreq->len); + + if (sync) { + /* Keep nr_outstanding incremented so that the ref always belongs to + * us, and the service code isn't punted off to a random thread pool to + * process. + */ + for (;;) { + wait_var_event(&rreq->nr_outstanding, + atomic_read(&rreq->nr_outstanding) =3D=3D 1); + netfs_rreq_assess(rreq, false); + if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) + break; + cond_resched(); + } + + ret =3D rreq->error; + if (ret =3D=3D 0 && rreq->submitted < rreq->len) { + trace_netfs_failure(rreq, NULL, ret, netfs_fail_short_read); + ret =3D -EIO; + } + netfs_put_request(rreq, false, netfs_rreq_trace_put_hold); + } else { + /* If we decrement nr_outstanding to 0, the ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_outstanding)) + netfs_rreq_assess(rreq, false); + ret =3D 0; + } + return ret; +} + +static void netfs_cache_expand_readahead(struct netfs_io_request *rreq, + loff_t *_start, size_t *_len, loff_t i_size) +{ + struct netfs_cache_resources *cres =3D &rreq->cache_resources; + + if (cres->ops && cres->ops->expand_readahead) + cres->ops->expand_readahead(cres, _start, _len, i_size); +} + +static void netfs_rreq_expand(struct netfs_io_request *rreq, + struct readahead_control *ractl) +{ + /* Give the cache a chance to change the request parameters. The + * resultant request must contain the original region. + */ + netfs_cache_expand_readahead(rreq, &rreq->start, &rreq->len, rreq->i_size= ); + + /* Give the netfs a chance to change the request parameters. The + * resultant request must contain the original region. + */ + if (rreq->netfs_ops->expand_readahead) + rreq->netfs_ops->expand_readahead(rreq); + + /* Expand the request if the cache wants it to start earlier. Note + * that the expansion may get further extended if the VM wishes to + * insert THPs and the preferred start and/or end wind up in the middle + * of THPs. + * + * If this is the case, however, the THP size should be an integer + * multiple of the cache granule size, so we get a whole number of + * granules to deal with. + */ + if (rreq->start !=3D readahead_pos(ractl) || + rreq->len !=3D readahead_length(ractl)) { + readahead_expand(ractl, rreq->start, rreq->len); + rreq->start =3D readahead_pos(ractl); + rreq->len =3D readahead_length(ractl); + + trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl), + netfs_read_trace_expanded); + } +} + +/** + * netfs_readahead - Helper to manage a read request + * @ractl: The description of the readahead request + * + * Fulfil a readahead request by drawing data from the cache if possible, = or + * the netfs if not. Space beyond the EOF is zero-filled. Multiple I/O + * requests from different sources will get munged together. If necessary= , the + * readahead window can be expanded in either direction to a more convenie= nt + * alighment for RPC efficiency or to make storage in the cache feasible. + * + * The calling netfs must initialise a netfs context contiguous to the vfs + * inode before calling this. + * + * This is usable whether or not caching is enabled. + */ +void netfs_readahead(struct readahead_control *ractl) +{ + struct netfs_io_request *rreq; + struct netfs_i_context *ctx =3D netfs_i_context(ractl->mapping->host); + int ret; + + _enter("%lx,%x", readahead_index(ractl), readahead_count(ractl)); + + if (readahead_count(ractl) =3D=3D 0) + return; + + rreq =3D netfs_alloc_request(ractl->mapping, ractl->file, + readahead_pos(ractl), + readahead_length(ractl), + NETFS_READAHEAD); + if (IS_ERR(rreq)) + return; + + if (ctx->ops->begin_cache_operation) { + ret =3D ctx->ops->begin_cache_operation(rreq); + if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) + goto cleanup_free; + } + + netfs_stat(&netfs_n_rh_readahead); + trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl), + netfs_read_trace_readahead); + + netfs_rreq_expand(rreq, ractl); + + /* Drop the refs on the folios here rather than in the cache or + * filesystem. The locks will be dropped in netfs_rreq_unlock(). + */ + while (readahead_folio(ractl)) + ; + + netfs_begin_read(rreq, false); + return; + +cleanup_free: + netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); + return; +} +EXPORT_SYMBOL(netfs_readahead); + +/** + * netfs_readpage - Helper to manage a readpage request + * @file: The file to read from + * @subpage: A subpage of the folio to read + * + * Fulfil a readpage request by drawing data from the cache if possible, o= r the + * netfs if not. Space beyond the EOF is zero-filled. Multiple I/O reque= sts + * from different sources will get munged together. + * + * The calling netfs must initialise a netfs context contiguous to the vfs + * inode before calling this. + * + * This is usable whether or not caching is enabled. + */ +int netfs_readpage(struct file *file, struct page *subpage) +{ + struct folio *folio =3D page_folio(subpage); + struct address_space *mapping =3D folio->mapping; + struct netfs_io_request *rreq; + struct netfs_i_context *ctx =3D netfs_i_context(mapping->host); + int ret; + + _enter("%lx", folio_index(folio)); + + rreq =3D netfs_alloc_request(mapping, file, + folio_file_pos(folio), folio_size(folio), + NETFS_READPAGE); + if (IS_ERR(rreq)) { + ret =3D PTR_ERR(rreq); + goto alloc_error; + } + + if (ctx->ops->begin_cache_operation) { + ret =3D ctx->ops->begin_cache_operation(rreq); + if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) + goto discard; + } + + netfs_stat(&netfs_n_rh_readpage); + trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage); + return netfs_begin_read(rreq, true); + +discard: + netfs_put_request(rreq, false, netfs_rreq_trace_put_discard); +alloc_error: + folio_unlock(folio); + return ret; +} +EXPORT_SYMBOL(netfs_readpage); + +/* + * Prepare a folio for writing without reading first + * @folio: The folio being prepared + * @pos: starting position for the write + * @len: length of write + * @always_fill: T if the folio should always be completely filled/cleared + * + * In some cases, write_begin doesn't need to read at all: + * - full folio write + * - write that lies in a folio that is completely beyond EOF + * - write that covers the folio from start to EOF or beyond it + * + * If any of these criteria are met, then zero out the unwritten parts + * of the folio and return true. Otherwise, return false. + */ +static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t = len, + bool always_fill) +{ + struct inode *inode =3D folio_inode(folio); + loff_t i_size =3D i_size_read(inode); + size_t offset =3D offset_in_folio(folio, pos); + size_t plen =3D folio_size(folio); + + if (unlikely(always_fill)) { + if (pos - offset + len <=3D i_size) + return false; /* Page entirely before EOF */ + zero_user_segment(&folio->page, 0, plen); + folio_mark_uptodate(folio); + return true; + } + + /* Full folio write */ + if (offset =3D=3D 0 && len >=3D plen) + return true; + + /* Page entirely beyond the end of the file */ + if (pos - offset >=3D i_size) + goto zero_out; + + /* Write that covers from the start of the folio to EOF or beyond */ + if (offset =3D=3D 0 && (pos + len) >=3D i_size) + goto zero_out; + + return false; +zero_out: + zero_user_segments(&folio->page, 0, offset, offset + len, len); + return true; +} + +/** + * netfs_write_begin - Helper to prepare for writing + * @file: The file to read from + * @mapping: The mapping to read from + * @pos: File position at which the write will begin + * @len: The length of the write (may extend beyond the end of the folio c= hosen) + * @aop_flags: AOP_* flags + * @_folio: Where to put the resultant folio + * @_fsdata: Place for the netfs to store a cookie + * + * Pre-read data for a write-begin request by drawing data from the cache = if + * possible, or the netfs if not. Space beyond the EOF is zero-filled. + * Multiple I/O requests from different sources will get munged together. = If + * necessary, the readahead window can be expanded in either direction to a + * more convenient alighment for RPC efficiency or to make storage in the = cache + * feasible. + * + * The calling netfs must provide a table of operations, only one of which, + * issue_op, is mandatory. + * + * The check_write_begin() operation can be provided to check for and flush + * conflicting writes once the folio is grabbed and locked. It is passed a + * pointer to the fsdata cookie that gets returned to the VM to be passed = to + * write_end. It is permitted to sleep. It should return 0 if the request + * should go ahead; unlock the folio and return -EAGAIN to cause the folio= to + * be regot; or return an error. + * + * The calling netfs must initialise a netfs context contiguous to the vfs + * inode before calling this. + * + * This is usable whether or not caching is enabled. + */ +int netfs_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int aop_flags, + struct folio **_folio, void **_fsdata) +{ + struct netfs_io_request *rreq; + struct netfs_i_context *ctx =3D netfs_i_context(file_inode(file )); + struct folio *folio; + unsigned int fgp_flags; + pgoff_t index =3D pos >> PAGE_SHIFT; + int ret; + + DEFINE_READAHEAD(ractl, file, NULL, mapping, index); + +retry: + fgp_flags =3D FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_STABLE; + if (aop_flags & AOP_FLAG_NOFS) + fgp_flags |=3D FGP_NOFS; + folio =3D __filemap_get_folio(mapping, index, fgp_flags, + mapping_gfp_mask(mapping)); + if (!folio) + return -ENOMEM; + + if (ctx->ops->check_write_begin) { + /* Allow the netfs (eg. ceph) to flush conflicts. */ + ret =3D ctx->ops->check_write_begin(file, pos, len, folio, _fsdata); + if (ret < 0) { + trace_netfs_failure(NULL, NULL, ret, netfs_fail_check_write_begin); + if (ret =3D=3D -EAGAIN) + goto retry; + goto error; + } + } + + if (folio_test_uptodate(folio)) + goto have_folio; + + /* If the page is beyond the EOF, we want to clear it - unless it's + * within the cache granule containing the EOF, in which case we need + * to preload the granule. + */ + if (!netfs_is_cache_enabled(ctx) && + netfs_skip_folio_read(folio, pos, len, false)) { + netfs_stat(&netfs_n_rh_write_zskip); + goto have_folio_no_wait; + } + + rreq =3D netfs_alloc_request(mapping, file, + folio_file_pos(folio), folio_size(folio), + NETFS_READ_FOR_WRITE); + if (IS_ERR(rreq)) { + ret =3D PTR_ERR(rreq); + goto error; + } + rreq->no_unlock_folio =3D folio_index(folio); + __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); + + if (ctx->ops->begin_cache_operation) { + ret =3D ctx->ops->begin_cache_operation(rreq); + if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) + goto error_put; + } + + netfs_stat(&netfs_n_rh_write_begin); + trace_netfs_read(rreq, pos, len, netfs_read_trace_write_begin); + + /* Expand the request to meet caching requirements and download + * preferences. + */ + ractl._nr_pages =3D folio_nr_pages(folio); + netfs_rreq_expand(rreq, &ractl); + + /* We hold the folio locks, so we can drop the references */ + folio_get(folio); + while (readahead_folio(&ractl)) + ; + + ret =3D netfs_begin_read(rreq, true); + if (ret < 0) + goto error; + +have_folio: + ret =3D folio_wait_fscache_killable(folio); + if (ret < 0) + goto error; +have_folio_no_wait: + *_folio =3D folio; + _leave(" =3D 0"); + return 0; + +error_put: + netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); +error: + folio_unlock(folio); + folio_put(folio); + _leave(" =3D %d", ret); + return ret; +} +EXPORT_SYMBOL(netfs_write_begin); diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c deleted file mode 100644 index d448dc4f1010..000000000000 --- a/fs/netfs/read_helper.c +++ /dev/null @@ -1,1085 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* Network filesystem high-level read support. - * - * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "internal.h" -#define CREATE_TRACE_POINTS -#include - -MODULE_DESCRIPTION("Network fs support"); -MODULE_AUTHOR("Red Hat, Inc."); -MODULE_LICENSE("GPL"); - -unsigned netfs_debug; -module_param_named(debug, netfs_debug, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask"); - -/* - * Clear the unread part of an I/O request. - */ -static void netfs_clear_unread(struct netfs_io_subrequest *subreq) -{ - struct iov_iter iter; - - iov_iter_xarray(&iter, READ, &subreq->rreq->mapping->i_pages, - subreq->start + subreq->transferred, - subreq->len - subreq->transferred); - iov_iter_zero(iov_iter_count(&iter), &iter); -} - -static void netfs_cache_read_terminated(void *priv, ssize_t transferred_or= _error, - bool was_async) -{ - struct netfs_io_subrequest *subreq =3D priv; - - netfs_subreq_terminated(subreq, transferred_or_error, was_async); -} - -/* - * Issue a read against the cache. - * - Eats the caller's ref on subreq. - */ -static void netfs_read_from_cache(struct netfs_io_request *rreq, - struct netfs_io_subrequest *subreq, - enum netfs_read_from_hole read_hole) -{ - struct netfs_cache_resources *cres =3D &rreq->cache_resources; - struct iov_iter iter; - - netfs_stat(&netfs_n_rh_read); - iov_iter_xarray(&iter, READ, &rreq->mapping->i_pages, - subreq->start + subreq->transferred, - subreq->len - subreq->transferred); - - cres->ops->read(cres, subreq->start, &iter, read_hole, - netfs_cache_read_terminated, subreq); -} - -/* - * Fill a subrequest region with zeroes. - */ -static void netfs_fill_with_zeroes(struct netfs_io_request *rreq, - struct netfs_io_subrequest *subreq) -{ - netfs_stat(&netfs_n_rh_zero); - __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); - netfs_subreq_terminated(subreq, 0, false); -} - -/* - * Ask the netfs to issue a read request to the server for us. - * - * The netfs is expected to read from subreq->pos + subreq->transferred to - * subreq->pos + subreq->len - 1. It may not backtrack and write data int= o the - * buffer prior to the transferred point as it might clobber dirty data - * obtained from the cache. - * - * Alternatively, the netfs is allowed to indicate one of two things: - * - * - NETFS_SREQ_SHORT_READ: A short read - it will get called again to try= and - * make progress. - * - * - NETFS_SREQ_CLEAR_TAIL: A short read - the rest of the buffer will be - * cleared. - */ -static void netfs_read_from_server(struct netfs_io_request *rreq, - struct netfs_io_subrequest *subreq) -{ - netfs_stat(&netfs_n_rh_download); - rreq->netfs_ops->issue_read(subreq); -} - -/* - * Release those waiting. - */ -static void netfs_rreq_completed(struct netfs_io_request *rreq, bool was_a= sync) -{ - trace_netfs_rreq(rreq, netfs_rreq_trace_done); - netfs_clear_subrequests(rreq, was_async); - netfs_put_request(rreq, was_async, netfs_rreq_trace_put_complete); -} - -/* - * Deal with the completion of writing the data to the cache. We have to = clear - * the PG_fscache bits on the folios involved and release the caller's ref. - * - * May be called in softirq mode and we inherit a ref from the caller. - */ -static void netfs_rreq_unmark_after_write(struct netfs_io_request *rreq, - bool was_async) -{ - struct netfs_io_subrequest *subreq; - struct folio *folio; - pgoff_t unlocked =3D 0; - bool have_unlocked =3D false; - - rcu_read_lock(); - - list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { - XA_STATE(xas, &rreq->mapping->i_pages, subreq->start / PAGE_SIZE); - - xas_for_each(&xas, folio, (subreq->start + subreq->len - 1) / PAGE_SIZE)= { - /* We might have multiple writes from the same huge - * folio, but we mustn't unlock a folio more than once. - */ - if (have_unlocked && folio_index(folio) <=3D unlocked) - continue; - unlocked =3D folio_index(folio); - folio_end_fscache(folio); - have_unlocked =3D true; - } - } - - rcu_read_unlock(); - netfs_rreq_completed(rreq, was_async); -} - -static void netfs_rreq_copy_terminated(void *priv, ssize_t transferred_or_= error, - bool was_async) -{ - struct netfs_io_subrequest *subreq =3D priv; - struct netfs_io_request *rreq =3D subreq->rreq; - - if (IS_ERR_VALUE(transferred_or_error)) { - netfs_stat(&netfs_n_rh_write_failed); - trace_netfs_failure(rreq, subreq, transferred_or_error, - netfs_fail_copy_to_cache); - } else { - netfs_stat(&netfs_n_rh_write_done); - } - - trace_netfs_sreq(subreq, netfs_sreq_trace_write_term); - - /* If we decrement nr_copy_ops to 0, the ref belongs to us. */ - if (atomic_dec_and_test(&rreq->nr_copy_ops)) - netfs_rreq_unmark_after_write(rreq, was_async); - - netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated); -} - -/* - * Perform any outstanding writes to the cache. We inherit a ref from the - * caller. - */ -static void netfs_rreq_do_write_to_cache(struct netfs_io_request *rreq) -{ - struct netfs_cache_resources *cres =3D &rreq->cache_resources; - struct netfs_io_subrequest *subreq, *next, *p; - struct iov_iter iter; - int ret; - - trace_netfs_rreq(rreq, netfs_rreq_trace_copy); - - /* We don't want terminating writes trying to wake us up whilst we're - * still going through the list. - */ - atomic_inc(&rreq->nr_copy_ops); - - list_for_each_entry_safe(subreq, p, &rreq->subrequests, rreq_link) { - if (!test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) { - list_del_init(&subreq->rreq_link); - netfs_put_subrequest(subreq, false, - netfs_sreq_trace_put_no_copy); - } - } - - list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { - /* Amalgamate adjacent writes */ - while (!list_is_last(&subreq->rreq_link, &rreq->subrequests)) { - next =3D list_next_entry(subreq, rreq_link); - if (next->start !=3D subreq->start + subreq->len) - break; - subreq->len +=3D next->len; - list_del_init(&next->rreq_link); - netfs_put_subrequest(next, false, - netfs_sreq_trace_put_merged); - } - - ret =3D cres->ops->prepare_write(cres, &subreq->start, &subreq->len, - rreq->i_size, true); - if (ret < 0) { - trace_netfs_failure(rreq, subreq, ret, netfs_fail_prepare_write); - trace_netfs_sreq(subreq, netfs_sreq_trace_write_skip); - continue; - } - - iov_iter_xarray(&iter, WRITE, &rreq->mapping->i_pages, - subreq->start, subreq->len); - - atomic_inc(&rreq->nr_copy_ops); - netfs_stat(&netfs_n_rh_write); - netfs_get_subrequest(subreq, netfs_sreq_trace_get_copy_to_cache); - trace_netfs_sreq(subreq, netfs_sreq_trace_write); - cres->ops->write(cres, subreq->start, &iter, - netfs_rreq_copy_terminated, subreq); - } - - /* If we decrement nr_copy_ops to 0, the usage ref belongs to us. */ - if (atomic_dec_and_test(&rreq->nr_copy_ops)) - netfs_rreq_unmark_after_write(rreq, false); -} - -static void netfs_rreq_write_to_cache_work(struct work_struct *work) -{ - struct netfs_io_request *rreq =3D - container_of(work, struct netfs_io_request, work); - - netfs_rreq_do_write_to_cache(rreq); -} - -static void netfs_rreq_write_to_cache(struct netfs_io_request *rreq) -{ - rreq->work.func =3D netfs_rreq_write_to_cache_work; - if (!queue_work(system_unbound_wq, &rreq->work)) - BUG(); -} - -/* - * Unlock the folios in a read operation. We need to set PG_fscache on any - * folios we're going to write back before we unlock them. - */ -void netfs_rreq_unlock_folios(struct netfs_io_request *rreq) -{ - struct netfs_io_subrequest *subreq; - struct folio *folio; - unsigned int iopos, account =3D 0; - pgoff_t start_page =3D rreq->start / PAGE_SIZE; - pgoff_t last_page =3D ((rreq->start + rreq->len) / PAGE_SIZE) - 1; - bool subreq_failed =3D false; - - XA_STATE(xas, &rreq->mapping->i_pages, start_page); - - if (test_bit(NETFS_RREQ_FAILED, &rreq->flags)) { - __clear_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags); - list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { - __clear_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); - } - } - - /* Walk through the pagecache and the I/O request lists simultaneously. - * We may have a mixture of cached and uncached sections and we only - * really want to write out the uncached sections. This is slightly - * complicated by the possibility that we might have huge pages with a - * mixture inside. - */ - subreq =3D list_first_entry(&rreq->subrequests, - struct netfs_io_subrequest, rreq_link); - iopos =3D 0; - subreq_failed =3D (subreq->error < 0); - - trace_netfs_rreq(rreq, netfs_rreq_trace_unlock); - - rcu_read_lock(); - xas_for_each(&xas, folio, last_page) { - unsigned int pgpos =3D (folio_index(folio) - start_page) * PAGE_SIZE; - unsigned int pgend =3D pgpos + folio_size(folio); - bool pg_failed =3D false; - - for (;;) { - if (!subreq) { - pg_failed =3D true; - break; - } - if (test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) - folio_start_fscache(folio); - pg_failed |=3D subreq_failed; - if (pgend < iopos + subreq->len) - break; - - account +=3D subreq->transferred; - iopos +=3D subreq->len; - if (!list_is_last(&subreq->rreq_link, &rreq->subrequests)) { - subreq =3D list_next_entry(subreq, rreq_link); - subreq_failed =3D (subreq->error < 0); - } else { - subreq =3D NULL; - subreq_failed =3D false; - } - if (pgend =3D=3D iopos) - break; - } - - if (!pg_failed) { - flush_dcache_folio(folio); - folio_mark_uptodate(folio); - } - - if (!test_bit(NETFS_RREQ_DONT_UNLOCK_FOLIOS, &rreq->flags)) { - if (folio_index(folio) =3D=3D rreq->no_unlock_folio && - test_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags)) - _debug("no unlock"); - else - folio_unlock(folio); - } - } - rcu_read_unlock(); - - task_io_account_read(account); - if (rreq->netfs_ops->done) - rreq->netfs_ops->done(rreq); -} - -/* - * Handle a short read. - */ -static void netfs_rreq_short_read(struct netfs_io_request *rreq, - struct netfs_io_subrequest *subreq) -{ - __clear_bit(NETFS_SREQ_SHORT_IO, &subreq->flags); - __set_bit(NETFS_SREQ_SEEK_DATA_READ, &subreq->flags); - - netfs_stat(&netfs_n_rh_short_read); - trace_netfs_sreq(subreq, netfs_sreq_trace_resubmit_short); - - netfs_get_subrequest(subreq, netfs_sreq_trace_get_short_read); - atomic_inc(&rreq->nr_outstanding); - if (subreq->source =3D=3D NETFS_READ_FROM_CACHE) - netfs_read_from_cache(rreq, subreq, NETFS_READ_HOLE_CLEAR); - else - netfs_read_from_server(rreq, subreq); -} - -/* - * Resubmit any short or failed operations. Returns true if we got the rr= eq - * ref back. - */ -static bool netfs_rreq_perform_resubmissions(struct netfs_io_request *rreq) -{ - struct netfs_io_subrequest *subreq; - - WARN_ON(in_interrupt()); - - trace_netfs_rreq(rreq, netfs_rreq_trace_resubmit); - - /* We don't want terminating submissions trying to wake us up whilst - * we're still going through the list. - */ - atomic_inc(&rreq->nr_outstanding); - - __clear_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags); - list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { - if (subreq->error) { - if (subreq->source !=3D NETFS_READ_FROM_CACHE) - break; - subreq->source =3D NETFS_DOWNLOAD_FROM_SERVER; - subreq->error =3D 0; - netfs_stat(&netfs_n_rh_download_instead); - trace_netfs_sreq(subreq, netfs_sreq_trace_download_instead); - netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); - atomic_inc(&rreq->nr_outstanding); - netfs_read_from_server(rreq, subreq); - } else if (test_bit(NETFS_SREQ_SHORT_IO, &subreq->flags)) { - netfs_rreq_short_read(rreq, subreq); - } - } - - /* If we decrement nr_outstanding to 0, the usage ref belongs to us. */ - if (atomic_dec_and_test(&rreq->nr_outstanding)) - return true; - - wake_up_var(&rreq->nr_outstanding); - return false; -} - -/* - * Check to see if the data read is still valid. - */ -static void netfs_rreq_is_still_valid(struct netfs_io_request *rreq) -{ - struct netfs_io_subrequest *subreq; - - if (!rreq->netfs_ops->is_still_valid || - rreq->netfs_ops->is_still_valid(rreq)) - return; - - list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { - if (subreq->source =3D=3D NETFS_READ_FROM_CACHE) { - subreq->error =3D -ESTALE; - __set_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags); - } - } -} - -/* - * Assess the state of a read request and decide what to do next. - * - * Note that we could be in an ordinary kernel thread, on a workqueue or in - * softirq context at this point. We inherit a ref from the caller. - */ -static void netfs_rreq_assess(struct netfs_io_request *rreq, bool was_asyn= c) -{ - trace_netfs_rreq(rreq, netfs_rreq_trace_assess); - -again: - netfs_rreq_is_still_valid(rreq); - - if (!test_bit(NETFS_RREQ_FAILED, &rreq->flags) && - test_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags)) { - if (netfs_rreq_perform_resubmissions(rreq)) - goto again; - return; - } - - netfs_rreq_unlock_folios(rreq); - - clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &rreq->flags); - wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS); - - if (test_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags)) - return netfs_rreq_write_to_cache(rreq); - - netfs_rreq_completed(rreq, was_async); -} - -static void netfs_rreq_work(struct work_struct *work) -{ - struct netfs_io_request *rreq =3D - container_of(work, struct netfs_io_request, work); - netfs_rreq_assess(rreq, false); -} - -/* - * Handle the completion of all outstanding I/O operations on a read reque= st. - * We inherit a ref from the caller. - */ -static void netfs_rreq_terminated(struct netfs_io_request *rreq, - bool was_async) -{ - if (test_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags) && - was_async) { - if (!queue_work(system_unbound_wq, &rreq->work)) - BUG(); - } else { - netfs_rreq_assess(rreq, was_async); - } -} - -/** - * netfs_subreq_terminated - Note the termination of an I/O operation. - * @subreq: The I/O request that has terminated. - * @transferred_or_error: The amount of data transferred or an error code. - * @was_async: The termination was asynchronous - * - * This tells the read helper that a contributory I/O operation has termin= ated, - * one way or another, and that it should integrate the results. - * - * The caller indicates in @transferred_or_error the outcome of the operat= ion, - * supplying a positive value to indicate the number of bytes transferred,= 0 to - * indicate a failure to transfer anything that should be retried or a neg= ative - * error code. The helper will look after reissuing I/O operations as - * appropriate and writing downloaded data to the cache. - * - * If @was_async is true, the caller might be running in softirq or interr= upt - * context and we can't sleep. - */ -void netfs_subreq_terminated(struct netfs_io_subrequest *subreq, - ssize_t transferred_or_error, - bool was_async) -{ - struct netfs_io_request *rreq =3D subreq->rreq; - int u; - - _enter("[%u]{%llx,%lx},%zd", - subreq->debug_index, subreq->start, subreq->flags, - transferred_or_error); - - switch (subreq->source) { - case NETFS_READ_FROM_CACHE: - netfs_stat(&netfs_n_rh_read_done); - break; - case NETFS_DOWNLOAD_FROM_SERVER: - netfs_stat(&netfs_n_rh_download_done); - break; - default: - break; - } - - if (IS_ERR_VALUE(transferred_or_error)) { - subreq->error =3D transferred_or_error; - trace_netfs_failure(rreq, subreq, transferred_or_error, - netfs_fail_read); - goto failed; - } - - if (WARN(transferred_or_error > subreq->len - subreq->transferred, - "Subreq overread: R%x[%x] %zd > %zu - %zu", - rreq->debug_id, subreq->debug_index, - transferred_or_error, subreq->len, subreq->transferred)) - transferred_or_error =3D subreq->len - subreq->transferred; - - subreq->error =3D 0; - subreq->transferred +=3D transferred_or_error; - if (subreq->transferred < subreq->len) - goto incomplete; - -complete: - __clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags); - if (test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) - set_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags); - -out: - trace_netfs_sreq(subreq, netfs_sreq_trace_terminated); - - /* If we decrement nr_outstanding to 0, the ref belongs to us. */ - u =3D atomic_dec_return(&rreq->nr_outstanding); - if (u =3D=3D 0) - netfs_rreq_terminated(rreq, was_async); - else if (u =3D=3D 1) - wake_up_var(&rreq->nr_outstanding); - - netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated); - return; - -incomplete: - if (test_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags)) { - netfs_clear_unread(subreq); - subreq->transferred =3D subreq->len; - goto complete; - } - - if (transferred_or_error =3D=3D 0) { - if (__test_and_set_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags)) { - subreq->error =3D -ENODATA; - goto failed; - } - } else { - __clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags); - } - - __set_bit(NETFS_SREQ_SHORT_IO, &subreq->flags); - set_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags); - goto out; - -failed: - if (subreq->source =3D=3D NETFS_READ_FROM_CACHE) { - netfs_stat(&netfs_n_rh_read_failed); - set_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags); - } else { - netfs_stat(&netfs_n_rh_download_failed); - set_bit(NETFS_RREQ_FAILED, &rreq->flags); - rreq->error =3D subreq->error; - } - goto out; -} -EXPORT_SYMBOL(netfs_subreq_terminated); - -static enum netfs_io_source netfs_cache_prepare_read(struct netfs_io_subre= quest *subreq, - loff_t i_size) -{ - struct netfs_io_request *rreq =3D subreq->rreq; - struct netfs_cache_resources *cres =3D &rreq->cache_resources; - - if (cres->ops) - return cres->ops->prepare_read(subreq, i_size); - if (subreq->start >=3D rreq->i_size) - return NETFS_FILL_WITH_ZEROES; - return NETFS_DOWNLOAD_FROM_SERVER; -} - -/* - * Work out what sort of subrequest the next one will be. - */ -static enum netfs_io_source -netfs_rreq_prepare_read(struct netfs_io_request *rreq, - struct netfs_io_subrequest *subreq) -{ - enum netfs_io_source source; - - _enter("%llx-%llx,%llx", subreq->start, subreq->start + subreq->len, rreq= ->i_size); - - source =3D netfs_cache_prepare_read(subreq, rreq->i_size); - if (source =3D=3D NETFS_INVALID_READ) - goto out; - - if (source =3D=3D NETFS_DOWNLOAD_FROM_SERVER) { - /* Call out to the netfs to let it shrink the request to fit - * its own I/O sizes and boundaries. If it shinks it here, it - * will be called again to make simultaneous calls; if it wants - * to make serial calls, it can indicate a short read and then - * we will call it again. - */ - if (subreq->len > rreq->i_size - subreq->start) - subreq->len =3D rreq->i_size - subreq->start; - - if (rreq->netfs_ops->clamp_length && - !rreq->netfs_ops->clamp_length(subreq)) { - source =3D NETFS_INVALID_READ; - goto out; - } - } - - if (WARN_ON(subreq->len =3D=3D 0)) - source =3D NETFS_INVALID_READ; - -out: - subreq->source =3D source; - trace_netfs_sreq(subreq, netfs_sreq_trace_prepare); - return source; -} - -/* - * Slice off a piece of a read request and submit an I/O request for it. - */ -static bool netfs_rreq_submit_slice(struct netfs_io_request *rreq, - unsigned int *_debug_index) -{ - struct netfs_io_subrequest *subreq; - enum netfs_io_source source; - - subreq =3D netfs_alloc_subrequest(rreq); - if (!subreq) - return false; - - subreq->debug_index =3D (*_debug_index)++; - subreq->start =3D rreq->start + rreq->submitted; - subreq->len =3D rreq->len - rreq->submitted; - - _debug("slice %llx,%zx,%zx", subreq->start, subreq->len, rreq->submitted); - list_add_tail(&subreq->rreq_link, &rreq->subrequests); - - /* Call out to the cache to find out what it can do with the remaining - * subset. It tells us in subreq->flags what it decided should be done - * and adjusts subreq->len down if the subset crosses a cache boundary. - * - * Then when we hand the subset, it can choose to take a subset of that - * (the starts must coincide), in which case, we go around the loop - * again and ask it to download the next piece. - */ - source =3D netfs_rreq_prepare_read(rreq, subreq); - if (source =3D=3D NETFS_INVALID_READ) - goto subreq_failed; - - atomic_inc(&rreq->nr_outstanding); - - rreq->submitted +=3D subreq->len; - - trace_netfs_sreq(subreq, netfs_sreq_trace_submit); - switch (source) { - case NETFS_FILL_WITH_ZEROES: - netfs_fill_with_zeroes(rreq, subreq); - break; - case NETFS_DOWNLOAD_FROM_SERVER: - netfs_read_from_server(rreq, subreq); - break; - case NETFS_READ_FROM_CACHE: - netfs_read_from_cache(rreq, subreq, NETFS_READ_HOLE_IGNORE); - break; - default: - BUG(); - } - - return true; - -subreq_failed: - rreq->error =3D subreq->error; - netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_failed); - return false; -} - -/* - * Begin the process of reading in a chunk of data, where that data may be - * stitched together from multiple sources, including multiple servers and= the - * local cache. - */ -int netfs_begin_read(struct netfs_io_request *rreq, bool sync) -{ - unsigned int debug_index =3D 0; - int ret; - - _enter("R=3D%x %llx-%llx", - rreq->debug_id, rreq->start, rreq->start + rreq->len - 1); - - if (rreq->len =3D=3D 0) { - pr_err("Zero-sized read [R=3D%x]\n", rreq->debug_id); - netfs_put_request(rreq, false, netfs_rreq_trace_put_zero_len); - return -EIO; - } - - INIT_WORK(&rreq->work, netfs_rreq_work); - - if (sync) - netfs_get_request(rreq, netfs_rreq_trace_get_hold); - - /* Chop the read into slices according to what the cache and the netfs - * want and submit each one. - */ - atomic_set(&rreq->nr_outstanding, 1); - do { - if (!netfs_rreq_submit_slice(rreq, &debug_index)) - break; - - } while (rreq->submitted < rreq->len); - - if (sync) { - /* Keep nr_outstanding incremented so that the ref always belongs to - * us, and the service code isn't punted off to a random thread pool to - * process. - */ - for (;;) { - wait_var_event(&rreq->nr_outstanding, - atomic_read(&rreq->nr_outstanding) =3D=3D 1); - netfs_rreq_assess(rreq, false); - if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) - break; - cond_resched(); - } - - ret =3D rreq->error; - if (ret =3D=3D 0 && rreq->submitted < rreq->len) { - trace_netfs_failure(rreq, NULL, ret, netfs_fail_short_read); - ret =3D -EIO; - } - netfs_put_request(rreq, false, netfs_rreq_trace_put_hold); - } else { - /* If we decrement nr_outstanding to 0, the ref belongs to us. */ - if (atomic_dec_and_test(&rreq->nr_outstanding)) - netfs_rreq_assess(rreq, false); - ret =3D 0; - } - return ret; -} - -static void netfs_cache_expand_readahead(struct netfs_io_request *rreq, - loff_t *_start, size_t *_len, loff_t i_size) -{ - struct netfs_cache_resources *cres =3D &rreq->cache_resources; - - if (cres->ops && cres->ops->expand_readahead) - cres->ops->expand_readahead(cres, _start, _len, i_size); -} - -static void netfs_rreq_expand(struct netfs_io_request *rreq, - struct readahead_control *ractl) -{ - /* Give the cache a chance to change the request parameters. The - * resultant request must contain the original region. - */ - netfs_cache_expand_readahead(rreq, &rreq->start, &rreq->len, rreq->i_size= ); - - /* Give the netfs a chance to change the request parameters. The - * resultant request must contain the original region. - */ - if (rreq->netfs_ops->expand_readahead) - rreq->netfs_ops->expand_readahead(rreq); - - /* Expand the request if the cache wants it to start earlier. Note - * that the expansion may get further extended if the VM wishes to - * insert THPs and the preferred start and/or end wind up in the middle - * of THPs. - * - * If this is the case, however, the THP size should be an integer - * multiple of the cache granule size, so we get a whole number of - * granules to deal with. - */ - if (rreq->start !=3D readahead_pos(ractl) || - rreq->len !=3D readahead_length(ractl)) { - readahead_expand(ractl, rreq->start, rreq->len); - rreq->start =3D readahead_pos(ractl); - rreq->len =3D readahead_length(ractl); - - trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl), - netfs_read_trace_expanded); - } -} - -/** - * netfs_readahead - Helper to manage a read request - * @ractl: The description of the readahead request - * - * Fulfil a readahead request by drawing data from the cache if possible, = or - * the netfs if not. Space beyond the EOF is zero-filled. Multiple I/O - * requests from different sources will get munged together. If necessary= , the - * readahead window can be expanded in either direction to a more convenie= nt - * alighment for RPC efficiency or to make storage in the cache feasible. - * - * The calling netfs must initialise a netfs context contiguous to the vfs - * inode before calling this. - * - * This is usable whether or not caching is enabled. - */ -void netfs_readahead(struct readahead_control *ractl) -{ - struct netfs_io_request *rreq; - struct netfs_i_context *ctx =3D netfs_i_context(ractl->mapping->host); - int ret; - - _enter("%lx,%x", readahead_index(ractl), readahead_count(ractl)); - - if (readahead_count(ractl) =3D=3D 0) - return; - - rreq =3D netfs_alloc_request(ractl->mapping, ractl->file, - readahead_pos(ractl), - readahead_length(ractl), - NETFS_READAHEAD); - if (IS_ERR(rreq)) - return; - - if (ctx->ops->begin_cache_operation) { - ret =3D ctx->ops->begin_cache_operation(rreq); - if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) - goto cleanup_free; - } - - netfs_stat(&netfs_n_rh_readahead); - trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl), - netfs_read_trace_readahead); - - netfs_rreq_expand(rreq, ractl); - - /* Drop the refs on the folios here rather than in the cache or - * filesystem. The locks will be dropped in netfs_rreq_unlock(). - */ - while (readahead_folio(ractl)) - ; - - netfs_begin_read(rreq, false); - return; - -cleanup_free: - netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); - return; -} -EXPORT_SYMBOL(netfs_readahead); - -/** - * netfs_readpage - Helper to manage a readpage request - * @file: The file to read from - * @subpage: A subpage of the folio to read - * - * Fulfil a readpage request by drawing data from the cache if possible, o= r the - * netfs if not. Space beyond the EOF is zero-filled. Multiple I/O reque= sts - * from different sources will get munged together. - * - * The calling netfs must initialise a netfs context contiguous to the vfs - * inode before calling this. - * - * This is usable whether or not caching is enabled. - */ -int netfs_readpage(struct file *file, struct page *subpage) -{ - struct folio *folio =3D page_folio(subpage); - struct address_space *mapping =3D folio->mapping; - struct netfs_io_request *rreq; - struct netfs_i_context *ctx =3D netfs_i_context(mapping->host); - int ret; - - _enter("%lx", folio_index(folio)); - - rreq =3D netfs_alloc_request(mapping, file, - folio_file_pos(folio), folio_size(folio), - NETFS_READPAGE); - if (IS_ERR(rreq)) { - ret =3D PTR_ERR(rreq); - goto alloc_error; - } - - if (ctx->ops->begin_cache_operation) { - ret =3D ctx->ops->begin_cache_operation(rreq); - if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) - goto discard; - } - - netfs_stat(&netfs_n_rh_readpage); - trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage); - return netfs_begin_read(rreq, true); - -discard: - netfs_put_request(rreq, false, netfs_rreq_trace_put_discard); -alloc_error: - folio_unlock(folio); - return ret; -} -EXPORT_SYMBOL(netfs_readpage); - -/* - * Prepare a folio for writing without reading first - * @folio: The folio being prepared - * @pos: starting position for the write - * @len: length of write - * @always_fill: T if the folio should always be completely filled/cleared - * - * In some cases, write_begin doesn't need to read at all: - * - full folio write - * - write that lies in a folio that is completely beyond EOF - * - write that covers the folio from start to EOF or beyond it - * - * If any of these criteria are met, then zero out the unwritten parts - * of the folio and return true. Otherwise, return false. - */ -static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t = len, - bool always_fill) -{ - struct inode *inode =3D folio_inode(folio); - loff_t i_size =3D i_size_read(inode); - size_t offset =3D offset_in_folio(folio, pos); - size_t plen =3D folio_size(folio); - - if (unlikely(always_fill)) { - if (pos - offset + len <=3D i_size) - return false; /* Page entirely before EOF */ - zero_user_segment(&folio->page, 0, plen); - folio_mark_uptodate(folio); - return true; - } - - /* Full folio write */ - if (offset =3D=3D 0 && len >=3D plen) - return true; - - /* Page entirely beyond the end of the file */ - if (pos - offset >=3D i_size) - goto zero_out; - - /* Write that covers from the start of the folio to EOF or beyond */ - if (offset =3D=3D 0 && (pos + len) >=3D i_size) - goto zero_out; - - return false; -zero_out: - zero_user_segments(&folio->page, 0, offset, offset + len, len); - return true; -} - -/** - * netfs_write_begin - Helper to prepare for writing - * @file: The file to read from - * @mapping: The mapping to read from - * @pos: File position at which the write will begin - * @len: The length of the write (may extend beyond the end of the folio c= hosen) - * @aop_flags: AOP_* flags - * @_folio: Where to put the resultant folio - * @_fsdata: Place for the netfs to store a cookie - * - * Pre-read data for a write-begin request by drawing data from the cache = if - * possible, or the netfs if not. Space beyond the EOF is zero-filled. - * Multiple I/O requests from different sources will get munged together. = If - * necessary, the readahead window can be expanded in either direction to a - * more convenient alighment for RPC efficiency or to make storage in the = cache - * feasible. - * - * The calling netfs must provide a table of operations, only one of which, - * issue_op, is mandatory. - * - * The check_write_begin() operation can be provided to check for and flush - * conflicting writes once the folio is grabbed and locked. It is passed a - * pointer to the fsdata cookie that gets returned to the VM to be passed = to - * write_end. It is permitted to sleep. It should return 0 if the request - * should go ahead; unlock the folio and return -EAGAIN to cause the folio= to - * be regot; or return an error. - * - * The calling netfs must initialise a netfs context contiguous to the vfs - * inode before calling this. - * - * This is usable whether or not caching is enabled. - */ -int netfs_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned int len, unsigned int aop_flags, - struct folio **_folio, void **_fsdata) -{ - struct netfs_io_request *rreq; - struct netfs_i_context *ctx =3D netfs_i_context(file_inode(file )); - struct folio *folio; - unsigned int fgp_flags; - pgoff_t index =3D pos >> PAGE_SHIFT; - int ret; - - DEFINE_READAHEAD(ractl, file, NULL, mapping, index); - -retry: - fgp_flags =3D FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_STABLE; - if (aop_flags & AOP_FLAG_NOFS) - fgp_flags |=3D FGP_NOFS; - folio =3D __filemap_get_folio(mapping, index, fgp_flags, - mapping_gfp_mask(mapping)); - if (!folio) - return -ENOMEM; - - if (ctx->ops->check_write_begin) { - /* Allow the netfs (eg. ceph) to flush conflicts. */ - ret =3D ctx->ops->check_write_begin(file, pos, len, folio, _fsdata); - if (ret < 0) { - trace_netfs_failure(NULL, NULL, ret, netfs_fail_check_write_begin); - if (ret =3D=3D -EAGAIN) - goto retry; - goto error; - } - } - - if (folio_test_uptodate(folio)) - goto have_folio; - - /* If the page is beyond the EOF, we want to clear it - unless it's - * within the cache granule containing the EOF, in which case we need - * to preload the granule. - */ - if (!netfs_is_cache_enabled(ctx) && - netfs_skip_folio_read(folio, pos, len, false)) { - netfs_stat(&netfs_n_rh_write_zskip); - goto have_folio_no_wait; - } - - rreq =3D netfs_alloc_request(mapping, file, - folio_file_pos(folio), folio_size(folio), - NETFS_READ_FOR_WRITE); - if (IS_ERR(rreq)) { - ret =3D PTR_ERR(rreq); - goto error; - } - rreq->no_unlock_folio =3D folio_index(folio); - __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); - - if (ctx->ops->begin_cache_operation) { - ret =3D ctx->ops->begin_cache_operation(rreq); - if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) - goto error_put; - } - - netfs_stat(&netfs_n_rh_write_begin); - trace_netfs_read(rreq, pos, len, netfs_read_trace_write_begin); - - /* Expand the request to meet caching requirements and download - * preferences. - */ - ractl._nr_pages =3D folio_nr_pages(folio); - netfs_rreq_expand(rreq, &ractl); - - /* We hold the folio locks, so we can drop the references */ - folio_get(folio); - while (readahead_folio(&ractl)) - ; - - ret =3D netfs_begin_read(rreq, true); - if (ret < 0) - goto error; - -have_folio: - ret =3D folio_wait_fscache_killable(folio); - if (ret < 0) - goto error; -have_folio_no_wait: - *_folio =3D folio; - _leave(" =3D 0"); - return 0; - -error_put: - netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); -error: - folio_unlock(folio); - folio_put(folio); - _leave(" =3D %d", ret); - return ret; -} -EXPORT_SYMBOL(netfs_write_begin); From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CA3B5C433F5 for ; Thu, 10 Mar 2022 16:21:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241394AbiCJQWf (ORCPT ); Thu, 10 Mar 2022 11:22:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42792 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243612AbiCJQWV (ORCPT ); Thu, 10 Mar 2022 11:22:21 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id A0072198D1E for ; Thu, 10 Mar 2022 08:20:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929209; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MKkz4POAiTwx16QDznUxzSbfLwVZ+jSj07p3N19L6Fw=; b=iyHQoSBCZKCte3b/FsfclOl7O94+mBVbWPXJRz+iP5ZHH+gCaKT9mXGBZa/KEa/pkN1aD/ a2hBtcPoNiooRuNdgKuSln3Kgv4r/oY2Jh3iH35CNo9OW65EPk9hqkNF/XDz4Kn80L1mFE JmpQp4Gel8K8txUK9HddUFBWv9EVWOg= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-267-wC9fxpJGO3KzkRI4wOPAqg-1; Thu, 10 Mar 2022 11:20:06 -0500 X-MC-Unique: wC9fxpJGO3KzkRI4wOPAqg-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 354618066F3; Thu, 10 Mar 2022 16:20:04 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 622457C026; Thu, 10 Mar 2022 16:20:00 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 17/20] netfs: Split fs/netfs/read_helper.c From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:19:59 +0000 Message-ID: <164692919953.2099075.7156989585513833046.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Split fs/netfs/read_helper.c into two pieces, one to deal with buffered writes and one to deal with the I/O mechanism. Changes =3D=3D=3D=3D=3D=3D=3D ver #2) - Add kdoc reference to new file. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164623005586.3564931.6149556072728481767.st= git@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678217075.1200972.5101072043126828757.st= git@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/netfs/Makefile | 1=20 fs/netfs/buffered_read.c | 428 ++++++++++++++++++++++++++++++++++++++++++= ++++ fs/netfs/io.c | 418 ------------------------------------------= --- 3 files changed, 429 insertions(+), 418 deletions(-) create mode 100644 fs/netfs/buffered_read.c diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index 51ece4f7bc77..88b904532bc7 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 =20 netfs-y :=3D \ + buffered_read.o \ io.o \ objects.o =20 diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c new file mode 100644 index 000000000000..09ba7097a970 --- /dev/null +++ b/fs/netfs/buffered_read.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Network filesystem high-level buffered read support. + * + * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include +#include +#include "internal.h" + +/* + * Unlock the folios in a read operation. We need to set PG_fscache on any + * folios we're going to write back before we unlock them. + */ +void netfs_rreq_unlock_folios(struct netfs_io_request *rreq) +{ + struct netfs_io_subrequest *subreq; + struct folio *folio; + unsigned int iopos, account =3D 0; + pgoff_t start_page =3D rreq->start / PAGE_SIZE; + pgoff_t last_page =3D ((rreq->start + rreq->len) / PAGE_SIZE) - 1; + bool subreq_failed =3D false; + + XA_STATE(xas, &rreq->mapping->i_pages, start_page); + + if (test_bit(NETFS_RREQ_FAILED, &rreq->flags)) { + __clear_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags); + list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { + __clear_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); + } + } + + /* Walk through the pagecache and the I/O request lists simultaneously. + * We may have a mixture of cached and uncached sections and we only + * really want to write out the uncached sections. This is slightly + * complicated by the possibility that we might have huge pages with a + * mixture inside. + */ + subreq =3D list_first_entry(&rreq->subrequests, + struct netfs_io_subrequest, rreq_link); + iopos =3D 0; + subreq_failed =3D (subreq->error < 0); + + trace_netfs_rreq(rreq, netfs_rreq_trace_unlock); + + rcu_read_lock(); + xas_for_each(&xas, folio, last_page) { + unsigned int pgpos =3D (folio_index(folio) - start_page) * PAGE_SIZE; + unsigned int pgend =3D pgpos + folio_size(folio); + bool pg_failed =3D false; + + for (;;) { + if (!subreq) { + pg_failed =3D true; + break; + } + if (test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) + folio_start_fscache(folio); + pg_failed |=3D subreq_failed; + if (pgend < iopos + subreq->len) + break; + + account +=3D subreq->transferred; + iopos +=3D subreq->len; + if (!list_is_last(&subreq->rreq_link, &rreq->subrequests)) { + subreq =3D list_next_entry(subreq, rreq_link); + subreq_failed =3D (subreq->error < 0); + } else { + subreq =3D NULL; + subreq_failed =3D false; + } + if (pgend =3D=3D iopos) + break; + } + + if (!pg_failed) { + flush_dcache_folio(folio); + folio_mark_uptodate(folio); + } + + if (!test_bit(NETFS_RREQ_DONT_UNLOCK_FOLIOS, &rreq->flags)) { + if (folio_index(folio) =3D=3D rreq->no_unlock_folio && + test_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags)) + _debug("no unlock"); + else + folio_unlock(folio); + } + } + rcu_read_unlock(); + + task_io_account_read(account); + if (rreq->netfs_ops->done) + rreq->netfs_ops->done(rreq); +} + +static void netfs_cache_expand_readahead(struct netfs_io_request *rreq, + loff_t *_start, size_t *_len, loff_t i_size) +{ + struct netfs_cache_resources *cres =3D &rreq->cache_resources; + + if (cres->ops && cres->ops->expand_readahead) + cres->ops->expand_readahead(cres, _start, _len, i_size); +} + +static void netfs_rreq_expand(struct netfs_io_request *rreq, + struct readahead_control *ractl) +{ + /* Give the cache a chance to change the request parameters. The + * resultant request must contain the original region. + */ + netfs_cache_expand_readahead(rreq, &rreq->start, &rreq->len, rreq->i_size= ); + + /* Give the netfs a chance to change the request parameters. The + * resultant request must contain the original region. + */ + if (rreq->netfs_ops->expand_readahead) + rreq->netfs_ops->expand_readahead(rreq); + + /* Expand the request if the cache wants it to start earlier. Note + * that the expansion may get further extended if the VM wishes to + * insert THPs and the preferred start and/or end wind up in the middle + * of THPs. + * + * If this is the case, however, the THP size should be an integer + * multiple of the cache granule size, so we get a whole number of + * granules to deal with. + */ + if (rreq->start !=3D readahead_pos(ractl) || + rreq->len !=3D readahead_length(ractl)) { + readahead_expand(ractl, rreq->start, rreq->len); + rreq->start =3D readahead_pos(ractl); + rreq->len =3D readahead_length(ractl); + + trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl), + netfs_read_trace_expanded); + } +} + +/** + * netfs_readahead - Helper to manage a read request + * @ractl: The description of the readahead request + * + * Fulfil a readahead request by drawing data from the cache if possible, = or + * the netfs if not. Space beyond the EOF is zero-filled. Multiple I/O + * requests from different sources will get munged together. If necessary= , the + * readahead window can be expanded in either direction to a more convenie= nt + * alighment for RPC efficiency or to make storage in the cache feasible. + * + * The calling netfs must initialise a netfs context contiguous to the vfs + * inode before calling this. + * + * This is usable whether or not caching is enabled. + */ +void netfs_readahead(struct readahead_control *ractl) +{ + struct netfs_io_request *rreq; + struct netfs_i_context *ctx =3D netfs_i_context(ractl->mapping->host); + int ret; + + _enter("%lx,%x", readahead_index(ractl), readahead_count(ractl)); + + if (readahead_count(ractl) =3D=3D 0) + return; + + rreq =3D netfs_alloc_request(ractl->mapping, ractl->file, + readahead_pos(ractl), + readahead_length(ractl), + NETFS_READAHEAD); + if (IS_ERR(rreq)) + return; + + if (ctx->ops->begin_cache_operation) { + ret =3D ctx->ops->begin_cache_operation(rreq); + if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) + goto cleanup_free; + } + + netfs_stat(&netfs_n_rh_readahead); + trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl), + netfs_read_trace_readahead); + + netfs_rreq_expand(rreq, ractl); + + /* Drop the refs on the folios here rather than in the cache or + * filesystem. The locks will be dropped in netfs_rreq_unlock(). + */ + while (readahead_folio(ractl)) + ; + + netfs_begin_read(rreq, false); + return; + +cleanup_free: + netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); + return; +} +EXPORT_SYMBOL(netfs_readahead); + +/** + * netfs_readpage - Helper to manage a readpage request + * @file: The file to read from + * @subpage: A subpage of the folio to read + * + * Fulfil a readpage request by drawing data from the cache if possible, o= r the + * netfs if not. Space beyond the EOF is zero-filled. Multiple I/O reque= sts + * from different sources will get munged together. + * + * The calling netfs must initialise a netfs context contiguous to the vfs + * inode before calling this. + * + * This is usable whether or not caching is enabled. + */ +int netfs_readpage(struct file *file, struct page *subpage) +{ + struct folio *folio =3D page_folio(subpage); + struct address_space *mapping =3D folio_file_mapping(folio); + struct netfs_io_request *rreq; + struct netfs_i_context *ctx =3D netfs_i_context(mapping->host); + int ret; + + _enter("%lx", folio_index(folio)); + + rreq =3D netfs_alloc_request(mapping, file, + folio_file_pos(folio), folio_size(folio), + NETFS_READPAGE); + if (IS_ERR(rreq)) { + ret =3D PTR_ERR(rreq); + goto alloc_error; + } + + if (ctx->ops->begin_cache_operation) { + ret =3D ctx->ops->begin_cache_operation(rreq); + if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) + goto discard; + } + + netfs_stat(&netfs_n_rh_readpage); + trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage); + return netfs_begin_read(rreq, true); + +discard: + netfs_put_request(rreq, false, netfs_rreq_trace_put_discard); +alloc_error: + folio_unlock(folio); + return ret; +} +EXPORT_SYMBOL(netfs_readpage); + +/* + * Prepare a folio for writing without reading first + * @folio: The folio being prepared + * @pos: starting position for the write + * @len: length of write + * @always_fill: T if the folio should always be completely filled/cleared + * + * In some cases, write_begin doesn't need to read at all: + * - full folio write + * - write that lies in a folio that is completely beyond EOF + * - write that covers the folio from start to EOF or beyond it + * + * If any of these criteria are met, then zero out the unwritten parts + * of the folio and return true. Otherwise, return false. + */ +static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t = len, + bool always_fill) +{ + struct inode *inode =3D folio_inode(folio); + loff_t i_size =3D i_size_read(inode); + size_t offset =3D offset_in_folio(folio, pos); + size_t plen =3D folio_size(folio); + + if (unlikely(always_fill)) { + if (pos - offset + len <=3D i_size) + return false; /* Page entirely before EOF */ + zero_user_segment(&folio->page, 0, plen); + folio_mark_uptodate(folio); + return true; + } + + /* Full folio write */ + if (offset =3D=3D 0 && len >=3D plen) + return true; + + /* Page entirely beyond the end of the file */ + if (pos - offset >=3D i_size) + goto zero_out; + + /* Write that covers from the start of the folio to EOF or beyond */ + if (offset =3D=3D 0 && (pos + len) >=3D i_size) + goto zero_out; + + return false; +zero_out: + zero_user_segments(&folio->page, 0, offset, offset + len, len); + return true; +} + +/** + * netfs_write_begin - Helper to prepare for writing + * @file: The file to read from + * @mapping: The mapping to read from + * @pos: File position at which the write will begin + * @len: The length of the write (may extend beyond the end of the folio c= hosen) + * @aop_flags: AOP_* flags + * @_folio: Where to put the resultant folio + * @_fsdata: Place for the netfs to store a cookie + * + * Pre-read data for a write-begin request by drawing data from the cache = if + * possible, or the netfs if not. Space beyond the EOF is zero-filled. + * Multiple I/O requests from different sources will get munged together. = If + * necessary, the readahead window can be expanded in either direction to a + * more convenient alighment for RPC efficiency or to make storage in the = cache + * feasible. + * + * The calling netfs must provide a table of operations, only one of which, + * issue_op, is mandatory. + * + * The check_write_begin() operation can be provided to check for and flush + * conflicting writes once the folio is grabbed and locked. It is passed a + * pointer to the fsdata cookie that gets returned to the VM to be passed = to + * write_end. It is permitted to sleep. It should return 0 if the request + * should go ahead; unlock the folio and return -EAGAIN to cause the folio= to + * be regot; or return an error. + * + * The calling netfs must initialise a netfs context contiguous to the vfs + * inode before calling this. + * + * This is usable whether or not caching is enabled. + */ +int netfs_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int aop_flags, + struct folio **_folio, void **_fsdata) +{ + struct netfs_io_request *rreq; + struct netfs_i_context *ctx =3D netfs_i_context(file_inode(file )); + struct folio *folio; + unsigned int fgp_flags; + pgoff_t index =3D pos >> PAGE_SHIFT; + int ret; + + DEFINE_READAHEAD(ractl, file, NULL, mapping, index); + +retry: + fgp_flags =3D FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_STABLE; + if (aop_flags & AOP_FLAG_NOFS) + fgp_flags |=3D FGP_NOFS; + folio =3D __filemap_get_folio(mapping, index, fgp_flags, + mapping_gfp_mask(mapping)); + if (!folio) + return -ENOMEM; + + if (ctx->ops->check_write_begin) { + /* Allow the netfs (eg. ceph) to flush conflicts. */ + ret =3D ctx->ops->check_write_begin(file, pos, len, folio, _fsdata); + if (ret < 0) { + trace_netfs_failure(NULL, NULL, ret, netfs_fail_check_write_begin); + if (ret =3D=3D -EAGAIN) + goto retry; + goto error; + } + } + + if (folio_test_uptodate(folio)) + goto have_folio; + + /* If the page is beyond the EOF, we want to clear it - unless it's + * within the cache granule containing the EOF, in which case we need + * to preload the granule. + */ + if (!netfs_is_cache_enabled(ctx) && + netfs_skip_folio_read(folio, pos, len, false)) { + netfs_stat(&netfs_n_rh_write_zskip); + goto have_folio_no_wait; + } + + rreq =3D netfs_alloc_request(mapping, file, + folio_file_pos(folio), folio_size(folio), + NETFS_READ_FOR_WRITE); + if (IS_ERR(rreq)) { + ret =3D PTR_ERR(rreq); + goto error; + } + rreq->no_unlock_folio =3D folio_index(folio); + __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); + + if (ctx->ops->begin_cache_operation) { + ret =3D ctx->ops->begin_cache_operation(rreq); + if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) + goto error_put; + } + + netfs_stat(&netfs_n_rh_write_begin); + trace_netfs_read(rreq, pos, len, netfs_read_trace_write_begin); + + /* Expand the request to meet caching requirements and download + * preferences. + */ + ractl._nr_pages =3D folio_nr_pages(folio); + netfs_rreq_expand(rreq, &ractl); + + /* We hold the folio locks, so we can drop the references */ + folio_get(folio); + while (readahead_folio(&ractl)) + ; + + ret =3D netfs_begin_read(rreq, true); + if (ret < 0) + goto error; + +have_folio: + ret =3D folio_wait_fscache_killable(folio); + if (ret < 0) + goto error; +have_folio_no_wait: + *_folio =3D folio; + _leave(" =3D 0"); + return 0; + +error_put: + netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); +error: + folio_unlock(folio); + folio_put(folio); + _leave(" =3D %d", ret); + return ret; +} +EXPORT_SYMBOL(netfs_write_begin); diff --git a/fs/netfs/io.c b/fs/netfs/io.c index d448dc4f1010..6d43f9ea1b5a 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -246,91 +246,6 @@ static void netfs_rreq_write_to_cache(struct netfs_io_= request *rreq) BUG(); } =20 -/* - * Unlock the folios in a read operation. We need to set PG_fscache on any - * folios we're going to write back before we unlock them. - */ -void netfs_rreq_unlock_folios(struct netfs_io_request *rreq) -{ - struct netfs_io_subrequest *subreq; - struct folio *folio; - unsigned int iopos, account =3D 0; - pgoff_t start_page =3D rreq->start / PAGE_SIZE; - pgoff_t last_page =3D ((rreq->start + rreq->len) / PAGE_SIZE) - 1; - bool subreq_failed =3D false; - - XA_STATE(xas, &rreq->mapping->i_pages, start_page); - - if (test_bit(NETFS_RREQ_FAILED, &rreq->flags)) { - __clear_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags); - list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { - __clear_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); - } - } - - /* Walk through the pagecache and the I/O request lists simultaneously. - * We may have a mixture of cached and uncached sections and we only - * really want to write out the uncached sections. This is slightly - * complicated by the possibility that we might have huge pages with a - * mixture inside. - */ - subreq =3D list_first_entry(&rreq->subrequests, - struct netfs_io_subrequest, rreq_link); - iopos =3D 0; - subreq_failed =3D (subreq->error < 0); - - trace_netfs_rreq(rreq, netfs_rreq_trace_unlock); - - rcu_read_lock(); - xas_for_each(&xas, folio, last_page) { - unsigned int pgpos =3D (folio_index(folio) - start_page) * PAGE_SIZE; - unsigned int pgend =3D pgpos + folio_size(folio); - bool pg_failed =3D false; - - for (;;) { - if (!subreq) { - pg_failed =3D true; - break; - } - if (test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) - folio_start_fscache(folio); - pg_failed |=3D subreq_failed; - if (pgend < iopos + subreq->len) - break; - - account +=3D subreq->transferred; - iopos +=3D subreq->len; - if (!list_is_last(&subreq->rreq_link, &rreq->subrequests)) { - subreq =3D list_next_entry(subreq, rreq_link); - subreq_failed =3D (subreq->error < 0); - } else { - subreq =3D NULL; - subreq_failed =3D false; - } - if (pgend =3D=3D iopos) - break; - } - - if (!pg_failed) { - flush_dcache_folio(folio); - folio_mark_uptodate(folio); - } - - if (!test_bit(NETFS_RREQ_DONT_UNLOCK_FOLIOS, &rreq->flags)) { - if (folio_index(folio) =3D=3D rreq->no_unlock_folio && - test_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags)) - _debug("no unlock"); - else - folio_unlock(folio); - } - } - rcu_read_unlock(); - - task_io_account_read(account); - if (rreq->netfs_ops->done) - rreq->netfs_ops->done(rreq); -} - /* * Handle a short read. */ @@ -750,336 +665,3 @@ int netfs_begin_read(struct netfs_io_request *rreq, b= ool sync) } return ret; } - -static void netfs_cache_expand_readahead(struct netfs_io_request *rreq, - loff_t *_start, size_t *_len, loff_t i_size) -{ - struct netfs_cache_resources *cres =3D &rreq->cache_resources; - - if (cres->ops && cres->ops->expand_readahead) - cres->ops->expand_readahead(cres, _start, _len, i_size); -} - -static void netfs_rreq_expand(struct netfs_io_request *rreq, - struct readahead_control *ractl) -{ - /* Give the cache a chance to change the request parameters. The - * resultant request must contain the original region. - */ - netfs_cache_expand_readahead(rreq, &rreq->start, &rreq->len, rreq->i_size= ); - - /* Give the netfs a chance to change the request parameters. The - * resultant request must contain the original region. - */ - if (rreq->netfs_ops->expand_readahead) - rreq->netfs_ops->expand_readahead(rreq); - - /* Expand the request if the cache wants it to start earlier. Note - * that the expansion may get further extended if the VM wishes to - * insert THPs and the preferred start and/or end wind up in the middle - * of THPs. - * - * If this is the case, however, the THP size should be an integer - * multiple of the cache granule size, so we get a whole number of - * granules to deal with. - */ - if (rreq->start !=3D readahead_pos(ractl) || - rreq->len !=3D readahead_length(ractl)) { - readahead_expand(ractl, rreq->start, rreq->len); - rreq->start =3D readahead_pos(ractl); - rreq->len =3D readahead_length(ractl); - - trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl), - netfs_read_trace_expanded); - } -} - -/** - * netfs_readahead - Helper to manage a read request - * @ractl: The description of the readahead request - * - * Fulfil a readahead request by drawing data from the cache if possible, = or - * the netfs if not. Space beyond the EOF is zero-filled. Multiple I/O - * requests from different sources will get munged together. If necessary= , the - * readahead window can be expanded in either direction to a more convenie= nt - * alighment for RPC efficiency or to make storage in the cache feasible. - * - * The calling netfs must initialise a netfs context contiguous to the vfs - * inode before calling this. - * - * This is usable whether or not caching is enabled. - */ -void netfs_readahead(struct readahead_control *ractl) -{ - struct netfs_io_request *rreq; - struct netfs_i_context *ctx =3D netfs_i_context(ractl->mapping->host); - int ret; - - _enter("%lx,%x", readahead_index(ractl), readahead_count(ractl)); - - if (readahead_count(ractl) =3D=3D 0) - return; - - rreq =3D netfs_alloc_request(ractl->mapping, ractl->file, - readahead_pos(ractl), - readahead_length(ractl), - NETFS_READAHEAD); - if (IS_ERR(rreq)) - return; - - if (ctx->ops->begin_cache_operation) { - ret =3D ctx->ops->begin_cache_operation(rreq); - if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) - goto cleanup_free; - } - - netfs_stat(&netfs_n_rh_readahead); - trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl), - netfs_read_trace_readahead); - - netfs_rreq_expand(rreq, ractl); - - /* Drop the refs on the folios here rather than in the cache or - * filesystem. The locks will be dropped in netfs_rreq_unlock(). - */ - while (readahead_folio(ractl)) - ; - - netfs_begin_read(rreq, false); - return; - -cleanup_free: - netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); - return; -} -EXPORT_SYMBOL(netfs_readahead); - -/** - * netfs_readpage - Helper to manage a readpage request - * @file: The file to read from - * @subpage: A subpage of the folio to read - * - * Fulfil a readpage request by drawing data from the cache if possible, o= r the - * netfs if not. Space beyond the EOF is zero-filled. Multiple I/O reque= sts - * from different sources will get munged together. - * - * The calling netfs must initialise a netfs context contiguous to the vfs - * inode before calling this. - * - * This is usable whether or not caching is enabled. - */ -int netfs_readpage(struct file *file, struct page *subpage) -{ - struct folio *folio =3D page_folio(subpage); - struct address_space *mapping =3D folio->mapping; - struct netfs_io_request *rreq; - struct netfs_i_context *ctx =3D netfs_i_context(mapping->host); - int ret; - - _enter("%lx", folio_index(folio)); - - rreq =3D netfs_alloc_request(mapping, file, - folio_file_pos(folio), folio_size(folio), - NETFS_READPAGE); - if (IS_ERR(rreq)) { - ret =3D PTR_ERR(rreq); - goto alloc_error; - } - - if (ctx->ops->begin_cache_operation) { - ret =3D ctx->ops->begin_cache_operation(rreq); - if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) - goto discard; - } - - netfs_stat(&netfs_n_rh_readpage); - trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage); - return netfs_begin_read(rreq, true); - -discard: - netfs_put_request(rreq, false, netfs_rreq_trace_put_discard); -alloc_error: - folio_unlock(folio); - return ret; -} -EXPORT_SYMBOL(netfs_readpage); - -/* - * Prepare a folio for writing without reading first - * @folio: The folio being prepared - * @pos: starting position for the write - * @len: length of write - * @always_fill: T if the folio should always be completely filled/cleared - * - * In some cases, write_begin doesn't need to read at all: - * - full folio write - * - write that lies in a folio that is completely beyond EOF - * - write that covers the folio from start to EOF or beyond it - * - * If any of these criteria are met, then zero out the unwritten parts - * of the folio and return true. Otherwise, return false. - */ -static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t = len, - bool always_fill) -{ - struct inode *inode =3D folio_inode(folio); - loff_t i_size =3D i_size_read(inode); - size_t offset =3D offset_in_folio(folio, pos); - size_t plen =3D folio_size(folio); - - if (unlikely(always_fill)) { - if (pos - offset + len <=3D i_size) - return false; /* Page entirely before EOF */ - zero_user_segment(&folio->page, 0, plen); - folio_mark_uptodate(folio); - return true; - } - - /* Full folio write */ - if (offset =3D=3D 0 && len >=3D plen) - return true; - - /* Page entirely beyond the end of the file */ - if (pos - offset >=3D i_size) - goto zero_out; - - /* Write that covers from the start of the folio to EOF or beyond */ - if (offset =3D=3D 0 && (pos + len) >=3D i_size) - goto zero_out; - - return false; -zero_out: - zero_user_segments(&folio->page, 0, offset, offset + len, len); - return true; -} - -/** - * netfs_write_begin - Helper to prepare for writing - * @file: The file to read from - * @mapping: The mapping to read from - * @pos: File position at which the write will begin - * @len: The length of the write (may extend beyond the end of the folio c= hosen) - * @aop_flags: AOP_* flags - * @_folio: Where to put the resultant folio - * @_fsdata: Place for the netfs to store a cookie - * - * Pre-read data for a write-begin request by drawing data from the cache = if - * possible, or the netfs if not. Space beyond the EOF is zero-filled. - * Multiple I/O requests from different sources will get munged together. = If - * necessary, the readahead window can be expanded in either direction to a - * more convenient alighment for RPC efficiency or to make storage in the = cache - * feasible. - * - * The calling netfs must provide a table of operations, only one of which, - * issue_op, is mandatory. - * - * The check_write_begin() operation can be provided to check for and flush - * conflicting writes once the folio is grabbed and locked. It is passed a - * pointer to the fsdata cookie that gets returned to the VM to be passed = to - * write_end. It is permitted to sleep. It should return 0 if the request - * should go ahead; unlock the folio and return -EAGAIN to cause the folio= to - * be regot; or return an error. - * - * The calling netfs must initialise a netfs context contiguous to the vfs - * inode before calling this. - * - * This is usable whether or not caching is enabled. - */ -int netfs_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned int len, unsigned int aop_flags, - struct folio **_folio, void **_fsdata) -{ - struct netfs_io_request *rreq; - struct netfs_i_context *ctx =3D netfs_i_context(file_inode(file )); - struct folio *folio; - unsigned int fgp_flags; - pgoff_t index =3D pos >> PAGE_SHIFT; - int ret; - - DEFINE_READAHEAD(ractl, file, NULL, mapping, index); - -retry: - fgp_flags =3D FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_STABLE; - if (aop_flags & AOP_FLAG_NOFS) - fgp_flags |=3D FGP_NOFS; - folio =3D __filemap_get_folio(mapping, index, fgp_flags, - mapping_gfp_mask(mapping)); - if (!folio) - return -ENOMEM; - - if (ctx->ops->check_write_begin) { - /* Allow the netfs (eg. ceph) to flush conflicts. */ - ret =3D ctx->ops->check_write_begin(file, pos, len, folio, _fsdata); - if (ret < 0) { - trace_netfs_failure(NULL, NULL, ret, netfs_fail_check_write_begin); - if (ret =3D=3D -EAGAIN) - goto retry; - goto error; - } - } - - if (folio_test_uptodate(folio)) - goto have_folio; - - /* If the page is beyond the EOF, we want to clear it - unless it's - * within the cache granule containing the EOF, in which case we need - * to preload the granule. - */ - if (!netfs_is_cache_enabled(ctx) && - netfs_skip_folio_read(folio, pos, len, false)) { - netfs_stat(&netfs_n_rh_write_zskip); - goto have_folio_no_wait; - } - - rreq =3D netfs_alloc_request(mapping, file, - folio_file_pos(folio), folio_size(folio), - NETFS_READ_FOR_WRITE); - if (IS_ERR(rreq)) { - ret =3D PTR_ERR(rreq); - goto error; - } - rreq->no_unlock_folio =3D folio_index(folio); - __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); - - if (ctx->ops->begin_cache_operation) { - ret =3D ctx->ops->begin_cache_operation(rreq); - if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) - goto error_put; - } - - netfs_stat(&netfs_n_rh_write_begin); - trace_netfs_read(rreq, pos, len, netfs_read_trace_write_begin); - - /* Expand the request to meet caching requirements and download - * preferences. - */ - ractl._nr_pages =3D folio_nr_pages(folio); - netfs_rreq_expand(rreq, &ractl); - - /* We hold the folio locks, so we can drop the references */ - folio_get(folio); - while (readahead_folio(&ractl)) - ; - - ret =3D netfs_begin_read(rreq, true); - if (ret < 0) - goto error; - -have_folio: - ret =3D folio_wait_fscache_killable(folio); - if (ret < 0) - goto error; -have_folio_no_wait: - *_folio =3D folio; - _leave(" =3D 0"); - return 0; - -error_put: - netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); -error: - folio_unlock(folio); - folio_put(folio); - _leave(" =3D %d", ret); - return ret; -} -EXPORT_SYMBOL(netfs_write_begin); From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2EDB0C433EF for ; Thu, 10 Mar 2022 16:22:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243919AbiCJQXk (ORCPT ); Thu, 10 Mar 2022 11:23:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41956 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241963AbiCJQWY (ORCPT ); Thu, 10 Mar 2022 11:22:24 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 68BFA198D1C for ; Thu, 10 Mar 2022 08:20:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929216; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Vx29rT5TlHTfNGQkxguW5BNxDabNH2dmb1JDbWcqEMk=; b=hLtkkC7zbdoPfFL1ifyZBnzS9kMqTDfrOknAamIP5ihprG10GHAILCdL7VU3EnAImWIGzP 5dZXlUBOqzALdb7CD2ZaYyI0V2l236UGEW3hKgwIR8Jf/1Ohy+U2yPf7o8GhFXQJZ4Qf3L cPPJR+4988B/ReHUGHh6rph5hDJrMLg= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-28-v9Q8EBx7MqaLc751bjzqdQ-1; Thu, 10 Mar 2022 11:20:15 -0500 X-MC-Unique: v9Q8EBx7MqaLc751bjzqdQ-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 672C51091DA2; Thu, 10 Mar 2022 16:20:13 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4E4637C038; Thu, 10 Mar 2022 16:20:10 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 18/20] netfs: Split some core bits out into their own file From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:20:09 +0000 Message-ID: <164692920944.2099075.11990502173226013856.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Split some core bits out into their own file. More bits will be added to this file later. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164623006934.3564931.17932680017894039748.s= tgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678218407.1200972.1731208226140990280.st= git@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/netfs/Makefile | 1 + fs/netfs/internal.h | 7 +++++-- fs/netfs/io.c | 10 ---------- fs/netfs/main.c | 20 ++++++++++++++++++++ 4 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 fs/netfs/main.c diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index 88b904532bc7..f684c0cd1ec5 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -3,6 +3,7 @@ netfs-y :=3D \ buffered_read.o \ io.o \ + main.o \ objects.o =20 netfs-$(CONFIG_NETFS_STATS) +=3D stats.o diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 1cd2778bfa7d..622b421d4753 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -23,10 +23,13 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *= rreq); /* * io.c */ -extern unsigned int netfs_debug; - int netfs_begin_read(struct netfs_io_request *rreq, bool sync); =20 +/* + * main.c + */ +extern unsigned int netfs_debug; + /* * objects.c */ diff --git a/fs/netfs/io.c b/fs/netfs/io.c index 6d43f9ea1b5a..428925899282 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -15,16 +15,6 @@ #include #include #include "internal.h" -#define CREATE_TRACE_POINTS -#include - -MODULE_DESCRIPTION("Network fs support"); -MODULE_AUTHOR("Red Hat, Inc."); -MODULE_LICENSE("GPL"); - -unsigned netfs_debug; -module_param_named(debug, netfs_debug, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask"); =20 /* * Clear the unread part of an I/O request. diff --git a/fs/netfs/main.c b/fs/netfs/main.c new file mode 100644 index 000000000000..068568702957 --- /dev/null +++ b/fs/netfs/main.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Miscellaneous bits for the netfs support library. + * + * Copyright (C) 2022 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include +#include +#include "internal.h" +#define CREATE_TRACE_POINTS +#include + +MODULE_DESCRIPTION("Network fs support"); +MODULE_AUTHOR("Red Hat, Inc."); +MODULE_LICENSE("GPL"); + +unsigned netfs_debug; +module_param_named(debug, netfs_debug, uint, S_IWUSR | S_IRUGO); +MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask"); From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 898CFC433F5 for ; Thu, 10 Mar 2022 16:22:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242855AbiCJQXu (ORCPT ); Thu, 10 Mar 2022 11:23:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42116 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244335AbiCJQW6 (ORCPT ); Thu, 10 Mar 2022 11:22:58 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 1D19C19BE4F for ; Thu, 10 Mar 2022 08:20:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929236; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4VDtuLWXavBV/HS2lCkWzp80ZEjJiDU9cATmIiTQeMQ=; b=H6t8Iy5cVI5RoYEQ/HNw3I+ozz8Ws42NIln+dYVAPBq0Htdrt0+zJUg7LmTmSKHOM1dZAx x1HkK1aCZzio5+aoAoXheJ24WTBHs7lkJ1eGkGKVGhoewo84Jnh76HHGqcR1IEuSWFvauQ QFepy7lSUedUFtIGqHTznr2elkU0Fno= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-85-fKSWy9FZOjiXgqUdR_ymBA-1; Thu, 10 Mar 2022 11:20:34 -0500 X-MC-Unique: fKSWy9FZOjiXgqUdR_ymBA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id AA8921006AA5; Thu, 10 Mar 2022 16:20:30 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 81B261073025; Thu, 10 Mar 2022 16:20:19 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 19/20] netfs: Keep track of the actual remote file size From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:20:18 +0000 Message-ID: <164692921865.2099075.5310757978508056134.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Provide a place in which to keep track of the actual remote file size in the netfs context. This is needed because inode->i_size will be updated as we buffer writes in the pagecache, but the server file size won't get updated until we flush them back. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164623013727.3564931.17659955636985232717.s= tgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678219305.1200972.6459431995188365134.st= git@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- include/linux/netfs.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 8458b30172a5..c7bf1eaf51d5 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -126,6 +126,7 @@ struct netfs_i_context { #if IS_ENABLED(CONFIG_FSCACHE) struct fscache_cookie *cache; #endif + loff_t remote_i_size; /* Size of the remote file */ }; =20 /* @@ -324,6 +325,21 @@ static inline void netfs_i_context_init(struct inode *= inode, =20 memset(ctx, 0, sizeof(*ctx)); ctx->ops =3D ops; + ctx->remote_i_size =3D i_size_read(inode); +} + +/** + * netfs_resize_file - Note that a file got resized + * @inode: The inode being resized + * @new_i_size: The new file size + * + * Inform the netfs lib that a file got resized so that it can adjust its = state. + */ +static inline void netfs_resize_file(struct inode *inode, loff_t new_i_siz= e) +{ + struct netfs_i_context *ctx =3D netfs_i_context(inode); + + ctx->remote_i_size =3D new_i_size; } =20 /** From nobody Tue Jun 23 08:15:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 61C14C433EF for ; Thu, 10 Mar 2022 16:23:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244190AbiCJQY3 (ORCPT ); Thu, 10 Mar 2022 11:24:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42106 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244838AbiCJQXO (ORCPT ); Thu, 10 Mar 2022 11:23:14 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 70C9F1986FB for ; Thu, 10 Mar 2022 08:21:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646929289; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6OEvdGln4GLB/K6WbXv/BIS67SElyOgtgishIXX+IXU=; b=SQo9TRpbuRykNsn+zSkuGI/UeWhQ7D9Zt9GlLfwk4XGiz/VKsEAgnfh78siEt1V5awALOX GEY5u1UMTvHDqb/KVmneZJSBM5XqQELxotEygr+tcLrISsg/nrzhHoJ5tejkmfruSN6Dhl MLf5xqmrW5bpWodFsutdAT427VdGY4A= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-231-ixK_enuePSaw29LoFcSyjg-1; Thu, 10 Mar 2022 11:21:24 -0500 X-MC-Unique: ixK_enuePSaw29LoFcSyjg-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 25C5F1854E31; Thu, 10 Mar 2022 16:21:04 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 089AB7C04D; Thu, 10 Mar 2022 16:20:36 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH v3 20/20] afs: Maintain netfs_i_context::remote_i_size From: David Howells To: linux-cachefs@redhat.com Cc: Jeff Layton , linux-afs@lists.infradead.org, dhowells@redhat.com, Anna Schumaker , Steve French , Dominique Martinet , Jeff Layton , David Wysochanski , Ilya Dryomov , Jeffle Xu , Linus Torvalds , linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 10 Mar 2022 16:20:35 +0000 Message-ID: <164692923592.2099075.5466132542956550401.stgit@warthog.procyon.org.uk> In-Reply-To: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> References: <164692883658.2099075.5745824552116419504.stgit@warthog.procyon.org.uk> User-Agent: StGit/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Make afs use netfslib's tracking for the server's idea of what the current inode size is independently of inode->i_size. We really want to use this value when calculating the new vnode size when initiating a StoreData RPC op rather than the size stat() presents to the user (ie. inode->i_size) as the latter is affected by as-yet uncommitted writes. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-afs@lists.infradead.org Link: https://lore.kernel.org/r/164623014626.3564931.8375344024648265358.st= git@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678220204.1200972.17408022517463940584.s= tgit@warthog.procyon.org.uk/ # v2 Tested-by: Dominique Martinet # 9p Tested-by: Jeff Layton --- fs/afs/inode.c | 1 + fs/afs/write.c | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 5b5e40197655..2fe402483ad5 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -246,6 +246,7 @@ static void afs_apply_status(struct afs_operation *op, * idea of what the size should be that's not the same as * what's on the server. */ + vnode->netfs_ctx.remote_i_size =3D status->size; if (change_size) { afs_set_i_size(vnode, status->size); inode->i_ctime =3D t; diff --git a/fs/afs/write.c b/fs/afs/write.c index e4b47f67a408..85c9056ba9fb 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -353,9 +353,10 @@ static const struct afs_operation_ops afs_store_data_o= peration =3D { static int afs_store_data(struct afs_vnode *vnode, struct iov_iter *iter, = loff_t pos, bool laundering) { + struct netfs_i_context *ictx =3D &vnode->netfs_ctx; struct afs_operation *op; struct afs_wb_key *wbk =3D NULL; - loff_t size =3D iov_iter_count(iter), i_size; + loff_t size =3D iov_iter_count(iter); int ret =3D -ENOKEY; =20 _enter("%s{%llx:%llu.%u},%llx,%llx", @@ -377,15 +378,13 @@ static int afs_store_data(struct afs_vnode *vnode, st= ruct iov_iter *iter, loff_t return -ENOMEM; } =20 - i_size =3D i_size_read(&vnode->vfs_inode); - afs_op_set_vnode(op, 0, vnode); op->file[0].dv_delta =3D 1; op->file[0].modification =3D true; op->store.write_iter =3D iter; op->store.pos =3D pos; op->store.size =3D size; - op->store.i_size =3D max(pos + size, i_size); + op->store.i_size =3D max(pos + size, ictx->remote_i_size); op->store.laundering =3D laundering; op->mtime =3D vnode->vfs_inode.i_mtime; op->flags |=3D AFS_OPERATION_UNINTR;