From patchwork Fri Oct 13 16:03: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: 13421161 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 DDB4DCDB483 for ; Fri, 13 Oct 2023 16:05:53 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 58C606B029B; Fri, 13 Oct 2023 12:05:41 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 4ED0F6B029D; Fri, 13 Oct 2023 12:05:41 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 367816B029C; Fri, 13 Oct 2023 12:05:41 -0400 (EDT) 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 228C66B029A for ; Fri, 13 Oct 2023 12:05:41 -0400 (EDT) Received: from smtpin08.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id DAE5D1CA954 for ; Fri, 13 Oct 2023 16:05:40 +0000 (UTC) X-FDA: 81340913640.08.795316E Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf04.hostedemail.com (Postfix) with ESMTP id A886240020 for ; Fri, 13 Oct 2023 16:05:38 +0000 (UTC) Authentication-Results: imf04.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=CL1fsf+0; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf04.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=1697213138; 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=eZnc3j734khDGwXznc6wh2xPv7mSRAABdKA6EQBsCg4=; b=qGbWOfKJTeIg3mjLD+8x5MmJHzzLENhOapPa7n/M3BVrgI0ksUNLOK1urqw19LPU+X7kH9 nN0VHUBPB9YC5IiJ1lnZ0kPrxh0x0Cgo6D8Lda0KJDWdzr4XQ5XBy6B7AnL0n4nAgt4Kx5 Q+jggloATIp258HCQnSmSdiDHtc52lM= ARC-Authentication-Results: i=1; imf04.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=CL1fsf+0; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf04.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=1697213138; a=rsa-sha256; cv=none; b=5DBk+3EDb3or+JSTTYpC7XUjtlPVHh+1UMPju3lyQLUcIOx8tZRkTn14RyG6X3NUhDi3rO Z0AwKw6wN04w9ohJDEjWkgR0NAWgJFA4p3z40Wk9GQOWRLZS98V6cIrOF/zRLNW3pFZwUe tFXoXoQgbjAjzyDG2JIFBgty7oVEVH4= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1697213138; 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=eZnc3j734khDGwXznc6wh2xPv7mSRAABdKA6EQBsCg4=; b=CL1fsf+0FeAqna15xvLLLYQPuCo0G8tYoVARAULjBfWFE6pJojwI914bdNhIIpN96X/fr6 aMwJCZ+R+6b8uBOcx3ELmENB2sLWCCXx1OTwwNE7QTLTwUIWruWzc2+8sfbAFHlFpfxjah Xp1x91bfXJeh37/DUUVTmqsoSOXlV3U= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-319-Jzb0pISoMpSdZfj-hqrYxg-1; Fri, 13 Oct 2023 12:05:24 -0400 X-MC-Unique: Jzb0pISoMpSdZfj-hqrYxg-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id BC5CF1C113E2; Fri, 13 Oct 2023 16:05:23 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.42.28.226]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3BDEFC15BBC; Fri, 13 Oct 2023 16:05: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 , Ilya Dryomov , Christian Brauner , 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, linux-cachefs@redhat.com Subject: [RFC PATCH 17/53] netfs: Extend the netfs_io_*request structs to handle writes Date: Fri, 13 Oct 2023 17:03:46 +0100 Message-ID: <20231013160423.2218093-18-dhowells@redhat.com> In-Reply-To: <20231013160423.2218093-1-dhowells@redhat.com> References: <20231013160423.2218093-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.8 X-Rspamd-Server: rspam09 X-Rspamd-Queue-Id: A886240020 X-Stat-Signature: mfdkbroti7xbre4h7ckk3awos4r8f3b9 X-Rspam-User: X-HE-Tag: 1697213138-375444 X-HE-Meta: U2FsdGVkX1+nWRhdfXmihhZOD4dmECFxIyuLSwYXoJLSHoIg/ztN0EeENja+vK7CuI/hzvBQQt5Tj6QRoqzsKWJXO1ybHQhE+PaKIMCuXbmKQrNJms9W+Y35klgKiP398kgaOfSHNmngu/mFaINgBS+8llLgEfiwxVPZtMYu7EYtsGu3ACOY0PCV115eyi+/LVC5mT1UOOTQeTtatoXtaBJAndpadbvoauptT53g6DVD5qKs7T0lqbC6e0zcr5J6ied7zA+RQstUQ8Q7I4wlwywOxu9jQZKCkLanAgLpTPO5rBOzGogO067xpiq+cs46Pof37gY3VJ9FUf5zQMfTYts9i/JaMZoK3NGVgza1J7nagDJjzYx4qVFDVkSPWHlKONvJciTd3THFcS5p7WKa5rYLSPQUVkPSEtl/bh86+yM3SuUyHA7zYEFHNXP5+XWy/9KnZRkehMGQeoQJR+oUWYrSp7U+j0diZsP/h63EeuumM4M/rjmOSp6R/DavEN6qYW1nTqbbVj+dKx/g+Kkf8RRTfjjgIJgOe+jyMp8badD3OhjDklcKg/5+7xIxZBWCtbpw9ikfA/45r/+swVcttnXt+Cyd6rkZOFDuLZbCTNeh74rHeplqgLn52IYQz/P00DOQmAEarHyvT/2SH/K1pUPRZy59dBrUcXY4I12mdbYmd4x74cEYMi9PtdFtVMVK9iEYLLJv4d8CqAbisc19cjFxvsGVJHhaHeYW48UqSBJU/kxk922OwFQeK/g5zP0OtbWKvB7scNtumIwiTD085SsjB2MQmeuSP2m/F/ojcFbup9mB/W9946r0YpHH+uAvVAsGYIggUN1xSgFzaqqrgJt1HW2+G4hNW0f0c+sqVjQhHFbT6F9JC4hPL88Vfv6YrUb6HNbM0TjHgafPUiJNludb3cahEBuGRKm0Nxmx1XU0/f3ZvNM9TNMgrWLmWXG6S5yyjlGNPjGK9KYpkFE 5eAdxn+3 OCGBzIXH22Sdl8xIYgRf2bBGlKesmGG9rmcIx+ckeQgV1FrXadXauwAhOS8tu+LlIQyPW6LLCCHr8GUY5UQuspSmZD1JHE7YjCk5bEBt5t5xUj+GSYhFmw5CdViz8DfgFEtcMQaI0bJp6IeYdBDrR9/MY/V7xA3Vb2h7cj7gbblEX5p14zJR0C3SDDB3+8V7skFkIdXqxXOrkRVu2uWDoOp9/zyZB4MY649quh5zqhbYVmgW1rYlbd8+xLLXFPh3CG96YGdiYNo28Ii4SBU6rbCEAEn0uG45Htp1vBuuXJPR4VIjPISVAjca5yr+ppqRRiILsxa08UwR7t62Qxo3iJdQzQA== 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: 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 | 18 ++++++++++++++---- include/linux/netfs.h | 15 ++++++++++++++- include/trace/events/netfs.h | 8 ++++++-- 6 files changed, 48 insertions(+), 8 deletions(-) diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 00e01278316f..46183dad4d50 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -109,6 +109,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; static inline void netfs_stat(atomic_t *stat) diff --git a/fs/netfs/main.c b/fs/netfs/main.c index 0f0c6e70aa44..e990738c2213 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 9b965a509e5a..30ec42566966 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 (file && file->f_flags & O_NONBLOCK) __set_bit(NETFS_RREQ_NONBLOCK, &rreq->flags); if (rreq->netfs_ops->init_request) { @@ -50,6 +54,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; @@ -134,6 +139,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 5510a7a14a40..ce2a1a983280 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; void netfs_stats_show(struct seq_file *m) { @@ -50,9 +56,13 @@ void netfs_stats_show(struct seq_file *m) 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", - atomic_read(&netfs_n_rh_write), - atomic_read(&netfs_n_rh_write_done), - atomic_read(&netfs_n_rh_write_failed)); + seq_printf(m, "WrHelp : 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, "WrHelp : WR=%u ws=%u wf=%u\n", + atomic_read(&netfs_n_wh_write), + atomic_read(&netfs_n_wh_write_done), + atomic_read(&netfs_n_wh_write_failed)); } EXPORT_SYMBOL(netfs_stats_show); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index aaf1c1d4de51..4115274e3129 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, @@ -151,9 +154,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 */ @@ -178,6 +186,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); /* @@ -202,6 +212,7 @@ struct netfs_io_request { unsigned int direct_bv_count; /* Number of elements in bv[] */ unsigned int debug_id; unsigned int rsize; /* Maximum read 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 */ @@ -223,6 +234,8 @@ struct netfs_io_request { #define NETFS_RREQ_NONBLOCK 6 /* Don't block if possible (O_NONBLOCK) */ #define NETFS_RREQ_BLOCKED 7 /* We blocked */ #define NETFS_RREQ_USE_BOUNCE_BUFFER 8 /* Use bounce buffer */ +#define NETFS_RREQ_WRITE_TO_CACHE 9 /* Need to write to the cache */ +#define NETFS_RREQ_UPLOAD_TO_SERVER 10 /* 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") \