From patchwork Wed Dec 13 15:23:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491207 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 52DF1C4332F for ; Wed, 13 Dec 2023 15:24:08 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 386376B02C8; Wed, 13 Dec 2023 10:24:07 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 297856B02E3; Wed, 13 Dec 2023 10:24:07 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 077816B02EB; Wed, 13 Dec 2023 10:24:06 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id E44166B02C8 for ; Wed, 13 Dec 2023 10:24:06 -0500 (EST) Received: from smtpin14.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id B1FAC80213 for ; Wed, 13 Dec 2023 15:24:06 +0000 (UTC) X-FDA: 81562165692.14.BEB8DFA Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf05.hostedemail.com (Postfix) with ESMTP id E4A44100021 for ; Wed, 13 Dec 2023 15:24:04 +0000 (UTC) Authentication-Results: imf05.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=OUs5lJOd; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf05.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481045; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=5AXujXz3QZo64NpPid5/uzblwNcf/fEUZkXIJcV2mdU=; b=dnLCWPHdDK6KoONsSGDS+j9Fm6a2+CihwMOOJqU8Jz0cp4xX6wS3vlk2g1EuAk5aB7TO4W A9dP9lygWU0fidmton4u1ibemQO/AuMmiMhWJRFfbxTJH2ZTIK0jPedNmU8TEOJGoLCKOh 6r/I6muhHlgAuy6O6wYBnIeLYGPqKYY= ARC-Authentication-Results: i=1; imf05.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=OUs5lJOd; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf05.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481045; a=rsa-sha256; cv=none; b=WQ4U0zHyqLjOBNto4d3zook4sT8QIbuWQ+i7sXbxvlWsRZcT+dSb0BzkPkXjJ5JMWQh4v+ CcZqs4ssUhnlVyuJTYyiACNG7go3T0hccf0/3j0ojKgV+GZdF7J2jCrxtCDiJ8sZ1LjcRi 3cD++0/1+cxgIyVnPI0lgVQy4hREy5g= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481044; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5AXujXz3QZo64NpPid5/uzblwNcf/fEUZkXIJcV2mdU=; b=OUs5lJOdhHDRP1yfPYit/BVg//AG6zpb3ZzLbtWczwzXmixNmeXPD7qxrmHNj1s8ejIz9i J7Lrucw7EuxjZwPlRgpMvCpeJcNdSrjarSLXXHkxmZTsCD3aJY89YYR4Em4opw9A1OYQ0x g/F0XPryRSkDbNJzohQs6n77+4VFYNo= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-433-5mjsK05sNA-sGk1TIeUmzQ-1; Wed, 13 Dec 2023 10:24:00 -0500 X-MC-Unique: 5mjsK05sNA-sGk1TIeUmzQ-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6666E881B6B; Wed, 13 Dec 2023 15:23:59 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8C2ED492BC8; Wed, 13 Dec 2023 15:23:56 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 01/39] netfs, fscache: Move fs/fscache/* into fs/netfs/ Date: Wed, 13 Dec 2023 15:23:11 +0000 Message-ID: <20231213152350.431591-2-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.9 X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: E4A44100021 X-Stat-Signature: rmtj9bapw6abgwhtr3je89b1no5bomx1 X-HE-Tag: 1702481044-812909 X-HE-Meta: U2FsdGVkX18dNRrm9FrTMK0dHG23P98hNRRZ1WinpnmxwMOUOIsJDhSBuwBIhLjyavznq2CG2ELY1x3HQ1ncsyNIBWZxcWj+UmzMnA6nY9Ycm2qRszDFEaEfR6IqG14QrI5v7vbmB1CwQqpR4gq/MuJClCv5lmHqvONMZcrcSKq6aAPVbIyfdKd7/KOudXqPD/PJWbdqKRT7l2xCa9oj+6iyy0rBpPCgdxgOffzBvFEegSt6C2ZZLC85gU9/BP/VuTMTKdpriYt9Pjwc2GmNoTyiRFj2NuAYS/KyF+5pLNTFFJ9nQdrPnt3SGDtH0i67d8XxBSLPi22jUKSVvRatkLtaRUaPiZUQAbwjMBEkPPfWO1YYO/lrgLz8aJqnJY/+jeGjw8AgcS4w6FYv0ZPZzFTF94BNvBJ55JvDatPUS3R5mXfNQpYvTQgRf6/d9BHxIass/gHKWEF78nUx+PPnzm21klg8vcixKHxzATbdrloSsZblBKV8bbcZjjcwIhs/Cdco0AAJRBHG8vX/x5jchhCXk37V5suzewpHozazjR4U/WZvHHE273iqNSJUmCKU0jH+CzooT1Y2ooT+GnNELFYvtDSYcjvYllsOxg3jF7B+9FLdyiwX0/UiWXnDmKiARMLo2UKx6EwADgcQxtRdsC3XyfNnQzhzIuwsqvXBGDFax9nWs0A0lIntQ9PfrtRIq0qfsZ5umzBoU/fOsEqpNkFMpUw0xZjtoAaEbTUfzRTqvfRqewblyPEAxJn8QV0rrQP0xTvJS6L16yZlE8ylB11cNsUTCtoKP5jCkFTJmKd6yHsYt0mQ/9d1OcEUnkjNznCDaJMXx4M/37k7I5J0bUFKBNCKOswkjbNp5iZIkpbMCBDA1fxd4BfrOvBiEasKtp5+grB7cuvvrHENgkQ7GE4CkzGK8RSjxicPcO8y9a+8x/HiPxjsHQ3n1rEr4ltbrs2GCvcSjbHcVC5XRDX n2tolvya 3aIhnQhOaV3RiLvz77o+eRDtwfIZ8eewE5sNkE/Lu9mxnRV0B/ppFNfbQFLHs5+1dQnCsCtOJKgG1UAo2Ug7Fy1QUYeZ4ZoV7T1mOCD8k9bbmbl8cSylAiyvC+vsORnaDVeT3jjKoIbMHHXNwFWb4VNP5biXVvoDpbx6u4zHl4DeS7w9FHxioNuJyzXKxCFFRr4aydDg7t0NhS2hCOk+Ihr2ufPBafDAY4xlQz+/x0mBdiEA= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: There's a problem with dependencies between netfslib and fscache as each wants to access some functions of the other. Deal with this by moving fs/fscache/* into fs/netfs/ and renaming those files to begin with "fscache-". For the moment, the moved files are changed as little as possible and an fscache module is still built. A subsequent patch will integrate them. Signed-off-by: David Howells cc: Jeff Layton cc: Christian Brauner cc: linux-fsdevel@vger.kernel.org cc: linux-cachefs@redhat.com --- MAINTAINERS | 2 +- fs/Kconfig | 1 - fs/Makefile | 1 - fs/fscache/Kconfig | 40 ------------------- fs/fscache/Makefile | 16 -------- fs/netfs/Kconfig | 39 ++++++++++++++++++ fs/netfs/Makefile | 14 ++++++- fs/{fscache/cache.c => netfs/fscache_cache.c} | 0 .../cookie.c => netfs/fscache_cookie.c} | 0 .../internal.h => netfs/fscache_internal.h} | 0 fs/{fscache/io.c => netfs/fscache_io.c} | 0 fs/{fscache/main.c => netfs/fscache_main.c} | 0 fs/{fscache/proc.c => netfs/fscache_proc.c} | 0 fs/{fscache/stats.c => netfs/fscache_stats.c} | 0 .../volume.c => netfs/fscache_volume.c} | 0 fs/netfs/internal.h | 5 +++ fs/netfs/main.c | 5 ++- 17 files changed, 61 insertions(+), 62 deletions(-) delete mode 100644 fs/fscache/Kconfig delete mode 100644 fs/fscache/Makefile rename fs/{fscache/cache.c => netfs/fscache_cache.c} (100%) rename fs/{fscache/cookie.c => netfs/fscache_cookie.c} (100%) rename fs/{fscache/internal.h => netfs/fscache_internal.h} (100%) rename fs/{fscache/io.c => netfs/fscache_io.c} (100%) rename fs/{fscache/main.c => netfs/fscache_main.c} (100%) rename fs/{fscache/proc.c => netfs/fscache_proc.c} (100%) rename fs/{fscache/stats.c => netfs/fscache_stats.c} (100%) rename fs/{fscache/volume.c => netfs/fscache_volume.c} (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 902708b4530d..10eff1e83ec1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8617,7 +8617,7 @@ M: David Howells L: linux-cachefs@redhat.com (moderated for non-subscribers) S: Supported F: Documentation/filesystems/caching/ -F: fs/fscache/ +F: fs/netfs/fscache-* F: include/linux/fscache*.h FSCRYPT: FILE SYSTEM LEVEL ENCRYPTION SUPPORT diff --git a/fs/Kconfig b/fs/Kconfig index cf62d86b514f..26c3821bf1fb 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -140,7 +140,6 @@ source "fs/overlayfs/Kconfig" menu "Caches" source "fs/netfs/Kconfig" -source "fs/fscache/Kconfig" source "fs/cachefiles/Kconfig" endmenu diff --git a/fs/Makefile b/fs/Makefile index 75522f88e763..af7632368e98 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -60,7 +60,6 @@ obj-$(CONFIG_DLM) += dlm/ # Do not add any filesystems before this line obj-$(CONFIG_NETFS_SUPPORT) += netfs/ -obj-$(CONFIG_FSCACHE) += fscache/ obj-$(CONFIG_REISERFS_FS) += reiserfs/ obj-$(CONFIG_EXT4_FS) += ext4/ # We place ext4 before ext2 so that clean ext3 root fs's do NOT mount using the diff --git a/fs/fscache/Kconfig b/fs/fscache/Kconfig deleted file mode 100644 index b313a978ae0a..000000000000 --- a/fs/fscache/Kconfig +++ /dev/null @@ -1,40 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -config FSCACHE - tristate "General filesystem local caching manager" - select NETFS_SUPPORT - help - This option enables a generic filesystem caching manager that can be - used by various network and other filesystems to cache data locally. - Different sorts of caches can be plugged in, depending on the - resources available. - - See Documentation/filesystems/caching/fscache.rst for more information. - -config FSCACHE_STATS - bool "Gather statistical information on local caching" - depends on FSCACHE && PROC_FS - select NETFS_STATS - help - This option causes statistical information to be gathered on local - caching and exported through file: - - /proc/fs/fscache/stats - - The gathering of statistics adds a certain amount of overhead to - execution as there are a quite a few stats gathered, and on a - multi-CPU system these may be on cachelines that keep bouncing - between CPUs. On the other hand, the stats are very useful for - debugging purposes. Saying 'Y' here is recommended. - - See Documentation/filesystems/caching/fscache.rst for more information. - -config FSCACHE_DEBUG - bool "Debug FS-Cache" - depends on FSCACHE - help - This permits debugging to be dynamically enabled in the local caching - management module. If this is set, the debugging output may be - enabled by setting bits in /sys/modules/fscache/parameter/debug. - - See Documentation/filesystems/caching/fscache.rst for more information. diff --git a/fs/fscache/Makefile b/fs/fscache/Makefile deleted file mode 100644 index afb090ea16c4..000000000000 --- a/fs/fscache/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for general filesystem caching code -# - -fscache-y := \ - cache.o \ - cookie.o \ - io.o \ - main.o \ - volume.o - -fscache-$(CONFIG_PROC_FS) += proc.o -fscache-$(CONFIG_FSCACHE_STATS) += stats.o - -obj-$(CONFIG_FSCACHE) := fscache.o diff --git a/fs/netfs/Kconfig b/fs/netfs/Kconfig index b4db21022cb4..b4378688357c 100644 --- a/fs/netfs/Kconfig +++ b/fs/netfs/Kconfig @@ -21,3 +21,42 @@ config NETFS_STATS multi-CPU system these may be on cachelines that keep bouncing between CPUs. On the other hand, the stats are very useful for debugging purposes. Saying 'Y' here is recommended. + +config FSCACHE + tristate "General filesystem local caching manager" + select NETFS_SUPPORT + help + This option enables a generic filesystem caching manager that can be + used by various network and other filesystems to cache data locally. + Different sorts of caches can be plugged in, depending on the + resources available. + + See Documentation/filesystems/caching/fscache.rst for more information. + +config FSCACHE_STATS + bool "Gather statistical information on local caching" + depends on FSCACHE && PROC_FS + select NETFS_STATS + help + This option causes statistical information to be gathered on local + caching and exported through file: + + /proc/fs/fscache/stats + + The gathering of statistics adds a certain amount of overhead to + execution as there are a quite a few stats gathered, and on a + multi-CPU system these may be on cachelines that keep bouncing + between CPUs. On the other hand, the stats are very useful for + debugging purposes. Saying 'Y' here is recommended. + + See Documentation/filesystems/caching/fscache.rst for more information. + +config FSCACHE_DEBUG + bool "Debug FS-Cache" + depends on FSCACHE + help + This permits debugging to be dynamically enabled in the local caching + management module. If this is set, the debugging output may be + enabled by setting bits in /sys/modules/fscache/parameter/debug. + + See Documentation/filesystems/caching/fscache.rst for more information. diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index 386d6fb92793..bbb2b824bd5e 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -1,5 +1,17 @@ # SPDX-License-Identifier: GPL-2.0 +fscache-y := \ + fscache_cache.o \ + fscache_cookie.o \ + fscache_io.o \ + fscache_main.o \ + fscache_volume.o + +fscache-$(CONFIG_PROC_FS) += fscache_proc.o +fscache-$(CONFIG_FSCACHE_STATS) += fscache_stats.o + +obj-$(CONFIG_FSCACHE) := fscache.o + netfs-y := \ buffered_read.o \ io.o \ @@ -9,4 +21,4 @@ netfs-y := \ netfs-$(CONFIG_NETFS_STATS) += stats.o -obj-$(CONFIG_NETFS_SUPPORT) := netfs.o +obj-$(CONFIG_NETFS_SUPPORT) += netfs.o diff --git a/fs/fscache/cache.c b/fs/netfs/fscache_cache.c similarity index 100% rename from fs/fscache/cache.c rename to fs/netfs/fscache_cache.c diff --git a/fs/fscache/cookie.c b/fs/netfs/fscache_cookie.c similarity index 100% rename from fs/fscache/cookie.c rename to fs/netfs/fscache_cookie.c diff --git a/fs/fscache/internal.h b/fs/netfs/fscache_internal.h similarity index 100% rename from fs/fscache/internal.h rename to fs/netfs/fscache_internal.h diff --git a/fs/fscache/io.c b/fs/netfs/fscache_io.c similarity index 100% rename from fs/fscache/io.c rename to fs/netfs/fscache_io.c diff --git a/fs/fscache/main.c b/fs/netfs/fscache_main.c similarity index 100% rename from fs/fscache/main.c rename to fs/netfs/fscache_main.c diff --git a/fs/fscache/proc.c b/fs/netfs/fscache_proc.c similarity index 100% rename from fs/fscache/proc.c rename to fs/netfs/fscache_proc.c diff --git a/fs/fscache/stats.c b/fs/netfs/fscache_stats.c similarity index 100% rename from fs/fscache/stats.c rename to fs/netfs/fscache_stats.c diff --git a/fs/fscache/volume.c b/fs/netfs/fscache_volume.c similarity index 100% rename from fs/fscache/volume.c rename to fs/netfs/fscache_volume.c diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 43fac1b14e40..e96432499eb2 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -5,9 +5,12 @@ * Written by David Howells (dhowells@redhat.com) */ +#include +#include #include #include #include +#include "fscache_internal.h" #ifdef pr_fmt #undef pr_fmt @@ -107,6 +110,7 @@ static inline bool netfs_is_cache_enabled(struct netfs_inode *ctx) /* * debug tracing */ +#if 0 #define dbgprintk(FMT, ...) \ printk("[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__) @@ -143,3 +147,4 @@ do { \ #define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__) #define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__) #endif +#endif diff --git a/fs/netfs/main.c b/fs/netfs/main.c index 068568702957..237c54a01d97 100644 --- a/fs/netfs/main.c +++ b/fs/netfs/main.c @@ -8,8 +8,8 @@ #include #include #include "internal.h" -#define CREATE_TRACE_POINTS -#include +//#define CREATE_TRACE_POINTS +//#include MODULE_DESCRIPTION("Network fs support"); MODULE_AUTHOR("Red Hat, Inc."); @@ -18,3 +18,4 @@ 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 patchwork Wed Dec 13 15:23:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491208 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id E37F0C4332F for ; Wed, 13 Dec 2023 15:24:11 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 6E05C6B03D2; Wed, 13 Dec 2023 10:24:11 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 668DF6B03D3; Wed, 13 Dec 2023 10:24:11 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 445DA6B03D4; Wed, 13 Dec 2023 10:24:11 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 2EAC46B03D2 for ; Wed, 13 Dec 2023 10:24:11 -0500 (EST) Received: from smtpin27.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id F116C16012F for ; Wed, 13 Dec 2023 15:24:10 +0000 (UTC) X-FDA: 81562165860.27.7C7BB2A Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf10.hostedemail.com (Postfix) with ESMTP id 0F642C0027 for ; Wed, 13 Dec 2023 15:24:08 +0000 (UTC) Authentication-Results: imf10.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=Cd9uuCRB; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf10.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481049; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=/DyGf3YNSow+1Mki9omJNMosAIv6zOkX5qGi/JSZ9vQ=; b=CJqevbp91mIpFTVpNegCuIs9s+e4V9685uucMMWIedKWDrnV1zgdZUFQ0OY11KcN+xxJ8g gHobY5Gxfz78DCyh906zCPfW/q/9RT73YWb7cpcDLu2oV8MFZLh2qn31+0aAjfKfnhXATA eVvkrYRwpxXnebtordRbPR6YhdxSC/g= ARC-Authentication-Results: i=1; imf10.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=Cd9uuCRB; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf10.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481049; a=rsa-sha256; cv=none; b=1xucPeinhDxPmdo00OnYjn5M1gUT5ELjQ9S9O3E0PaJJuciEx9XMx/4XpDjdDuCcdsmxF/ ECvXtxan7L6XJcVZ0j4JiI1dn9zGPiB3MDv5eanZNRAd1wvCyHYT3wxjlsaIdXpr9Hj93E E/g4fISRZoCHdQMOwJx10OjNnIpMOGQ= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481048; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/DyGf3YNSow+1Mki9omJNMosAIv6zOkX5qGi/JSZ9vQ=; b=Cd9uuCRB5VcmZXUqVcD7y4EN7DEptJVjsIexDkk02Cyh5zv2Cegq5XdQH/Jmvsl2OyMtVF bpONbKxbApyMfS8MeUWyLTxnS6lLWSDG6Y7JfhT1lmSgZYEjDgRYReFNCUNUGLgqe22kBK QwnyUTSWvmTGc98uEq8/kADmSa2G4N8= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-114-uKlq7dhxPtW50Ig8cODnlQ-1; Wed, 13 Dec 2023 10:24:05 -0500 X-MC-Unique: uKlq7dhxPtW50Ig8cODnlQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 80524101A592; Wed, 13 Dec 2023 15:24:03 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 32AC740C6EB9; Wed, 13 Dec 2023 15:24:00 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 02/39] netfs, fscache: Combine fscache with netfs Date: Wed, 13 Dec 2023 15:23:12 +0000 Message-ID: <20231213152350.431591-3-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-Rspamd-Queue-Id: 0F642C0027 X-Rspam-User: X-Rspamd-Server: rspam05 X-Stat-Signature: e8x914j6pxdutf3xset6jmzi54gricx6 X-HE-Tag: 1702481048-622425 X-HE-Meta: U2FsdGVkX18IFFcPEVN1Bn72kWQr75k03mNb93oS5o5zXhyrkMOECGF6ePcy8vnC+ZWWzYKq9lo/ZcfRkiN1BCpbWB0KeVqhJRbNW2nV2pR2gn4Jh/v8mVEJVG5F9YgOvWDhKAUC3LPkpMX85shz3doAOdzuScwJ+ohEqReMHt0VkzjkoJuD5rmKU/c8DD29che+TyQZ8HMG2IXmSXiBnPUYPnj1qD8CjBjRa+wz2++GU2ZiB7Lil5uq+CgEyJ/53tBnvOLKBEaVyzsVzm1g1/fykdmXWaoyn7g4ZjibLyg+OfEOYfDPAr/u/TWiC5xhynpa63jKnM6B29XHempLsaV4fw/F4yYa1bJqvL4xDVvArvPvax/emC/QEmaBgo+oFbnVQdwLCz1vqPw8m6dM/wr67z+bhcphg/TsK4x0apZlZNzR3pyzR+aOvKqe9Ubjkj1NcF6C1Ad2JPMy4pJa83QRc9KLQiAeJkw5kckLW7Dxr6rk2WxOZJaFjqbTjifbXPM2EBlp4AuQAqwSiQ046bHcXrh5JYS03pnvbe4pnFgv9UzFaw4OFEnqGFqG3iYgufqll3nPab2PerVHZA6sbEW34LTLOq96g04+bag7GNSrYIYu07Jj/gYHSApAS2qaspcT1j9kgnWJcuWFp2bnh2j49DEBHz4i7zB4Ae9gf0bEdYtAnnFIa3IVddeRAqJxPxLFKelTftaN4rkChhBm0n/woYCf6z/o14sd9Ze7CN+j5uLq5vqC0GHPTpT0fLoP9gXixm99P7Ixdp8N5igsfXPyGcPQfulXCOjbcR1E/dTxdMBUeHxpWolwRuNIoimNHK3QqwlqbE0c5h4tOxDbmEYeUooOB0ukBFSgwGd9eVMztGcFY3lxpjvvDgXRTdH3XtCt2MHuD5TEDLBZ567HvPi7HWGKMGPPioruct6cd93Km6N9yvfxQJvh2/TBKmQZryFNT4r/kpdoNoNqwN4 ol4hoD9w MsqV1/QZKBRq5I7W++d3mfsvQagijPsszB1Yv0vRzAqyslQN07o2emqLhNTJpQxf3IKNt7ABN3cXMZTWCscbSOC+3YbEoemhj0XdtxFmM72milW8GyX64Lor6wTFsJ0Hc/M+Z2IVUBeFSSDxMeA1oBXL2ENcT/nrDbUlUR3I6L8cXB8TnYyErQ432VdRfDT9xpaUo18zgVNnPm0l22pfBWlRAFCOC2u8bLqJgSfcCE80qetY= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Now that the fscache code is moved to be colocated with the netfslib code so that they combined into one module, do the combining. Signed-off-by: David Howells cc: Jeff Layton cc: Christian Brauner cc: linux-fsdevel@vger.kernel.org cc: linux-cachefs@redhat.com --- fs/netfs/Kconfig | 4 +- fs/netfs/Makefile | 24 ++-- fs/netfs/fscache_internal.h | 267 +----------------------------------- fs/netfs/fscache_main.c | 17 +-- fs/netfs/internal.h | 192 +++++++++++++++++++++++++- fs/netfs/main.c | 4 +- fs/nfs/Kconfig | 4 +- 7 files changed, 213 insertions(+), 299 deletions(-) diff --git a/fs/netfs/Kconfig b/fs/netfs/Kconfig index b4378688357c..bec805e0c44c 100644 --- a/fs/netfs/Kconfig +++ b/fs/netfs/Kconfig @@ -23,8 +23,8 @@ config NETFS_STATS debugging purposes. Saying 'Y' here is recommended. config FSCACHE - tristate "General filesystem local caching manager" - select NETFS_SUPPORT + bool "General filesystem local caching manager" + depends on NETFS_SUPPORT help This option enables a generic filesystem caching manager that can be used by various network and other filesystems to cache data locally. diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index bbb2b824bd5e..b57162ef9cfb 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -1,17 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -fscache-y := \ - fscache_cache.o \ - fscache_cookie.o \ - fscache_io.o \ - fscache_main.o \ - fscache_volume.o - -fscache-$(CONFIG_PROC_FS) += fscache_proc.o -fscache-$(CONFIG_FSCACHE_STATS) += fscache_stats.o - -obj-$(CONFIG_FSCACHE) := fscache.o - netfs-y := \ buffered_read.o \ io.o \ @@ -21,4 +9,16 @@ netfs-y := \ netfs-$(CONFIG_NETFS_STATS) += stats.o +netfs-$(CONFIG_FSCACHE) += \ + fscache_cache.o \ + fscache_cookie.o \ + fscache_io.o \ + fscache_main.o \ + fscache_volume.o + +ifeq ($(CONFIG_PROC_FS),y) +netfs-$(CONFIG_FSCACHE) += fscache_proc.o +endif +netfs-$(CONFIG_FSCACHE_STATS) += fscache_stats.o + obj-$(CONFIG_NETFS_SUPPORT) += netfs.o diff --git a/fs/netfs/fscache_internal.h b/fs/netfs/fscache_internal.h index 1336f517e9b1..a09b948fcef2 100644 --- a/fs/netfs/fscache_internal.h +++ b/fs/netfs/fscache_internal.h @@ -5,273 +5,10 @@ * Written by David Howells (dhowells@redhat.com) */ +#include "internal.h" + #ifdef pr_fmt #undef pr_fmt #endif #define pr_fmt(fmt) "FS-Cache: " fmt - -#include -#include -#include -#include -#include - -/* - * cache.c - */ -#ifdef CONFIG_PROC_FS -extern const struct seq_operations fscache_caches_seq_ops; -#endif -bool fscache_begin_cache_access(struct fscache_cache *cache, enum fscache_access_trace why); -void fscache_end_cache_access(struct fscache_cache *cache, enum fscache_access_trace why); -struct fscache_cache *fscache_lookup_cache(const char *name, bool is_cache); -void fscache_put_cache(struct fscache_cache *cache, enum fscache_cache_trace where); - -static inline enum fscache_cache_state fscache_cache_state(const struct fscache_cache *cache) -{ - return smp_load_acquire(&cache->state); -} - -static inline bool fscache_cache_is_live(const struct fscache_cache *cache) -{ - return fscache_cache_state(cache) == FSCACHE_CACHE_IS_ACTIVE; -} - -static inline void fscache_set_cache_state(struct fscache_cache *cache, - enum fscache_cache_state new_state) -{ - smp_store_release(&cache->state, new_state); - -} - -static inline bool fscache_set_cache_state_maybe(struct fscache_cache *cache, - enum fscache_cache_state old_state, - enum fscache_cache_state new_state) -{ - return try_cmpxchg_release(&cache->state, &old_state, new_state); -} - -/* - * cookie.c - */ -extern struct kmem_cache *fscache_cookie_jar; -#ifdef CONFIG_PROC_FS -extern const struct seq_operations fscache_cookies_seq_ops; -#endif -extern struct timer_list fscache_cookie_lru_timer; - -extern void fscache_print_cookie(struct fscache_cookie *cookie, char prefix); -extern bool fscache_begin_cookie_access(struct fscache_cookie *cookie, - enum fscache_access_trace why); - -static inline void fscache_see_cookie(struct fscache_cookie *cookie, - enum fscache_cookie_trace where) -{ - trace_fscache_cookie(cookie->debug_id, refcount_read(&cookie->ref), - where); -} - -/* - * main.c - */ -extern unsigned fscache_debug; - -extern unsigned int fscache_hash(unsigned int salt, const void *data, size_t len); - -/* - * proc.c - */ -#ifdef CONFIG_PROC_FS -extern int __init fscache_proc_init(void); -extern void fscache_proc_cleanup(void); -#else -#define fscache_proc_init() (0) -#define fscache_proc_cleanup() do {} while (0) -#endif - -/* - * stats.c - */ -#ifdef CONFIG_FSCACHE_STATS -extern atomic_t fscache_n_volumes; -extern atomic_t fscache_n_volumes_collision; -extern atomic_t fscache_n_volumes_nomem; -extern atomic_t fscache_n_cookies; -extern atomic_t fscache_n_cookies_lru; -extern atomic_t fscache_n_cookies_lru_expired; -extern atomic_t fscache_n_cookies_lru_removed; -extern atomic_t fscache_n_cookies_lru_dropped; - -extern atomic_t fscache_n_acquires; -extern atomic_t fscache_n_acquires_ok; -extern atomic_t fscache_n_acquires_oom; - -extern atomic_t fscache_n_invalidates; - -extern atomic_t fscache_n_relinquishes; -extern atomic_t fscache_n_relinquishes_retire; -extern atomic_t fscache_n_relinquishes_dropped; - -extern atomic_t fscache_n_resizes; -extern atomic_t fscache_n_resizes_null; - -static inline void fscache_stat(atomic_t *stat) -{ - atomic_inc(stat); -} - -static inline void fscache_stat_d(atomic_t *stat) -{ - atomic_dec(stat); -} - -#define __fscache_stat(stat) (stat) - -int fscache_stats_show(struct seq_file *m, void *v); -#else - -#define __fscache_stat(stat) (NULL) -#define fscache_stat(stat) do {} while (0) -#define fscache_stat_d(stat) do {} while (0) -#endif - -/* - * volume.c - */ -#ifdef CONFIG_PROC_FS -extern const struct seq_operations fscache_volumes_seq_ops; -#endif - -struct fscache_volume *fscache_get_volume(struct fscache_volume *volume, - enum fscache_volume_trace where); -void fscache_put_volume(struct fscache_volume *volume, - enum fscache_volume_trace where); -bool fscache_begin_volume_access(struct fscache_volume *volume, - struct fscache_cookie *cookie, - enum fscache_access_trace why); -void fscache_create_volume(struct fscache_volume *volume, bool wait); - - -/*****************************************************************************/ -/* - * debug tracing - */ -#define dbgprintk(FMT, ...) \ - printk("[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__) - -#define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__) -#define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__) -#define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__) - -#define kjournal(FMT, ...) no_printk(FMT, ##__VA_ARGS__) - -#ifdef __KDEBUG -#define _enter(FMT, ...) kenter(FMT, ##__VA_ARGS__) -#define _leave(FMT, ...) kleave(FMT, ##__VA_ARGS__) -#define _debug(FMT, ...) kdebug(FMT, ##__VA_ARGS__) - -#elif defined(CONFIG_FSCACHE_DEBUG) -#define _enter(FMT, ...) \ -do { \ - if (__do_kdebug(ENTER)) \ - kenter(FMT, ##__VA_ARGS__); \ -} while (0) - -#define _leave(FMT, ...) \ -do { \ - if (__do_kdebug(LEAVE)) \ - kleave(FMT, ##__VA_ARGS__); \ -} while (0) - -#define _debug(FMT, ...) \ -do { \ - if (__do_kdebug(DEBUG)) \ - kdebug(FMT, ##__VA_ARGS__); \ -} while (0) - -#else -#define _enter(FMT, ...) no_printk("==> %s("FMT")", __func__, ##__VA_ARGS__) -#define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__) -#define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__) -#endif - -/* - * determine whether a particular optional debugging point should be logged - * - we need to go through three steps to persuade cpp to correctly join the - * shorthand in FSCACHE_DEBUG_LEVEL with its prefix - */ -#define ____do_kdebug(LEVEL, POINT) \ - unlikely((fscache_debug & \ - (FSCACHE_POINT_##POINT << (FSCACHE_DEBUG_ ## LEVEL * 3)))) -#define ___do_kdebug(LEVEL, POINT) \ - ____do_kdebug(LEVEL, POINT) -#define __do_kdebug(POINT) \ - ___do_kdebug(FSCACHE_DEBUG_LEVEL, POINT) - -#define FSCACHE_DEBUG_CACHE 0 -#define FSCACHE_DEBUG_COOKIE 1 -#define FSCACHE_DEBUG_OBJECT 2 -#define FSCACHE_DEBUG_OPERATION 3 - -#define FSCACHE_POINT_ENTER 1 -#define FSCACHE_POINT_LEAVE 2 -#define FSCACHE_POINT_DEBUG 4 - -#ifndef FSCACHE_DEBUG_LEVEL -#define FSCACHE_DEBUG_LEVEL CACHE -#endif - -/* - * assertions - */ -#if 1 /* defined(__KDEBUGALL) */ - -#define ASSERT(X) \ -do { \ - if (unlikely(!(X))) { \ - pr_err("\n"); \ - pr_err("Assertion failed\n"); \ - BUG(); \ - } \ -} while (0) - -#define ASSERTCMP(X, OP, Y) \ -do { \ - if (unlikely(!((X) OP (Y)))) { \ - pr_err("\n"); \ - pr_err("Assertion failed\n"); \ - pr_err("%lx " #OP " %lx is false\n", \ - (unsigned long)(X), (unsigned long)(Y)); \ - BUG(); \ - } \ -} while (0) - -#define ASSERTIF(C, X) \ -do { \ - if (unlikely((C) && !(X))) { \ - pr_err("\n"); \ - pr_err("Assertion failed\n"); \ - BUG(); \ - } \ -} while (0) - -#define ASSERTIFCMP(C, X, OP, Y) \ -do { \ - if (unlikely((C) && !((X) OP (Y)))) { \ - pr_err("\n"); \ - pr_err("Assertion failed\n"); \ - pr_err("%lx " #OP " %lx is false\n", \ - (unsigned long)(X), (unsigned long)(Y)); \ - BUG(); \ - } \ -} while (0) - -#else - -#define ASSERT(X) do {} while (0) -#define ASSERTCMP(X, OP, Y) do {} while (0) -#define ASSERTIF(C, X) do {} while (0) -#define ASSERTIFCMP(C, X, OP, Y) do {} while (0) - -#endif /* assert or not */ diff --git a/fs/netfs/fscache_main.c b/fs/netfs/fscache_main.c index dad85fd84f6f..00600a4d9ce5 100644 --- a/fs/netfs/fscache_main.c +++ b/fs/netfs/fscache_main.c @@ -8,18 +8,9 @@ #define FSCACHE_DEBUG_LEVEL CACHE #include #include -#define CREATE_TRACE_POINTS #include "internal.h" - -MODULE_DESCRIPTION("FS Cache Manager"); -MODULE_AUTHOR("Red Hat, Inc."); -MODULE_LICENSE("GPL"); - -unsigned fscache_debug; -module_param_named(debug, fscache_debug, uint, - S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(fscache_debug, - "FS-Cache debugging mask"); +#define CREATE_TRACE_POINTS +#include EXPORT_TRACEPOINT_SYMBOL(fscache_access_cache); EXPORT_TRACEPOINT_SYMBOL(fscache_access_volume); @@ -92,7 +83,7 @@ static int __init fscache_init(void) goto error_cookie_jar; } - pr_notice("Loaded\n"); + pr_notice("FS-Cache loaded\n"); return 0; error_cookie_jar: @@ -115,7 +106,7 @@ static void __exit fscache_exit(void) kmem_cache_destroy(fscache_cookie_jar); fscache_proc_cleanup(); destroy_workqueue(fscache_wq); - pr_notice("Unloaded\n"); + pr_notice("FS-Cache unloaded\n"); } module_exit(fscache_exit); diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index e96432499eb2..43769ac606e8 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -9,8 +9,9 @@ #include #include #include +#include #include -#include "fscache_internal.h" +#include #ifdef pr_fmt #undef pr_fmt @@ -106,11 +107,143 @@ static inline bool netfs_is_cache_enabled(struct netfs_inode *ctx) #endif } +/* + * fscache-cache.c + */ +#ifdef CONFIG_PROC_FS +extern const struct seq_operations fscache_caches_seq_ops; +#endif +bool fscache_begin_cache_access(struct fscache_cache *cache, enum fscache_access_trace why); +void fscache_end_cache_access(struct fscache_cache *cache, enum fscache_access_trace why); +struct fscache_cache *fscache_lookup_cache(const char *name, bool is_cache); +void fscache_put_cache(struct fscache_cache *cache, enum fscache_cache_trace where); + +static inline enum fscache_cache_state fscache_cache_state(const struct fscache_cache *cache) +{ + return smp_load_acquire(&cache->state); +} + +static inline bool fscache_cache_is_live(const struct fscache_cache *cache) +{ + return fscache_cache_state(cache) == FSCACHE_CACHE_IS_ACTIVE; +} + +static inline void fscache_set_cache_state(struct fscache_cache *cache, + enum fscache_cache_state new_state) +{ + smp_store_release(&cache->state, new_state); + +} + +static inline bool fscache_set_cache_state_maybe(struct fscache_cache *cache, + enum fscache_cache_state old_state, + enum fscache_cache_state new_state) +{ + return try_cmpxchg_release(&cache->state, &old_state, new_state); +} + +/* + * fscache-cookie.c + */ +extern struct kmem_cache *fscache_cookie_jar; +#ifdef CONFIG_PROC_FS +extern const struct seq_operations fscache_cookies_seq_ops; +#endif +extern struct timer_list fscache_cookie_lru_timer; + +extern void fscache_print_cookie(struct fscache_cookie *cookie, char prefix); +extern bool fscache_begin_cookie_access(struct fscache_cookie *cookie, + enum fscache_access_trace why); + +static inline void fscache_see_cookie(struct fscache_cookie *cookie, + enum fscache_cookie_trace where) +{ + trace_fscache_cookie(cookie->debug_id, refcount_read(&cookie->ref), + where); +} + +/* + * fscache-main.c + */ +extern unsigned int fscache_hash(unsigned int salt, const void *data, size_t len); + +/* + * fscache-proc.c + */ +#ifdef CONFIG_PROC_FS +extern int __init fscache_proc_init(void); +extern void fscache_proc_cleanup(void); +#else +#define fscache_proc_init() (0) +#define fscache_proc_cleanup() do {} while (0) +#endif + +/* + * fscache-stats.c + */ +#ifdef CONFIG_FSCACHE_STATS +extern atomic_t fscache_n_volumes; +extern atomic_t fscache_n_volumes_collision; +extern atomic_t fscache_n_volumes_nomem; +extern atomic_t fscache_n_cookies; +extern atomic_t fscache_n_cookies_lru; +extern atomic_t fscache_n_cookies_lru_expired; +extern atomic_t fscache_n_cookies_lru_removed; +extern atomic_t fscache_n_cookies_lru_dropped; + +extern atomic_t fscache_n_acquires; +extern atomic_t fscache_n_acquires_ok; +extern atomic_t fscache_n_acquires_oom; + +extern atomic_t fscache_n_invalidates; + +extern atomic_t fscache_n_relinquishes; +extern atomic_t fscache_n_relinquishes_retire; +extern atomic_t fscache_n_relinquishes_dropped; + +extern atomic_t fscache_n_resizes; +extern atomic_t fscache_n_resizes_null; + +static inline void fscache_stat(atomic_t *stat) +{ + atomic_inc(stat); +} + +static inline void fscache_stat_d(atomic_t *stat) +{ + atomic_dec(stat); +} + +#define __fscache_stat(stat) (stat) + +int fscache_stats_show(struct seq_file *m, void *v); +#else + +#define __fscache_stat(stat) (NULL) +#define fscache_stat(stat) do {} while (0) +#define fscache_stat_d(stat) do {} while (0) +#endif + +/* + * fscache-volume.c + */ +#ifdef CONFIG_PROC_FS +extern const struct seq_operations fscache_volumes_seq_ops; +#endif + +struct fscache_volume *fscache_get_volume(struct fscache_volume *volume, + enum fscache_volume_trace where); +void fscache_put_volume(struct fscache_volume *volume, + enum fscache_volume_trace where); +bool fscache_begin_volume_access(struct fscache_volume *volume, + struct fscache_cookie *cookie, + enum fscache_access_trace why); +void fscache_create_volume(struct fscache_volume *volume, bool wait); + /*****************************************************************************/ /* * debug tracing */ -#if 0 #define dbgprintk(FMT, ...) \ printk("[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__) @@ -147,4 +280,57 @@ do { \ #define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__) #define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__) #endif -#endif + +/* + * assertions + */ +#if 1 /* defined(__KDEBUGALL) */ + +#define ASSERT(X) \ +do { \ + if (unlikely(!(X))) { \ + pr_err("\n"); \ + pr_err("Assertion failed\n"); \ + BUG(); \ + } \ +} while (0) + +#define ASSERTCMP(X, OP, Y) \ +do { \ + if (unlikely(!((X) OP (Y)))) { \ + pr_err("\n"); \ + pr_err("Assertion failed\n"); \ + pr_err("%lx " #OP " %lx is false\n", \ + (unsigned long)(X), (unsigned long)(Y)); \ + BUG(); \ + } \ +} while (0) + +#define ASSERTIF(C, X) \ +do { \ + if (unlikely((C) && !(X))) { \ + pr_err("\n"); \ + pr_err("Assertion failed\n"); \ + BUG(); \ + } \ +} while (0) + +#define ASSERTIFCMP(C, X, OP, Y) \ +do { \ + if (unlikely((C) && !((X) OP (Y)))) { \ + pr_err("\n"); \ + pr_err("Assertion failed\n"); \ + pr_err("%lx " #OP " %lx is false\n", \ + (unsigned long)(X), (unsigned long)(Y)); \ + BUG(); \ + } \ +} while (0) + +#else + +#define ASSERT(X) do {} while (0) +#define ASSERTCMP(X, OP, Y) do {} while (0) +#define ASSERTIF(C, X) do {} while (0) +#define ASSERTIFCMP(C, X, OP, Y) do {} while (0) + +#endif /* assert or not */ diff --git a/fs/netfs/main.c b/fs/netfs/main.c index 237c54a01d97..1ba8091fcf3e 100644 --- a/fs/netfs/main.c +++ b/fs/netfs/main.c @@ -8,8 +8,8 @@ #include #include #include "internal.h" -//#define CREATE_TRACE_POINTS -//#include +#define CREATE_TRACE_POINTS +#include MODULE_DESCRIPTION("Network fs support"); MODULE_AUTHOR("Red Hat, Inc."); diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 01ac733a6320..f7e32d76e34d 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -169,8 +169,8 @@ config ROOT_NFS config NFS_FSCACHE bool "Provide NFS client caching support" - depends on NFS_FS=m && FSCACHE || NFS_FS=y && FSCACHE=y - select NETFS_SUPPORT + depends on NFS_FS=m && NETFS_SUPPORT || NFS_FS=y && NETFS_SUPPORT=y + select FSCACHE help Say Y here if you want NFS data to be cached locally on disc through the general filesystem cache manager From patchwork Wed Dec 13 15:23:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491209 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 25CCEC4167B for ; Wed, 13 Dec 2023 15:24:15 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id AAF386B03D3; Wed, 13 Dec 2023 10:24:14 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id A5EDB6B03D5; Wed, 13 Dec 2023 10:24:14 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 8B1576B03D9; Wed, 13 Dec 2023 10:24:14 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 780A86B03D3 for ; Wed, 13 Dec 2023 10:24:14 -0500 (EST) Received: from smtpin15.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 42B391401E3 for ; Wed, 13 Dec 2023 15:24:14 +0000 (UTC) X-FDA: 81562166028.15.0578B66 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf19.hostedemail.com (Postfix) with ESMTP id 8823F1A001D for ; Wed, 13 Dec 2023 15:24:12 +0000 (UTC) Authentication-Results: imf19.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=iwL90qEP; spf=pass (imf19.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481052; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=OcMZgNlV77xdSoN3X7eszXopt58ZURHGiYs5iCbwsVE=; b=YgeDBHLJRWUXrs/JXRMnSJTDrFaxqhIeXlBtMyGIJHJ/642fllU/LUxWR1NFlEHHaE1Vig D1QLTqeQPI+D7IgXg8dJFaaQHJ2IOyoBNo8GNj0kXiYCAZPZlVBsqT1o+LPp5AoY4TAxzp lhqxwiN1QuhOPeUFlujqiodBWXaarn4= ARC-Authentication-Results: i=1; imf19.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=iwL90qEP; spf=pass (imf19.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481052; a=rsa-sha256; cv=none; b=UDBFmrOwZ6Iq4vZ9QIHkzb0uBVykUNehJCGGI/d8iYWURS8eg569aEpPT/vC7qyufsUts6 /TAm9LeraiH/aQEpXp7sYn3pJRkNklgzXR43dByJBGJG0Fnjr8IfKofA3q0wHXgWWf2ltQ N4RJjgH1AbQUfnPDN6YjmaFqDEAOarY= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481051; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OcMZgNlV77xdSoN3X7eszXopt58ZURHGiYs5iCbwsVE=; b=iwL90qEPsmE6GA8/2/GyP4FSPvJv4+sd/dDmha49sSMEcpeWDxLIl/JU3GNY1Bk5DjfdoV 5ObU07frnX3ipITYPmYZ1jqc56J1MprqpG+hV5LTl1OvrtLlebKJ9X/JiqxXRo9+Oo1Ppu Q48j3ln4HjIZI9smfsGwwOTdtgfMgkM= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-54-fzPm2Mo_Miy80xV08Sb7FA-1; Wed, 13 Dec 2023 10:24:08 -0500 X-MC-Unique: fzPm2Mo_Miy80xV08Sb7FA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 56BA9863010; Wed, 13 Dec 2023 15:24:07 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4B8341C060B1; Wed, 13 Dec 2023 15:24:04 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 03/39] netfs, fscache: Remove ->begin_cache_operation Date: Wed, 13 Dec 2023 15:23:13 +0000 Message-ID: <20231213152350.431591-4-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.7 X-Rspamd-Queue-Id: 8823F1A001D X-Rspam-User: X-Stat-Signature: sgq41hx1wicz7wabst6uk56ytbotdjuz X-Rspamd-Server: rspam01 X-HE-Tag: 1702481052-370447 X-HE-Meta: U2FsdGVkX1/tKVLngLdRqxrlRWqR0++H4H6s+wludUFdsS9fJSo5JqFQ+EawOUuWBiMvCbydw2dfjP+bRRfg+iaC/qaagRFKpT2s+/aKZtMhYXURm05CwY4o4cjQiJxpkSDLpSg5lWzMyvh79WQoMa4WlUpISpP6tkz8v7aTcfmUF/kHC52Jzn+jEUJwiib+YJEH8Vf8X9eNLKKB3RQMJ3H6JjXYIkrf4LDi9Yvxvsl8ln55w4LOumCimBOuuvG/N2REACY8tkqtHxmA8i24LODdwaSAFumThqHCYjIaknEOWdDSTIF7GdD/fmYX2l14lvHf60K0sU6+63lsJGJr3IknFZzMnPrCpyRZp2fIjwVEFgJU9mYFAQ4PzFQYrZSW9sRHqcqa9O9fFoN5uU459bdEtORncAzj2sv/Gtw2Ng52MSjc8bmrlnxqerHnVEuslwMSg/M2Z6Tk7YdAbV++WFBL1Ei6z77D8xo5nBYx3G0swtuc5JrjTCg1FTxtPTp8zSTHnZvLhmsTez+pFbJdYXQvfdDPG4E9LDAdxUDmAni2It70oYmRy2HvRjZrzmHEs4QQmplSS2L6mD4px6mq8z3CGZ6e4lfkqhg+mXUUijS0/w28gN5B9oZOvisTCubUPnz7qGiZO8WFGkjSiPBziGecMOUtTqdOvcRooIxwSHRkESkuoliiq+84GF3xTwCeeQ3Z1CkRuXgUtPrvJNKpCXy3+8DkN3b/GBtrSJ4XdPuT8pbHdPMvTHQTrWOC+m+SASImoHwoIevO8LB+Sr2H63x5QsNdAK2GOIJWgcuRB3RFJsgxRzagnX5QAlQwOG4CUitV5kQ4ZXlZNRtny3NmF9Gb/SSyQAXmhVE6Nf9b/8nZS1lZAp/OXJ/IdiO7kI/RVeRiziwIEhJ3yL1uZvyoPOj0Lj8jrbtNj+YJoBVCjt0bAPClgOTaQpZ+1NRBJzhTJhlf7nHokkPFMl0LgPg M5iaxj1O pSsQDkFD03rv4OJxxajM+dyJUnckJpi6IuVe/BHJQ5AwGXhPEQG6VvksP/fYPEocLA25W/1HhX0EXWcqGz4St749nhzoWHsuh2/howMP+OxYVZPosULsZ8bwswJPlpdsjgPSr+tkehy0FoTGNmyYAqH1ylv97sKfFE8ctCpJmPC/ajuF4IBrjSF9BnS6TUZrMGYtxl2oyAZstL1UqJxkmAHRqoLM1G/pby/QGSj2nQK6VQPz3DUBHIOEd+Fr8NpvuS1IDXI8kvmoDPrNJqvAvIiMW0Q== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Remove ->begin_cache_operation() in favour of just calling fscache directly. Signed-off-by: David Howells cc: Jeff Layton cc: Christian Brauner cc: linux-fsdevel@vger.kernel.org cc: linux-cachefs@redhat.com --- Documentation/filesystems/netfs_library.rst | 23 +++----------- fs/9p/vfs_addr.c | 16 ---------- fs/afs/file.c | 13 -------- fs/ceph/addr.c | 1 - fs/ceph/cache.h | 12 -------- fs/netfs/buffered_read.c | 33 +++++++++++---------- fs/nfs/fscache.c | 7 ----- include/linux/fscache.h | 3 -- include/linux/netfs.h | 4 +-- 9 files changed, 23 insertions(+), 89 deletions(-) diff --git a/Documentation/filesystems/netfs_library.rst b/Documentation/filesystems/netfs_library.rst index 48b95d04f72d..4cc657d743f7 100644 --- a/Documentation/filesystems/netfs_library.rst +++ b/Documentation/filesystems/netfs_library.rst @@ -295,7 +295,6 @@ through which it can issue requests and negotiate:: struct netfs_request_ops { void (*init_request)(struct netfs_io_request *rreq, struct file *file); void (*free_request)(struct netfs_io_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_read)(struct netfs_io_subrequest *subreq); @@ -317,20 +316,6 @@ The operations are as follows: [Optional] This is called as the request is being deallocated so that the filesystem can clean up any state it has attached there. - * ``begin_cache_operation()`` - - [Optional] This is called to ask the network filesystem to call into the - cache (if present) to initialise the caching state for this read. The netfs - library module cannot access the cache directly, so the cache should call - something like fscache_begin_read_operation() to do this. - - The cache gets to store its state in ->cache_resources and must set a table - of operations of its own there (though of a different type). - - This should return 0 on success and an error code otherwise. If an error is - reported, the operation may proceed anyway, just without local caching (only - out of memory and interruption errors cause failure here). - * ``expand_readahead()`` [Optional] This is called to allow the filesystem to expand the size of a @@ -460,14 +445,14 @@ When implementing a local cache to be used by the read helpers, two things are required: some way for the network filesystem to initialise the caching for a read request and a table of operations for the helpers to call. -The network filesystem's ->begin_cache_operation() method 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:: +To begin a cache operation on an fscache object, the following function is +called:: int fscache_begin_read_operation(struct netfs_io_request *rreq, struct fscache_cookie *cookie); -passing in the request pointer and the cookie corresponding to the file. +passing in the request pointer and the cookie corresponding to the file. This +fills in the cache resources mentioned below. The netfs_io_request object contains a place for the cache to hang its state:: diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 8a635999a7d6..39db7c01e30a 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -82,25 +82,9 @@ static void v9fs_free_request(struct netfs_io_request *rreq) p9_fid_put(fid); } -/** - * v9fs_begin_cache_operation - Begin a cache operation for a read - * @rreq: The read request - */ -static int v9fs_begin_cache_operation(struct netfs_io_request *rreq) -{ -#ifdef CONFIG_9P_FSCACHE - struct fscache_cookie *cookie = v9fs_inode_cookie(V9FS_I(rreq->inode)); - - return fscache_begin_read_operation(&rreq->cache_resources, cookie); -#else - return -ENOBUFS; -#endif -} - const struct netfs_request_ops v9fs_req_ops = { .init_request = v9fs_init_request, .free_request = v9fs_free_request, - .begin_cache_operation = v9fs_begin_cache_operation, .issue_read = v9fs_issue_read, }; diff --git a/fs/afs/file.c b/fs/afs/file.c index 30914e0d9cb2..0326ae21fbea 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -363,18 +363,6 @@ static int afs_init_request(struct netfs_io_request *rreq, struct file *file) return 0; } -static int afs_begin_cache_operation(struct netfs_io_request *rreq) -{ -#ifdef CONFIG_AFS_FSCACHE - struct afs_vnode *vnode = AFS_FS_I(rreq->inode); - - return fscache_begin_read_operation(&rreq->cache_resources, - afs_vnode_cache(vnode)); -#else - return -ENOBUFS; -#endif -} - static int afs_check_write_begin(struct file *file, loff_t pos, unsigned len, struct folio **foliop, void **_fsdata) { @@ -391,7 +379,6 @@ static void afs_free_request(struct netfs_io_request *rreq) const struct netfs_request_ops afs_req_ops = { .init_request = afs_init_request, .free_request = afs_free_request, - .begin_cache_operation = afs_begin_cache_operation, .check_write_begin = afs_check_write_begin, .issue_read = afs_issue_read, }; diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 13af429ab030..654f408a0aca 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -509,7 +509,6 @@ static void ceph_netfs_free_request(struct netfs_io_request *rreq) const struct netfs_request_ops ceph_netfs_ops = { .init_request = ceph_init_request, .free_request = ceph_netfs_free_request, - .begin_cache_operation = ceph_begin_cache_operation, .issue_read = ceph_netfs_issue_read, .expand_readahead = ceph_netfs_expand_readahead, .clamp_length = ceph_netfs_clamp_length, diff --git a/fs/ceph/cache.h b/fs/ceph/cache.h index dc502daac49a..b804f1094764 100644 --- a/fs/ceph/cache.h +++ b/fs/ceph/cache.h @@ -57,13 +57,6 @@ static inline int ceph_fscache_dirty_folio(struct address_space *mapping, return fscache_dirty_folio(mapping, folio, ceph_fscache_cookie(ci)); } -static inline int ceph_begin_cache_operation(struct netfs_io_request *rreq) -{ - struct fscache_cookie *cookie = ceph_fscache_cookie(ceph_inode(rreq->inode)); - - return fscache_begin_read_operation(&rreq->cache_resources, cookie); -} - static inline bool ceph_is_cache_enabled(struct inode *inode) { return fscache_cookie_enabled(ceph_fscache_cookie(ceph_inode(inode))); @@ -135,11 +128,6 @@ static inline bool ceph_is_cache_enabled(struct inode *inode) return false; } -static inline int ceph_begin_cache_operation(struct netfs_io_request *rreq) -{ - return -ENOBUFS; -} - static inline void ceph_fscache_note_page_release(struct inode *inode) { } diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 2cd3ccf4c439..d39d0ffe75d2 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -147,6 +147,15 @@ static void netfs_rreq_expand(struct netfs_io_request *rreq, } } +/* + * Begin an operation, and fetch the stored zero point value from the cookie if + * available. + */ +static int netfs_begin_cache_read(struct netfs_io_request *rreq, struct netfs_inode *ctx) +{ + return fscache_begin_read_operation(&rreq->cache_resources, netfs_i_cookie(ctx)); +} + /** * netfs_readahead - Helper to manage a read request * @ractl: The description of the readahead request @@ -180,11 +189,9 @@ void netfs_readahead(struct readahead_control *ractl) if (IS_ERR(rreq)) return; - if (ctx->ops->begin_cache_operation) { - ret = ctx->ops->begin_cache_operation(rreq); - if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS) - goto cleanup_free; - } + ret = netfs_begin_cache_read(rreq, ctx); + if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS) + goto cleanup_free; netfs_stat(&netfs_n_rh_readahead); trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl), @@ -238,11 +245,9 @@ int netfs_read_folio(struct file *file, struct folio *folio) goto alloc_error; } - if (ctx->ops->begin_cache_operation) { - ret = ctx->ops->begin_cache_operation(rreq); - if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS) - goto discard; - } + ret = netfs_begin_cache_read(rreq, ctx); + if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS) + goto discard; netfs_stat(&netfs_n_rh_readpage); trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage); @@ -390,11 +395,9 @@ int netfs_write_begin(struct netfs_inode *ctx, rreq->no_unlock_folio = folio_index(folio); __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); - if (ctx->ops->begin_cache_operation) { - ret = ctx->ops->begin_cache_operation(rreq); - if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS) - goto error_put; - } + ret = netfs_begin_cache_read(rreq, ctx); + if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS) + goto error_put; netfs_stat(&netfs_n_rh_write_begin); trace_netfs_read(rreq, pos, len, netfs_read_trace_write_begin); diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index b05717fe0d4e..2d1bfee225c3 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c @@ -274,12 +274,6 @@ static void nfs_netfs_free_request(struct netfs_io_request *rreq) put_nfs_open_context(rreq->netfs_priv); } -static inline int nfs_netfs_begin_cache_operation(struct netfs_io_request *rreq) -{ - return fscache_begin_read_operation(&rreq->cache_resources, - netfs_i_cookie(netfs_inode(rreq->inode))); -} - static struct nfs_netfs_io_data *nfs_netfs_alloc(struct netfs_io_subrequest *sreq) { struct nfs_netfs_io_data *netfs; @@ -387,7 +381,6 @@ void nfs_netfs_read_completion(struct nfs_pgio_header *hdr) const struct netfs_request_ops nfs_netfs_ops = { .init_request = nfs_netfs_init_request, .free_request = nfs_netfs_free_request, - .begin_cache_operation = nfs_netfs_begin_cache_operation, .issue_read = nfs_netfs_issue_read, .clamp_length = nfs_netfs_clamp_length }; diff --git a/include/linux/fscache.h b/include/linux/fscache.h index 8e312c8323a8..9ed6696aee7a 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -437,9 +437,6 @@ const struct netfs_cache_ops *fscache_operation_valid(const struct netfs_cache_r * indicates the cache resources to which the operation state should be * attached; @cookie indicates the cache object that will be accessed. * - * This is intended to be called from the ->begin_cache_operation() netfs lib - * operation as implemented by the network filesystem. - * * @cres->inval_counter is set from @cookie->inval_counter for comparison at * the end of the operation. This allows invalidation during the operation to * be detected by the caller. diff --git a/include/linux/netfs.h b/include/linux/netfs.h index b11a84f6c32b..d294ff8f9ae4 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -208,7 +208,6 @@ struct netfs_io_request { struct netfs_request_ops { int (*init_request)(struct netfs_io_request *rreq, struct file *file); void (*free_request)(struct netfs_io_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); @@ -229,8 +228,7 @@ enum netfs_read_from_hole { }; /* - * Table of operations for access to a cache. This is obtained by - * rreq->ops->begin_cache_operation(). + * Table of operations for access to a cache. */ struct netfs_cache_ops { /* End an operation */ From patchwork Wed Dec 13 15:23:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491210 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1D3BDC4167D for ; Wed, 13 Dec 2023 15:24:22 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id A3A456B03DB; Wed, 13 Dec 2023 10:24:21 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 9EA396B03DC; Wed, 13 Dec 2023 10:24:21 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 8647C6B03DD; Wed, 13 Dec 2023 10:24:21 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 73B7C6B03DB for ; Wed, 13 Dec 2023 10:24:21 -0500 (EST) Received: from smtpin26.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 390891401E3 for ; Wed, 13 Dec 2023 15:24:21 +0000 (UTC) X-FDA: 81562166322.26.B6CD64E Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf28.hostedemail.com (Postfix) with ESMTP id 6E4BBC0023 for ; Wed, 13 Dec 2023 15:24:19 +0000 (UTC) Authentication-Results: imf28.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=KHcySl1h; spf=pass (imf28.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481059; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=9XI1xSoIOgSiowLypR6weaVQC9UtzbtGS+yNMugVydM=; b=fiYwYEVt8ugTVffi/P3WIMdjNsahUkDJxQAlhe44acsQM7FNcE+S6CJpLOxgQgxRS7fVIb 3bHw50NSYk1c45cRGxUl4FkscN9BMWbGqZn93qCsX46o1vGIvGHo156WHNw7+Ndi6NWLUj GR2+MgUOQ+p6hoJueOolyxOA7KTBvTo= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481059; a=rsa-sha256; cv=none; b=631SnLPVvfbCjdEXrZcpfSHdKvX7YprylnjDuVHnhIZrDn9mgQlTUQ81VS+hQFRtXmC2Jn LpxrgEyhkbPRyFW+y+PLqfbqe4uYkCkkhUbLyHPeTHSvCP2rIQWRM4tXqAprVIS2RmuAp7 cXPIIvtUUmBEbidBQLsd5dHy0MT1qQ0= ARC-Authentication-Results: i=1; imf28.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=KHcySl1h; spf=pass (imf28.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481058; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9XI1xSoIOgSiowLypR6weaVQC9UtzbtGS+yNMugVydM=; b=KHcySl1h7FbIphK5p+lXRSLT0Nms5fUuxvRHo9VTgJwPE3IXHANngKT957aBa36jbruaIo M+MeyrF2D0mlR5NMN4CbvIPNXeM84zfX+8vpQMpiYrqg6K0Y5PlA/AFw5iZvTOosIMAkbN MDn31iLOko2fOJ+w+bPnSZlPUrdJbCM= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-223-oSg6gETKO86pTc99K02n8A-1; Wed, 13 Dec 2023 10:24:12 -0500 X-MC-Unique: oSg6gETKO86pTc99K02n8A-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id DF8FF863017; Wed, 13 Dec 2023 15:24:10 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 213A01C060B1; Wed, 13 Dec 2023 15:24:08 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 04/39] netfs, fscache: Move /proc/fs/fscache to /proc/fs/netfs and put in a symlink Date: Wed, 13 Dec 2023 15:23:14 +0000 Message-ID: <20231213152350.431591-5-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.7 X-Rspamd-Queue-Id: 6E4BBC0023 X-Rspam-User: X-Stat-Signature: ws3i61grz89dhoa93k9htwfizscu8o9o X-Rspamd-Server: rspam03 X-HE-Tag: 1702481059-986991 X-HE-Meta: U2FsdGVkX18YcnVdVU7uLimc1/vkxfNDKWIRQtaVyOc4o7pi6OTdXepoD9wIKhsGCzEQ+n1NxMp0+Fl8QYhDFR+NYw2FgsVjtcHFldTdEsgJhjmjqu4c2GwCwzTv2DDIjmfLxMpVWOwn2D68g4HIuBElYkrW17cidnnCKNRxOtIXysKRS7ckjtT+usbFvEjA4mY+sWrOrpkIfOxQEeur0FSiaXUE3LTVzC9pclBuPtig1JWssSQ7yF1etMi+Psr/uE+7NDx+Yqcau8tOZvBB4KwC4vgGc1ito023M9GjribkWNUtjsg/zV/mySZqOWK9SrTeoo2iA8uB1tTJcCQOL5l8wZg332+64AP6ePFOLGkXfzNVM4Qu/Eqwrn7kl56rc6290ndjtLhP4pYPvP9Dx6ikhpdeZUwXf18O9G6Gg/8zzmMXBUCcp5MlaCMbLdB+1GZneCxYPUgI4iPkpYQclwFGmOwxX78Vz5a1jMZeWbWwPaYxYyT4XhWTw602edO/e3WGFMCeWCQ9GdRRccQaP6gmkPeMaOiV1KFj0O5NCP4xYqdu2vam1HU97BqrhtRy2kRX4A6IEWS06M7nqBffAGAoVFNsZfd3Lp61oHuilTeiLCX57kWUWEJWqMbk1EXWPoTwfJ2g+J6KN/ZmSD9Y2tWGVgiMA6NhhBHdjzta47EvDiw3KTg9C7k3jWnQTdJ6EE6BThDJl6ZXH2Vo4vYE0eE4jBM81m4sRsXUwztvJLSbXFSfUmqaJgzgvGwpXbH3x9MiahR2909fxnL8DmduoEQYvTPTkA1cZBLlRByslwnDD5kIs+xxu0K3KNdLlHJ0TkTsXQJK2ONRTINQghJ8u74VJxU9J9GbYpRycUrBqVXuDNcpDtk1eP5FHi8mJF7b5jdH36+vJS3G36zm9f7AYcA2F0mrhIQT+zjsyVgs0DxlkcG+lkqrOOezWdcIDnfH4NBTDPYNHChKBh8eXFM PPhtBGfL s0Z11qjZ9/uS+GbNomQuqrFvfo6TY69g0IdnhdDj7YrIWjdyIalPmgCQw6zHLk6vXOqd5yggzw5o1mAd0+u54+xtYOlCWiEY+owQpIKWZrcbo7clMQXkytGAxnSVy1DsEYg/Cx70ZWi/7w6F0C9+ldTL+vHE6c9ToBCJI5pjHNwwzl62n8IHYX0TM5RQI6qmK3Q6kCbOLmyHCLWoEPbXksMJRd8MngF8ZVZGIgt0tyMTOWYk= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Rename /proc/fs/fscache to "netfs" and make a symlink from fscache to that. Signed-off-by: David Howells cc: Jeff Layton cc: Christian Brauner cc: linux-fsdevel@vger.kernel.org cc: linux-cachefs@redhat.com --- fs/netfs/fscache_main.c | 8 ++------ fs/netfs/fscache_proc.c | 23 ++++++++--------------- fs/netfs/fscache_stats.c | 4 +--- fs/netfs/internal.h | 12 +++++++++++- fs/netfs/main.c | 33 +++++++++++++++++++++++++++++++++ fs/netfs/stats.c | 13 +++++++------ include/linux/netfs.h | 1 - 7 files changed, 62 insertions(+), 32 deletions(-) diff --git a/fs/netfs/fscache_main.c b/fs/netfs/fscache_main.c index 00600a4d9ce5..42e98bb523e3 100644 --- a/fs/netfs/fscache_main.c +++ b/fs/netfs/fscache_main.c @@ -62,7 +62,7 @@ unsigned int fscache_hash(unsigned int salt, const void *data, size_t len) /* * initialise the fs caching module */ -static int __init fscache_init(void) +int __init fscache_init(void) { int ret = -ENOMEM; @@ -94,12 +94,10 @@ static int __init fscache_init(void) return ret; } -fs_initcall(fscache_init); - /* * clean up on module removal */ -static void __exit fscache_exit(void) +void __exit fscache_exit(void) { _enter(""); @@ -108,5 +106,3 @@ static void __exit fscache_exit(void) destroy_workqueue(fscache_wq); pr_notice("FS-Cache unloaded\n"); } - -module_exit(fscache_exit); diff --git a/fs/netfs/fscache_proc.c b/fs/netfs/fscache_proc.c index dc3b0e9c8cce..ecd0d1edafaa 100644 --- a/fs/netfs/fscache_proc.c +++ b/fs/netfs/fscache_proc.c @@ -12,41 +12,34 @@ #include "internal.h" /* - * initialise the /proc/fs/fscache/ directory + * Add files to /proc/fs/netfs/. */ int __init fscache_proc_init(void) { - if (!proc_mkdir("fs/fscache", NULL)) - goto error_dir; + if (!proc_symlink("fs/fscache", NULL, "../netfs")) + goto error_sym; - if (!proc_create_seq("fs/fscache/caches", S_IFREG | 0444, NULL, + if (!proc_create_seq("fs/netfs/caches", S_IFREG | 0444, NULL, &fscache_caches_seq_ops)) goto error; - if (!proc_create_seq("fs/fscache/volumes", S_IFREG | 0444, NULL, + if (!proc_create_seq("fs/netfs/volumes", S_IFREG | 0444, NULL, &fscache_volumes_seq_ops)) goto error; - if (!proc_create_seq("fs/fscache/cookies", S_IFREG | 0444, NULL, + if (!proc_create_seq("fs/netfs/cookies", S_IFREG | 0444, NULL, &fscache_cookies_seq_ops)) goto error; - -#ifdef CONFIG_FSCACHE_STATS - if (!proc_create_single("fs/fscache/stats", S_IFREG | 0444, NULL, - fscache_stats_show)) - goto error; -#endif - return 0; error: remove_proc_entry("fs/fscache", NULL); -error_dir: +error_sym: return -ENOMEM; } /* - * clean up the /proc/fs/fscache/ directory + * Clean up the /proc/fs/fscache symlink. */ void fscache_proc_cleanup(void) { diff --git a/fs/netfs/fscache_stats.c b/fs/netfs/fscache_stats.c index fc94e5e79f1c..aad812ead398 100644 --- a/fs/netfs/fscache_stats.c +++ b/fs/netfs/fscache_stats.c @@ -52,7 +52,7 @@ EXPORT_SYMBOL(fscache_n_culled); /* * display the general statistics */ -int fscache_stats_show(struct seq_file *m, void *v) +int fscache_stats_show(struct seq_file *m) { seq_puts(m, "FS-Cache statistics\n"); seq_printf(m, "Cookies: n=%d v=%d vcol=%u voom=%u\n", @@ -96,7 +96,5 @@ int fscache_stats_show(struct seq_file *m, void *v) seq_printf(m, "IO : rd=%u wr=%u\n", atomic_read(&fscache_n_read), atomic_read(&fscache_n_write)); - - netfs_stats_show(m); return 0; } diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 43769ac606e8..a15fe67e1db7 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -76,6 +76,7 @@ extern atomic_t netfs_n_rh_write_done; extern atomic_t netfs_n_rh_write_failed; extern atomic_t netfs_n_rh_write_zskip; +int netfs_stats_show(struct seq_file *m, void *v); static inline void netfs_stat(atomic_t *stat) { @@ -166,6 +167,13 @@ static inline void fscache_see_cookie(struct fscache_cookie *cookie, * fscache-main.c */ extern unsigned int fscache_hash(unsigned int salt, const void *data, size_t len); +#ifdef CONFIG_PROC_FS +int __init fscache_init(void); +void __exit fscache_exit(void); +#else +static inline int fscache_init(void) { return 0; } +static inline void fscache_exit(void) {} +#endif /* * fscache-proc.c @@ -216,12 +224,14 @@ static inline void fscache_stat_d(atomic_t *stat) #define __fscache_stat(stat) (stat) -int fscache_stats_show(struct seq_file *m, void *v); +int fscache_stats_show(struct seq_file *m); #else #define __fscache_stat(stat) (NULL) #define fscache_stat(stat) do {} while (0) #define fscache_stat_d(stat) do {} while (0) + +static inline int fscache_stats_show(struct seq_file *m) { return 0; } #endif /* diff --git a/fs/netfs/main.c b/fs/netfs/main.c index 1ba8091fcf3e..c9af6e0896d3 100644 --- a/fs/netfs/main.c +++ b/fs/netfs/main.c @@ -7,6 +7,8 @@ #include #include +#include +#include #include "internal.h" #define CREATE_TRACE_POINTS #include @@ -19,3 +21,34 @@ unsigned netfs_debug; module_param_named(debug, netfs_debug, uint, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask"); +static int __init netfs_init(void) +{ + int ret = -ENOMEM; + + if (!proc_mkdir("fs/netfs", NULL)) + goto error; + +#ifdef CONFIG_FSCACHE_STATS + if (!proc_create_single("fs/netfs/stats", S_IFREG | 0444, NULL, + netfs_stats_show)) + goto error_proc; +#endif + + ret = fscache_init(); + if (ret < 0) + goto error_proc; + return 0; + +error_proc: + remove_proc_entry("fs/netfs", NULL); +error: + return ret; +} +fs_initcall(netfs_init); + +static void __exit netfs_exit(void) +{ + fscache_exit(); + remove_proc_entry("fs/netfs", NULL); +} +module_exit(netfs_exit); diff --git a/fs/netfs/stats.c b/fs/netfs/stats.c index 5510a7a14a40..6025dc485f7e 100644 --- a/fs/netfs/stats.c +++ b/fs/netfs/stats.c @@ -28,31 +28,32 @@ atomic_t netfs_n_rh_write_done; atomic_t netfs_n_rh_write_failed; atomic_t netfs_n_rh_write_zskip; -void netfs_stats_show(struct seq_file *m) +int netfs_stats_show(struct seq_file *m, void *v) { - seq_printf(m, "RdHelp : RA=%u RP=%u WB=%u WBZ=%u rr=%u sr=%u\n", + seq_printf(m, "Netfs : RA=%u RP=%u WB=%u WBZ=%u rr=%u sr=%u\n", atomic_read(&netfs_n_rh_readahead), atomic_read(&netfs_n_rh_readpage), atomic_read(&netfs_n_rh_write_begin), atomic_read(&netfs_n_rh_write_zskip), atomic_read(&netfs_n_rh_rreq), atomic_read(&netfs_n_rh_sreq)); - seq_printf(m, "RdHelp : ZR=%u sh=%u sk=%u\n", + seq_printf(m, "Netfs : ZR=%u sh=%u sk=%u\n", atomic_read(&netfs_n_rh_zero), atomic_read(&netfs_n_rh_short_read), atomic_read(&netfs_n_rh_write_zskip)); - seq_printf(m, "RdHelp : DL=%u ds=%u df=%u di=%u\n", + seq_printf(m, "Netfs : DL=%u ds=%u df=%u di=%u\n", atomic_read(&netfs_n_rh_download), atomic_read(&netfs_n_rh_download_done), atomic_read(&netfs_n_rh_download_failed), atomic_read(&netfs_n_rh_download_instead)); - seq_printf(m, "RdHelp : RD=%u rs=%u rf=%u\n", + seq_printf(m, "Netfs : RD=%u rs=%u rf=%u\n", atomic_read(&netfs_n_rh_read), atomic_read(&netfs_n_rh_read_done), atomic_read(&netfs_n_rh_read_failed)); - seq_printf(m, "RdHelp : WR=%u ws=%u wf=%u\n", + seq_printf(m, "Netfs : WR=%u ws=%u wf=%u\n", atomic_read(&netfs_n_rh_write), atomic_read(&netfs_n_rh_write_done), atomic_read(&netfs_n_rh_write_failed)); + return fscache_stats_show(m); } EXPORT_SYMBOL(netfs_stats_show); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index d294ff8f9ae4..9bd91cd615d5 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -294,7 +294,6 @@ void netfs_get_subrequest(struct netfs_io_subrequest *subreq, enum netfs_sreq_ref_trace what); void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_async, enum netfs_sreq_ref_trace what); -void netfs_stats_show(struct seq_file *); ssize_t netfs_extract_user_iter(struct iov_iter *orig, size_t orig_len, struct iov_iter *new, iov_iter_extraction_t extraction_flags); From patchwork Wed Dec 13 15:23:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491211 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 502E8C4332F for ; Wed, 13 Dec 2023 15:24:24 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id D20446B03DC; Wed, 13 Dec 2023 10:24:23 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id CD12E6B03E0; Wed, 13 Dec 2023 10:24:23 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id AFE146B03E1; Wed, 13 Dec 2023 10:24:23 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 9505B6B03DC for ; Wed, 13 Dec 2023 10:24:23 -0500 (EST) Received: from smtpin01.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 6F8811A0210 for ; Wed, 13 Dec 2023 15:24:23 +0000 (UTC) X-FDA: 81562166406.01.EC49773 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf27.hostedemail.com (Postfix) with ESMTP id A05A440019 for ; Wed, 13 Dec 2023 15:24:21 +0000 (UTC) Authentication-Results: imf27.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=St0qiU0C; spf=pass (imf27.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481061; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=/yhsUpzLzPwpBfrpQlO8RphbApvPRXSAjecvAMUH8XM=; b=UWCin6uH7VsgmrHWdyxVoUzyhJoZMWDg7vA598gjTvs4Lf1GrQDEsE55InKqZL4yIjVwJP Mbj8zypaZYAv7En/HXdA+FWoc1vDkZYzc5bM28rmKnMUv9KH+5FTbZij1s0QRBGpcwnZia hXF+PJ7+Vmwl9Mq6EqrhBRje7bPt//g= ARC-Authentication-Results: i=1; imf27.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=St0qiU0C; spf=pass (imf27.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481061; a=rsa-sha256; cv=none; b=8q9g1k0svVpUDTdlvzokVlEqBVXHjV7h1qTtwEwlEfQFdgIdjlktr94CtdA2FnXxvnx7Uy lfme/ApI7TWZa+jWPJCYz9ShCstEyCgBigHGSNmqev7V/LAYdAmDY872F6xsI3G5tQtNhH jXpbOd6i3hl64DyVxsiO+lmzcP3mXKo= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481061; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/yhsUpzLzPwpBfrpQlO8RphbApvPRXSAjecvAMUH8XM=; b=St0qiU0CPXTwSW33QFaYs+XenoERuLGzmbylpJZKrenXmE0W9NH8LyxXRyCccUW1WTJe8c ReYbAbnJP7CE27TTTtYuc3FYuXFos8dgex6b5e4ihofvsyc4AlOXa5sQL6RRoQGPPzc4uA kn1vUYXSHUE0c7eu4Ln0P+IRGZRR7/g= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-688-_BZ3FQ8QOJKS9fPhjAjUbg-1; Wed, 13 Dec 2023 10:24:15 -0500 X-MC-Unique: _BZ3FQ8QOJKS9fPhjAjUbg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6CF6088F5AD; Wed, 13 Dec 2023 15:24:14 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8FC511C060B1; Wed, 13 Dec 2023 15:24:11 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 05/39] netfs: Move pinning-for-writeback from fscache to netfs Date: Wed, 13 Dec 2023 15:23:15 +0000 Message-ID: <20231213152350.431591-6-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.7 X-Rspamd-Queue-Id: A05A440019 X-Rspam-User: X-Stat-Signature: bpd4xzsxtwnodqm1ry3cc973jnom6m4i X-Rspamd-Server: rspam01 X-HE-Tag: 1702481061-564922 X-HE-Meta: U2FsdGVkX19qzpH4u0ZXc7JZIiyVs1/CcfbfdZvfkzPrqEDDo8UtfxJCEiGD/3zgB+xc9WZaJ+ErVQagEMIZwGchnq+qGYH9cLvRV9GGcXpwxEZgItXWOSaKn6cCEhe+u4JNO3+jSrnYOZRIlchknbGynuTinq7pHivMDZZNNE87M2fdmKv6Fr3phKUlwXbdvBCTRyFYT2Pz3TLagHGpdG9tS3iGi9i8jl1Z4VAiXMtmQ6XPYng6FYF4GUT7vtOWfeVQpYkyTsZoDHMXwh4HTEkoPwvcNm4MWbHG2Igemv7Dj90vwTsm2SVkEx/iF1FM+ZbV+JMfAulW7wyNzkiuMj/7ZpsDLX196k4c3zv3du7qOYTH7pf0ORWQ2Sh9+OG5YODmDYkwNF3vxB7e8GmDsprdr0HS9hIXLS3XLCNPu52zmj//uw7rRC463RArjveDNlBGX7Ne4OTculbXcFAm3povdpWMOit2CBywrdUuwLDJvba5J/dYuiLcx6ZbDBdRc9Ppd7gHCiEc0CUKKgUMPNurrIk4xUJB5eo9XhbXxZ29L4g72aV6+8FPvRbXhs0qtUJ1af4hkcPy7Yp1GZs1TIUr6ofkJNNmpigmKHoXlPrjl8b1h6iJCl6S45EhRkimGRYO1HePi1BD+kchkZERa2CFwD5WrdzjzdGdKv2v9cFxgZgBrHmXic2sOnj5Jaf9i0FBBwgrwfIBEmnIlvotXizpbiuvDtONPhKDifS2NTsXYepLCO29IwuH/N4nxIlMw0PYgsRFXrX3HqYzEi/ieC7MqiWpBcFdJ2OLsAqngocmoes4UyfVCNR47AbhPoeqwZJcxhPStNcJpMzLbBJWe70DOnWRfkj/F+6JJ7rslqfPaPY+pzPqpAxk4h23MRxkFEk09pyM4Bhmtb4r6F8UcpH2bC7NPNPV3aSwhwfIeul+dlTfN/ATe9zvXr5A5ENFDkuQiSnURacTEuU+Nra xjnr/8Zj PbtFq+ybZGwPsqk6h4bT1Rc9dKelVh6GB7LA2fYhU73B7IdDs08NumOYJ1kU5vqZ7aNL9VUOxB7HLloAmPtzvcXzjva3YlaFqAkiKdez3S4PGHDOuCZlPxLA/fNHjW4Hd0RnqC45TAJX18x5uFzLtcoy4LEPRdw1VwUk1KaKxBH6ZnbW2BCHv17ckMXxL2+fQLnSJqQ8QNtk2CUwk5HFINhpXqV4/Cs0Bq7iZQOMCuuu4FyMrLVUYAH8IN7FKKh40jUzaHM6PtUULE1xTUQSqBOpob1xOiKAUPQWUfZiTeKH4FdHqCltMbih2mjHWS3qzxAeMHyDGOVlmLVsWV6eT6D2Mcw== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Move the resource pinning-for-writeback from fscache code to netfslib code. This is used to keep a cache backing object pinned whilst we have dirty pages on the netfs inode in the pagecache such that VM writeback will be able to reach it. Whilst we're at it, switch the parameters of netfs_unpin_writeback() to match ->write_inode() so that it can be used for that directly. Note that this mechanism could be more generically useful than that for network filesystems. Quite often they have to keep around other resources (e.g. authentication tokens or network connections) until the writeback is complete. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/9p/vfs_addr.c | 33 ++++----------- fs/9p/vfs_inode.c | 3 +- fs/9p/vfs_super.c | 14 +------ fs/afs/file.c | 8 +--- fs/afs/inode.c | 2 +- fs/afs/internal.h | 6 --- fs/afs/super.c | 2 +- fs/afs/write.c | 9 ---- fs/ceph/cache.h | 23 ++++------- fs/ceph/inode.c | 2 +- fs/fs-writeback.c | 10 ++--- fs/netfs/Makefile | 1 + fs/netfs/fscache_io.c | 40 ------------------ fs/netfs/misc.c | 86 +++++++++++++++++++++++++++++++++++++++ fs/smb/client/cifsfs.c | 5 +-- fs/smb/client/file.c | 18 +------- include/linux/fs.h | 2 +- include/linux/fscache.h | 42 ------------------- include/linux/netfs.h | 3 ++ include/linux/writeback.h | 2 +- 20 files changed, 124 insertions(+), 187 deletions(-) create mode 100644 fs/netfs/misc.c diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 39db7c01e30a..131b83c31f85 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -317,30 +317,15 @@ static int v9fs_write_end(struct file *filp, struct address_space *mapping, return copied; } -#ifdef CONFIG_9P_FSCACHE -/* - * Mark a page as having been made dirty and thus needing writeback. We also - * need to pin the cache object to write back to. - */ -static bool v9fs_dirty_folio(struct address_space *mapping, struct folio *folio) -{ - struct v9fs_inode *v9inode = V9FS_I(mapping->host); - - return fscache_dirty_folio(mapping, folio, v9fs_inode_cookie(v9inode)); -} -#else -#define v9fs_dirty_folio filemap_dirty_folio -#endif - const struct address_space_operations v9fs_addr_operations = { - .read_folio = netfs_read_folio, - .readahead = netfs_readahead, - .dirty_folio = v9fs_dirty_folio, - .writepage = v9fs_vfs_writepage, - .write_begin = v9fs_write_begin, - .write_end = v9fs_write_end, - .release_folio = v9fs_release_folio, + .read_folio = netfs_read_folio, + .readahead = netfs_readahead, + .dirty_folio = netfs_dirty_folio, + .writepage = v9fs_vfs_writepage, + .write_begin = v9fs_write_begin, + .write_end = v9fs_write_end, + .release_folio = v9fs_release_folio, .invalidate_folio = v9fs_invalidate_folio, - .launder_folio = v9fs_launder_folio, - .direct_IO = v9fs_direct_IO, + .launder_folio = v9fs_launder_folio, + .direct_IO = v9fs_direct_IO, }; diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index b845ee18a80b..74122540e00f 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -376,8 +376,7 @@ void v9fs_evict_inode(struct inode *inode) #ifdef CONFIG_9P_FSCACHE version = cpu_to_le32(v9inode->qid.version); - fscache_clear_inode_writeback(v9fs_inode_cookie(v9inode), inode, - &version); + netfs_clear_inode_writeback(inode, &version); #endif clear_inode(inode); diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 73db55c050bf..941f7d0e0bfa 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -289,31 +289,21 @@ static int v9fs_drop_inode(struct inode *inode) static int v9fs_write_inode(struct inode *inode, struct writeback_control *wbc) { - struct v9fs_inode *v9inode; - /* * send an fsync request to server irrespective of * wbc->sync_mode. */ p9_debug(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode); - - v9inode = V9FS_I(inode); - fscache_unpin_writeback(wbc, v9fs_inode_cookie(v9inode)); - - return 0; + return netfs_unpin_writeback(inode, wbc); } static int v9fs_write_inode_dotl(struct inode *inode, struct writeback_control *wbc) { - struct v9fs_inode *v9inode; - v9inode = V9FS_I(inode); p9_debug(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode); - fscache_unpin_writeback(wbc, v9fs_inode_cookie(v9inode)); - - return 0; + return netfs_unpin_writeback(inode, wbc); } static const struct super_operations v9fs_super_ops = { diff --git a/fs/afs/file.c b/fs/afs/file.c index 0326ae21fbea..c09e881da5d2 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -55,7 +55,7 @@ const struct inode_operations afs_file_inode_operations = { const struct address_space_operations afs_file_aops = { .read_folio = netfs_read_folio, .readahead = netfs_readahead, - .dirty_folio = afs_dirty_folio, + .dirty_folio = netfs_dirty_folio, .launder_folio = afs_launder_folio, .release_folio = afs_release_folio, .invalidate_folio = afs_invalidate_folio, @@ -383,12 +383,6 @@ const struct netfs_request_ops afs_req_ops = { .issue_read = afs_issue_read, }; -int afs_write_inode(struct inode *inode, struct writeback_control *wbc) -{ - fscache_unpin_writeback(wbc, afs_vnode_cache(AFS_FS_I(inode))); - return 0; -} - /* * Adjust the dirty region of the page on truncation or full invalidation, * getting rid of the markers altogether if the region is entirely invalidated. diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 12b90d680fb6..de3e8fec54b7 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -647,7 +647,7 @@ void afs_evict_inode(struct inode *inode) truncate_inode_pages_final(&inode->i_data); afs_set_cache_aux(vnode, &aux); - fscache_clear_inode_writeback(afs_vnode_cache(vnode), inode, &aux); + netfs_clear_inode_writeback(inode, &aux); clear_inode(inode); while (!list_empty(&vnode->wb_keys)) { diff --git a/fs/afs/internal.h b/fs/afs/internal.h index f360726f6082..379fcd698062 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -1166,7 +1166,6 @@ extern int afs_release(struct inode *, struct file *); extern int afs_fetch_data(struct afs_vnode *, struct afs_read *); extern struct afs_read *afs_alloc_read(gfp_t); extern void afs_put_read(struct afs_read *); -extern int afs_write_inode(struct inode *, struct writeback_control *); static inline struct afs_read *afs_get_read(struct afs_read *req) { @@ -1658,11 +1657,6 @@ bool afs_try_get_volume(struct afs_volume *volume, enum afs_volume_trace reason) /* * write.c */ -#ifdef CONFIG_AFS_FSCACHE -bool afs_dirty_folio(struct address_space *, struct folio *); -#else -#define afs_dirty_folio filemap_dirty_folio -#endif extern int afs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, struct page **pagep, void **fsdata); diff --git a/fs/afs/super.c b/fs/afs/super.c index ae2d66a52add..f3ba1c3e72f5 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -55,7 +55,7 @@ int afs_net_id; static const struct super_operations afs_super_ops = { .statfs = afs_statfs, .alloc_inode = afs_alloc_inode, - .write_inode = afs_write_inode, + .write_inode = netfs_unpin_writeback, .drop_inode = afs_drop_inode, .destroy_inode = afs_destroy_inode, .free_inode = afs_free_inode, diff --git a/fs/afs/write.c b/fs/afs/write.c index 61d34ad2ca7d..62e1cc5985c4 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -23,15 +23,6 @@ static void afs_write_to_cache(struct afs_vnode *vnode, loff_t start, size_t len loff_t i_size, bool caching); #ifdef CONFIG_AFS_FSCACHE -/* - * Mark a page as having been made dirty and thus needing writeback. We also - * need to pin the cache object to write back to. - */ -bool afs_dirty_folio(struct address_space *mapping, struct folio *folio) -{ - return fscache_dirty_folio(mapping, folio, - afs_vnode_cache(AFS_FS_I(mapping->host))); -} static void afs_folio_start_fscache(bool caching, struct folio *folio) { if (caching) diff --git a/fs/ceph/cache.h b/fs/ceph/cache.h index b804f1094764..8fc7d828d990 100644 --- a/fs/ceph/cache.h +++ b/fs/ceph/cache.h @@ -43,19 +43,13 @@ static inline void ceph_fscache_resize(struct inode *inode, loff_t to) } } -static inline void ceph_fscache_unpin_writeback(struct inode *inode, +static inline int ceph_fscache_unpin_writeback(struct inode *inode, struct writeback_control *wbc) { - fscache_unpin_writeback(wbc, ceph_fscache_cookie(ceph_inode(inode))); + return netfs_unpin_writeback(inode, wbc); } -static inline int ceph_fscache_dirty_folio(struct address_space *mapping, - struct folio *folio) -{ - struct ceph_inode_info *ci = ceph_inode(mapping->host); - - return fscache_dirty_folio(mapping, folio, ceph_fscache_cookie(ci)); -} +#define ceph_fscache_dirty_folio netfs_dirty_folio static inline bool ceph_is_cache_enabled(struct inode *inode) { @@ -112,16 +106,13 @@ static inline void ceph_fscache_resize(struct inode *inode, loff_t to) { } -static inline void ceph_fscache_unpin_writeback(struct inode *inode, - struct writeback_control *wbc) +static inline int ceph_fscache_unpin_writeback(struct inode *inode, + struct writeback_control *wbc) { + return 0; } -static inline int ceph_fscache_dirty_folio(struct address_space *mapping, - struct folio *folio) -{ - return filemap_dirty_folio(mapping, folio); -} +#define ceph_fscache_dirty_folio filemap_dirty_folio static inline bool ceph_is_cache_enabled(struct inode *inode) { diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 0679240f06db..3149d79a9dbe 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -694,7 +694,7 @@ void ceph_evict_inode(struct inode *inode) percpu_counter_dec(&mdsc->metric.total_inodes); truncate_inode_pages_final(&inode->i_data); - if (inode->i_state & I_PINNING_FSCACHE_WB) + if (inode->i_state & I_PINNING_NETFS_WB) ceph_fscache_unuse_cookie(inode, true); clear_inode(inode); diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index a66c9d0556dc..3c9e4256a6d3 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1675,11 +1675,11 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) inode->i_state |= I_DIRTY_PAGES; - else if (unlikely(inode->i_state & I_PINNING_FSCACHE_WB)) { + else if (unlikely(inode->i_state & I_PINNING_NETFS_WB)) { if (!(inode->i_state & I_DIRTY_PAGES)) { - inode->i_state &= ~I_PINNING_FSCACHE_WB; - wbc->unpinned_fscache_wb = true; - dirty |= I_PINNING_FSCACHE_WB; /* Cause write_inode */ + inode->i_state &= ~I_PINNING_NETFS_WB; + wbc->unpinned_netfs_wb = true; + dirty |= I_PINNING_NETFS_WB; /* Cause write_inode */ } } @@ -1691,7 +1691,7 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) if (ret == 0) ret = err; } - wbc->unpinned_fscache_wb = false; + wbc->unpinned_netfs_wb = false; trace_writeback_single_inode(inode, wbc, nr_to_write); return ret; } diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index b57162ef9cfb..a84fe9bbd3c4 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -5,6 +5,7 @@ netfs-y := \ io.o \ iterator.o \ main.o \ + misc.o \ objects.o netfs-$(CONFIG_NETFS_STATS) += stats.o diff --git a/fs/netfs/fscache_io.c b/fs/netfs/fscache_io.c index 0d2b8dec8f82..79171a687930 100644 --- a/fs/netfs/fscache_io.c +++ b/fs/netfs/fscache_io.c @@ -158,46 +158,6 @@ int __fscache_begin_write_operation(struct netfs_cache_resources *cres, } EXPORT_SYMBOL(__fscache_begin_write_operation); -/** - * fscache_dirty_folio - Mark folio dirty and pin a cache object for writeback - * @mapping: The mapping the folio belongs to. - * @folio: The folio being dirtied. - * @cookie: The cookie referring to the cache object - * - * Set the dirty flag on a folio and pin an in-use cache object in memory - * so that writeback can later write to it. This is intended - * to be called from the filesystem's ->dirty_folio() method. - * - * Return: true if the dirty flag was set on the folio, false otherwise. - */ -bool fscache_dirty_folio(struct address_space *mapping, struct folio *folio, - struct fscache_cookie *cookie) -{ - struct inode *inode = mapping->host; - bool need_use = false; - - _enter(""); - - if (!filemap_dirty_folio(mapping, folio)) - return false; - if (!fscache_cookie_valid(cookie)) - return true; - - if (!(inode->i_state & I_PINNING_FSCACHE_WB)) { - spin_lock(&inode->i_lock); - if (!(inode->i_state & I_PINNING_FSCACHE_WB)) { - inode->i_state |= I_PINNING_FSCACHE_WB; - need_use = true; - } - spin_unlock(&inode->i_lock); - - if (need_use) - fscache_use_cookie(cookie, true); - } - return true; -} -EXPORT_SYMBOL(fscache_dirty_folio); - struct fscache_write_request { struct netfs_cache_resources cache_resources; struct address_space *mapping; diff --git a/fs/netfs/misc.c b/fs/netfs/misc.c new file mode 100644 index 000000000000..68baf55c47a4 --- /dev/null +++ b/fs/netfs/misc.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Miscellaneous routines. + * + * Copyright (C) 2023 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include +#include "internal.h" + +/** + * netfs_dirty_folio - Mark folio dirty and pin a cache object for writeback + * @mapping: The mapping the folio belongs to. + * @folio: The folio being dirtied. + * + * Set the dirty flag on a folio and pin an in-use cache object in memory so + * that writeback can later write to it. This is intended to be called from + * the filesystem's ->dirty_folio() method. + * + * Return: true if the dirty flag was set on the folio, false otherwise. + */ +bool netfs_dirty_folio(struct address_space *mapping, struct folio *folio) +{ + struct inode *inode = mapping->host; + struct netfs_inode *ictx = netfs_inode(inode); + struct fscache_cookie *cookie = netfs_i_cookie(ictx); + bool need_use = false; + + _enter(""); + + if (!filemap_dirty_folio(mapping, folio)) + return false; + if (!fscache_cookie_valid(cookie)) + return true; + + if (!(inode->i_state & I_PINNING_NETFS_WB)) { + spin_lock(&inode->i_lock); + if (!(inode->i_state & I_PINNING_NETFS_WB)) { + inode->i_state |= I_PINNING_NETFS_WB; + need_use = true; + } + spin_unlock(&inode->i_lock); + + if (need_use) + fscache_use_cookie(cookie, true); + } + return true; +} +EXPORT_SYMBOL(netfs_dirty_folio); + +/** + * netfs_unpin_writeback - Unpin writeback resources + * @inode: The inode on which the cookie resides + * @wbc: The writeback control + * + * Unpin the writeback resources pinned by netfs_dirty_folio(). This is + * intended to be called as/by the netfs's ->write_inode() method. + */ +int netfs_unpin_writeback(struct inode *inode, struct writeback_control *wbc) +{ + struct fscache_cookie *cookie = netfs_i_cookie(netfs_inode(inode)); + + if (wbc->unpinned_netfs_wb) + fscache_unuse_cookie(cookie, NULL, NULL); + return 0; +} +EXPORT_SYMBOL(netfs_unpin_writeback); + +/** + * netfs_clear_inode_writeback - Clear writeback resources pinned by an inode + * @inode: The inode to clean up + * @aux: Auxiliary data to apply to the inode + * + * Clear any writeback resources held by an inode when the inode is evicted. + * This must be called before clear_inode() is called. + */ +void netfs_clear_inode_writeback(struct inode *inode, const void *aux) +{ + struct fscache_cookie *cookie = netfs_i_cookie(netfs_inode(inode)); + + if (inode->i_state & I_PINNING_NETFS_WB) { + loff_t i_size = i_size_read(inode); + fscache_unuse_cookie(cookie, aux, &i_size); + } +} +EXPORT_SYMBOL(netfs_clear_inode_writeback); diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index 2131638f26d0..96a65cf9b5ec 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -429,7 +429,7 @@ static void cifs_evict_inode(struct inode *inode) { truncate_inode_pages_final(&inode->i_data); - if (inode->i_state & I_PINNING_FSCACHE_WB) + if (inode->i_state & I_PINNING_NETFS_WB) cifs_fscache_unuse_inode_cookie(inode, true); cifs_fscache_release_inode_cookie(inode); clear_inode(inode); @@ -792,8 +792,7 @@ static int cifs_show_stats(struct seq_file *s, struct dentry *root) static int cifs_write_inode(struct inode *inode, struct writeback_control *wbc) { - fscache_unpin_writeback(wbc, cifs_inode_cookie(inode)); - return 0; + return netfs_unpin_writeback(inode, wbc); } static int cifs_drop_inode(struct inode *inode) diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index 45ca492c141c..b25cace63768 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -5041,27 +5041,13 @@ static void cifs_swap_deactivate(struct file *file) /* do we need to unpin (or unlock) the file */ } -/* - * Mark a page as having been made dirty and thus needing writeback. We also - * need to pin the cache object to write back to. - */ -#ifdef CONFIG_CIFS_FSCACHE -static bool cifs_dirty_folio(struct address_space *mapping, struct folio *folio) -{ - return fscache_dirty_folio(mapping, folio, - cifs_inode_cookie(mapping->host)); -} -#else -#define cifs_dirty_folio filemap_dirty_folio -#endif - const struct address_space_operations cifs_addr_ops = { .read_folio = cifs_read_folio, .readahead = cifs_readahead, .writepages = cifs_writepages, .write_begin = cifs_write_begin, .write_end = cifs_write_end, - .dirty_folio = cifs_dirty_folio, + .dirty_folio = netfs_dirty_folio, .release_folio = cifs_release_folio, .direct_IO = cifs_direct_io, .invalidate_folio = cifs_invalidate_folio, @@ -5085,7 +5071,7 @@ const struct address_space_operations cifs_addr_ops_smallbuf = { .writepages = cifs_writepages, .write_begin = cifs_write_begin, .write_end = cifs_write_end, - .dirty_folio = cifs_dirty_folio, + .dirty_folio = netfs_dirty_folio, .release_folio = cifs_release_folio, .invalidate_folio = cifs_invalidate_folio, .launder_folio = cifs_launder_folio, diff --git a/include/linux/fs.h b/include/linux/fs.h index 897c63c64556..f4fd7f80ce93 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2373,7 +2373,7 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, #define I_CREATING (1 << 15) #define I_DONTCACHE (1 << 16) #define I_SYNC_QUEUED (1 << 17) -#define I_PINNING_FSCACHE_WB (1 << 18) +#define I_PINNING_NETFS_WB (1 << 18) #define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC) #define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES) diff --git a/include/linux/fscache.h b/include/linux/fscache.h index 9ed6696aee7a..6e8562cbcc43 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -626,48 +626,6 @@ static inline void fscache_write_to_cache(struct fscache_cookie *cookie, } -#if __fscache_available -bool fscache_dirty_folio(struct address_space *mapping, struct folio *folio, - struct fscache_cookie *cookie); -#else -#define fscache_dirty_folio(MAPPING, FOLIO, COOKIE) \ - filemap_dirty_folio(MAPPING, FOLIO) -#endif - -/** - * fscache_unpin_writeback - Unpin writeback resources - * @wbc: The writeback control - * @cookie: The cookie referring to the cache object - * - * Unpin the writeback resources pinned by fscache_dirty_folio(). This is - * intended to be called by the netfs's ->write_inode() method. - */ -static inline void fscache_unpin_writeback(struct writeback_control *wbc, - struct fscache_cookie *cookie) -{ - if (wbc->unpinned_fscache_wb) - fscache_unuse_cookie(cookie, NULL, NULL); -} - -/** - * fscache_clear_inode_writeback - Clear writeback resources pinned by an inode - * @cookie: The cookie referring to the cache object - * @inode: The inode to clean up - * @aux: Auxiliary data to apply to the inode - * - * Clear any writeback resources held by an inode when the inode is evicted. - * This must be called before clear_inode() is called. - */ -static inline void fscache_clear_inode_writeback(struct fscache_cookie *cookie, - struct inode *inode, - const void *aux) -{ - if (inode->i_state & I_PINNING_FSCACHE_WB) { - loff_t i_size = i_size_read(inode); - fscache_unuse_cookie(cookie, aux, &i_size); - } -} - /** * fscache_note_page_release - Note that a netfs page got released * @cookie: The cookie corresponding to the file diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 9bd91cd615d5..32faf6c89702 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -288,6 +288,9 @@ int netfs_read_folio(struct file *, struct folio *); int netfs_write_begin(struct netfs_inode *, struct file *, struct address_space *, loff_t pos, unsigned int len, struct folio **, void **fsdata); +bool netfs_dirty_folio(struct address_space *mapping, struct folio *folio); +int netfs_unpin_writeback(struct inode *inode, struct writeback_control *wbc); +void netfs_clear_inode_writeback(struct inode *inode, const void *aux); void netfs_subreq_terminated(struct netfs_io_subrequest *, ssize_t, bool); void netfs_get_subrequest(struct netfs_io_subrequest *subreq, diff --git a/include/linux/writeback.h b/include/linux/writeback.h index f47701c114dd..4148d8ffff26 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -60,7 +60,7 @@ struct writeback_control { unsigned for_reclaim:1; /* Invoked from the page allocator */ unsigned range_cyclic:1; /* range_start is cyclic */ unsigned for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ - unsigned unpinned_fscache_wb:1; /* Cleared I_PINNING_FSCACHE_WB */ + unsigned unpinned_netfs_wb:1; /* Cleared I_PINNING_NETFS_WB */ /* * When writeback IOs are bounced through async layers, only the From patchwork Wed Dec 13 15:23:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491212 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3CC28C4332F for ; Wed, 13 Dec 2023 15:24:28 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id C5DA66B03E0; Wed, 13 Dec 2023 10:24:27 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id C0E616B03E4; Wed, 13 Dec 2023 10:24:27 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id A60196B03E6; Wed, 13 Dec 2023 10:24:27 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 925E96B03E0 for ; Wed, 13 Dec 2023 10:24:27 -0500 (EST) Received: from smtpin16.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 44260140ADF for ; Wed, 13 Dec 2023 15:24:27 +0000 (UTC) X-FDA: 81562166574.16.4F1C42F Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf05.hostedemail.com (Postfix) with ESMTP id 9201110000A for ; Wed, 13 Dec 2023 15:24:25 +0000 (UTC) Authentication-Results: imf05.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=EtuTPRUp; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf05.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481065; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=xXclU2RwEHr6/zRJbfo0avpxB2MmbXmM1O7VqBArdhM=; b=RP5myJZYOM8HIRJwzeDU0W/Op68CmTAyCgBXDba/2PCZqd82NPXElwelYK9gVODhNgb/sR gGq9z/6RhmhU4cIiU7igN2rJVplg3EVuOFSrGphc3SElulUUNU3+rNfGeM6pYgjndndEyD GI6hAWjhiwFjrVTtzpI8I+75sURaNpQ= ARC-Authentication-Results: i=1; imf05.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=EtuTPRUp; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf05.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481065; a=rsa-sha256; cv=none; b=Nic6oyOJ10bD/RsM/7tHAXOSWUkYfcCd/zK1d0FoShm8FWHWugw6vY07BWTTSIHE3Zhs5z owTn9oWNxOWv5wIObQbSm14xgqLjd22fmS65Xj93uE9HX75bkmUmG35i5UyVwb4UpJrl3q ws7SGFM4Paaay+FkF/LOAIF9dpG3r08= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481064; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xXclU2RwEHr6/zRJbfo0avpxB2MmbXmM1O7VqBArdhM=; b=EtuTPRUpIwGM04qPcikPwp/dEVSUcLfXeDhcdfCON5h8LhtnTQqCXfbBKjv69vJosXtYMO bVDE4p3yN1EEU8k3WoK/DHhv0QZTT7p7s+52wqJYotrUKGAjUiXT9NAjwBxRJCXQ8YewKu u3TI7O/eaASy1GTszM/XfASs6XAwOxk= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-344-n_hhXb5pO6ysfAa7O8x7VQ-1; Wed, 13 Dec 2023 10:24:19 -0500 X-MC-Unique: n_hhXb5pO6ysfAa7O8x7VQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 430E41C05B02; Wed, 13 Dec 2023 15:24:18 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4C1982166B32; Wed, 13 Dec 2023 15:24:15 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 06/39] netfs: Add a procfile to list in-progress requests Date: Wed, 13 Dec 2023 15:23:16 +0000 Message-ID: <20231213152350.431591-7-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.6 X-Rspamd-Queue-Id: 9201110000A X-Rspam-User: X-Rspamd-Server: rspam04 X-Stat-Signature: n5dcqxrqabip53ebrsjqowqqffoy9bju X-HE-Tag: 1702481065-320399 X-HE-Meta: U2FsdGVkX1/gOKIhUmLcRUG+29sod8AP0UGFLBCTx4AxHlNgvZtioVImwqZzZdlQzhx6F6Q+eaO0sZQpZhfPGq5U1tJs4VB0oO5BTOZOuUJzRlAGZSdJOpmuaYVgVNJC8q/XPdeMCZNkl2nQHKoOXy9kxXqe/s1Ki3UWv8IueqgclDG+IPHZyhZfqauV3S9blLbkutYuCbb7sVuuPaRy3QUucw5R4edxVJjNmT8n+InbHAKT7tl0fWt+oAIdVkRBKn7P6BUwO4Bb6aakn6VV+Wbl+PPUKd2j6X8llqQOJA/t4YxBr7mX+G1JMFIg/uBrVx6Gy9ijcM6TQqWHyBhe6/P71LmO312nr8jjXWiTqT3gW3B3vHlw87NHeaKsLtPaZoYPOpouWMDUrAgf2qodCCWUBhAm68xw4mYIzAA8u9hy8S/2gd/N0lzDSjKW4dVChMOJWeEonwWX4x3EUqWR+wiE8sw0msgjzfgpthWMG59y05xfGr6S9ZiiLLu9DUQhLduQBeD9oxU6IMpLJxBUMwd6AJmOmqSd1XLn5nYQvyj7wbLNZ3DmzzangHk5/cYVKcBtUsMAxsuyeN6JRu7sP8pE+9g0CnE1rRT/r2434UkJeXvdVlcdaJG9r54rVoWJtzXdQzb+wwqGoYG+VqX+f42DYXrOVTPPAmd1sDUftpmUyP82gFFWqEdqH4EcyF0JKAXNjBmeRg7M/BC59Ek2ktHOWZ2MLkCL0qKxTS1+ud3AqM4BVzV+LzhIbBHMcSyrJabQfQbltdS4aleMbeatIqWFY9LxPDiNdb+9bdV2SWJ8E2qdmapBEcAF+yFbwX3b90rKzrIh1VfOKWF5QcSv826WezNv7FGyFHz/3umgKbYeS5/qgsSM/WGm220ybezB6PHe66qNV7t+Wq4LOA25F/4piOPFHOxtn9n3fWMySeirizR2xpND0Okc0cZfu64FZoZSbBMUUW40P0D1w0i Pxd1viRm ohSSjoUEimM4YVUa+ikjUsTo4Bo8jhpdg2Hs3unF6iJq7ewBDniEE8ujI2J0eOseZ/uAw3GgKocfJE03sN64EDB2yBUBmR9A0MgRyiP1d8vKoSC+govIk016fE5xHd97oniU9170omGWyrc2+bGAu1LNxzmK6Qs3MzmRcVDC8lby+EUX1RznrtT5MUXHE2mZuid7OkxbFBvX1BHTFBbrv/M1r+dJvgZn9ifCfcYryJL7ki16e7n406i+GPI/rIfuoMj7BD7t+XZwqU3u19m0TStoVceIAGWxpg5v8/Uu84mZgWV0= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Add a procfile, /proc/fs/netfs/requests, to list in-progress netfslib I/O requests. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/internal.h | 22 ++++++++++++++ fs/netfs/main.c | 69 ++++++++++++++++++++++++++++++++++++++++++- fs/netfs/objects.c | 4 ++- include/linux/netfs.h | 6 +++- 4 files changed, 98 insertions(+), 3 deletions(-) diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index a15fe67e1db7..937d9a22f178 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -33,6 +33,28 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync); * main.c */ extern unsigned int netfs_debug; +extern struct list_head netfs_io_requests; +extern spinlock_t netfs_proc_lock; + +#ifdef CONFIG_PROC_FS +static inline void netfs_proc_add_rreq(struct netfs_io_request *rreq) +{ + spin_lock(&netfs_proc_lock); + list_add_tail_rcu(&rreq->proc_link, &netfs_io_requests); + spin_unlock(&netfs_proc_lock); +} +static inline void netfs_proc_del_rreq(struct netfs_io_request *rreq) +{ + if (!list_empty(&rreq->proc_link)) { + spin_lock(&netfs_proc_lock); + list_del_rcu(&rreq->proc_link); + spin_unlock(&netfs_proc_lock); + } +} +#else +static inline void netfs_proc_add_rreq(struct netfs_io_request *rreq) {} +static inline void netfs_proc_del_rreq(struct netfs_io_request *rreq) {} +#endif /* * objects.c diff --git a/fs/netfs/main.c b/fs/netfs/main.c index c9af6e0896d3..97ce1436615b 100644 --- a/fs/netfs/main.c +++ b/fs/netfs/main.c @@ -21,13 +21,80 @@ unsigned netfs_debug; module_param_named(debug, netfs_debug, uint, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask"); +#ifdef CONFIG_PROC_FS +LIST_HEAD(netfs_io_requests); +DEFINE_SPINLOCK(netfs_proc_lock); + +static const char *netfs_origins[] = { + [NETFS_READAHEAD] = "RA", + [NETFS_READPAGE] = "RP", + [NETFS_READ_FOR_WRITE] = "RW", +}; + +/* + * Generate a list of I/O requests in /proc/fs/netfs/requests + */ +static int netfs_requests_seq_show(struct seq_file *m, void *v) +{ + struct netfs_io_request *rreq; + + if (v == &netfs_io_requests) { + seq_puts(m, + "REQUEST OR REF FL ERR OPS COVERAGE\n" + "======== == === == ==== === =========\n" + ); + return 0; + } + + rreq = list_entry(v, struct netfs_io_request, proc_link); + seq_printf(m, + "%08x %s %3d %2lx %4d %3d @%04llx %zx/%zx", + rreq->debug_id, + netfs_origins[rreq->origin], + refcount_read(&rreq->ref), + rreq->flags, + rreq->error, + atomic_read(&rreq->nr_outstanding), + rreq->start, rreq->submitted, rreq->len); + seq_putc(m, '\n'); + return 0; +} + +static void *netfs_requests_seq_start(struct seq_file *m, loff_t *_pos) + __acquires(rcu) +{ + rcu_read_lock(); + return seq_list_start_head(&netfs_io_requests, *_pos); +} + +static void *netfs_requests_seq_next(struct seq_file *m, void *v, loff_t *_pos) +{ + return seq_list_next(v, &netfs_io_requests, _pos); +} + +static void netfs_requests_seq_stop(struct seq_file *m, void *v) + __releases(rcu) +{ + rcu_read_unlock(); +} + +static const struct seq_operations netfs_requests_seq_ops = { + .start = netfs_requests_seq_start, + .next = netfs_requests_seq_next, + .stop = netfs_requests_seq_stop, + .show = netfs_requests_seq_show, +}; +#endif /* CONFIG_PROC_FS */ + static int __init netfs_init(void) { int ret = -ENOMEM; if (!proc_mkdir("fs/netfs", NULL)) goto error; - + if (!proc_create_seq("fs/netfs/requests", S_IFREG | 0444, NULL, + &netfs_requests_seq_ops)) + goto error_proc; #ifdef CONFIG_FSCACHE_STATS if (!proc_create_single("fs/netfs/stats", S_IFREG | 0444, NULL, netfs_stats_show)) diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index e17cdf53f6a7..85f428fc52e6 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -45,6 +45,7 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, } } + netfs_proc_add_rreq(rreq); netfs_stat(&netfs_n_rh_rreq); return rreq; } @@ -76,12 +77,13 @@ static void netfs_free_request(struct work_struct *work) container_of(work, struct netfs_io_request, work); trace_netfs_rreq(rreq, netfs_rreq_trace_free); + netfs_proc_del_rreq(rreq); netfs_clear_subrequests(rreq, false); if (rreq->netfs_ops->free_request) rreq->netfs_ops->free_request(rreq); if (rreq->cache_resources.ops) rreq->cache_resources.ops->end_operation(&rreq->cache_resources); - kfree(rreq); + kfree_rcu(rreq, rcu); netfs_stat_d(&netfs_n_rh_rreq); } diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 32faf6c89702..7244ddebd974 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -175,10 +175,14 @@ enum netfs_io_origin { * operations to a variety of data stores and then stitch the result together. */ struct netfs_io_request { - struct work_struct work; + union { + struct work_struct work; + struct rcu_head rcu; + }; struct inode *inode; /* The file being accessed */ struct address_space *mapping; /* The mapping being accessed */ struct netfs_cache_resources cache_resources; + struct list_head proc_link; /* Link in netfs_iorequests */ struct list_head subrequests; /* Contributory I/O operations */ void *netfs_priv; /* Private data for the netfs */ unsigned int debug_id; From patchwork Wed Dec 13 15:23:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491213 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id EFD84C4332F for ; Wed, 13 Dec 2023 15:24:30 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 6B7856B03EC; Wed, 13 Dec 2023 10:24:30 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 666F56B03ED; Wed, 13 Dec 2023 10:24:30 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 508726B03EE; Wed, 13 Dec 2023 10:24:30 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id 371E56B03EC for ; Wed, 13 Dec 2023 10:24:30 -0500 (EST) Received: from smtpin20.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id F171914023E for ; Wed, 13 Dec 2023 15:24:29 +0000 (UTC) X-FDA: 81562166658.20.4BFC403 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf02.hostedemail.com (Postfix) with ESMTP id 37E7980002 for ; Wed, 13 Dec 2023 15:24:28 +0000 (UTC) Authentication-Results: imf02.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=WIOleZUV; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf02.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481068; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=4hViO3AGp6pToaoN8VF8Iwb+OF6je+qeF4CeyLwe0vY=; b=Bi+HFmQA7jojdsfvw2sZPoTzTIHOa/ppPN4pL81h2yMEmfuj9npWxkZ8PVdVGLlyN79aao oJVZCgv6ctuklT5P98dwi6vtkLdMTWvz4HJSDBLFyhxsGK2JJ1poMKet7tV+KZpWrjO+Wp uHmlN5yKUVSYDrU+sOpEDnhfTDn/FAw= ARC-Authentication-Results: i=1; imf02.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=WIOleZUV; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf02.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481068; a=rsa-sha256; cv=none; b=V/WbsYXHB23MTzAmKxvRL3ZyTCKygxsu/bZ6t+LC9MsfnswWTsLWFe2GUmurDh+yvrpCTI JOu8GOTEdkE21dD9a1KWTa43DdJ/7rTr2ePwPqY2J5Z49uGbZB5uR8aPhTvM5ExEcEmPZ1 ogCGtfgMK32NmZBHLV4eRRyf/PIqAb0= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481067; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4hViO3AGp6pToaoN8VF8Iwb+OF6je+qeF4CeyLwe0vY=; b=WIOleZUVq4BvcKe35ehXvFXi3JcG8KntZLCABcTRx07LeVGLg+oAmADZ+sSjypHwU5nlBb bsmAA5bZzNlUu6XGN2toW3tVAZIyh2e5smF4jcg563YWvG0x69bBaXM7rW/YUFtUv7kQDb kSIDwn7XaoVSXcPXSoOYJr4OXdkT1Ck= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-146-hdgHiFcROYScI5wxcv-SWw-1; Wed, 13 Dec 2023 10:24:23 -0500 X-MC-Unique: hdgHiFcROYScI5wxcv-SWw-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 1F3CC3C0E64B; Wed, 13 Dec 2023 15:24:22 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id F10D1C15968; Wed, 13 Dec 2023 15:24:18 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 07/39] netfs: Allow the netfs to make the io (sub)request alloc larger Date: Wed, 13 Dec 2023 15:23:17 +0000 Message-ID: <20231213152350.431591-8-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.8 X-Rspamd-Queue-Id: 37E7980002 X-Rspam-User: X-Rspamd-Server: rspam05 X-Stat-Signature: k98p74rcrhqtasmqjgyrzib69x3twp75 X-HE-Tag: 1702481068-581497 X-HE-Meta: U2FsdGVkX18lqG8/14WO7IkVmVI9c9+QxZVWrwq78ZNBufEGLW+OFObWj90BeJQv0VnDDHo2LwpfCXykHEloUOKkY+6FUXQnHijlSFQuciKn3ytT6ahGgHbKR0jKHG/hrlUrQklwwcdRFWvLHc82hvxoQMI+uGp2UbAq3mZJ/PkEkZqfeWHWMMf3mn3ThEgP2eKrKWeMhMVLci2dGtf3mDKUxubN2FT7lnE5eE/QwevYTN/oyM4CjsffFR5mJuXgVXI7RenvnJoCjF6Tqz1ReglgQMDlghGAH0ViF7snF/vkGhTEJ01uvzO8q2Ax7Pb5ALcVkVMSTr4FY0jLALSB8I6/yA7xONd9m13fb+4LQqgTydwIrSkVHBc0kuFe8TuD1Ec4OzfNUXvNOAZU1zH0ZLaHdFiX4f9KOJTpH4kWDoUP/GDAyxtRj/Cw3KGsM1PyuN1dHVmEKclEDrFx7AOGkRueCzKOuw65VeyrfETVV1FiqyZ9+5iMJOyEIsJmYUrdQz9/RKjMz/sH8LQQviR9o4AuKc/hId5M50Y/95fQisW0zg6FwJdqHonKcbh4Qys60ZT354wVjpvq70iJuZ5YiwjaQwca5K8Xxq+ZItSS00dWuKVanITJfosTVnQtUrR+yNMcTQoa7lh/rGRdX0M8krxucyGNLkqQ6rRl6rXO6sPkNg0QSvUr6K0i8iemkw1FiEhCzjVhq+U6bPWPpV1EAWvdWQM7VHtL1Dby8I4Vioe8OPWVTqfo/l23AV69FUd05qk9HRtcQr6k8uXqKi6CRVq18IFGUr6UqfU5Z/cJHvTtaOZKazfaV/bTMFk3Zr2S3EvyXBKbNalEwFOUAiQGxo2dJCo3ugPVMduQBChq0X22P3LTS0IRKa6UESbO7HuBffayaKloG6fNA7HdClrHNmO/Kt8bHM0Ze1bCqrk4cknfqKvi18z9vCgJuppUu+FUVepwnhPAJod/ap8L08B ljdFVrIQ pjNojnZ92KO4Mh7tK01AGlx73lW+bGfD8vDaf4Or5thIrzNBRlo9sDtQFOUEOZuWa8tM+TTjRMiR7xtKMQ0rIFWmGB040er31wGjAex+bl1eIH1ARkGijONjYUuxQZUJv/5bmvNOaBuB8ITeQWaWktyh1Kq+8YcicHjuHEw6zCPA9raW1UgDFnEEDjLjiOZVVjHnB2jCYsyqUk2YBdby2D+mfi7p8YEn9wdBCKyDW2qdTDI4aXf/Miife6aDDqOLlZVqayHgEUSddYgfD1G7/gc70b3p6tnnbx5kBvVp5I/D2R00= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Allow the network filesystem to specify extra space to be allocated on the end of the io (sub)request. This allows cifs, for example, to use this space rather than allocating its own cifs_readdata struct. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/objects.c | 7 +++++-- include/linux/netfs.h | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 85f428fc52e6..c4229c5f3f54 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -22,7 +22,8 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, struct netfs_io_request *rreq; int ret; - rreq = kzalloc(sizeof(struct netfs_io_request), GFP_KERNEL); + rreq = kzalloc(ctx->ops->io_request_size ?: sizeof(struct netfs_io_request), + GFP_KERNEL); if (!rreq) return ERR_PTR(-ENOMEM); @@ -114,7 +115,9 @@ struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request *rreq { struct netfs_io_subrequest *subreq; - subreq = kzalloc(sizeof(struct netfs_io_subrequest), GFP_KERNEL); + subreq = kzalloc(rreq->netfs_ops->io_subrequest_size ?: + sizeof(struct netfs_io_subrequest), + GFP_KERNEL); if (subreq) { INIT_LIST_HEAD(&subreq->rreq_link); refcount_set(&subreq->ref, 2); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 7244ddebd974..d6f27000eeb0 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -210,6 +210,8 @@ struct netfs_io_request { * Operations the network filesystem can/must provide to the helpers. */ struct netfs_request_ops { + unsigned int io_request_size; /* Alloc size for netfs_io_request struct */ + unsigned int io_subrequest_size; /* Alloc size for netfs_io_subrequest struct */ int (*init_request)(struct netfs_io_request *rreq, struct file *file); void (*free_request)(struct netfs_io_request *rreq); From patchwork Wed Dec 13 15:23:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491214 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id E1E25C4332F for ; Wed, 13 Dec 2023 15:24:33 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 7C9946B03ED; Wed, 13 Dec 2023 10:24:33 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 753706B03EF; Wed, 13 Dec 2023 10:24:33 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5F5616B03F0; Wed, 13 Dec 2023 10:24:33 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 4BB116B03ED for ; Wed, 13 Dec 2023 10:24:33 -0500 (EST) Received: from smtpin20.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 2493C80BFF for ; Wed, 13 Dec 2023 15:24:33 +0000 (UTC) X-FDA: 81562166826.20.8FBFE7B Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf28.hostedemail.com (Postfix) with ESMTP id 5D253C000E for ; Wed, 13 Dec 2023 15:24:31 +0000 (UTC) Authentication-Results: imf28.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=Ojp4M+ck; spf=pass (imf28.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481071; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=shWxGi+94hUVdbxc3FCgiKxDR0g1X33mrWTu84CcD7w=; b=txwAu3fdV4uSTGAqkYVaSXDSiwheFUXp6DkLIGLuiuAS2FytmFFWyrMG4GYdqDU6rr9JsC 6Sy9LnsS/zQa/j92m9K9rQH8Cz8Bu3agpUu7IQx1RG351SvP21jI6ot9K24VTv1sl1iwMi 3rM2fl7ESiSFKvWZhcyDxf+CeSphgbk= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481071; a=rsa-sha256; cv=none; b=oCbSVDwC79/t/YuwHUfjlipbZPE47Kkq2kRR0x2NmVFoPcWZzhS0E2Lc/xc976vUWXnnnM 6BVSYpkDZ3dw+15ltUEnC6AfeJMPsoU2dqZyu4BgDTH799MmU9vH4X/foV9Dr5jJA+KUhT a0gRzr8H0u3EjXgHIdvn9wa9zLALg68= ARC-Authentication-Results: i=1; imf28.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=Ojp4M+ck; spf=pass (imf28.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481070; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=shWxGi+94hUVdbxc3FCgiKxDR0g1X33mrWTu84CcD7w=; b=Ojp4M+ck/+9mDtm/095jHhKxf82U35JqSBpUWaIRA63NiAExUtPAwwk6EaUs0kcLSglErV XQuJfXVSsBCnkuo7cCtJJd48fRHGQ//7ka1qWs5WW/AmDyLxWOfDDn0cVwOnEfxM2b6j4m Uw//ztYzmSqVKgIEq93he+GX0pbDrEU= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-631-3z4VMODgPtmn2_8Q_yyXqA-1; Wed, 13 Dec 2023 10:24:27 -0500 X-MC-Unique: 3z4VMODgPtmn2_8Q_yyXqA-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 23E3085A58F; Wed, 13 Dec 2023 15:24:26 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id F1DF2492BC6; Wed, 13 Dec 2023 15:24:22 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 08/39] netfs: Add a ->free_subrequest() op Date: Wed, 13 Dec 2023 15:23:18 +0000 Message-ID: <20231213152350.431591-9-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.9 X-Stat-Signature: fcf9jaqn4pejuxz4jrsyy99gomizd7z4 X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: 5D253C000E X-Rspam-User: X-HE-Tag: 1702481071-974898 X-HE-Meta: U2FsdGVkX19HC7LowlYwFU4SEjqGT1V+Xg13uEUZBuqCKAfEyX1E7MnGnRZc2eFO6YgBHV8+paaOW86AqDHNHB/z8I94YXqVtyDiJJX6TxAUYVtkLKVtf4aWXDJYOyZMtkg4WbLK7rusOqmyARctfn9pKuP0Skl9Ml2nOaAKa+5rMeatxJ9kEVCuPLeAvhKOMAwnSIliTyE3KkLEomEl6I6UOvawItxEO7M1WA+mkFNEhZccLmKYUVN5kWr4cexbLrn/bBaIwe9VaUC6J+piMRxaC2rSWauWdop/1GVw1Vht28UeRPg3cAUAO28uDGKs7z4EuwV2sZ0D5GHDulyVeZ8k2uDuqO2Fv3nj97a/2odRVrojnzcq7NBG32IojF/SA7P3bup3F8eTkewmwG2uGlP8YufruIHNwN5+KQFINJkhBK1zZeQfQviTsXNI5H1KvhH4ofSWWspWVjg+/kG/d95CpHBJ8nJpXsCIbDjWWEVzlv+6tTKI83Eo13qaxvpzs/mivWANDbqzqPtqB0i95/O7Mu0ibUz6jmtAQT65tsv58jHaAZmjppLLAJNTgRKM3Jbv4OGdr1mASrw/SLlLNJKi3CfXJarX+AXplUKFCsglvslNhZO6DHa+g+8IP3oFRnNHZe6vQCyMCN4qd8pnI+n812xQb6VbB3ZARU2uq9ZTiwKs6ru1FPKjb1PSvysffGrp1iEBaEBGbLq9kQFLx4B23BmZZWbREmcuk3sUID/3CTjS/+EHp2EB97z/wOO+xltxpd0ptUs8FBm63q7ZzR5cIP21T5lE1sd2ahf83+GIcAWRXcVhQ+5u/zl7ca1uYAnXY0/LjFOVTsPs3H+HocV8Kfqfc3VCJQf33FTCWVX0rK5seMstlJF5gTUj2z1Ih2/41ooYkJqjzKaGcIECHqInY+sPl7+LYM6Zzo2lHUYvaQY7CDvig/Kuylv3KhxRMxzovi/V1wgDTYqZy5C 0VCgFolC BhTnk3RpW0f7UDRaBJVL8NOWZmnSj3t6GXmZNwQ/FnCOFjZXA8rtivgf+Er1KbfFoGf30uUYapG9mxTB2MCuImyXVazq6mkav1+P0zBd8iFpEsWKOhk/pShxCsa6BYg1DZ4H5/o2LOQjDss7iAuBIWPq91Cs2ERwrfVgTvempGnIhkp6TuuufpZc3pLSn6nlzJ0ILUjhIRq9WjMwN/m6U+Vh7g7pQi/qCM7Ixxm2rBC77dZSj9wKsWPUub2jU17EErVCl2tfTxtl8uapkeTYauaQNPoPP+gknhWsMmadIXB9bFvWA4wKtCF/r/8qwwXT3/3Pt4Ub/GJQUciUo+uiJArIMjg== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Add a ->free_subrequest() op so that the netfs can clean up data attached to a subrequest. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/objects.c | 2 ++ include/linux/netfs.h | 1 + 2 files changed, 3 insertions(+) diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index c4229c5f3f54..1bd20bdad983 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -145,6 +145,8 @@ static void netfs_free_subrequest(struct netfs_io_subrequest *subreq, struct netfs_io_request *rreq = subreq->rreq; trace_netfs_sreq(subreq, netfs_sreq_trace_free); + if (rreq->netfs_ops->free_subrequest) + rreq->netfs_ops->free_subrequest(subreq); kfree(subreq); netfs_stat_d(&netfs_n_rh_sreq); netfs_put_request(rreq, was_async, netfs_rreq_trace_put_subreq); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index d6f27000eeb0..06f57d9d09f6 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -214,6 +214,7 @@ struct netfs_request_ops { unsigned int io_subrequest_size; /* Alloc size for netfs_io_subrequest struct */ int (*init_request)(struct netfs_io_request *rreq, struct file *file); void (*free_request)(struct netfs_io_request *rreq); + void (*free_subrequest)(struct netfs_io_subrequest *rreq); void (*expand_readahead)(struct netfs_io_request *rreq); bool (*clamp_length)(struct netfs_io_subrequest *subreq); From patchwork Wed Dec 13 15:23:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491215 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id A104FC4332F for ; Wed, 13 Dec 2023 15:24:41 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 30E8F6B03FF; Wed, 13 Dec 2023 10:24:41 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 2BDB06B0400; Wed, 13 Dec 2023 10:24:41 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 121EF6B0404; Wed, 13 Dec 2023 10:24:41 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id F02366B03FF for ; Wed, 13 Dec 2023 10:24:40 -0500 (EST) Received: from smtpin27.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id D49991A0197 for ; Wed, 13 Dec 2023 15:24:40 +0000 (UTC) X-FDA: 81562167120.27.DBFD923 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf27.hostedemail.com (Postfix) with ESMTP id 1D6EC40018 for ; Wed, 13 Dec 2023 15:24:38 +0000 (UTC) Authentication-Results: imf27.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=MDcrZnHw; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf27.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481079; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=5vbdrTroQCTzU63MkJdxlO30JfSuAww8GyU+Oz0OZyc=; b=JRXWY20f+8h/VjVFk1SnXkAP9hXdkkqZTbTj/NU0aNCDxPNABUdBi7e3COcxVsRoqS3OPT Tz0epkYiirlcfL5BC4Vo4dFhemGCHaD2WiLeEpIaCLDTiJWoNsnizckgcSOvk0oy9rBpQL kSMOr5VTLq1DqQ7Vin4A+NJPxNsR5GY= ARC-Authentication-Results: i=1; imf27.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=MDcrZnHw; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf27.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481079; a=rsa-sha256; cv=none; b=wvaiTDZZdGk8kVjR5+jyCVRrxOKQXxbQrjFcdE5ijECMDWhcjiKOX/wSp6nUbbE98b4+7t 1TI4UtyP5ZNPe6Pq3j2bKjAOeOAPcmS9rPWD2x6Tut/lvJ2OpOqL1R4cndYH5jjoXNmnM7 Y5HSfsdweQoNdIdcJSDFxlLOnZAUpGs= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481078; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5vbdrTroQCTzU63MkJdxlO30JfSuAww8GyU+Oz0OZyc=; b=MDcrZnHwypkkg7rV10uCSEqUD0PQ7fR+1grftRSt3ZnNHp9Rx5kGYX6aU/TobIgRWdt9CB R1p7YPECdEjoIS8nhhdsE4AWfm5i4ZIYUCvkKyh3ki4MuKg+nX5kYU/Qipg05osab3PzFS QVPJXs/H03gtMWW8/5Yw3SWaVPpqr8M= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-558-XqPlUECeO4yQBV9Zj7c5EA-1; Wed, 13 Dec 2023 10:24:31 -0500 X-MC-Unique: XqPlUECeO4yQBV9Zj7c5EA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 72EF229AC034; Wed, 13 Dec 2023 15:24:30 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id D792D40C6EB9; Wed, 13 Dec 2023 15:24:26 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 09/39] afs: Don't use folio->private to record partial modification Date: Wed, 13 Dec 2023 15:23:19 +0000 Message-ID: <20231213152350.431591-10-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-Rspamd-Queue-Id: 1D6EC40018 X-Rspam-User: X-Rspamd-Server: rspam04 X-Stat-Signature: 8j4dmhtcehe7ggj68dcw9rp5itwochkg X-HE-Tag: 1702481078-511070 X-HE-Meta: U2FsdGVkX18SEYsMm2VyIej16HNLRN62BXRUZ8DkeHbvKvLp6MFfSVFgrC7bN8CjEsXC5PmikhSV+HCAJ8ocOuctB+QK+hOkrHxI/R0eWrnqyK6TWNdEmycEMraw4pOnA4vCdVh6/kvWpELQFuI1k9GkaEHAoqjO3TG9LnjOZVyRvh+qnnef6eVIJApN3cwTFvlk/nJ5gcDQjPlgpqZJuTR4J8yedl9vqifyaKPPBjny0JalKRpNbwP9tcfHOzOM/UZ+EhhcJfcJHL+nTwPQXYqfs7ANaJVZKEJI0G0DgVW+bgIKIbUMfFiLNjFNGaIoOWpxPr5A+Lxm1ATs6GOZ0jj4/mgBgbVyzWu7llMR9t3UDo8khklVrb4064RvrYnh4JmCSvYdP9nx2rA9uhUzBnEsLIIlkJ4OHT8DUQTNrt8TdiPqWzw4pNWqX8yWq+5obi+HOYaaq28Ep+5UCbVMpEcQI6zfza14HwgMBhpBRtDbgw/pCjvnYQanNi191JCo4lol18Im6JehDAkjh7niqObuqWaGMVoclMlToDZIrcnrCylPcCZ0vGbiR5MAH/G6QAe9EqpX9RQORJzTMhFdwXjadafcURR/2KlZZsnpB9bTe9+6wfCdKTkRGikVdm/HZVrveFhdUQw2Rf4GtVscxMvwU7Q6Hx4hiGz0O7Uw/OcSk0XIWXXfTBdzIXHtz+xNkGFlZSjaMa+Vvpf1hRuG/ij6fG6qF2sSp07uKb01WTpYwkc+6RIDajo5J+yePm5NY3zAjEj08KSTh2x+29giXQpkokvQmIK28jbLmasx6c5OZ8WHf9SgBZEip9bMIoNbYZ0IFdT9BxE0fZxNT3vg1/1Ys3IbokPsU86eemoEGe8fPSAnanW5vQ9a+IFzwaHSxKJum5646FGNjlP+oVWvrpAFmpLWDTe67cWdE+m0ChZdZ11Ys9mVJWHhRUYsRBLPWIz19kLvPQY/aPpQRm/ 4XsIMVZE TyOeGNZspQ+Ebzu4SYv98QIwx6Kjw8OodgkKNXzPw4lF3saemdFll3wdlkKF2utue3ucWaPInvfk+MxFSbE1r9XnEwfpM2F82M03n10FqnMCPzsI+rilJXZNx4kTm6a3VFXSohDbuv39/htx1nCngsQstGLZ+opHURuXGNvWZwbKryR3O3Tqaq8ByByMbntRgvkaPSX5+xqpbE+WcSCEbvqFYJasuyaMs2VwO2AoKEHaZ5lbERG0z4fpP7tZnJvWDbqS4B96zijLT0sGctfeXntCoRMKqCDDQN+gnlJBFBVmlM5rDCZpdZWrrEy+Ar6fgPsmyzJF2pCOGNBWFl3geAtn9SwF/ibipFRz86bNB1Q3etcwfcM5VNctDoYV9ldWc100aI7P4wqhpHMWTY3kMGqWBa5u8rX/0GBBM X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: AFS currently uses folio->private to store the range of bytes within a folio that have been modified - the idea being that if we have, say, a 2MiB folio and someone writes a single byte, we only have to write back that single page and not the whole 2MiB folio - thereby saving on network bandwidth. Remove this, at least for now, and accept the extra network load (which doesn't matter in the common case of writing a whole file at a time from beginning to end). This makes folio->private available for netfslib to use. Signed-off-by: David Howells cc: Marc Dionne cc: Jeff Layton cc: linux-afs@lists.infradead.org cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/afs/file.c | 67 ------------- fs/afs/internal.h | 56 ----------- fs/afs/write.c | 188 ++++++++----------------------------- include/trace/events/afs.h | 16 +--- 4 files changed, 42 insertions(+), 285 deletions(-) diff --git a/fs/afs/file.c b/fs/afs/file.c index c09e881da5d2..5e2bca3b02fd 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -383,63 +383,6 @@ const struct netfs_request_ops afs_req_ops = { .issue_read = afs_issue_read, }; -/* - * Adjust the dirty region of the page on truncation or full invalidation, - * getting rid of the markers altogether if the region is entirely invalidated. - */ -static void afs_invalidate_dirty(struct folio *folio, size_t offset, - size_t length) -{ - struct afs_vnode *vnode = AFS_FS_I(folio_inode(folio)); - unsigned long priv; - unsigned int f, t, end = offset + length; - - priv = (unsigned long)folio_get_private(folio); - - /* we clean up only if the entire page is being invalidated */ - if (offset == 0 && length == folio_size(folio)) - goto full_invalidate; - - /* If the page was dirtied by page_mkwrite(), the PTE stays writable - * and we don't get another notification to tell us to expand it - * again. - */ - if (afs_is_folio_dirty_mmapped(priv)) - return; - - /* We may need to shorten the dirty region */ - f = afs_folio_dirty_from(folio, priv); - t = afs_folio_dirty_to(folio, priv); - - if (t <= offset || f >= end) - return; /* Doesn't overlap */ - - if (f < offset && t > end) - return; /* Splits the dirty region - just absorb it */ - - if (f >= offset && t <= end) - goto undirty; - - if (f < offset) - t = offset; - else - f = end; - if (f == t) - goto undirty; - - priv = afs_folio_dirty(folio, f, t); - folio_change_private(folio, (void *)priv); - trace_afs_folio_dirty(vnode, tracepoint_string("trunc"), folio); - return; - -undirty: - trace_afs_folio_dirty(vnode, tracepoint_string("undirty"), folio); - folio_clear_dirty_for_io(folio); -full_invalidate: - trace_afs_folio_dirty(vnode, tracepoint_string("inval"), folio); - folio_detach_private(folio); -} - /* * invalidate part or all of a page * - release a page and clean up its private data if offset is 0 (indicating @@ -450,11 +393,6 @@ static void afs_invalidate_folio(struct folio *folio, size_t offset, { _enter("{%lu},%zu,%zu", folio->index, offset, length); - BUG_ON(!folio_test_locked(folio)); - - if (folio_get_private(folio)) - afs_invalidate_dirty(folio, offset, length); - folio_wait_fscache(folio); _leave(""); } @@ -482,11 +420,6 @@ static bool afs_release_folio(struct folio *folio, gfp_t gfp) fscache_note_page_release(afs_vnode_cache(vnode)); #endif - if (folio_test_private(folio)) { - trace_afs_folio_dirty(vnode, tracepoint_string("rel"), folio); - folio_detach_private(folio); - } - /* Indicate that the folio can be released */ _leave(" = T"); return true; diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 379fcd698062..b638c0f87298 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -984,62 +984,6 @@ static inline void afs_invalidate_cache(struct afs_vnode *vnode, unsigned int fl i_size_read(&vnode->netfs.inode), flags); } -/* - * We use folio->private to hold the amount of the folio that we've written to, - * splitting the field into two parts. However, we need to represent a range - * 0...FOLIO_SIZE, so we reduce the resolution if the size of the folio - * exceeds what we can encode. - */ -#ifdef CONFIG_64BIT -#define __AFS_FOLIO_PRIV_MASK 0x7fffffffUL -#define __AFS_FOLIO_PRIV_SHIFT 32 -#define __AFS_FOLIO_PRIV_MMAPPED 0x80000000UL -#else -#define __AFS_FOLIO_PRIV_MASK 0x7fffUL -#define __AFS_FOLIO_PRIV_SHIFT 16 -#define __AFS_FOLIO_PRIV_MMAPPED 0x8000UL -#endif - -static inline unsigned int afs_folio_dirty_resolution(struct folio *folio) -{ - int shift = folio_shift(folio) - (__AFS_FOLIO_PRIV_SHIFT - 1); - return (shift > 0) ? shift : 0; -} - -static inline size_t afs_folio_dirty_from(struct folio *folio, unsigned long priv) -{ - unsigned long x = priv & __AFS_FOLIO_PRIV_MASK; - - /* The lower bound is inclusive */ - return x << afs_folio_dirty_resolution(folio); -} - -static inline size_t afs_folio_dirty_to(struct folio *folio, unsigned long priv) -{ - unsigned long x = (priv >> __AFS_FOLIO_PRIV_SHIFT) & __AFS_FOLIO_PRIV_MASK; - - /* The upper bound is immediately beyond the region */ - return (x + 1) << afs_folio_dirty_resolution(folio); -} - -static inline unsigned long afs_folio_dirty(struct folio *folio, size_t from, size_t to) -{ - unsigned int res = afs_folio_dirty_resolution(folio); - from >>= res; - to = (to - 1) >> res; - return (to << __AFS_FOLIO_PRIV_SHIFT) | from; -} - -static inline unsigned long afs_folio_dirty_mmapped(unsigned long priv) -{ - return priv | __AFS_FOLIO_PRIV_MMAPPED; -} - -static inline bool afs_is_folio_dirty_mmapped(unsigned long priv) -{ - return priv & __AFS_FOLIO_PRIV_MMAPPED; -} - #include /*****************************************************************************/ diff --git a/fs/afs/write.c b/fs/afs/write.c index 62e1cc5985c4..959dfa8f1af0 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -16,7 +16,8 @@ static int afs_writepages_region(struct address_space *mapping, struct writeback_control *wbc, - loff_t start, loff_t end, loff_t *_next, + unsigned long long start, + unsigned long long end, loff_t *_next, bool max_one_loop); static void afs_write_to_cache(struct afs_vnode *vnode, loff_t start, size_t len, @@ -34,25 +35,6 @@ static void afs_folio_start_fscache(bool caching, struct folio *folio) } #endif -/* - * Flush out a conflicting write. This may extend the write to the surrounding - * pages if also dirty and contiguous to the conflicting region.. - */ -static int afs_flush_conflicting_write(struct address_space *mapping, - struct folio *folio) -{ - struct writeback_control wbc = { - .sync_mode = WB_SYNC_ALL, - .nr_to_write = LONG_MAX, - .range_start = folio_pos(folio), - .range_end = LLONG_MAX, - }; - loff_t next; - - return afs_writepages_region(mapping, &wbc, folio_pos(folio), LLONG_MAX, - &next, true); -} - /* * prepare to perform part of a write to a page */ @@ -62,10 +44,6 @@ int afs_write_begin(struct file *file, struct address_space *mapping, { struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); struct folio *folio; - unsigned long priv; - unsigned f, from; - unsigned t, to; - pgoff_t index; int ret; _enter("{%llx:%llu},%llx,%x", @@ -79,49 +57,20 @@ int afs_write_begin(struct file *file, struct address_space *mapping, if (ret < 0) return ret; - index = folio_index(folio); - from = pos - index * PAGE_SIZE; - to = from + len; - try_again: /* See if this page is already partially written in a way that we can * merge the new write with. */ - if (folio_test_private(folio)) { - priv = (unsigned long)folio_get_private(folio); - f = afs_folio_dirty_from(folio, priv); - t = afs_folio_dirty_to(folio, priv); - ASSERTCMP(f, <=, t); - - if (folio_test_writeback(folio)) { - trace_afs_folio_dirty(vnode, tracepoint_string("alrdy"), folio); - folio_unlock(folio); - goto wait_for_writeback; - } - /* If the file is being filled locally, allow inter-write - * spaces to be merged into writes. If it's not, only write - * back what the user gives us. - */ - if (!test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags) && - (to < f || from > t)) - goto flush_conflicting_write; + if (folio_test_writeback(folio)) { + trace_afs_folio_dirty(vnode, tracepoint_string("alrdy"), folio); + folio_unlock(folio); + goto wait_for_writeback; } *_page = folio_file_page(folio, pos / PAGE_SIZE); _leave(" = 0"); return 0; - /* The previous write and this write aren't adjacent or overlapping, so - * flush the page out. - */ -flush_conflicting_write: - trace_afs_folio_dirty(vnode, tracepoint_string("confl"), folio); - folio_unlock(folio); - - ret = afs_flush_conflicting_write(mapping, folio); - if (ret < 0) - goto error; - wait_for_writeback: ret = folio_wait_writeback_killable(folio); if (ret < 0) @@ -147,9 +96,6 @@ int afs_write_end(struct file *file, struct address_space *mapping, { struct folio *folio = page_folio(subpage); struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); - unsigned long priv; - unsigned int f, from = offset_in_folio(folio, pos); - unsigned int t, to = from + copied; loff_t i_size, write_end_pos; _enter("{%llx:%llu},{%lx}", @@ -179,23 +125,6 @@ int afs_write_end(struct file *file, struct address_space *mapping, fscache_update_cookie(afs_vnode_cache(vnode), NULL, &write_end_pos); } - if (folio_test_private(folio)) { - priv = (unsigned long)folio_get_private(folio); - f = afs_folio_dirty_from(folio, priv); - t = afs_folio_dirty_to(folio, priv); - if (from < f) - f = from; - if (to > t) - t = to; - priv = afs_folio_dirty(folio, f, t); - folio_change_private(folio, (void *)priv); - trace_afs_folio_dirty(vnode, tracepoint_string("dirty+"), folio); - } else { - priv = afs_folio_dirty(folio, from, to); - folio_attach_private(folio, (void *)priv); - trace_afs_folio_dirty(vnode, tracepoint_string("dirty"), folio); - } - if (folio_mark_dirty(folio)) _debug("dirtied %lx", folio_index(folio)); @@ -300,7 +229,6 @@ static void afs_pages_written_back(struct afs_vnode *vnode, loff_t start, unsign } trace_afs_folio_dirty(vnode, tracepoint_string("clear"), folio); - folio_detach_private(folio); folio_end_writeback(folio); } @@ -454,17 +382,12 @@ static void afs_extend_writeback(struct address_space *mapping, long *_count, loff_t start, loff_t max_len, - bool new_content, bool caching, - unsigned int *_len) + size_t *_len) { struct folio_batch fbatch; struct folio *folio; - unsigned long priv; - unsigned int psize, filler = 0; - unsigned int f, t; - loff_t len = *_len; - pgoff_t index = (start + len) / PAGE_SIZE; + pgoff_t index = (start + *_len) / PAGE_SIZE; bool stop = true; unsigned int i; @@ -492,7 +415,7 @@ static void afs_extend_writeback(struct address_space *mapping, continue; } - /* Has the page moved or been split? */ + /* Has the folio moved or been split? */ if (unlikely(folio != xas_reload(&xas))) { folio_put(folio); break; @@ -510,24 +433,13 @@ static void afs_extend_writeback(struct address_space *mapping, break; } - psize = folio_size(folio); - priv = (unsigned long)folio_get_private(folio); - f = afs_folio_dirty_from(folio, priv); - t = afs_folio_dirty_to(folio, priv); - if (f != 0 && !new_content) { - folio_unlock(folio); - folio_put(folio); - break; - } - - len += filler + t; - filler = psize - t; - if (len >= max_len || *_count <= 0) + index += folio_nr_pages(folio); + *_count -= folio_nr_pages(folio); + *_len += folio_size(folio); + stop = false; + if (*_len >= max_len || *_count <= 0) stop = true; - else if (t == psize || new_content) - stop = false; - index += folio_nr_pages(folio); if (!folio_batch_add(&fbatch, folio)) break; if (stop) @@ -552,16 +464,12 @@ static void afs_extend_writeback(struct address_space *mapping, BUG(); folio_start_writeback(folio); afs_folio_start_fscache(caching, folio); - - *_count -= folio_nr_pages(folio); folio_unlock(folio); } folio_batch_release(&fbatch); cond_resched(); } while (!stop); - - *_len = len; } /* @@ -571,14 +479,13 @@ static void afs_extend_writeback(struct address_space *mapping, static ssize_t afs_write_back_from_locked_folio(struct address_space *mapping, struct writeback_control *wbc, struct folio *folio, - loff_t start, loff_t end) + unsigned long long start, + unsigned long long end) { struct afs_vnode *vnode = AFS_FS_I(mapping->host); struct iov_iter iter; - unsigned long priv; - unsigned int offset, to, len, max_len; - loff_t i_size = i_size_read(&vnode->netfs.inode); - bool new_content = test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); + unsigned long long i_size = i_size_read(&vnode->netfs.inode); + size_t len, max_len; bool caching = fscache_cookie_enabled(afs_vnode_cache(vnode)); long count = wbc->nr_to_write; int ret; @@ -595,13 +502,9 @@ static ssize_t afs_write_back_from_locked_folio(struct address_space *mapping, * immediately lockable, is not dirty or is missing, or we reach the * end of the range. */ - priv = (unsigned long)folio_get_private(folio); - offset = afs_folio_dirty_from(folio, priv); - to = afs_folio_dirty_to(folio, priv); trace_afs_folio_dirty(vnode, tracepoint_string("store"), folio); - len = to - offset; - start += offset; + len = folio_size(folio); if (start < i_size) { /* Trim the write to the EOF; the extra data is ignored. Also * put an upper limit on the size of a single storedata op. @@ -610,12 +513,10 @@ static ssize_t afs_write_back_from_locked_folio(struct address_space *mapping, max_len = min_t(unsigned long long, max_len, end - start + 1); max_len = min_t(unsigned long long, max_len, i_size - start); - if (len < max_len && - (to == folio_size(folio) || new_content)) + if (len < max_len) afs_extend_writeback(mapping, vnode, &count, - start, max_len, new_content, - caching, &len); - len = min_t(loff_t, len, max_len); + start, max_len, caching, &len); + len = min_t(unsigned long long, len, i_size - start); } /* We now have a contiguous set of dirty pages, each with writeback @@ -625,7 +526,7 @@ static ssize_t afs_write_back_from_locked_folio(struct address_space *mapping, folio_unlock(folio); if (start < i_size) { - _debug("write back %x @%llx [%llx]", len, start, i_size); + _debug("write back %zx @%llx [%llx]", len, start, i_size); /* Speculatively write to the cache. We have to fix this up * later if the store fails. @@ -635,7 +536,7 @@ static ssize_t afs_write_back_from_locked_folio(struct address_space *mapping, iov_iter_xarray(&iter, ITER_SOURCE, &mapping->i_pages, start, len); ret = afs_store_data(vnode, &iter, start, false); } else { - _debug("write discard %x @%llx [%llx]", len, start, i_size); + _debug("write discard %zx @%llx [%llx]", len, start, i_size); /* The dirty region was entirely beyond the EOF. */ fscache_clear_page_bits(mapping, start, len, caching); @@ -691,7 +592,8 @@ static ssize_t afs_write_back_from_locked_folio(struct address_space *mapping, */ static int afs_writepages_region(struct address_space *mapping, struct writeback_control *wbc, - loff_t start, loff_t end, loff_t *_next, + unsigned long long start, + unsigned long long end, loff_t *_next, bool max_one_loop) { struct folio *folio; @@ -903,7 +805,6 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf) struct inode *inode = file_inode(file); struct afs_vnode *vnode = AFS_FS_I(inode); struct afs_file *af = file->private_data; - unsigned long priv; vm_fault_t ret = VM_FAULT_RETRY; _enter("{{%llx:%llu}},{%lx}", vnode->fid.vid, vnode->fid.vnode, folio_index(folio)); @@ -927,24 +828,15 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf) if (folio_lock_killable(folio) < 0) goto out; - /* We mustn't change folio->private until writeback is complete as that - * details the portion of the page we need to write back and we might - * need to redirty the page if there's a problem. - */ if (folio_wait_writeback_killable(folio) < 0) { folio_unlock(folio); goto out; } - priv = afs_folio_dirty(folio, 0, folio_size(folio)); - priv = afs_folio_dirty_mmapped(priv); - if (folio_test_private(folio)) { - folio_change_private(folio, (void *)priv); + if (folio_test_dirty(folio)) trace_afs_folio_dirty(vnode, tracepoint_string("mkwrite+"), folio); - } else { - folio_attach_private(folio, (void *)priv); + else trace_afs_folio_dirty(vnode, tracepoint_string("mkwrite"), folio); - } file_update_time(file); ret = VM_FAULT_LOCKED; @@ -989,30 +881,26 @@ int afs_launder_folio(struct folio *folio) struct afs_vnode *vnode = AFS_FS_I(folio_inode(folio)); struct iov_iter iter; struct bio_vec bv; - unsigned long priv; - unsigned int f, t; + unsigned long long fend, i_size = vnode->netfs.inode.i_size; + size_t len; int ret = 0; _enter("{%lx}", folio->index); - priv = (unsigned long)folio_get_private(folio); - if (folio_clear_dirty_for_io(folio)) { - f = 0; - t = folio_size(folio); - if (folio_test_private(folio)) { - f = afs_folio_dirty_from(folio, priv); - t = afs_folio_dirty_to(folio, priv); - } + if (folio_clear_dirty_for_io(folio) && folio_pos(folio) < i_size) { + len = folio_size(folio); + fend = folio_pos(folio) + len; + if (vnode->netfs.inode.i_size < fend) + len = fend - i_size; - bvec_set_folio(&bv, folio, t - f, f); - iov_iter_bvec(&iter, ITER_SOURCE, &bv, 1, bv.bv_len); + bvec_set_folio(&bv, folio, len, 0); + iov_iter_bvec(&iter, WRITE, &bv, 1, len); trace_afs_folio_dirty(vnode, tracepoint_string("launder"), folio); - ret = afs_store_data(vnode, &iter, folio_pos(folio) + f, true); + ret = afs_store_data(vnode, &iter, folio_pos(folio), true); } trace_afs_folio_dirty(vnode, tracepoint_string("laundered"), folio); - folio_detach_private(folio); folio_wait_fscache(folio); return ret; } diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index 5194b7e6dc8d..7780bd716ce0 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -911,26 +911,18 @@ TRACE_EVENT(afs_folio_dirty, __field(struct afs_vnode *, vnode) __field(const char *, where) __field(pgoff_t, index) - __field(unsigned long, from) - __field(unsigned long, to) + __field(size_t, size) ), TP_fast_assign( - unsigned long priv = (unsigned long)folio_get_private(folio); __entry->vnode = vnode; __entry->where = where; __entry->index = folio_index(folio); - __entry->from = afs_folio_dirty_from(folio, priv); - __entry->to = afs_folio_dirty_to(folio, priv); - __entry->to |= (afs_is_folio_dirty_mmapped(priv) ? - (1UL << (BITS_PER_LONG - 1)) : 0); + __entry->size = folio_size(folio); ), - TP_printk("vn=%p %lx %s %lx-%lx%s", - __entry->vnode, __entry->index, __entry->where, - __entry->from, - __entry->to & ~(1UL << (BITS_PER_LONG - 1)), - __entry->to & (1UL << (BITS_PER_LONG - 1)) ? " M" : "") + TP_printk("vn=%p ix=%05lx s=%05lx %s", + __entry->vnode, __entry->index, __entry->size, __entry->where) ); TRACE_EVENT(afs_call_state, From patchwork Wed Dec 13 15:23:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491216 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id CD0AEC4332F for ; Wed, 13 Dec 2023 15:24:48 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 5CE6F8D0023; Wed, 13 Dec 2023 10:24:48 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 57CB48D0015; Wed, 13 Dec 2023 10:24:48 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 3CFA18D0023; Wed, 13 Dec 2023 10:24:48 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id 2A5098D0015 for ; Wed, 13 Dec 2023 10:24:48 -0500 (EST) Received: from smtpin08.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 03BDE1401E3 for ; Wed, 13 Dec 2023 15:24:47 +0000 (UTC) X-FDA: 81562167456.08.0BAAD49 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf23.hostedemail.com (Postfix) with ESMTP id A9687140017 for ; Wed, 13 Dec 2023 15:24:45 +0000 (UTC) Authentication-Results: imf23.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=EXPiZAsV; spf=pass (imf23.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481085; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=jj3k9IeX7NTGcPRjglvEPxLODcDVViOsYShT5ukMf5o=; b=kX+JWAuTq1NekvtS0BSROkPYGBC65KgHsaaj72HG79zivvmxR0nIbhqj9jWCrns8HnyjLW FlUlSY/3kI5VH9Q6b6Da5TojecNhPPxbFJeuAp12/XRGJjKy0iC6E5UNQ1WwJmMu8w5k21 ajbU/D8xQcRsFcuk4vs3o0mZCDlT3+E= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481085; a=rsa-sha256; cv=none; b=si2pc7jFPV6zy6fpVyYvLaf74sefRmppEanrsGCgokOMNXeA+qiCpNDkzSX2Hn9euKapzS Aq3OXB4phkkfLgpFGAedoNTOuLlB7n82bjHpX3WJn6a5zN+dwbHStJdDJyrLNbi6EnEoKU 5bEbwS/bvFtXKdtmvZTHvdymeclkQyI= ARC-Authentication-Results: i=1; imf23.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=EXPiZAsV; spf=pass (imf23.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481085; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jj3k9IeX7NTGcPRjglvEPxLODcDVViOsYShT5ukMf5o=; b=EXPiZAsVUBidViiiO37/kf6xhnDitV9R3c5ZqkfKq21ueywJDv6TNoAwje5jgH6K4rwBp6 bej3oMGaof8arw9H8DiCUktDxFH8e3gsTGZs7zJVY61yvkHRPFAVq2diBCn/7/0rC88Q2r n9TSRqs6xDbvNsrx264Bgoz/lEDjIHQ= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-134-erhQmRKCNr2uZTNY3BdNZw-1; Wed, 13 Dec 2023 10:24:40 -0500 X-MC-Unique: erhQmRKCNr2uZTNY3BdNZw-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 70D82881B6F; Wed, 13 Dec 2023 15:24:39 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 80F8D2166B31; Wed, 13 Dec 2023 15:24:36 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 10/39] netfs: Provide invalidate_folio and release_folio calls Date: Wed, 13 Dec 2023 15:23:20 +0000 Message-ID: <20231213152350.431591-11-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.6 X-Rspamd-Queue-Id: A9687140017 X-Rspam-User: X-Rspamd-Server: rspam11 X-Stat-Signature: 3zppy6oxtjsttrmk9dcec131iw35ijq1 X-HE-Tag: 1702481085-576155 X-HE-Meta: U2FsdGVkX19rPYVrOZIDfcHfPNiExkr1iq34p6BbfVDviOaHu7USlwwT4JeKNa0ffEsQKAZAJ3/fGIHsf2It/jjmo0MhRYaThbHa/atfvO1q8J7FcQUo+qhKaSMCwZmCvqdOGXaAVBqcL4Q9sDmXbQd9FtQxg//BZ4mAl/IYY5CRxWy1TLAyg3mmegUJSQYT2beCGRhTlu9sJvRTQgod0xHBSPh13qSSDFN23NpXLek46HtdwANHN51fU5+GZlOB7mW+XLc8g3OGRaaj9jcDO2xBQjX5UgeWkGV0N6cbPBS3AWcrxUgD12OeUZZRWKzlikcMMQT6RfkocZunZMV53CUHU9aECRV3CFvovwbu5QYTfPHmB1JTvmKII7EUaD+5nB4ynNeGT5WkyEqVlLqCr0n3I5hGoZsogF17gVcj0lTHgQIe/Jr6pO/IZ+lc1qYbuDpGxPZMOYJXhcTHrfOaIZhwi8YuiAKku0q05zBhRGJmBsHb8nvshoiHTTTw82Xp2iEnC21T3rcmCbsGiAWn3Vpe+2JfshXZOzQhgRg8ENSnyF/LrXtNukXH6Ve/KMu05Lc3dgN5PM/katOOdGtmqo2AfHJdjrDYbNZUiXsMAlLXejLLoCH+d2q4Ul/SozzZLffnh2yulymeLwOT1STHuXgSu1CEUmEYaowsM/IHFsjypnHNBwFuKd4rJ/mWH/MOUwl+9Kw6+Zd85XSfxVsFcX/sWqbvxNfILLXdst7U9DQLZzN4v2JC63219m73iegJnqEywR7RBFAgdeuVml+UvP0suq3uqnEvdxhfT7GRN/ksK9EbX0Th/3sYJpRr+Zyo2zMW+fFmbSwUKq7+NIWSbjf3mnnrbbjl0lnQjGfrdjAbXJ27XLnT+aOnsK5k9vsnnDrpMHuz4/kek6PXJW3D8oaKC80ts3BdjIS37ow3S+FmEI4DtE8MLcuxZaEKguQD2lppjcJ5KLBQY4HhFDY lCd0X0+n 50Q7/mdO3Hm70CvY/oAEbVnmxsU1UXSRK+aDwAnJSg7Xy0YsOBcppb7M/fl1fVpZTxkqz6S9uAJ1V/RAJzNjS0DUT78nw9Vz3jI/z7viUnMTkpedBpwkLrnvg+Zxul63lMHZRTemB6gnd8iqaKQukqzAI4DO7iSg68E/L2TsBIXY+nlUQkD5L9sFRI4n3I+GpZ334wQnjGRPuv0d+luhgyd0Eq4yGkkmaRjvVp5cmhKvimOO/uVxVG/tCPrv2yQ6omSzAVIQb5GdtGooqkuI4UPT5tQ8ALdLRSQRNC3LeNOezYXUXzxU4LtjQRr1YSGP8UGEZg5ZVDHh6xkgElF/Tc8jqXg== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Provide default invalidate_folio and release_folio calls. These will need to interact with invalidation correctly at some point. They will be needed if netfslib is to make use of folio->private for its own purposes. Signed-off-by: David Howells Reviewed-by: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/9p/vfs_addr.c | 33 ++------------------------- fs/afs/file.c | 53 ++++--------------------------------------- fs/ceph/addr.c | 24 ++------------------ fs/netfs/misc.c | 42 ++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 6 +++-- 5 files changed, 54 insertions(+), 104 deletions(-) diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 131b83c31f85..055b672a247d 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -88,35 +88,6 @@ const struct netfs_request_ops v9fs_req_ops = { .issue_read = v9fs_issue_read, }; -/** - * v9fs_release_folio - release the private state associated with a folio - * @folio: The folio to be released - * @gfp: The caller's allocation restrictions - * - * Returns true if the page can be released, false otherwise. - */ - -static bool v9fs_release_folio(struct folio *folio, gfp_t gfp) -{ - if (folio_test_private(folio)) - return false; -#ifdef CONFIG_9P_FSCACHE - if (folio_test_fscache(folio)) { - if (current_is_kswapd() || !(gfp & __GFP_FS)) - return false; - folio_wait_fscache(folio); - } - fscache_note_page_release(v9fs_inode_cookie(V9FS_I(folio_inode(folio)))); -#endif - return true; -} - -static void v9fs_invalidate_folio(struct folio *folio, size_t offset, - size_t length) -{ - folio_wait_fscache(folio); -} - #ifdef CONFIG_9P_FSCACHE static void v9fs_write_to_cache_done(void *priv, ssize_t transferred_or_error, bool was_async) @@ -324,8 +295,8 @@ const struct address_space_operations v9fs_addr_operations = { .writepage = v9fs_vfs_writepage, .write_begin = v9fs_write_begin, .write_end = v9fs_write_end, - .release_folio = v9fs_release_folio, - .invalidate_folio = v9fs_invalidate_folio, + .release_folio = netfs_release_folio, + .invalidate_folio = netfs_invalidate_folio, .launder_folio = v9fs_launder_folio, .direct_IO = v9fs_direct_IO, }; diff --git a/fs/afs/file.c b/fs/afs/file.c index 5e2bca3b02fd..c5013ec3c1dc 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -20,9 +20,6 @@ static int afs_file_mmap(struct file *file, struct vm_area_struct *vma); static int afs_symlink_read_folio(struct file *file, struct folio *folio); -static void afs_invalidate_folio(struct folio *folio, size_t offset, - size_t length); -static bool afs_release_folio(struct folio *folio, gfp_t gfp_flags); static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter); static ssize_t afs_file_splice_read(struct file *in, loff_t *ppos, @@ -57,8 +54,8 @@ const struct address_space_operations afs_file_aops = { .readahead = netfs_readahead, .dirty_folio = netfs_dirty_folio, .launder_folio = afs_launder_folio, - .release_folio = afs_release_folio, - .invalidate_folio = afs_invalidate_folio, + .release_folio = netfs_release_folio, + .invalidate_folio = netfs_invalidate_folio, .write_begin = afs_write_begin, .write_end = afs_write_end, .writepages = afs_writepages, @@ -67,8 +64,8 @@ const struct address_space_operations afs_file_aops = { const struct address_space_operations afs_symlink_aops = { .read_folio = afs_symlink_read_folio, - .release_folio = afs_release_folio, - .invalidate_folio = afs_invalidate_folio, + .release_folio = netfs_release_folio, + .invalidate_folio = netfs_invalidate_folio, .migrate_folio = filemap_migrate_folio, }; @@ -383,48 +380,6 @@ const struct netfs_request_ops afs_req_ops = { .issue_read = afs_issue_read, }; -/* - * invalidate part or all of a page - * - release a page and clean up its private data if offset is 0 (indicating - * the entire page) - */ -static void afs_invalidate_folio(struct folio *folio, size_t offset, - size_t length) -{ - _enter("{%lu},%zu,%zu", folio->index, offset, length); - - folio_wait_fscache(folio); - _leave(""); -} - -/* - * release a page and clean up its private state if it's not busy - * - return true if the page can now be released, false if not - */ -static bool afs_release_folio(struct folio *folio, gfp_t gfp) -{ - struct afs_vnode *vnode = AFS_FS_I(folio_inode(folio)); - - _enter("{{%llx:%llu}[%lu],%lx},%x", - vnode->fid.vid, vnode->fid.vnode, folio_index(folio), folio->flags, - gfp); - - /* deny if folio is being written to the cache and the caller hasn't - * elected to wait */ -#ifdef CONFIG_AFS_FSCACHE - if (folio_test_fscache(folio)) { - if (current_is_kswapd() || !(gfp & __GFP_FS)) - return false; - folio_wait_fscache(folio); - } - fscache_note_page_release(afs_vnode_cache(vnode)); -#endif - - /* Indicate that the folio can be released */ - _leave(" = T"); - return true; -} - static void afs_add_open_mmap(struct afs_vnode *vnode) { if (atomic_inc_return(&vnode->cb_nr_mmap) == 1) { diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 654f408a0aca..500a87b68a9a 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -159,27 +159,7 @@ static void ceph_invalidate_folio(struct folio *folio, size_t offset, ceph_put_snap_context(snapc); } - folio_wait_fscache(folio); -} - -static bool ceph_release_folio(struct folio *folio, gfp_t gfp) -{ - struct inode *inode = folio->mapping->host; - struct ceph_client *cl = ceph_inode_to_client(inode); - - doutc(cl, "%llx.%llx idx %lu (%sdirty)\n", ceph_vinop(inode), - folio->index, folio_test_dirty(folio) ? "" : "not "); - - if (folio_test_private(folio)) - return false; - - if (folio_test_fscache(folio)) { - if (current_is_kswapd() || !(gfp & __GFP_FS)) - return false; - folio_wait_fscache(folio); - } - ceph_fscache_note_page_release(inode); - return true; + netfs_invalidate_folio(folio, offset, length); } static void ceph_netfs_expand_readahead(struct netfs_io_request *rreq) @@ -1585,7 +1565,7 @@ const struct address_space_operations ceph_aops = { .write_end = ceph_write_end, .dirty_folio = ceph_dirty_folio, .invalidate_folio = ceph_invalidate_folio, - .release_folio = ceph_release_folio, + .release_folio = netfs_release_folio, .direct_IO = noop_direct_IO, }; diff --git a/fs/netfs/misc.c b/fs/netfs/misc.c index 68baf55c47a4..d946d85764de 100644 --- a/fs/netfs/misc.c +++ b/fs/netfs/misc.c @@ -84,3 +84,45 @@ void netfs_clear_inode_writeback(struct inode *inode, const void *aux) } } EXPORT_SYMBOL(netfs_clear_inode_writeback); + +/* + * netfs_invalidate_folio - Invalidate or partially invalidate a folio + * @folio: Folio proposed for release + * @offset: Offset of the invalidated region + * @length: Length of the invalidated region + * + * Invalidate part or all of a folio for a network filesystem. The folio will + * be removed afterwards if the invalidated region covers the entire folio. + */ +void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length) +{ + _enter("{%lx},%zx,%zx", folio_index(folio), offset, length); + + folio_wait_fscache(folio); +} +EXPORT_SYMBOL(netfs_invalidate_folio); + +/** + * netfs_release_folio - Try to release a folio + * @folio: Folio proposed for release + * @gfp: Flags qualifying the release + * + * Request release of a folio and clean up its private state if it's not busy. + * Returns true if the folio can now be released, false if not + */ +bool netfs_release_folio(struct folio *folio, gfp_t gfp) +{ + struct netfs_inode *ctx = netfs_inode(folio_inode(folio)); + + if (folio_test_private(folio)) + return false; + if (folio_test_fscache(folio)) { + if (current_is_kswapd() || !(gfp & __GFP_FS)) + return false; + folio_wait_fscache(folio); + } + + fscache_note_page_release(netfs_i_cookie(ctx)); + return true; +} +EXPORT_SYMBOL(netfs_release_folio); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 06f57d9d09f6..8efbfd3b2820 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -293,11 +293,13 @@ struct readahead_control; void netfs_readahead(struct readahead_control *); int netfs_read_folio(struct file *, struct folio *); int netfs_write_begin(struct netfs_inode *, struct file *, - struct address_space *, loff_t pos, unsigned int len, - struct folio **, void **fsdata); + struct address_space *, loff_t pos, unsigned int len, + struct folio **, void **fsdata); bool netfs_dirty_folio(struct address_space *mapping, struct folio *folio); int netfs_unpin_writeback(struct inode *inode, struct writeback_control *wbc); void netfs_clear_inode_writeback(struct inode *inode, const void *aux); +void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length); +bool netfs_release_folio(struct folio *folio, gfp_t gfp); void netfs_subreq_terminated(struct netfs_io_subrequest *, ssize_t, bool); void netfs_get_subrequest(struct netfs_io_subrequest *subreq, From patchwork Wed Dec 13 15:23:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491217 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7319BC4332F for ; Wed, 13 Dec 2023 15:24:53 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 09DD58D0024; Wed, 13 Dec 2023 10:24:53 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 04CDE8D0015; Wed, 13 Dec 2023 10:24:52 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id E30068D0024; Wed, 13 Dec 2023 10:24:52 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id D087D8D0015 for ; Wed, 13 Dec 2023 10:24:52 -0500 (EST) Received: from smtpin15.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 980AA1C11F1 for ; Wed, 13 Dec 2023 15:24:52 +0000 (UTC) X-FDA: 81562167624.15.60745AD Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf23.hostedemail.com (Postfix) with ESMTP id C5801140006 for ; Wed, 13 Dec 2023 15:24:50 +0000 (UTC) Authentication-Results: imf23.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=SDoNxHjo; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf23.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481090; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=hI7SPLixeI9nlQ4BAck1nNakLW38S3QG1L7ZzowPna4=; b=2SmTuFSqMK3wo8hALhJDCg+pqPYUpxwIMYK9FW9vFLvglaKZ5xJbbBKnDtTqM2y9YLDJh4 PdGrk7mcen7oMzKERscfeY1AcjBEbMpNvH4r9l562FNNlFJnbDlYihyY0C4ni2CBSAsOK5 9mjBDfJhGnf+Ag+TE1z9uaVkW8tEt/g= ARC-Authentication-Results: i=1; imf23.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=SDoNxHjo; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf23.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481090; a=rsa-sha256; cv=none; b=MH2+SXN5sCRifELyqvIPSnJ1KYQTzEZeV2rYucnDVPaflW5yIuuyR6EeFqbXG830NSRtHx c/DTRbMRZZE53d1ffy447aHVDBtJXuxuMZ2p6f376PaFv/m0iQjefO56TXbKDo3GQmJrj6 xWEb+Zzb4hO2HE5Q9Af91lo5KEpacxM= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481090; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hI7SPLixeI9nlQ4BAck1nNakLW38S3QG1L7ZzowPna4=; b=SDoNxHjoTT0uDpVMCUofavuw/8Y3ouKfTpFWLsto7RlrKiYrC1rrlMX0GlXyDW/8w4Rolr D9Wga1AA9rmDzUFT4H7Yzh2Wiq9WrDp/0TIccvtQZ2OtgVEWGdm5DJIA9pD0k9+YP4Kz/E +z82CO6HJjrnUtSKdp9Q5EKRWZivfv8= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-589-Iu8FZkuoNLiT9tX-_Vy2-g-1; Wed, 13 Dec 2023 10:24:45 -0500 X-MC-Unique: Iu8FZkuoNLiT9tX-_Vy2-g-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 51291881B70; Wed, 13 Dec 2023 15:24:43 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 42D562166B31; Wed, 13 Dec 2023 15:24:40 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 11/39] netfs: Implement unbuffered/DIO vs buffered I/O locking Date: Wed, 13 Dec 2023 15:23:21 +0000 Message-ID: <20231213152350.431591-12-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.6 X-Rspamd-Queue-Id: C5801140006 X-Rspam-User: X-Rspamd-Server: rspam05 X-Stat-Signature: 5naramcbebr36yd3c6hjzk4wwt1ou1ab X-HE-Tag: 1702481090-977439 X-HE-Meta: U2FsdGVkX19U4ARXvamXpbsV4eg08FiHEUgwScb8NP0Oqxl5r9mGsKCGjxtGBl3fTa7uJljc0NsQP9WWW++QB+XPYA8LnT0AQhImJFpRpY5yp/Df11eYSsL0u49s8YNwDFQjWhlNu1ILArZjnJ5m0aHx6UJi9QXJPmr7FLTvYOLAaoPjG1ay5pKFdDKhDrW01Rs7/XujrwuV2fhvC93Mw0y15iv5TXVyVd9hiu00B+q00jFEVjjuNYTbAID1hdaHRVxpHLcdRCsuIQ2hp93KhKMeWmo84j5VmrqSkMQ7ZiNTJEmMS/NjVYLm8j535mLDICzu84hJxM/qkelzRV1pc3ob8xHC33oTdJlXNgDchGR/963IOVSYxOn3T8Uz6yeQ/bEOJfdHGCFoBaUmfRUNWoHdOS8dMeZuUjHF/WpBCjE0tvZuxQru4E2U9HYRSt0Sua04StBlOsdLC0JRZb4OnBmHaJ/EPQYv6ZW0HjRp06PaoEdpspOOoCLtt2andSZ2ryeWf4oe3Pyn0PcRSinvwlF9kwo5BSXM+1bQyJXWxfS7tjpN8neo8ahn+IRLB9Mk3UyiSXl03lcg1tkSFUgFDNcF/lOz4KKZnjGixBZ1Ulrrlu5b8UY20vSsdKfBLhyvKhshHDGIIgk5N6oIj4VymTUYHTPs5ZjfCoV2nLDzx9LiP+h/v8at7nWoEf2pgZoTkvtqJoTLtWYzVeWIH0bHl0ZPt7NIVNdS5HD4azL+w1PdBii3Mi0Juhpxa9JgVy65wVE/hOfWHEWbaiAnqqoNA/6IooggzglhdmtdrBRRYxY/oKuaWcR1rgDmlGxIUP8gLSy30Osp+mi1bve07BzyQRD03A8kZRTLnEaRNeW8lEpTvpXxRPqpoXB6hsQT2dopU5Dm1myW6c6BA20MDjB3FmbuGEsG7XV2bR7ngYciIGopJo95/DQYpWmrOko+fc+OblJWr6OrI2fnZ54+l5b y+g/WBfp gMXfJM0CVdsNfv742Nvvp6PnknZ4qTqsm+TX2n6g7gow4Dm5G3T/dzZxcDZjQY8IaiLfG5IoTxfbsmbUGPPk5PTATv+z9EN83TK3SHvhVfDkXCN8PFPVpNA5Ic3M17ogtx1gdZ2IbFVh0pQ6rOJGY4J97L77fZyST0S293i1lfXUV0xlNKQu3gPdAYTh42i4XZ640zXNnqGcNqMDKvTo2GR8tI/bCtBYpomiEt8FA1fT+vjc6JRROyHiDjf9KuLFjouPFDrYQmWh022jsm2nCtTtEm0qzlhkFW9fgJ9SlCP+o5mU= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Borrow NFS's direct-vs-buffered I/O locking into netfslib. Similar code is also used in ceph. Modify it to have the correct checker annotations for i_rwsem lock acquisition/release and to return -ERESTARTSYS if waits are interrupted. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/Makefile | 1 + fs/netfs/locking.c | 215 ++++++++++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 10 ++ 3 files changed, 226 insertions(+) create mode 100644 fs/netfs/locking.c diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index a84fe9bbd3c4..cf3fc847b8ac 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -4,6 +4,7 @@ netfs-y := \ buffered_read.o \ io.o \ iterator.o \ + locking.o \ main.o \ misc.o \ objects.o diff --git a/fs/netfs/locking.c b/fs/netfs/locking.c new file mode 100644 index 000000000000..58e0f48394c5 --- /dev/null +++ b/fs/netfs/locking.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * I/O and data path helper functionality. + * + * Borrowed from NFS Copyright (c) 2016 Trond Myklebust + */ + +#include +#include + +/* + * inode_dio_wait_interruptible - wait for outstanding DIO requests to finish + * @inode: inode to wait for + * + * Waits for all pending direct I/O requests to finish so that we can + * proceed with a truncate or equivalent operation. + * + * Must be called under a lock that serializes taking new references + * to i_dio_count, usually by inode->i_mutex. + */ +static int inode_dio_wait_interruptible(struct inode *inode) +{ + if (!atomic_read(&inode->i_dio_count)) + return 0; + + wait_queue_head_t *wq = bit_waitqueue(&inode->i_state, __I_DIO_WAKEUP); + DEFINE_WAIT_BIT(q, &inode->i_state, __I_DIO_WAKEUP); + + for (;;) { + prepare_to_wait(wq, &q.wq_entry, TASK_INTERRUPTIBLE); + if (!atomic_read(&inode->i_dio_count)) + break; + if (signal_pending(current)) + break; + schedule(); + } + finish_wait(wq, &q.wq_entry); + + return atomic_read(&inode->i_dio_count) ? -ERESTARTSYS : 0; +} + +/* Call with exclusively locked inode->i_rwsem */ +static int netfs_block_o_direct(struct netfs_inode *ictx) +{ + if (!test_bit(NETFS_ICTX_ODIRECT, &ictx->flags)) + return 0; + clear_bit(NETFS_ICTX_ODIRECT, &ictx->flags); + return inode_dio_wait_interruptible(&ictx->inode); +} + +/** + * netfs_start_io_read - declare the file is being used for buffered reads + * @inode: file inode + * + * Declare that a buffered read operation is about to start, and ensure + * that we block all direct I/O. + * On exit, the function ensures that the NETFS_ICTX_ODIRECT flag is unset, + * and holds a shared lock on inode->i_rwsem to ensure that the flag + * cannot be changed. + * In practice, this means that buffered read operations are allowed to + * execute in parallel, thanks to the shared lock, whereas direct I/O + * operations need to wait to grab an exclusive lock in order to set + * NETFS_ICTX_ODIRECT. + * Note that buffered writes and truncates both take a write lock on + * inode->i_rwsem, meaning that those are serialised w.r.t. the reads. + */ +int netfs_start_io_read(struct inode *inode) + __acquires(inode->i_rwsem) +{ + struct netfs_inode *ictx = netfs_inode(inode); + + /* Be an optimist! */ + if (down_read_interruptible(&inode->i_rwsem) < 0) + return -ERESTARTSYS; + if (test_bit(NETFS_ICTX_ODIRECT, &ictx->flags) == 0) + return 0; + up_read(&inode->i_rwsem); + + /* Slow path.... */ + if (down_write_killable(&inode->i_rwsem) < 0) + return -ERESTARTSYS; + if (netfs_block_o_direct(ictx) < 0) { + up_write(&inode->i_rwsem); + return -ERESTARTSYS; + } + downgrade_write(&inode->i_rwsem); + return 0; +} +EXPORT_SYMBOL(netfs_start_io_read); + +/** + * netfs_end_io_read - declare that the buffered read operation is done + * @inode: file inode + * + * Declare that a buffered read operation is done, and release the shared + * lock on inode->i_rwsem. + */ +void netfs_end_io_read(struct inode *inode) + __releases(inode->i_rwsem) +{ + up_read(&inode->i_rwsem); +} +EXPORT_SYMBOL(netfs_end_io_read); + +/** + * netfs_start_io_write - declare the file is being used for buffered writes + * @inode: file inode + * + * Declare that a buffered read operation is about to start, and ensure + * that we block all direct I/O. + */ +int netfs_start_io_write(struct inode *inode) + __acquires(inode->i_rwsem) +{ + struct netfs_inode *ictx = netfs_inode(inode); + + if (down_write_killable(&inode->i_rwsem) < 0) + return -ERESTARTSYS; + if (netfs_block_o_direct(ictx) < 0) { + up_write(&inode->i_rwsem); + return -ERESTARTSYS; + } + return 0; +} +EXPORT_SYMBOL(netfs_start_io_write); + +/** + * netfs_end_io_write - declare that the buffered write operation is done + * @inode: file inode + * + * Declare that a buffered write operation is done, and release the + * lock on inode->i_rwsem. + */ +void netfs_end_io_write(struct inode *inode) + __releases(inode->i_rwsem) +{ + up_write(&inode->i_rwsem); +} +EXPORT_SYMBOL(netfs_end_io_write); + +/* Call with exclusively locked inode->i_rwsem */ +static int netfs_block_buffered(struct inode *inode) +{ + struct netfs_inode *ictx = netfs_inode(inode); + int ret; + + if (!test_bit(NETFS_ICTX_ODIRECT, &ictx->flags)) { + set_bit(NETFS_ICTX_ODIRECT, &ictx->flags); + if (inode->i_mapping->nrpages != 0) { + unmap_mapping_range(inode->i_mapping, 0, 0, 0); + ret = filemap_fdatawait(inode->i_mapping); + if (ret < 0) { + clear_bit(NETFS_ICTX_ODIRECT, &ictx->flags); + return ret; + } + } + } + return 0; +} + +/** + * netfs_start_io_direct - declare the file is being used for direct i/o + * @inode: file inode + * + * Declare that a direct I/O operation is about to start, and ensure + * that we block all buffered I/O. + * On exit, the function ensures that the NETFS_ICTX_ODIRECT flag is set, + * and holds a shared lock on inode->i_rwsem to ensure that the flag + * cannot be changed. + * In practice, this means that direct I/O operations are allowed to + * execute in parallel, thanks to the shared lock, whereas buffered I/O + * operations need to wait to grab an exclusive lock in order to clear + * NETFS_ICTX_ODIRECT. + * Note that buffered writes and truncates both take a write lock on + * inode->i_rwsem, meaning that those are serialised w.r.t. O_DIRECT. + */ +int netfs_start_io_direct(struct inode *inode) + __acquires(inode->i_rwsem) +{ + struct netfs_inode *ictx = netfs_inode(inode); + int ret; + + /* Be an optimist! */ + if (down_read_interruptible(&inode->i_rwsem) < 0) + return -ERESTARTSYS; + if (test_bit(NETFS_ICTX_ODIRECT, &ictx->flags) != 0) + return 0; + up_read(&inode->i_rwsem); + + /* Slow path.... */ + if (down_write_killable(&inode->i_rwsem) < 0) + return -ERESTARTSYS; + ret = netfs_block_buffered(inode); + if (ret < 0) { + up_write(&inode->i_rwsem); + return ret; + } + downgrade_write(&inode->i_rwsem); + return 0; +} +EXPORT_SYMBOL(netfs_start_io_direct); + +/** + * netfs_end_io_direct - declare that the direct i/o operation is done + * @inode: file inode + * + * Declare that a direct I/O operation is done, and release the shared + * lock on inode->i_rwsem. + */ +void netfs_end_io_direct(struct inode *inode) + __releases(inode->i_rwsem) +{ + up_read(&inode->i_rwsem); +} +EXPORT_SYMBOL(netfs_end_io_direct); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 8efbfd3b2820..fc6d9756a029 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -129,6 +129,8 @@ struct netfs_inode { struct fscache_cookie *cache; #endif loff_t remote_i_size; /* Size of the remote file */ + unsigned long flags; +#define NETFS_ICTX_ODIRECT 0 /* The file has DIO in progress */ }; /* @@ -310,6 +312,13 @@ ssize_t netfs_extract_user_iter(struct iov_iter *orig, size_t orig_len, struct iov_iter *new, iov_iter_extraction_t extraction_flags); +int netfs_start_io_read(struct inode *inode); +void netfs_end_io_read(struct inode *inode); +int netfs_start_io_write(struct inode *inode); +void netfs_end_io_write(struct inode *inode); +int netfs_start_io_direct(struct inode *inode); +void netfs_end_io_direct(struct inode *inode); + /** * netfs_inode - Get the netfs inode context from the inode * @inode: The inode to query @@ -335,6 +344,7 @@ static inline void netfs_inode_init(struct netfs_inode *ctx, { ctx->ops = ops; ctx->remote_i_size = i_size_read(&ctx->inode); + ctx->flags = 0; #if IS_ENABLED(CONFIG_FSCACHE) ctx->cache = NULL; #endif From patchwork Wed Dec 13 15:23:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491218 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 914D6C4332F for ; Wed, 13 Dec 2023 15:24:56 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id E32C68D0025; Wed, 13 Dec 2023 10:24:55 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id DE2028D0015; Wed, 13 Dec 2023 10:24:55 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id C35E08D0025; Wed, 13 Dec 2023 10:24:55 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id B249F8D0015 for ; Wed, 13 Dec 2023 10:24:55 -0500 (EST) Received: from smtpin17.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 7F12D801B5 for ; Wed, 13 Dec 2023 15:24:55 +0000 (UTC) X-FDA: 81562167750.17.B656332 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf10.hostedemail.com (Postfix) with ESMTP id B3A88C001B for ; Wed, 13 Dec 2023 15:24:53 +0000 (UTC) Authentication-Results: imf10.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=OYXycag3; spf=pass (imf10.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481093; a=rsa-sha256; cv=none; b=NFeu1zYuXbeIVyqWqsCniP3AZ3EH3MEhdfZz2Xq206zKcRMZkPteHh4f2mbShz5Q0boYi3 48F+pMOBmwPlibSeRZj44les32OVxzdMQzX9mXxJIlZMI/1kY6P8xFjo5C6paTJB7AeasL GUl0j277BGMbKiu7Qkcve23hRTegqU8= ARC-Authentication-Results: i=1; imf10.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=OYXycag3; spf=pass (imf10.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481093; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=YNj0M7wIH2KyJkCq66ZNM2ALuHL5lOHXJKpMpeEunrM=; b=YQsMSZxPAgFYueCgVh2gQ4NTvMpboOil8tBpFmLxy5WmOCRqeazXvYyJ4rC342Rkg4ZvbL LPhAWhNAxSWm28ph5v8QTTbZq4jAWLSeEmdLxfl7pZCjYhBReEyk10Ur4/fEHDSugBJeUT Cj3K0YVIyhM3frhZcIlFA2evi8cpzAk= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481093; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YNj0M7wIH2KyJkCq66ZNM2ALuHL5lOHXJKpMpeEunrM=; b=OYXycag3JKvh2eKnPERkkAHMAOy7XrDSTmWJuf1xSz725BvHLlvKsDD3Y0U3r/WgaOhjQb D7NgmpcjVb1PmGx8ucoTH35leqOFsFvM7z9wjdWNWPTX2Y8QOkWm5kyWtVrBsah/MSS7UO RGvFTGP8kJJ42Uus0DCOIxEpgRw5EWY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-675-9FNdQqbQO5ugbyzmDoD44A-1; Wed, 13 Dec 2023 10:24:48 -0500 X-MC-Unique: 9FNdQqbQO5ugbyzmDoD44A-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3E581863012; Wed, 13 Dec 2023 15:24:47 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 139493C2F; Wed, 13 Dec 2023 15:24:43 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 12/39] netfs: Add iov_iters to (sub)requests to describe various buffers Date: Wed, 13 Dec 2023 15:23:22 +0000 Message-ID: <20231213152350.431591-13-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Rspamd-Server: rspam08 X-Rspamd-Queue-Id: B3A88C001B X-Stat-Signature: ebipntj9edgzyt9fuxyrcomfj573b8zg X-Rspam-User: X-HE-Tag: 1702481093-390098 X-HE-Meta: U2FsdGVkX19dzg8H1YQ001bSr4+GgEsbfIUC+gonf2wP98AgePvI1tGfa1xcgs9Dev10LQNIJh7dUbGhSC3nd3aF7MS6Iitdq305DiP4V/1qPI0IzdeKpaWhmB/Re62VNZLC3RENOzW9hT2KCObr1NzLCwnyR9gHxg/FVfbGPb0toukmFH0XB2NcFF3MWBU6ea9i4UHP4AQknA3DXzSrbZu0FvUX50MkULWsNMtSzi4cm2preMFnTqM6qx8cExG2lbEYJOEixkKb+zwkOljF6p++juDLxACRGf9HPc+YM2BFLXrRQHkhwre4BkpWTW8kw60A+F44esxhTB63/Uf38ptBk3Evxg0EVGkCfs6yD3CmZM5hCZc6b6JFGleEi0LaHiKm0GX9a3Sogj/LhIG5tTem5O46ZT9EnNOgW5S3dBB0zx96EkkNYJsfrbOvoso4WJlrhn5YodF8vxpd45Yo+nkL8rbhg9Xv2OlSoZewv6lE26B75PfyR1tvSCIfIIPZqRoisTY1A4C47AqszmoGdYjKmSCcMPybdW0p2IcAXdecmy6fDeioCqk6Kd4aPJw03VdRpPGRbOSt3OGEN2/Wq9E9yqMFEVxZXM6W0oJ/96/h94xjUurdsLf1UBOt9jdI53Cgm77iB1W/61U/5lYeph3RAC8dbKMrvJrbIclqN5O+h9/PzFPs51cmEDDUO0fJj6C8LKHtN/VK2GbQJPRTR4uqde3KNtb1prTxqfoacgSCRhTfXsJMwqSQffMR+r3gS57MmVt/A/PsJikylnAifSpIPsqL4CrTHWZrYB6QfyKmKnv5/Re9DFtNsqEQxfiblOzhZT2+5i92EfEdcmukAKMIrkl0buoQIGrYFX+u1kh2iyyqeHfEM6tWrxd3iX9/oOqLL5A67XGFsebDeFY/PnZ0WnlFJaQVY+O9a5bGGGZHCcAHL6LT01FcnPNwIcNWebsojuVqpSzbB+lpva6 YB6UDA1o sFQ2MFTcscGdyoxgt3YHK56/oP3hbbl8nmZh19CQv7NkFLswNxf8qZejE34VMQP1dONmUV+8iCesoGJGOqqBjwHPvFXMksPs9sSL688YLDPfV5R2f0q5GZO0aZFbw8tZprlyiNB1xCdRDohUufAMWPqVPvPJ2waz+mNz8M4RCnu2W+TLgcahI8d51YNimkriJEl1FJU+7dPWoOpWzgqPUsN4jIvWx5e16ge0B/KCf+tz0bBelgnFMkNsNMvJOaC5SQHbia2udNqX/ycpiNksVyGUT+6Jr1+Bl0XpralYM/PXigQVUuB7tRC0Mb+9y35LicjAQAnoZmIOcbvfnNhcsqLYu1A== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Add three iov_iter structs: (1) Add an iov_iter (->iter) to the I/O request to describe the unencrypted-side buffer. (2) Add an iov_iter (->io_iter) to the I/O request to describe the encrypted-side I/O buffer. This may be a different size to the buffer in (1). (3) Add an iov_iter (->io_iter) to the I/O subrequest to describe the part of the I/O buffer for that subrequest. This will allow future patches to point to a bounce buffer instead for purposes of handling oversize writes, decryption (where we want to save the encrypted data to the cache) and decompression. These iov_iters persist for the lifetime of the (sub)request, and so can be accessed multiple times without worrying about them being deallocated upon return to the caller. The network filesystem must appropriately advance the iterator before terminating the request. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/afs/file.c | 6 +--- fs/netfs/buffered_read.c | 13 ++++++++ fs/netfs/io.c | 69 +++++++++++++++++++++++++++++----------- include/linux/netfs.h | 3 ++ 4 files changed, 67 insertions(+), 24 deletions(-) diff --git a/fs/afs/file.c b/fs/afs/file.c index c5013ec3c1dc..aa95b4d6376c 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -320,11 +320,7 @@ static void afs_issue_read(struct netfs_io_subrequest *subreq) fsreq->len = subreq->len - subreq->transferred; fsreq->key = key_get(subreq->rreq->netfs_priv); fsreq->vnode = vnode; - fsreq->iter = &fsreq->def_iter; - - iov_iter_xarray(&fsreq->def_iter, ITER_DEST, - &fsreq->vnode->netfs.inode.i_mapping->i_pages, - fsreq->pos, fsreq->len); + fsreq->iter = &subreq->io_iter; afs_fetch_data(fsreq->vnode, fsreq); afs_put_read(fsreq); diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index d39d0ffe75d2..751556faa70b 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -199,6 +199,10 @@ void netfs_readahead(struct readahead_control *ractl) netfs_rreq_expand(rreq, ractl); + /* Set up the output buffer */ + iov_iter_xarray(&rreq->iter, ITER_DEST, &ractl->mapping->i_pages, + rreq->start, 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(). */ @@ -251,6 +255,11 @@ int netfs_read_folio(struct file *file, struct folio *folio) netfs_stat(&netfs_n_rh_readpage); trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage); + + /* Set up the output buffer */ + iov_iter_xarray(&rreq->iter, ITER_DEST, &mapping->i_pages, + rreq->start, rreq->len); + return netfs_begin_read(rreq, true); discard: @@ -408,6 +417,10 @@ int netfs_write_begin(struct netfs_inode *ctx, ractl._nr_pages = folio_nr_pages(folio); netfs_rreq_expand(rreq, &ractl); + /* Set up the output buffer */ + iov_iter_xarray(&rreq->iter, ITER_DEST, &mapping->i_pages, + rreq->start, rreq->len); + /* We hold the folio locks, so we can drop the references */ folio_get(folio); while (readahead_folio(&ractl)) diff --git a/fs/netfs/io.c b/fs/netfs/io.c index 7f753380e047..e9d408e211b8 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -21,12 +21,7 @@ */ static void netfs_clear_unread(struct netfs_io_subrequest *subreq) { - struct iov_iter iter; - - iov_iter_xarray(&iter, ITER_DEST, &subreq->rreq->mapping->i_pages, - subreq->start + subreq->transferred, - subreq->len - subreq->transferred); - iov_iter_zero(iov_iter_count(&iter), &iter); + iov_iter_zero(iov_iter_count(&subreq->io_iter), &subreq->io_iter); } static void netfs_cache_read_terminated(void *priv, ssize_t transferred_or_error, @@ -46,14 +41,9 @@ static void netfs_read_from_cache(struct netfs_io_request *rreq, enum netfs_read_from_hole read_hole) { struct netfs_cache_resources *cres = &rreq->cache_resources; - struct iov_iter iter; netfs_stat(&netfs_n_rh_read); - iov_iter_xarray(&iter, ITER_DEST, &rreq->mapping->i_pages, - subreq->start + subreq->transferred, - subreq->len - subreq->transferred); - - cres->ops->read(cres, subreq->start, &iter, read_hole, + cres->ops->read(cres, subreq->start, &subreq->io_iter, read_hole, netfs_cache_read_terminated, subreq); } @@ -88,6 +78,11 @@ static void netfs_read_from_server(struct netfs_io_request *rreq, struct netfs_io_subrequest *subreq) { netfs_stat(&netfs_n_rh_download); + if (iov_iter_count(&subreq->io_iter) != subreq->len - subreq->transferred) + pr_warn("R=%08x[%u] ITER PRE-MISMATCH %zx != %zx-%zx %lx\n", + rreq->debug_id, subreq->debug_index, + iov_iter_count(&subreq->io_iter), subreq->len, + subreq->transferred, subreq->flags); rreq->netfs_ops->issue_read(subreq); } @@ -259,6 +254,30 @@ static void netfs_rreq_short_read(struct netfs_io_request *rreq, netfs_read_from_server(rreq, subreq); } +/* + * Reset the subrequest iterator prior to resubmission. + */ +static void netfs_reset_subreq_iter(struct netfs_io_request *rreq, + struct netfs_io_subrequest *subreq) +{ + size_t remaining = subreq->len - subreq->transferred; + size_t count = iov_iter_count(&subreq->io_iter); + + if (count == remaining) + return; + + _debug("R=%08x[%u] ITER RESUB-MISMATCH %zx != %zx-%zx-%llx %x\n", + rreq->debug_id, subreq->debug_index, + iov_iter_count(&subreq->io_iter), subreq->transferred, + subreq->len, rreq->i_size, + subreq->io_iter.iter_type); + + if (count < remaining) + iov_iter_revert(&subreq->io_iter, remaining - count); + else + iov_iter_advance(&subreq->io_iter, count - remaining); +} + /* * Resubmit any short or failed operations. Returns true if we got the rreq * ref back. @@ -287,6 +306,7 @@ static bool netfs_rreq_perform_resubmissions(struct netfs_io_request *rreq) trace_netfs_sreq(subreq, netfs_sreq_trace_download_instead); netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); atomic_inc(&rreq->nr_outstanding); + netfs_reset_subreq_iter(rreq, subreq); netfs_read_from_server(rreq, subreq); } else if (test_bit(NETFS_SREQ_SHORT_IO, &subreq->flags)) { netfs_rreq_short_read(rreq, subreq); @@ -399,9 +419,9 @@ void netfs_subreq_terminated(struct netfs_io_subrequest *subreq, struct netfs_io_request *rreq = subreq->rreq; int u; - _enter("[%u]{%llx,%lx},%zd", - subreq->debug_index, subreq->start, subreq->flags, - transferred_or_error); + _enter("R=%x[%x]{%llx,%lx},%zd", + rreq->debug_id, subreq->debug_index, + subreq->start, subreq->flags, transferred_or_error); switch (subreq->source) { case NETFS_READ_FROM_CACHE: @@ -501,7 +521,8 @@ static enum netfs_io_source netfs_cache_prepare_read(struct netfs_io_subrequest */ static enum netfs_io_source netfs_rreq_prepare_read(struct netfs_io_request *rreq, - struct netfs_io_subrequest *subreq) + struct netfs_io_subrequest *subreq, + struct iov_iter *io_iter) { enum netfs_io_source source; @@ -528,9 +549,14 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq, } } - if (WARN_ON(subreq->len == 0)) + if (WARN_ON(subreq->len == 0)) { source = NETFS_INVALID_READ; + goto out; + } + subreq->io_iter = *io_iter; + iov_iter_truncate(&subreq->io_iter, subreq->len); + iov_iter_advance(io_iter, subreq->len); out: subreq->source = source; trace_netfs_sreq(subreq, netfs_sreq_trace_prepare); @@ -541,6 +567,7 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq, * 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, + struct iov_iter *io_iter, unsigned int *_debug_index) { struct netfs_io_subrequest *subreq; @@ -565,7 +592,7 @@ static bool netfs_rreq_submit_slice(struct netfs_io_request *rreq, * (the starts must coincide), in which case, we go around the loop * again and ask it to download the next piece. */ - source = netfs_rreq_prepare_read(rreq, subreq); + source = netfs_rreq_prepare_read(rreq, subreq, io_iter); if (source == NETFS_INVALID_READ) goto subreq_failed; @@ -603,6 +630,7 @@ static bool netfs_rreq_submit_slice(struct netfs_io_request *rreq, */ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) { + struct iov_iter io_iter; unsigned int debug_index = 0; int ret; @@ -615,6 +643,8 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) return -EIO; } + rreq->io_iter = rreq->iter; + INIT_WORK(&rreq->work, netfs_rreq_work); if (sync) @@ -624,8 +654,9 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) * want and submit each one. */ atomic_set(&rreq->nr_outstanding, 1); + io_iter = rreq->io_iter; do { - if (!netfs_rreq_submit_slice(rreq, &debug_index)) + if (!netfs_rreq_submit_slice(rreq, &io_iter, &debug_index)) break; } while (rreq->submitted < rreq->len); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index fc6d9756a029..3da962e977f5 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -150,6 +150,7 @@ struct netfs_cache_resources { struct netfs_io_subrequest { struct netfs_io_request *rreq; /* Supervising I/O request */ struct list_head rreq_link; /* Link in rreq->subrequests */ + struct iov_iter io_iter; /* Iterator for this 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 */ @@ -186,6 +187,8 @@ struct netfs_io_request { struct netfs_cache_resources cache_resources; struct list_head proc_link; /* Link in netfs_iorequests */ struct list_head subrequests; /* Contributory I/O operations */ + struct iov_iter iter; /* Unencrypted-side iterator */ + struct iov_iter io_iter; /* I/O (Encrypted-side) iterator */ void *netfs_priv; /* Private data for the netfs */ unsigned int debug_id; atomic_t nr_outstanding; /* Number of ops in progress */ From patchwork Wed Dec 13 15:23:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491219 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id CA3E6C4332F for ; Wed, 13 Dec 2023 15:24:59 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 5811D8D0026; Wed, 13 Dec 2023 10:24:59 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 509798D0015; Wed, 13 Dec 2023 10:24:59 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 3A89E8D0026; Wed, 13 Dec 2023 10:24:59 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 256CC8D0015 for ; Wed, 13 Dec 2023 10:24:59 -0500 (EST) Received: from smtpin12.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 02CD51A01B7 for ; Wed, 13 Dec 2023 15:24:59 +0000 (UTC) X-FDA: 81562167918.12.7826109 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf21.hostedemail.com (Postfix) with ESMTP id 5A7BC1C0009 for ; Wed, 13 Dec 2023 15:24:57 +0000 (UTC) Authentication-Results: imf21.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=RingbvM1; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf21.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481097; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=R2/A7TiJV6TZ1k1DToK4IbKjyWB1JSrvz3z2/pRYZzc=; b=uHE/l7BSslo196l0zMXZ37jDT0DW7zvZWZQrp/W8/zdl2UeXHiDQj4rJ0f9l1pzn06IQc7 F/MxSwHwWAnS3h4kbPLl0qp8czjQajD9Gi9s/OWnFieUITSPkQIOoigcDkreFBxe8QNXmA Y4d5r0LKFm62OnekDZjH/OFIdmjSKdo= ARC-Authentication-Results: i=1; imf21.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=RingbvM1; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf21.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481097; a=rsa-sha256; cv=none; b=SohVyflhIzjRYkIlgYllLamwTTp/9bQHBAdxKMv3n7ocASAQaGRjT0aqHHs/ceeqajZSXO YuK4M6zb2iFuPgyqGTFUnrjjfKjKjZVJdLbuqzyncPRARDXWR9YUkW6kSUV9zMm+1YDh+H kQRXlohNrOsc1uMBWGPEvgzhIehW+Xg= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481096; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=R2/A7TiJV6TZ1k1DToK4IbKjyWB1JSrvz3z2/pRYZzc=; b=RingbvM10SHG1iXU4+zWHzqhPBqayExhHRB7bfB8Gw55HorRXBT1++IezpHqupq782G+0d G50kChosBJAXWOTFo29OYhV21k/WSWagSdWxQOq2IiGIP/lmqGpa4hifpOhUHedHv9784h y6aqj1gQr/cnbL3g32Mqzc5f4b0+2pE= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-490-LMlGDmguMLmZbn_a6WmlQQ-1; Wed, 13 Dec 2023 10:24:52 -0500 X-MC-Unique: LMlGDmguMLmZbn_a6WmlQQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 0B4CF863010; Wed, 13 Dec 2023 15:24:51 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 035311121306; Wed, 13 Dec 2023 15:24:47 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 13/39] netfs: Add support for DIO buffering Date: Wed, 13 Dec 2023 15:23:23 +0000 Message-ID: <20231213152350.431591-14-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.3 X-Rspamd-Server: rspam09 X-Rspamd-Queue-Id: 5A7BC1C0009 X-Stat-Signature: 3xk6ckgjg5e7f8eur193dxb9pmyp4hzb X-Rspam-User: X-HE-Tag: 1702481097-960492 X-HE-Meta: U2FsdGVkX19P+/ffUxdSHyuZGTtSkL6zSUkK4ki4SS653CPbJGnX/hrgq09szJSerWq6OscaPKcXICbwuqAKYeE7ndvWM3BToQ48Whes3Qg5JB2mSkXu2BsqbuOFH8HD29cLh/6ue0cV4xHHO2ujfv2Ro3/ajVpT35SpQn5h2nGLU3MMV6Lps/Wd7endDdVuIIXdjo4JHRDrhAIzk/9+bHcL71aYcbTgEdOoBte1RijyTUpSeNINpPn6koqhfSraqI46/EeJXHOEXDWSPJDm8jfeFmwgUlswAi4OezJhilj3YLz8wyFrLIRut3OBtwCW47GzMPlqGRJtbg8xLhfZKERiIVa3sPdqwv7AmyhUUFeHuvwAp5aBgGJTFR3baFu7/LkasblZRvj14A9j/bI/AgnU5f0ooH6jM3hLlrk/EYls3G084YrLj4vZnEiieESSImhRqvFVoEkEnEzUlDCC81d8GBH3V2f32yfTZkXAHENXPTivKuMwnpTHvMOmoD7ckS5GvWaRMJuAjZkte4TWG+mp+R5+KYTdsWwQSzsryUpw/jX7L7Kk29w1rtsfLRK0P6COAiXOt3yPb7uMbnW033PVvuKDIW9Q5pOAuGSGFPTfeG6U3S81ku2vrjoXuiG/K8hXP2t2ZqUSOb8WGql8MwXmGWpJc7kyG00kEhH+HI7JdttTqG62u5kcdXVG7aa/ddihSMux5+24sircNb/EE09sv0vlvyury74iKvhJXVJQzYE//oBBrunlM2Fjpg2FdxZiy4fz8RuqfDXRfO0tZaVQ8jY7YRnJs7XQOOcMHzm6nXr23pah4/hb24sDzWdGsHDG4AaBMq/nKBb5mf2FqshZH3kWlNxwzw0Bm2m/CSeQB82AQHjZKWUZVF31NIrBXH/JJxdnJjdvgGUrMoHr9vg9nS5FrefOH+0MyeOX2TuO574FQPnm+lkSvWB3GkLrsiJXybj1GESdlYY6UAn H+Dm1ERv QmUisOaBkSvI27M/zLpg3X/uRSECdIp3p3wTwbkJWlzz9GvjS8xi8qcAMzYczgoLfmxfxQtWqYbU4Mau/lB/5n4DCGctBe+1sm/EpP6OJdfCuCoFjehG6ZFhmkDldm69SozzwJVjM7ES4+9asXgohjW41ffVUR8mGpDSSWfi9zgMH4IHU03LzSMn52mBqFSgkuxrd/clU82mgh/Czu00pwX09MDOdATSCjgf4qTplEnrW9xIgKdiBABKi5uJDAd863MnzwGRH475Oxwd+ltjHhnVOiu1RyNKvEk54yR4ehPsdK6Q= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Add a bvec array pointer and an iterator to netfs_io_request for either holding a copy of a DIO iterator or a list of all the bits of buffer pointed to by a DIO iterator. There are two problems: Firstly, if an iovec-class iov_iter is passed to ->read_iter() or ->write_iter(), this cannot be passed directly to kernel_sendmsg() or kernel_recvmsg() as that may cause locking recursion if a fault is generated, so we need to keep track of the pages involved separately. Secondly, if the I/O is asynchronous, we must copy the iov_iter describing the buffer before returning to the caller as it may be immediately deallocated. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/objects.c | 10 ++++++++++ include/linux/netfs.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 1bd20bdad983..4df5e5eeada6 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -76,6 +76,7 @@ static void netfs_free_request(struct work_struct *work) { struct netfs_io_request *rreq = container_of(work, struct netfs_io_request, work); + unsigned int i; trace_netfs_rreq(rreq, netfs_rreq_trace_free); netfs_proc_del_rreq(rreq); @@ -84,6 +85,15 @@ static void netfs_free_request(struct work_struct *work) rreq->netfs_ops->free_request(rreq); if (rreq->cache_resources.ops) rreq->cache_resources.ops->end_operation(&rreq->cache_resources); + if (rreq->direct_bv) { + for (i = 0; i < rreq->direct_bv_count; i++) { + if (rreq->direct_bv[i].bv_page) { + if (rreq->direct_bv_unpin) + unpin_user_page(rreq->direct_bv[i].bv_page); + } + } + kvfree(rreq->direct_bv); + } kfree_rcu(rreq, rcu); netfs_stat_d(&netfs_n_rh_rreq); } diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 3da962e977f5..bbb33ccbf719 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -190,6 +190,9 @@ struct netfs_io_request { struct iov_iter iter; /* Unencrypted-side iterator */ struct iov_iter io_iter; /* I/O (Encrypted-side) iterator */ void *netfs_priv; /* Private data for the netfs */ + struct bio_vec *direct_bv /* DIO buffer list (when handling iovec-iter) */ + __counted_by(direct_bv_count); + unsigned int direct_bv_count; /* Number of elements in direct_bv[] */ unsigned int debug_id; atomic_t nr_outstanding; /* Number of ops in progress */ atomic_t nr_copy_ops; /* Number of copy-to-cache ops in progress */ @@ -197,6 +200,7 @@ struct netfs_io_request { size_t len; /* Length of the request */ short error; /* 0 or error that occurred */ enum netfs_io_origin origin; /* Origin of the request */ + bool direct_bv_unpin; /* T if direct_bv[] must be unpinned */ 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 */ From patchwork Wed Dec 13 15:23:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491220 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id A6A06C4167B for ; Wed, 13 Dec 2023 15:25:05 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 3FAA56B0400; Wed, 13 Dec 2023 10:25:05 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 3AADE6B0405; Wed, 13 Dec 2023 10:25:05 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 224286B0407; Wed, 13 Dec 2023 10:25:05 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 08EEE6B0400 for ; Wed, 13 Dec 2023 10:25:05 -0500 (EST) Received: from smtpin07.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id C439C40253 for ; Wed, 13 Dec 2023 15:25:04 +0000 (UTC) X-FDA: 81562168128.07.680DCFF Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf23.hostedemail.com (Postfix) with ESMTP id 18328140023 for ; Wed, 13 Dec 2023 15:25:02 +0000 (UTC) Authentication-Results: imf23.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=UvVXvz2q; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf23.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481103; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=PLa1FYhVvXUSTtOx9SWX7UrxEmhpA+746l5QW31q7Os=; b=M++JXr2aimuVNYlaMxeQy23xmHV80JV6CMklG2Z1oWQv161XtvJlC+UqaJfuz0V6/6Kaz2 qEAHk220FSLITkc7XIb1AjhLzf5lTwhZtrmwCETtCyI1rwj7gOFoffkxqCchF+0cS96WPI IWEGVeT0f1kAsYETIFmGfWcKdrWwyc0= ARC-Authentication-Results: i=1; imf23.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=UvVXvz2q; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf23.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481103; a=rsa-sha256; cv=none; b=J0Y5Sn8d4eW1yAP01kw8f6QAYVp4Iw6w932Mp72HXvs4crfWi0l1lIYdB86gLS1TOSaLbj p/+KBQTXqoZdzXFtrRDZ0ldNLz6TCH8WPSgUlPwLI0VDn/72O4k3FLN20KMaCEZ5NeGPNV Rv25Yr7PhaqxfHw/k89xgYtV1fzcBg8= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481102; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PLa1FYhVvXUSTtOx9SWX7UrxEmhpA+746l5QW31q7Os=; b=UvVXvz2qq0/3v3Asf5A5TQ6ejxTeo9DN+cR/8oOqXQVn8jyCQ2bLqgymLa7uu7e0uFKbRY 38FyAoTCSP6fEYFIp+APzYPttCH6Km8iyGnL43EiUwyOt1xBQ7rXUPGQ1azou312E7VQ7i C/x3QDWDEUePi4c1gucrsNPa0MPiX50= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-471-JqQgBQZUPnO1fkGTGEhnIw-1; Wed, 13 Dec 2023 10:24:56 -0500 X-MC-Unique: JqQgBQZUPnO1fkGTGEhnIw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 952AD280CFA0; Wed, 13 Dec 2023 15:24:54 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id BD2A340C6EBA; Wed, 13 Dec 2023 15:24:51 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 14/39] netfs: Provide tools to create a buffer in an xarray Date: Wed, 13 Dec 2023 15:23:24 +0000 Message-ID: <20231213152350.431591-15-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 18328140023 X-Stat-Signature: 848xmqq913o5dgp1br6n1im4cykiuouu X-HE-Tag: 1702481102-865120 X-HE-Meta: U2FsdGVkX19/NAySVqZ1DCJLLXNhFAtSM1G4/e9yIDwodOhdg6w82PvIjqY7qLYU7+8ocSOiRM/dYMVzOCs0edkN69/5gjmSCIdIty4f5vKHJnkGlMAylbYmso5oM+64V7HNB4fA7QoDO/ZCzcp0AK+5PviVvbYTGeY8/W0/AZcmruByzjBQvvemHK/G3FMoGTJxQnpT+MjKT/zmi7E5ZGJy6PB9dB8CjVWakKUJ6mqaGO+vA3OaLwV4xrU70z+K85uWjGQLGanQ76qYGU3h2AlDbaqxxWqvvQsrBMczDqcSZ7wspBYMzqCPgViW6gxdGZ67EP7Zki9C8PbjPi/YQbqPSpP3nGFj4pfRrGrbWqNeHFOxk46yV2AlbxUvx7q8/2UxPeRvQrG26j75HfbFai+mafy9J8v+a5Ufll+nyqeQxxZbQpuUgE/bqQqYK+ifgyzjQPUYreqjYZvxrt6R2PpRxomI1AfLqd+GQYu5dHwEYH0RQW9rQiFOyT8GhSm+8U4HjA2FAtC80uYkz2f78+YukrhIqcino/EEnCcAswI0bPU48adVsdPxdX/oHD8f8fa9Ht2xtx6e8vVxVAzD1igj2xAIAbHo9It/rBCjWu8GWloyeZ80XnDOjtbKHqljhGgP8g+hb1WyYT8WN36vhZMv3ETFqq9kiVLMc1CBEZyQ7WuXBPIJ+5MzIiQssgF0sCXpTGc4s3SFwx9W1Q+2a7uQBG/JyZb/NiiGoUWLgB9B2IJ1yz3icSJBwZPRGhYsuUapDq7+M/vEMs73/p1aoRj0RwFAZy1e2p4LQrlqNzPBj/Oxokc783bAdIO90iSt3uZYNg24UyAxC6buKHLwn9O6QfowlQqM7GJc6cQXz0jHUf2Sxfu0Bk2wJoGwVzMibpc1SVXQiuaMthLdwwGKrV+0Ewcfq8b+PxBmBoHSkQ73NqXQ/prlPepB05NWkEOAhAeLzOG3I1PSAhCwZyh 5FwkjrDB UXp6yYk8EUWmZfnc8QYpjn9YsgE5+4p2yqpTSbIuEsbGtUbSVrWUqjKug7297nEQiUEL/LOzJlLQXpzlxFv9owgVKUbdulbnsL2uStZRlADlXsQIcAw/gz1us9jnUMbhgGupyinKpRUFwRlrjakcwTDUZphccs61MAztae6By2C3Nh9PxJuk64xG/5QPD+186biBNNHiDC+Hd+Ni5W4rDPtro4WNX6fpgnOXhIgvOyW2Pxz70fwibdkEY8OfbpZdAss6YB6ZogShqy9LO06GoUteQ00cwJoibn/1btdeLYpXKdwatNnAOuHqB3xoXZoPKWpLB X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Provide tools to create a buffer in an xarray, with a function to add new folios with a mark. This will be used to create bounce buffer and can be used more easily to create a list of folios the span of which would require more than a page's worth of bio_vec structs. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/internal.h | 13 +++++++ fs/netfs/misc.c | 81 +++++++++++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 4 +++ 3 files changed, 98 insertions(+) diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 937d9a22f178..20eb1fd6986e 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -56,6 +56,19 @@ static inline void netfs_proc_add_rreq(struct netfs_io_request *rreq) {} static inline void netfs_proc_del_rreq(struct netfs_io_request *rreq) {} #endif +/* + * misc.c + */ +#define NETFS_FLAG_PUT_MARK BIT(0) +#define NETFS_FLAG_PAGECACHE_MARK BIT(1) +int netfs_xa_store_and_mark(struct xarray *xa, unsigned long index, + struct folio *folio, unsigned int flags, + gfp_t gfp_mask); +int netfs_add_folios_to_buffer(struct xarray *buffer, + struct address_space *mapping, + pgoff_t index, pgoff_t to, gfp_t gfp_mask); +void netfs_clear_buffer(struct xarray *buffer); + /* * objects.c */ diff --git a/fs/netfs/misc.c b/fs/netfs/misc.c index d946d85764de..96014c3d1683 100644 --- a/fs/netfs/misc.c +++ b/fs/netfs/misc.c @@ -8,6 +8,87 @@ #include #include "internal.h" +/* + * Attach a folio to the buffer and maybe set marks on it to say that we need + * to put the folio later and twiddle the pagecache flags. + */ +int netfs_xa_store_and_mark(struct xarray *xa, unsigned long index, + struct folio *folio, unsigned int flags, + gfp_t gfp_mask) +{ + XA_STATE_ORDER(xas, xa, index, folio_order(folio)); + +retry: + xas_lock(&xas); + for (;;) { + xas_store(&xas, folio); + if (!xas_error(&xas)) + break; + xas_unlock(&xas); + if (!xas_nomem(&xas, gfp_mask)) + return xas_error(&xas); + goto retry; + } + + if (flags & NETFS_FLAG_PUT_MARK) + xas_set_mark(&xas, NETFS_BUF_PUT_MARK); + if (flags & NETFS_FLAG_PAGECACHE_MARK) + xas_set_mark(&xas, NETFS_BUF_PAGECACHE_MARK); + xas_unlock(&xas); + return xas_error(&xas); +} + +/* + * Create the specified range of folios in the buffer attached to the read + * request. The folios are marked with NETFS_BUF_PUT_MARK so that we know that + * these need freeing later. + */ +int netfs_add_folios_to_buffer(struct xarray *buffer, + struct address_space *mapping, + pgoff_t index, pgoff_t to, gfp_t gfp_mask) +{ + struct folio *folio; + int ret; + + if (to + 1 == index) /* Page range is inclusive */ + return 0; + + do { + /* TODO: Figure out what order folio can be allocated here */ + folio = filemap_alloc_folio(readahead_gfp_mask(mapping), 0); + if (!folio) + return -ENOMEM; + folio->index = index; + ret = netfs_xa_store_and_mark(buffer, index, folio, + NETFS_FLAG_PUT_MARK, gfp_mask); + if (ret < 0) { + folio_put(folio); + return ret; + } + + index += folio_nr_pages(folio); + } while (index <= to && index != 0); + + return 0; +} + +/* + * Clear an xarray buffer, putting a ref on the folios that have + * NETFS_BUF_PUT_MARK set. + */ +void netfs_clear_buffer(struct xarray *buffer) +{ + struct folio *folio; + XA_STATE(xas, buffer, 0); + + rcu_read_lock(); + xas_for_each_marked(&xas, folio, ULONG_MAX, NETFS_BUF_PUT_MARK) { + folio_put(folio); + } + rcu_read_unlock(); + xa_destroy(buffer); +} + /** * netfs_dirty_folio - Mark folio dirty and pin a cache object for writeback * @mapping: The mapping the folio belongs to. diff --git a/include/linux/netfs.h b/include/linux/netfs.h index bbb33ccbf719..c05150f51beb 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -109,6 +109,10 @@ static inline int wait_on_page_fscache_killable(struct page *page) return folio_wait_private_2_killable(page_folio(page)); } +/* Marks used on xarray-based buffers */ +#define NETFS_BUF_PUT_MARK XA_MARK_0 /* - Page needs putting */ +#define NETFS_BUF_PAGECACHE_MARK XA_MARK_1 /* - Page needs wb/dirty flag wrangling */ + enum netfs_io_source { NETFS_FILL_WITH_ZEROES, NETFS_DOWNLOAD_FROM_SERVER, From patchwork Wed Dec 13 15:23:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491222 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 092C2C4332F for ; Wed, 13 Dec 2023 15:25:21 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id D23A78D0028; Wed, 13 Dec 2023 10:25:17 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id C87378D0015; Wed, 13 Dec 2023 10:25:17 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id A44CA8D0029; Wed, 13 Dec 2023 10:25:17 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 7CC978D0028 for ; Wed, 13 Dec 2023 10:25:17 -0500 (EST) Received: from smtpin24.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 262C11C1487 for ; Wed, 13 Dec 2023 15:25:17 +0000 (UTC) X-FDA: 81562168674.24.3CE599D Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf09.hostedemail.com (Postfix) with ESMTP id 4A91E140012 for ; Wed, 13 Dec 2023 15:25:15 +0000 (UTC) Authentication-Results: imf09.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=ajzImziC; spf=pass (imf09.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481115; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=TyeDCrkCzlrF45NKmRnzOuDvS9hPtHcwk1ZYplID5CE=; b=SY9egxGuWUInjonQFr2gjve+YCmIjKEN3KlF+LBUKPKZzfqCEXWP+QzuxzDvOsE5THwOTb TP62XtEus9vxbtvd9CZluO7p2BV5G1QHYHuB0hZqW/FKjJltb2HWAkUeOhdn0MUDPRLuuT rrsQvkVFLGMnNca0Mb2tk1+j/KleDgc= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481115; a=rsa-sha256; cv=none; b=XntGJPIafOZ5T35pZr6iEHwnghqJunx8GZU7jeB4I8ZkLDhnvXBKysApwhVI5naJ14yKF6 SKWDwMF+tOjxt87c0Rw8n7sHmOmEfCvmdLcbj67DNNyeHLiHYe7xHwg9gFL/ZRVMQGtmfC dJHq9XDu7I/gj1QHX1CMK0xh/+ykJqE= ARC-Authentication-Results: i=1; imf09.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=ajzImziC; spf=pass (imf09.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481114; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TyeDCrkCzlrF45NKmRnzOuDvS9hPtHcwk1ZYplID5CE=; b=ajzImziCdqdFmkBlqGlNXSAzRDbcPSyuGg6qn3Nkr3E7n4BAtSQ0WcTcP9bvRDhNdGJ2rF eNDzLEx4/Yf1JHIhWMV5nzAAxACHmbBX/iymeflTBqz+sXGjA61mg+RRrT0s7PfEoUYXNe Z8FafJ9oDVsAWek0xCORg7cHIAmQrJI= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-279-80XknK_sN16WwcytEyXF_A-1; Wed, 13 Dec 2023 10:25:11 -0500 X-MC-Unique: 80XknK_sN16WwcytEyXF_A-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 74836863018; Wed, 13 Dec 2023 15:24:58 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5FF89519D; Wed, 13 Dec 2023 15:24:55 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 15/39] netfs: Add bounce buffering support Date: Wed, 13 Dec 2023 15:23:25 +0000 Message-ID: <20231213152350.431591-16-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.5 X-Stat-Signature: x5pqdhs145zujs19fcdfcu4owozhm6mi X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: 4A91E140012 X-Rspam-User: X-HE-Tag: 1702481115-416834 X-HE-Meta: U2FsdGVkX1+Fk4O7QZCJjK9/Rbc13nEDnYeC1Iiwzg6N7pgL6YMIg5S4QFcYQpSUHR5byq/eaxmQycpH66oxYx5i4iC/xFZsfFwnSDOQrhxDypLlvL/6a6YLDO7hmrvxxioSrgFzItVbD9ojgwUwgdQr9r/+g91lh0gQM7vuYgDYdXt0+MFn8ovCsE59D9hq9QLnTFRq/xDKfNMJDnWzwNk3RtrOFlwaPzuP/VDDAqbnRzbsKRq7BOKHTslw7iOGyGjMWzVXWosyQ0uSXBfgTCsl/g78B8gLyT6w6ntg7k3PS6B/fzkkk7oA/QPbXIH8GbD+AEE7fRt0aW176OvCPYA++9psVs3Yylmn50VGHRVzemrP4n2CNfFa90OVcKpGNbAvUsOyDu2Q7wSm4c/9SYhut2tbVlufmHYBFrFvYkhXUFlsHYa81rswxn+s6slRu0gEZQpoR/2uWyOgNXvZhzXTz4lt6l8ZGZIDyNQhcdUx6WS7QqyVmvWbf0SJxw03WYbdSBjbwTGTqorPMxpgsIqgi+OHoPCHiNxgRCcS2GW4PjhtXf4bwF4MxQ9JLqx6lYIVjNDsGk3F1CnMwgpq3Qu+VmkJKcNJJjQdB2c3ru/b4qGAU+HLNbCo8mfgMgL0UtllBRnlD+f4athpUku99nDzdeGblGHEo+HvUVAf8fP8IaDNhaiIipeMmSAcb6NcQaIBk2FUxhzZdAfxgJGYmwQvq1KvXyf6rQ687Xh4RCdubNvlhQo2n9n5OHAdBZLn3R/VLgqFA+36HMrpSn5nfFR3pymxDUzQP8k9xeQKs9b/VP8zPQLeUpsGFe6zr41nc2jxDO3ycYJHKFwjRpiOZ6siK6WbopLwIVsnjlMvy2I7NRlwq8muyPjj8PgG+mHE09yI6wiJbwWA5ttipNDLuaM2oXqNuOewUXKkU+wUv63YsCYNIAeqO5ovrlgvzJB09mVsbg94dBTBKjlbaM+ 6mFmRYLo khJzZ0xo65unsMDgJ9qaUy0mKwEk2pPcAaFidNtiXBhI2vUq53PUS110XQXvISjdVUxFGZLfwMByy9Vbh2Ep3nEyc6EsrjVmzM/QcSoe2zst64JW/zvplEWimgCRtK7oBYF9mp3cwXKgKBpz280Cn8FM3FgQkrmso3AiTIpc1wRr++a7LdoTSV/sEK9NTKLjL9fphhri4TnY257umBvK3nWFsKOihBEJi7oEc45T6jXcV2QwuON/Lf/zHuvhKL7qPeliAUAm/T+NRV5MKuYx28Pd/YqvcTLyr6x39avbJMsQepG8= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Add a second xarray struct to netfs_io_request for the purposes of holding a bounce buffer for when we have to deal with encrypted/compressed data or if we have to up/download data in blocks larger than we were asked for. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/io.c | 6 +++++- fs/netfs/objects.c | 3 +++ include/linux/netfs.h | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/netfs/io.c b/fs/netfs/io.c index e9d408e211b8..d8e9cd6ce338 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -643,7 +643,11 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) return -EIO; } - rreq->io_iter = rreq->iter; + if (test_bit(NETFS_RREQ_USE_BOUNCE_BUFFER, &rreq->flags)) + iov_iter_xarray(&rreq->io_iter, ITER_DEST, &rreq->bounce, + rreq->start, rreq->len); + else + rreq->io_iter = rreq->iter; INIT_WORK(&rreq->work, netfs_rreq_work); diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 4df5e5eeada6..9f3f33c93317 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -35,12 +35,14 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, rreq->inode = inode; rreq->i_size = i_size_read(inode); rreq->debug_id = atomic_inc_return(&debug_ids); + xa_init(&rreq->bounce); INIT_LIST_HEAD(&rreq->subrequests); refcount_set(&rreq->ref, 1); __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); if (rreq->netfs_ops->init_request) { ret = rreq->netfs_ops->init_request(rreq, file); if (ret < 0) { + xa_destroy(&rreq->bounce); kfree(rreq); return ERR_PTR(ret); } @@ -94,6 +96,7 @@ static void netfs_free_request(struct work_struct *work) } kvfree(rreq->direct_bv); } + netfs_clear_buffer(&rreq->bounce); kfree_rcu(rreq, rcu); netfs_stat_d(&netfs_n_rh_rreq); } diff --git a/include/linux/netfs.h b/include/linux/netfs.h index c05150f51beb..8a5b8e7bc358 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -194,6 +194,7 @@ struct netfs_io_request { struct iov_iter iter; /* Unencrypted-side iterator */ struct iov_iter io_iter; /* I/O (Encrypted-side) iterator */ void *netfs_priv; /* Private data for the netfs */ + struct xarray bounce; /* Bounce buffer (eg. for crypto/compression) */ struct bio_vec *direct_bv /* DIO buffer list (when handling iovec-iter) */ __counted_by(direct_bv_count); unsigned int direct_bv_count; /* Number of elements in direct_bv[] */ @@ -216,6 +217,7 @@ struct netfs_io_request { #define NETFS_RREQ_DONT_UNLOCK_FOLIOS 3 /* Don't unlock the folios on completion */ #define NETFS_RREQ_FAILED 4 /* The request failed */ #define NETFS_RREQ_IN_PROGRESS 5 /* Unlocked when the request completes */ +#define NETFS_RREQ_USE_BOUNCE_BUFFER 6 /* Use bounce buffer */ const struct netfs_request_ops *netfs_ops; }; From patchwork Wed Dec 13 15:23:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491221 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8303CC4167B for ; Wed, 13 Dec 2023 15:25:18 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 89C708D0027; Wed, 13 Dec 2023 10:25:17 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 7A1428D0015; Wed, 13 Dec 2023 10:25:17 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 530948D0027; Wed, 13 Dec 2023 10:25:17 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id 36ED48D0015 for ; Wed, 13 Dec 2023 10:25:17 -0500 (EST) Received: from smtpin24.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id 1118A120B55 for ; Wed, 13 Dec 2023 15:25:17 +0000 (UTC) X-FDA: 81562168674.24.CD7632A Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf12.hostedemail.com (Postfix) with ESMTP id 1595440009 for ; Wed, 13 Dec 2023 15:25:14 +0000 (UTC) Authentication-Results: imf12.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=TniM+p1a; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf12.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481115; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=kDE/M1RbzgmjQWasqi03vRWSNjlBlYY2O7ZHPetmOEs=; b=qBA1tRfnE3adRtwNtrW6U4tR62ygKPflmZHWsNgwkWos4EyMPa+7d5QAgsu/KmEeu5A/F7 LR32WaekO7eL3NuNDBTqacNfGZzUkA86giSraxnl3N37c0Vllbho/8Bz8QKwxDb+CosGmg 1l7Z5DIhHf30Zeq7naZTiUoFUhZJGqQ= ARC-Authentication-Results: i=1; imf12.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=TniM+p1a; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf12.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481115; a=rsa-sha256; cv=none; b=x3FAswUKIi75Y3LcILycYe73jISNCu9ZPGy5XTH44PAFoD4AixAiguJnQhysMgoKG69j+n ALT2LS7jepjuhrSzqIQPtjhASenIcH15iN5Eq/FO56LtlUoCijTaxh1OGBDrbBf6qtNHpO PDyAdbnOoeooQ55OY6YvAHJQ4yu70eQ= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481114; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=kDE/M1RbzgmjQWasqi03vRWSNjlBlYY2O7ZHPetmOEs=; b=TniM+p1a2MFiDv30MFyiuPLjuEeW2WClFgiAy5Ag31HSlmQqublBZ54SyBsdh2l9VoiGPK dUEG63kMD8+utLwCUANnHL94wP4TEEA9CaL5tza6YQ3POoJ/BN8afpbBuSLqPytTk+7N1G 81RzHwLAzet1e/QP9lrJD1+dvlkA5pk= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-356-ScxEoKBwP5O-h7Cdj3saLA-1; Wed, 13 Dec 2023 10:25:06 -0500 X-MC-Unique: ScxEoKBwP5O-h7Cdj3saLA-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 71B541C04340; Wed, 13 Dec 2023 15:25:02 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 592C451E3; Wed, 13 Dec 2023 15:24:59 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 16/39] netfs: Add func to calculate pagecount/size-limited span of an iterator Date: Wed, 13 Dec 2023 15:23:26 +0000 Message-ID: <20231213152350.431591-17-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.5 X-Rspamd-Queue-Id: 1595440009 X-Rspam-User: X-Rspamd-Server: rspam02 X-Stat-Signature: 1hae6s1nxmyyfd8s1r4ktre37u6ak9pw X-HE-Tag: 1702481114-813112 X-HE-Meta: U2FsdGVkX1/WA9vfuAZQFfmejXk3xZPuhLulLOoAKNjYuC7Lxt6w/eqINm2PrhCNzDZeg8x65dF+b5GQZ6XSZ7XKkw1zsW0AqmXY6/KsRThQDEqwiZvjUf3zL7guqD+/y7q/st3uFRIQESxaFxyoceLABD/VoguF170Id8NtaIBS7Pl7TA3Tzg7SW4Ea3DC4jwaA7F79mf1ZC5ckNVlQFrb60QhduCYKqsBsDdenZN0RPZyuIFd+faqsdWs4Or/vpJ8qrEF/tM3cxLW6339+aiXpkOuB7Z0YGiQsq7JER4cxlrkkSiyEunmYEeF4mVyAljFL9PXoZhcUcpmFKfwuK3bxtpXKKos0sCSXStVhfHU9xqLMqW3UnoCjchWTS+yJlVDcbNE39POKkkyWomKYXTqfGG7/7M2HyyQxy0fL7gY7AaM/xrwMErFvSz+jLbkGUuXC7L7q9d877i6TRwNno2fCVTo4hCKoNr1b795upv2YiXwL9BjAS7m5CDX3BM23oJpVrNghKhhIQJy7Eg6v24QyhxOeaTkMar+qPOinrspFl72Dw4tlAPdDA2s1kXjKZrQJkazbI7afv49uRfJ4DEoZNKTCMZ1IjouZoZL/wgYFN7Aix0o58AOgeP1dCTzjg6ZiAiV5yIbVoUQUxM4go0eiNSz2zl9whLmXzZUz+9/012p/+1pzGGZV1zVR7DJW6Xd6Figl2V5k3he8FdEPxVm7IwRRFVfa1HEJlcxDKoxJpNgxahDZRwfJCHo5uEB+GeB3p9K4aP1Mdv1c/tIZnrHAAQR/ssVplxJX0sBkdhpL6K6WTxHLuU4bfP83z9Qarje9yQ5UcJWy5ihuY0pV1YLssr4I3ydKxEkJv4Q0nrn1zL0VvOdeE+t0z1Y/5wAhKNzg1u+bWTCfzK4rx5qlz7XLx3gLY1D8CTaofhHe2Lc4Sch6g8wyGPvue1B8UIRu+wE7zg6JzxeH7L9KMnR 3cXrcYd1 Y36fSZWnvWWdh0DKL03sZqGaJCEe9bv8Mqh3UFTOlFfhWKl1ixlp8x6NV+UfIny6GE0i+sUa4tu0CuUdBz78BBi39Zq7RlmIHi7l6iwllQFqer5l20KWUm+Hczt1E/0WuZgsHHps7m/UvrcRtL1/Ly0EdtFT6taJfnns6+WAQnBZvZajA6kKeHCa1Gghx2QqrnqNwtAZW12u+HvIFJ62GRKbPgqdjH+VoslgMJyCXtJGGYDnLSc7Smryy3aKERiKm8QPFqFckAT0Vh2UeNtF2a4bSQVTDMos7h1r/G0wAOGoVV04= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Add a function to work out how much of an ITER_BVEC or ITER_XARRAY iterator we can use in a pagecount-limited and size-limited span. This will be used, for example, to limit the number of segments in a subrequest to the maximum number of elements that an RDMA transfer can handle. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/iterator.c | 97 +++++++++++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 2 + 2 files changed, 99 insertions(+) diff --git a/fs/netfs/iterator.c b/fs/netfs/iterator.c index 2ff07ba655a0..b781bbbf1d8d 100644 --- a/fs/netfs/iterator.c +++ b/fs/netfs/iterator.c @@ -101,3 +101,100 @@ ssize_t netfs_extract_user_iter(struct iov_iter *orig, size_t orig_len, return npages; } EXPORT_SYMBOL_GPL(netfs_extract_user_iter); + +/* + * Select the span of a bvec iterator we're going to use. Limit it by both maximum + * size and maximum number of segments. Returns the size of the span in bytes. + */ +static size_t netfs_limit_bvec(const struct iov_iter *iter, size_t start_offset, + size_t max_size, size_t max_segs) +{ + const struct bio_vec *bvecs = iter->bvec; + unsigned int nbv = iter->nr_segs, ix = 0, nsegs = 0; + size_t len, span = 0, n = iter->count; + size_t skip = iter->iov_offset + start_offset; + + if (WARN_ON(!iov_iter_is_bvec(iter)) || + WARN_ON(start_offset > n) || + n == 0) + return 0; + + while (n && ix < nbv && skip) { + len = bvecs[ix].bv_len; + if (skip < len) + break; + skip -= len; + n -= len; + ix++; + } + + while (n && ix < nbv) { + len = min3(n, bvecs[ix].bv_len - skip, max_size); + span += len; + nsegs++; + ix++; + if (span >= max_size || nsegs >= max_segs) + break; + skip = 0; + n -= len; + } + + return min(span, max_size); +} + +/* + * Select the span of an xarray iterator we're going to use. Limit it by both + * maximum size and maximum number of segments. It is assumed that segments + * can be larger than a page in size, provided they're physically contiguous. + * Returns the size of the span in bytes. + */ +static size_t netfs_limit_xarray(const struct iov_iter *iter, size_t start_offset, + size_t max_size, size_t max_segs) +{ + struct folio *folio; + unsigned int nsegs = 0; + loff_t pos = iter->xarray_start + iter->iov_offset; + pgoff_t index = pos / PAGE_SIZE; + size_t span = 0, n = iter->count; + + XA_STATE(xas, iter->xarray, index); + + if (WARN_ON(!iov_iter_is_xarray(iter)) || + WARN_ON(start_offset > n) || + n == 0) + return 0; + max_size = min(max_size, n - start_offset); + + rcu_read_lock(); + xas_for_each(&xas, folio, ULONG_MAX) { + size_t offset, flen, len; + if (xas_retry(&xas, folio)) + continue; + if (WARN_ON(xa_is_value(folio))) + break; + if (WARN_ON(folio_test_hugetlb(folio))) + break; + + flen = folio_size(folio); + offset = offset_in_folio(folio, pos); + len = min(max_size, flen - offset); + span += len; + nsegs++; + if (span >= max_size || nsegs >= max_segs) + break; + } + + rcu_read_unlock(); + return min(span, max_size); +} + +size_t netfs_limit_iter(const struct iov_iter *iter, size_t start_offset, + size_t max_size, size_t max_segs) +{ + if (iov_iter_is_bvec(iter)) + return netfs_limit_bvec(iter, start_offset, max_size, max_segs); + if (iov_iter_is_xarray(iter)) + return netfs_limit_xarray(iter, start_offset, max_size, max_segs); + BUG(); +} +EXPORT_SYMBOL(netfs_limit_iter); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 8a5b8e7bc358..a30b47e10797 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -324,6 +324,8 @@ void netfs_put_subrequest(struct netfs_io_subrequest *subreq, ssize_t netfs_extract_user_iter(struct iov_iter *orig, size_t orig_len, struct iov_iter *new, iov_iter_extraction_t extraction_flags); +size_t netfs_limit_iter(const struct iov_iter *iter, size_t start_offset, + size_t max_size, size_t max_segs); int netfs_start_io_read(struct inode *inode); void netfs_end_io_read(struct inode *inode); From patchwork Wed Dec 13 15:23:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491223 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 755A4C4167B for ; Wed, 13 Dec 2023 15:25:23 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 33A358D0029; Wed, 13 Dec 2023 10:25:19 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 1E9D88D0015; Wed, 13 Dec 2023 10:25:19 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id E81B38D0029; Wed, 13 Dec 2023 10:25:18 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id CA8CF8D0015 for ; Wed, 13 Dec 2023 10:25:18 -0500 (EST) Received: from smtpin02.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id A521B1A012A for ; Wed, 13 Dec 2023 15:25:18 +0000 (UTC) X-FDA: 81562168716.02.0C03531 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf20.hostedemail.com (Postfix) with ESMTP id BB1A31C0028 for ; Wed, 13 Dec 2023 15:25:16 +0000 (UTC) Authentication-Results: imf20.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b="ZC/jQUV+"; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf20.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481116; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=YJNYoDwT7ftU812GMv/DOgXVSH8Cj0I5WKRdeJiGu3I=; b=0WAhmgU9WZevrAaggBDrY91VoTmgzWWZ6TGIdGQZiKzzhNaR1gAhq6GsA60TD+eOy0ZVDQ dbrF7yQsgEMGZ6jqZ8zZW2xW15Q9VqcsdZAyu94V0c68WhNAnX0Rds30MUJyHoBGHFPv98 zMTjnzClBH6RH+HHhOcP6fnRQBUAh9k= ARC-Authentication-Results: i=1; imf20.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b="ZC/jQUV+"; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf20.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481116; a=rsa-sha256; cv=none; b=EBRNNS9fkigdByn1YiSJq+JT6UGYnlG/d5aCrStoArwDGHhLo6gkkyV89RimOrP3PFtieg Nn3iMUdo6UK+/sK7e/L9/f5We3h8MJfSgIO+ZX/G04RKIHSUbXlvnKZIuVUedhql7DYJkc NbKDSjrqh989m9Kmh430uZqNIRJqdLg= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481116; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YJNYoDwT7ftU812GMv/DOgXVSH8Cj0I5WKRdeJiGu3I=; b=ZC/jQUV+EwS6snYfTNqF+TGgdXRyzFclwE1aa2QS1xGvKU4vo7mjyRly3Gyk0zUsYFGWI7 OAseGkxBaQsVvHh0ngNcOA/EkG+EIbga0L96LaSqra45sYueaKGRtzrsaGxz3WVXa3xBYe M0zlGF1gdBiLRjvgddnaGC1YFq2jdEs= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-441-flG4pN2DMa-Hpy2vCSDm9Q-1; Wed, 13 Dec 2023 10:25:11 -0500 X-MC-Unique: flG4pN2DMa-Hpy2vCSDm9Q-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id D07A71C06E02; Wed, 13 Dec 2023 15:25:06 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3FA05492BC8; Wed, 13 Dec 2023 15:25:03 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 17/39] netfs: Limit subrequest by size or number of segments Date: Wed, 13 Dec 2023 15:23:27 +0000 Message-ID: <20231213152350.431591-18-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.9 X-Rspamd-Queue-Id: BB1A31C0028 X-Rspam-User: X-Rspamd-Server: rspam04 X-Stat-Signature: hdtnbnaz1cy3xdyjjfeyam6t6hbobxt9 X-HE-Tag: 1702481116-271 X-HE-Meta: U2FsdGVkX1/3QEar+aPh8BmKWpMZWHeXaFFLgu/FwZE3kfdejZ61heWgr63gRYqIua820SgOcuzaeJZ5S8HgdB8oSyFfJp+9u+RUiwSY+FMCYSKqPPwarxqxGF4CL3kYKRfCV44mm9fX7ncv+pnVq/NAKGJVE+1vZmC2oDCAiep2TCFp7xwTBGL5X+d7RMthK3bW2pENWFuSJEx7Q0B5HmLormCfUsgaU5Q60qNkyY7VEV4Ynk9VrPRSnKJSlp46UMujIC7VjUqLVO7s/TTXocWaZ7bJpSkPwjOSKXjOZOPdH2W0o/S1fxCzKXfsp1vCjgFmxt2nogFgxKW9uAAnBlyB0pMWjewEAJ7CEKirO/tbSLAcV5aE24VmQ3Txba5A98uLK0wKBmxN5EDred46SKrmUkpq7Eni6b2IXkBO50rwcI21QrUqfhzUEW56p8/eBHT9qUjrdu1erH6cYD0XfyrzYncsXwlN4ud1gyWMjQ8gL3wJmItQ05AzCdgzJZxO/Ww7xxL37p6qkjIFLzyS+PqkZM9xkKMlQrwrbdZa/BkzDCObi/j7/jGsybsVUfaqTYFGJrNKToA534m0WYmAo1tVqQ9hKs3ZRNHsC87oY3pGi8ZNQ5T1HK2cq+yLtJC/ML4W1mrULmOhJ4lKNT7fhx/VBj4Wfu2WlJ9TfJJMHlTzb+sLSY/EZ+UBRkh1wCAa3noDO4IoBwhrDHjUgBWP5ZgM02soRlySqNdUegV8BM1+8w4SQ9/9fXFcrE1nv2KCtecwsJCfWgPQVdIt/Ms8J2U0MEXvIvxZdNZRLtv3GQQP9rJBseKY8khOzYNKf/0DjSNkF2kzQmT7Wcs684rLcAFlzz3wrM2dGTHPDrNKQjp2g/OuYlMwF8uqen4QXHLbYH5wG+oMb6kwro8Ai7ULxfJfLN8Z/lcOYx8dYG1ILVtzC/rirpPoRUE1vE6IjkXMFmEzrMcsrqe43GIMqM8 hTLa9Rw5 6jRoRTf6fjGwNAmKkqjqNQMDlYsj3CPyDyOqfuPj0joaIREd05tLmMQwHOuHoKN2VX9ntUXTl7A572T7fHlmSVTg50jQ+tIoq5zEZLdCROpNoImDqt6cE/xdv6+yjOpGyZlVW/PARpQ/d62K5SHr3/o59uJgWy2m3JPPWgXy3+zysSr/XJM1yNAEtm7Jey77oTRWtWAq4+c5RK8pnlKoEPyBMXUnP9fe/VxS3fjd9T0LS2i2na2EmL0HdcMz6x3AScLju2KxdC7lxaSWGd7UPqFNHpQwt8mdb6f+cPwX11V0Me0M= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Limit a subrequest to a maximum size and/or a maximum number of contiguous physical regions. This permits, for instance, an subreq's iterator to be limited to the number of DMA'able segments that a large RDMA request can handle. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/io.c | 18 ++++++++++++++++++ include/linux/netfs.h | 1 + include/trace/events/netfs.h | 1 + 3 files changed, 20 insertions(+) diff --git a/fs/netfs/io.c b/fs/netfs/io.c index d8e9cd6ce338..c80b8eed1209 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -525,6 +525,7 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq, struct iov_iter *io_iter) { enum netfs_io_source source; + size_t lsize; _enter("%llx-%llx,%llx", subreq->start, subreq->start + subreq->len, rreq->i_size); @@ -547,13 +548,30 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq, source = NETFS_INVALID_READ; goto out; } + + if (subreq->max_nr_segs) { + lsize = netfs_limit_iter(io_iter, 0, subreq->len, + subreq->max_nr_segs); + if (subreq->len > lsize) { + subreq->len = lsize; + trace_netfs_sreq(subreq, netfs_sreq_trace_limited); + } + } } + if (subreq->len > rreq->len) + pr_warn("R=%08x[%u] SREQ>RREQ %zx > %zx\n", + rreq->debug_id, subreq->debug_index, + subreq->len, rreq->len); + if (WARN_ON(subreq->len == 0)) { source = NETFS_INVALID_READ; goto out; } + subreq->source = source; + trace_netfs_sreq(subreq, netfs_sreq_trace_prepare); + subreq->io_iter = *io_iter; iov_iter_truncate(&subreq->io_iter, subreq->len); iov_iter_advance(io_iter, subreq->len); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index a30b47e10797..406d5a3a3298 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -161,6 +161,7 @@ struct netfs_io_subrequest { refcount_t ref; short error; /* 0 or error that occurred */ unsigned short debug_index; /* Index in list (for debugging output) */ + unsigned int max_nr_segs; /* 0 or max number of segments in an iterator */ enum netfs_io_source source; /* Where to read from/write to */ unsigned long flags; #define NETFS_SREQ_COPY_TO_CACHE 0 /* Set if should copy the data to the cache */ diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index beec534cbaab..fce6d0bc78e5 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -44,6 +44,7 @@ #define netfs_sreq_traces \ EM(netfs_sreq_trace_download_instead, "RDOWN") \ EM(netfs_sreq_trace_free, "FREE ") \ + EM(netfs_sreq_trace_limited, "LIMIT") \ EM(netfs_sreq_trace_prepare, "PREP ") \ EM(netfs_sreq_trace_resubmit_short, "SHORT") \ EM(netfs_sreq_trace_submit, "SUBMT") \ From patchwork Wed Dec 13 15:23:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491224 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id EB988C4332F for ; Wed, 13 Dec 2023 15:25:25 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 756508D002A; Wed, 13 Dec 2023 10:25:19 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 5F75C8D0015; Wed, 13 Dec 2023 10:25:19 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 24AE78D002B; Wed, 13 Dec 2023 10:25:19 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id F22A08D002A for ; Wed, 13 Dec 2023 10:25:18 -0500 (EST) Received: from smtpin28.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id CBB00A01C1 for ; Wed, 13 Dec 2023 15:25:18 +0000 (UTC) X-FDA: 81562168716.28.663C0A5 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf27.hostedemail.com (Postfix) with ESMTP id 254194001F for ; Wed, 13 Dec 2023 15:25:16 +0000 (UTC) Authentication-Results: imf27.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=XuGokl76; spf=pass (imf27.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481117; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=lvA6ro7QUMhtjJlsHPwIgzyPLJOZgWtkvO2st3qI+pQ=; b=ZnzefD2t8OOCH14iKwTXVwsTwXrDFdCjZu4h0EPwusLbVkpafJ1jtF8kxXJiLERB2DISEr BQavzUTjlEzx3uspThtae6QaGOTb1biMBh4rlUMiXIkBUApnJaTbAqT1gvs9qA2ZaTVCOR VqbVPk0e8heutReAmZtGsYLS0BPgCec= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481117; a=rsa-sha256; cv=none; b=DyMEYG1ilkhEaPP9tqNt1YQ7+FozrFD7+14XTUn5dBNpGI5LtuYgtWv6r1TzluZF4ymfcV KG7NKEg4rx1yyEdjuF7P23MOKqNAEw0Jo58domliuGmiRwLvU2lwlH2QKq6dOJwMyrUzn7 chjLhldDp2QNtoM0CSyB0jpUorh4PLk= ARC-Authentication-Results: i=1; imf27.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=XuGokl76; spf=pass (imf27.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481116; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lvA6ro7QUMhtjJlsHPwIgzyPLJOZgWtkvO2st3qI+pQ=; b=XuGokl767gJGPoyK9vIuO2SxMNaI8WI2tu124l3IP2ovKf3g1P7CCQeRa8un5eHD5yPR+Z y0xbxJheYt+RVEoYfOmi+KMcoFxloPvxmDjcIgVbO50ehxuYGdVMLkqO0cOK2gGzfArG9w syzRpRK23ZaHvjs5cfwD6pgKkxwpVS8= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-671-iyLSuWLZPsOdcU7o8BoPxg-1; Wed, 13 Dec 2023 10:25:13 -0500 X-MC-Unique: iyLSuWLZPsOdcU7o8BoPxg-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id B2A0F88FA32; Wed, 13 Dec 2023 15:25:11 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id BDB4C2166B31; Wed, 13 Dec 2023 15:25:07 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 18/39] netfs: Export netfs_put_subrequest() and some tracepoints Date: Wed, 13 Dec 2023 15:23:28 +0000 Message-ID: <20231213152350.431591-19-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.6 X-Stat-Signature: k336d4pyoebxtrgro7zc9dtpeyjmrknw X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: 254194001F X-Rspam-User: X-HE-Tag: 1702481116-239215 X-HE-Meta: U2FsdGVkX1/w3N8bf/VefR0G1rfxFpDXzEo/Do9K6LLk/b/CMALQF0rsmFycycsQKU9DKmTgFkYInwBx+a3Ym7+Wb/2PHTbnDsd1WmyFtBN1ChmAtGhVPZ3XW8yuRNsXsiBQA5D8MeTBEefla+T2haUKBY0Fj3p68YaKWJo+Vo6DEfxdIcCOkx+fRiWzB9sj3mwkSRFnG3TBSikVjZsDVKuzhYAkLl5q0Jrbg5lMpzzUVKasnWb8/pnc+8C5djFXVmcZtX/mZsd/vdqBTa3Lek8v9hBaozJMgG/BFhyyJAfwEUlsvTnCxVhDY5xv25MvkmTSs6Ifm8bLKRDxRf0JTtTfBxKc4eijflv0b8ycdMIOLImCSVpF0QkbowbKvPYZDbohWwXPjdHAmLTBlw5i/pmwWt3rQrNQE/2YJO409PMD7DBALHM96xHDvE9VUt6O+IaIqZGUkC1jQmT/uhXdS2T4k3hp/Lax/PybWgOCQqmDwHVZrIV5SiShuvPD8erfAP9QjkCHdXXmHx/1tLs5d5uiGbZCxfPaVoxrrcLtalS7FRi15BzE3wu94OUWd1glZS9NKwxMXaZpc9TUDvZeiVrYrQrLX801rE76cHSPwFNYlnAItEe3QFjM9hRh6yMD9OZrhaLGmuWwb21xU2NzKlZPNMqrmOcXKR6kFnajaSPQ3jcunBXoqZY1SJULYecJawS7O60o53J6DlEBjQoVRcPXz/68imGSM9uIxWjjsH6pgQWlz5p5u1z213F/VLjROxPIfmTDs+3kGSx/WZeoXI9pQyBxlx4rh9JxWwgmsYx5TCCPYfXol+cpGQT7dp6rR6BMRpUPZaX0y1T+d8ZZHIy6NTSn8tHXr5u1FQh0qzWqFGyncRRqanayacjbd7yrArT6Ixb+ShtPD+PRME3K8/YFqVK37IwbEzrRR7L5jjC9Q8OLkWzXZxAj3HiNo1IyJyw6kJGXdS2c0252+wT m9tWiLSJ w5svPgitivnAtmHVJ+kXw0UMTQUya8Ix9kBN0osBH5sxPwzFMLzd3rtkGOliHGI6pkSv+Z/YfOMGmwtUwNSZV8WFipAVPqykMIaP0Dm8dwp4nwdnEHCvl0HUYWiMAxNctX7veHxUoZTk8RCCMMKd3RZGbQ9QKksL4u0c4CmZxyGkU1Dnidfc2vCtC8SK4RHwx8Udh6cLSz5k4UVEm0SlTgPF/E0OZu896GA1IyelHPMQKCL/Byi/taSOCCGxvBuaBPoIRhDfA6w2GTEEUguF1tMVgdjN9hX6uISrh75yUkuWbzTyXi+TnSzc5dm7p+BmzLAs04pq7WUa8kES6bsYmxj5cGQ== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Export netfs_put_subrequest() and the netfs_rreq and netfs_sreq tracepoints. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/main.c | 3 +++ fs/netfs/objects.c | 1 + 2 files changed, 4 insertions(+) diff --git a/fs/netfs/main.c b/fs/netfs/main.c index 97ce1436615b..404e68e339bf 100644 --- a/fs/netfs/main.c +++ b/fs/netfs/main.c @@ -17,6 +17,9 @@ MODULE_DESCRIPTION("Network fs support"); MODULE_AUTHOR("Red Hat, Inc."); MODULE_LICENSE("GPL"); +EXPORT_TRACEPOINT_SYMBOL(netfs_rreq); +EXPORT_TRACEPOINT_SYMBOL(netfs_sreq); + unsigned netfs_debug; module_param_named(debug, netfs_debug, uint, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask"); diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 9f3f33c93317..a7947e82374a 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -178,3 +178,4 @@ void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_async, if (dead) netfs_free_subrequest(subreq, was_async); } +EXPORT_SYMBOL(netfs_put_subrequest); From patchwork Wed Dec 13 15:23:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491225 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9042DC4332F for ; Wed, 13 Dec 2023 15:25:28 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 50E4B8D002B; Wed, 13 Dec 2023 10:25:24 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 4BB538D0015; Wed, 13 Dec 2023 10:25:24 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 1E4348D002B; Wed, 13 Dec 2023 10:25:24 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id F0E208D0015 for ; Wed, 13 Dec 2023 10:25:23 -0500 (EST) Received: from smtpin10.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id CF12F1C116F for ; Wed, 13 Dec 2023 15:25:23 +0000 (UTC) X-FDA: 81562168926.10.11E723F Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf09.hostedemail.com (Postfix) with ESMTP id 0875814002A for ; Wed, 13 Dec 2023 15:25:21 +0000 (UTC) Authentication-Results: imf09.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=ETi9cHtY; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf09.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481122; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=FiYKm77Ht/I6AsAMlaNFj+jCmOgPY/9fZvw3wuH/0+8=; b=wcx/ua2LHiG3ky2pPYiSriZHO6uyk1zH4hMRlwZ29yKuHgAPFjL9tbY7V/+PVmcBQH0LeS yebA/7EnSWvK8xOFXDZxGUg77oQbZ5IvgGAPaeozAHi/rueGuJAjGMI408HHuGBOMK+pnn l7dRQywkAMiLsBP74mDx2NdH5sPhuR4= ARC-Authentication-Results: i=1; imf09.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=ETi9cHtY; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf09.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481122; a=rsa-sha256; cv=none; b=Wa5IlNIN/uQMOCXfAFwBvvGZryGzjcBolgNHBv6cODzVN9xnSHH5oUbjvGtdX85gMk4BRh bk10IbNpUUHgJVd9ELmBxxnjjCZSHGcihM8xfP3Pued0BPFgNvp7AmsippBRAWn5A3EA6V vO/AeFnbBt/vEIyt4MgEG2KkgAZ0YQU= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481121; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FiYKm77Ht/I6AsAMlaNFj+jCmOgPY/9fZvw3wuH/0+8=; b=ETi9cHtYxBiFVorFRonLXwXbenJ/vP75jQg+CAz57iWhFBKfgtk74m1B3Xl4KK/H1wqHgs aSAtTlRAsURuI2QeUKx+bmzkRD//N4Y4W2VaF0USneAmCJt1sdBom0yZm9xWeQVyyelLOd zE6nVjAOsYFVuqtYQtKJpgBSoq1IOdk= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-610-oG-RsZfGM26XNfj-72Frrw-1; Wed, 13 Dec 2023 10:25:18 -0500 X-MC-Unique: oG-RsZfGM26XNfj-72Frrw-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 4CFAD3C23FE5; Wed, 13 Dec 2023 15:25:16 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 978F551E3; Wed, 13 Dec 2023 15:25:12 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 19/39] netfs: Extend the netfs_io_*request structs to handle writes Date: Wed, 13 Dec 2023 15:23:29 +0000 Message-ID: <20231213152350.431591-20-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.5 X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 0875814002A X-Stat-Signature: sfifopozff9s85jiybdxtfgwwizt7oxh X-HE-Tag: 1702481121-469785 X-HE-Meta: U2FsdGVkX18ZA2ViBKwxzhgLFKtIy4YX3QGoB/mfpYId+n4y/H+MGIZujmFqfdafr0xshOWX/iVYJAHGVDh1/eonElStietyg6lim7Is1F0l2qK2qQFS8KV2dsp5yI5E60Sxv9b7D2tof7KtABgJPVOcHEsmD02TW62c1RJY1X1ZQ2bayMWxjX5hTpVbgTzIXRC3ugow1Vx9tydJCwpg7kUsT1q31cmdaEMcaraQvhDVy/Q/JFsPhEf2x6kivtBXOrmi8pXMOgDwI+bZnU43FfsYyViI50m71hNIRv8lkvsOfSpPK+2ixv6QU8EnJBsOX/hKNcgyA59DQU0XLovrMaU0ODwxrUPpXAMGENaUoH4BQudeIEmssdAUdMb8wWIPKPLX+BnTvFA+v8kB9esdJtSVkY64ovXz1Yzc32o4H5r0BquvYqW9A0Tp9F/UI6flA2f0OIbHvEktiOdwD2Ip8NcwpFV6PDbMjqKk+DaNwzdjD/Mmz9pIBL73ABUiVAVPEk/Sln9MhLcQnUSTK5776sXj1nC8uJjHphHJpq7Sw8+hyc/wbs76EKVANTipTU1uG/hur5jcle4k0lh4QHPxsIntzsYCWoM+ZFf8RHhCgkUD2tS2lZdi0i0bd/O+EnPVsowCofQ7QP/eMCYJ2Og4xBV4nPbYo10I3XZBEydbpQ2sOFVqvazFFB1vwXCieB+4kABfW1a9UffX4lqQe0nd/rf2Oss0N6sEF/Lt1B5nTh9fT86VfFp+Daoq+znukxQBiavtDB+ijdLnv59Kzk9HeDfNlNR6OtdYNEDVLcIEYTHDZBpjFVvk5Cc8MZ7c6yEcOiW4CEs9h0aags1lehy3ybym22L622rP56YN1G7F50E5ZKXbFiTq/qdW6vunoSOnRFR0Ib9JlCVAmOxrIsamPlJFn0STISmYxGFLP8jlcSDJ62GirECIZTF4MMbKokLgS2txwHQQU6oL8DrN8PF BkR8SXbV HPM4hhtR1jR3Bf7QHyRzDJDmVCXbAF/L3gOahpVAq4XduZAW0WCXmy4RJk7gbQyS9YykpZLKBEKnEjcSr9rN3UUGQ6LetvwdJO+BCvA8ay2ZwcuPd3NTmH6j+IoOMIVTbzpr6vgTmoB+yngRU2NsEQdddMRWwJPP1TrE8dHTcmhbhAB0k0RGgyskLApdLMzuUTFlyE9HVEi8RbBhQrxDGNoLwTNeaL84OMO24fOnRS4ERTOCW2JlaFzvFVceY93OE/4jihPeXVEgi7AT1f3lEylfjI4xV6wMhRJWGj7CQXS8lXNzeqdXnDQs1oKd1CdMhNMPDureL1vqH9ePm2goFnQp7mg== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Modify the netfs_io_request struct to act as a point around which writes can be coordinated. It represents and pins a range of pages that need writing and a list of regions of dirty data in that range of pages. If RMW is required, the original data can be downloaded into the bounce buffer, decrypted if necessary, the modifications made, then the modified data can be reencrypted/recompressed and sent back to the server. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/internal.h | 6 ++++++ fs/netfs/main.c | 3 ++- fs/netfs/objects.c | 6 ++++++ fs/netfs/stats.c | 16 +++++++++++++--- include/linux/netfs.h | 15 ++++++++++++++- include/trace/events/netfs.h | 8 ++++++-- 6 files changed, 47 insertions(+), 7 deletions(-) diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 20eb1fd6986e..8d1bfc9c3e2f 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -110,6 +110,12 @@ extern atomic_t netfs_n_rh_write_begin; extern atomic_t netfs_n_rh_write_done; extern atomic_t netfs_n_rh_write_failed; extern atomic_t netfs_n_rh_write_zskip; +extern atomic_t netfs_n_wh_upload; +extern atomic_t netfs_n_wh_upload_done; +extern atomic_t netfs_n_wh_upload_failed; +extern atomic_t netfs_n_wh_write; +extern atomic_t netfs_n_wh_write_done; +extern atomic_t netfs_n_wh_write_failed; int netfs_stats_show(struct seq_file *m, void *v); diff --git a/fs/netfs/main.c b/fs/netfs/main.c index 404e68e339bf..6584eafda944 100644 --- a/fs/netfs/main.c +++ b/fs/netfs/main.c @@ -28,10 +28,11 @@ MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask"); LIST_HEAD(netfs_io_requests); DEFINE_SPINLOCK(netfs_proc_lock); -static const char *netfs_origins[] = { +static const char *netfs_origins[nr__netfs_io_origin] = { [NETFS_READAHEAD] = "RA", [NETFS_READPAGE] = "RP", [NETFS_READ_FOR_WRITE] = "RW", + [NETFS_WRITEBACK] = "WB", }; /* diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index a7947e82374a..7ef804e8915c 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -20,6 +20,7 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, struct inode *inode = file ? file_inode(file) : mapping->host; struct netfs_inode *ctx = netfs_inode(inode); struct netfs_io_request *rreq; + bool cached = netfs_is_cache_enabled(ctx); int ret; rreq = kzalloc(ctx->ops->io_request_size ?: sizeof(struct netfs_io_request), @@ -38,7 +39,10 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, xa_init(&rreq->bounce); INIT_LIST_HEAD(&rreq->subrequests); refcount_set(&rreq->ref, 1); + __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); + if (cached) + __set_bit(NETFS_RREQ_WRITE_TO_CACHE, &rreq->flags); if (rreq->netfs_ops->init_request) { ret = rreq->netfs_ops->init_request(rreq, file); if (ret < 0) { @@ -48,6 +52,7 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, } } + trace_netfs_rreq_ref(rreq->debug_id, 1, netfs_rreq_trace_new); netfs_proc_add_rreq(rreq); netfs_stat(&netfs_n_rh_rreq); return rreq; @@ -132,6 +137,7 @@ struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request *rreq sizeof(struct netfs_io_subrequest), GFP_KERNEL); if (subreq) { + INIT_WORK(&subreq->work, NULL); INIT_LIST_HEAD(&subreq->rreq_link); refcount_set(&subreq->ref, 2); subreq->rreq = rreq; diff --git a/fs/netfs/stats.c b/fs/netfs/stats.c index 6025dc485f7e..c1f85cd595a4 100644 --- a/fs/netfs/stats.c +++ b/fs/netfs/stats.c @@ -27,6 +27,12 @@ atomic_t netfs_n_rh_write_begin; atomic_t netfs_n_rh_write_done; atomic_t netfs_n_rh_write_failed; atomic_t netfs_n_rh_write_zskip; +atomic_t netfs_n_wh_upload; +atomic_t netfs_n_wh_upload_done; +atomic_t netfs_n_wh_upload_failed; +atomic_t netfs_n_wh_write; +atomic_t netfs_n_wh_write_done; +atomic_t netfs_n_wh_write_failed; int netfs_stats_show(struct seq_file *m, void *v) { @@ -50,10 +56,14 @@ int netfs_stats_show(struct seq_file *m, void *v) atomic_read(&netfs_n_rh_read), atomic_read(&netfs_n_rh_read_done), atomic_read(&netfs_n_rh_read_failed)); + seq_printf(m, "Netfs : UL=%u us=%u uf=%u\n", + atomic_read(&netfs_n_wh_upload), + atomic_read(&netfs_n_wh_upload_done), + atomic_read(&netfs_n_wh_upload_failed)); seq_printf(m, "Netfs : WR=%u ws=%u wf=%u\n", - atomic_read(&netfs_n_rh_write), - atomic_read(&netfs_n_rh_write_done), - atomic_read(&netfs_n_rh_write_failed)); + atomic_read(&netfs_n_wh_write), + atomic_read(&netfs_n_wh_write_done), + atomic_read(&netfs_n_wh_write_failed)); return fscache_stats_show(m); } EXPORT_SYMBOL(netfs_stats_show); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 406d5a3a3298..fce7a5a86e8e 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -118,6 +118,9 @@ enum netfs_io_source { NETFS_DOWNLOAD_FROM_SERVER, NETFS_READ_FROM_CACHE, NETFS_INVALID_READ, + NETFS_UPLOAD_TO_SERVER, + NETFS_WRITE_TO_CACHE, + NETFS_INVALID_WRITE, } __mode(byte); typedef void (*netfs_io_terminated_t)(void *priv, ssize_t transferred_or_error, @@ -149,9 +152,14 @@ struct netfs_cache_resources { }; /* - * Descriptor for a single component subrequest. + * Descriptor for a single component subrequest. Each operation represents an + * individual read/write from/to a server, a cache, a journal, etc.. + * + * The buffer iterator is persistent for the life of the subrequest struct and + * the pages it points to can be relied on to exist for the duration. */ struct netfs_io_subrequest { + struct work_struct work; struct netfs_io_request *rreq; /* Supervising I/O request */ struct list_head rreq_link; /* Link in rreq->subrequests */ struct iov_iter io_iter; /* Iterator for this subrequest */ @@ -176,6 +184,8 @@ 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 */ + NETFS_WRITEBACK, /* This write was triggered by writepages */ + nr__netfs_io_origin } __mode(byte); /* @@ -200,6 +210,7 @@ struct netfs_io_request { __counted_by(direct_bv_count); unsigned int direct_bv_count; /* Number of elements in direct_bv[] */ unsigned int debug_id; + unsigned int subreq_counter; /* Next subreq->debug_index */ 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 */ @@ -219,6 +230,8 @@ struct netfs_io_request { #define NETFS_RREQ_FAILED 4 /* The request failed */ #define NETFS_RREQ_IN_PROGRESS 5 /* Unlocked when the request completes */ #define NETFS_RREQ_USE_BOUNCE_BUFFER 6 /* Use bounce buffer */ +#define NETFS_RREQ_WRITE_TO_CACHE 7 /* Need to write to the cache */ +#define NETFS_RREQ_UPLOAD_TO_SERVER 8 /* Need to write to the server */ const struct netfs_request_ops *netfs_ops; }; diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index fce6d0bc78e5..4ea4e34d279f 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -24,7 +24,8 @@ #define netfs_rreq_origins \ EM(NETFS_READAHEAD, "RA") \ EM(NETFS_READPAGE, "RP") \ - E_(NETFS_READ_FOR_WRITE, "RW") + EM(NETFS_READ_FOR_WRITE, "RW") \ + E_(NETFS_WRITEBACK, "WB") #define netfs_rreq_traces \ EM(netfs_rreq_trace_assess, "ASSESS ") \ @@ -39,7 +40,10 @@ EM(NETFS_FILL_WITH_ZEROES, "ZERO") \ EM(NETFS_DOWNLOAD_FROM_SERVER, "DOWN") \ EM(NETFS_READ_FROM_CACHE, "READ") \ - E_(NETFS_INVALID_READ, "INVL") \ + EM(NETFS_INVALID_READ, "INVL") \ + EM(NETFS_UPLOAD_TO_SERVER, "UPLD") \ + EM(NETFS_WRITE_TO_CACHE, "WRIT") \ + E_(NETFS_INVALID_WRITE, "INVL") #define netfs_sreq_traces \ EM(netfs_sreq_trace_download_instead, "RDOWN") \ From patchwork Wed Dec 13 15:23:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491226 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C96DC4167D for ; Wed, 13 Dec 2023 15:25:31 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id ED0538D002C; Wed, 13 Dec 2023 10:25:29 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id E5E018D0015; Wed, 13 Dec 2023 10:25:29 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id C5C668D002C; Wed, 13 Dec 2023 10:25:29 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id B0E6D8D0015 for ; Wed, 13 Dec 2023 10:25:29 -0500 (EST) Received: from smtpin03.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 8FA1E1A01B6 for ; Wed, 13 Dec 2023 15:25:29 +0000 (UTC) X-FDA: 81562169178.03.C217B7D Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf03.hostedemail.com (Postfix) with ESMTP id B3D0E2000E for ; Wed, 13 Dec 2023 15:25:27 +0000 (UTC) Authentication-Results: imf03.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=RqxUxQdO; spf=pass (imf03.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481127; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=VpkcpqQGFjGGotXxykSSFj/z2Mj8Id/3cGjDF6fP5aE=; b=624glz5lMST8z6NjdeVKHG9bHjNv2oBevZqG3aoWXYT0E0TN//+yk3YeBeTqQGMPtcTwKO /rGzXg+7AlReytHSkpxMHJVQPCqsdRGz+xYf6LAMKU1OEOFkCnGasCVKFVuEKQKx8QYk82 dSwUltB01lMFrpBnWZVr/E9do2oZW7I= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481127; a=rsa-sha256; cv=none; b=JOs+DdACriPbl1DSKKZCg4NjVsP0QC989Ww11D5LU7XuaIOSVJSbEkbzwEA1SCUndRHoro ikOIds6nDtCIHoBKGOa6BaTZW3sOYuJwP8gy5P8BHzw0RaDOMYHciL8vH+WecS8nd2uwJT EDUDAeEKNa+zVSSZ3iTSQabod+mUl0U= ARC-Authentication-Results: i=1; imf03.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=RqxUxQdO; spf=pass (imf03.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481127; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VpkcpqQGFjGGotXxykSSFj/z2Mj8Id/3cGjDF6fP5aE=; b=RqxUxQdOkbPY4YYeTiaNVi8hIkdd7ntVKpUuArwKWTIb0TeLYLqAxqIrHbTwwmAbw1B16X aHQL+y9mWQZyunwv/Ov6XdZUOFy0IRFj96rXlRnDZ24YaymjGok8AznUzGQGVKw1CQv5Wd aGeTPjhdjnAV2cnWZvsx042PRka1dOw= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-304-88t-8xhZOheK8Hq2lph6_g-1; Wed, 13 Dec 2023 10:25:22 -0500 X-MC-Unique: 88t-8xhZOheK8Hq2lph6_g-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 42531182FD4A; Wed, 13 Dec 2023 15:25:21 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 54C0BC15968; Wed, 13 Dec 2023 15:25:17 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 20/39] netfs: Add a hook to allow tell the netfs to update its i_size Date: Wed, 13 Dec 2023 15:23:30 +0000 Message-ID: <20231213152350.431591-21-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.8 X-Stat-Signature: tdrk8wrwpybnsum7q19hnggtjn8ggktt X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: B3D0E2000E X-Rspam-User: X-HE-Tag: 1702481127-474578 X-HE-Meta: U2FsdGVkX1+D1p9j81i+XqCz8vrkGNeewQp+uhdvu/MEAWOzpdHCwfCnZI6Kbigh0dRzrjihI8BhP+eR86f/Ymwzm89EXK+MaBAoNrhfnwIFmwhCN5Rm0bkFaMHQUGTLYEChKVWlVhM6fWHmZq5uBaufTAwjkcV4Siu41wCrhV46FoJcnaOtwHyakoCLh2+wg1SVHMnNMIsaY93FcZtLYOBymrgK1N0SjLiJG0RJTvBTgSnm+mnap/fRCIiLPZxiIYY7Ys0unoqXEK7j8Yn6jdGgqrMWqHd2rLQWXJ7Q8Ybs4OSZzWT+07Ll4+b/dgCY2fE7fXz7pMef7IkMdksaxq5OdgulBSXthta1jA8dhz42uA+lDbA7EMVMD2VrnT/tD/b89nbx1ZFZLi/l1I2SjdEFsKEkQeUuD5YJbLo+BK+wgCebXI8fXzgCB+a+kJbftJobEj7OIZ6tS8qu1STN/kLDppHxTaucnMECuzJOb7Ohgs2dJ6Q3gGAXCv8N9YsKIPuNpHJhIhRgRhRKxQ0o0KAexW++UwRYwIFno/W4AbGfaFpexO8p13Vbu5aHNhikzDuPaaJ1y9f4zdPJejUfvGP1M+jKX+G0AoTfJPyjW+Rfvf63QZ4Nk+RLPU61IqOPas7FE4br5BcktXLr9+W848WOaC0R5Y02EL0xOjjDstQdwr1nO7cqSSb8G5z7EOz0Y3kBIlzpj6PR7s0FsJz+r04fGhqWQaqvTviZuo6Wfi2zdrouWcZH9jjfnGLSA52OQXb8sGl8DwiZOtphK4ZSxFjmQ2AaILXimC7/ct+MEKjQ+/TKL5T20co3vAnbO+coTVCd8tt5Gnq8I2W1uUtHEswknRTY4O/rZDa8LsEolnKyo5rKTYFoAaRjDDtZfqMuB3+N6Xlmb5QP+kWBDoeruy+ldUfX9hxWMOlZpF49AND2qyRiu6UuAPhXkVjUZJCJSdQaZyBdhvI/qPex2Wt MNIDRupE sp4o0jfvK2rWpJqcdFCfWkdnPvoe34AC1J+RF3h1Fi48onbpEm90OsxInUvHfGGGsDgmneUAgbIFD1LAzVimfAxRhtkgT+4uHf5pu0LkGyndBJ3ld6/l0e+pFgSYNRNbmvdt3wB3DG2b+ByivhIvCALzm8+wGgISOptiiYI4H/+2Om/NTBOm/JO3ANxcwGHNORiIPkjdcgAwDQCvg4noZ/4iQ6SrWneArJl5pMfF1aDUaTM0MhLJ/2FDxDJ12/J7nKNnVnQVurKUxwAdUUYcQEyXz4ZRvIN/F23BQ/9exfL92wIshSuIchoU2r+6kOVX/rYFjZEae4wyTpYgZCDhlcllWKKmwPOdxSILqQD25mmV9yCEZvuQOFsFKIA== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Add a hook for netfslib's write helpers to call to tell the network filesystem that it should update its i_size. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- include/linux/netfs.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/netfs.h b/include/linux/netfs.h index fce7a5a86e8e..a14af93efccf 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -245,6 +245,7 @@ struct netfs_request_ops { void (*free_request)(struct netfs_io_request *rreq); void (*free_subrequest)(struct netfs_io_subrequest *rreq); + /* Read request handling */ void (*expand_readahead)(struct netfs_io_request *rreq); bool (*clamp_length)(struct netfs_io_subrequest *subreq); void (*issue_read)(struct netfs_io_subrequest *subreq); @@ -252,6 +253,9 @@ struct netfs_request_ops { int (*check_write_begin)(struct file *file, loff_t pos, unsigned len, struct folio **foliop, void **_fsdata); void (*done)(struct netfs_io_request *rreq); + + /* Modification handling */ + void (*update_i_size)(struct inode *inode, loff_t i_size); }; /* From patchwork Wed Dec 13 15:23:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491227 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 25616C4332F for ; Wed, 13 Dec 2023 15:25:35 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id B512E8D002D; Wed, 13 Dec 2023 10:25:34 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id AAFE08D0015; Wed, 13 Dec 2023 10:25:34 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 94FEF8D002D; Wed, 13 Dec 2023 10:25:34 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id 811678D0015 for ; Wed, 13 Dec 2023 10:25:34 -0500 (EST) Received: from smtpin16.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id E7F33A0B77 for ; Wed, 13 Dec 2023 15:25:33 +0000 (UTC) X-FDA: 81562169346.16.9DB3D81 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf22.hostedemail.com (Postfix) with ESMTP id 3A91AC0010 for ; Wed, 13 Dec 2023 15:25:32 +0000 (UTC) Authentication-Results: imf22.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=T5Iu23sR; spf=pass (imf22.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481132; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=i1NCs1wijkp9oudHg0v3ZW2pY0xP/Retx1SxWP1fmpE=; b=kq5IlIf7qke0rw7nJhmcFdpcbJDegNnKo6AdlolGFE6iRi5BT0SI8fHosqhX7DQE9ckIGo OZtw3zOleS4++xp8eJOBL/nKqObZJklW5M0WMwYAk0pwhvFHbuKP+vyp2vlXTrCKY/2Fx/ F4Ylcug/IdUgYC19rlv+sxvrnD+WQjI= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481132; a=rsa-sha256; cv=none; b=l6h0hAuIAjCXeUF9AIA62nXnouBAGA3FB7S7FDzQNJMq403gYHUzMlGRcsCuTM3kt2MFgc gKerKn2mHKPzAKqL9s2KoMORrsklM4k3R/q8sJBbJO5wnIE1ERjpwXWfMT1B8MgOVuB1H/ 1H7H+QMcBIV0sBcpPXaub1pE9uuowLM= ARC-Authentication-Results: i=1; imf22.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=T5Iu23sR; spf=pass (imf22.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481131; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=i1NCs1wijkp9oudHg0v3ZW2pY0xP/Retx1SxWP1fmpE=; b=T5Iu23sRSw2qw3kT+WEg3WGh8S2q18LNpIO3DRRebp84UlJ7fM9dNK1lAMDTNMkoOxzyou 6DXQ3rNltfwV6NuXZhQGTDBaaurMSJl49WuK/RZCJK9agdQQLzK2RPsKuV+jKYUpfOjYql EyjgE9hUdlNIZ19V/1R+phK+miFupfo= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-510-SR5-99_mNgesTFIbAUuluQ-1; Wed, 13 Dec 2023 10:25:28 -0500 X-MC-Unique: SR5-99_mNgesTFIbAUuluQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id CEA853801F6E; Wed, 13 Dec 2023 15:25:25 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 174293C2F; Wed, 13 Dec 2023 15:25:21 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 21/39] netfs: Make netfs_put_request() handle a NULL pointer Date: Wed, 13 Dec 2023 15:23:31 +0000 Message-ID: <20231213152350.431591-22-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Rspamd-Queue-Id: 3A91AC0010 X-Rspam-User: X-Rspamd-Server: rspam11 X-Stat-Signature: epcxjqi3wk67q4rcym8aa95u546a6irm X-HE-Tag: 1702481132-47977 X-HE-Meta: U2FsdGVkX18qWALbjz1ucu7Brvc+kAtMVshLAB1XGj9MJD6YN+lkIztQarGsQrpr/zMntBztr1Oh5SG8E3jVltxQ38bOehnGU/gN3g4rLCP8tkAUkbOZnC1qzaFAMSbEkaaBZ2OKCVOsJEdPB2zKAxYSqH4mqEYRioDDRqDc/p+9qnYDMwU5ncIRuufZBu48j+QnOWbTxwwUyXQ99MsIclI/frcrQnXt+DodjuuZfxa+LuB5Ofdx40jfN/OFFpGFMALITF43jm9Y5krQJOezGdgJDpiH/7AFY9NZEGZThefWoMV+1eAocNPfYNIzFP2go8VqYck3gc+5dO3uVJNHn5ULeDSUYcGCQ7Z4IhKcFJZhe22yeK2xIiyTzG87hi4emTAfUkedY8RPf/3/AciOSx/0s/YVWItYwQUhCZF3vVTo7aSiNbMNI2oesXCVZH2xZwbNsccOlTnc3HmY1lcgJUVwXOvyZRek/WTrDmhi4zG9PZlMhSxcT9myqusqERbFrIm54ez13rHm8VDXjtGCQWjNndu10MpSL+rJse45qRDtNHc0es0FvWboB1Yw37ZTG8mSQt2shx4NyhCpKNMKikQPdTbe8qGaG+G5lR+2TcsI0jGimInxTMHjBLWu09Z0vItRzYN30GpGMzXp5PfNVrkCrAjpGdDQ5aB1IyK0qCGaw2hH3MkXHZVXqQkZzodUalER8+C1aU2GAlYVY7A5ryEH5UEEN5FSTwUqS/0ZNWOpqHZoLYgFqCNdqoTs8ylG137RgK6f50+azYBS8Md2eZgd3XhHl1cphW6Pskmmi1WE9+/bmPpZSdJc2liAzIfMMEQEMUe7iHj3hTIcBSgeLiMtJB0Zg2lb8zbI1jUfAiFFpYQo17iPH25KT0Guoj58a9maAwO6tVH/admOOK+ncsKFr0LesaNaUjCD40dYvshBeNisb/EznKlFcnrqLBa9WAL1NX3JSN6iprE/vuZ NPn7y/7u lUkDKS2LXsmOU6SbOi6KmDq3xQEF3wTLqYtYAKwojcyS//fmspi4LFoxlvze401fdj65bZeme5mOC3bVCICA0W6Jl8S/M0rlObaZDtH88k2noEaOnGLG0Ber5xXaYGhQt4ztkcAMPpl2wuRsXEt4q/aebo7I+Bir+Nwzd2+L2psFFEDsB6x6Irop6Z8HWKH2dPwuwBkp3VViIS0ztE5R7IhTVXkiCdhuPQsNtDY6bKVYLj6MnPggpS0Gezsp2PHXKxNd/3t1deJqCUHjxMjF1axTcLpAGvOrDtrppaoLd02uBgwLaiE4zT+bU0v/iWpvz//qRMFNzzd/lvhX0GbzvKHJ5MQ== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Make netfs_put_request() just return if given a NULL request pointer. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/objects.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 7ef804e8915c..3ce6313cc5f9 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -109,19 +109,22 @@ static void netfs_free_request(struct work_struct *work) void netfs_put_request(struct netfs_io_request *rreq, bool was_async, enum netfs_rreq_ref_trace what) { - unsigned int debug_id = rreq->debug_id; + unsigned int debug_id; bool dead; int r; - dead = __refcount_dec_and_test(&rreq->ref, &r); - trace_netfs_rreq_ref(debug_id, r - 1, what); - if (dead) { - if (was_async) { - rreq->work.func = netfs_free_request; - if (!queue_work(system_unbound_wq, &rreq->work)) - BUG(); - } else { - netfs_free_request(&rreq->work); + if (rreq) { + debug_id = rreq->debug_id; + dead = __refcount_dec_and_test(&rreq->ref, &r); + trace_netfs_rreq_ref(debug_id, r - 1, what); + if (dead) { + if (was_async) { + rreq->work.func = netfs_free_request; + if (!queue_work(system_unbound_wq, &rreq->work)) + BUG(); + } else { + netfs_free_request(&rreq->work); + } } } } From patchwork Wed Dec 13 15:23:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491228 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1DEF0C4332F for ; Wed, 13 Dec 2023 15:25:42 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id AB0BE8D002E; Wed, 13 Dec 2023 10:25:41 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id A60878D0015; Wed, 13 Dec 2023 10:25:41 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 8DA438D002E; Wed, 13 Dec 2023 10:25:41 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 794478D0015 for ; Wed, 13 Dec 2023 10:25:41 -0500 (EST) Received: from smtpin04.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 40D338022D for ; Wed, 13 Dec 2023 15:25:41 +0000 (UTC) X-FDA: 81562169682.04.09212C7 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf21.hostedemail.com (Postfix) with ESMTP id 5A1361C0016 for ; Wed, 13 Dec 2023 15:25:39 +0000 (UTC) Authentication-Results: imf21.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=GgXoWsAc; spf=pass (imf21.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481139; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=9CUqcQhkx342wCXCrXY79eb8GLJZvNRKMGt3t1k0yyQ=; b=zh8VUwOo8W/aQ71xvj3NjqQWzPXhkVsBaRKIJL+Knbr1zQBRWSpFrl2nCRVwCfWTWj9/ep BW2PdIPBpyvE2ITQMbGJL7Q7BDGJddBxoy+Wu9CSlcfjyS9aVwJ5WUd6b2bFFErNTNqnS3 KqQW2y/+PNTfic89T6z9UKAGIYj1G1g= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481139; a=rsa-sha256; cv=none; b=dDsT1HYSzRR+g5kQ6NJ2daEzQiUOd2bfmVCXg7FBa/t+Blg6HjWPC5Pd2hor4XY01OnfrG un+9gK8rlNt+9C/XFOTCdsVml92IRAqzsXrjyZRJy/VgPz9YcU9mEnHiZO3ARTLxh2vIpy 0UKIhDHWzf7jXtYFxtK68PurvR+gaK8= ARC-Authentication-Results: i=1; imf21.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=GgXoWsAc; spf=pass (imf21.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481138; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9CUqcQhkx342wCXCrXY79eb8GLJZvNRKMGt3t1k0yyQ=; b=GgXoWsAcYLOD2kiUO1GSAYHPdloZ0608Uf147ZnNlWG3Dk/OEjl9xk0KgFI6uhcL6F6DS9 yC2ZMi+kVgofu+wTNOtp0D+2op5LIfTryJkQ4fdF0UK9+a5vF6kTYZHIStyxKzh/8/JzuI d1Ohd75lofOkei3FrW5RxVsG2GYm8zY= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-283-eQU1o3hfOjiQzs7oWTcaHQ-1; Wed, 13 Dec 2023 10:25:35 -0500 X-MC-Unique: eQU1o3hfOjiQzs7oWTcaHQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 5C4DD3C2E0BA; Wed, 13 Dec 2023 15:25:29 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8FD7B112131D; Wed, 13 Dec 2023 15:25:26 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 22/39] netfs: Make the refcounting of netfs_begin_read() easier to use Date: Wed, 13 Dec 2023 15:23:32 +0000 Message-ID: <20231213152350.431591-23-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.3 X-Stat-Signature: wzpuizjaunuxchjiexaaidj6cbz16equ X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: 5A1361C0016 X-Rspam-User: X-HE-Tag: 1702481139-333651 X-HE-Meta: U2FsdGVkX1/9aSBHG4oUkp4NA0IJNkCEqTS0QPg8Jm4mvrYh8YassNS8FWAs+b+PkCkNkHSDsYV1zdnlv0QnJtt6iQ6KDNw9pdKw/cmkaUP+xUDqBByQhWE9YqD09Jo1Zky9hIme42tPiSYaNruEM5qlMaj9mZDqQyZjzBmdelIg7vuC8+KK2sPOxCMlEmqa2hl7ZtXhQOk38j1DP2qnv7Pm+LOBo666YfDOQdT2aqLqYue4L9XMWijI3LDeyMT98BYjT5cJ1/DstKHuYDBsuur5AK/58lnGrNqsGicc4sFg0bzYTaSx6FpzERMqEB3u9OdFMKRpxTB78LT+4VCoEWRdd07bnazA9+h5/0fs5fuFsyy5gkAXu5gIpk9ZX11X244GgeZQHEiGz2DAM9rPdKDW6E+u4jb3qbTmxG7cMIkeqVaGcr1faijWN82CGSJRGeBi4iODN8V0qzOvHH/eR/DRDH4eRbPGcYuM/AkeZuSn1OeQantoSZdYheG7A2qI5inZO3AeRk/dFVKwEPq8fkBif4j4lcBLqb2vtiKNGglv2QMx/xAyck2V4OLyYy54P4/MB3odgkIzRjdnuiPYRWt6RNUAGxr4urk9/YrPVEBIqhuHkRxmumpSPh6Q8kxmZRsXfoi7qIT7bOmqVkahISrh0kQsfUr43yLgwlSRh+w5YMQaTyK4DL6iFyK4dXOlKd78XcTfrpnkgYlxqoPQW2Bzjw7D0ztkA7YSAnyMq/30vbTv3R9jo9rk/MBF5ve58U8+7AL3kTtrHhlkpXKgd/PJpziDWpa9zV/iQJQsRkor80jTzMAa+VRaaBAAeHYvvH8O9ivRTUj8MsbAvo7QiDGBgraRN2GOvyLQaFw1bLG7jAFk4h6zPVsn3+vLzyASbccipUMgt9GHKpGH0MHDhP9cOYLb/4IWCC0CaSueckWe/751pbawjAf3rlx6/I37R1qLnBy9XkUSG7p/iSR kqTPImLX SF6O0Vmm6+R0l3CoKNx2HeOjOiBjgbS/5Q4Qdd63QaetF+0RmacY4R0Pr3CbpMwGoejojekKZxOHUOK5Fd8J3g3zEvqnl5GkECVpHav0VK3QeXj3hGkYyum8A5okUJKbrjjs/4MggvUi9ikARQaJmSzmC30vAIpkPMswEIVbsZH/rn3xs/mZahOpJPR6+C3vOUqFxwtkisZF2SbaqpUr8Bl2JxOG5IBAU3NUb2dlhRKvIGybayO6hGyOTPANCumK2VMyvhWmY3UYweWWno/Shm+sp/aTv+MFXqQ6MlL2UaN9qsR1TIkQdUu+89GqNB+rQr+pmpPK8Cq9hWDZmBbGmtnC1BtL1Ak5Px/Fg X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Make the refcounting of netfs_begin_read() easier to use by not eating the caller's ref on the netfs_io_request it's given. This makes it easier to use when we need to look in the request struct after. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/buffered_read.c | 6 +++++- fs/netfs/io.c | 28 +++++++++++++--------------- include/trace/events/netfs.h | 9 +++++---- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 751556faa70b..6b9a44cafbac 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -210,6 +210,7 @@ void netfs_readahead(struct readahead_control *ractl) ; netfs_begin_read(rreq, false); + netfs_put_request(rreq, false, netfs_rreq_trace_put_return); return; cleanup_free: @@ -260,7 +261,9 @@ int netfs_read_folio(struct file *file, struct folio *folio) iov_iter_xarray(&rreq->iter, ITER_DEST, &mapping->i_pages, rreq->start, rreq->len); - return netfs_begin_read(rreq, true); + ret = netfs_begin_read(rreq, true); + netfs_put_request(rreq, false, netfs_rreq_trace_put_return); + return ret; discard: netfs_put_request(rreq, false, netfs_rreq_trace_put_discard); @@ -429,6 +432,7 @@ int netfs_write_begin(struct netfs_inode *ctx, ret = netfs_begin_read(rreq, true); if (ret < 0) goto error; + netfs_put_request(rreq, false, netfs_rreq_trace_put_return); have_folio: ret = folio_wait_fscache_killable(folio); diff --git a/fs/netfs/io.c b/fs/netfs/io.c index c80b8eed1209..1795f8679be9 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -362,6 +362,7 @@ static void netfs_rreq_assess(struct netfs_io_request *rreq, bool was_async) netfs_rreq_unlock_folios(rreq); + trace_netfs_rreq(rreq, netfs_rreq_trace_wake_ip); clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &rreq->flags); wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS); @@ -657,7 +658,6 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) if (rreq->len == 0) { pr_err("Zero-sized read [R=%x]\n", rreq->debug_id); - netfs_put_request(rreq, false, netfs_rreq_trace_put_zero_len); return -EIO; } @@ -669,12 +669,10 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) 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. */ + netfs_get_request(rreq, netfs_rreq_trace_get_for_outstanding); atomic_set(&rreq->nr_outstanding, 1); io_iter = rreq->io_iter; do { @@ -684,25 +682,25 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) } 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. + /* 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. Note that this might start + * further work, such as writing to the cache. */ - for (;;) { - wait_var_event(&rreq->nr_outstanding, - atomic_read(&rreq->nr_outstanding) == 1); + wait_var_event(&rreq->nr_outstanding, + atomic_read(&rreq->nr_outstanding) == 1); + if (atomic_dec_and_test(&rreq->nr_outstanding)) netfs_rreq_assess(rreq, false); - if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) - break; - cond_resched(); - } + + trace_netfs_rreq(rreq, netfs_rreq_trace_wait_ip); + wait_on_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS, + TASK_UNINTERRUPTIBLE); ret = rreq->error; if (ret == 0 && rreq->submitted < rreq->len) { trace_netfs_failure(rreq, NULL, ret, netfs_fail_short_read); ret = -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)) diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 4ea4e34d279f..6daadf2aac8a 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -34,7 +34,9 @@ EM(netfs_rreq_trace_free, "FREE ") \ EM(netfs_rreq_trace_resubmit, "RESUBMT") \ EM(netfs_rreq_trace_unlock, "UNLOCK ") \ - E_(netfs_rreq_trace_unmark, "UNMARK ") + EM(netfs_rreq_trace_unmark, "UNMARK ") \ + EM(netfs_rreq_trace_wait_ip, "WAIT-IP") \ + E_(netfs_rreq_trace_wake_ip, "WAKE-IP") #define netfs_sreq_sources \ EM(NETFS_FILL_WITH_ZEROES, "ZERO") \ @@ -65,14 +67,13 @@ E_(netfs_fail_prepare_write, "prep-write") #define netfs_rreq_ref_traces \ - EM(netfs_rreq_trace_get_hold, "GET HOLD ") \ + EM(netfs_rreq_trace_get_for_outstanding,"GET OUTSTND") \ 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_return, "PUT RETURN ") \ EM(netfs_rreq_trace_put_subreq, "PUT SUBREQ ") \ - EM(netfs_rreq_trace_put_zero_len, "PUT ZEROLEN") \ E_(netfs_rreq_trace_new, "NEW ") #define netfs_sreq_ref_traces \ From patchwork Wed Dec 13 15:23:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491229 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id B3863C4167D for ; Wed, 13 Dec 2023 15:25:43 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 46EA58D002F; Wed, 13 Dec 2023 10:25:42 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 420818D0015; Wed, 13 Dec 2023 10:25:42 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 24B328D002F; Wed, 13 Dec 2023 10:25:42 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id 1121A8D0015 for ; Wed, 13 Dec 2023 10:25:42 -0500 (EST) Received: from smtpin21.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id DAC2980531 for ; Wed, 13 Dec 2023 15:25:41 +0000 (UTC) X-FDA: 81562169682.21.CCED5D1 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf19.hostedemail.com (Postfix) with ESMTP id 199D11A001E for ; Wed, 13 Dec 2023 15:25:39 +0000 (UTC) Authentication-Results: imf19.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=Cxz7YL5v; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf19.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481140; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=/P39zA4P9i416f7rYVx3fltLx7nFHwqFVafrmIB+g6A=; b=7T0HnBW61ZhgazK2/T4puyXqlb9LAg95wiMnrTJMhZ9/Z4LYqxtulUwhG9Rv1r1F5KbYzW 1yMXTeUnAkRynwKCrl2VAHSmZrBNLQmmqFmduPil7LiH46HIS81h2f0bCAgBadTpDRFWY3 urUD71JM3dY5FZdcGjc8zMEOrZ9Ur20= ARC-Authentication-Results: i=1; imf19.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=Cxz7YL5v; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf19.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481140; a=rsa-sha256; cv=none; b=2nCKJNzgVWccJ/xmz4VjE7YiZLrZojGTFErt3lJ83/WHwjL9RPF0g94ajT0e/QkXVgJpPA NElCoBjKa53lcQtgWYMjtzh0LME9n9kx6TALgK0JwxgIYcAhSY7PglvelLtQYxBVi8VcxC HTYLEY6rGqxWXDmRD9w+hl+oVwsi80I= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481138; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/P39zA4P9i416f7rYVx3fltLx7nFHwqFVafrmIB+g6A=; b=Cxz7YL5v7z0UnQQ2JX/RthdXPKtU4cirSVn2trfirRzIcqJ3T3jUEgA8WJ7M7R46Yf9NKh WdBrKB14wz/j81Iquffg/YO1yDugYMHd1zavt42ZGDnG5v133NXe+l+FI/k75QzOJ075yv Ywr764MCuwhlpeHjvanEfoqenqu4NgI= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-16-M56nMa6TPRejKwmGXDGC8A-1; Wed, 13 Dec 2023 10:25:36 -0500 X-MC-Unique: M56nMa6TPRejKwmGXDGC8A-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6F1BE8828D5; Wed, 13 Dec 2023 15:25:33 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 36718492BE6; Wed, 13 Dec 2023 15:25:30 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 23/39] netfs: Prep to use folio->private for write grouping and streaming write Date: Wed, 13 Dec 2023 15:23:33 +0000 Message-ID: <20231213152350.431591-24-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.10 X-Rspamd-Queue-Id: 199D11A001E X-Rspam-User: X-Rspamd-Server: rspam02 X-Stat-Signature: xnww8pny6a6qhnnkr548xf6gx9rgt753 X-HE-Tag: 1702481139-923670 X-HE-Meta: U2FsdGVkX188mmb77Uuum+KgzOFZTFUN+pUfcYqgkWJBFjQldtS/e6Llqa+i2Yi2fSb/UXOie1AwrjX/tO+ueb+GYEHfPdlp7twZi4KaiQ8L2a5XhoHyyFG64jvCYFwc4EV10hZFftJg8hR9mPWV49eWYr9J1oww4URgBqm56JVWf7zRdCvGSpleTfx+LGlbFNzfZVT1FvplRPqlHXhyWt6grBJfmmYs3tVOsWbCdMXSnupGeWDXCxRJNJSFzc9FvRY2f+cnSRHk3HPhuqf5sX34fH0YOcfIg7OohsWYJ+3sbNcaKT4/Vjk6MYjLfrhJCMFwRZCox6CJsTNAml2GHFnuTcHJXcdKhJRN3Y6MeodiS5XU7gnRXE+qLXRLPWnHIg/7RrwPiroC+hydyjru2mfk/nBCSdZWqOY0XyEx1hGi4kh7lbwC/j1m5PdLo4olfSJ/3IQrOWn2yckg5I5IwKvw+acuTmhJUzgtmiJvtJUEuFAiGJeSH8cOIM+ChCbHWrjKkC6P+ENOc2hCHqpeqg8RbECOEsOLD6QnYJDIyBSc7WxR6H9+plrYS7OiK3kDAondlcSMQewLUkQuONfkutgwLj80v16nQzgMWgfXesnys/wujPEpznKXKZ9GdZldMO2oC0sB0GCrcPS4nRghLZc3RDloyoTpcrkTTlmN2M3iiQXaHqaX75qUDrcHaMeIEidrlr/MDtXRgST0My0u+S3FvaV2TV557cj19sBas+JhbHbmCCdDfIdYngJmemDp93rP+ZfbURpHq10lwoYAEMrlE+KiprVUkPzZ5K4bCFsGCXWoMMe+TswMiZCp0w7mJQLrpvHr5KyRaMhhrmaL91ezuuqLIJjNoldRcOnkyyKyh01iinTDLneyZTA+HMdrsOlCifAfuRIx13GY/GYJZRVFBM8pNgfyF4gF0UktO7ZxnGsid0L71LG931OLJAaQrcdJ4hH6WthLbIYueRp 7ZN6ON40 965a7j1UXnFnIrmtgoWQlRNS7qGWzcTfOCQ5aU7C23D3Q2ewcF7m583uMtpTWCQjBQHPqPuFbSFdJWpFJLCtK/qcBNXKjQdBOKYfhWFFMtpAtRr1el5k4+EhLR1x16XSSJIXlSUXRPEmokIVNyz4ocq1e+h07GhYhj0XlPBmXKowpte2VnA41DRjmFsHhi54CkLgk7RxldGs33mzhWTZicp4WMYzKpVSUiBiU/VGI/I/wtaxh/X1+ac0VY8iVPWrUCFjsrtFtxUCmchH+VPPld9hXeRUpDB5ZWLlH9Wag4xmlxCY= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Prepare to use folio->private to hold information write grouping and streaming write. These are implemented in the same commit as they both make use of folio->private and will be both checked at the same time in several places. "Write grouping" involves ordering the writeback of groups of writes, such as is needed for ceph snaps. A group is represented by a filesystem-supplied object which must contain a netfs_group struct. This contains just a refcount and a pointer to a destructor. "Streaming write" is the storage of data in folios that are marked dirty, but not uptodate, to avoid unnecessary reads of data. This is represented by a netfs_folio struct. This contains the offset and length of the modified region plus the otherwise displaced write grouping pointer. The way folio->private is multiplexed is: (1) If private is NULL then neither is in operation on a dirty folio. (2) If private is set, with bit 0 clear, then this points to a group. (3) If private is set, with bit 0 set, then this points to a netfs_folio struct (with bit 0 AND'ed out). Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/internal.h | 28 ++++++++++++++++++++++++++ fs/netfs/misc.c | 46 +++++++++++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 41 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 8d1bfc9c3e2f..1b83c534593a 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -149,6 +149,34 @@ static inline bool netfs_is_cache_enabled(struct netfs_inode *ctx) #endif } +/* + * Get a ref on a netfs group attached to a dirty page (e.g. a ceph snap). + */ +static inline struct netfs_group *netfs_get_group(struct netfs_group *netfs_group) +{ + if (netfs_group) + refcount_inc(&netfs_group->ref); + return netfs_group; +} + +/* + * Dispose of a netfs group attached to a dirty page (e.g. a ceph snap). + */ +static inline void netfs_put_group(struct netfs_group *netfs_group) +{ + if (netfs_group && refcount_dec_and_test(&netfs_group->ref)) + netfs_group->free(netfs_group); +} + +/* + * Dispose of a netfs group attached to a dirty page (e.g. a ceph snap). + */ +static inline void netfs_put_group_many(struct netfs_group *netfs_group, int nr) +{ + if (netfs_group && refcount_sub_and_test(nr, &netfs_group->ref)) + netfs_group->free(netfs_group); +} + /* * fscache-cache.c */ diff --git a/fs/netfs/misc.c b/fs/netfs/misc.c index 96014c3d1683..40421ced4cd3 100644 --- a/fs/netfs/misc.c +++ b/fs/netfs/misc.c @@ -177,9 +177,55 @@ EXPORT_SYMBOL(netfs_clear_inode_writeback); */ void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length) { + struct netfs_folio *finfo = NULL; + size_t flen = folio_size(folio); + _enter("{%lx},%zx,%zx", folio_index(folio), offset, length); folio_wait_fscache(folio); + + if (!folio_test_private(folio)) + return; + + finfo = netfs_folio_info(folio); + + if (offset == 0 && length >= flen) + goto erase_completely; + + if (finfo) { + /* We have a partially uptodate page from a streaming write. */ + unsigned int fstart = finfo->dirty_offset; + unsigned int fend = fstart + finfo->dirty_len; + unsigned int end = offset + length; + + if (offset >= fend) + return; + if (end <= fstart) + return; + if (offset <= fstart && end >= fend) + goto erase_completely; + if (offset <= fstart && end > fstart) + goto reduce_len; + if (offset > fstart && end >= fend) + goto move_start; + /* A partial write was split. The caller has already zeroed + * it, so just absorb the hole. + */ + } + return; + +erase_completely: + netfs_put_group(netfs_folio_group(folio)); + folio_detach_private(folio); + folio_clear_uptodate(folio); + kfree(finfo); + return; +reduce_len: + finfo->dirty_len = offset + length - finfo->dirty_offset; + return; +move_start: + finfo->dirty_len -= offset - finfo->dirty_offset; + finfo->dirty_offset = offset; } EXPORT_SYMBOL(netfs_invalidate_folio); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index a14af93efccf..2406e11b41bd 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -140,6 +140,47 @@ struct netfs_inode { #define NETFS_ICTX_ODIRECT 0 /* The file has DIO in progress */ }; +/* + * A netfs group - for instance a ceph snap. This is marked on dirty pages and + * pages marked with a group must be flushed before they can be written under + * the domain of another group. + */ +struct netfs_group { + refcount_t ref; + void (*free)(struct netfs_group *netfs_group); +}; + +/* + * Information about a dirty page (attached only if necessary). + * folio->private + */ +struct netfs_folio { + struct netfs_group *netfs_group; /* Filesystem's grouping marker (or NULL). */ + unsigned int dirty_offset; /* Write-streaming dirty data offset */ + unsigned int dirty_len; /* Write-streaming dirty data length */ +}; +#define NETFS_FOLIO_INFO 0x1UL /* OR'd with folio->private. */ + +static inline struct netfs_folio *netfs_folio_info(struct folio *folio) +{ + void *priv = folio_get_private(folio); + + if ((unsigned long)priv & NETFS_FOLIO_INFO) + return (struct netfs_folio *)((unsigned long)priv & ~NETFS_FOLIO_INFO); + return NULL; +} + +static inline struct netfs_group *netfs_folio_group(struct folio *folio) +{ + struct netfs_folio *finfo; + void *priv = folio_get_private(folio); + + finfo = netfs_folio_info(folio); + if (finfo) + return finfo->netfs_group; + return priv; +} + /* * Resources required to do operations on a cache. */ From patchwork Wed Dec 13 15:23:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491230 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 34916C4332F for ; Wed, 13 Dec 2023 15:25:50 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id C36EC8D0030; Wed, 13 Dec 2023 10:25:49 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id BE6FF8D0015; Wed, 13 Dec 2023 10:25:49 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id A156E8D0030; Wed, 13 Dec 2023 10:25:49 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 8C42C8D0015 for ; Wed, 13 Dec 2023 10:25:49 -0500 (EST) Received: from smtpin05.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 7383CC01E2 for ; Wed, 13 Dec 2023 15:25:46 +0000 (UTC) X-FDA: 81562169892.05.3811CD8 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf03.hostedemail.com (Postfix) with ESMTP id 94FA62000D for ; Wed, 13 Dec 2023 15:25:44 +0000 (UTC) Authentication-Results: imf03.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=fzbEi90U; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf03.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481144; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=mTfmcNPb0gO1dPN+fv6cw9EjGqJBYpwlxH/Goq7Tcsg=; b=5H/6bo4R/etxEvj/l+8M+zPRV6tGnfWQdEctWhsSdMpXTOWTawq3xaBh8xk8f3WUGUqyFN Q6JG7BfgzrbGbB4TZetruEOHlnbQdZykq0aj7k6GZHf+dX5/r6+vxnNaBisj3iqeVK+/6Y EmUzlPEvg/Rh4clQxgov/9eTZVYTWHg= ARC-Authentication-Results: i=1; imf03.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=fzbEi90U; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf03.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481144; a=rsa-sha256; cv=none; b=O6TqQIGv0G+QEL9QRutaEsVWNFWlETMi1gZwSAGCceSuZZFE0tM+F0UzYT+2tjvJO/A7nC RNHAlKnB7+KsuDJzM2V5ydu+FiI7c2/cSyK/srLqBNojvbYUtwaJHbtIKghfyci5DONKpt YG9SpPCjfB/Zd9qwVUJgzZAZXHjRF7g= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481143; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=mTfmcNPb0gO1dPN+fv6cw9EjGqJBYpwlxH/Goq7Tcsg=; b=fzbEi90UvuO6wzpzEyQiM+qjphsD8O0LJ5cw1fX1C22PlrVlxDv++6l9gkT6v2EyKfQrgd iLvei2E5b8cf3Ey77NLwOC4eG5115KD98x7mysXUtP5EXqhAQC+VWkRo45znO55fWOH12j IIeGocmPrnJsSyDA7Tjz7UpeTQ72yzw= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-677-0voZJWsMPjGkJFjCSOYEhQ-1; Wed, 13 Dec 2023 10:25:38 -0500 X-MC-Unique: 0voZJWsMPjGkJFjCSOYEhQ-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3FBC9101A52A; Wed, 13 Dec 2023 15:25:37 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 33F1C492BC6; Wed, 13 Dec 2023 15:25:34 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 24/39] netfs: Dispatch write requests to process a writeback slice Date: Wed, 13 Dec 2023 15:23:34 +0000 Message-ID: <20231213152350.431591-25-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.9 X-Rspam-User: X-Stat-Signature: whwh9o6krdum4k1n9ez8pxfuxetxxdir X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: 94FA62000D X-HE-Tag: 1702481144-429847 X-HE-Meta: U2FsdGVkX1+Ph/4y2kN/J/dOlF3ezcz2k+H+wHi8DLoeYosnQzIzglMr7fruLQGs5rIGLW6Kw2luL4CUIioaBVcykjegDhCAJ2d95rocdQF6taLXr6XDCd9BROn0/rNXpUP47aOe9YJKp5ts+NxO0iAnYFpKf+adoxN1F69um8QOz/trxSZhnHAOEoMB7xcPooubhEAWN/WCe++uBic0N2nKt5xooNS8m72gPymlzLd/koucHIE2eMcaShJmnKVs+s1lfnZfEAImxdL8tAf5GRZEBc6zgCG45ByTm3hoVPYgL1czFhN2eRdPI9l0Km1afoUtQ9GkAs8t5NaAvezZvXMKR7j1+wBNVSkxTKyxcYbIaubGF46NFgm5ZGFw1RhMqxXxxNzYdYy3TXhBPwgi/UOKnE8r3myu2w6D8bA2wbr4C++8LHi4smTRf3fBKVOWV+0261c4dl9F7hXx2ujHidAYHzA43Q/zX0Pm7YW6RtSCRsuJyhot6mpP/t26Lbule/9AbWBk5XzbeKC9+S8oV4XGVeMbGCRAFkrPYblkjJCFfdCORIOw2Vwa3f75AerjeMXDl1+k7OcPUCpcHg457/0ZGj8g9rtzvMOLeSXWz1zanhqaL7/xLNjA+SGtBWnhJIQnJuKaelElNFw4pQoQFMD1s36s6WTua8yfu5JFQNX+GJYS+XGiG677ridN/mcMfWUajn7ghnC1+a1mP/PcGFc2UvpD96xyDUtbrf45Il9EyktYIKPHXwhzickV0eXP4H1EX2sYxyNZdXP1WKms7dOuJNhsgIu9G/qiP+qLj5ub4MmCPVqafDI0EUDn55TmFqxmKM8pLSnfr3uRFYvL+DplJF5FwFrMe/m0mvXKbdrMXdJ1JmTf6k47HRVL2fIAD5c400/vEqMK33AsJ1Tl60Vwz3c0Hzej39fTCX0KcXL5ubA2+fYiZIHE7IAkw82DJztewFHaQNic1bRuZan JC+JFIeN 4HP5EAu1XSsCPpRu5Ty9AjKBGAwLBzhWJd/HLCse9elgTiEbS5W0Q8VcIHYxg0OFvlRZybIdy6JTPG8soG4YAflk0qfDGOf/ZFmy5j1f5mxWmyVw2IsB8wXPSpOrPUHwsZKAPMpHcLCe4XLZfkGMZW4atlRjxShkXVqOXuOEA3FYWIhUGZbvKm7x9S3NfT7UPAwq5uqDIDIH4o0syriuZRJOKRvNMdwTdC2XOFLHgZsqquKzgPbZVL1D/CDWg85TzZ3/Xiu3E6q2VVdTyVByunMblKI2+4RcfZC3mYR1G+liegsv6Xuw8T3OzhVGoakBElzc+ X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Dispatch one or more write reqeusts to process a writeback slice, where a slice is tailored more to logical block divisions within the file (such as crypto blocks, an object layout or cache granules) than the protocol RPC maximum capacity. The dispatch doesn't happen until throttling allows, at which point the entire writeback slice is processed and queued. A slice may be written to multiple destinations (one or more servers and the local cache) and the writes to each destination might be split up along different lines. The writeback slice holds the required folios pinned. An iov_iter is provided in netfs_write_request that describes the buffer to be used. This may be part of the pagecache, may have auxiliary padding pages attached or may be a bounce buffer resulting from crypto or compression. Consequently, the filesystem must not twiddle the folio markings directly. The following API is available to the filesystem: (1) The ->create_write_requests() method is called to ask the filesystem to create the requests it needs. This is passed the writeback slice to be processed. (2) The filesystem should then call netfs_create_write_request() to create the requests it needs. (3) Once a request is initialised, netfs_queue_write_request() can be called to dispatch it asynchronously, if not completed immediately. (4) netfs_write_request_completed() should be called to note the completion of a request. (5) netfs_get_write_request() and netfs_put_write_request() are provided to refcount a request. These take constants from the netfs_wreq_trace enum for logging into ftrace. (6) The ->free_write_request is method is called to ask the filesystem to clean up a request. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/Makefile | 3 +- fs/netfs/internal.h | 6 + fs/netfs/output.c | 363 +++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 13 ++ include/trace/events/netfs.h | 50 ++++- 5 files changed, 432 insertions(+), 3 deletions(-) create mode 100644 fs/netfs/output.c diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index cf3fc847b8ac..c69c6775b8ac 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -7,7 +7,8 @@ netfs-y := \ locking.o \ main.o \ misc.o \ - objects.o + objects.o \ + output.o netfs-$(CONFIG_NETFS_STATS) += stats.o diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 1b83c534593a..a71fc21fc4ad 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -88,6 +88,12 @@ static inline void netfs_see_request(struct netfs_io_request *rreq, trace_netfs_rreq_ref(rreq->debug_id, refcount_read(&rreq->ref), what); } +/* + * output.c + */ +int netfs_begin_write(struct netfs_io_request *wreq, bool may_wait, + enum netfs_write_trace what); + /* * stats.c */ diff --git a/fs/netfs/output.c b/fs/netfs/output.c new file mode 100644 index 000000000000..2ad0fd8c32be --- /dev/null +++ b/fs/netfs/output.c @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Network filesystem high-level write support. + * + * Copyright (C) 2023 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include +#include +#include +#include +#include +#include +#include "internal.h" + +/** + * netfs_create_write_request - Create a write operation. + * @wreq: The write request this is storing from. + * @dest: The destination type + * @start: Start of the region this write will modify + * @len: Length of the modification + * @worker: The worker function to handle the write(s) + * + * Allocate a write operation, set it up and add it to the list on a write + * request. + */ +struct netfs_io_subrequest *netfs_create_write_request(struct netfs_io_request *wreq, + enum netfs_io_source dest, + loff_t start, size_t len, + work_func_t worker) +{ + struct netfs_io_subrequest *subreq; + + subreq = netfs_alloc_subrequest(wreq); + if (subreq) { + INIT_WORK(&subreq->work, worker); + subreq->source = dest; + subreq->start = start; + subreq->len = len; + subreq->debug_index = wreq->subreq_counter++; + + switch (subreq->source) { + case NETFS_UPLOAD_TO_SERVER: + netfs_stat(&netfs_n_wh_upload); + break; + case NETFS_WRITE_TO_CACHE: + netfs_stat(&netfs_n_wh_write); + break; + default: + BUG(); + } + + subreq->io_iter = wreq->io_iter; + iov_iter_advance(&subreq->io_iter, subreq->start - wreq->start); + iov_iter_truncate(&subreq->io_iter, subreq->len); + + trace_netfs_sreq_ref(wreq->debug_id, subreq->debug_index, + refcount_read(&subreq->ref), + netfs_sreq_trace_new); + atomic_inc(&wreq->nr_outstanding); + list_add_tail(&subreq->rreq_link, &wreq->subrequests); + trace_netfs_sreq(subreq, netfs_sreq_trace_prepare); + } + + return subreq; +} +EXPORT_SYMBOL(netfs_create_write_request); + +/* + * Process a completed write request once all the component operations have + * been completed. + */ +static void netfs_write_terminated(struct netfs_io_request *wreq, bool was_async) +{ + struct netfs_io_subrequest *subreq; + struct netfs_inode *ctx = netfs_inode(wreq->inode); + + _enter("R=%x[]", wreq->debug_id); + + trace_netfs_rreq(wreq, netfs_rreq_trace_write_done); + + list_for_each_entry(subreq, &wreq->subrequests, rreq_link) { + if (!subreq->error) + continue; + switch (subreq->source) { + case NETFS_UPLOAD_TO_SERVER: + /* Depending on the type of failure, this may prevent + * writeback completion unless we're in disconnected + * mode. + */ + if (!wreq->error) + wreq->error = subreq->error; + break; + + case NETFS_WRITE_TO_CACHE: + /* Failure doesn't prevent writeback completion unless + * we're in disconnected mode. + */ + if (subreq->error != -ENOBUFS) + ctx->ops->invalidate_cache(wreq); + break; + + default: + WARN_ON_ONCE(1); + if (!wreq->error) + wreq->error = -EIO; + return; + } + } + + wreq->cleanup(wreq); + + _debug("finished"); + trace_netfs_rreq(wreq, netfs_rreq_trace_wake_ip); + clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &wreq->flags); + wake_up_bit(&wreq->flags, NETFS_RREQ_IN_PROGRESS); + + netfs_clear_subrequests(wreq, was_async); + netfs_put_request(wreq, was_async, netfs_rreq_trace_put_complete); +} + +/* + * Deal with the completion of writing the data to the cache. + */ +void netfs_write_subrequest_terminated(void *_op, ssize_t transferred_or_error, + bool was_async) +{ + struct netfs_io_subrequest *subreq = _op; + struct netfs_io_request *wreq = subreq->rreq; + unsigned int u; + + _enter("%x[%x] %zd", wreq->debug_id, subreq->debug_index, transferred_or_error); + + switch (subreq->source) { + case NETFS_UPLOAD_TO_SERVER: + netfs_stat(&netfs_n_wh_upload_done); + break; + case NETFS_WRITE_TO_CACHE: + netfs_stat(&netfs_n_wh_write_done); + break; + case NETFS_INVALID_WRITE: + break; + default: + BUG(); + } + + if (IS_ERR_VALUE(transferred_or_error)) { + subreq->error = transferred_or_error; + trace_netfs_failure(wreq, subreq, transferred_or_error, + netfs_fail_write); + goto failed; + } + + if (WARN(transferred_or_error > subreq->len - subreq->transferred, + "Subreq excess write: R%x[%x] %zd > %zu - %zu", + wreq->debug_id, subreq->debug_index, + transferred_or_error, subreq->len, subreq->transferred)) + transferred_or_error = subreq->len - subreq->transferred; + + subreq->error = 0; + subreq->transferred += transferred_or_error; + + if (iov_iter_count(&subreq->io_iter) != subreq->len - subreq->transferred) + pr_warn("R=%08x[%u] ITER POST-MISMATCH %zx != %zx-%zx %x\n", + wreq->debug_id, subreq->debug_index, + iov_iter_count(&subreq->io_iter), subreq->len, + subreq->transferred, subreq->io_iter.iter_type); + + if (subreq->transferred < subreq->len) + goto incomplete; + + __clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags); +out: + trace_netfs_sreq(subreq, netfs_sreq_trace_terminated); + + /* If we decrement nr_outstanding to 0, the ref belongs to us. */ + u = atomic_dec_return(&wreq->nr_outstanding); + if (u == 0) + netfs_write_terminated(wreq, was_async); + else if (u == 1) + wake_up_var(&wreq->nr_outstanding); + + netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated); + return; + +incomplete: + if (transferred_or_error == 0) { + if (__test_and_set_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags)) { + subreq->error = -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, &wreq->flags); + goto out; + +failed: + switch (subreq->source) { + case NETFS_WRITE_TO_CACHE: + netfs_stat(&netfs_n_wh_write_failed); + set_bit(NETFS_RREQ_INCOMPLETE_IO, &wreq->flags); + break; + case NETFS_UPLOAD_TO_SERVER: + netfs_stat(&netfs_n_wh_upload_failed); + set_bit(NETFS_RREQ_FAILED, &wreq->flags); + wreq->error = subreq->error; + break; + default: + break; + } + goto out; +} +EXPORT_SYMBOL(netfs_write_subrequest_terminated); + +static void netfs_write_to_cache_op(struct netfs_io_subrequest *subreq) +{ + struct netfs_io_request *wreq = subreq->rreq; + struct netfs_cache_resources *cres = &wreq->cache_resources; + + trace_netfs_sreq(subreq, netfs_sreq_trace_submit); + + cres->ops->write(cres, subreq->start, &subreq->io_iter, + netfs_write_subrequest_terminated, subreq); +} + +static void netfs_write_to_cache_op_worker(struct work_struct *work) +{ + struct netfs_io_subrequest *subreq = + container_of(work, struct netfs_io_subrequest, work); + + netfs_write_to_cache_op(subreq); +} + +/** + * netfs_queue_write_request - Queue a write request for attention + * @subreq: The write request to be queued + * + * Queue the specified write request for processing by a worker thread. We + * pass the caller's ref on the request to the worker thread. + */ +void netfs_queue_write_request(struct netfs_io_subrequest *subreq) +{ + if (!queue_work(system_unbound_wq, &subreq->work)) + netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_wip); +} +EXPORT_SYMBOL(netfs_queue_write_request); + +/* + * Set up a op for writing to the cache. + */ +static void netfs_set_up_write_to_cache(struct netfs_io_request *wreq) +{ + struct netfs_cache_resources *cres; + struct netfs_io_subrequest *subreq; + struct netfs_inode *ctx = netfs_inode(wreq->inode); + struct fscache_cookie *cookie = netfs_i_cookie(ctx); + loff_t start = wreq->start; + size_t len = wreq->len; + int ret; + + if (!fscache_cookie_enabled(cookie)) { + clear_bit(NETFS_RREQ_WRITE_TO_CACHE, &wreq->flags); + return; + } + + _debug("write to cache"); + subreq = netfs_create_write_request(wreq, NETFS_WRITE_TO_CACHE, start, len, + netfs_write_to_cache_op_worker); + if (!subreq) + return; + + cres = &wreq->cache_resources; + ret = fscache_begin_read_operation(cres, cookie); + if (ret < 0) { + netfs_write_subrequest_terminated(subreq, ret, false); + return; + } + + ret = cres->ops->prepare_write(cres, &start, &len, i_size_read(wreq->inode), + true); + if (ret < 0) { + netfs_write_subrequest_terminated(subreq, ret, false); + return; + } + + netfs_queue_write_request(subreq); +} + +/* + * Begin the process of writing out a chunk of data. + * + * We are given a write request that holds a series of dirty regions and + * (partially) covers a sequence of folios, all of which are present. The + * pages must have been marked as writeback as appropriate. + * + * We need to perform the following steps: + * + * (1) If encrypting, create an output buffer and encrypt each block of the + * data into it, otherwise the output buffer will point to the original + * folios. + * + * (2) If the data is to be cached, set up a write op for the entire output + * buffer to the cache, if the cache wants to accept it. + * + * (3) If the data is to be uploaded (ie. not merely cached): + * + * (a) If the data is to be compressed, create a compression buffer and + * compress the data into it. + * + * (b) For each destination we want to upload to, set up write ops to write + * to that destination. We may need multiple writes if the data is not + * contiguous or the span exceeds wsize for a server. + */ +int netfs_begin_write(struct netfs_io_request *wreq, bool may_wait, + enum netfs_write_trace what) +{ + struct netfs_inode *ctx = netfs_inode(wreq->inode); + + _enter("R=%x %llx-%llx f=%lx", + wreq->debug_id, wreq->start, wreq->start + wreq->len - 1, + wreq->flags); + + trace_netfs_write(wreq, what); + if (wreq->len == 0 || wreq->iter.count == 0) { + pr_err("Zero-sized write [R=%x]\n", wreq->debug_id); + return -EIO; + } + + wreq->io_iter = wreq->iter; + + /* ->outstanding > 0 carries a ref */ + netfs_get_request(wreq, netfs_rreq_trace_get_for_outstanding); + atomic_set(&wreq->nr_outstanding, 1); + + /* Start the encryption/compression going. We can do that in the + * background whilst we generate a list of write ops that we want to + * perform. + */ + // TODO: Encrypt or compress the region as appropriate + + /* We need to write all of the region to the cache */ + if (test_bit(NETFS_RREQ_WRITE_TO_CACHE, &wreq->flags)) + netfs_set_up_write_to_cache(wreq); + + /* However, we don't necessarily write all of the region to the server. + * Caching of reads is being managed this way also. + */ + if (test_bit(NETFS_RREQ_UPLOAD_TO_SERVER, &wreq->flags)) + ctx->ops->create_write_requests(wreq, wreq->start, wreq->len); + + if (atomic_dec_and_test(&wreq->nr_outstanding)) + netfs_write_terminated(wreq, false); + + if (!may_wait) + return -EIOCBQUEUED; + + wait_on_bit(&wreq->flags, NETFS_RREQ_IN_PROGRESS, + TASK_UNINTERRUPTIBLE); + return wreq->error; +} diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 2406e11b41bd..143374a77e84 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -251,6 +251,7 @@ struct netfs_io_request { __counted_by(direct_bv_count); unsigned int direct_bv_count; /* Number of elements in direct_bv[] */ unsigned int debug_id; + unsigned int wsize; /* Maximum write size (0 for none) */ unsigned int subreq_counter; /* Next subreq->debug_index */ atomic_t nr_outstanding; /* Number of ops in progress */ atomic_t nr_copy_ops; /* Number of copy-to-cache ops in progress */ @@ -274,6 +275,7 @@ struct netfs_io_request { #define NETFS_RREQ_WRITE_TO_CACHE 7 /* Need to write to the cache */ #define NETFS_RREQ_UPLOAD_TO_SERVER 8 /* Need to write to the server */ const struct netfs_request_ops *netfs_ops; + void (*cleanup)(struct netfs_io_request *req); }; /* @@ -297,6 +299,11 @@ struct netfs_request_ops { /* Modification handling */ void (*update_i_size)(struct inode *inode, loff_t i_size); + + /* Write request handling */ + void (*create_write_requests)(struct netfs_io_request *wreq, + loff_t start, size_t len); + void (*invalidate_cache)(struct netfs_io_request *wreq); }; /* @@ -385,6 +392,12 @@ ssize_t netfs_extract_user_iter(struct iov_iter *orig, size_t orig_len, iov_iter_extraction_t extraction_flags); size_t netfs_limit_iter(const struct iov_iter *iter, size_t start_offset, size_t max_size, size_t max_segs); +struct netfs_io_subrequest *netfs_create_write_request( + struct netfs_io_request *wreq, enum netfs_io_source dest, + loff_t start, size_t len, work_func_t worker); +void netfs_write_subrequest_terminated(void *_op, ssize_t transferred_or_error, + bool was_async); +void netfs_queue_write_request(struct netfs_io_subrequest *subreq); int netfs_start_io_read(struct inode *inode); void netfs_end_io_read(struct inode *inode); diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 6daadf2aac8a..e03635172760 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") +#define netfs_write_traces \ + EM(netfs_write_trace_dio_write, "DIO-WRITE") \ + EM(netfs_write_trace_unbuffered_write, "UNB-WRITE") \ + E_(netfs_write_trace_writeback, "WRITEBACK") + #define netfs_rreq_origins \ EM(NETFS_READAHEAD, "RA") \ EM(NETFS_READPAGE, "RP") \ @@ -32,11 +37,13 @@ EM(netfs_rreq_trace_copy, "COPY ") \ EM(netfs_rreq_trace_done, "DONE ") \ EM(netfs_rreq_trace_free, "FREE ") \ + EM(netfs_rreq_trace_redirty, "REDIRTY") \ EM(netfs_rreq_trace_resubmit, "RESUBMT") \ EM(netfs_rreq_trace_unlock, "UNLOCK ") \ EM(netfs_rreq_trace_unmark, "UNMARK ") \ EM(netfs_rreq_trace_wait_ip, "WAIT-IP") \ - E_(netfs_rreq_trace_wake_ip, "WAKE-IP") + EM(netfs_rreq_trace_wake_ip, "WAKE-IP") \ + E_(netfs_rreq_trace_write_done, "WR-DONE") #define netfs_sreq_sources \ EM(NETFS_FILL_WITH_ZEROES, "ZERO") \ @@ -64,7 +71,8 @@ EM(netfs_fail_copy_to_cache, "copy-to-cache") \ EM(netfs_fail_read, "read") \ EM(netfs_fail_short_read, "short-read") \ - E_(netfs_fail_prepare_write, "prep-write") + EM(netfs_fail_prepare_write, "prep-write") \ + E_(netfs_fail_write, "write") #define netfs_rreq_ref_traces \ EM(netfs_rreq_trace_get_for_outstanding,"GET OUTSTND") \ @@ -74,6 +82,8 @@ EM(netfs_rreq_trace_put_failed, "PUT FAILED ") \ EM(netfs_rreq_trace_put_return, "PUT RETURN ") \ EM(netfs_rreq_trace_put_subreq, "PUT SUBREQ ") \ + EM(netfs_rreq_trace_put_work, "PUT WORK ") \ + EM(netfs_rreq_trace_see_work, "SEE WORK ") \ E_(netfs_rreq_trace_new, "NEW ") #define netfs_sreq_ref_traces \ @@ -82,9 +92,12 @@ 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_discard, "PUT DISCARD") \ 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") \ + EM(netfs_sreq_trace_put_wip, "PUT WIP ") \ + EM(netfs_sreq_trace_put_work, "PUT WORK ") \ E_(netfs_sreq_trace_put_terminated, "PUT TERM ") #ifndef __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY @@ -96,6 +109,7 @@ #define E_(a, b) a enum netfs_read_trace { netfs_read_traces } __mode(byte); +enum netfs_write_trace { netfs_write_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); @@ -113,6 +127,7 @@ enum netfs_sreq_ref_trace { netfs_sreq_ref_traces } __mode(byte); #define E_(a, b) TRACE_DEFINE_ENUM(a); netfs_read_traces; +netfs_write_traces; netfs_rreq_origins; netfs_rreq_traces; netfs_sreq_sources; @@ -320,6 +335,37 @@ TRACE_EVENT(netfs_sreq_ref, __entry->ref) ); +TRACE_EVENT(netfs_write, + TP_PROTO(const struct netfs_io_request *wreq, + enum netfs_write_trace what), + + TP_ARGS(wreq, what), + + TP_STRUCT__entry( + __field(unsigned int, wreq ) + __field(unsigned int, cookie ) + __field(enum netfs_write_trace, what ) + __field(unsigned long long, start ) + __field(size_t, len ) + ), + + TP_fast_assign( + struct netfs_inode *__ctx = netfs_inode(wreq->inode); + struct fscache_cookie *__cookie = netfs_i_cookie(__ctx); + __entry->wreq = wreq->debug_id; + __entry->cookie = __cookie ? __cookie->debug_id : 0; + __entry->what = what; + __entry->start = wreq->start; + __entry->len = wreq->len; + ), + + TP_printk("R=%08x %s c=%08x by=%llx-%llx", + __entry->wreq, + __print_symbolic(__entry->what, netfs_write_traces), + __entry->cookie, + __entry->start, __entry->start + __entry->len - 1) + ); + #undef EM #undef E_ #endif /* _TRACE_NETFS_H */ From patchwork Wed Dec 13 15:23:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491231 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1788EC4167D for ; Wed, 13 Dec 2023 15:25:52 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 83FF08D0031; Wed, 13 Dec 2023 10:25:51 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 7EECE8D0015; Wed, 13 Dec 2023 10:25:51 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5F5D38D0031; Wed, 13 Dec 2023 10:25:51 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 4AD988D0015 for ; Wed, 13 Dec 2023 10:25:51 -0500 (EST) Received: from smtpin19.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id 149E8120230 for ; Wed, 13 Dec 2023 15:25:51 +0000 (UTC) X-FDA: 81562170102.19.A6C0BB3 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf03.hostedemail.com (Postfix) with ESMTP id 2E65920002 for ; Wed, 13 Dec 2023 15:25:49 +0000 (UTC) Authentication-Results: imf03.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b="CP9qUV/W"; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf03.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481149; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=s/wuPVyGasrVALHALpJTImhcNEkEG3+akMJGWVq4CGc=; b=tC/unugwqGULKpQ1zJ6abz32uyNbYrzNI5BzpzrRXytqG4r+Q9XN6O1XoWzyHOYyeUW9f+ FJ+pbJt7o7oOzQ1OU2rq33SAqT9xgFRhb4d90eUR2kMFJXRoFlJBZjtiJiNDWz7LC7DWpJ mlBueq5jvla8nnw2eFmHCvAAQlx0ZWI= ARC-Authentication-Results: i=1; imf03.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b="CP9qUV/W"; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf03.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481149; a=rsa-sha256; cv=none; b=YGDRYf8HC4qAv8WKPqCeQIsqOrn3P4qEvKaHd5LRJT9AfffkgrsBUzLfN6Q3VR72wBlbLf oAgLTFRcattED1Ohgc/yH0d8db8xil+taIqgfjZdygPHV45fQfatE9GoXRoO16KJZvpOlM u1nlHR+mnWE+ZLCuFah8whxEbldXMIg= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481148; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=s/wuPVyGasrVALHALpJTImhcNEkEG3+akMJGWVq4CGc=; b=CP9qUV/WYUx6vm16vf3rKwCdoS3FtZ7pj7FFXtiTy/C71YsEVz7XuTx/mJT769DhaHjbNe roXGimbKoYFPM3QxDWcfXvA9MXMdDKLpEpcHu0Jsub5LClLvReWH83YOawKcoJF1R4Z3zu 96Rxdwi+DwbGfogDF17Dt/pcn6KhBUI= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-348-R2jZbAjqPKeVIZ9nPy0rYQ-1; Wed, 13 Dec 2023 10:25:43 -0500 X-MC-Unique: R2jZbAjqPKeVIZ9nPy0rYQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6908B890FC2; Wed, 13 Dec 2023 15:25:41 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0155740C6EBA; Wed, 13 Dec 2023 15:25:37 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 25/39] netfs: Provide func to copy data to pagecache for buffered write Date: Wed, 13 Dec 2023 15:23:35 +0000 Message-ID: <20231213152350.431591-26-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-Rspamd-Queue-Id: 2E65920002 X-Rspam-User: X-Rspamd-Server: rspam02 X-Stat-Signature: 63pfntk9js8z7x783r4xq4gtqdp9gua3 X-HE-Tag: 1702481149-796288 X-HE-Meta: U2FsdGVkX19LGeUntF0oQv3yeSDH+ccxvE1LOFuE4tChP2h0gO2C0U+TXdmXbdRGfXHom4rmjGlGh1sww32RJEj8a4HmxH/6zFxGSwGOKXG0xzz+slb9cSWtGwBqydcilEkbUGwKX+4gLQk0kis8cM+HSAyL7Vnm1/vO1BZYDLxTGpdy/ZyHCsZvx+haXEDw6eRaZY9DgcwsVMnsunaw3WYWimtiMfm6BzP48WjjbCYZau1dCbqu0YI8BE8/aEh4pTSNrwlo64mRbE7JzuAq3M+cWmM7R4CsqStHk8flaV26Vy+W+sZlNdAXPrtpogyq7neYOYGlTZFhUZp1AyT0H0gSB2XyY0/Of2FeB1VTdzfEVDcvXBkcWlpsBNSGiAkHIJal+oFjFHLIdj8dn+yXjUIoNIB3IczAlNJ2+lciK+np842Ip54G68hOmxmrEqTY1wEl/iEw3rt5/HawtMLVz98TcfJjoxezr+ONbaY208+O4W71o1JUzrdV2blyNLkbDvugoJEiP/A7d7fBi/bUuJyjPTeebKOW7v2lhoM8pJ2vZgUdG+/wd3EBvtjkvEeoLmlo/YKbFd2DznhmlxVf8dKxnIHnKyKopNUcyAWLb0+JVn+2IbRMddOhQky8FixqJ+xMCKoKR6qvlRZpIa6c81Y3sPqORw4NcY/ddU6gRgnUh2lCcvIh1K//sF0n7ckngNq64h3e/dchvlRHTTqfhKDSA3l7lKimIVTroBNW7uH9bqmR8VeZmr7Pd9lAxhMrEwKoHK8ArFBWT3DS3Wtc48W9KLYhUlml2l7kfvdv6AlZFbBT2WqjGOBBh/u6iw9Wdf6XfcdBE9u6dhjxTP80izylV2e3bPIbEXosbcy62yb3hl/ppKeaa/Rla3n/JnmPoTf/V5rvU3S0b9eXMnnDN7GpuDRJ0Gvki6CQR+C5exw5opI2EcKthkoPdoIR9+eD+8ZG9660y49tWahACcO Xs/DfB2A +sWaW2goYZv8mbF7PWqQ/S9hqcDWUBGnsaA7VOAsyT7zZHf/LkLNXw/1kC/qIuwxDWLu4ew7KclGZb6gJ3f3x/31Dno+fOzsVZFWppmTcfJ8A2N/oxci484fwTO35MeMlttQAzxtDBh+kT/tOwNrM9Ydh3LJqEh7wbLrnlZymvigsUYkPP3SAwvMqF47cTQkybkPLZCrb9n9bctW2R/imA0vXoC1khIcsR/PmLqOvh34LYasz71LnkUoxkJhR6VblvAbMnV/Kh0CRCRSloWc8YO6CqcHWkjleSuloAzjy8Zg+73/Ktm8ovinMJy2tIJVLA3NE X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Provide a netfs write helper, netfs_perform_write() to buffer data to be written in the pagecache and mark the modified folios dirty. It will perform "streaming writes" for folios that aren't currently resident, if possible, storing data in partially modified folios that are marked dirty, but not uptodate. It will also tag pages as belonging to fs-specific write groups if so directed by the filesystem. This is derived from generic_perform_write(), but doesn't use ->write_begin() and ->write_end(), having that logic rolled in instead. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/Makefile | 1 + fs/netfs/buffered_read.c | 49 ++++++ fs/netfs/buffered_write.c | 330 +++++++++++++++++++++++++++++++++++ fs/netfs/internal.h | 2 + fs/netfs/io.c | 1 + include/linux/netfs.h | 5 + include/trace/events/netfs.h | 73 ++++++++ 7 files changed, 461 insertions(+) create mode 100644 fs/netfs/buffered_write.c diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index c69c6775b8ac..85d8333a1ed4 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -2,6 +2,7 @@ netfs-y := \ buffered_read.o \ + buffered_write.o \ io.o \ iterator.o \ locking.o \ diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 6b9a44cafbac..73a6e4d61f9d 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -63,6 +63,7 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq) break; } if (!folio_started && test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) { + trace_netfs_folio(folio, netfs_folio_trace_copy_to_cache); folio_start_fscache(folio); folio_started = true; } @@ -454,3 +455,51 @@ int netfs_write_begin(struct netfs_inode *ctx, return ret; } EXPORT_SYMBOL(netfs_write_begin); + +/* + * Preload the data into a page we're proposing to write into. + */ +int netfs_prefetch_for_write(struct file *file, struct folio *folio, + size_t offset, size_t len) +{ + struct netfs_io_request *rreq; + struct address_space *mapping = folio_file_mapping(folio); + struct netfs_inode *ctx = netfs_inode(mapping->host); + unsigned long long start = folio_pos(folio); + size_t flen = folio_size(folio); + int ret; + + _enter("%zx @%llx", flen, start); + + ret = -ENOMEM; + + rreq = netfs_alloc_request(mapping, file, start, flen, + NETFS_READ_FOR_WRITE); + if (IS_ERR(rreq)) { + ret = PTR_ERR(rreq); + goto error; + } + + rreq->no_unlock_folio = folio_index(folio); + __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); + ret = netfs_begin_cache_read(rreq, ctx); + if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS) + goto error_put; + + netfs_stat(&netfs_n_rh_write_begin); + trace_netfs_read(rreq, start, flen, netfs_read_trace_prefetch_for_write); + + /* Set up the output buffer */ + iov_iter_xarray(&rreq->iter, ITER_DEST, &mapping->i_pages, + rreq->start, rreq->len); + + ret = netfs_begin_read(rreq, true); + netfs_put_request(rreq, false, netfs_rreq_trace_put_return); + return ret; + +error_put: + netfs_put_request(rreq, false, netfs_rreq_trace_put_discard); +error: + _leave(" = %d", ret); + return ret; +} diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c new file mode 100644 index 000000000000..6e7f06d9962d --- /dev/null +++ b/fs/netfs/buffered_write.c @@ -0,0 +1,330 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Network filesystem high-level write support. + * + * Copyright (C) 2023 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include +#include +#include +#include +#include +#include +#include "internal.h" + +/* + * Determined write method. Adjust netfs_folio_traces if this is changed. + */ +enum netfs_how_to_modify { + NETFS_FOLIO_IS_UPTODATE, /* Folio is uptodate already */ + NETFS_JUST_PREFETCH, /* We have to read the folio anyway */ + NETFS_WHOLE_FOLIO_MODIFY, /* We're going to overwrite the whole folio */ + NETFS_MODIFY_AND_CLEAR, /* We can assume there is no data to be downloaded. */ + NETFS_STREAMING_WRITE, /* Store incomplete data in non-uptodate page. */ + NETFS_STREAMING_WRITE_CONT, /* Continue streaming write. */ + NETFS_FLUSH_CONTENT, /* Flush incompatible content. */ +}; + +static void netfs_set_group(struct folio *folio, struct netfs_group *netfs_group) +{ + if (netfs_group && !folio_get_private(folio)) + folio_attach_private(folio, netfs_get_group(netfs_group)); +} + +/* + * Decide how we should modify a folio. We might be attempting to do + * write-streaming, in which case we don't want to a local RMW cycle if we can + * avoid it. If we're doing local caching or content crypto, we award that + * priority over avoiding RMW. If the file is open readably, then we also + * assume that we may want to read what we wrote. + */ +static enum netfs_how_to_modify netfs_how_to_modify(struct netfs_inode *ctx, + struct file *file, + struct folio *folio, + void *netfs_group, + size_t flen, + size_t offset, + size_t len, + bool maybe_trouble) +{ + struct netfs_folio *finfo = netfs_folio_info(folio); + loff_t pos = folio_file_pos(folio); + + _enter(""); + + if (netfs_folio_group(folio) != netfs_group) + return NETFS_FLUSH_CONTENT; + + if (folio_test_uptodate(folio)) + return NETFS_FOLIO_IS_UPTODATE; + + if (pos >= ctx->remote_i_size) + return NETFS_MODIFY_AND_CLEAR; + + if (!maybe_trouble && offset == 0 && len >= flen) + return NETFS_WHOLE_FOLIO_MODIFY; + + if (file->f_mode & FMODE_READ) + return NETFS_JUST_PREFETCH; + + if (netfs_is_cache_enabled(ctx)) + return NETFS_JUST_PREFETCH; + + if (!finfo) + return NETFS_STREAMING_WRITE; + + /* We can continue a streaming write only if it continues on from the + * previous. If it overlaps, we must flush lest we suffer a partial + * copy and disjoint dirty regions. + */ + if (offset == finfo->dirty_offset + finfo->dirty_len) + return NETFS_STREAMING_WRITE_CONT; + return NETFS_FLUSH_CONTENT; +} + +/* + * Grab a folio for writing and lock it. + */ +static struct folio *netfs_grab_folio_for_write(struct address_space *mapping, + loff_t pos, size_t part) +{ + pgoff_t index = pos / PAGE_SIZE; + + return __filemap_get_folio(mapping, index, FGP_WRITEBEGIN, + mapping_gfp_mask(mapping)); +} + +/** + * netfs_perform_write - Copy data into the pagecache. + * @iocb: The operation parameters + * @iter: The source buffer + * @netfs_group: Grouping for dirty pages (eg. ceph snaps). + * + * Copy data into pagecache pages attached to the inode specified by @iocb. + * The caller must hold appropriate inode locks. + * + * Dirty pages are tagged with a netfs_folio struct if they're not up to date + * to indicate the range modified. Dirty pages may also be tagged with a + * netfs-specific grouping such that data from an old group gets flushed before + * a new one is started. + */ +ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, + struct netfs_group *netfs_group) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file_inode(file); + struct address_space *mapping = inode->i_mapping; + struct netfs_inode *ctx = netfs_inode(inode); + struct netfs_folio *finfo; + struct folio *folio; + enum netfs_how_to_modify howto; + enum netfs_folio_trace trace; + unsigned int bdp_flags = (iocb->ki_flags & IOCB_SYNC) ? 0: BDP_ASYNC; + ssize_t written = 0, ret; + loff_t i_size, pos = iocb->ki_pos, from, to; + size_t max_chunk = PAGE_SIZE << MAX_PAGECACHE_ORDER; + bool maybe_trouble = false; + + do { + size_t flen; + size_t offset; /* Offset into pagecache folio */ + size_t part; /* Bytes to write to folio */ + size_t copied; /* Bytes copied from user */ + + ret = balance_dirty_pages_ratelimited_flags(mapping, bdp_flags); + if (unlikely(ret < 0)) + break; + + offset = pos & (max_chunk - 1); + part = min(max_chunk - offset, iov_iter_count(iter)); + + /* Bring in the user pages that we will copy from _first_ lest + * we hit a nasty deadlock on copying from the same page as + * we're writing to, without it being marked uptodate. + * + * Not only is this an optimisation, but it is also required to + * check that the address is actually valid, when atomic + * usercopies are used below. + * + * We rely on the page being held onto long enough by the LRU + * that we can grab it below if this causes it to be read. + */ + ret = -EFAULT; + if (unlikely(fault_in_iov_iter_readable(iter, part) == part)) + break; + + ret = -ENOMEM; + folio = netfs_grab_folio_for_write(mapping, pos, part); + if (!folio) + break; + + flen = folio_size(folio); + offset = pos & (flen - 1); + part = min_t(size_t, flen - offset, part); + + if (signal_pending(current)) { + ret = written ? -EINTR : -ERESTARTSYS; + goto error_folio_unlock; + } + + /* See if we need to prefetch the area we're going to modify. + * We need to do this before we get a lock on the folio in case + * there's more than one writer competing for the same cache + * block. + */ + howto = netfs_how_to_modify(ctx, file, folio, netfs_group, + flen, offset, part, maybe_trouble); + _debug("howto %u", howto); + switch (howto) { + case NETFS_JUST_PREFETCH: + ret = netfs_prefetch_for_write(file, folio, offset, part); + if (ret < 0) { + _debug("prefetch = %zd", ret); + goto error_folio_unlock; + } + break; + case NETFS_FOLIO_IS_UPTODATE: + case NETFS_WHOLE_FOLIO_MODIFY: + case NETFS_STREAMING_WRITE_CONT: + break; + case NETFS_MODIFY_AND_CLEAR: + zero_user_segment(&folio->page, 0, offset); + break; + case NETFS_STREAMING_WRITE: + ret = -EIO; + if (WARN_ON(folio_get_private(folio))) + goto error_folio_unlock; + break; + case NETFS_FLUSH_CONTENT: + trace_netfs_folio(folio, netfs_flush_content); + from = folio_pos(folio); + to = from + folio_size(folio) - 1; + folio_unlock(folio); + folio_put(folio); + ret = filemap_write_and_wait_range(mapping, from, to); + if (ret < 0) + goto error_folio_unlock; + continue; + } + + if (mapping_writably_mapped(mapping)) + flush_dcache_folio(folio); + + copied = copy_folio_from_iter_atomic(folio, offset, part, iter); + + flush_dcache_folio(folio); + + /* Deal with a (partially) failed copy */ + if (copied == 0) { + ret = -EFAULT; + goto error_folio_unlock; + } + + trace = (enum netfs_folio_trace)howto; + switch (howto) { + case NETFS_FOLIO_IS_UPTODATE: + case NETFS_JUST_PREFETCH: + netfs_set_group(folio, netfs_group); + break; + case NETFS_MODIFY_AND_CLEAR: + zero_user_segment(&folio->page, offset + copied, flen); + netfs_set_group(folio, netfs_group); + folio_mark_uptodate(folio); + break; + case NETFS_WHOLE_FOLIO_MODIFY: + if (unlikely(copied < part)) { + maybe_trouble = true; + iov_iter_revert(iter, copied); + copied = 0; + goto retry; + } + netfs_set_group(folio, netfs_group); + folio_mark_uptodate(folio); + break; + case NETFS_STREAMING_WRITE: + if (offset == 0 && copied == flen) { + netfs_set_group(folio, netfs_group); + folio_mark_uptodate(folio); + trace = netfs_streaming_filled_page; + break; + } + finfo = kzalloc(sizeof(*finfo), GFP_KERNEL); + if (!finfo) { + iov_iter_revert(iter, copied); + ret = -ENOMEM; + goto error_folio_unlock; + } + finfo->netfs_group = netfs_get_group(netfs_group); + finfo->dirty_offset = offset; + finfo->dirty_len = copied; + folio_attach_private(folio, (void *)((unsigned long)finfo | + NETFS_FOLIO_INFO)); + break; + case NETFS_STREAMING_WRITE_CONT: + finfo = netfs_folio_info(folio); + finfo->dirty_len += copied; + if (finfo->dirty_offset == 0 && finfo->dirty_len == flen) { + if (finfo->netfs_group) + folio_change_private(folio, finfo->netfs_group); + else + folio_detach_private(folio); + folio_mark_uptodate(folio); + kfree(finfo); + trace = netfs_streaming_cont_filled_page; + } + break; + default: + WARN(true, "Unexpected modify type %u ix=%lx\n", + howto, folio_index(folio)); + ret = -EIO; + goto error_folio_unlock; + } + + trace_netfs_folio(folio, trace); + + /* Update the inode size if we moved the EOF marker */ + i_size = i_size_read(inode); + pos += copied; + if (pos > i_size) { + if (ctx->ops->update_i_size) { + ctx->ops->update_i_size(inode, pos); + } else { + i_size_write(inode, pos); +#if IS_ENABLED(CONFIG_FSCACHE) + fscache_update_cookie(ctx->cache, NULL, &pos); +#endif + } + } + written += copied; + + folio_mark_dirty(folio); + retry: + folio_unlock(folio); + folio_put(folio); + folio = NULL; + + cond_resched(); + } while (iov_iter_count(iter)); + +out: + if (likely(written)) { + /* Flush and wait for a write that requires immediate synchronisation. */ + if (iocb->ki_flags & (IOCB_DSYNC | IOCB_SYNC)) { + _debug("dsync"); + ret = filemap_fdatawait_range(mapping, iocb->ki_pos, + iocb->ki_pos + written); + } + + iocb->ki_pos += written; + } + + _leave(" = %zd [%zd]", written, ret); + return written ? written : ret; + +error_folio_unlock: + folio_unlock(folio); + folio_put(folio); + goto out; +} +EXPORT_SYMBOL(netfs_perform_write); diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index a71fc21fc4ad..62c349cc71f9 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -23,6 +23,8 @@ * buffered_read.c */ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq); +int netfs_prefetch_for_write(struct file *file, struct folio *folio, + size_t offset, size_t len); /* * io.c diff --git a/fs/netfs/io.c b/fs/netfs/io.c index 1795f8679be9..776ca0aa6b62 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -125,6 +125,7 @@ static void netfs_rreq_unmark_after_write(struct netfs_io_request *rreq, if (have_unlocked && folio_index(folio) <= unlocked) continue; unlocked = folio_index(folio); + trace_netfs_folio(folio, netfs_folio_trace_end_copy); folio_end_fscache(folio); have_unlocked = true; } diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 143374a77e84..63258998defb 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -370,6 +370,11 @@ struct netfs_cache_ops { loff_t *_data_start, size_t *_data_len); }; +/* High-level write API */ +ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, + struct netfs_group *netfs_group); + +/* Address operations API */ struct readahead_control; void netfs_readahead(struct readahead_control *); int netfs_read_folio(struct file *, struct folio *); diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index e03635172760..8308b81f36be 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -19,6 +19,7 @@ EM(netfs_read_trace_expanded, "EXPANDED ") \ EM(netfs_read_trace_readahead, "READAHEAD") \ EM(netfs_read_trace_readpage, "READPAGE ") \ + EM(netfs_read_trace_prefetch_for_write, "PREFETCHW") \ E_(netfs_read_trace_write_begin, "WRITEBEGN") #define netfs_write_traces \ @@ -100,6 +101,31 @@ EM(netfs_sreq_trace_put_work, "PUT WORK ") \ E_(netfs_sreq_trace_put_terminated, "PUT TERM ") +#define netfs_folio_traces \ + /* The first few correspond to enum netfs_how_to_modify */ \ + EM(netfs_folio_is_uptodate, "mod-uptodate") \ + EM(netfs_just_prefetch, "mod-prefetch") \ + EM(netfs_whole_folio_modify, "mod-whole-f") \ + EM(netfs_modify_and_clear, "mod-n-clear") \ + EM(netfs_streaming_write, "mod-streamw") \ + EM(netfs_streaming_write_cont, "mod-streamw+") \ + EM(netfs_flush_content, "flush") \ + EM(netfs_streaming_filled_page, "mod-streamw-f") \ + EM(netfs_streaming_cont_filled_page, "mod-streamw-f+") \ + /* The rest are for writeback */ \ + EM(netfs_folio_trace_clear, "clear") \ + EM(netfs_folio_trace_clear_s, "clear-s") \ + EM(netfs_folio_trace_clear_g, "clear-g") \ + EM(netfs_folio_trace_copy_to_cache, "copy") \ + EM(netfs_folio_trace_end_copy, "end-copy") \ + EM(netfs_folio_trace_kill, "kill") \ + EM(netfs_folio_trace_mkwrite, "mkwrite") \ + EM(netfs_folio_trace_mkwrite_plus, "mkwrite+") \ + EM(netfs_folio_trace_redirty, "redirty") \ + EM(netfs_folio_trace_redirtied, "redirtied") \ + EM(netfs_folio_trace_store, "store") \ + E_(netfs_folio_trace_store_plus, "store+") + #ifndef __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY #define __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY @@ -115,6 +141,7 @@ 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); +enum netfs_folio_trace { netfs_folio_traces } __mode(byte); #endif @@ -135,6 +162,7 @@ netfs_sreq_traces; netfs_failures; netfs_rreq_ref_traces; netfs_sreq_ref_traces; +netfs_folio_traces; /* * Now redefine the EM() and E_() macros to map the enums to the strings that @@ -335,6 +363,51 @@ TRACE_EVENT(netfs_sreq_ref, __entry->ref) ); +TRACE_EVENT(netfs_folio, + TP_PROTO(struct folio *folio, enum netfs_folio_trace why), + + TP_ARGS(folio, why), + + TP_STRUCT__entry( + __field(ino_t, ino) + __field(pgoff_t, index) + __field(unsigned int, nr) + __field(enum netfs_folio_trace, why) + ), + + TP_fast_assign( + __entry->ino = folio->mapping->host->i_ino; + __entry->why = why; + __entry->index = folio_index(folio); + __entry->nr = folio_nr_pages(folio); + ), + + TP_printk("i=%05lx ix=%05lx-%05lx %s", + __entry->ino, __entry->index, __entry->index + __entry->nr - 1, + __print_symbolic(__entry->why, netfs_folio_traces)) + ); + +TRACE_EVENT(netfs_write_iter, + TP_PROTO(const struct kiocb *iocb, const struct iov_iter *from), + + TP_ARGS(iocb, from), + + TP_STRUCT__entry( + __field(unsigned long long, start ) + __field(size_t, len ) + __field(unsigned int, flags ) + ), + + TP_fast_assign( + __entry->start = iocb->ki_pos; + __entry->len = iov_iter_count(from); + __entry->flags = iocb->ki_flags; + ), + + TP_printk("WRITE-ITER s=%llx l=%zx f=%x", + __entry->start, __entry->len, __entry->flags) + ); + TRACE_EVENT(netfs_write, TP_PROTO(const struct netfs_io_request *wreq, enum netfs_write_trace what), From patchwork Wed Dec 13 15:23:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491232 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id EEBA3C4332F for ; Wed, 13 Dec 2023 15:25:56 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 77CA58D0032; Wed, 13 Dec 2023 10:25:56 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 72CBC8D0015; Wed, 13 Dec 2023 10:25:56 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5CC638D0032; Wed, 13 Dec 2023 10:25:56 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 4A8378D0015 for ; Wed, 13 Dec 2023 10:25:56 -0500 (EST) Received: from smtpin26.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id 2FAB2120235 for ; Wed, 13 Dec 2023 15:25:56 +0000 (UTC) X-FDA: 81562170312.26.42A0050 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf16.hostedemail.com (Postfix) with ESMTP id 5CEF3180012 for ; Wed, 13 Dec 2023 15:25:54 +0000 (UTC) Authentication-Results: imf16.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=RT4gAKCQ; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf16.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481154; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=n7vsxkTeFDyw/Xz/jQpnFttohdwf2WdzS8Vx6FHSJ3Y=; b=plwcG6RB29R8ZSg1AqXaNo8ORTQyuAeazumRGJnO0wSiN/2SuT8pJU+BFETFbOp75uHRc0 g0i61AZfSa3ODwQIu6yfwPU9WzHiGjrUZZFo3orFQ3N9TBBxVcj0pexXYdo2ett0poP1uz TVgJY+iagXL8NeqSBPepGnlqqRIKoKc= ARC-Authentication-Results: i=1; imf16.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=RT4gAKCQ; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf16.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481154; a=rsa-sha256; cv=none; b=fb6BQq8hFndHU2nTcg0rtn0uhv7n6epxlOL986PmTrjk8mJiwkF+X9g1Qy6ageS2k01xWV o8FyuHxT7SLk4qvMPc+ayhN8udfhUvfJFG1/PHt1yaqoCqZRmNYkgIHbCUsVmQjzWctdtn GjMc6s7NIoLU1Qv13XWUHUF+hSdXgMY= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481153; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=n7vsxkTeFDyw/Xz/jQpnFttohdwf2WdzS8Vx6FHSJ3Y=; b=RT4gAKCQ5aeBc0Mu2JkuRI7h7BgleBU0plagw6WOeTXYbylze1BDQdoWWsU1dxf/HkZjm/ 3WxCVax6JDqTLigF7608rpC3+1n8n9E8vXCW3oRDtbJOSBWVwleJjYeJuWbaV4DpkLsrn6 YRiYlUW6X7ZuaFjRp9uqsa5pP7fYRSA= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-160-Hk0BL4cxNNG-H2Glo3kY9Q-1; Wed, 13 Dec 2023 10:25:49 -0500 X-MC-Unique: Hk0BL4cxNNG-H2Glo3kY9Q-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E65E8881F47; Wed, 13 Dec 2023 15:25:45 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 718511121312; Wed, 13 Dec 2023 15:25:42 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 26/39] netfs: Make netfs_read_folio() handle streaming-write pages Date: Wed, 13 Dec 2023 15:23:36 +0000 Message-ID: <20231213152350.431591-27-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.3 X-Rspamd-Queue-Id: 5CEF3180012 X-Rspam-User: X-Rspamd-Server: rspam05 X-Stat-Signature: xnzuwwyhcdb4rp55thkrm86yfr1ndw37 X-HE-Tag: 1702481154-283981 X-HE-Meta: U2FsdGVkX1/i30LYM+L+8Mlku7nY2M94Z75d6EnYr8t7RmHJ/PkRMYh/jaRm5jArs6ajDqrDk7m8HZg3s+KhLf1r6vk6+P/zMFSTmiENJE3SdQaOEd/yiUVXhqJhBZfvGFjsi/UvQw34PeUPB4Qjxd9PjyRbEnxIUQz/0GgzdZjOWP4QOZgebwB3gTvsAx0+Qw4THYGTuyerKtpdmf5wodVOrmbqpxCtWtH1QuyJZzZi0eOJgGfvthNV/gnnZzGK7Wo9EAcnpmgFKPJg/PYw09EBJRVzEW0gpX6vkM5JqNRm5MaXSZeAW+e2NGcbNLAuiBRa//ke9eHsTR7q8DFaRKiIOjQOwWH7QRDcCcd6E4nGnHAsEZTFHHM7KRy9WEpg3Bo3DQU7mfKGugcqVqVZnV7OvZr9dnm6s4/H0rbxKJ3IMhfNtjp60Hmh8BEoYFGX+xIcVr8mtYkUsdng9/e6SOWAoeNPlv4G9mtobU0swS4ZNvISMJlNDLS0gOr2Fmw0C7xEwAnhR3IqRneYjCXBNAS7V/XSF/96/m4icignhL3iEE1ocbu5gzhhUbVkOzFfg0uR1mQzH02CNDSLz4gu4llDU+N4Kw5qqspVvYS6C2bs6L1oTResUJvMec23183eZRdiqI4owAp64vkC6R/AT3rPVO+y2FoGi6FoUloMgtBK+V30SynawFQJrM2sTx2DrvGUbfCsgsvGl81XGLhdW+yKNXDbn89UFkly+sydgsrHeHba1zhmfNiYe9F7S0VAHtAH6ouXp+1mSoYPg41w8oViHbtNbpiWcWPfkylXObLdGACMESimOFiOvqx0QQJUdWBSznOzT0TtPS7mE63cjbpZl0GzBP4lcAAKCURkTjx4ENUC7dJf2Fr4BubDfpUn/8o7EkyYTGrdjydEu/9iFBaF8WvBJXTlfG21yZy+RCRlATta5a8cyNyOpdHCsx5fFMcC6O2tjHc18jfl1EL wsPX0Ucu /mmS2qcaJyrkkAWN4JL4xmXbw0Iy5FeHML9NIboI91Lhuq5K8KtNWWhUO6m0ZhMOuhX9KmZc+5JXVTQqEuAbkT/lBW6Sdgb9XDttY9CS4NT4zxQ30F1aZQ5H+WFAmnEhSP0PB8rpn4b61RpcdSBGiYr0NCeXA6bPKYdPZ3jxTIoB+rm3MVQ3cY7XZydVACJbsiiNadR7c2adGHzrqlXMEVxXCpZYFyySGYcLCgH4hlPRfudoA12QxNRbZkfZ4nF84VySijLEiXUd1cexWNw8HnHhdZDjBHta1SjKRLdffxX9CGzfzlgC5aczloKqwxBpI4yLJ1wlkL76sGOjPb4tn8FjQ5Q== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: netfs_read_folio() needs to handle partially-valid pages that are marked dirty, but not uptodate in the event that someone tries to read a page was used to cache data by a streaming write. In such a case, make netfs_read_folio() set up a bvec iterator that points to the parts of the folio that need filling and to a sink page for the data that should be discarded and use that instead of i_pages as the iterator to be written to. This requires netfs_rreq_unlock_folios() to convert the page into a normal dirty uptodate page, getting rid of the partial write record and bumping the group pointer over to folio->private. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/buffered_read.c | 61 ++++++++++++++++++++++++++++++++++-- include/trace/events/netfs.h | 2 ++ 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 73a6e4d61f9d..950f63fc156a 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -16,6 +16,7 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq) { struct netfs_io_subrequest *subreq; + struct netfs_folio *finfo; struct folio *folio; pgoff_t start_page = rreq->start / PAGE_SIZE; pgoff_t last_page = ((rreq->start + rreq->len) / PAGE_SIZE) - 1; @@ -87,6 +88,15 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq) if (!pg_failed) { flush_dcache_folio(folio); + finfo = netfs_folio_info(folio); + if (finfo) { + trace_netfs_folio(folio, netfs_folio_trace_filled_gaps); + if (finfo->netfs_group) + folio_change_private(folio, finfo->netfs_group); + else + folio_detach_private(folio); + kfree(finfo); + } folio_mark_uptodate(folio); } @@ -239,6 +249,7 @@ int netfs_read_folio(struct file *file, struct folio *folio) struct address_space *mapping = folio_file_mapping(folio); struct netfs_io_request *rreq; struct netfs_inode *ctx = netfs_inode(mapping->host); + struct folio *sink = NULL; int ret; _enter("%lx", folio_index(folio)); @@ -259,12 +270,56 @@ int netfs_read_folio(struct file *file, struct folio *folio) trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage); /* Set up the output buffer */ - iov_iter_xarray(&rreq->iter, ITER_DEST, &mapping->i_pages, - rreq->start, rreq->len); + if (folio_test_dirty(folio)) { + /* Handle someone trying to read from an unflushed streaming + * write. We fiddle the buffer so that a gap at the beginning + * and/or a gap at the end get copied to, but the middle is + * discarded. + */ + struct netfs_folio *finfo = netfs_folio_info(folio); + struct bio_vec *bvec; + unsigned int from = finfo->dirty_offset; + unsigned int to = from + finfo->dirty_len; + unsigned int off = 0, i = 0; + size_t flen = folio_size(folio); + size_t nr_bvec = flen / PAGE_SIZE + 2; + size_t part; + + ret = -ENOMEM; + bvec = kmalloc_array(nr_bvec, sizeof(*bvec), GFP_KERNEL); + if (!bvec) + goto discard; + + sink = folio_alloc(GFP_KERNEL, 0); + if (!sink) + goto discard; + + trace_netfs_folio(folio, netfs_folio_trace_read_gaps); + + rreq->direct_bv = bvec; + rreq->direct_bv_count = nr_bvec; + if (from > 0) { + bvec_set_folio(&bvec[i++], folio, from, 0); + off = from; + } + while (off < to) { + part = min_t(size_t, to - off, PAGE_SIZE); + bvec_set_folio(&bvec[i++], sink, part, 0); + off += part; + } + if (to < flen) + bvec_set_folio(&bvec[i++], folio, flen - to, to); + iov_iter_bvec(&rreq->iter, ITER_DEST, bvec, i, rreq->len); + } else { + iov_iter_xarray(&rreq->iter, ITER_DEST, &mapping->i_pages, + rreq->start, rreq->len); + } ret = netfs_begin_read(rreq, true); + if (sink) + folio_put(sink); netfs_put_request(rreq, false, netfs_rreq_trace_put_return); - return ret; + return ret < 0 ? ret : 0; discard: netfs_put_request(rreq, false, netfs_rreq_trace_put_discard); diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 8308b81f36be..082a5e717b58 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -118,9 +118,11 @@ EM(netfs_folio_trace_clear_g, "clear-g") \ EM(netfs_folio_trace_copy_to_cache, "copy") \ EM(netfs_folio_trace_end_copy, "end-copy") \ + EM(netfs_folio_trace_filled_gaps, "filled-gaps") \ EM(netfs_folio_trace_kill, "kill") \ EM(netfs_folio_trace_mkwrite, "mkwrite") \ EM(netfs_folio_trace_mkwrite_plus, "mkwrite+") \ + EM(netfs_folio_trace_read_gaps, "read-gaps") \ EM(netfs_folio_trace_redirty, "redirty") \ EM(netfs_folio_trace_redirtied, "redirtied") \ EM(netfs_folio_trace_store, "store") \ From patchwork Wed Dec 13 15:23:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491236 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 633B1C4167B for ; Wed, 13 Dec 2023 15:26:23 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id E814E6B03CB; Wed, 13 Dec 2023 10:26:22 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id E33C96B03CE; Wed, 13 Dec 2023 10:26:22 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id CD1AD6B03D0; Wed, 13 Dec 2023 10:26:22 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id BD4AC6B03CB for ; Wed, 13 Dec 2023 10:26:22 -0500 (EST) Received: from smtpin13.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 9A70C1C14F0 for ; Wed, 13 Dec 2023 15:26:22 +0000 (UTC) X-FDA: 81562171404.13.A6B3D83 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf16.hostedemail.com (Postfix) with ESMTP id EF25B18002C for ; Wed, 13 Dec 2023 15:26:20 +0000 (UTC) Authentication-Results: imf16.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=e7r3PqB2; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf16.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481181; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=KbBg4oLyg/4VjucqWLPnAUrUGVI7xibirsiFMNrNygw=; b=yZ9L7nCkUTa0n5KZnNMUl8ZMZB9UoU25iOMkEqUCyETJZAj+iNrsgfxQpuZM0c0XCUnYRe pkBFF5r5FFxz5lCuT79zyn5i7Ri/IEA93w/T462jM8j6njNycfBb/MfgRCR1K62NS1X2Tc gBJlrushaeD2reZf6bfTEmXmSEnPKmI= ARC-Authentication-Results: i=1; imf16.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=e7r3PqB2; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf16.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481181; a=rsa-sha256; cv=none; b=i5ho5JUXlpcdS8PnYVaeA3aT9AZGeLdQqSbKRpLHM+LJMM0XhzuJJba36s/R4yRu53sA39 zcmDQO5wbhhJtGq2jeJXbOpeTiIBX+i/hIS3jq2BkrQ4ef9d4gzcbtZPSQP967tfosL+02 18HHS87Hc17xLu7h3s6PDq2UJDfU4kU= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481180; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KbBg4oLyg/4VjucqWLPnAUrUGVI7xibirsiFMNrNygw=; b=e7r3PqB2vAv8B2rswgc1BUQ+c/EHWz8K6LVhVxYc6pEmwZK8ndjW1R7zR8a7Fq0srSrslG VUmU+K85t8R92UjmaRuTTV+S1qzPEC4tS5j5Pu2izjPF/hHov5vPsZCEIYKAhQ7LTwLcYR HRlXHiXWS2wRZVha5SJ2SSqD3Gt58GY= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-16-K1t_OTENORi1A-IFlHrJWg-1; Wed, 13 Dec 2023 10:25:59 -0500 X-MC-Unique: K1t_OTENORi1A-IFlHrJWg-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 797C53811F42; Wed, 13 Dec 2023 15:25:50 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id BD51451E3; Wed, 13 Dec 2023 15:25:46 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 27/39] netfs: Allocate multipage folios in the writepath Date: Wed, 13 Dec 2023 15:23:37 +0000 Message-ID: <20231213152350.431591-28-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.5 X-Rspamd-Queue-Id: EF25B18002C X-Rspam-User: X-Rspamd-Server: rspam04 X-Stat-Signature: cmr37o3q167w6gqkxr7sxnubmwqebmi4 X-HE-Tag: 1702481180-935858 X-HE-Meta: U2FsdGVkX19M1QygElZC93muGfSRBB9dSjhyxJ/jU8nNKG1y+RUWFs0ZMrDuoDZmFm/HY78Gr5i/Z/aOq59Q6xTlHDmk9xHMhiZe2uTaIDQLKhnRqj68C4PpTmIcdEgGi4By0ZnjWFhQiwXD8d0EhLhCIwcBx6ix4vJ8+lahaRTDYbuCZWTt2AQ+s7S6tzfUr7gtl1qV/Og3bsB45o7LXmPJ0jNslzPWp8Lf9Wpp+3fuITUgiWsapQ5NT5oRFzn6EyFy6D4E0daF89SK+S7jAHjWVnsTVRLTs8a6NteU3WEIvXEMuHQgAHwVmP1kf2Mh5MyERuxj9zshXw35VJ/xSjqgb5EZNnZlT2jYdBk9gOJ73oYE+gfJjPFURQ7ak0ckya9/bfTObhewvf/jwEej02VBnC7Py4wRMuQ6DmoYrj/HsGxKxwpjJ6k+sZqr1YlCPW6d0ABU5x8WZ1/ujpZq2nT75J9rsA71p4WyFQgfLigygfcRA8brvSJm3Lor54vywV3Jch90s5tuhsTNmhKpZTTqYa1HxMUWWtW/z/V64UR83rx65QC05ICtnlUIy/pagKDjyU153udvXn9YZ9S6una2WuEpIahZMdUKQylzWiTHRvkaKJN5OAjhjPRDzhSomg/GP2mQZjrcDKuG+2FfzKoFCwePVPf38nMjPbu7lkAd/50bIjJh42X613Vg0NXzKCpmCFbAzOoberLrGBhDEKpcSwZZ/YLOT6SzA27hW+iUO7vBL7rYUzwcQ8qvI0if6jzetOo3/ptJfJAzhkHhPcs/bEm+w4uEDM4NzAcWrbxPNKOQfBuVxBFxS0D1clvvvJyS8mhbto6OC6yaRPpQGkqJd6QbTuiaNRDe8GawkotkRSYfFEzY2a+7Z33lnAyAzMudTxdCeVgdfyE0A50lbWsgzEaPCawh4CHo9KL2eMdQkbSF9eFvyJmjovIsoD/dPHLNC7S4ewWY1UT1qN+ Q2gApLae k41sNW9pwyQtzmIW43cgzz0DKvkdPehaPuz/UVTLuPie8Pnt69dRLE5c+SoPk4WJERQZ33Fr8zQ+u4PPKSv9LnGHO+PVBJNtuOGuUhddbVx7LnUuxsugylYxIdb7NuVIScd/id+vu6ic9ih5piMUnJt/RSG0QFWhRQaCYSVteT6iiifeLM9siF6quircxZKN/G/b9Um4vIbZw487shk7y88quP7C9PHDUrHB+998aZ/0+z/zI2hTbH+EN92u2V5tXQICB2x1TIHJ51CCfRwhY07ev2ZF3ky8nzFPz X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Allocate a multipage folio when copying data into the pagecache if possible if there's sufficient data to warrant it. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/buffered_write.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index 6e7f06d9962d..b76688e98f81 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -84,14 +84,19 @@ static enum netfs_how_to_modify netfs_how_to_modify(struct netfs_inode *ctx, } /* - * Grab a folio for writing and lock it. + * Grab a folio for writing and lock it. Attempt to allocate as large a folio + * as possible to hold as much of the remaining length as possible in one go. */ static struct folio *netfs_grab_folio_for_write(struct address_space *mapping, loff_t pos, size_t part) { pgoff_t index = pos / PAGE_SIZE; + fgf_t fgp_flags = FGP_WRITEBEGIN; - return __filemap_get_folio(mapping, index, FGP_WRITEBEGIN, + if (mapping_large_folio_support(mapping)) + fgp_flags |= fgf_set_order(pos % PAGE_SIZE + part); + + return __filemap_get_folio(mapping, index, fgp_flags, mapping_gfp_mask(mapping)); } From patchwork Wed Dec 13 15:23:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491233 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 294EBC4332F for ; Wed, 13 Dec 2023 15:26:06 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id B73396B00D1; Wed, 13 Dec 2023 10:26:05 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id B237F6B00D2; Wed, 13 Dec 2023 10:26:05 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 99DF46B00D3; Wed, 13 Dec 2023 10:26:05 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id 83C0B6B00D1 for ; Wed, 13 Dec 2023 10:26:05 -0500 (EST) Received: from smtpin15.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 57EEE14024C for ; Wed, 13 Dec 2023 15:26:05 +0000 (UTC) X-FDA: 81562170690.15.124C81A Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf13.hostedemail.com (Postfix) with ESMTP id 75F9420013 for ; Wed, 13 Dec 2023 15:26:03 +0000 (UTC) Authentication-Results: imf13.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b="Invr/rg+"; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf13.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481163; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=oIwLzDiZpaZMbFiReSwdjbMUxVWmR1x4Wpn5Zq569s4=; b=ImAm3tZm/eXEblZhZCzeQLAJwn1dOnUQvs/UzSPxtyszzSdfGI3l01Lrk82mAAzj8a+5tO 3dPxIRuZb3xqVNUu+4FrOzGhLIpGnq7fey6f1M5yVEfxDPMqRk6xyBEoycaM8pAyj9qOtx pZZW7yX08zEx7R11vBbISc6ywitkwh4= ARC-Authentication-Results: i=1; imf13.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b="Invr/rg+"; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf13.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481163; a=rsa-sha256; cv=none; b=X/fSdPN24HiDhybyANsPEPZGsOcXX2NNu2RsRuH5VVL0nnFkGl/LJbHPM9m60I5Xd3w576 XBr9ebshQ8S7XAQTn4+JELjIJZrh+oU+f37sVCGpS/IrCeEoWwNoj3h+N/+huXeKYfZ1Ai CyHUeW7SBGGAkc8nBCPVKOlCg0TY1Q8= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481162; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=oIwLzDiZpaZMbFiReSwdjbMUxVWmR1x4Wpn5Zq569s4=; b=Invr/rg+XZzJc3nv1PD0FMFVIEtzdlZXrGHfD3PcLiYTYepdsPJnXgywCd4C0bjSiHLgX8 21KovPQDnoGL07kiCzybKGtgVadEhaVpMgkNmJZ0zpb4UJeQXNBJgwB4WAVzyfJhuWUcaO sla2FNWnM4/AlliasGeAjU+hVMd6QCY= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-558-J6bMlVj2NQiuKCy5TuSEbg-1; Wed, 13 Dec 2023 10:25:59 -0500 X-MC-Unique: J6bMlVj2NQiuKCy5TuSEbg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id DDD7F1C18CCA; Wed, 13 Dec 2023 15:25:57 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 65E3440C6EB9; Wed, 13 Dec 2023 15:25:54 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 28/39] netfs: Implement support for unbuffered/DIO read Date: Wed, 13 Dec 2023 15:23:38 +0000 Message-ID: <20231213152350.431591-29-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 75F9420013 X-Stat-Signature: 75yt9ef5t9t8pkurm66d7ebmnt1m1ig6 X-HE-Tag: 1702481163-58600 X-HE-Meta: U2FsdGVkX18U22cXWMWqjplk97J+8OEw9dRDLzGUsXtjPe0Y98R+76EN8UZsQEPNQ8m554eIpcGRcWA0gxG9pLPTwLCmZSCjRBjkx29wCNWAZF4dYPPZI7iqLYf6qulVZLnKI8TqcPNFuZ8MEZjcLYAB8ee8xhy2SkDdQVCItY1azSVgVBE8AOn54/fvzgxZtUEh7+fBXO62/wlpkGifa2CBSLo1XaQVET7ktYq2eA5SOopBLkm5dRSDPspecgIJsWqMKP/V+w+FQGGwA5dxnG3a211a3vpjzBh16wb99WTn+HOHHim7d4r8MFrs1Ag4nfvZ5lAQAG35B55NQLi2HqZiawgpmycuz676+DBrUj4IDKQDdbqAiYVmT9kWBGe8mbRtkXcyAWE/lAqGYkvF7hKC+AZEoFIz4osNRwvbLzeTrVp3vtdaQdx04GhK0dfvKHTpgVnJF1FgNV8+W/Dn5nhhtyar10b8bIOniaqOX436tjcEmy1N5aGvHCuepl0u0JzB7YFVaKUisAiZB5yU7QcXx9ohyBbmLvvcqVdQOwwzbHyIl4kggOg33p3bW/6eea6v0n53nRCTCSSTNcLTIPGQbCJY0bCsdqJk9txItIXAjyV5jSIUo8qM9dMTnZUl7dpsvWOGBzxYz7u0PGiDjYyTZrXH27n467KmCEzVpZ8f6KRMCY2rXAAPt9A/j2Xyti/IKDGqpnt4GwxnMNBqm/AaWLzafWQZiga3LajhMimrCaqjK2UH56iSkwf2XCmQpo73yQTDiZte9VtXnoPpq94K1Pe5TxgeApq3cat/Y6vsq3iGS2VqvdB6iwPC5bFKR3mox9xYd108sXeP0ltbSavCsUNO3pVTx8x9uV/kG5/LPDfTby1Xr9SjITPbyGaXhtR3qDZu1bMOdhAw82CtdRTygZIG3WJc8UencDALb5Ui7yFdz813CaODESMrEFxd1CcMLE1BW8JmbZ93ZcM NDYWRlHo t0wDc53d+oYBLJhqkpyirl2gxPPSQ8qn/1EvtmRlfSjjKvFZIM6pQgdZx3KOTD0XqrJTwCWauUyw4F0YGwuQvG+aeAulxuigRLuGN+VTIUme0nLMj8PL3/J/Cgjb/OfmuxmPKuxg7AVoIk3lcYQu3syTTNfog7gAvws2IYrkIqqM3+1DJgnKxvWLYG6tre+i9H2Ewqd2vnnDRPM+9XN0Qg9lk8nAZL7Zr1GSpVLtqnD6hvPpu3oG6cBJ10r+iNLjC7Oh74UTcSeqx9/Eh3oTHHYcvWpda4QaSfPclzf1YMc207OCFYPZxUBmatJEc0XBw30ez X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Implement support for unbuffered and DIO reads in the netfs library, utilising the existing read helper code to do block splitting and individual queuing. The code also handles extraction of the destination buffer from the supplied iterator, allowing async unbuffered reads to take place. The read will be split up according to the rsize setting and, if supplied, the ->clamp_length() method. Note that the next subrequest will be issued as soon as issue_op returns, without waiting for previous ones to finish. The network filesystem needs to pause or handle queuing them if it doesn't want to fire them all at the server simultaneously. Once all the subrequests have finished, the state will be assessed and the amount of data to be indicated as having being obtained will be determined. As the subrequests may finish in any order, if an intermediate subrequest is short, any further subrequests may be copied into the buffer and then abandoned. In the future, this will also take care of doing an unbuffered read from encrypted content, with the decryption being done by the library. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/Makefile | 1 + fs/netfs/direct_read.c | 252 +++++++++++++++++++++++++++++++++++ fs/netfs/internal.h | 1 + fs/netfs/io.c | 82 ++++++++++-- fs/netfs/main.c | 1 + fs/netfs/objects.c | 5 +- fs/netfs/stats.c | 4 +- include/linux/netfs.h | 9 ++ include/trace/events/netfs.h | 7 +- mm/filemap.c | 1 + 10 files changed, 352 insertions(+), 11 deletions(-) create mode 100644 fs/netfs/direct_read.c diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index 85d8333a1ed4..e968ab1eca40 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -3,6 +3,7 @@ netfs-y := \ buffered_read.o \ buffered_write.o \ + direct_read.o \ io.o \ iterator.o \ locking.o \ diff --git a/fs/netfs/direct_read.c b/fs/netfs/direct_read.c new file mode 100644 index 000000000000..1d26468aafd9 --- /dev/null +++ b/fs/netfs/direct_read.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Direct I/O support. + * + * Copyright (C) 2023 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" + +/* + * Copy all of the data from the folios in the source xarray into the + * destination iterator. We cannot step through and kmap the dest iterator if + * it's an iovec, so we have to step through the xarray and drop the RCU lock + * each time. + */ +static int netfs_copy_xarray_to_iter(struct netfs_io_request *rreq, + struct xarray *xa, struct iov_iter *dst, + unsigned long long start, size_t avail) +{ + struct folio *folio; + void *base; + pgoff_t index = start / PAGE_SIZE; + size_t len, copied, count = min(avail, iov_iter_count(dst)); + + XA_STATE(xas, xa, index); + + _enter("%zx", count); + + if (!count) { + trace_netfs_failure(rreq, NULL, -EIO, netfs_fail_dio_read_zero); + return -EIO; + } + + len = PAGE_SIZE - offset_in_page(start); + rcu_read_lock(); + xas_for_each(&xas, folio, ULONG_MAX) { + size_t offset; + + if (xas_retry(&xas, folio)) + continue; + + /* There shouldn't be a need to call xas_pause() as no one else + * should be modifying the xarray we're iterating over. + * Really, we only need the RCU readlock to keep lockdep happy + * inside xas_for_each(). + */ + rcu_read_unlock(); + + offset = offset_in_folio(folio, start); + kdebug("folio %lx +%zx [%llx]", folio->index, offset, start); + + while (offset < folio_size(folio)) { + len = min(count, len); + + base = kmap_local_folio(folio, offset); + copied = copy_to_iter(base, len, dst); + kunmap_local(base); + if (copied != len) + goto out; + count -= len; + if (count == 0) + goto out; + + start += len; + offset += len; + len = PAGE_SIZE; + } + + rcu_read_lock(); + } + + rcu_read_unlock(); +out: + _leave(" = %zx", count); + return count ? -EFAULT : 0; +} + +/* + * If we did a direct read to a bounce buffer (say we needed to decrypt it), + * copy the data obtained to the destination iterator. + */ +static int netfs_dio_copy_bounce_to_dest(struct netfs_io_request *rreq) +{ + struct iov_iter *dest_iter = &rreq->iter; + struct kiocb *iocb = rreq->iocb; + unsigned long long start = rreq->start; + + _enter("%zx/%zx @%llx", rreq->transferred, rreq->len, start); + + if (!test_bit(NETFS_RREQ_USE_BOUNCE_BUFFER, &rreq->flags)) + return 0; + + if (start < iocb->ki_pos) { + if (rreq->transferred <= iocb->ki_pos - start) { + trace_netfs_failure(rreq, NULL, -EIO, netfs_fail_dio_read_short); + return -EIO; + } + rreq->len = rreq->transferred; + rreq->transferred -= iocb->ki_pos - start; + } + + if (rreq->transferred > iov_iter_count(dest_iter)) + rreq->transferred = iov_iter_count(dest_iter); + + _debug("xfer %zx/%zx @%llx", rreq->transferred, rreq->len, iocb->ki_pos); + return netfs_copy_xarray_to_iter(rreq, &rreq->bounce, dest_iter, + iocb->ki_pos, rreq->transferred); +} + +/** + * netfs_unbuffered_read_iter_locked - Perform an unbuffered or direct I/O read + * @iocb: The I/O control descriptor describing the read + * @iter: The output buffer (also specifies read length) + * + * Perform an unbuffered I/O or direct I/O from the file in @iocb to the + * output buffer. No use is made of the pagecache. + * + * The caller must hold any appropriate locks. + */ +static ssize_t netfs_unbuffered_read_iter_locked(struct kiocb *iocb, struct iov_iter *iter) +{ + struct netfs_io_request *rreq; + struct netfs_inode *ctx; + unsigned long long start, end; + unsigned int min_bsize; + pgoff_t first, last; + ssize_t ret; + size_t orig_count = iov_iter_count(iter); + bool async = !is_sync_kiocb(iocb); + + _enter(""); + + if (!orig_count) + return 0; /* Don't update atime */ + + ret = kiocb_write_and_wait(iocb, orig_count); + if (ret < 0) + return ret; + file_accessed(iocb->ki_filp); + + rreq = netfs_alloc_request(iocb->ki_filp->f_mapping, iocb->ki_filp, + iocb->ki_pos, orig_count, + NETFS_DIO_READ); + if (IS_ERR(rreq)) + return PTR_ERR(rreq); + + ctx = netfs_inode(rreq->inode); + netfs_stat(&netfs_n_rh_dio_read); + trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_dio_read); + + /* If this is an async op, we have to keep track of the destination + * buffer for ourselves as the caller's iterator will be trashed when + * we return. + * + * In such a case, extract an iterator to represent as much of the the + * output buffer as we can manage. Note that the extraction might not + * be able to allocate a sufficiently large bvec array and may shorten + * the request. + */ + if (user_backed_iter(iter)) { + ret = netfs_extract_user_iter(iter, rreq->len, &rreq->iter, 0); + if (ret < 0) + goto out; + rreq->direct_bv = (struct bio_vec *)rreq->iter.bvec; + rreq->direct_bv_count = ret; + rreq->direct_bv_unpin = iov_iter_extract_will_pin(iter); + rreq->len = iov_iter_count(&rreq->iter); + } else { + rreq->iter = *iter; + rreq->len = orig_count; + rreq->direct_bv_unpin = false; + iov_iter_advance(iter, orig_count); + } + + /* If we're going to use a bounce buffer, we need to set it up. We + * will then need to pad the request out to the minimum block size. + */ + if (test_bit(NETFS_RREQ_USE_BOUNCE_BUFFER, &rreq->flags)) { + start = rreq->start; + end = min_t(unsigned long long, + round_up(rreq->start + rreq->len, min_bsize), + ctx->remote_i_size); + + rreq->start = start; + rreq->len = end - start; + first = start / PAGE_SIZE; + last = (end - 1) / PAGE_SIZE; + _debug("bounce %llx-%llx %lx-%lx", + rreq->start, end, first, last); + + ret = netfs_add_folios_to_buffer(&rreq->bounce, rreq->mapping, + first, last, GFP_KERNEL); + if (ret < 0) + goto out; + } + + if (async) + rreq->iocb = iocb; + + ret = netfs_begin_read(rreq, is_sync_kiocb(iocb)); + if (ret < 0) + goto out; /* May be -EIOCBQUEUED */ + if (!async) { + ret = netfs_dio_copy_bounce_to_dest(rreq); + if (ret == 0) { + iocb->ki_pos += rreq->transferred; + ret = rreq->transferred; + } + } + +out: + netfs_put_request(rreq, false, netfs_rreq_trace_put_return); + if (ret > 0) + orig_count -= ret; + if (ret != -EIOCBQUEUED) + iov_iter_revert(iter, orig_count - iov_iter_count(iter)); + return ret; +} + +/** + * netfs_unbuffered_read_iter - Perform an unbuffered or direct I/O read + * @iocb: The I/O control descriptor describing the read + * @iter: The output buffer (also specifies read length) + * + * Perform an unbuffered I/O or direct I/O from the file in @iocb to the + * output buffer. No use is made of the pagecache. + */ +ssize_t netfs_unbuffered_read_iter(struct kiocb *iocb, struct iov_iter *iter) +{ + struct inode *inode = file_inode(iocb->ki_filp); + ssize_t ret; + + if (!iter->count) + return 0; /* Don't update atime */ + + ret = netfs_start_io_direct(inode); + if (ret == 0) { + ret = netfs_unbuffered_read_iter_locked(iocb, iter); + netfs_end_io_direct(inode); + } + return ret; +} +EXPORT_SYMBOL(netfs_unbuffered_read_iter); diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 62c349cc71f9..5bb1cdbdee0e 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -100,6 +100,7 @@ int netfs_begin_write(struct netfs_io_request *wreq, bool may_wait, * stats.c */ #ifdef CONFIG_NETFS_STATS +extern atomic_t netfs_n_rh_dio_read; extern atomic_t netfs_n_rh_readahead; extern atomic_t netfs_n_rh_readpage; extern atomic_t netfs_n_rh_rreq; diff --git a/fs/netfs/io.c b/fs/netfs/io.c index 776ca0aa6b62..e017dc735cdb 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -78,7 +78,9 @@ static void netfs_read_from_server(struct netfs_io_request *rreq, struct netfs_io_subrequest *subreq) { netfs_stat(&netfs_n_rh_download); - if (iov_iter_count(&subreq->io_iter) != subreq->len - subreq->transferred) + + if (rreq->origin != NETFS_DIO_READ && + iov_iter_count(&subreq->io_iter) != subreq->len - subreq->transferred) pr_warn("R=%08x[%u] ITER PRE-MISMATCH %zx != %zx-%zx %lx\n", rreq->debug_id, subreq->debug_index, iov_iter_count(&subreq->io_iter), subreq->len, @@ -341,6 +343,43 @@ static void netfs_rreq_is_still_valid(struct netfs_io_request *rreq) } } +/* + * Determine how much we can admit to having read from a DIO read. + */ +static void netfs_rreq_assess_dio(struct netfs_io_request *rreq) +{ + struct netfs_io_subrequest *subreq; + unsigned int i; + size_t transferred = 0; + + for (i = 0; i < rreq->direct_bv_count; i++) + flush_dcache_page(rreq->direct_bv[i].bv_page); + + list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { + if (subreq->error || subreq->transferred == 0) + break; + transferred += subreq->transferred; + if (subreq->transferred < subreq->len) + break; + } + + for (i = 0; i < rreq->direct_bv_count; i++) + flush_dcache_page(rreq->direct_bv[i].bv_page); + + rreq->transferred = transferred; + task_io_account_read(transferred); + + if (rreq->iocb) { + rreq->iocb->ki_pos += transferred; + if (rreq->iocb->ki_complete) + rreq->iocb->ki_complete( + rreq->iocb, rreq->error ? rreq->error : transferred); + } + if (rreq->netfs_ops->done) + rreq->netfs_ops->done(rreq); + inode_dio_end(rreq->inode); +} + /* * Assess the state of a read request and decide what to do next. * @@ -361,7 +400,10 @@ static void netfs_rreq_assess(struct netfs_io_request *rreq, bool was_async) return; } - netfs_rreq_unlock_folios(rreq); + if (rreq->origin != NETFS_DIO_READ) + netfs_rreq_unlock_folios(rreq); + else + netfs_rreq_assess_dio(rreq); trace_netfs_rreq(rreq, netfs_rreq_trace_wake_ip); clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &rreq->flags); @@ -526,14 +568,16 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq, struct netfs_io_subrequest *subreq, struct iov_iter *io_iter) { - enum netfs_io_source source; + enum netfs_io_source source = NETFS_DOWNLOAD_FROM_SERVER; size_t lsize; _enter("%llx-%llx,%llx", subreq->start, subreq->start + subreq->len, rreq->i_size); - source = netfs_cache_prepare_read(subreq, rreq->i_size); - if (source == NETFS_INVALID_READ) - goto out; + if (rreq->origin != NETFS_DIO_READ) { + source = netfs_cache_prepare_read(subreq, rreq->i_size); + if (source == NETFS_INVALID_READ) + goto out; + } if (source == NETFS_DOWNLOAD_FROM_SERVER) { /* Call out to the netfs to let it shrink the request to fit @@ -544,6 +588,8 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq, */ if (subreq->len > rreq->i_size - subreq->start) subreq->len = rreq->i_size - subreq->start; + if (rreq->rsize && subreq->len > rreq->rsize) + subreq->len = rreq->rsize; if (rreq->netfs_ops->clamp_length && !rreq->netfs_ops->clamp_length(subreq)) { @@ -662,6 +708,9 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) return -EIO; } + if (rreq->origin == NETFS_DIO_READ) + inode_dio_begin(rreq->inode); + if (test_bit(NETFS_RREQ_USE_BOUNCE_BUFFER, &rreq->flags)) iov_iter_xarray(&rreq->io_iter, ITER_DEST, &rreq->bounce, rreq->start, rreq->len); @@ -677,11 +726,25 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) atomic_set(&rreq->nr_outstanding, 1); io_iter = rreq->io_iter; do { + _debug("submit %llx + %zx >= %llx", + rreq->start, rreq->submitted, rreq->i_size); + if (rreq->origin == NETFS_DIO_READ && + rreq->start + rreq->submitted >= rreq->i_size) + break; if (!netfs_rreq_submit_slice(rreq, &io_iter, &debug_index)) break; + if (test_bit(NETFS_RREQ_BLOCKED, &rreq->flags) && + test_bit(NETFS_RREQ_NONBLOCK, &rreq->flags)) + break; } while (rreq->submitted < rreq->len); + if (!rreq->submitted) { + netfs_put_request(rreq, false, netfs_rreq_trace_put_no_submit); + ret = 0; + goto out; + } + if (sync) { /* Keep nr_outstanding incremented so that the ref always * belongs to us, and the service code isn't punted off to a @@ -698,7 +761,8 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) TASK_UNINTERRUPTIBLE); ret = rreq->error; - if (ret == 0 && rreq->submitted < rreq->len) { + if (ret == 0 && rreq->submitted < rreq->len && + rreq->origin != NETFS_DIO_READ) { trace_netfs_failure(rreq, NULL, ret, netfs_fail_short_read); ret = -EIO; } @@ -706,7 +770,9 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) /* 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 = 0; + ret = -EIOCBQUEUED; } + +out: return ret; } diff --git a/fs/netfs/main.c b/fs/netfs/main.c index 6584eafda944..d4430b51b03c 100644 --- a/fs/netfs/main.c +++ b/fs/netfs/main.c @@ -33,6 +33,7 @@ static const char *netfs_origins[nr__netfs_io_origin] = { [NETFS_READPAGE] = "RP", [NETFS_READ_FOR_WRITE] = "RW", [NETFS_WRITEBACK] = "WB", + [NETFS_DIO_READ] = "DR", }; /* diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 3ce6313cc5f9..d46e957812a6 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -20,7 +20,8 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, struct inode *inode = file ? file_inode(file) : mapping->host; struct netfs_inode *ctx = netfs_inode(inode); struct netfs_io_request *rreq; - bool cached = netfs_is_cache_enabled(ctx); + bool is_dio = (origin == NETFS_DIO_READ); + bool cached = is_dio && netfs_is_cache_enabled(ctx); int ret; rreq = kzalloc(ctx->ops->io_request_size ?: sizeof(struct netfs_io_request), @@ -43,6 +44,8 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); if (cached) __set_bit(NETFS_RREQ_WRITE_TO_CACHE, &rreq->flags); + if (file && file->f_flags & O_NONBLOCK) + __set_bit(NETFS_RREQ_NONBLOCK, &rreq->flags); if (rreq->netfs_ops->init_request) { ret = rreq->netfs_ops->init_request(rreq, file); if (ret < 0) { diff --git a/fs/netfs/stats.c b/fs/netfs/stats.c index c1f85cd595a4..15fd5c3f0f39 100644 --- a/fs/netfs/stats.c +++ b/fs/netfs/stats.c @@ -9,6 +9,7 @@ #include #include "internal.h" +atomic_t netfs_n_rh_dio_read; atomic_t netfs_n_rh_readahead; atomic_t netfs_n_rh_readpage; atomic_t netfs_n_rh_rreq; @@ -36,7 +37,8 @@ atomic_t netfs_n_wh_write_failed; int netfs_stats_show(struct seq_file *m, void *v) { - seq_printf(m, "Netfs : RA=%u RP=%u WB=%u WBZ=%u rr=%u sr=%u\n", + seq_printf(m, "Netfs : DR=%u RA=%u RP=%u WB=%u WBZ=%u rr=%u sr=%u\n", + atomic_read(&netfs_n_rh_dio_read), atomic_read(&netfs_n_rh_readahead), atomic_read(&netfs_n_rh_readpage), atomic_read(&netfs_n_rh_write_begin), diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 63258998defb..da391f8c81c7 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -226,6 +226,7 @@ enum netfs_io_origin { NETFS_READPAGE, /* This read is a synchronous read */ NETFS_READ_FOR_WRITE, /* This read is to prepare a write */ NETFS_WRITEBACK, /* This write was triggered by writepages */ + NETFS_DIO_READ, /* This is a direct I/O read */ nr__netfs_io_origin } __mode(byte); @@ -240,6 +241,7 @@ struct netfs_io_request { }; struct inode *inode; /* The file being accessed */ struct address_space *mapping; /* The mapping being accessed */ + struct kiocb *iocb; /* AIO completion vector */ struct netfs_cache_resources cache_resources; struct list_head proc_link; /* Link in netfs_iorequests */ struct list_head subrequests; /* Contributory I/O operations */ @@ -251,12 +253,14 @@ struct netfs_io_request { __counted_by(direct_bv_count); unsigned int direct_bv_count; /* Number of elements in direct_bv[] */ unsigned int debug_id; + unsigned int rsize; /* Maximum read size (0 for none) */ unsigned int wsize; /* Maximum write size (0 for none) */ unsigned int subreq_counter; /* Next subreq->debug_index */ 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 */ + size_t transferred; /* Amount to be indicated as transferred */ short error; /* 0 or error that occurred */ enum netfs_io_origin origin; /* Origin of the request */ bool direct_bv_unpin; /* T if direct_bv[] must be unpinned */ @@ -274,6 +278,8 @@ struct netfs_io_request { #define NETFS_RREQ_USE_BOUNCE_BUFFER 6 /* Use bounce buffer */ #define NETFS_RREQ_WRITE_TO_CACHE 7 /* Need to write to the cache */ #define NETFS_RREQ_UPLOAD_TO_SERVER 8 /* Need to write to the server */ +#define NETFS_RREQ_NONBLOCK 9 /* Don't block if possible (O_NONBLOCK) */ +#define NETFS_RREQ_BLOCKED 10 /* We blocked */ const struct netfs_request_ops *netfs_ops; void (*cleanup)(struct netfs_io_request *req); }; @@ -370,6 +376,9 @@ struct netfs_cache_ops { loff_t *_data_start, size_t *_data_len); }; +/* High-level read API. */ +ssize_t netfs_unbuffered_read_iter(struct kiocb *iocb, struct iov_iter *iter); + /* High-level write API */ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, struct netfs_group *netfs_group); diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 082a5e717b58..5a4edadf0e59 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -16,6 +16,7 @@ * Define enums for tracing information. */ #define netfs_read_traces \ + EM(netfs_read_trace_dio_read, "DIO-READ ") \ EM(netfs_read_trace_expanded, "EXPANDED ") \ EM(netfs_read_trace_readahead, "READAHEAD") \ EM(netfs_read_trace_readpage, "READPAGE ") \ @@ -31,7 +32,8 @@ EM(NETFS_READAHEAD, "RA") \ EM(NETFS_READPAGE, "RP") \ EM(NETFS_READ_FOR_WRITE, "RW") \ - E_(NETFS_WRITEBACK, "WB") + EM(NETFS_WRITEBACK, "WB") \ + E_(NETFS_DIO_READ, "DR") #define netfs_rreq_traces \ EM(netfs_rreq_trace_assess, "ASSESS ") \ @@ -70,6 +72,8 @@ #define netfs_failures \ EM(netfs_fail_check_write_begin, "check-write-begin") \ EM(netfs_fail_copy_to_cache, "copy-to-cache") \ + EM(netfs_fail_dio_read_short, "dio-read-short") \ + EM(netfs_fail_dio_read_zero, "dio-read-zero") \ EM(netfs_fail_read, "read") \ EM(netfs_fail_short_read, "short-read") \ EM(netfs_fail_prepare_write, "prep-write") \ @@ -81,6 +85,7 @@ 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_no_submit, "PUT NO-SUBM") \ EM(netfs_rreq_trace_put_return, "PUT RETURN ") \ EM(netfs_rreq_trace_put_subreq, "PUT SUBREQ ") \ EM(netfs_rreq_trace_put_work, "PUT WORK ") \ diff --git a/mm/filemap.c b/mm/filemap.c index c0d7e1d7eea2..85a8eb23cfd2 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2678,6 +2678,7 @@ int kiocb_write_and_wait(struct kiocb *iocb, size_t count) return filemap_write_and_wait_range(mapping, pos, end); } +EXPORT_SYMBOL_GPL(kiocb_write_and_wait); int kiocb_invalidate_pages(struct kiocb *iocb, size_t count) { From patchwork Wed Dec 13 15:23:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491234 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 24F99C4332F for ; Wed, 13 Dec 2023 15:26:12 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id ADCB96B00DF; Wed, 13 Dec 2023 10:26:11 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id A8B256B00E2; Wed, 13 Dec 2023 10:26:11 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 902626B00E4; Wed, 13 Dec 2023 10:26:11 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 7AF196B00DF for ; Wed, 13 Dec 2023 10:26:11 -0500 (EST) Received: from smtpin29.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 5568FA01BB for ; Wed, 13 Dec 2023 15:26:11 +0000 (UTC) X-FDA: 81562170942.29.1C9507E Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf26.hostedemail.com (Postfix) with ESMTP id 91AAB140002 for ; Wed, 13 Dec 2023 15:26:09 +0000 (UTC) Authentication-Results: imf26.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=fUkGFbsO; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf26.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481169; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=soahaV3Ag+Cs3wN9SRRVq/36ef3xCwusWO4Gbn5hYDY=; b=aB75vFmkUxGT8RyWgOzEFZvZnrIeEvqlWs6GCFivqFB1pmjQ1Kqf7BgR96x6IM6TcenwbR E8SI9Ei54kjmlW4i2Hte/M6IgahrWiuIY0b8sT6DTV+pA/kXJbx/Z/ocgnPpCS8ikGAN0q unrtA2dzTBuue/LFwnPq5ZuIzrzMqN4= ARC-Authentication-Results: i=1; imf26.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=fUkGFbsO; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf26.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481169; a=rsa-sha256; cv=none; b=8oYknv/TKKBuvc3eOcq5FBkr+ckYhcB2CI8vAraFBqxvdRTmnttgoylh53vmPRGs3tBDg7 xSKYPaJmc/FT6AgcaAagUpAevfln+lvGhxBOrdWWMBxOf+5Vw8p1owwQi+VL+YhzgLPSlV Yst07xj7zFb+izvdZGF8exr7k2MPbF0= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481168; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=soahaV3Ag+Cs3wN9SRRVq/36ef3xCwusWO4Gbn5hYDY=; b=fUkGFbsOb0yvJKwWKCl7aWT0g1XPaLAxvBMWSHJVfZq6+qYa7q0fxrPlN6KUP4HYuXKNIQ FP9TqWWLhoa5+p7meP/jYAIEgdy3Pa3BZTHVzaO8Zpc4VrMdIX/3CZe1/YEKbFZ2mBsP+y Lg0QHEinJ6wcRbO/RM6HgJX1avaJAbM= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-426-U2OrQWLGOcGyj7SuIU9gJA-1; Wed, 13 Dec 2023 10:26:04 -0500 X-MC-Unique: U2OrQWLGOcGyj7SuIU9gJA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 954611C18CC3; Wed, 13 Dec 2023 15:26:02 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id E15ED3C25; Wed, 13 Dec 2023 15:25:58 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 29/39] netfs: Implement unbuffered/DIO write support Date: Wed, 13 Dec 2023 15:23:39 +0000 Message-ID: <20231213152350.431591-30-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Rspamd-Server: rspam09 X-Rspamd-Queue-Id: 91AAB140002 X-Stat-Signature: c81dxjo9is7thpuobb81eaytmzofn5rh X-Rspam-User: X-HE-Tag: 1702481169-848348 X-HE-Meta: U2FsdGVkX19BQCS/mo7VBYQ/kA0y0S4Upg4sVSG/OhvVbt2DyXbRdz1vDZbqDVFtA9c7jnJDqszWrZMKLNaXX0zGI0WkRb7QNbOqOg9AzfihVXpsVexHHbXUKmllpQaoUk1ojX5+DTGMMASR04i8n0fdtkuhNl9EwGKt13i8K6SbkjUn+atnDcJeCBqBI4P9fbGLXVqJ40SorCeAdTK2iA4WDBfPV6nB/D+kkllzvjrKK9pUBx/0vutQ/E+j2Eiv3gKccKu2IaclP8XfG94rflpo91yDt3DDtA5araiq1qWTsJMxZvVRYmdMnkmyTrK54SIeAfy0t10YHX/YJ8rjQBWo6PlI6xckscUZziJdqNK318QXcWGRAksb8lTiOY8s/8nozOl1jnT/ona/sT+GkZRl+1rTx8vA+3i/V0ZnYweqYVSL2jpEzF9lUzUTBFMTHt1UsPe7Z7cBhU3FBUN/zKATvb3xVVZio4CV+5rbRWCboWSNE3zVb7j1wQziXkMmQfgIPipm9aDk2kltjwybHDQHSscMKoP09fRVf2LSkeuNbPB7qmFiKn/Eh84cpourYW7wHxyAr6HPUdMEx+VooU1PFWr5V/wI9AZEoNbUEFYFxOI0AM1nB6svXl79/3vXw4h1b96ZOgIWc44WAIa73xSIthdf6PSXW0ZwoxZseSkH34CoNhHHP2kLBnJEpYjQg8ZO3SOGcCWH72tU5LHbRlEt3wBUm9Pk01BzkjmaRWO8wac3TF9WEagbIhyu2240Ls05Q9cP2n0IYtpSsICv31SnZNehEOCBlltt2xQI7Z8Z8vgttcAU/exLqYZJ8ND2qIHcRzTxi2itx5IaF1yppN1FcQAaUIYVUSmGIKRO+3RXnsEukXE4wD/ogVwNt7mgECKK6cUgpXVWz/MVxzyUSKHaAAxpUyskY66VN+4gp6H/uTwaI7v086tUFXwvkmvDLlk//vU3cKimaIIJCqX wIV9kBIi 6mrCaKAwBNsN/W+XdmQZNnD1XADyAsy0AZSTPCmL55OezZabTxRheENkJY5HsyB00f5iDnnf63fyi2GFzVM3LuJ2jkrfR6s3YKsJZr//Wm9vYZdRDUO3pv4ZVzr/CUVckIVT+2TMZitq+FFVseQPSa3AePXs9r5WE6QYrqM2+93sakQ6RjeN7mRssVM2Fjy/UAGeLxENZy//FD5uwuj3G7r5M8r+FZ9BUxRJR2jdXfvwKVsFEDVdl0ajEzlXQFEvYB1igVTvmUk0I2ZaJ6yGF3+EKTxthrRjrxlW/2GRA3v1Mtu9AAt13WW8BgBGvO09cq6Su X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Implement support for unbuffered writes and direct I/O writes. If the write is misaligned with respect to the fscrypt block size, then RMW cycles are performed if necessary. DIO writes are a special case of unbuffered writes with extra restriction imposed, such as block size alignment requirements. Also provide a field that can tell the code to add some extra space onto the bounce buffer for use by the filesystem in the case of a content-encrypted file. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/afs/inode.c | 2 +- fs/netfs/Makefile | 1 + fs/netfs/direct_write.c | 166 +++++++++++++++++++++++++++++++++++ fs/netfs/internal.h | 6 ++ fs/netfs/io.c | 2 +- fs/netfs/main.c | 12 +-- fs/netfs/objects.c | 6 +- fs/netfs/output.c | 30 +++++++ include/linux/netfs.h | 4 + include/trace/events/netfs.h | 4 +- 10 files changed, 223 insertions(+), 10 deletions(-) create mode 100644 fs/netfs/direct_write.c diff --git a/fs/afs/inode.c b/fs/afs/inode.c index de3e8fec54b7..c43112dcbbbb 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -249,7 +249,7 @@ static void afs_apply_status(struct afs_operation *op, * what's on the server. */ vnode->netfs.remote_i_size = status->size; - if (change_size) { + if (change_size || status->size > i_size_read(inode)) { afs_set_i_size(vnode, status->size); inode_set_ctime_to_ts(inode, t); inode_set_atime_to_ts(inode, t); diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index e968ab1eca40..d4d1d799819e 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -4,6 +4,7 @@ netfs-y := \ buffered_read.o \ buffered_write.o \ direct_read.o \ + direct_write.o \ io.o \ iterator.o \ locking.o \ diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c new file mode 100644 index 000000000000..bb0c2718f57b --- /dev/null +++ b/fs/netfs/direct_write.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Unbuffered and direct write support. + * + * Copyright (C) 2023 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include +#include +#include "internal.h" + +static void netfs_cleanup_dio_write(struct netfs_io_request *wreq) +{ + struct inode *inode = wreq->inode; + unsigned long long end = wreq->start + wreq->len; + + if (!wreq->error && + i_size_read(inode) < end) { + if (wreq->netfs_ops->update_i_size) + wreq->netfs_ops->update_i_size(inode, end); + else + i_size_write(inode, end); + } +} + +/* + * Perform an unbuffered write where we may have to do an RMW operation on an + * encrypted file. This can also be used for direct I/O writes. + */ +ssize_t netfs_unbuffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *iter, + struct netfs_group *netfs_group) +{ + struct netfs_io_request *wreq; + unsigned long long start = iocb->ki_pos; + unsigned long long end = start + iov_iter_count(iter); + ssize_t ret, n; + bool async = !is_sync_kiocb(iocb); + + _enter(""); + + /* We're going to need a bounce buffer if what we transmit is going to + * be different in some way to the source buffer, e.g. because it gets + * encrypted/compressed or because it needs expanding to a block size. + */ + // TODO + + _debug("uw %llx-%llx", start, end); + + wreq = netfs_alloc_request(iocb->ki_filp->f_mapping, iocb->ki_filp, + start, end - start, + iocb->ki_flags & IOCB_DIRECT ? + NETFS_DIO_WRITE : NETFS_UNBUFFERED_WRITE); + if (IS_ERR(wreq)) + return PTR_ERR(wreq); + + { + /* If this is an async op and we're not using a bounce buffer, + * we have to save the source buffer as the iterator is only + * good until we return. In such a case, extract an iterator + * to represent as much of the the output buffer as we can + * manage. Note that the extraction might not be able to + * allocate a sufficiently large bvec array and may shorten the + * request. + */ + if (async || user_backed_iter(iter)) { + n = netfs_extract_user_iter(iter, wreq->len, &wreq->iter, 0); + if (n < 0) { + ret = n; + goto out; + } + wreq->direct_bv = (struct bio_vec *)wreq->iter.bvec; + wreq->direct_bv_count = n; + wreq->direct_bv_unpin = iov_iter_extract_will_pin(iter); + wreq->len = iov_iter_count(&wreq->iter); + } else { + wreq->iter = *iter; + } + + wreq->io_iter = wreq->iter; + } + + /* Copy the data into the bounce buffer and encrypt it. */ + // TODO + + /* Dispatch the write. */ + __set_bit(NETFS_RREQ_UPLOAD_TO_SERVER, &wreq->flags); + if (async) + wreq->iocb = iocb; + wreq->cleanup = netfs_cleanup_dio_write; + ret = netfs_begin_write(wreq, is_sync_kiocb(iocb), + iocb->ki_flags & IOCB_DIRECT ? + netfs_write_trace_dio_write : + netfs_write_trace_unbuffered_write); + if (ret < 0) { + _debug("begin = %zd", ret); + goto out; + } + + if (!async) { + trace_netfs_rreq(wreq, netfs_rreq_trace_wait_ip); + wait_on_bit(&wreq->flags, NETFS_RREQ_IN_PROGRESS, + TASK_UNINTERRUPTIBLE); + + ret = wreq->error; + _debug("waited = %zd", ret); + if (ret == 0) { + ret = wreq->transferred; + iocb->ki_pos += ret; + } + } else { + ret = -EIOCBQUEUED; + } + +out: + netfs_put_request(wreq, false, netfs_rreq_trace_put_return); + return ret; +} + +/** + * netfs_unbuffered_write_iter - Unbuffered write to a file + * @iocb: IO state structure + * @from: iov_iter with data to write + * + * Do an unbuffered write to a file, writing the data directly to the server + * and not lodging the data in the pagecache. + * + * Return: + * * Negative error code if no data has been written at all of + * vfs_fsync_range() failed for a synchronous write + * * Number of bytes written, even for truncated writes + */ +ssize_t netfs_unbuffered_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file->f_mapping->host; + struct netfs_inode *ictx = netfs_inode(inode); + ssize_t ret; + + _enter("%llx,%zx,%llx", iocb->ki_pos, iov_iter_count(from), i_size_read(inode)); + + trace_netfs_write_iter(iocb, from); + + ret = netfs_start_io_direct(inode); + if (ret < 0) + return ret; + ret = generic_write_checks(iocb, from); + if (ret < 0) + goto out; + ret = file_remove_privs(file); + if (ret < 0) + goto out; + ret = file_update_time(file); + if (ret < 0) + goto out; + ret = kiocb_invalidate_pages(iocb, iov_iter_count(from)); + if (ret < 0) + goto out; + + fscache_invalidate(netfs_i_cookie(ictx), NULL, i_size_read(inode), + FSCACHE_INVAL_DIO_WRITE); + ret = netfs_unbuffered_write_iter_locked(iocb, from, NULL); +out: + netfs_end_io_direct(inode); + return ret; +} +EXPORT_SYMBOL(netfs_unbuffered_write_iter); diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 5bb1cdbdee0e..fe72280b0f30 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -26,6 +26,12 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq); int netfs_prefetch_for_write(struct file *file, struct folio *folio, size_t offset, size_t len); +/* + * direct_write.c + */ +ssize_t netfs_unbuffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *iter, + struct netfs_group *netfs_group); + /* * io.c */ diff --git a/fs/netfs/io.c b/fs/netfs/io.c index e017dc735cdb..894c3305710d 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -645,7 +645,7 @@ static bool netfs_rreq_submit_slice(struct netfs_io_request *rreq, subreq->debug_index = (*_debug_index)++; subreq->start = rreq->start + rreq->submitted; - subreq->len = rreq->len - rreq->submitted; + subreq->len = io_iter->count; _debug("slice %llx,%zx,%zx", subreq->start, subreq->len, rreq->submitted); list_add_tail(&subreq->rreq_link, &rreq->subrequests); diff --git a/fs/netfs/main.c b/fs/netfs/main.c index d4430b51b03c..9fe96de6960e 100644 --- a/fs/netfs/main.c +++ b/fs/netfs/main.c @@ -29,11 +29,13 @@ LIST_HEAD(netfs_io_requests); DEFINE_SPINLOCK(netfs_proc_lock); static const char *netfs_origins[nr__netfs_io_origin] = { - [NETFS_READAHEAD] = "RA", - [NETFS_READPAGE] = "RP", - [NETFS_READ_FOR_WRITE] = "RW", - [NETFS_WRITEBACK] = "WB", - [NETFS_DIO_READ] = "DR", + [NETFS_READAHEAD] = "RA", + [NETFS_READPAGE] = "RP", + [NETFS_READ_FOR_WRITE] = "RW", + [NETFS_WRITEBACK] = "WB", + [NETFS_UNBUFFERED_WRITE] = "UW", + [NETFS_DIO_READ] = "DR", + [NETFS_DIO_WRITE] = "DW", }; /* diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index d46e957812a6..c1218b183197 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -20,8 +20,10 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, struct inode *inode = file ? file_inode(file) : mapping->host; struct netfs_inode *ctx = netfs_inode(inode); struct netfs_io_request *rreq; - bool is_dio = (origin == NETFS_DIO_READ); - bool cached = is_dio && netfs_is_cache_enabled(ctx); + bool is_unbuffered = (origin == NETFS_UNBUFFERED_WRITE || + origin == NETFS_DIO_READ || + origin == NETFS_DIO_WRITE); + bool cached = !is_unbuffered && netfs_is_cache_enabled(ctx); int ret; rreq = kzalloc(ctx->ops->io_request_size ?: sizeof(struct netfs_io_request), diff --git a/fs/netfs/output.c b/fs/netfs/output.c index 2ad0fd8c32be..560cbcea0c0a 100644 --- a/fs/netfs/output.c +++ b/fs/netfs/output.c @@ -74,11 +74,21 @@ static void netfs_write_terminated(struct netfs_io_request *wreq, bool was_async { struct netfs_io_subrequest *subreq; struct netfs_inode *ctx = netfs_inode(wreq->inode); + size_t transferred = 0; _enter("R=%x[]", wreq->debug_id); trace_netfs_rreq(wreq, netfs_rreq_trace_write_done); + list_for_each_entry(subreq, &wreq->subrequests, rreq_link) { + if (subreq->error || subreq->transferred == 0) + break; + transferred += subreq->transferred; + if (subreq->transferred < subreq->len) + break; + } + wreq->transferred = transferred; + list_for_each_entry(subreq, &wreq->subrequests, rreq_link) { if (!subreq->error) continue; @@ -110,11 +120,28 @@ static void netfs_write_terminated(struct netfs_io_request *wreq, bool was_async wreq->cleanup(wreq); + if (wreq->origin == NETFS_DIO_WRITE && + wreq->mapping->nrpages) { + pgoff_t first = wreq->start >> PAGE_SHIFT; + pgoff_t last = (wreq->start + wreq->transferred - 1) >> PAGE_SHIFT; + invalidate_inode_pages2_range(wreq->mapping, first, last); + } + + if (wreq->origin == NETFS_DIO_WRITE) + inode_dio_end(wreq->inode); + _debug("finished"); trace_netfs_rreq(wreq, netfs_rreq_trace_wake_ip); clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &wreq->flags); wake_up_bit(&wreq->flags, NETFS_RREQ_IN_PROGRESS); + if (wreq->iocb) { + wreq->iocb->ki_pos += transferred; + if (wreq->iocb->ki_complete) + wreq->iocb->ki_complete( + wreq->iocb, wreq->error ? wreq->error : transferred); + } + netfs_clear_subrequests(wreq, was_async); netfs_put_request(wreq, was_async, netfs_rreq_trace_put_complete); } @@ -329,6 +356,9 @@ int netfs_begin_write(struct netfs_io_request *wreq, bool may_wait, return -EIO; } + if (wreq->origin == NETFS_DIO_WRITE) + inode_dio_begin(wreq->inode); + wreq->io_iter = wreq->iter; /* ->outstanding > 0 carries a ref */ diff --git a/include/linux/netfs.h b/include/linux/netfs.h index da391f8c81c7..00c87f4e809c 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -138,6 +138,7 @@ struct netfs_inode { loff_t remote_i_size; /* Size of the remote file */ unsigned long flags; #define NETFS_ICTX_ODIRECT 0 /* The file has DIO in progress */ +#define NETFS_ICTX_UNBUFFERED 1 /* I/O should not use the pagecache */ }; /* @@ -226,7 +227,9 @@ enum netfs_io_origin { NETFS_READPAGE, /* This read is a synchronous read */ NETFS_READ_FOR_WRITE, /* This read is to prepare a write */ NETFS_WRITEBACK, /* This write was triggered by writepages */ + NETFS_UNBUFFERED_WRITE, /* This is an unbuffered write */ NETFS_DIO_READ, /* This is a direct I/O read */ + NETFS_DIO_WRITE, /* This is a direct I/O write */ nr__netfs_io_origin } __mode(byte); @@ -382,6 +385,7 @@ ssize_t netfs_unbuffered_read_iter(struct kiocb *iocb, struct iov_iter *iter); /* High-level write API */ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, struct netfs_group *netfs_group); +ssize_t netfs_unbuffered_write_iter(struct kiocb *iocb, struct iov_iter *from); /* Address operations API */ struct readahead_control; diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 5a4edadf0e59..914a24b03d08 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -33,7 +33,9 @@ EM(NETFS_READPAGE, "RP") \ EM(NETFS_READ_FOR_WRITE, "RW") \ EM(NETFS_WRITEBACK, "WB") \ - E_(NETFS_DIO_READ, "DR") + EM(NETFS_UNBUFFERED_WRITE, "UW") \ + EM(NETFS_DIO_READ, "DR") \ + E_(NETFS_DIO_WRITE, "DW") #define netfs_rreq_traces \ EM(netfs_rreq_trace_assess, "ASSESS ") \ From patchwork Wed Dec 13 15:23:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491235 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9DA1FC4332F for ; Wed, 13 Dec 2023 15:26:16 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 30FF16B00FD; Wed, 13 Dec 2023 10:26:16 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 2C0496B0105; Wed, 13 Dec 2023 10:26:16 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 160C26B011C; Wed, 13 Dec 2023 10:26:16 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 01CD96B00FD for ; Wed, 13 Dec 2023 10:26:15 -0500 (EST) Received: from smtpin30.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id C79ED80531 for ; Wed, 13 Dec 2023 15:26:15 +0000 (UTC) X-FDA: 81562171110.30.DA0A00F Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf19.hostedemail.com (Postfix) with ESMTP id 0FEF31A0029 for ; Wed, 13 Dec 2023 15:26:13 +0000 (UTC) Authentication-Results: imf19.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=itHGQkxp; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf19.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481174; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=bK45Roxm3IC/nkVEsH43k2qGwF+l+q9rJ2GGBczBW+0=; b=bC6ATR6ANOjFwqsELCGxkc0Har/xvlTvNwQ0jlnxMj04VnMo1NBNJO6vstGQQASeQv+Oaa jSQZNVm1HT7GMrf0U2pmk8qcv2RqDHSoHymlAoMcJjpMza/n+lrojjee2SiIkh/GfRn1c/ OPh72NjIhazDc2hl9rydVkhg3zAB5RU= ARC-Authentication-Results: i=1; imf19.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=itHGQkxp; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf19.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481174; a=rsa-sha256; cv=none; b=im7WZNw78Wxy7SpBwW0ji77LwXcBCBizU9KUH76gaOQ4pRdL+N15x5omKBExWZbgDU9UrQ WMZvj8S3dtaIULC7YZLjkChy4T13JWnt+nIlh7DyLtTnq5dGNrQ+NxsL7H92DC0HGmabD2 M0J87rKoZ3hYT7x6AMkxnPtKVEFDHmY= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481173; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bK45Roxm3IC/nkVEsH43k2qGwF+l+q9rJ2GGBczBW+0=; b=itHGQkxp/r+/kymNoBqNIEeu8sCCjslzoKD8HS61dJtB/h20QphOwkKOzOXuovwOELQsgn 5hkAsUHfEcxON95Si2cSO5O+3Gzgv2OXDJ+E1bEao62+th3aC8OgUCi8qm6kSf8vS6qfMs 4wdgY/of6Je0ykwcca+G2Sz8+ak1w+s= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-286-0fI0XmfbP--2wLLfUpTaCw-1; Wed, 13 Dec 2023 10:26:09 -0500 X-MC-Unique: 0fI0XmfbP--2wLLfUpTaCw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 35572101CC6E; Wed, 13 Dec 2023 15:26:07 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 937E41121312; Wed, 13 Dec 2023 15:26:03 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 30/39] netfs: Implement buffered write API Date: Wed, 13 Dec 2023 15:23:40 +0000 Message-ID: <20231213152350.431591-31-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.3 X-Rspamd-Queue-Id: 0FEF31A0029 X-Rspam-User: X-Rspamd-Server: rspam02 X-Stat-Signature: p5gakibxhmj1yzsj9fwbi5zr48p9fj5x X-HE-Tag: 1702481173-408625 X-HE-Meta: U2FsdGVkX1+3RMlRPgWjl/8xvytrSUeT66G3Yt7eG6Btecy8krOPHm2lCRN6JnL0Pkj4qGC8HvhoB7OhUm53VMuQkqOptGuDy6GAescQeZZ7v90JhPbnAtRAmWcAfUaXVzU4cBAomhHDCV+YHnEPaPqM6CzvqGaNAngBhADqJobf8UqqkJZEK8139Kt/J6pIx9yg4ZHuVsy2EYFJKO+mjii0gDBtdMG4/zilLHY3cSYfDlhqLXR9+ISxU1bb/uhdco0WqBQnKwLQ6HxjGYEN52euY72m4Ao/Ll0ebaZ6R7txjZbgcSqlTfXAPRekDXjuEIT1Jk6wqIc6XMlxcp5EzQ3+NaykSk3sSRLQQzAHM/VVoMw7JNM/4BPHx9kCWYcIGQBA3JIQWzU2B9CrN05UPvZ0+nGMT3yzzPva5fGFpf6oAuCwkXahymgKMZXPNw73ATaA1cIphr1GIT1EiT2nIDxVw3xxsYF7ECFNKp1TdDJyBJOHdZHIcTKu2I3oECRLqLmKelYlIeI7n/xcTxPOWE72Qd4/QvdENt3y1q+hcFAHl3LiGaQZpNAKIFKc2pKiQug6Jo7BUxjS0nlJgKucrpPRdJD0hwGTfkvYSAoktWmD1zIsxs54B3XA4auhHKl99V4WIWLkn7/FkBOoy+0FWRO+GAuSgjP9XWTVldhfNXIXUoWwISLoQFrJmc/YCVRJrsGPbHpZrqC3tvlcMhM+ED26Fvx7xKFJ49PkD347Xi5mupGhII1C6n80SisQaU3tVgQY0cSf/xOgjJOEitk9FWnJlWnSOcUHuGPLvRODU8rm8vJ49gm+tsH7R56kGRWRC9gYw48mtAh0D8pXQbgh8IuiFT1NCuKKoJhikHiXEzb8a+Ya8IlU+mZCmTBKAYYUBw6YkrjUTvW7bUDecp+WcfpGL6xkHqxpoGgHz3xACwOMJve842FrdMc7ooOctnmNXfdqaZFWmyrdM6ZC8yv PDi28R3O +wW07p/PEo1NvI4Vto6Bs3UK9Pl91FM9VLczpMZxrzkKr/yfUoYT7gQz1TpUTXuZkVWOli3F+5bczGX23s4+HiW6l2GwQNNvsiMsoUh9zu5cmZwbs8Roeyz4IzkGq57sJ1kEPBDm7dSk80h0fvqMeLoacafU13wu35+yMpDU1uFRltxLCUfGzTNCVVj0Lu+uZu0kpxOtGHFOzlGYXMb1otGnJ+TF9hqQIG782rSMLh24rpBOLEghivGDMWa8q/iNWNgicuZ2SIJoC8w1adFEXJblgiDrfP9Pye6p9xs2qFWnuA4o= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Institute a netfs write helper, netfs_file_write_iter(), to be pointed at by the network filesystem ->write_iter() call. Make it handled buffered writes by calling the previously defined netfs_perform_write() to copy the source data into the pagecache. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/buffered_write.c | 83 +++++++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 3 ++ 2 files changed, 86 insertions(+) diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index b76688e98f81..f244123ab568 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -333,3 +333,86 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, goto out; } EXPORT_SYMBOL(netfs_perform_write); + +/** + * netfs_buffered_write_iter_locked - write data to a file + * @iocb: IO state structure (file, offset, etc.) + * @from: iov_iter with data to write + * @netfs_group: Grouping for dirty pages (eg. ceph snaps). + * + * This function does all the work needed for actually writing data to a + * file. It does all basic checks, removes SUID from the file, updates + * modification times and calls proper subroutines depending on whether we + * do direct IO or a standard buffered write. + * + * The caller must hold appropriate locks around this function and have called + * generic_write_checks() already. The caller is also responsible for doing + * any necessary syncing afterwards. + * + * This function does *not* take care of syncing data in case of O_SYNC write. + * A caller has to handle it. This is mainly due to the fact that we want to + * avoid syncing under i_rwsem. + * + * Return: + * * number of bytes written, even for truncated writes + * * negative error code if no data has been written at all + */ +ssize_t netfs_buffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *from, + struct netfs_group *netfs_group) +{ + struct file *file = iocb->ki_filp; + ssize_t ret; + + trace_netfs_write_iter(iocb, from); + + ret = file_remove_privs(file); + if (ret) + return ret; + + ret = file_update_time(file); + if (ret) + return ret; + + return netfs_perform_write(iocb, from, netfs_group); +} +EXPORT_SYMBOL(netfs_buffered_write_iter_locked); + +/** + * netfs_file_write_iter - write data to a file + * @iocb: IO state structure + * @from: iov_iter with data to write + * + * Perform a write to a file, writing into the pagecache if possible and doing + * an unbuffered write instead if not. + * + * Return: + * * Negative error code if no data has been written at all of + * vfs_fsync_range() failed for a synchronous write + * * Number of bytes written, even for truncated writes + */ +ssize_t netfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file->f_mapping->host; + struct netfs_inode *ictx = netfs_inode(inode); + ssize_t ret; + + _enter("%llx,%zx,%llx", iocb->ki_pos, iov_iter_count(from), i_size_read(inode)); + + if ((iocb->ki_flags & IOCB_DIRECT) || + test_bit(NETFS_ICTX_UNBUFFERED, &ictx->flags)) + return netfs_unbuffered_write_iter(iocb, from); + + ret = netfs_start_io_write(inode); + if (ret < 0) + return ret; + + ret = generic_write_checks(iocb, from); + if (ret > 0) + ret = netfs_buffered_write_iter_locked(iocb, from, NULL); + netfs_end_io_write(inode); + if (ret > 0) + ret = generic_write_sync(iocb, ret); + return ret; +} +EXPORT_SYMBOL(netfs_file_write_iter); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 00c87f4e809c..702b864a4993 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -385,7 +385,10 @@ ssize_t netfs_unbuffered_read_iter(struct kiocb *iocb, struct iov_iter *iter); /* High-level write API */ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, struct netfs_group *netfs_group); +ssize_t netfs_buffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *from, + struct netfs_group *netfs_group); ssize_t netfs_unbuffered_write_iter(struct kiocb *iocb, struct iov_iter *from); +ssize_t netfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from); /* Address operations API */ struct readahead_control; From patchwork Wed Dec 13 15:23:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491237 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 06792C4332F for ; Wed, 13 Dec 2023 15:26:25 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id C11B16B03CE; Wed, 13 Dec 2023 10:26:23 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id B51046B03D1; Wed, 13 Dec 2023 10:26:23 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 88D1F6B03D4; Wed, 13 Dec 2023 10:26:23 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 751596B03CE for ; Wed, 13 Dec 2023 10:26:23 -0500 (EST) Received: from smtpin07.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id 45652401FB for ; Wed, 13 Dec 2023 15:26:23 +0000 (UTC) X-FDA: 81562171446.07.DD4731B Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf13.hostedemail.com (Postfix) with ESMTP id 859EF2000A for ; Wed, 13 Dec 2023 15:26:21 +0000 (UTC) Authentication-Results: imf13.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=CCYpSc5a; spf=pass (imf13.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481181; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=YcUt6Wlq9qFzNGrM+VViKKkJSoOctikTKew3FuWO+5w=; b=1LhG6Kbu8gJQIaPWj6wNOljzjIeP96xK4DV4CsWMvwcVeuP8I/9h4snPz1i9tMR5MtDujQ e+s2FU+yuSPCDKawngQQCFvZ+vugq+IxhdreWEl/7b9L5l3ulHZYoYXWeMBf5smJ4hYghe Cyr9Kjx2cg6KoI4uLl+aoN8rrr5CCcg= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481181; a=rsa-sha256; cv=none; b=7qbddaWNlZNhvuG6lK28YCGyvNch928FS9RnAZMRBS0IIents+KV/uoTWI9TR55mmRDtJX mvqyPiMvGvID8a/+ruAIChpN13jJxs3kceBpLvi8QXO+5Wl3m07CpcGhh8Gv4hhCzPDf5e pPBkqvcOz7dMk/rcFeS33fqayds5cMQ= ARC-Authentication-Results: i=1; imf13.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=CCYpSc5a; spf=pass (imf13.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481180; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YcUt6Wlq9qFzNGrM+VViKKkJSoOctikTKew3FuWO+5w=; b=CCYpSc5aq/aX5vTqle23WICK7jAIE4/Uje1hTXfL4I7BSf8JH9AlX6YW4CeVPpbnAkSrj8 AN8oOkwx/ud7y66amH/OSDm1v4B84m16VfqmvE7iePLA1XefACfB3jDDRiy4QFsZIqTZcz JL3trTyCaTTfXxFQJ0yK4r+sQqRuRQU= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-477-izgs5zPOPzO_FpSrM-V7uQ-1; Wed, 13 Dec 2023 10:26:13 -0500 X-MC-Unique: izgs5zPOPzO_FpSrM-V7uQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id CD5CC890FCD; Wed, 13 Dec 2023 15:26:11 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2EE7F40C6EB9; Wed, 13 Dec 2023 15:26:08 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 31/39] netfs: Allow buffered shared-writeable mmap through netfs_page_mkwrite() Date: Wed, 13 Dec 2023 15:23:41 +0000 Message-ID: <20231213152350.431591-32-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-Stat-Signature: 464ry5esf3z3nzci43n66zkj1u3wd7nq X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: 859EF2000A X-Rspam-User: X-HE-Tag: 1702481181-677295 X-HE-Meta: U2FsdGVkX1/uAgsQE35+OdtvRxtE2ygTj/bsRgw/2pCMGnjTuaqax7OC5qUy0QrXGN9lsxPQB7i2xH+8w/4IhDGdcvl2E6r0jI4L4q0OhULAfan8OzbsPp/6ThpkmYjNxQhChPrT928NePqzFYf1Ju3KGg6BueJQZ7vOIqGrkK4dizuNzOeggAS6k/ulEAWoI5ovipZOHdyPGaoCYVG4yd1jhabrGmJzq69He3WZEu9pmtUPpS/iIaAqnMO15GV0hcUC3vaHg8+4e+hjpbzOUxAy/LxlWT6ObJYF6TcdV2YrKbxOxIpza7+BbdU4UbWPSyMpGfk3bbpl5eFn+IszKsV18QyeVKDc11MT4FTcGNgePuSSf8P1lTPb8SqlpLmg0o5FlVaiHS/amAzID+SRfBxJuMVZ8JuxCYf2MGQkD8Y5cs6W5vRgdhwmosRWHzGSkXzXijAvQEHxoCbFTFQz5F53YAEFDpEGcZxMPpMf30V8wGmT+6HZ2P69xY/w6duiHVPvpj4oxNR2ZHcw/Y5BEG4oQe0olWrBvlPWEoUZlAAMZ5CfbV0XUIjSkiBtcWSTYI2Wx2nRamC2qU0NNcTLo07CZ0x79eMun/+gtcd0Q3etrZmC+z++Ay+U+NBonu/XwRQenrLtNS9GQxXQUpxKeHklx/UurVMe3UW5USm4ccVa5nwDPYGdyBPfYi5XgQLnYT9z373S6hJtCimjKuA2ByOu6/XMdd7jK8enLLfyiKivO3SLT4AMzxKy5aLFwEJbcexnT8UOcLBjVVhnIc6aqPYHgmX+mx+pToF53DxTmhORdwldK/O+g/YrfgDHtSnoJq9K8nIwy9/FaxI3iXmW32S/q6C6JpbwVtAhC1JcDFIqqzsr6xZ1AQZgHM2SU4QpQbD7wGBAvSBx5zVxj0+Ak7auOvrG90WJP/6BHj+x7ZNVoNxEFOmWzJl6Ae4zVsFpebjWWIMSA66BP/4l9F6 U9aLh1sJ sdOcgMTbaJi+LbIbOgdrIIta3AGEmjl5bUvpoHwEbBE+xi1V/86n0rL0X3lERKNbXejq5cveMBb4iZHsjxIYlal0PjXMgexVADxOOL3R+Xp5KzJITGK173NjW+UPQMTneBDiU7Coc2Omg6XqyR/gkdUdvS6aejpvRZhPQEwCVSwWmWoyl26R43nLHc04Vvhl2U2tNDZttajSkMZ+B8v1KQEwYHbgnSr8Qe6H8YDLeSxJH4O3seaHaO7tjQPQUXpDtKZbrT0+IGCKYNmt91HbhTZVFcdoC2EGdM9RMaIWHtlGqmQdeI4WqphL5wm+LtT1NKVFg3SDPle/6tMHYqWTA9DcAAg== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Provide an entry point to delegate a filesystem's ->page_mkwrite() to. This checks for conflicting writes, then attached any netfs-specific group marking (e.g. ceph snap) to the page to be considered dirty. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/buffered_write.c | 59 +++++++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 4 +++ 2 files changed, 63 insertions(+) diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index f244123ab568..70cb8e98d068 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -416,3 +416,62 @@ ssize_t netfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) return ret; } EXPORT_SYMBOL(netfs_file_write_iter); + +/* + * Notification that a previously read-only page is about to become writable. + * Note that the caller indicates a single page of a multipage folio. + */ +vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_group) +{ + struct folio *folio = page_folio(vmf->page); + struct file *file = vmf->vma->vm_file; + struct inode *inode = file_inode(file); + vm_fault_t ret = VM_FAULT_RETRY; + int err; + + _enter("%lx", folio->index); + + sb_start_pagefault(inode->i_sb); + + if (folio_wait_writeback_killable(folio)) + goto out; + + if (folio_lock_killable(folio) < 0) + goto out; + + /* Can we see a streaming write here? */ + if (WARN_ON(!folio_test_uptodate(folio))) { + ret = VM_FAULT_SIGBUS | VM_FAULT_LOCKED; + goto out; + } + + if (netfs_folio_group(folio) != netfs_group) { + folio_unlock(folio); + err = filemap_fdatawait_range(inode->i_mapping, + folio_pos(folio), + folio_pos(folio) + folio_size(folio)); + switch (err) { + case 0: + ret = VM_FAULT_RETRY; + goto out; + case -ENOMEM: + ret = VM_FAULT_OOM; + goto out; + default: + ret = VM_FAULT_SIGBUS; + goto out; + } + } + + if (folio_test_dirty(folio)) + trace_netfs_folio(folio, netfs_folio_trace_mkwrite_plus); + else + trace_netfs_folio(folio, netfs_folio_trace_mkwrite); + netfs_set_group(folio, netfs_group); + file_update_time(file); + ret = VM_FAULT_LOCKED; +out: + sb_end_pagefault(inode->i_sb); + return ret; +} +EXPORT_SYMBOL(netfs_page_mkwrite); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 702b864a4993..46c0a6b45bb8 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -403,6 +403,10 @@ void netfs_clear_inode_writeback(struct inode *inode, const void *aux); void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length); bool netfs_release_folio(struct folio *folio, gfp_t gfp); +/* VMA operations API. */ +vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_group); + +/* (Sub)request management API. */ void netfs_subreq_terminated(struct netfs_io_subrequest *, ssize_t, bool); void netfs_get_subrequest(struct netfs_io_subrequest *subreq, enum netfs_sreq_ref_trace what); From patchwork Wed Dec 13 15:23:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491238 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6A5F3C4167D for ; Wed, 13 Dec 2023 15:26:27 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 7A6366B03D4; Wed, 13 Dec 2023 10:26:25 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 72DC86B03D9; Wed, 13 Dec 2023 10:26:25 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 57F766B03E1; Wed, 13 Dec 2023 10:26:25 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 431826B03D4 for ; Wed, 13 Dec 2023 10:26:25 -0500 (EST) Received: from smtpin17.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id F3C1E80213 for ; Wed, 13 Dec 2023 15:26:24 +0000 (UTC) X-FDA: 81562171488.17.5E5269B Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf23.hostedemail.com (Postfix) with ESMTP id 22B2F14000D for ; Wed, 13 Dec 2023 15:26:22 +0000 (UTC) Authentication-Results: imf23.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=EKi12sBL; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf23.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481183; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=BBeV+gPa6exSN5f9Ij71agEQGyyesbGBrZnLGz9yhJU=; b=euif6OUaxivCfJlSIKvENXbwQ+W7jgK1/sXKeRyehofRHsaNeaBp5NQHoZW2V5w5ZaAfOJ qmW0e5njufJ2c+4WJED+VVR8Ebyepcpc2TX7ZizPdy2uUhvUmBHfHbrr34ah3Hfg82NViu +l3DuQpHRXy8aDPHxWPHl4ToAC72aUc= ARC-Authentication-Results: i=1; imf23.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=EKi12sBL; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf23.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481183; a=rsa-sha256; cv=none; b=8YkbQ4TqzFIZNcaWMexbx9ydaHD0/TPoN345nstQL/P/qeZ1Aewuqi4S+s0+LobDKjyu30 VSxWZ2GmeXYBcgQ/mHh281eSk173ylKMG/2Qtpaipi2EjZ1EBB51NO3NAVdwMrAPrRjUpG 5zYQHFDnhDhSwop8zGVSEHOurQstAOo= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481182; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BBeV+gPa6exSN5f9Ij71agEQGyyesbGBrZnLGz9yhJU=; b=EKi12sBLRraGtUz/3KwmwIRxkwz+H5oRsDcXqSf6zEoUthGaMvzmh7/NTo2ls+5bH8b+em rxF5cM+mLVJXyLmlNxVmmZLhl0+ODhinNSao6nZNUldGgpM1g4JNV5ZdAO1r/vU3C+Nrvp weFrE4NiDTbdP3TPAdvxclVa0hZiTJI= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-164-IpH6uSoMNuWTQihb2mC7IA-1; Wed, 13 Dec 2023 10:26:17 -0500 X-MC-Unique: IpH6uSoMNuWTQihb2mC7IA-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 57C073811F29; Wed, 13 Dec 2023 15:26:16 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id AF03B2026D66; Wed, 13 Dec 2023 15:26:12 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 32/39] netfs: Provide netfs_file_read_iter() Date: Wed, 13 Dec 2023 15:23:42 +0000 Message-ID: <20231213152350.431591-33-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.4 X-Rspamd-Queue-Id: 22B2F14000D X-Rspam-User: X-Rspamd-Server: rspam05 X-Stat-Signature: 1hkye99q8jdg74to9b3rtt93xsuw7aq6 X-HE-Tag: 1702481182-110079 X-HE-Meta: U2FsdGVkX19qx2R4zRxuSNIocMJD65/H1EEEsCHsHJ+ZCuAFch8Cs+qV6oouyetvujYTKn8ckvwP5/hqDC4zh/ur1ZOAxdqCyuzCgcSidYLHIag5KcG4Qjf2EH3luTo87SEhYXJu5SbvXUe7Ry1uBmV7Y9RhNVJ1iegV6RBKQLOYK9YVrEr91Q8vx7cTfJM3fUdBU+BpbYBCi9q1wxzVxWy1KLE/vXnxMnrgRngAyrOw1WEGB64mB2+qq0mTgkrvzY7YlCy7ZIszaZFAeFxgQU4I3LhHHPZ5udziM/MxTyuIO/3L5kLMJCXto2KL/kx+YNo4g61+scTw9e4ZCzuGjwLmQ3QHjwvMjSEaWrRWUI6cFqh16GPHjUiDA4alfPWJV4+XLBn/fVcdVYI69EzdVekOsYQBJnRO0Lrf2dR7DgayIOv/etJJfjKaisflDMC9YD0ytqO7yahbbK5hcrGf9PrEeoDwWiLpy7nIKVquziWy1JWc6/YzjsKp4SRWZTIk2WP6fg7UMx21x5X6fYQ97AafU83v3yaIvoEmCDqR8h/c4RsSZjuBG/9ba0KNjxi1krPsPIoiv56Ye8GTiClcCkSm7/18NxSxNnjXp0SJbC89lQMBUNaJTN/RPUL7KKlb3++6Ig1wZ+g74ylqc8CtdY4IcZtHNFXZu6Upo0usUPqsZb7c8NQ8FTt7iEd8vX+6ZgD3trlYrq5JN5YSSojGXhO//BhPEOmAYnlexWf81gSvNw+X7wR2+VgEYZrGClsBOvLaKoqwdyYgFUvybuuCIMfi3v8Ex+OmoZCu7+WRj85NvY8RGMv/SqraC9Ia7hGo7sXovKQl6znGrxsSlmXfV0PKO82Vwo2wGQvasJzpqZoOq3WCx/LFQWz2O+OImgqiR88m9IGuekmLKJFcNfsYvhTgpkh9X/jWunMwcFIJRRHAVYLqeIumydyUW35+zjTij3Q/tW3FtlTrplrJROk M2SUhyLf wdJJE/FvKIWOiQY3ZgdhmwweoyDD+pKUPAstnvlOz7L5FTMmz1R0kgBEKjs8H8TYJRu/RWQVtFeYZKkZWRVvpWQXZ3gkJTY4OKb/4M+v2S1vldgPlJJ0JaVz2pdYgxF2vZqqZnuZs9PhNa0a7W+kng6xhjqjzzKYOZvQRbhnFKjhvRvONJqPo4/PiILFBk3uMbBMe1TR2SarPybLk+sd5TwZonbcEL7r2gjV83IeBqop4QH0K5eefy/UmPFf1vW83YWgwtiP4guitJr2wlMifWfKyf/w5CuOqLZYQxK5kvavPCmf4HnycO9J1aGKEYE7663kgRgdlqWOFNZoxJSZA+88d7g== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Provide a top-level-ish function that can be pointed to directly by ->read_iter file op. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/buffered_read.c | 73 ++++++++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 2 ++ 2 files changed, 75 insertions(+) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 950f63fc156a..a59e7b2edaac 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -558,3 +558,76 @@ int netfs_prefetch_for_write(struct file *file, struct folio *folio, _leave(" = %d", ret); return ret; } + +/** + * netfs_buffered_read_iter - Filesystem buffered I/O read routine + * @iocb: kernel I/O control block + * @iter: destination for the data read + * + * This is the ->read_iter() routine for all filesystems that can use the page + * cache directly. + * + * The IOCB_NOWAIT flag in iocb->ki_flags indicates that -EAGAIN shall be + * returned when no data can be read without waiting for I/O requests to + * complete; it doesn't prevent readahead. + * + * The IOCB_NOIO flag in iocb->ki_flags indicates that no new I/O requests + * shall be made for the read or for readahead. When no data can be read, + * -EAGAIN shall be returned. When readahead would be triggered, a partial, + * possibly empty read shall be returned. + * + * Return: + * * number of bytes copied, even for partial reads + * * negative error code (or 0 if IOCB_NOIO) if nothing was read + */ +ssize_t netfs_buffered_read_iter(struct kiocb *iocb, struct iov_iter *iter) +{ + struct inode *inode = file_inode(iocb->ki_filp); + struct netfs_inode *ictx = netfs_inode(inode); + ssize_t ret; + + if (WARN_ON_ONCE((iocb->ki_flags & IOCB_DIRECT) || + test_bit(NETFS_ICTX_UNBUFFERED, &ictx->flags))) + return -EINVAL; + + ret = netfs_start_io_read(inode); + if (ret == 0) { + ret = filemap_read(iocb, iter, 0); + netfs_end_io_read(inode); + } + return ret; +} +EXPORT_SYMBOL(netfs_buffered_read_iter); + +/** + * netfs_file_read_iter - Generic filesystem read routine + * @iocb: kernel I/O control block + * @iter: destination for the data read + * + * This is the ->read_iter() routine for all filesystems that can use the page + * cache directly. + * + * The IOCB_NOWAIT flag in iocb->ki_flags indicates that -EAGAIN shall be + * returned when no data can be read without waiting for I/O requests to + * complete; it doesn't prevent readahead. + * + * The IOCB_NOIO flag in iocb->ki_flags indicates that no new I/O requests + * shall be made for the read or for readahead. When no data can be read, + * -EAGAIN shall be returned. When readahead would be triggered, a partial, + * possibly empty read shall be returned. + * + * Return: + * * number of bytes copied, even for partial reads + * * negative error code (or 0 if IOCB_NOIO) if nothing was read + */ +ssize_t netfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) +{ + struct netfs_inode *ictx = netfs_inode(iocb->ki_filp->f_mapping->host); + + if ((iocb->ki_flags & IOCB_DIRECT) || + test_bit(NETFS_ICTX_UNBUFFERED, &ictx->flags)) + return netfs_unbuffered_read_iter(iocb, iter); + + return netfs_buffered_read_iter(iocb, iter); +} +EXPORT_SYMBOL(netfs_file_read_iter); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 46c0a6b45bb8..638f42fdaef5 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -381,6 +381,8 @@ struct netfs_cache_ops { /* High-level read API. */ ssize_t netfs_unbuffered_read_iter(struct kiocb *iocb, struct iov_iter *iter); +ssize_t netfs_buffered_read_iter(struct kiocb *iocb, struct iov_iter *iter); +ssize_t netfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter); /* High-level write API */ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, From patchwork Wed Dec 13 15:23:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491239 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 50F70C4332F for ; Wed, 13 Dec 2023 15:26:32 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id D49926B03F0; Wed, 13 Dec 2023 10:26:31 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id CFB026B03EE; Wed, 13 Dec 2023 10:26:31 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id B4C336B03F0; Wed, 13 Dec 2023 10:26:31 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id A17CA6B03E6 for ; Wed, 13 Dec 2023 10:26:31 -0500 (EST) Received: from smtpin01.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 82E791A0204 for ; Wed, 13 Dec 2023 15:26:31 +0000 (UTC) X-FDA: 81562171782.01.854E639 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf23.hostedemail.com (Postfix) with ESMTP id A4293140022 for ; Wed, 13 Dec 2023 15:26:29 +0000 (UTC) Authentication-Results: imf23.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=F13rQRbZ; spf=pass (imf23.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481189; a=rsa-sha256; cv=none; b=kqC476K6miOmGnhATVCL/B10HdUMODNS+1ikQZ4+62bev2IAy/usMRdwN/aVLFLDEsnlC+ aIoaokwysKpEIGle1jjzQ285toDAwIQKl1GLdnID0hOPWq5Y+hx8mh41iZMYkBVONlfYyT xJKw6nuAQAOWGG6oygxhlNlB15Lo/f0= ARC-Authentication-Results: i=1; imf23.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=F13rQRbZ; spf=pass (imf23.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481189; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=GWz3UetJ1H2inkDCEy0FPsiHj6M0nuo6NxktZOcXvKA=; b=B6/2eRA+cEko42HJpwJjxUqZwJEKij7KtmO8YXWmbgt7ODNDRq+Z/IZci9OdAIy926PK0D YuGxuzasKf0CrDivM6AHcvySAtwYYyeUTgHuqhwcamlWeWmTnmE7LHJsxvuVaZjA73kYL/ deoR8weMX2OO4ifgbWc2uCoExkqG07I= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481188; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GWz3UetJ1H2inkDCEy0FPsiHj6M0nuo6NxktZOcXvKA=; b=F13rQRbZ2T+XJIOGweYCLtRX+iqLQyJ2APg0Mmf3szmrE8rBKoZEjlgPwDT3V2fX5UxdCu UDJYv+LMNSdH4ABntaZNUZX51Nx+JoTUBgOrGtKZPcNltcYKlwPyaYwGiCorlEH6YY4DuD EIPONuZxy3i0ZvLYnpdOXjDsyDvnC+8= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-39-froc9UFwN7-mmdgB76l15A-1; Wed, 13 Dec 2023 10:26:22 -0500 X-MC-Unique: froc9UFwN7-mmdgB76l15A-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id DAA1F1C18CC3; Wed, 13 Dec 2023 15:26:20 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 68A102026D66; Wed, 13 Dec 2023 15:26:17 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 33/39] netfs, cachefiles: Pass upper bound length to allow expansion Date: Wed, 13 Dec 2023 15:23:43 +0000 Message-ID: <20231213152350.431591-34-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.4 X-Rspamd-Server: rspam08 X-Rspamd-Queue-Id: A4293140022 X-Stat-Signature: w58u6o3bcebx1nbsbo4h98pi6338n9jo X-Rspam-User: X-HE-Tag: 1702481189-30220 X-HE-Meta: U2FsdGVkX19OlGfXZoGdTMSJ0M3aXIVJ/hIYcDRbCMnbO433ecexSbTincsjVwpQCfthjjlChYpmhGrHCqixFwgmU9KQBCBJM8pCCCiy4K4C0c1HxqhwBY4SmzSJEb0NePiEaUWstiXiTt6T/gr2rCSALMMuBUhDEbzBS0aGVy8FRdOzjyXjm6uH5/Qro4ddSmLlXgdM5HIMWBlnHy8Y7fZFI+nEexTClO9B4EkwjawibDe96RhfzUBC3KNBUEisedkEErO7OPQMDHANqLpIYRjncLaj5EBHadsOJT2sAourUD+5N+UYd6p6hEVwqFmSY5zWNPFErr52ZM/2MNaOngRUodxbQ9VKg+JH5Mx/sc1XAe6vKTZwxRkUeU8l5MQ4MLQ536I60xATV9TZ80bCSiE9/ISDwEAcdDRFnHQy8TfYeRMslzRFAVXFmsku0rdV7K3TDX8uL6r2c1/soAPqfrP7Mrys0Ir2GwnSvcmaFSVkkbrbGOEnfDtG9Lgl7ox7gdzIPF3/56vrRg10rtBJ9XBxu1RBH/u3IptBwEjGRV3vf6AT7Sap5/pe22huhKC+7GjWkTN2cYaD1GydbiGY7WiltIxdMxFMXDHvm9zys8J+HaH9vaqc2+faYS7acOhK4qNUCTi2c3vleCZ//gEbf2pg4u+NIjovHNuh2xymLN2hs1v5myZhBhUEUN1eICE5lw+r6G9//fnLU2c7QWrNgVgjukIyhuSsAnv4+APGm0MC84egYZZs8ZqNGX1zNVtkhRCtp8Og2EBiIJ64u84vzJjR6yXQvVilEERjntkRVOXuwzpz3DOsC68VA+k18sI3gFehsp9xxocSjL3NSEtM0GZAQp2JypoGQT4CBvAd2q2LnU4xgRnSa1+k7CBscmpcO6kMuRyuhOqNuLQft6zI5veG3GQNi2sL/dp2G18CCmfGn3SsojOyipw3BLStvqRjgFl81fbcUkKEcJstAOZ +aF0jHVu tKR4hsMSjbzxymC4XKONU1fHy3F8kBdcaLSfuEburtONPZqJJOEifBmo2uSoJYq4lT9BQ9hGw725jBZZocF8odpqqTwOQUSZ9YrRyhP35jf/ETAi6D4oDxDtGL17QQ1P6KiovShYKLxdeA3k846W5xO25O/CBOadQc5Ip0HigDjfoROZZaV4nCc2Tai9wA97QRj58AfvM+XB0WYc4vqdP+BYJXWcnoglORkGRgmY5h9PHjGCrpGpZBelUa2QsKgmFLXhuVL7tRZVS/iPiPv+0m4nRoR7WnPGXurgTRA1P4fHHnfc= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Make netfslib pass the maximum length to the ->prepare_write() op to tell the cache how much it can expand the length of a write to. This allows a write to the server at the end of a file to be limited to a few bytes whilst writing an entire block to the cache (something required by direct I/O). Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/cachefiles/internal.h | 2 +- fs/cachefiles/io.c | 10 ++++++---- fs/cachefiles/ondemand.c | 2 +- fs/netfs/fscache_io.c | 2 +- fs/netfs/io.c | 2 +- fs/netfs/objects.c | 1 + fs/netfs/output.c | 25 ++++++++++--------------- fs/smb/client/fscache.c | 2 +- include/linux/netfs.h | 5 +++-- 9 files changed, 25 insertions(+), 26 deletions(-) diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index 4a87c9d714a9..d33169f0018b 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -246,7 +246,7 @@ extern bool cachefiles_begin_operation(struct netfs_cache_resources *cres, enum fscache_want_state want_state); extern int __cachefiles_prepare_write(struct cachefiles_object *object, struct file *file, - loff_t *_start, size_t *_len, + loff_t *_start, size_t *_len, size_t upper_len, bool no_space_allocated_yet); extern int __cachefiles_write(struct cachefiles_object *object, struct file *file, diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c index 5857241c5918..9fe69a60eb24 100644 --- a/fs/cachefiles/io.c +++ b/fs/cachefiles/io.c @@ -517,7 +517,7 @@ cachefiles_prepare_ondemand_read(struct netfs_cache_resources *cres, */ int __cachefiles_prepare_write(struct cachefiles_object *object, struct file *file, - loff_t *_start, size_t *_len, + loff_t *_start, size_t *_len, size_t upper_len, bool no_space_allocated_yet) { struct cachefiles_cache *cache = object->volume->cache; @@ -529,6 +529,8 @@ int __cachefiles_prepare_write(struct cachefiles_object *object, down = start - round_down(start, PAGE_SIZE); *_start = start - down; *_len = round_up(down + len, PAGE_SIZE); + if (down < start || *_len > upper_len) + return -ENOBUFS; /* We need to work out whether there's sufficient disk space to perform * the write - but we can skip that check if we have space already @@ -591,8 +593,8 @@ int __cachefiles_prepare_write(struct cachefiles_object *object, } static int cachefiles_prepare_write(struct netfs_cache_resources *cres, - loff_t *_start, size_t *_len, loff_t i_size, - bool no_space_allocated_yet) + loff_t *_start, size_t *_len, size_t upper_len, + loff_t i_size, bool no_space_allocated_yet) { struct cachefiles_object *object = cachefiles_cres_object(cres); struct cachefiles_cache *cache = object->volume->cache; @@ -608,7 +610,7 @@ static int cachefiles_prepare_write(struct netfs_cache_resources *cres, cachefiles_begin_secure(cache, &saved_cred); ret = __cachefiles_prepare_write(object, cachefiles_cres_file(cres), - _start, _len, + _start, _len, upper_len, no_space_allocated_yet); cachefiles_end_secure(cache, saved_cred); return ret; diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c index b8fbbb1961bb..5fd74ec60bef 100644 --- a/fs/cachefiles/ondemand.c +++ b/fs/cachefiles/ondemand.c @@ -50,7 +50,7 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb, return -ENOBUFS; cachefiles_begin_secure(cache, &saved_cred); - ret = __cachefiles_prepare_write(object, file, &pos, &len, true); + ret = __cachefiles_prepare_write(object, file, &pos, &len, len, true); cachefiles_end_secure(cache, saved_cred); if (ret < 0) return ret; diff --git a/fs/netfs/fscache_io.c b/fs/netfs/fscache_io.c index 79171a687930..ad572f7ee897 100644 --- a/fs/netfs/fscache_io.c +++ b/fs/netfs/fscache_io.c @@ -237,7 +237,7 @@ void __fscache_write_to_cache(struct fscache_cookie *cookie, fscache_access_io_write) < 0) goto abandon_free; - ret = cres->ops->prepare_write(cres, &start, &len, i_size, false); + ret = cres->ops->prepare_write(cres, &start, &len, len, i_size, false); if (ret < 0) goto abandon_end; diff --git a/fs/netfs/io.c b/fs/netfs/io.c index 894c3305710d..5d9098db815a 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -199,7 +199,7 @@ static void netfs_rreq_do_write_to_cache(struct netfs_io_request *rreq) } ret = cres->ops->prepare_write(cres, &subreq->start, &subreq->len, - rreq->i_size, true); + 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); diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index c1218b183197..16252cc4576e 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -33,6 +33,7 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, rreq->start = start; rreq->len = len; + rreq->upper_len = len; rreq->origin = origin; rreq->netfs_ops = ctx->ops; rreq->mapping = mapping; diff --git a/fs/netfs/output.c b/fs/netfs/output.c index 560cbcea0c0a..cc9065733b42 100644 --- a/fs/netfs/output.c +++ b/fs/netfs/output.c @@ -280,7 +280,7 @@ EXPORT_SYMBOL(netfs_queue_write_request); */ static void netfs_set_up_write_to_cache(struct netfs_io_request *wreq) { - struct netfs_cache_resources *cres; + struct netfs_cache_resources *cres = &wreq->cache_resources; struct netfs_io_subrequest *subreq; struct netfs_inode *ctx = netfs_inode(wreq->inode); struct fscache_cookie *cookie = netfs_i_cookie(ctx); @@ -294,26 +294,21 @@ static void netfs_set_up_write_to_cache(struct netfs_io_request *wreq) } _debug("write to cache"); - subreq = netfs_create_write_request(wreq, NETFS_WRITE_TO_CACHE, start, len, - netfs_write_to_cache_op_worker); - if (!subreq) + ret = fscache_begin_write_operation(cres, cookie); + if (ret < 0) return; - cres = &wreq->cache_resources; - ret = fscache_begin_read_operation(cres, cookie); - if (ret < 0) { - netfs_write_subrequest_terminated(subreq, ret, false); + ret = cres->ops->prepare_write(cres, &start, &len, wreq->upper_len, + i_size_read(wreq->inode), true); + if (ret < 0) return; - } - ret = cres->ops->prepare_write(cres, &start, &len, i_size_read(wreq->inode), - true); - if (ret < 0) { - netfs_write_subrequest_terminated(subreq, ret, false); + subreq = netfs_create_write_request(wreq, NETFS_WRITE_TO_CACHE, start, len, + netfs_write_to_cache_op_worker); + if (!subreq) return; - } - netfs_queue_write_request(subreq); + netfs_write_to_cache_op(subreq); } /* diff --git a/fs/smb/client/fscache.c b/fs/smb/client/fscache.c index e5cad149f5a2..c4a3cb736881 100644 --- a/fs/smb/client/fscache.c +++ b/fs/smb/client/fscache.c @@ -180,7 +180,7 @@ static int fscache_fallback_write_pages(struct inode *inode, loff_t start, size_ if (ret < 0) return ret; - ret = cres.ops->prepare_write(&cres, &start, &len, i_size_read(inode), + ret = cres.ops->prepare_write(&cres, &start, &len, len, i_size_read(inode), no_space_allocated_yet); if (ret == 0) ret = fscache_write(&cres, start, &iter, NULL, NULL); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 638f42fdaef5..f98deef22d06 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -263,6 +263,7 @@ struct netfs_io_request { 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 */ + size_t upper_len; /* Length can be extended to here */ size_t transferred; /* Amount to be indicated as transferred */ short error; /* 0 or error that occurred */ enum netfs_io_origin origin; /* Origin of the request */ @@ -360,8 +361,8 @@ struct netfs_cache_ops { * actually do. */ int (*prepare_write)(struct netfs_cache_resources *cres, - loff_t *_start, size_t *_len, loff_t i_size, - bool no_space_allocated_yet); + loff_t *_start, size_t *_len, size_t upper_len, + loff_t i_size, bool no_space_allocated_yet); /* Prepare an on-demand read operation, shortening it to a cached/uncached * boundary as appropriate. From patchwork Wed Dec 13 15:23:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491240 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B9ABC4167B for ; Wed, 13 Dec 2023 15:26:34 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id B02376B03EE; Wed, 13 Dec 2023 10:26:33 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id A39F86B0404; Wed, 13 Dec 2023 10:26:33 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 868E06B040A; Wed, 13 Dec 2023 10:26:33 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 74B036B03EE for ; Wed, 13 Dec 2023 10:26:33 -0500 (EST) Received: from smtpin20.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 4A7FDC0154 for ; Wed, 13 Dec 2023 15:26:33 +0000 (UTC) X-FDA: 81562171866.20.185800A Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf18.hostedemail.com (Postfix) with ESMTP id 568421C0015 for ; Wed, 13 Dec 2023 15:26:31 +0000 (UTC) Authentication-Results: imf18.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=V+bctvLf; spf=pass (imf18.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481191; a=rsa-sha256; cv=none; b=T6C8JFQLX36WbKdYXbyrMyqL3YdBR9jZ5K1ZBoDmjkFn9gR62XKuDjXFzAdwgpaieWnGFA p9My44hWeaBLYTBPUj/guzscTTRORahMUyHGqEp+aiyLc6XmqFwiLYGz3RH2Ygke1HFAS7 DHgwmjq/5YnZiDgRJUL/Wc7GQ1P3/Tw= ARC-Authentication-Results: i=1; imf18.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=V+bctvLf; spf=pass (imf18.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481191; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=ffwHrME+qwnYjEte5BzYbjGIILNzwy45sAFMV1nfCCk=; b=i5dLmvDKWiXrpFHudW7RJx98fGqVkffUOxTF5vUMrPWbiiu/fX4O4AHh/3Y75cCOo2AAKS dSc/lwo1GcqqQHMVSxiiipWsFEXhOjfJjMrZIpvQJxgWBtmoLJxUx0QxwTKz5iMh0+zVJa E9KMfoSVZ5dh5ZQtI11buWQzX9acyIk= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481190; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ffwHrME+qwnYjEte5BzYbjGIILNzwy45sAFMV1nfCCk=; b=V+bctvLfmbUN31F2P4CZZ2+xwHvSA9eDiazO1NUv/YKwwyZN63HQQM8p8lQql4KYtR6dX1 KDRCI7g6fFRq5ybc1KzHFsqaVYoy3zMxIWr/iEr3ECjzqTggmczB2q6y0vdESu8IEvHRiz 991J9y64gzVSZACqzl2ZTGS9uIxeYQc= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-310-LRZMXLGmPcK6Ji_nZUT1kw-1; Wed, 13 Dec 2023 10:26:26 -0500 X-MC-Unique: LRZMXLGmPcK6Ji_nZUT1kw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 0F0C229AB3F5; Wed, 13 Dec 2023 15:26:25 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id BF1A03C25; Wed, 13 Dec 2023 15:26:21 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 34/39] netfs: Provide a writepages implementation Date: Wed, 13 Dec 2023 15:23:44 +0000 Message-ID: <20231213152350.431591-35-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Rspamd-Server: rspam08 X-Rspamd-Queue-Id: 568421C0015 X-Stat-Signature: 5b5u7o4fdcyqyjszdcmgndn7a97w8s17 X-Rspam-User: X-HE-Tag: 1702481191-932797 X-HE-Meta: U2FsdGVkX19tECxib3QH83OnewWz//jaZWsMOehwwVgj+hTEIHpLY3zm5BEsNcqeSYfhW2m7wXqltNz77eK5ItpgoUyIV8nD0KI5g8UiFWvSIzbsEI5qKnfvrD1sPMfmEMu7IWLbtf4EFkcjv7LmmpiaQqr06QFNZwZ/Q63KZU/jt9PUczlo0GKVkKG1N93HhmnCtGomj4/kaNgrViQY/fAgJjGsVzw85Hq4Bw+t8wj3bKNc+wAd+q4eAV0H7D8lo4skSKwDZJo3W93ES9qvP+HnszmVAnYawwtaun9jyo6d+1W+T6w1AJjNn+eZ0bMyv1U9eSCTeNIK9miBGDOWEVs9EW5bP/6jy4Y0IaT8Aai96XRMmuoyuYCPdf5aPzdq6qQ1/KbFeYnP97bALONIdNn4Qbmk45cTLlXb3dSndbeeE7KvMpZFrXje360eQ7tnbGlOTO0SVx0gPAw4qCR+QfcMFt6dVq8hkljkmzzUxvM6PJRTyRrmjR8hze2DXVitnoqNA2x70oAT5HZmICwQ431LI25BsbfLPdG8ijKAfleik7ZNBt/kDGIYmnghuKPcKGGdeZiJT2lujq5PeECaVagcMIGEAgqWnVElxk5z0f1ItxwwNoLCU6QlO+RWm671v25iXs2zd3H6Zqd4F3v5nlEQRtNdrQKPIo5a1EfTQs4zffGDT8ezxnPkgX+HcMuNMTtQqtarlElaQzncW1SZhe8mVCYTyYgKSDrSc2kPBdbYrkC03Fm0N4MfcDnqweltEian/z2niTaBl7O6krnMK2b/TW8q/ha8pTDqzF1w3nZGgv27fVnWKdW/HjbsSXQ4uJqqfyTyYAjg4syoLPZBCjvl+jp6deuJwDbhy3QOot2WoSUhfmuDiyx3zcAq0Zsh4DsANhZKAv825UQrX4h0HcCMV8WNTd7/G+bLs3XXh1dcXri6c4zJLX7e7MORMG/BA+d5zd6Y2Hvo0iD/W/C 4OqNFWrA XCGBfAfiI627fftH7EupJk0/hEIoq8JgnNtayqc0Ot/cY2xfH2+wojqtIZgNhcu/SBQ98SroJHFQLDBOhO7BuQ7fP33yV9V96NQXFfwFIWPf2385Ekz00xrVj1xFaxuI6n/+UFeE+IdLecumX51LsbED22JXERN8QUZ+puuwPL/j3EbcidZrXvXYxA77ai9C1wOqHJJW4ffi6tEi+WpufNjVAKmhtlmzFz6eGwddBe3+n/vkCT+HCqsCJWGwMHp3wWcFav/z11p6zHBhKk4TTaX5h81LE2ubmoD4a9KEyEAW1sss= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Provide an implementation of writepages for network filesystems to delegate to. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/buffered_write.c | 647 ++++++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 2 + 2 files changed, 649 insertions(+) diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index 70cb8e98d068..42f89f8ea8af 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -32,6 +32,18 @@ static void netfs_set_group(struct folio *folio, struct netfs_group *netfs_group folio_attach_private(folio, netfs_get_group(netfs_group)); } +#if IS_ENABLED(CONFIG_FSCACHE) +static void netfs_folio_start_fscache(bool caching, struct folio *folio) +{ + if (caching) + folio_start_fscache(folio); +} +#else +static void netfs_folio_start_fscache(bool caching, struct folio *folio) +{ +} +#endif + /* * Decide how we should modify a folio. We might be attempting to do * write-streaming, in which case we don't want to a local RMW cycle if we can @@ -475,3 +487,638 @@ vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_gr return ret; } EXPORT_SYMBOL(netfs_page_mkwrite); + +/* + * Kill all the pages in the given range + */ +static void netfs_kill_pages(struct address_space *mapping, + loff_t start, loff_t len) +{ + struct folio *folio; + pgoff_t index = start / PAGE_SIZE; + pgoff_t last = (start + len - 1) / PAGE_SIZE, next; + + _enter("%llx-%llx", start, start + len - 1); + + do { + _debug("kill %lx (to %lx)", index, last); + + folio = filemap_get_folio(mapping, index); + if (IS_ERR(folio)) { + next = index + 1; + continue; + } + + next = folio_next_index(folio); + + trace_netfs_folio(folio, netfs_folio_trace_kill); + folio_clear_uptodate(folio); + if (folio_test_fscache(folio)) + folio_end_fscache(folio); + folio_end_writeback(folio); + folio_lock(folio); + generic_error_remove_folio(mapping, folio); + folio_unlock(folio); + folio_put(folio); + + } while (index = next, index <= last); + + _leave(""); +} + +/* + * Redirty all the pages in a given range. + */ +static void netfs_redirty_pages(struct address_space *mapping, + loff_t start, loff_t len) +{ + struct folio *folio; + pgoff_t index = start / PAGE_SIZE; + pgoff_t last = (start + len - 1) / PAGE_SIZE, next; + + _enter("%llx-%llx", start, start + len - 1); + + do { + _debug("redirty %llx @%llx", len, start); + + folio = filemap_get_folio(mapping, index); + if (IS_ERR(folio)) { + next = index + 1; + continue; + } + + next = folio_next_index(folio); + trace_netfs_folio(folio, netfs_folio_trace_redirty); + filemap_dirty_folio(mapping, folio); + if (folio_test_fscache(folio)) + folio_end_fscache(folio); + folio_end_writeback(folio); + folio_put(folio); + } while (index = next, index <= last); + + balance_dirty_pages_ratelimited(mapping); + + _leave(""); +} + +/* + * Completion of write to server + */ +static void netfs_pages_written_back(struct netfs_io_request *wreq) +{ + struct address_space *mapping = wreq->mapping; + struct netfs_folio *finfo; + struct netfs_group *group = NULL; + struct folio *folio; + pgoff_t last; + int gcount = 0; + + XA_STATE(xas, &mapping->i_pages, wreq->start / PAGE_SIZE); + + _enter("%llx-%llx", wreq->start, wreq->start + wreq->len); + + rcu_read_lock(); + + last = (wreq->start + wreq->len - 1) / PAGE_SIZE; + xas_for_each(&xas, folio, last) { + WARN(!folio_test_writeback(folio), + "bad %zx @%llx page %lx %lx\n", + wreq->len, wreq->start, folio_index(folio), last); + + if ((finfo = netfs_folio_info(folio))) { + /* Streaming writes cannot be redirtied whilst under + * writeback, so discard the streaming record. + */ + folio_detach_private(folio); + group = finfo->netfs_group; + gcount++; + trace_netfs_folio(folio, netfs_folio_trace_clear_s); + kfree(finfo); + } else if ((group = netfs_folio_group(folio))) { + /* Need to detach the group pointer if the page didn't + * get redirtied. If it has been redirtied, then it + * must be within the same group. + */ + if (folio_test_dirty(folio)) { + trace_netfs_folio(folio, netfs_folio_trace_redirtied); + goto end_wb; + } + if (folio_trylock(folio)) { + if (!folio_test_dirty(folio)) { + folio_detach_private(folio); + gcount++; + trace_netfs_folio(folio, netfs_folio_trace_clear_g); + } else { + trace_netfs_folio(folio, netfs_folio_trace_redirtied); + } + folio_unlock(folio); + goto end_wb; + } + + xas_pause(&xas); + rcu_read_unlock(); + folio_lock(folio); + if (!folio_test_dirty(folio)) { + folio_detach_private(folio); + gcount++; + trace_netfs_folio(folio, netfs_folio_trace_clear_g); + } else { + trace_netfs_folio(folio, netfs_folio_trace_redirtied); + } + folio_unlock(folio); + rcu_read_lock(); + } else { + trace_netfs_folio(folio, netfs_folio_trace_clear); + } + end_wb: + if (folio_test_fscache(folio)) + folio_end_fscache(folio); + folio_end_writeback(folio); + } + + rcu_read_unlock(); + netfs_put_group_many(group, gcount); + _leave(""); +} + +/* + * Deal with the disposition of the folios that are under writeback to close + * out the operation. + */ +static void netfs_cleanup_buffered_write(struct netfs_io_request *wreq) +{ + struct address_space *mapping = wreq->mapping; + + _enter(""); + + switch (wreq->error) { + case 0: + netfs_pages_written_back(wreq); + break; + + default: + pr_notice("R=%08x Unexpected error %d\n", wreq->debug_id, wreq->error); + fallthrough; + case -EACCES: + case -EPERM: + case -ENOKEY: + case -EKEYEXPIRED: + case -EKEYREJECTED: + case -EKEYREVOKED: + case -ENETRESET: + case -EDQUOT: + case -ENOSPC: + netfs_redirty_pages(mapping, wreq->start, wreq->len); + break; + + case -EROFS: + case -EIO: + case -EREMOTEIO: + case -EFBIG: + case -ENOENT: + case -ENOMEDIUM: + case -ENXIO: + netfs_kill_pages(mapping, wreq->start, wreq->len); + break; + } + + if (wreq->error) + mapping_set_error(mapping, wreq->error); + if (wreq->netfs_ops->done) + wreq->netfs_ops->done(wreq); +} + +/* + * Extend the region to be written back to include subsequent contiguously + * dirty pages if possible, but don't sleep while doing so. + * + * If this page holds new content, then we can include filler zeros in the + * writeback. + */ +static void netfs_extend_writeback(struct address_space *mapping, + struct netfs_group *group, + struct xa_state *xas, + long *_count, + loff_t start, + loff_t max_len, + bool caching, + size_t *_len, + size_t *_top) +{ + struct netfs_folio *finfo; + struct folio_batch fbatch; + struct folio *folio; + unsigned int i; + pgoff_t index = (start + *_len) / PAGE_SIZE; + size_t len; + void *priv; + bool stop = true; + + folio_batch_init(&fbatch); + + do { + /* Firstly, we gather up a batch of contiguous dirty pages + * under the RCU read lock - but we can't clear the dirty flags + * there if any of those pages are mapped. + */ + rcu_read_lock(); + + xas_for_each(xas, folio, ULONG_MAX) { + stop = true; + if (xas_retry(xas, folio)) + continue; + if (xa_is_value(folio)) + break; + if (folio_index(folio) != index) { + xas_reset(xas); + break; + } + + priv = rcu_dereference(*(__force void __rcu **)&folio->private); + if ((const struct netfs_group *)priv != group) { + finfo = (void *)((unsigned long)priv & ~NETFS_FOLIO_INFO); + if (finfo->netfs_group != group) { + xas_reset(xas); + break; + } + if (finfo->dirty_offset > 0) { + xas_reset(xas); + break; + } + } + + if (!folio_try_get_rcu(folio)) { + xas_reset(xas); + continue; + } + + /* Has the folio moved or been split? */ + if (unlikely(folio != xas_reload(xas))) { + folio_put(folio); + xas_reset(xas); + break; + } + + if (!folio_trylock(folio)) { + folio_put(folio); + xas_reset(xas); + break; + } + if (!folio_test_dirty(folio) || + folio_test_writeback(folio) || + folio_test_fscache(folio)) { + folio_unlock(folio); + folio_put(folio); + xas_reset(xas); + break; + } + + stop = false; + len = folio_size(folio); + priv = folio->private; + if ((const struct netfs_group *)priv != group) { + stop = true; + finfo = (void *)((unsigned long)priv & ~NETFS_FOLIO_INFO); + if (finfo->netfs_group != group || + finfo->dirty_offset > 0) { + folio_unlock(folio); + folio_put(folio); + xas_reset(xas); + break; + } + len = finfo->dirty_len; + } + + *_top += folio_size(folio); + index += folio_nr_pages(folio); + *_count -= folio_nr_pages(folio); + *_len += len; + if (*_len >= max_len || *_count <= 0) + stop = true; + + if (!folio_batch_add(&fbatch, folio)) + break; + if (stop) + break; + } + + xas_pause(xas); + rcu_read_unlock(); + + /* Now, if we obtained any folios, we can shift them to being + * writable and mark them for caching. + */ + if (!folio_batch_count(&fbatch)) + break; + + for (i = 0; i < folio_batch_count(&fbatch); i++) { + folio = fbatch.folios[i]; + trace_netfs_folio(folio, netfs_folio_trace_store_plus); + + if (!folio_clear_dirty_for_io(folio)) + BUG(); + folio_start_writeback(folio); + netfs_folio_start_fscache(caching, folio); + folio_unlock(folio); + } + + folio_batch_release(&fbatch); + cond_resched(); + } while (!stop); +} + +/* + * Synchronously write back the locked page and any subsequent non-locked dirty + * pages. + */ +static ssize_t netfs_write_back_from_locked_folio(struct address_space *mapping, + struct writeback_control *wbc, + struct netfs_group *group, + struct xa_state *xas, + struct folio *folio, + unsigned long long start, + unsigned long long end) +{ + struct netfs_io_request *wreq; + struct netfs_folio *finfo; + struct netfs_inode *ctx = netfs_inode(mapping->host); + unsigned long long i_size = i_size_read(&ctx->inode); + size_t len, max_len; + bool caching = netfs_is_cache_enabled(ctx); + long count = wbc->nr_to_write; + int ret; + + _enter(",%lx,%llx-%llx,%u", folio_index(folio), start, end, caching); + + wreq = netfs_alloc_request(mapping, NULL, start, folio_size(folio), + NETFS_WRITEBACK); + if (IS_ERR(wreq)) { + folio_unlock(folio); + return PTR_ERR(wreq); + } + + if (!folio_clear_dirty_for_io(folio)) + BUG(); + folio_start_writeback(folio); + netfs_folio_start_fscache(caching, folio); + + count -= folio_nr_pages(folio); + + /* Find all consecutive lockable dirty pages that have contiguous + * written regions, stopping when we find a page that is not + * immediately lockable, is not dirty or is missing, or we reach the + * end of the range. + */ + trace_netfs_folio(folio, netfs_folio_trace_store); + + len = wreq->len; + finfo = netfs_folio_info(folio); + if (finfo) { + start += finfo->dirty_offset; + if (finfo->dirty_offset + finfo->dirty_len != len) { + len = finfo->dirty_len; + goto cant_expand; + } + len = finfo->dirty_len; + } + + if (start < i_size) { + /* Trim the write to the EOF; the extra data is ignored. Also + * put an upper limit on the size of a single storedata op. + */ + max_len = 65536 * 4096; + max_len = min_t(unsigned long long, max_len, end - start + 1); + max_len = min_t(unsigned long long, max_len, i_size - start); + + if (len < max_len) + netfs_extend_writeback(mapping, group, xas, &count, start, + max_len, caching, &len, &wreq->upper_len); + } + +cant_expand: + len = min_t(unsigned long long, len, i_size - start); + + /* We now have a contiguous set of dirty pages, each with writeback + * set; the first page is still locked at this point, but all the rest + * have been unlocked. + */ + folio_unlock(folio); + wreq->start = start; + wreq->len = len; + + if (start < i_size) { + _debug("write back %zx @%llx [%llx]", len, start, i_size); + + /* Speculatively write to the cache. We have to fix this up + * later if the store fails. + */ + wreq->cleanup = netfs_cleanup_buffered_write; + + iov_iter_xarray(&wreq->iter, ITER_SOURCE, &mapping->i_pages, start, + wreq->upper_len); + __set_bit(NETFS_RREQ_UPLOAD_TO_SERVER, &wreq->flags); + ret = netfs_begin_write(wreq, true, netfs_write_trace_writeback); + if (ret == 0 || ret == -EIOCBQUEUED) + wbc->nr_to_write -= len / PAGE_SIZE; + } else { + _debug("write discard %zx @%llx [%llx]", len, start, i_size); + + /* The dirty region was entirely beyond the EOF. */ + fscache_clear_page_bits(mapping, start, len, caching); + netfs_pages_written_back(wreq); + ret = 0; + } + + netfs_put_request(wreq, false, netfs_rreq_trace_put_return); + _leave(" = 1"); + return 1; +} + +/* + * Write a region of pages back to the server + */ +static ssize_t netfs_writepages_begin(struct address_space *mapping, + struct writeback_control *wbc, + struct netfs_group *group, + struct xa_state *xas, + unsigned long long *_start, + unsigned long long end) +{ + const struct netfs_folio *finfo; + struct folio *folio; + unsigned long long start = *_start; + ssize_t ret; + void *priv; + int skips = 0; + + _enter("%llx,%llx,", start, end); + +search_again: + /* Find the first dirty page in the group. */ + rcu_read_lock(); + + for (;;) { + folio = xas_find_marked(xas, end / PAGE_SIZE, PAGECACHE_TAG_DIRTY); + if (xas_retry(xas, folio) || xa_is_value(folio)) + continue; + if (!folio) + break; + + /* Skip any dirty folio that's not in the group of interest. */ + priv = rcu_dereference(*(__force void __rcu **)&folio->private); + if ((const struct netfs_group *)priv != group) { + finfo = (void *)((unsigned long)priv & ~NETFS_FOLIO_INFO); + if (finfo->netfs_group != group) + continue; + } + + if (!folio_try_get_rcu(folio)) { + xas_reset(xas); + continue; + } + + if (unlikely(folio != xas_reload(xas))) { + folio_put(folio); + xas_reset(xas); + continue; + } + + xas_pause(xas); + break; + } + rcu_read_unlock(); + if (!folio) + return 0; + + start = folio_pos(folio); /* May regress with THPs */ + + _debug("wback %lx", folio_index(folio)); + + /* At this point we hold neither the i_pages lock nor the page lock: + * the page may be truncated or invalidated (changing page->mapping to + * NULL), or even swizzled back from swapper_space to tmpfs file + * mapping + */ +lock_again: + if (wbc->sync_mode != WB_SYNC_NONE) { + ret = folio_lock_killable(folio); + if (ret < 0) + return ret; + } else { + if (!folio_trylock(folio)) + goto search_again; + } + + if (folio->mapping != mapping || + !folio_test_dirty(folio)) { + start += folio_size(folio); + folio_unlock(folio); + goto search_again; + } + + if (folio_test_writeback(folio) || + folio_test_fscache(folio)) { + folio_unlock(folio); + if (wbc->sync_mode != WB_SYNC_NONE) { + folio_wait_writeback(folio); +#ifdef CONFIG_NETFS_FSCACHE + folio_wait_fscache(folio); +#endif + goto lock_again; + } + + start += folio_size(folio); + if (wbc->sync_mode == WB_SYNC_NONE) { + if (skips >= 5 || need_resched()) { + ret = 0; + goto out; + } + skips++; + } + goto search_again; + } + + ret = netfs_write_back_from_locked_folio(mapping, wbc, group, xas, + folio, start, end); +out: + if (ret > 0) + *_start = start + ret; + _leave(" = %zd [%llx]", ret, *_start); + return ret; +} + +/* + * Write a region of pages back to the server + */ +static int netfs_writepages_region(struct address_space *mapping, + struct writeback_control *wbc, + struct netfs_group *group, + unsigned long long *_start, + unsigned long long end) +{ + ssize_t ret; + + XA_STATE(xas, &mapping->i_pages, *_start / PAGE_SIZE); + + do { + ret = netfs_writepages_begin(mapping, wbc, group, &xas, + _start, end); + if (ret > 0 && wbc->nr_to_write > 0) + cond_resched(); + } while (ret > 0 && wbc->nr_to_write > 0); + + return ret > 0 ? 0 : ret; +} + +/* + * write some of the pending data back to the server + */ +int netfs_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + struct netfs_group *group = NULL; + loff_t start, end; + int ret; + + _enter(""); + + /* We have to be careful as we can end up racing with setattr() + * truncating the pagecache since the caller doesn't take a lock here + * to prevent it. + */ + + if (wbc->range_cyclic && mapping->writeback_index) { + start = mapping->writeback_index * PAGE_SIZE; + ret = netfs_writepages_region(mapping, wbc, group, + &start, LLONG_MAX); + if (ret < 0) + goto out; + + if (wbc->nr_to_write <= 0) { + mapping->writeback_index = start / PAGE_SIZE; + goto out; + } + + start = 0; + end = mapping->writeback_index * PAGE_SIZE; + mapping->writeback_index = 0; + ret = netfs_writepages_region(mapping, wbc, group, &start, end); + if (ret == 0) + mapping->writeback_index = start / PAGE_SIZE; + } else if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) { + start = 0; + ret = netfs_writepages_region(mapping, wbc, group, + &start, LLONG_MAX); + if (wbc->nr_to_write > 0 && ret == 0) + mapping->writeback_index = start / PAGE_SIZE; + } else { + start = wbc->range_start; + ret = netfs_writepages_region(mapping, wbc, group, + &start, wbc->range_end); + } + +out: + _leave(" = %d", ret); + return ret; +} +EXPORT_SYMBOL(netfs_writepages); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index f98deef22d06..ef17d94a2fbd 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -400,6 +400,8 @@ int netfs_read_folio(struct file *, struct folio *); int netfs_write_begin(struct netfs_inode *, struct file *, struct address_space *, loff_t pos, unsigned int len, struct folio **, void **fsdata); +int netfs_writepages(struct address_space *mapping, + struct writeback_control *wbc); bool netfs_dirty_folio(struct address_space *mapping, struct folio *folio); int netfs_unpin_writeback(struct inode *inode, struct writeback_control *wbc); void netfs_clear_inode_writeback(struct inode *inode, const void *aux); From patchwork Wed Dec 13 15:23:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491241 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8456FC4167D for ; Wed, 13 Dec 2023 15:26:44 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 163156B040B; Wed, 13 Dec 2023 10:26:44 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 112B76B040C; Wed, 13 Dec 2023 10:26:44 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id ECE4A6B040D; Wed, 13 Dec 2023 10:26:43 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id DD7F66B040B for ; Wed, 13 Dec 2023 10:26:43 -0500 (EST) Received: from smtpin26.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id BFDC01A0151 for ; Wed, 13 Dec 2023 15:26:43 +0000 (UTC) X-FDA: 81562172286.26.D6E366D Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf11.hostedemail.com (Postfix) with ESMTP id 112744000E for ; Wed, 13 Dec 2023 15:26:41 +0000 (UTC) Authentication-Results: imf11.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=fKazqaXf; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf11.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481202; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=rsXVY8tpr/E9yMFTv2Ypl/L7pV1HZSNyLiZDFqk/Fm8=; b=W53GNVBeeY+Q2gLKj9fWJeqFpHaMnMQP32RM/wg5mVtER8oeYp2FyDdxDCCaBp0Oc1rZfg w4+su1LzfiWJBEsW22rEjW8KtFBQnRni9bIsrXBf50Py66x8owXXm6XG5a4G4oyDOSNuGd mhygUfkpqxIjrNSopKHjmRPSONeZ/hE= ARC-Authentication-Results: i=1; imf11.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=fKazqaXf; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf11.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481202; a=rsa-sha256; cv=none; b=zRwAV1Dc5VF2zl2Ioh55SIyyrsLBXqzBFk6ZFAebTHUbfIBwHQcVSHt/BbXXFAb1t5ADjs YL35exovnugekxDEl3L6t6e2VTn64jBllLdQ4BMJc7iHHtBevq+FBopoGiEGwv6ObGk0Ly 3MyV27EWuGLC5Ua9DelWkM1XWPTHIlo= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481201; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rsXVY8tpr/E9yMFTv2Ypl/L7pV1HZSNyLiZDFqk/Fm8=; b=fKazqaXfIBPaDL3e0yEaKU177JtyVWPZugPQYqnywlEflMXWmoXRj+GMW0Pnwwcw9VoGLF Q7h2HtE6otPpI7PsJ0yo/AwJeVKT1wtfTrk1e0JXtKOT9hh6dVr2bFXeNYUQCBHJWBvMPn FZ8f5zYckVQ27Ql2xCbiZNHmK4IfS/A= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-658-jGM-5vUJMrmT8-w3P6yTPg-1; Wed, 13 Dec 2023 10:26:35 -0500 X-MC-Unique: jGM-5vUJMrmT8-w3P6yTPg-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 70A3485A58A; Wed, 13 Dec 2023 15:26:34 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 31312492BC6; Wed, 13 Dec 2023 15:26:31 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 35/39] netfs: Provide a launder_folio implementation Date: Wed, 13 Dec 2023 15:23:45 +0000 Message-ID: <20231213152350.431591-36-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.9 X-Rspamd-Queue-Id: 112744000E X-Rspam-User: X-Rspamd-Server: rspam04 X-Stat-Signature: 8jzp7abgngammsn5je9ox7ib84bob496 X-HE-Tag: 1702481201-281046 X-HE-Meta: U2FsdGVkX19318Pv/9BuhdkH1ppwn07x8MXsMTiTH6Os0ySWA5nvzA8HqhLbEuOv0D02AZhmw0jnQEZGuaXRAXtfFOWTIqgFuefSlTY2uJhpTpRTHA6uRQAnj+gJQMyaX0WrojXK/04rjhdxiNLCCTjTOX/A8tcGDV73VuSbDZkijTzGWRfou2oHRnTjDNfbGbx8wn9cHoQSn/ihlFNACeJgPViJerb/hE6cph9f6DXhnxMWE9z/jSiIXav4wGSF386I7AgJtNXaVo9lQDvlkfKkYU6zLm3tNahN5kb7FFRh5FQbiPy+6EeZtv9UL1qFyBCoITQyv4fnyMkENdJDgIaOQuO8Bc/eowLpByX/lB4Oet+/0HeqAvFVrocCHuAEsSX35YZ1f5QTysGQDesPbUNHchHcKyOSFNPnbeNgNUjRL0Yfx7cT18yMctvxHmRoiaejGLbbBoea3O5MqPZsEOBqY/QM5ZePrdVgvUpT8vfRFIg08f7ZF4Nv1+WXsdkoaXBHrSd4lORXbPweeB/GcUewN75JMLklwDhC7zZ+mlKLLCkf5XynmzWOJSCQHB9TzW1dEdrqHlhSVQW75OCCSD802aoTU9IlSrsHHSYVrpTk+cVhCvgWIMFSuUr2hZ0yr1TElTwRYcZ6PQAPhi1C/XJcUrtN9XyKh1i3eCC2ab91xocDCnHlWboh2LgyI2L9XvjLp20XUGb9Sln9YLQN9H9GZ8RUjlpfeNeOkTyIdTYtBGFHcbj2tKJqdcLG60q3Tm0v/CiVttwRNFLrGDEW0/1wp2RK2M5G9UnsokNG+tNzDwAlFIZQuL6g5tLhC9z8PjW8DZo0EDGykaucnyv4MgTHxyv8Q+iNtNR6Minq0ZUdnDowq5zYDc1h7FRi3BKFpSBDglscf+v87bkkceWl8yJJKT8d/bGj6TRiJ422Kp1ussaJt7xxJt3YaP4szNYyNuIJkNKlFDi6TMunZLZ P3y7aqbK BJfzcA6e48zcEz5W7O5KOMItVDFDo7vld80nZ5PCFQSeFyDkin6ekhKLf6UDLq0R7qFcE1eU6oKr4q1yz0/gwIRUO1ThCHfDjQvXXCZ+4PMEYmztDcjjER6Ollgac4fTzRdDP7ho/KbeAT9jK2F+LVr5y0ch9WLFFJcr9ZJmG7XMxwvOfEUT2Ffxs5UiZSFFQD3GUZ20y9VlgHz3PCtH2dNnHOYoIv6kpj5PE+CmMbdJQK51czGmF5NwMs2fsCf1j01WK3Ykra8dtshkms/mo0n7o2Q5zf3IB+PdJbrAmMZ0VOKv+pE0qkG+zHFcQwDMRW40I0M7j6HFWAIAjZEmiL0X+tA== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Provide a launder_folio implementation for netfslib. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/buffered_write.c | 74 ++++++++++++++++++++++++++++++++++++ fs/netfs/main.c | 1 + include/linux/netfs.h | 2 + include/trace/events/netfs.h | 3 ++ 4 files changed, 80 insertions(+) diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index 42f89f8ea8af..8e0ebb7175a4 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -1122,3 +1122,77 @@ int netfs_writepages(struct address_space *mapping, return ret; } EXPORT_SYMBOL(netfs_writepages); + +/* + * Deal with the disposition of a laundered folio. + */ +static void netfs_cleanup_launder_folio(struct netfs_io_request *wreq) +{ + if (wreq->error) { + pr_notice("R=%08x Laundering error %d\n", wreq->debug_id, wreq->error); + mapping_set_error(wreq->mapping, wreq->error); + } +} + +/** + * netfs_launder_folio - Clean up a dirty folio that's being invalidated + * @folio: The folio to clean + * + * This is called to write back a folio that's being invalidated when an inode + * is getting torn down. Ideally, writepages would be used instead. + */ +int netfs_launder_folio(struct folio *folio) +{ + struct netfs_io_request *wreq; + struct address_space *mapping = folio->mapping; + struct netfs_folio *finfo = netfs_folio_info(folio); + struct netfs_group *group = netfs_folio_group(folio); + struct bio_vec bvec; + unsigned long long i_size = i_size_read(mapping->host); + unsigned long long start = folio_pos(folio); + size_t offset = 0, len; + int ret = 0; + + if (finfo) { + offset = finfo->dirty_offset; + start += offset; + len = finfo->dirty_len; + } else { + len = folio_size(folio); + } + len = min_t(unsigned long long, len, i_size - start); + + wreq = netfs_alloc_request(mapping, NULL, start, len, NETFS_LAUNDER_WRITE); + if (IS_ERR(wreq)) { + ret = PTR_ERR(wreq); + goto out; + } + + if (!folio_clear_dirty_for_io(folio)) + goto out_put; + + trace_netfs_folio(folio, netfs_folio_trace_launder); + + _debug("launder %llx-%llx", start, start + len - 1); + + /* Speculatively write to the cache. We have to fix this up later if + * the store fails. + */ + wreq->cleanup = netfs_cleanup_launder_folio; + + bvec_set_folio(&bvec, folio, len, offset); + iov_iter_bvec(&wreq->iter, ITER_SOURCE, &bvec, 1, len); + __set_bit(NETFS_RREQ_UPLOAD_TO_SERVER, &wreq->flags); + ret = netfs_begin_write(wreq, true, netfs_write_trace_launder); + +out_put: + folio_detach_private(folio); + netfs_put_group(group); + kfree(finfo); + netfs_put_request(wreq, false, netfs_rreq_trace_put_return); +out: + folio_wait_fscache(folio); + _leave(" = %d", ret); + return ret; +} +EXPORT_SYMBOL(netfs_launder_folio); diff --git a/fs/netfs/main.c b/fs/netfs/main.c index 9fe96de6960e..8d5ee0f56f28 100644 --- a/fs/netfs/main.c +++ b/fs/netfs/main.c @@ -33,6 +33,7 @@ static const char *netfs_origins[nr__netfs_io_origin] = { [NETFS_READPAGE] = "RP", [NETFS_READ_FOR_WRITE] = "RW", [NETFS_WRITEBACK] = "WB", + [NETFS_LAUNDER_WRITE] = "LW", [NETFS_UNBUFFERED_WRITE] = "UW", [NETFS_DIO_READ] = "DR", [NETFS_DIO_WRITE] = "DW", diff --git a/include/linux/netfs.h b/include/linux/netfs.h index ef17d94a2fbd..a7c2cb856e81 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -227,6 +227,7 @@ enum netfs_io_origin { NETFS_READPAGE, /* This read is a synchronous read */ NETFS_READ_FOR_WRITE, /* This read is to prepare a write */ NETFS_WRITEBACK, /* This write was triggered by writepages */ + NETFS_LAUNDER_WRITE, /* This is triggered by ->launder_folio() */ NETFS_UNBUFFERED_WRITE, /* This is an unbuffered write */ NETFS_DIO_READ, /* This is a direct I/O read */ NETFS_DIO_WRITE, /* This is a direct I/O write */ @@ -407,6 +408,7 @@ int netfs_unpin_writeback(struct inode *inode, struct writeback_control *wbc); void netfs_clear_inode_writeback(struct inode *inode, const void *aux); void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length); bool netfs_release_folio(struct folio *folio, gfp_t gfp); +int netfs_launder_folio(struct folio *folio); /* VMA operations API. */ vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_group); diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 914a24b03d08..cc998798e20a 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -25,6 +25,7 @@ #define netfs_write_traces \ EM(netfs_write_trace_dio_write, "DIO-WRITE") \ + EM(netfs_write_trace_launder, "LAUNDER ") \ EM(netfs_write_trace_unbuffered_write, "UNB-WRITE") \ E_(netfs_write_trace_writeback, "WRITEBACK") @@ -33,6 +34,7 @@ EM(NETFS_READPAGE, "RP") \ EM(NETFS_READ_FOR_WRITE, "RW") \ EM(NETFS_WRITEBACK, "WB") \ + EM(NETFS_LAUNDER_WRITE, "LW") \ EM(NETFS_UNBUFFERED_WRITE, "UW") \ EM(NETFS_DIO_READ, "DR") \ E_(NETFS_DIO_WRITE, "DW") @@ -127,6 +129,7 @@ EM(netfs_folio_trace_end_copy, "end-copy") \ EM(netfs_folio_trace_filled_gaps, "filled-gaps") \ EM(netfs_folio_trace_kill, "kill") \ + EM(netfs_folio_trace_launder, "launder") \ EM(netfs_folio_trace_mkwrite, "mkwrite") \ EM(netfs_folio_trace_mkwrite_plus, "mkwrite+") \ EM(netfs_folio_trace_read_gaps, "read-gaps") \ From patchwork Wed Dec 13 15:23:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491242 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id AC52FC4332F for ; Wed, 13 Dec 2023 15:26:47 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 3D4876B040C; Wed, 13 Dec 2023 10:26:47 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 383CC6B040F; Wed, 13 Dec 2023 10:26:47 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 2256D6B0410; Wed, 13 Dec 2023 10:26:47 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 0E40C6B040C for ; Wed, 13 Dec 2023 10:26:47 -0500 (EST) Received: from smtpin22.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id D361F12015E for ; Wed, 13 Dec 2023 15:26:46 +0000 (UTC) X-FDA: 81562172412.22.AD00B46 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf29.hostedemail.com (Postfix) with ESMTP id EC568120025 for ; Wed, 13 Dec 2023 15:26:44 +0000 (UTC) Authentication-Results: imf29.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=HxA1pocf; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf29.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481205; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=DMHsdIxXvUk6Wbv0Mmvq6RSRYJtgXuGRYMsHtscd1pE=; b=ryH0blHL4/Ea8WiYUiq2XSoCk8V8Vkdm4Wn1vhRLYS0KdybHiEh5tzr1kET5DxLH2nFqQi K9CDIWu1W1zT2sNv758+Ij2MU4+wSPyhh23rANC3Yur398dK4magUY6+21lQbkaPeyn0wp T7y7o2NUxHwZIyx3DcDoAXQj1r8txOM= ARC-Authentication-Results: i=1; imf29.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=HxA1pocf; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf29.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481205; a=rsa-sha256; cv=none; b=OBAHHVdQMRmw0hso3VlW8CiSlJwkv1hLn1bXbwueNPfgMP3AGN8x8aBEIYhpanuWHc2RUV /E9zfvVajHDWP0soRnmo7sUFLntqty5a4NHF76kMms0oemHiWTvWIFne00qqTYfCvPeQOg g6p9jeiNnSQyM9euImcuG3YOXg7NlDA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481204; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DMHsdIxXvUk6Wbv0Mmvq6RSRYJtgXuGRYMsHtscd1pE=; b=HxA1pocfarDTlyKebJaeSmwWER4pir9XRdQxJosxGBFRRlnZH2iqm/8amZT4gmfuHNJlY8 eUzz5BMSiKyd0o0U1CvNMZYzcg7+B39fy61P5Pvypl7YFWWVVetO9hg5SUN+jQrJwLnBAk +GiEvtttaq49Q6MYhzjJd5HEIHKNBHc= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-694-Er9oBpO1OKyr_sJ9-Ser6g-1; Wed, 13 Dec 2023 10:26:41 -0500 X-MC-Unique: Er9oBpO1OKyr_sJ9-Ser6g-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id DE2AF3811F29; Wed, 13 Dec 2023 15:26:38 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 84755492BC6; Wed, 13 Dec 2023 15:26:35 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 36/39] netfs: Implement a write-through caching option Date: Wed, 13 Dec 2023 15:23:46 +0000 Message-ID: <20231213152350.431591-37-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.9 X-Rspam-User: X-Stat-Signature: yyk79xhd89tonq74g7y9wonxzkriho4q X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: EC568120025 X-HE-Tag: 1702481204-441304 X-HE-Meta: U2FsdGVkX1/lxfA8iTJqgYYIQvXOeqPuemfODD9Y1a1w0452yH5eZECSe7zJZs/QL98t4hQdQ+Sz8W/bNrqvjcPKDKEoDeApgOufNfQhDyOO7krhfNzjD8jSrmiIAZTeeqomPcn9iThYlMh1GwXRSCZXP5hD3jaDOgUvJJdwBDa4/YMC9iWmulA4tE0+4ldK2QHVJEgEU4bwH3iODfW9iznq2n0F0MB0Fia2Swr6s18jVwCH4mvKpI+spKJV1zdJOkKleXCA8HNbPhM0MumaBwzGWLM2m3keF/+AKudhdGZr1Yukyr1vN3VolwTePik4E2aXY99J1rdsmn1Rp0+Qt8qBhxBWWSuV3fNhtR36A2n/avwYnGmIwBZpfc7A1hd/s3nn4GY2xrS1mpOG9GHB+nhmaquaLHIcJj5ySwgat0952r71PxbHcODK8KkmrJeXN6EpLmGsndFSk9aJEW+aPRPH08c0bqJGP4jAV70WmmdKPs2dIFsNetekcO4X8YdSYjBtgAZzSWR1VEuSfGAorj41FgsWSmHQYVY9Kt4w/vg8zzhbVcKj6XZeCPUh8DPKUizqPhACSJVkXZ2hMU6pB2d9BofJmdNBBGDqzMYBgeyetC3158W5NpLBiT2DL3AVjluzD+R/IGfZ+zjFWGbyF0KySTXgs9lTD4icubwYLkrwZlosiCEpeNG6xHsYFJI9hn3BE0dpNzjW6Jo0P6hCcdZ0gDKORRG0EKLucjdb57ijCYhgDm/+q9W+q0oMQyfscELIxX00FKKn1JErdqrZ99bYE9VHgf1rpVXv++feuBZ62fGcbiB1BdSuAOKzjTa37CVJ1wYvhHbkHsdUTzKvpySoLzRN1gJKYcAKS/PefDpK0dTSwwse/x6ILgqHY3zRTwbsha1n+XPWXdCvVKx1G/ALihCPZ19oGjUEYxqyXLKOHuMQYKCOMGCNfKQF1sdazR8cUFjX/ORu8oq5DXJ JiTWb3Ap zEHsSNg9qJ7TUIk1ZWba3ZonoAUnW2xdV2CHLm0yj89ZJRevdS3dxn3vCYVzluNjzAmbkX9YIxcDYLI/FUQklxyTtcqaawvi8HLWnpmVyGoDxel6VJzOvFqwlpmIfo6b6LcuefYxJueUD3f52MWTUIXUOSB/pG8Pbspxy5dN/NlK6I3TAA3sinMyoEFHYOR1222vFEoZAoS2zmSmNCwCvMsdaY7A6E7S93fgtz2pIjGx8GvLq/2N5gBF7orJXnv1Gw3OKJ113QNp8DjJStVXZmw/EKHysTjgK2UNjgzznWNuWets= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Provide a flag whereby a filesystem may request that cifs_perform_write() perform write-through caching. This involves putting pages directly into writeback rather than dirty and attaching them to a write operation as we go. Further, the writes being made are limited to the byte range being written rather than whole folios being written. This can be used by cifs, for example, to deal with strict byte-range locking. This can't be used with content encryption as that may require expansion of the write RPC beyond the write being made. This doesn't affect writes via mmap - those are written back in the normal way; similarly failed writethrough writes are marked dirty and left to writeback to retry. Another option would be to simply invalidate them, but the contents can be simultaneously accessed by read() and through mmap. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/buffered_write.c | 69 +++++++++++++++++++++++---- fs/netfs/internal.h | 3 ++ fs/netfs/main.c | 1 + fs/netfs/objects.c | 1 + fs/netfs/output.c | 90 ++++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 2 + include/trace/events/netfs.h | 8 +++- 7 files changed, 162 insertions(+), 12 deletions(-) diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index 8e0ebb7175a4..dce6995fb644 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -26,6 +26,8 @@ enum netfs_how_to_modify { NETFS_FLUSH_CONTENT, /* Flush incompatible content. */ }; +static void netfs_cleanup_buffered_write(struct netfs_io_request *wreq); + static void netfs_set_group(struct folio *folio, struct netfs_group *netfs_group) { if (netfs_group && !folio_get_private(folio)) @@ -133,6 +135,14 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, struct inode *inode = file_inode(file); struct address_space *mapping = inode->i_mapping; struct netfs_inode *ctx = netfs_inode(inode); + struct writeback_control wbc = { + .sync_mode = WB_SYNC_NONE, + .for_sync = true, + .nr_to_write = LONG_MAX, + .range_start = iocb->ki_pos, + .range_end = iocb->ki_pos + iter->count, + }; + struct netfs_io_request *wreq = NULL; struct netfs_folio *finfo; struct folio *folio; enum netfs_how_to_modify howto; @@ -143,6 +153,30 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, size_t max_chunk = PAGE_SIZE << MAX_PAGECACHE_ORDER; bool maybe_trouble = false; + if (unlikely(test_bit(NETFS_ICTX_WRITETHROUGH, &ctx->flags) || + iocb->ki_flags & (IOCB_DSYNC | IOCB_SYNC)) + ) { + if (pos < i_size_read(inode)) { + ret = filemap_write_and_wait_range(mapping, pos, pos + iter->count); + if (ret < 0) { + goto out; + } + } + + wbc_attach_fdatawrite_inode(&wbc, mapping->host); + + wreq = netfs_begin_writethrough(iocb, iter->count); + if (IS_ERR(wreq)) { + wbc_detach_inode(&wbc); + ret = PTR_ERR(wreq); + wreq = NULL; + goto out; + } + if (!is_sync_kiocb(iocb)) + wreq->iocb = iocb; + wreq->cleanup = netfs_cleanup_buffered_write; + } + do { size_t flen; size_t offset; /* Offset into pagecache folio */ @@ -315,7 +349,25 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, } written += copied; - folio_mark_dirty(folio); + if (likely(!wreq)) { + folio_mark_dirty(folio); + } else { + if (folio_test_dirty(folio)) + /* Sigh. mmap. */ + folio_clear_dirty_for_io(folio); + /* We make multiple writes to the folio... */ + if (!folio_test_writeback(folio)) { + folio_wait_fscache(folio); + folio_start_writeback(folio); + folio_start_fscache(folio); + if (wreq->iter.count == 0) + trace_netfs_folio(folio, netfs_folio_trace_wthru); + else + trace_netfs_folio(folio, netfs_folio_trace_wthru_plus); + } + netfs_advance_writethrough(wreq, copied, + offset + copied == flen); + } retry: folio_unlock(folio); folio_put(folio); @@ -325,17 +377,14 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, } while (iov_iter_count(iter)); out: - if (likely(written)) { - /* Flush and wait for a write that requires immediate synchronisation. */ - if (iocb->ki_flags & (IOCB_DSYNC | IOCB_SYNC)) { - _debug("dsync"); - ret = filemap_fdatawait_range(mapping, iocb->ki_pos, - iocb->ki_pos + written); - } - - iocb->ki_pos += written; + if (unlikely(wreq)) { + ret = netfs_end_writethrough(wreq, iocb); + wbc_detach_inode(&wbc); + if (ret == -EIOCBQUEUED) + return ret; } + iocb->ki_pos += written; _leave(" = %zd [%zd]", written, ret); return written ? written : ret; diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index fe72280b0f30..b3749d6ec1ff 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -101,6 +101,9 @@ static inline void netfs_see_request(struct netfs_io_request *rreq, */ int netfs_begin_write(struct netfs_io_request *wreq, bool may_wait, enum netfs_write_trace what); +struct netfs_io_request *netfs_begin_writethrough(struct kiocb *iocb, size_t len); +int netfs_advance_writethrough(struct netfs_io_request *wreq, size_t copied, bool to_page_end); +int netfs_end_writethrough(struct netfs_io_request *wreq, struct kiocb *iocb); /* * stats.c diff --git a/fs/netfs/main.c b/fs/netfs/main.c index 8d5ee0f56f28..7139397931b7 100644 --- a/fs/netfs/main.c +++ b/fs/netfs/main.c @@ -33,6 +33,7 @@ static const char *netfs_origins[nr__netfs_io_origin] = { [NETFS_READPAGE] = "RP", [NETFS_READ_FOR_WRITE] = "RW", [NETFS_WRITEBACK] = "WB", + [NETFS_WRITETHROUGH] = "WT", [NETFS_LAUNDER_WRITE] = "LW", [NETFS_UNBUFFERED_WRITE] = "UW", [NETFS_DIO_READ] = "DR", diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 16252cc4576e..37626328577e 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -42,6 +42,7 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, rreq->debug_id = atomic_inc_return(&debug_ids); xa_init(&rreq->bounce); INIT_LIST_HEAD(&rreq->subrequests); + INIT_WORK(&rreq->work, NULL); refcount_set(&rreq->ref, 1); __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); diff --git a/fs/netfs/output.c b/fs/netfs/output.c index cc9065733b42..625eb68f3e5a 100644 --- a/fs/netfs/output.c +++ b/fs/netfs/output.c @@ -386,3 +386,93 @@ int netfs_begin_write(struct netfs_io_request *wreq, bool may_wait, TASK_UNINTERRUPTIBLE); return wreq->error; } + +/* + * Begin a write operation for writing through the pagecache. + */ +struct netfs_io_request *netfs_begin_writethrough(struct kiocb *iocb, size_t len) +{ + struct netfs_io_request *wreq; + struct file *file = iocb->ki_filp; + + wreq = netfs_alloc_request(file->f_mapping, file, iocb->ki_pos, len, + NETFS_WRITETHROUGH); + if (IS_ERR(wreq)) + return wreq; + + trace_netfs_write(wreq, netfs_write_trace_writethrough); + + __set_bit(NETFS_RREQ_UPLOAD_TO_SERVER, &wreq->flags); + iov_iter_xarray(&wreq->iter, ITER_SOURCE, &wreq->mapping->i_pages, wreq->start, 0); + wreq->io_iter = wreq->iter; + + /* ->outstanding > 0 carries a ref */ + netfs_get_request(wreq, netfs_rreq_trace_get_for_outstanding); + atomic_set(&wreq->nr_outstanding, 1); + return wreq; +} + +static void netfs_submit_writethrough(struct netfs_io_request *wreq, bool final) +{ + struct netfs_inode *ictx = netfs_inode(wreq->inode); + unsigned long long start; + size_t len; + + if (!test_bit(NETFS_RREQ_UPLOAD_TO_SERVER, &wreq->flags)) + return; + + start = wreq->start + wreq->submitted; + len = wreq->iter.count - wreq->submitted; + if (!final) { + len /= wreq->wsize; /* Round to number of maximum packets */ + len *= wreq->wsize; + } + + ictx->ops->create_write_requests(wreq, start, len); + wreq->submitted += len; +} + +/* + * Advance the state of the write operation used when writing through the + * pagecache. Data has been copied into the pagecache that we need to append + * to the request. If we've added more than wsize then we need to create a new + * subrequest. + */ +int netfs_advance_writethrough(struct netfs_io_request *wreq, size_t copied, bool to_page_end) +{ + _enter("ic=%zu sb=%zu ws=%u cp=%zu tp=%u", + wreq->iter.count, wreq->submitted, wreq->wsize, copied, to_page_end); + + wreq->iter.count += copied; + wreq->io_iter.count += copied; + if (to_page_end && wreq->io_iter.count - wreq->submitted >= wreq->wsize) + netfs_submit_writethrough(wreq, false); + + return wreq->error; +} + +/* + * End a write operation used when writing through the pagecache. + */ +int netfs_end_writethrough(struct netfs_io_request *wreq, struct kiocb *iocb) +{ + int ret = -EIOCBQUEUED; + + _enter("ic=%zu sb=%zu ws=%u", + wreq->iter.count, wreq->submitted, wreq->wsize); + + if (wreq->submitted < wreq->io_iter.count) + netfs_submit_writethrough(wreq, true); + + if (atomic_dec_and_test(&wreq->nr_outstanding)) + netfs_write_terminated(wreq, false); + + if (is_sync_kiocb(iocb)) { + wait_on_bit(&wreq->flags, NETFS_RREQ_IN_PROGRESS, + TASK_UNINTERRUPTIBLE); + ret = wreq->error; + } + + netfs_put_request(wreq, false, netfs_rreq_trace_put_return); + return ret; +} diff --git a/include/linux/netfs.h b/include/linux/netfs.h index a7c2cb856e81..fc77f7be220a 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -139,6 +139,7 @@ struct netfs_inode { unsigned long flags; #define NETFS_ICTX_ODIRECT 0 /* The file has DIO in progress */ #define NETFS_ICTX_UNBUFFERED 1 /* I/O should not use the pagecache */ +#define NETFS_ICTX_WRITETHROUGH 2 /* Write-through caching */ }; /* @@ -227,6 +228,7 @@ enum netfs_io_origin { NETFS_READPAGE, /* This read is a synchronous read */ NETFS_READ_FOR_WRITE, /* This read is to prepare a write */ NETFS_WRITEBACK, /* This write was triggered by writepages */ + NETFS_WRITETHROUGH, /* This write was made by netfs_perform_write() */ NETFS_LAUNDER_WRITE, /* This is triggered by ->launder_folio() */ NETFS_UNBUFFERED_WRITE, /* This is an unbuffered write */ NETFS_DIO_READ, /* This is a direct I/O read */ diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index cc998798e20a..447a8c21cf57 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -27,13 +27,15 @@ EM(netfs_write_trace_dio_write, "DIO-WRITE") \ EM(netfs_write_trace_launder, "LAUNDER ") \ EM(netfs_write_trace_unbuffered_write, "UNB-WRITE") \ - E_(netfs_write_trace_writeback, "WRITEBACK") + EM(netfs_write_trace_writeback, "WRITEBACK") \ + E_(netfs_write_trace_writethrough, "WRITETHRU") #define netfs_rreq_origins \ EM(NETFS_READAHEAD, "RA") \ EM(NETFS_READPAGE, "RP") \ EM(NETFS_READ_FOR_WRITE, "RW") \ EM(NETFS_WRITEBACK, "WB") \ + EM(NETFS_WRITETHROUGH, "WT") \ EM(NETFS_LAUNDER_WRITE, "LW") \ EM(NETFS_UNBUFFERED_WRITE, "UW") \ EM(NETFS_DIO_READ, "DR") \ @@ -136,7 +138,9 @@ EM(netfs_folio_trace_redirty, "redirty") \ EM(netfs_folio_trace_redirtied, "redirtied") \ EM(netfs_folio_trace_store, "store") \ - E_(netfs_folio_trace_store_plus, "store+") + EM(netfs_folio_trace_store_plus, "store+") \ + EM(netfs_folio_trace_wthru, "wthru") \ + E_(netfs_folio_trace_wthru_plus, "wthru+") #ifndef __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY #define __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY From patchwork Wed Dec 13 15:23:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491243 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id F1B54C4167D for ; Wed, 13 Dec 2023 15:26:50 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 387156B0411; Wed, 13 Dec 2023 10:26:50 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 224C16B0412; Wed, 13 Dec 2023 10:26:50 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id E84206B0416; Wed, 13 Dec 2023 10:26:49 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id C4E086B0411 for ; Wed, 13 Dec 2023 10:26:49 -0500 (EST) Received: from smtpin25.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 9363FC01E2 for ; Wed, 13 Dec 2023 15:26:49 +0000 (UTC) X-FDA: 81562172538.25.1A84E53 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf29.hostedemail.com (Postfix) with ESMTP id D5D1B120021 for ; Wed, 13 Dec 2023 15:26:47 +0000 (UTC) Authentication-Results: imf29.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=iHHs1bEU; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf29.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481207; a=rsa-sha256; cv=none; b=FNRD+ZF/9wPYRhEIgkYAzE2Vrmu1cnXfjOLw9sqcQKCz+BK4CWmD3dBtwiI2FMLmgFPAWY PhN86JnMZXbO3Wuyh3A7CUAx943nro5GqdiyaG4R80b5Yng1Uzg1i+tscQi7fUniv++Hae G9XkKa04MxeTLiEmcTlqRjRfRLd0LLs= ARC-Authentication-Results: i=1; imf29.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=iHHs1bEU; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf29.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481207; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=/Ab7pD2nMsmL/2vj0tSsGNun7wyGJFCz58dAavqg0G8=; b=DKMOPtV8YM9Ct3pa2O18d+bLPkp7gjAocXQoNWPfdtcKP2W7B4Mqdp1XjCpd7O3MFp3Yvf uAxzO8jkGiPUkbs/Q5jMDgPuj5HBSq0KaL03ErvxDUs2Q7ipicpCAcfiwe5Fu03w2PWkC4 gdzjsHPKFOPw5jUF2sqCwl+M3FNzPkY= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481207; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/Ab7pD2nMsmL/2vj0tSsGNun7wyGJFCz58dAavqg0G8=; b=iHHs1bEU30DAMBz9b0oMphhpd0tOqhELwy1TUjgyaCLPwWzHY0mTttZn9djeLSOWeXV61H p3R4wYAd27OXM5dxEA1+6iUWQum+KN2Za9x+8epHvPdXH/fXJyzq38L1YyC3Zp42DHSING Aes4FgavMl/qmbtL1mEMn1dxz330gLc= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-112-MKXcD1FRNDu_tpDUpTh0YQ-1; Wed, 13 Dec 2023 10:26:44 -0500 X-MC-Unique: MKXcD1FRNDu_tpDUpTh0YQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6E6978828CB; Wed, 13 Dec 2023 15:26:43 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id E6C3140C6EB9; Wed, 13 Dec 2023 15:26:39 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 37/39] netfs: Optimise away reads above the point at which there can be no data Date: Wed, 13 Dec 2023 15:23:47 +0000 Message-ID: <20231213152350.431591-38-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-Rspam-User: X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: D5D1B120021 X-Stat-Signature: s8jqooeytm9h44mgy6ernz8k4x75zjr1 X-HE-Tag: 1702481207-416606 X-HE-Meta: U2FsdGVkX19eDEKxVX+qUMbXqk3yc7QW98jAaMaGnxxkhqVI0WIhP+VJyvtiqgXTy8HTlJR3d9WtRjD5eSx0s/bBMTVYuH0oAy79RJ3piiC7K3klibsmUTzGoFg17HSV/RGHrtGZMJhvNO9YcbJIMEUTsAJkcV8ttDkgEeefUyF3WOrKfmdmwPB9I/OpSAF1Ly6DVGK6abbTqafmXKeVtr1X3umojYOOtUQSV+dWEiW9eKkuIUZIbMYZzvo9xVSVoqzSDXehwvksJYgIdc8FlfHJ2e1hiItpbFQhe4E3k87Wl3IpQPxerNODB4SSkCrRW0/EcKowSfdSUc3bZ6l/TLtQlOiEpaCZ8JSLz7d46n7JghhSnNcE/Ag0V3b6L5n30dkvB33hQhx/qB1QrrJNA5OVcmsdBt3GAu85Jiam40APjGdiXCzO3ZDmjB2s6aSFlMs5KgLjHK4Zrwb2ti/kUzdVTpTf6o92dHL/e9+0/QLRcaZ0nf5/Mol5hATVMeAkzr8iXv2CrozSooGEIVYWrcN5a/2Hb72iCvcpNDc7I7eB7m9h5+ymT288MaEuiyvkeSFxMvqArqP5HD3FerTzJjvFcgKD6zF6LFU3X2d0t3GOVUp+Wj3NPNU5w1nUg6bFLRRaSAqhyi3Se5kE+9uqt8r9wB+soii7EgVJZhKkiagynYVZfJOeJLKaCmL8d2KZW6B+7fyijPo8buOwdeNJWpsCPLVJid/LDNb0NPJOfGEgwEz2CZUgQLQlDKYLVu/qS0SUxF1s+7BYbGfUE/GNS84sE2JsXhax2ti7j15rofHimkylgVhh2byjoifsVNwhonlQ+FdzISonfuMuIVMCM4Mqum/C9QapzdA3T1FXUkHCZsAE2DDcgSzrm6+7nAzqNUJVdGC7Q4nsPmTUymO48a4BNfyVUAT7hbf/fZqmoC/LgqeXYQtGQogwm+VwCWIOc6YAgQ8m9P4hwOyKRFd bGixwGCs Wk9LavJj5KXeXxEWt9BRhp/ddgqca3CLWOK4bCQGtWXvjFdFuK02GgeJVEIZOmsJvkJbagAhqvLAQSjtRRRxclHCCRrIJPIVLjcQzs+ZeVbbFcEK4OMuOMJWaVc0cH6GJOOiUO+nGidRy86OJafK0yCL/ZiM7pRThINsmklyKtyyAKj5DMSM84PkZ3NFiQlZNLeb2BJPerAw2E4r3eCwh3UMMNH87SlcsaQM87/SzXIqdo5+X8Bq33ijUY4yN1tsXTYdh9ZM7WTSAm3rHq6vVXG9wPP8Lhv0znVW5+btTvP4mPek= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Track the file position above which the server is not expected to have any data (the "zero point") and preemptively assume that we can satisfy requests by filling them with zeroes locally rather than attempting to download them if they're over that line - even if we've written data back to the server. Assume that any data that was written back above that position is held in the local cache. Note that we have to split requests that straddle the line. Make use of this to optimise away some reads from the server. We need to set the zero point in the following circumstances: (1) When we see an extant remote inode and have no cache for it, we set the zero_point to i_size. (2) On local inode creation, we set zero_point to 0. (3) On local truncation down, we reduce zero_point to the new i_size if the new i_size is lower. (4) On local truncation up, we don't change zero_point. (5) On local modification, we don't change zero_point. (6) On remote invalidation, we set zero_point to the new i_size. (7) If stored data is discarded from the pagecache or culled from fscache, we must set zero_point above that if the data also got written to the server. (8) If dirty data is written back to the server, but not fscache, we must set zero_point above that. (9) If a direct I/O write is made, set zero_point above that. Assuming the above, any read from the server at or above the zero_point position will return all zeroes. The zero_point value can be stored in the cache, provided the above rules are applied to it by any code that culls part of the local cache. Signed-off-by: David Howells cc: Jeff Layton cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/afs/inode.c | 22 +++++++++++++--------- fs/netfs/buffered_write.c | 2 +- fs/netfs/direct_write.c | 4 ++++ fs/netfs/io.c | 10 ++++++++++ fs/netfs/misc.c | 5 +++++ fs/smb/client/cifsfs.c | 4 ++-- include/linux/netfs.h | 14 ++++++++++++-- 7 files changed, 47 insertions(+), 14 deletions(-) diff --git a/fs/afs/inode.c b/fs/afs/inode.c index c43112dcbbbb..dfd940a64e0f 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -166,6 +166,7 @@ static void afs_apply_status(struct afs_operation *op, struct inode *inode = &vnode->netfs.inode; struct timespec64 t; umode_t mode; + bool unexpected_jump = false; bool data_changed = false; bool change_size = vp->set_size; @@ -230,6 +231,7 @@ static void afs_apply_status(struct afs_operation *op, } change_size = true; data_changed = true; + unexpected_jump = true; } else if (vnode->status.type == AFS_FTYPE_DIR) { /* Expected directory change is handled elsewhere so * that we can locally edit the directory and save on a @@ -251,6 +253,8 @@ static void afs_apply_status(struct afs_operation *op, vnode->netfs.remote_i_size = status->size; if (change_size || status->size > i_size_read(inode)) { afs_set_i_size(vnode, status->size); + if (unexpected_jump) + vnode->netfs.zero_point = status->size; inode_set_ctime_to_ts(inode, t); inode_set_atime_to_ts(inode, t); } @@ -689,17 +693,17 @@ static void afs_setattr_success(struct afs_operation *op) static void afs_setattr_edit_file(struct afs_operation *op) { struct afs_vnode_param *vp = &op->file[0]; - struct inode *inode = &vp->vnode->netfs.inode; + struct afs_vnode *vnode = vp->vnode; if (op->setattr.attr->ia_valid & ATTR_SIZE) { loff_t size = op->setattr.attr->ia_size; loff_t i_size = op->setattr.old_i_size; - if (size < i_size) - truncate_pagecache(inode, size); - if (size != i_size) - fscache_resize_cookie(afs_vnode_cache(vp->vnode), - vp->scb.status.size); + if (size != i_size) { + truncate_setsize(&vnode->netfs.inode, size); + netfs_resize_file(&vnode->netfs, size, true); + fscache_resize_cookie(afs_vnode_cache(vnode), size); + } } } @@ -767,11 +771,11 @@ int afs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, */ if (!(attr->ia_valid & (supported & ~ATTR_SIZE & ~ATTR_MTIME)) && attr->ia_size < i_size && - attr->ia_size > vnode->status.size) { - truncate_pagecache(inode, attr->ia_size); + attr->ia_size > vnode->netfs.remote_i_size) { + truncate_setsize(inode, attr->ia_size); + netfs_resize_file(&vnode->netfs, size, false); fscache_resize_cookie(afs_vnode_cache(vnode), attr->ia_size); - i_size_write(inode, attr->ia_size); ret = 0; goto out_unlock; } diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index dce6995fb644..d7ce424b9188 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -73,7 +73,7 @@ static enum netfs_how_to_modify netfs_how_to_modify(struct netfs_inode *ctx, if (folio_test_uptodate(folio)) return NETFS_FOLIO_IS_UPTODATE; - if (pos >= ctx->remote_i_size) + if (pos >= ctx->zero_point) return NETFS_MODIFY_AND_CLEAR; if (!maybe_trouble && offset == 0 && len >= flen) diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c index bb0c2718f57b..aad05f2349a4 100644 --- a/fs/netfs/direct_write.c +++ b/fs/netfs/direct_write.c @@ -134,6 +134,7 @@ ssize_t netfs_unbuffered_write_iter(struct kiocb *iocb, struct iov_iter *from) struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; struct netfs_inode *ictx = netfs_inode(inode); + unsigned long long end; ssize_t ret; _enter("%llx,%zx,%llx", iocb->ki_pos, iov_iter_count(from), i_size_read(inode)); @@ -155,6 +156,9 @@ ssize_t netfs_unbuffered_write_iter(struct kiocb *iocb, struct iov_iter *from) ret = kiocb_invalidate_pages(iocb, iov_iter_count(from)); if (ret < 0) goto out; + end = iocb->ki_pos + iov_iter_count(from); + if (end > ictx->zero_point) + ictx->zero_point = end; fscache_invalidate(netfs_i_cookie(ictx), NULL, i_size_read(inode), FSCACHE_INVAL_DIO_WRITE); diff --git a/fs/netfs/io.c b/fs/netfs/io.c index 5d9098db815a..41a6113aa7fa 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -569,6 +569,7 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq, struct iov_iter *io_iter) { enum netfs_io_source source = NETFS_DOWNLOAD_FROM_SERVER; + struct netfs_inode *ictx = netfs_inode(rreq->inode); size_t lsize; _enter("%llx-%llx,%llx", subreq->start, subreq->start + subreq->len, rreq->i_size); @@ -586,6 +587,14 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq, * to make serial calls, it can indicate a short read and then * we will call it again. */ + if (rreq->origin != NETFS_DIO_READ) { + if (subreq->start >= ictx->zero_point) { + source = NETFS_FILL_WITH_ZEROES; + goto set; + } + if (subreq->len > ictx->zero_point - subreq->start) + subreq->len = ictx->zero_point - subreq->start; + } if (subreq->len > rreq->i_size - subreq->start) subreq->len = rreq->i_size - subreq->start; if (rreq->rsize && subreq->len > rreq->rsize) @@ -607,6 +616,7 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq, } } +set: if (subreq->len > rreq->len) pr_warn("R=%08x[%u] SREQ>RREQ %zx > %zx\n", rreq->debug_id, subreq->debug_index, diff --git a/fs/netfs/misc.c b/fs/netfs/misc.c index 40421ced4cd3..31e45dfad5b0 100644 --- a/fs/netfs/misc.c +++ b/fs/netfs/misc.c @@ -240,6 +240,11 @@ EXPORT_SYMBOL(netfs_invalidate_folio); bool netfs_release_folio(struct folio *folio, gfp_t gfp) { struct netfs_inode *ctx = netfs_inode(folio_inode(folio)); + unsigned long long end; + + end = folio_pos(folio) + folio_size(folio); + if (end > ctx->zero_point) + ctx->zero_point = end; if (folio_test_private(folio)) return false; diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index 96a65cf9b5ec..07cd88897c33 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -1220,7 +1220,7 @@ static int cifs_precopy_set_eof(struct inode *src_inode, struct cifsInodeInfo *s if (rc < 0) goto set_failed; - netfs_resize_file(&src_cifsi->netfs, src_end); + netfs_resize_file(&src_cifsi->netfs, src_end, true); fscache_resize_cookie(cifs_inode_cookie(src_inode), src_end); return 0; @@ -1351,7 +1351,7 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, smb_file_src, smb_file_target, off, len, destoff); if (rc == 0 && new_size > i_size_read(target_inode)) { truncate_setsize(target_inode, new_size); - netfs_resize_file(&target_cifsi->netfs, new_size); + netfs_resize_file(&target_cifsi->netfs, new_size, true); fscache_resize_cookie(cifs_inode_cookie(target_inode), new_size); } diff --git a/include/linux/netfs.h b/include/linux/netfs.h index fc77f7be220a..2005ad3b0e25 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -136,6 +136,8 @@ struct netfs_inode { struct fscache_cookie *cache; #endif loff_t remote_i_size; /* Size of the remote file */ + loff_t zero_point; /* Size after which we assume there's no data + * on the server */ unsigned long flags; #define NETFS_ICTX_ODIRECT 0 /* The file has DIO in progress */ #define NETFS_ICTX_UNBUFFERED 1 /* I/O should not use the pagecache */ @@ -465,22 +467,30 @@ static inline void netfs_inode_init(struct netfs_inode *ctx, { ctx->ops = ops; ctx->remote_i_size = i_size_read(&ctx->inode); + ctx->zero_point = ctx->remote_i_size; ctx->flags = 0; #if IS_ENABLED(CONFIG_FSCACHE) ctx->cache = NULL; #endif + /* ->releasepage() drives zero_point */ + mapping_set_release_always(ctx->inode.i_mapping); } /** * netfs_resize_file - Note that a file got resized * @ctx: The netfs inode being resized * @new_i_size: The new file size + * @changed_on_server: The change was applied to the server * * Inform the netfs lib that a file got resized so that it can adjust its state. */ -static inline void netfs_resize_file(struct netfs_inode *ctx, loff_t new_i_size) +static inline void netfs_resize_file(struct netfs_inode *ctx, loff_t new_i_size, + bool changed_on_server) { - ctx->remote_i_size = new_i_size; + if (changed_on_server) + ctx->remote_i_size = new_i_size; + if (new_i_size < ctx->zero_point) + ctx->zero_point = new_i_size; } /** From patchwork Wed Dec 13 15:23:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491244 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id DB374C4332F for ; Wed, 13 Dec 2023 15:26:56 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 707776B0412; Wed, 13 Dec 2023 10:26:56 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 6B8F96B0417; Wed, 13 Dec 2023 10:26:56 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 4E3D86B0418; Wed, 13 Dec 2023 10:26:56 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id 381036B0412 for ; Wed, 13 Dec 2023 10:26:56 -0500 (EST) Received: from smtpin15.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id E03A5160B81 for ; Wed, 13 Dec 2023 15:26:55 +0000 (UTC) X-FDA: 81562172790.15.4A77634 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf18.hostedemail.com (Postfix) with ESMTP id 1ADFD1C001C for ; Wed, 13 Dec 2023 15:26:53 +0000 (UTC) Authentication-Results: imf18.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=DJxITAGJ; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf18.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481214; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=6OpDWo92EAz8lnWtd0lrwWk2hVduMlXr4iw80i0tX5o=; b=Cvs10V/VAE3Wa1gUAy5xOGCvfI+YeWgb5tiiABE5xUwDozL16qjvoLwusczpwG3+BiydtP +HE8Wq3ApPUQZ9Y8v4RWNjnxLcUpO2xcDqD83l8BoMGsA8pHu8O+VgP+9wEdKCv5bkmFdJ ebfzVMsNWLg1LizFqYqjZNfIpTQIX1c= ARC-Authentication-Results: i=1; imf18.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=DJxITAGJ; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf18.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481214; a=rsa-sha256; cv=none; b=YXK5FBvGO8YcczqWaZqAojtLakUAJxvqlbQJoVhCTxiLwEKKZn8tJjpeGIolVKbHRsTBQT oECEPn725f/C7t99rtnOxxjotPnbIDo6u6NWyEn3C5zKrubk1Cb/2TSaSZSlp/yeb7gYaC r4bn12THXL9+Tr592LTYaoxesbm2CNg= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481213; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6OpDWo92EAz8lnWtd0lrwWk2hVduMlXr4iw80i0tX5o=; b=DJxITAGJypz7iCszP/V1PirhDGuwCLAUmtbWHa27hH9eI+M5wrsUpOx6QoEKZsalr7VQxH 091SWH/YASxU+NucWVrjFdf2Kr400DPV6UtCPJ0BbMaRvpObcT1fGfN6xW1sjSSWx3CEno QZxOrLCoyddYdI9oYPnPDUVg0eydoaM= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-42-WI5voJDsOmKzc7ZEW8vdYQ-1; Wed, 13 Dec 2023 10:26:49 -0500 X-MC-Unique: WI5voJDsOmKzc7ZEW8vdYQ-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id C1F3729AB400; Wed, 13 Dec 2023 15:26:47 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 34DCE51E3; Wed, 13 Dec 2023 15:26:44 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 38/39] afs: Use the netfs write helpers Date: Wed, 13 Dec 2023 15:23:48 +0000 Message-ID: <20231213152350.431591-39-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.5 X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 1ADFD1C001C X-Stat-Signature: 99n1afttdkjgb4njseu634kkgqn77xoh X-HE-Tag: 1702481213-600111 X-HE-Meta: U2FsdGVkX1+kMN0+YZvvfYRYjLXskDA2Lj2N8hhmetqQWxGqjCOy6sQeC2BEY0a0GN/QVQJpOJOmhS7hGASBXmG2R0boc1QYi8iKVLPl9soig6hUY0T4x8BV8a0+6TIFRrbl8lbqMrY+PJrpZDCy7LBn+yipFWdsXm7i0nWqv9ibXR+FDi6LIx2drjlO1/RSlrjYu6hUOiaOqbHlPt4yfVD+4WST9IiRxDzD9AT81qQcmJt3hh+hSkzXaw6qq/JvbQ1M6MFKN9WXjhkOdUFApCNpov62pgqwzdQcaqWUkJSWzDQRMyvgstjTeUzNozoSAwbvVCJFEK7fXiuxvwldRJNKzBJBvGq031Hz+YwmG2RjaAQxNwmz+KImnluCBrn2ThrDT7aVkzpLYZ20Qe1yW+I8W6d4NAPifb7C/PnoGdL0O4DSie03rHWgLoEJXBQPBQB2BxJqAcbXSyZcwXB29FfrT/MAJs+NH8tvkA272x9PMdbPuHjIy+v5NYvFvCYQEvoQ8uwil9ha7VenDlq5rzaSlk6GZDPu6I6X1/yub0iYbxZkMSnu+k4Rgiu3kNjA8mgSFpPLwCkLgbO8foM6Wbejp068MMWnZ4aJ/s7j0uqpCWdYA1iGQ9BY1oKyE43KXDTOTAy7qV78xLCUzzglwBTjROh58xUqKe+WaTSejN9gA0p0M/yunq+Bgky5j3SR6+8So/vb8fd7VE9T4Ql0xxDVImj260iOVqIC2SDlxFa/dQJAiBVv+EmK7fjOwmWtWBhEf/6sbauetAT1R2frq6P82PNQrfooVZqbr7m/Qxw7sE7afmE3OvU2wmTE7jJ7Hhwy9jPJZVEjpynSpfZhAz1tTX7zr2/Nyo7G9NAVs+xlU+z13KdOtqYgjyp4fSTXOVqYIfKvQQYz84lzyhM3cHJuuU8Jbxp6O2zqJMrWfVdZVTnBrJd5iU0s8VXSKPnFnee0fOeZSMXvtx+hZUU s6EqEJjy Q4hWk7GnQQD4zdxFvIKu/smvNOUO0R1NZ4E7OlJTInAxbbiG7T4FqSJdU39jRWTkIw66CQERzLNJFdW7OTVOYpMfvmj0So5Kwd0MaTYW+Ym2mDaA48UXDU8VF/aycpJzO2r+WisJOFvfXEOynDsq3maVtz8OntUBzgPeZiX9qKyZAGAAOIyV4NT+dVkpP/lyKBu3xz+evUBl7l5vlZ27i916TCutP3ZRIuLBM0HwB2MLKoSt7/k8sXuJJACobqufKTnP74QmgUWgbEXCrqTD2UugPyFDoMZda2+yTUPzTIHvIJFcJS1scc9ydZj3Wdc93i1Bm2fWEam3NhspiJwY9P2rjheayeRlNAq4/g9bzUMX0UsNaRl5CZot9PX5K9PcQwD+BcQgbvNoWWmIGum829kpPq1+I12sUXzZ8viBEKxUfwaTE4w42fAMmOg== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Make afs use the netfs write helpers. Signed-off-by: David Howells cc: Marc Dionne cc: Jeff Layton cc: linux-afs@lists.infradead.org cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/afs/file.c | 70 +++- fs/afs/internal.h | 10 +- fs/afs/write.c | 705 ++----------------------------------- include/trace/events/afs.h | 23 -- 4 files changed, 84 insertions(+), 724 deletions(-) diff --git a/fs/afs/file.c b/fs/afs/file.c index aa95b4d6376c..3d33b221d9ca 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -34,7 +34,7 @@ const struct file_operations afs_file_operations = { .release = afs_release, .llseek = generic_file_llseek, .read_iter = afs_file_read_iter, - .write_iter = afs_file_write, + .write_iter = netfs_file_write_iter, .mmap = afs_file_mmap, .splice_read = afs_file_splice_read, .splice_write = iter_file_splice_write, @@ -50,16 +50,15 @@ const struct inode_operations afs_file_inode_operations = { }; const struct address_space_operations afs_file_aops = { + .direct_IO = noop_direct_IO, .read_folio = netfs_read_folio, .readahead = netfs_readahead, .dirty_folio = netfs_dirty_folio, - .launder_folio = afs_launder_folio, + .launder_folio = netfs_launder_folio, .release_folio = netfs_release_folio, .invalidate_folio = netfs_invalidate_folio, - .write_begin = afs_write_begin, - .write_end = afs_write_end, - .writepages = afs_writepages, .migrate_folio = filemap_migrate_folio, + .writepages = afs_writepages, }; const struct address_space_operations afs_symlink_aops = { @@ -352,7 +351,10 @@ static int afs_symlink_read_folio(struct file *file, struct folio *folio) static int afs_init_request(struct netfs_io_request *rreq, struct file *file) { - rreq->netfs_priv = key_get(afs_file_key(file)); + if (file) + rreq->netfs_priv = key_get(afs_file_key(file)); + rreq->rsize = 256 * 1024; + rreq->wsize = 256 * 1024; return 0; } @@ -369,11 +371,36 @@ static void afs_free_request(struct netfs_io_request *rreq) key_put(rreq->netfs_priv); } +static void afs_update_i_size(struct inode *inode, loff_t new_i_size) +{ + struct afs_vnode *vnode = AFS_FS_I(inode); + loff_t i_size; + + write_seqlock(&vnode->cb_lock); + i_size = i_size_read(&vnode->netfs.inode); + if (new_i_size > i_size) { + i_size_write(&vnode->netfs.inode, new_i_size); + inode_set_bytes(&vnode->netfs.inode, new_i_size); + } + write_sequnlock(&vnode->cb_lock); + fscache_update_cookie(afs_vnode_cache(vnode), NULL, &new_i_size); +} + +static void afs_netfs_invalidate_cache(struct netfs_io_request *wreq) +{ + struct afs_vnode *vnode = AFS_FS_I(wreq->inode); + + afs_invalidate_cache(vnode, 0); +} + const struct netfs_request_ops afs_req_ops = { .init_request = afs_init_request, .free_request = afs_free_request, .check_write_begin = afs_check_write_begin, .issue_read = afs_issue_read, + .update_i_size = afs_update_i_size, + .invalidate_cache = afs_netfs_invalidate_cache, + .create_write_requests = afs_create_write_requests, }; static void afs_add_open_mmap(struct afs_vnode *vnode) @@ -441,28 +468,39 @@ static vm_fault_t afs_vm_map_pages(struct vm_fault *vmf, pgoff_t start_pgoff, pg static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) { - struct afs_vnode *vnode = AFS_FS_I(file_inode(iocb->ki_filp)); + struct inode *inode = file_inode(iocb->ki_filp); + struct afs_vnode *vnode = AFS_FS_I(inode); struct afs_file *af = iocb->ki_filp->private_data; - int ret; + ssize_t ret; - ret = afs_validate(vnode, af->key); + if (iocb->ki_flags & IOCB_DIRECT) + return netfs_unbuffered_read_iter(iocb, iter); + + ret = netfs_start_io_read(inode); if (ret < 0) return ret; - - return generic_file_read_iter(iocb, iter); + ret = afs_validate(vnode, af->key); + if (ret == 0) + ret = filemap_read(iocb, iter, 0); + netfs_end_io_read(inode); + return ret; } static ssize_t afs_file_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) { - struct afs_vnode *vnode = AFS_FS_I(file_inode(in)); + struct inode *inode = file_inode(in); + struct afs_vnode *vnode = AFS_FS_I(inode); struct afs_file *af = in->private_data; - int ret; + ssize_t ret; - ret = afs_validate(vnode, af->key); + ret = netfs_start_io_read(inode); if (ret < 0) return ret; - - return filemap_splice_read(in, ppos, pipe, len, flags); + ret = afs_validate(vnode, af->key); + if (ret == 0) + ret = filemap_splice_read(in, ppos, pipe, len, flags); + netfs_end_io_read(inode); + return ret; } diff --git a/fs/afs/internal.h b/fs/afs/internal.h index b638c0f87298..326eba1c89c7 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -1601,19 +1601,11 @@ bool afs_try_get_volume(struct afs_volume *volume, enum afs_volume_trace reason) /* * write.c */ -extern int afs_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, - struct page **pagep, void **fsdata); -extern int afs_write_end(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned copied, - struct page *page, void *fsdata); -extern int afs_writepage(struct page *, struct writeback_control *); extern int afs_writepages(struct address_space *, struct writeback_control *); -extern ssize_t afs_file_write(struct kiocb *, struct iov_iter *); extern int afs_fsync(struct file *, loff_t, loff_t, int); extern vm_fault_t afs_page_mkwrite(struct vm_fault *vmf); extern void afs_prune_wb_keys(struct afs_vnode *); -int afs_launder_folio(struct folio *); +void afs_create_write_requests(struct netfs_io_request *wreq, loff_t start, size_t len); /* * xattr.c diff --git a/fs/afs/write.c b/fs/afs/write.c index 959dfa8f1af0..74402d95a884 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -12,228 +12,17 @@ #include #include #include +#include #include "internal.h" -static int afs_writepages_region(struct address_space *mapping, - struct writeback_control *wbc, - unsigned long long start, - unsigned long long end, loff_t *_next, - bool max_one_loop); - -static void afs_write_to_cache(struct afs_vnode *vnode, loff_t start, size_t len, - loff_t i_size, bool caching); - -#ifdef CONFIG_AFS_FSCACHE -static void afs_folio_start_fscache(bool caching, struct folio *folio) -{ - if (caching) - folio_start_fscache(folio); -} -#else -static void afs_folio_start_fscache(bool caching, struct folio *folio) -{ -} -#endif - -/* - * prepare to perform part of a write to a page - */ -int afs_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, - struct page **_page, void **fsdata) -{ - struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); - struct folio *folio; - int ret; - - _enter("{%llx:%llu},%llx,%x", - vnode->fid.vid, vnode->fid.vnode, pos, len); - - /* Prefetch area to be written into the cache if we're caching this - * 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 = netfs_write_begin(&vnode->netfs, file, mapping, pos, len, &folio, fsdata); - if (ret < 0) - return ret; - -try_again: - /* See if this page is already partially written in a way that we can - * merge the new write with. - */ - if (folio_test_writeback(folio)) { - trace_afs_folio_dirty(vnode, tracepoint_string("alrdy"), folio); - folio_unlock(folio); - goto wait_for_writeback; - } - - *_page = folio_file_page(folio, pos / PAGE_SIZE); - _leave(" = 0"); - return 0; - -wait_for_writeback: - ret = folio_wait_writeback_killable(folio); - if (ret < 0) - goto error; - - ret = folio_lock_killable(folio); - if (ret < 0) - goto error; - goto try_again; - -error: - folio_put(folio); - _leave(" = %d", ret); - return ret; -} - -/* - * finalise part of a write to a page - */ -int afs_write_end(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned copied, - struct page *subpage, void *fsdata) -{ - struct folio *folio = page_folio(subpage); - struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); - loff_t i_size, write_end_pos; - - _enter("{%llx:%llu},{%lx}", - vnode->fid.vid, vnode->fid.vnode, folio_index(folio)); - - if (!folio_test_uptodate(folio)) { - if (copied < len) { - copied = 0; - goto out; - } - - folio_mark_uptodate(folio); - } - - if (copied == 0) - goto out; - - write_end_pos = pos + copied; - - i_size = i_size_read(&vnode->netfs.inode); - if (write_end_pos > i_size) { - write_seqlock(&vnode->cb_lock); - i_size = i_size_read(&vnode->netfs.inode); - if (write_end_pos > i_size) - afs_set_i_size(vnode, write_end_pos); - write_sequnlock(&vnode->cb_lock); - fscache_update_cookie(afs_vnode_cache(vnode), NULL, &write_end_pos); - } - - if (folio_mark_dirty(folio)) - _debug("dirtied %lx", folio_index(folio)); - -out: - folio_unlock(folio); - folio_put(folio); - return copied; -} - -/* - * kill all the pages in the given range - */ -static void afs_kill_pages(struct address_space *mapping, - loff_t start, loff_t len) -{ - struct afs_vnode *vnode = AFS_FS_I(mapping->host); - struct folio *folio; - pgoff_t index = start / PAGE_SIZE; - pgoff_t last = (start + len - 1) / PAGE_SIZE, next; - - _enter("{%llx:%llu},%llx @%llx", - vnode->fid.vid, vnode->fid.vnode, len, start); - - do { - _debug("kill %lx (to %lx)", index, last); - - folio = filemap_get_folio(mapping, index); - if (IS_ERR(folio)) { - next = index + 1; - continue; - } - - next = folio_next_index(folio); - - folio_clear_uptodate(folio); - folio_end_writeback(folio); - folio_lock(folio); - generic_error_remove_folio(mapping, folio); - folio_unlock(folio); - folio_put(folio); - - } while (index = next, index <= last); - - _leave(""); -} - -/* - * Redirty all the pages in a given range. - */ -static void afs_redirty_pages(struct writeback_control *wbc, - struct address_space *mapping, - loff_t start, loff_t len) -{ - struct afs_vnode *vnode = AFS_FS_I(mapping->host); - struct folio *folio; - pgoff_t index = start / PAGE_SIZE; - pgoff_t last = (start + len - 1) / PAGE_SIZE, next; - - _enter("{%llx:%llu},%llx @%llx", - vnode->fid.vid, vnode->fid.vnode, len, start); - - do { - _debug("redirty %llx @%llx", len, start); - - folio = filemap_get_folio(mapping, index); - if (IS_ERR(folio)) { - next = index + 1; - continue; - } - - next = index + folio_nr_pages(folio); - folio_redirty_for_writepage(wbc, folio); - folio_end_writeback(folio); - folio_put(folio); - } while (index = next, index <= last); - - _leave(""); -} - /* * completion of write to server */ static void afs_pages_written_back(struct afs_vnode *vnode, loff_t start, unsigned int len) { - struct address_space *mapping = vnode->netfs.inode.i_mapping; - struct folio *folio; - pgoff_t end; - - XA_STATE(xas, &mapping->i_pages, start / PAGE_SIZE); - _enter("{%llx:%llu},{%x @%llx}", vnode->fid.vid, vnode->fid.vnode, len, start); - rcu_read_lock(); - - end = (start + len - 1) / PAGE_SIZE; - xas_for_each(&xas, folio, end) { - if (!folio_test_writeback(folio)) { - kdebug("bad %x @%llx page %lx %lx", - len, start, folio_index(folio), end); - ASSERT(folio_test_writeback(folio)); - } - - trace_afs_folio_dirty(vnode, tracepoint_string("clear"), folio); - folio_end_writeback(folio); - } - - rcu_read_unlock(); - afs_prune_wb_keys(vnode); _leave(""); } @@ -370,337 +159,53 @@ static int afs_store_data(struct afs_vnode *vnode, struct iov_iter *iter, loff_t return afs_put_operation(op); } -/* - * Extend the region to be written back to include subsequent contiguously - * dirty pages if possible, but don't sleep while doing so. - * - * If this page holds new content, then we can include filler zeros in the - * writeback. - */ -static void afs_extend_writeback(struct address_space *mapping, - struct afs_vnode *vnode, - long *_count, - loff_t start, - loff_t max_len, - bool caching, - size_t *_len) +static void afs_upload_to_server(struct netfs_io_subrequest *subreq) { - struct folio_batch fbatch; - struct folio *folio; - pgoff_t index = (start + *_len) / PAGE_SIZE; - bool stop = true; - unsigned int i; - - XA_STATE(xas, &mapping->i_pages, index); - folio_batch_init(&fbatch); - - do { - /* Firstly, we gather up a batch of contiguous dirty pages - * under the RCU read lock - but we can't clear the dirty flags - * there if any of those pages are mapped. - */ - rcu_read_lock(); - - xas_for_each(&xas, folio, ULONG_MAX) { - stop = true; - if (xas_retry(&xas, folio)) - continue; - if (xa_is_value(folio)) - break; - if (folio_index(folio) != index) - break; - - if (!folio_try_get_rcu(folio)) { - xas_reset(&xas); - continue; - } - - /* Has the folio moved or been split? */ - if (unlikely(folio != xas_reload(&xas))) { - folio_put(folio); - break; - } - - if (!folio_trylock(folio)) { - folio_put(folio); - break; - } - if (!folio_test_dirty(folio) || - folio_test_writeback(folio) || - folio_test_fscache(folio)) { - folio_unlock(folio); - folio_put(folio); - break; - } - - index += folio_nr_pages(folio); - *_count -= folio_nr_pages(folio); - *_len += folio_size(folio); - stop = false; - if (*_len >= max_len || *_count <= 0) - stop = true; - - if (!folio_batch_add(&fbatch, folio)) - break; - if (stop) - break; - } - - if (!stop) - xas_pause(&xas); - rcu_read_unlock(); - - /* Now, if we obtained any folios, we can shift them to being - * writable and mark them for caching. - */ - if (!folio_batch_count(&fbatch)) - break; - - for (i = 0; i < folio_batch_count(&fbatch); i++) { - folio = fbatch.folios[i]; - trace_afs_folio_dirty(vnode, tracepoint_string("store+"), folio); + struct afs_vnode *vnode = AFS_FS_I(subreq->rreq->inode); + ssize_t ret; - if (!folio_clear_dirty_for_io(folio)) - BUG(); - folio_start_writeback(folio); - afs_folio_start_fscache(caching, folio); - folio_unlock(folio); - } + _enter("%x[%x],%zx", + subreq->rreq->debug_id, subreq->debug_index, subreq->io_iter.count); - folio_batch_release(&fbatch); - cond_resched(); - } while (!stop); + trace_netfs_sreq(subreq, netfs_sreq_trace_submit); + ret = afs_store_data(vnode, &subreq->io_iter, subreq->start, + subreq->rreq->origin == NETFS_LAUNDER_WRITE); + netfs_write_subrequest_terminated(subreq, ret < 0 ? ret : subreq->len, + false); } -/* - * Synchronously write back the locked page and any subsequent non-locked dirty - * pages. - */ -static ssize_t afs_write_back_from_locked_folio(struct address_space *mapping, - struct writeback_control *wbc, - struct folio *folio, - unsigned long long start, - unsigned long long end) +static void afs_upload_to_server_worker(struct work_struct *work) { - struct afs_vnode *vnode = AFS_FS_I(mapping->host); - struct iov_iter iter; - unsigned long long i_size = i_size_read(&vnode->netfs.inode); - size_t len, max_len; - bool caching = fscache_cookie_enabled(afs_vnode_cache(vnode)); - long count = wbc->nr_to_write; - int ret; - - _enter(",%lx,%llx-%llx", folio_index(folio), start, end); - - folio_start_writeback(folio); - afs_folio_start_fscache(caching, folio); - - count -= folio_nr_pages(folio); - - /* Find all consecutive lockable dirty pages that have contiguous - * written regions, stopping when we find a page that is not - * immediately lockable, is not dirty or is missing, or we reach the - * end of the range. - */ - trace_afs_folio_dirty(vnode, tracepoint_string("store"), folio); - - len = folio_size(folio); - if (start < i_size) { - /* Trim the write to the EOF; the extra data is ignored. Also - * put an upper limit on the size of a single storedata op. - */ - max_len = 65536 * 4096; - max_len = min_t(unsigned long long, max_len, end - start + 1); - max_len = min_t(unsigned long long, max_len, i_size - start); - - if (len < max_len) - afs_extend_writeback(mapping, vnode, &count, - start, max_len, caching, &len); - len = min_t(unsigned long long, len, i_size - start); - } - - /* We now have a contiguous set of dirty pages, each with writeback - * set; the first page is still locked at this point, but all the rest - * have been unlocked. - */ - folio_unlock(folio); - - if (start < i_size) { - _debug("write back %zx @%llx [%llx]", len, start, i_size); - - /* Speculatively write to the cache. We have to fix this up - * later if the store fails. - */ - afs_write_to_cache(vnode, start, len, i_size, caching); - - iov_iter_xarray(&iter, ITER_SOURCE, &mapping->i_pages, start, len); - ret = afs_store_data(vnode, &iter, start, false); - } else { - _debug("write discard %zx @%llx [%llx]", len, start, i_size); - - /* The dirty region was entirely beyond the EOF. */ - fscache_clear_page_bits(mapping, start, len, caching); - afs_pages_written_back(vnode, start, len); - ret = 0; - } - - switch (ret) { - case 0: - wbc->nr_to_write = count; - ret = len; - break; - - default: - pr_notice("kAFS: Unexpected error from FS.StoreData %d\n", ret); - fallthrough; - case -EACCES: - case -EPERM: - case -ENOKEY: - case -EKEYEXPIRED: - case -EKEYREJECTED: - case -EKEYREVOKED: - case -ENETRESET: - afs_redirty_pages(wbc, mapping, start, len); - mapping_set_error(mapping, ret); - break; - - case -EDQUOT: - case -ENOSPC: - afs_redirty_pages(wbc, mapping, start, len); - mapping_set_error(mapping, -ENOSPC); - break; - - case -EROFS: - case -EIO: - case -EREMOTEIO: - case -EFBIG: - case -ENOENT: - case -ENOMEDIUM: - case -ENXIO: - trace_afs_file_error(vnode, ret, afs_file_error_writeback_fail); - afs_kill_pages(mapping, start, len); - mapping_set_error(mapping, ret); - break; - } + struct netfs_io_subrequest *subreq = + container_of(work, struct netfs_io_subrequest, work); - _leave(" = %d", ret); - return ret; + afs_upload_to_server(subreq); } /* - * write a region of pages back to the server + * Set up write requests for a writeback slice. We need to add a write request + * for each write we want to make. */ -static int afs_writepages_region(struct address_space *mapping, - struct writeback_control *wbc, - unsigned long long start, - unsigned long long end, loff_t *_next, - bool max_one_loop) +void afs_create_write_requests(struct netfs_io_request *wreq, loff_t start, size_t len) { - struct folio *folio; - struct folio_batch fbatch; - ssize_t ret; - unsigned int i; - int n, skips = 0; - - _enter("%llx,%llx,", start, end); - folio_batch_init(&fbatch); + struct netfs_io_subrequest *subreq; - do { - pgoff_t index = start / PAGE_SIZE; + _enter("%x,%llx-%llx", wreq->debug_id, start, start + len); - n = filemap_get_folios_tag(mapping, &index, end / PAGE_SIZE, - PAGECACHE_TAG_DIRTY, &fbatch); - - if (!n) - break; - for (i = 0; i < n; i++) { - folio = fbatch.folios[i]; - start = folio_pos(folio); /* May regress with THPs */ - - _debug("wback %lx", folio_index(folio)); - - /* At this point we hold neither the i_pages lock nor the - * page lock: the page may be truncated or invalidated - * (changing page->mapping to NULL), or even swizzled - * back from swapper_space to tmpfs file mapping - */ -try_again: - if (wbc->sync_mode != WB_SYNC_NONE) { - ret = folio_lock_killable(folio); - if (ret < 0) { - folio_batch_release(&fbatch); - return ret; - } - } else { - if (!folio_trylock(folio)) - continue; - } - - if (folio->mapping != mapping || - !folio_test_dirty(folio)) { - start += folio_size(folio); - folio_unlock(folio); - continue; - } - - if (folio_test_writeback(folio) || - folio_test_fscache(folio)) { - folio_unlock(folio); - if (wbc->sync_mode != WB_SYNC_NONE) { - folio_wait_writeback(folio); -#ifdef CONFIG_AFS_FSCACHE - folio_wait_fscache(folio); -#endif - goto try_again; - } - - start += folio_size(folio); - if (wbc->sync_mode == WB_SYNC_NONE) { - if (skips >= 5 || need_resched()) { - *_next = start; - folio_batch_release(&fbatch); - _leave(" = 0 [%llx]", *_next); - return 0; - } - skips++; - } - continue; - } - - if (!folio_clear_dirty_for_io(folio)) - BUG(); - ret = afs_write_back_from_locked_folio(mapping, wbc, - folio, start, end); - if (ret < 0) { - _leave(" = %zd", ret); - folio_batch_release(&fbatch); - return ret; - } - - start += ret; - } - - folio_batch_release(&fbatch); - cond_resched(); - } while (wbc->nr_to_write > 0); - - *_next = start; - _leave(" = 0 [%llx]", *_next); - return 0; + subreq = netfs_create_write_request(wreq, NETFS_UPLOAD_TO_SERVER, + start, len, afs_upload_to_server_worker); + if (subreq) + netfs_queue_write_request(subreq); } /* * write some of the pending data back to the server */ -int afs_writepages(struct address_space *mapping, - struct writeback_control *wbc) +int afs_writepages(struct address_space *mapping, struct writeback_control *wbc) { struct afs_vnode *vnode = AFS_FS_I(mapping->host); - loff_t start, next; int ret; - _enter(""); - /* We have to be careful as we can end up racing with setattr() * truncating the pagecache since the caller doesn't take a lock here * to prevent it. @@ -710,68 +215,11 @@ int afs_writepages(struct address_space *mapping, else if (!down_read_trylock(&vnode->validate_lock)) return 0; - if (wbc->range_cyclic) { - start = mapping->writeback_index * PAGE_SIZE; - ret = afs_writepages_region(mapping, wbc, start, LLONG_MAX, - &next, false); - if (ret == 0) { - mapping->writeback_index = next / PAGE_SIZE; - if (start > 0 && wbc->nr_to_write > 0) { - ret = afs_writepages_region(mapping, wbc, 0, - start, &next, false); - if (ret == 0) - mapping->writeback_index = - next / PAGE_SIZE; - } - } - } else if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) { - ret = afs_writepages_region(mapping, wbc, 0, LLONG_MAX, - &next, false); - if (wbc->nr_to_write > 0 && ret == 0) - mapping->writeback_index = next / PAGE_SIZE; - } else { - ret = afs_writepages_region(mapping, wbc, - wbc->range_start, wbc->range_end, - &next, false); - } - + ret = netfs_writepages(mapping, wbc); up_read(&vnode->validate_lock); - _leave(" = %d", ret); return ret; } -/* - * write to an AFS file - */ -ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from) -{ - struct afs_vnode *vnode = AFS_FS_I(file_inode(iocb->ki_filp)); - struct afs_file *af = iocb->ki_filp->private_data; - ssize_t result; - size_t count = iov_iter_count(from); - - _enter("{%llx:%llu},{%zu},", - vnode->fid.vid, vnode->fid.vnode, count); - - if (IS_SWAPFILE(&vnode->netfs.inode)) { - printk(KERN_INFO - "AFS: Attempt to write to active swap file!\n"); - return -EBUSY; - } - - if (!count) - return 0; - - result = afs_validate(vnode, af->key); - if (result < 0) - return result; - - result = generic_file_write_iter(iocb, from); - - _leave(" = %zd", result); - return result; -} - /* * flush any dirty pages for this process, and check for write errors. * - the return status from this call provides a reliable indication of @@ -800,49 +248,11 @@ int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync) */ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf) { - struct folio *folio = page_folio(vmf->page); struct file *file = vmf->vma->vm_file; - struct inode *inode = file_inode(file); - struct afs_vnode *vnode = AFS_FS_I(inode); - struct afs_file *af = file->private_data; - vm_fault_t ret = VM_FAULT_RETRY; - - _enter("{{%llx:%llu}},{%lx}", vnode->fid.vid, vnode->fid.vnode, folio_index(folio)); - - afs_validate(vnode, af->key); - - sb_start_pagefault(inode->i_sb); - - /* Wait for the page to be written to the cache before we allow it to - * be modified. We then assume the entire page will need writing back. - */ -#ifdef CONFIG_AFS_FSCACHE - if (folio_test_fscache(folio) && - folio_wait_fscache_killable(folio) < 0) - goto out; -#endif - - if (folio_wait_writeback_killable(folio)) - goto out; - - if (folio_lock_killable(folio) < 0) - goto out; - - if (folio_wait_writeback_killable(folio) < 0) { - folio_unlock(folio); - goto out; - } - - if (folio_test_dirty(folio)) - trace_afs_folio_dirty(vnode, tracepoint_string("mkwrite+"), folio); - else - trace_afs_folio_dirty(vnode, tracepoint_string("mkwrite"), folio); - file_update_time(file); - ret = VM_FAULT_LOCKED; -out: - sb_end_pagefault(inode->i_sb); - return ret; + if (afs_validate(AFS_FS_I(file_inode(file)), afs_file_key(file)) < 0) + return VM_FAULT_SIGBUS; + return netfs_page_mkwrite(vmf, NULL); } /* @@ -872,60 +282,3 @@ void afs_prune_wb_keys(struct afs_vnode *vnode) afs_put_wb_key(wbk); } } - -/* - * Clean up a page during invalidation. - */ -int afs_launder_folio(struct folio *folio) -{ - struct afs_vnode *vnode = AFS_FS_I(folio_inode(folio)); - struct iov_iter iter; - struct bio_vec bv; - unsigned long long fend, i_size = vnode->netfs.inode.i_size; - size_t len; - int ret = 0; - - _enter("{%lx}", folio->index); - - if (folio_clear_dirty_for_io(folio) && folio_pos(folio) < i_size) { - len = folio_size(folio); - fend = folio_pos(folio) + len; - if (vnode->netfs.inode.i_size < fend) - len = fend - i_size; - - bvec_set_folio(&bv, folio, len, 0); - iov_iter_bvec(&iter, WRITE, &bv, 1, len); - - trace_afs_folio_dirty(vnode, tracepoint_string("launder"), folio); - ret = afs_store_data(vnode, &iter, folio_pos(folio), true); - } - - trace_afs_folio_dirty(vnode, tracepoint_string("laundered"), folio); - folio_wait_fscache(folio); - return ret; -} - -/* - * Deal with the completion of writing the data to the cache. - */ -static void afs_write_to_cache_done(void *priv, ssize_t transferred_or_error, - bool was_async) -{ - struct afs_vnode *vnode = priv; - - if (IS_ERR_VALUE(transferred_or_error) && - transferred_or_error != -ENOBUFS) - afs_invalidate_cache(vnode, 0); -} - -/* - * Save the write to the cache also. - */ -static void afs_write_to_cache(struct afs_vnode *vnode, - loff_t start, size_t len, loff_t i_size, - bool caching) -{ - fscache_write_to_cache(afs_vnode_cache(vnode), - vnode->netfs.inode.i_mapping, start, len, i_size, - afs_write_to_cache_done, vnode, caching); -} diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index 7780bd716ce0..8d73171cb9f0 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -902,29 +902,6 @@ TRACE_EVENT(afs_dir_check_failed, __entry->vnode, __entry->off, __entry->i_size) ); -TRACE_EVENT(afs_folio_dirty, - TP_PROTO(struct afs_vnode *vnode, const char *where, struct folio *folio), - - TP_ARGS(vnode, where, folio), - - TP_STRUCT__entry( - __field(struct afs_vnode *, vnode) - __field(const char *, where) - __field(pgoff_t, index) - __field(size_t, size) - ), - - TP_fast_assign( - __entry->vnode = vnode; - __entry->where = where; - __entry->index = folio_index(folio); - __entry->size = folio_size(folio); - ), - - TP_printk("vn=%p ix=%05lx s=%05lx %s", - __entry->vnode, __entry->index, __entry->size, __entry->where) - ); - TRACE_EVENT(afs_call_state, TP_PROTO(struct afs_call *call, enum afs_call_state from, From patchwork Wed Dec 13 15:23:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13491245 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id D60A0C4332F for ; Wed, 13 Dec 2023 15:27:03 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 644866B0420; Wed, 13 Dec 2023 10:27:03 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 5CE2E6B041D; Wed, 13 Dec 2023 10:27:03 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 4494C6B0420; Wed, 13 Dec 2023 10:27:03 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id 2C60A6B041C for ; Wed, 13 Dec 2023 10:27:03 -0500 (EST) Received: from smtpin20.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id 05A8DA20C3 for ; Wed, 13 Dec 2023 15:27:03 +0000 (UTC) X-FDA: 81562173126.20.AD84E12 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf25.hostedemail.com (Postfix) with ESMTP id 4BC60A001E for ; Wed, 13 Dec 2023 15:27:00 +0000 (UTC) Authentication-Results: imf25.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=YJFWcyxK; spf=pass (imf25.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1702481220; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=WXofuzcjAytVfATApIF5KG+Rehuwn0Pqcyfgmz8Uu6Q=; b=QV/NxYwNndWrzWhBdbJCaT2qKsvJVkpCKVTxZ5vgd28EmCQIrbPh5KnboiF+SAZOyHThkg GLZJA21NF1pXB5iyqXoHgMW08qO3ltdEBw6FSt7GyeXdk6s1J/xFEAXUHARFyFaLuu5Jqy 8wLnNBUkr5IzPwVHKPR8QE4oI1wFkjU= ARC-Authentication-Results: i=1; imf25.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=YJFWcyxK; spf=pass (imf25.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702481220; a=rsa-sha256; cv=none; b=Ks60Z217SQijJOhMQPNJgJWk+GRi4PTm2RAWJeL9NQbpidt+xZ8U6pfTVLxlAlE8XoCDPe Z46QA5pCOhMwUM+gCz3u3OQo1l2iwoTh2WrENONxz2rMjMJtswf6tQdGXfvRJKU28gGPFe VPjolFz1JMWpb8WB1azgmfU+it/B2Ow= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702481219; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WXofuzcjAytVfATApIF5KG+Rehuwn0Pqcyfgmz8Uu6Q=; b=YJFWcyxKiuEkPnKmwo44E8aoEavo5rk2R7Iyd0DG0LNPvzfphtbsY7AY9HQS7aX5dMaZp9 kMBWhhjurC+cmxyxELAErmAq4BWqHoHiO3VwZCIU0u9IhuH1Qu4pfldeM2qXBcUyDncSuM 325WyUzq1ikUdnutm8n/FkkOv+a6qhA= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-228-8_MjFYBWMP6LtGm0-uBNEQ-1; Wed, 13 Dec 2023 10:26:54 -0500 X-MC-Unique: 8_MjFYBWMP6LtGm0-uBNEQ-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id BE62A185A78E; Wed, 13 Dec 2023 15:26:52 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id F1FA351E3; Wed, 13 Dec 2023 15:26:48 +0000 (UTC) From: David Howells To: Jeff Layton , Steve French Cc: David Howells , Matthew Wilcox , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Dominique Martinet , Eric Van Hensbergen , Ilya Dryomov , Christian Brauner , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Latchesar Ionkov , Christian Schoenebeck Subject: [PATCH v4 39/39] 9p: Use netfslib read/write_iter Date: Wed, 13 Dec 2023 15:23:49 +0000 Message-ID: <20231213152350.431591-40-dhowells@redhat.com> In-Reply-To: <20231213152350.431591-1-dhowells@redhat.com> References: <20231213152350.431591-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.5 X-Rspamd-Queue-Id: 4BC60A001E X-Rspam-User: X-Stat-Signature: gpwmiwnafsw4rc8twwjqoh9t838gxiw7 X-Rspamd-Server: rspam01 X-HE-Tag: 1702481220-734486 X-HE-Meta: U2FsdGVkX18YE4BuGxPnU6uA9GVi5kMj0F0+NNdS5OMpVdZ8qneowgfrMa3NRbnibHIXC1IdyQllrarew94uEUUSadkVZBDLdwO0bHd7gZ7H5Lrr+P509YlV+my5mR8W6cjVqjHPrSo/zbmqoTkFiMr4nN/WDaLEOj2D2XhJSHmpzo08/A9Zh9u/pwjdE18OXedEXWzNXpVl422wgF7BI0XOvAZlLfmcjT+orRw1clO4BjaUTyXHVeNMRkU8Fw/g9GBjo94q4HEP3tEGI+YVvJPrjchM0RrPnn2VBlc7USwfOr8wvYPDdLcpVkl9/2K89aCgWBTi97z3fBEr2Ua1u2zqq/hcsY5HILNnamHNKbIccq7gaoAyQyycLqb2YGQnN6lqRaHFIMaXuUzrpcmavAPn4kTbaTGWmnUwXl8J0ZYmCsdCfEm296IgzU1zN+iJU4k+AouB0kQgv0QdgUUnPZW5plu6Spc0uT73BCsv91gyB1N4/X3HskNRya1Mx2INOcgZoMaJhYDTEkIzw9UR7H36p58EvCfW0DmLp96iHcQEWaimTTUCq0hio0Vo8NZrTanfT4++514clkpX9l8YC39kLE7rHGzX9aO6z3v8SN86h9ffttVcMuYoUMfgfQSZsJH9q31pWOqhSFNJ9VGPzj9QZDfI38AzzsQxPQ1kRdLQ4evTu/ptA33P5TIuhFj6GclLG+558BuR5kfMH64TQy1cLeBx71br3T/2uJGYWrGtu61saddPjYlXb+9plg+umNF+ZQXl5bvaa/AU+FkvkpbGWXFKdEXF4YwdDO4pJPqz8UXq/vvT5p1Y2zF+fA0zYfGMW4l1tIeN3f068PD+HHuj5zYv3NZxJgW3zYezSxtTdHMFWqh8GoHmPwt64gMvmdVfnfQHYgEx6E1JY4EtaFh6fBAT81LLa+XbWHtQmCCt7NVDSnebkU5Fy8Z6RV+BFKV1yqr6YTFgRKMaJRt Kq7cDqVL 0HsJ29as9TPtKHYqAYjVE0C4B/g6wiUGQD88XLZFhEhrV30O2XbW8cE2FcxnbPkZhP3iTxabizjQmPkQenBe2sssmqx0cDG7a9pslsX2iYIlDvFkUMipIX6iTW9FWIM+Ta1kllUyVzjwRqLmGxLBy8wjay0OAlAqGs7Swp3Lc69F6CN+t1a/cN5/qDzLMdad+ctZhi+o70ROjsay2/1hnJPmVweJFfw5tK7SlNpZVsDCqrGoFoG8kMJzV53V/Lz3GX6JPDb40wQm8RV7lftUJ4V6XZvA8YDSIPnNLxvN3YgTFPRsIDp3DW590fXO0Qs7OmhD92Xzcn/GsqyhlYx1+h21JbthDy5y2GmiZkNuPPmyE+82SQTYicjRtv4leWdH7IRO6BvDbagWBqAPZjN905IoS5bJNmPu1O5KsBYmc1z93pVsWUttiWLY1jlurPO/bXBWmET/wf3KzYHE= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Use netfslib's read and write iteration helpers, allowing netfslib to take over the management of the page cache for 9p files and to manage local disk caching. In particular, this eliminates write_begin, write_end, writepage and all mentions of struct page and struct folio from 9p. Note that netfslib now offers the possibility of write-through caching if that is desirable for 9p: just set the NETFS_ICTX_WRITETHROUGH flag in v9inode->netfs.flags in v9fs_set_netfs_context(). Note also this is untested as I can't get ganesha.nfsd to correctly parse the config to turn on 9p support. Signed-off-by: David Howells cc: Eric Van Hensbergen cc: Latchesar Ionkov cc: Dominique Martinet cc: Christian Schoenebeck cc: v9fs@lists.linux.dev cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org --- fs/9p/vfs_addr.c | 292 +++++++++++----------------------------------- fs/9p/vfs_file.c | 89 ++------------ fs/9p/vfs_inode.c | 2 - 3 files changed, 77 insertions(+), 306 deletions(-) diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 055b672a247d..0c7bcff05da2 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -19,12 +19,48 @@ #include #include #include +#include #include "v9fs.h" #include "v9fs_vfs.h" #include "cache.h" #include "fid.h" +static void v9fs_upload_to_server(struct netfs_io_subrequest *subreq) +{ + struct inode *inode = subreq->rreq->inode; + struct v9fs_inode __maybe_unused *v9inode = V9FS_I(inode); + struct p9_fid *fid = subreq->rreq->netfs_priv; + int err; + + trace_netfs_sreq(subreq, netfs_sreq_trace_submit); + p9_client_write(fid, subreq->start, &subreq->io_iter, &err); + netfs_write_subrequest_terminated(subreq, err < 0 ? err : subreq->len, + false); +} + +static void v9fs_upload_to_server_worker(struct work_struct *work) +{ + struct netfs_io_subrequest *subreq = + container_of(work, struct netfs_io_subrequest, work); + + v9fs_upload_to_server(subreq); +} + +/* + * Set up write requests for a writeback slice. We need to add a write request + * for each write we want to make. + */ +static void v9fs_create_write_requests(struct netfs_io_request *wreq, loff_t start, size_t len) +{ + struct netfs_io_subrequest *subreq; + + subreq = netfs_create_write_request(wreq, NETFS_UPLOAD_TO_SERVER, + start, len, v9fs_upload_to_server_worker); + if (subreq) + netfs_queue_write_request(subreq); +} + /** * v9fs_issue_read - Issue a read from 9P * @subreq: The read to make @@ -33,14 +69,10 @@ static void v9fs_issue_read(struct netfs_io_subrequest *subreq) { struct netfs_io_request *rreq = subreq->rreq; struct p9_fid *fid = rreq->netfs_priv; - struct iov_iter to; - loff_t pos = subreq->start + subreq->transferred; - size_t len = subreq->len - subreq->transferred; int total, err; - iov_iter_xarray(&to, ITER_DEST, &rreq->mapping->i_pages, pos, len); - - total = p9_client_read(fid, pos, &to, &err); + total = p9_client_read(fid, subreq->start + subreq->transferred, + &subreq->io_iter, &err); /* if we just extended the file size, any portion not in * cache won't be on server and is zeroes */ @@ -50,23 +82,37 @@ static void v9fs_issue_read(struct netfs_io_subrequest *subreq) } /** - * v9fs_init_request - Initialise a read request + * v9fs_init_request - Initialise a request * @rreq: The read request * @file: The file being read from */ static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file) { - struct p9_fid *fid = file->private_data; - - BUG_ON(!fid); + struct p9_fid *fid; + bool writing = (rreq->origin == NETFS_READ_FOR_WRITE || + rreq->origin == NETFS_WRITEBACK || + rreq->origin == NETFS_WRITETHROUGH || + rreq->origin == NETFS_LAUNDER_WRITE || + rreq->origin == NETFS_UNBUFFERED_WRITE || + rreq->origin == NETFS_DIO_WRITE); + + if (file) { + fid = file->private_data; + BUG_ON(!fid); + p9_fid_get(fid); + } else { + fid = v9fs_fid_find_inode(rreq->inode, writing, INVALID_UID, true); + if (!fid) { + WARN_ONCE(1, "folio expected an open fid inode->i_private=%p\n", + rreq->inode->i_private); + return -EINVAL; + } + } /* we might need to read from a fid that was opened write-only * for read-modify-write of page cache, use the writeback fid * for that */ - WARN_ON(rreq->origin == NETFS_READ_FOR_WRITE && - !(fid->mode & P9_ORDWR)); - - p9_fid_get(fid); + WARN_ON(writing && !(fid->mode & P9_ORDWR)); rreq->netfs_priv = fid; return 0; } @@ -86,217 +132,15 @@ const struct netfs_request_ops v9fs_req_ops = { .init_request = v9fs_init_request, .free_request = v9fs_free_request, .issue_read = v9fs_issue_read, + .create_write_requests = v9fs_create_write_requests, }; -#ifdef CONFIG_9P_FSCACHE -static void v9fs_write_to_cache_done(void *priv, ssize_t transferred_or_error, - bool was_async) -{ - struct v9fs_inode *v9inode = priv; - __le32 version; - - if (IS_ERR_VALUE(transferred_or_error) && - transferred_or_error != -ENOBUFS) { - version = cpu_to_le32(v9inode->qid.version); - fscache_invalidate(v9fs_inode_cookie(v9inode), &version, - i_size_read(&v9inode->netfs.inode), 0); - } -} -#endif - -static int v9fs_vfs_write_folio_locked(struct folio *folio) -{ - struct inode *inode = folio_inode(folio); - loff_t start = folio_pos(folio); - loff_t i_size = i_size_read(inode); - struct iov_iter from; - size_t len = folio_size(folio); - struct p9_fid *writeback_fid; - int err; - struct v9fs_inode __maybe_unused *v9inode = V9FS_I(inode); - struct fscache_cookie __maybe_unused *cookie = v9fs_inode_cookie(v9inode); - - if (start >= i_size) - return 0; /* Simultaneous truncation occurred */ - - len = min_t(loff_t, i_size - start, len); - - iov_iter_xarray(&from, ITER_SOURCE, &folio_mapping(folio)->i_pages, start, len); - - writeback_fid = v9fs_fid_find_inode(inode, true, INVALID_UID, true); - if (!writeback_fid) { - WARN_ONCE(1, "folio expected an open fid inode->i_private=%p\n", - inode->i_private); - return -EINVAL; - } - - folio_wait_fscache(folio); - folio_start_writeback(folio); - - p9_client_write(writeback_fid, start, &from, &err); - -#ifdef CONFIG_9P_FSCACHE - if (err == 0 && - fscache_cookie_enabled(cookie) && - test_bit(FSCACHE_COOKIE_IS_CACHING, &cookie->flags)) { - folio_start_fscache(folio); - fscache_write_to_cache(v9fs_inode_cookie(v9inode), - folio_mapping(folio), start, len, i_size, - v9fs_write_to_cache_done, v9inode, - true); - } -#endif - - folio_end_writeback(folio); - p9_fid_put(writeback_fid); - - return err; -} - -static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc) -{ - struct folio *folio = page_folio(page); - int retval; - - p9_debug(P9_DEBUG_VFS, "folio %p\n", folio); - - retval = v9fs_vfs_write_folio_locked(folio); - if (retval < 0) { - if (retval == -EAGAIN) { - folio_redirty_for_writepage(wbc, folio); - retval = 0; - } else { - mapping_set_error(folio_mapping(folio), retval); - } - } else - retval = 0; - - folio_unlock(folio); - return retval; -} - -static int v9fs_launder_folio(struct folio *folio) -{ - int retval; - - if (folio_clear_dirty_for_io(folio)) { - retval = v9fs_vfs_write_folio_locked(folio); - if (retval) - return retval; - } - folio_wait_fscache(folio); - return 0; -} - -/** - * v9fs_direct_IO - 9P address space operation for direct I/O - * @iocb: target I/O control block - * @iter: The data/buffer to use - * - * The presence of v9fs_direct_IO() in the address space ops vector - * allowes open() O_DIRECT flags which would have failed otherwise. - * - * In the non-cached mode, we shunt off direct read and write requests before - * the VFS gets them, so this method should never be called. - * - * Direct IO is not 'yet' supported in the cached mode. Hence when - * this routine is called through generic_file_aio_read(), the read/write fails - * with an error. - * - */ -static ssize_t -v9fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) -{ - struct file *file = iocb->ki_filp; - loff_t pos = iocb->ki_pos; - ssize_t n; - int err = 0; - - if (iov_iter_rw(iter) == WRITE) { - n = p9_client_write(file->private_data, pos, iter, &err); - if (n) { - struct inode *inode = file_inode(file); - loff_t i_size = i_size_read(inode); - - if (pos + n > i_size) - inode_add_bytes(inode, pos + n - i_size); - } - } else { - n = p9_client_read(file->private_data, pos, iter, &err); - } - return n ? n : err; -} - -static int v9fs_write_begin(struct file *filp, struct address_space *mapping, - loff_t pos, unsigned int len, - struct page **subpagep, void **fsdata) -{ - int retval; - struct folio *folio; - struct v9fs_inode *v9inode = V9FS_I(mapping->host); - - p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping); - - /* Prefetch area to be written into the cache if we're caching this - * 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 = netfs_write_begin(&v9inode->netfs, filp, mapping, pos, len, &folio, fsdata); - if (retval < 0) - return retval; - - *subpagep = &folio->page; - return retval; -} - -static int v9fs_write_end(struct file *filp, struct address_space *mapping, - loff_t pos, unsigned int len, unsigned int copied, - struct page *subpage, void *fsdata) -{ - loff_t last_pos = pos + copied; - struct folio *folio = page_folio(subpage); - struct inode *inode = mapping->host; - - p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping); - - if (!folio_test_uptodate(folio)) { - if (unlikely(copied < len)) { - copied = 0; - goto out; - } - - folio_mark_uptodate(folio); - } - - /* - * No need to use i_size_read() here, the i_size - * cannot change under us because we hold the i_mutex. - */ - if (last_pos > inode->i_size) { - inode_add_bytes(inode, last_pos - inode->i_size); - i_size_write(inode, last_pos); -#ifdef CONFIG_9P_FSCACHE - fscache_update_cookie(v9fs_inode_cookie(V9FS_I(inode)), NULL, - &last_pos); -#endif - } - folio_mark_dirty(folio); -out: - folio_unlock(folio); - folio_put(folio); - - return copied; -} - const struct address_space_operations v9fs_addr_operations = { - .read_folio = netfs_read_folio, - .readahead = netfs_readahead, - .dirty_folio = netfs_dirty_folio, - .writepage = v9fs_vfs_writepage, - .write_begin = v9fs_write_begin, - .write_end = v9fs_write_end, - .release_folio = netfs_release_folio, - .invalidate_folio = netfs_invalidate_folio, - .launder_folio = v9fs_launder_folio, - .direct_IO = v9fs_direct_IO, + .read_folio = netfs_read_folio, + .readahead = netfs_readahead, + .dirty_folio = netfs_dirty_folio, + .release_folio = netfs_release_folio, + .invalidate_folio = netfs_invalidate_folio, + .launder_folio = netfs_launder_folio, + .direct_IO = noop_direct_IO, }; diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 11cd8d23f6f2..bae330c2f0cf 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -353,25 +353,15 @@ static ssize_t v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct p9_fid *fid = iocb->ki_filp->private_data; - int ret, err = 0; p9_debug(P9_DEBUG_VFS, "fid %d count %zu offset %lld\n", fid->fid, iov_iter_count(to), iocb->ki_pos); - if (!(fid->mode & P9L_DIRECT)) { - p9_debug(P9_DEBUG_VFS, "(cached)\n"); - return generic_file_read_iter(iocb, to); - } - - if (iocb->ki_filp->f_flags & O_NONBLOCK) - ret = p9_client_read_once(fid, iocb->ki_pos, to, &err); - else - ret = p9_client_read(fid, iocb->ki_pos, to, &err); - if (!ret) - return err; + if (fid->mode & P9L_DIRECT) + return netfs_unbuffered_read_iter(iocb, to); - iocb->ki_pos += ret; - return ret; + p9_debug(P9_DEBUG_VFS, "(cached)\n"); + return netfs_file_read_iter(iocb, to); } /* @@ -407,46 +397,14 @@ v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct p9_fid *fid = file->private_data; - ssize_t retval; - loff_t origin; - int err = 0; p9_debug(P9_DEBUG_VFS, "fid %d\n", fid->fid); - if (!(fid->mode & (P9L_DIRECT | P9L_NOWRITECACHE))) { - p9_debug(P9_DEBUG_CACHE, "(cached)\n"); - return generic_file_write_iter(iocb, from); - } + if (fid->mode & (P9L_DIRECT | P9L_NOWRITECACHE)) + return netfs_unbuffered_write_iter(iocb, from); - retval = generic_write_checks(iocb, from); - if (retval <= 0) - return retval; - - origin = iocb->ki_pos; - retval = p9_client_write(file->private_data, iocb->ki_pos, from, &err); - if (retval > 0) { - struct inode *inode = file_inode(file); - loff_t i_size; - unsigned long pg_start, pg_end; - - pg_start = origin >> PAGE_SHIFT; - pg_end = (origin + retval - 1) >> PAGE_SHIFT; - if (inode->i_mapping && inode->i_mapping->nrpages) - invalidate_inode_pages2_range(inode->i_mapping, - pg_start, pg_end); - iocb->ki_pos += retval; - i_size = i_size_read(inode); - if (iocb->ki_pos > i_size) { - inode_add_bytes(inode, iocb->ki_pos - i_size); - /* - * Need to serialize against i_size_write() in - * v9fs_stat2inode() - */ - v9fs_i_size_write(inode, iocb->ki_pos); - } - return retval; - } - return err; + p9_debug(P9_DEBUG_CACHE, "(cached)\n"); + return netfs_file_write_iter(iocb, from); } static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end, @@ -519,36 +477,7 @@ v9fs_file_mmap(struct file *filp, struct vm_area_struct *vma) static vm_fault_t v9fs_vm_page_mkwrite(struct vm_fault *vmf) { - struct folio *folio = page_folio(vmf->page); - struct file *filp = vmf->vma->vm_file; - struct inode *inode = file_inode(filp); - - - p9_debug(P9_DEBUG_VFS, "folio %p fid %lx\n", - folio, (unsigned long)filp->private_data); - - /* Wait for the page to be written to the cache before we allow it to - * be modified. We then assume the entire page will need writing back. - */ -#ifdef CONFIG_9P_FSCACHE - if (folio_test_fscache(folio) && - folio_wait_fscache_killable(folio) < 0) - return VM_FAULT_NOPAGE; -#endif - - /* Update file times before taking page lock */ - file_update_time(filp); - - if (folio_lock_killable(folio) < 0) - return VM_FAULT_RETRY; - if (folio_mapping(folio) != inode->i_mapping) - goto out_unlock; - folio_wait_stable(folio); - - return VM_FAULT_LOCKED; -out_unlock: - folio_unlock(folio); - return VM_FAULT_NOPAGE; + return netfs_page_mkwrite(vmf, NULL); } static void v9fs_mmap_vm_close(struct vm_area_struct *vma) diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 74122540e00f..1c3f931914c0 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -374,10 +374,8 @@ void v9fs_evict_inode(struct inode *inode) truncate_inode_pages_final(&inode->i_data); -#ifdef CONFIG_9P_FSCACHE version = cpu_to_le32(v9inode->qid.version); netfs_clear_inode_writeback(inode, &version); -#endif clear_inode(inode); filemap_fdatawrite(&inode->i_data);