Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2216351/?format=api
{ "id": 2216351, "url": "http://patchwork.ozlabs.org/api/patches/2216351/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260326104544.509518-11-dhowells@redhat.com/", "project": { "id": 12, "url": "http://patchwork.ozlabs.org/api/projects/12/?format=api", "name": "Linux CIFS Client", "link_name": "linux-cifs-client", "list_id": "linux-cifs.vger.kernel.org", "list_email": "linux-cifs@vger.kernel.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260326104544.509518-11-dhowells@redhat.com>", "list_archive_url": null, "date": "2026-03-26T10:45:25", "name": "[10/26] netfs: Bulk load the readahead-provided folios up front", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "dbf2e878ccb1f73bdede9f473b10872c2b316448", "submitter": { "id": 59, "url": "http://patchwork.ozlabs.org/api/people/59/?format=api", "name": "David Howells", "email": "dhowells@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260326104544.509518-11-dhowells@redhat.com/mbox/", "series": [ { "id": 497565, "url": "http://patchwork.ozlabs.org/api/series/497565/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/list/?series=497565", "date": "2026-03-26T10:45:15", "name": "netfs: Keep track of folios in a segmented bio_vec[] chain", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/497565/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2216351/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2216351/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <linux-cifs+bounces-10533-incoming=patchwork.ozlabs.org@vger.kernel.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "linux-cifs@vger.kernel.org" ], "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=E2WAlz0E;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org;\n envelope-from=linux-cifs+bounces-10533-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)", "smtp.subspace.kernel.org;\n\tdkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com\n header.b=\"E2WAlz0E\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=170.10.129.124", "smtp.subspace.kernel.org;\n dmarc=pass (p=quarantine dis=none) header.from=redhat.com", "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=redhat.com" ], "Received": [ "from tor.lore.kernel.org (tor.lore.kernel.org\n [IPv6:2600:3c04:e001:36c::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fhLR453YGz1yGD\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 26 Mar 2026 22:00:32 +1100 (AEDT)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id C609E3013B7A\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 26 Mar 2026 10:50:24 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 5ED89389E01;\n\tThu, 26 Mar 2026 10:47:44 +0000 (UTC)", "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 4FD90340293\n\tfor <linux-cifs@vger.kernel.org>; Thu, 26 Mar 2026 10:47:42 +0000 (UTC)", "from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-693-m2zo_54vN3yDFY_z3Bv5eA-1; Thu,\n 26 Mar 2026 06:47:38 -0400", "from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id A126E18005BD;\n\tThu, 26 Mar 2026 10:47:34 +0000 (UTC)", "from warthog.procyon.org.com (unknown [10.44.33.121])\n\tby mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id E21EC1800671;\n\tThu, 26 Mar 2026 10:47:27 +0000 (UTC)" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1774522064; cv=none;\n b=SRVMU3LjkvQBhpFyUPeluHZGzBeiXkYjDRiksZMJCCG7Bb2ffh8MACBQoEm/G4j/msHKDFAzvFELzta792y+DluHrt9Jz7GJjuQzWTfd/MNOPDPpaaLkOwbA7Dbn654eFTry645WFwraicWv03KhrYpGWiBlvRJ5NpWK3Awv0Q0=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1774522064; c=relaxed/simple;\n\tbh=attGeeK+7AGJQcEd5IkZIh9qlrn2+ZW9hOEouMFzCuI=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=UBiU/bg4hYWU+lpax9NW+XIIIefpl6EeqfpGwVBzKzWmUJF52+mwunhl9nx3Xvq0Jb635Mt8x+LrEy5jcRPxEZH/rhtDx6+iyBRmYifQ44MWRIdXiYFHI+EoaJKRdtfYb22+vu4JJT0kyqtUYt2Fe3fnA+Hpfr7AQnvWC9QAgOc=", "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=quarantine dis=none) header.from=redhat.com;\n spf=pass smtp.mailfrom=redhat.com;\n dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com\n header.b=E2WAlz0E; arc=none smtp.client-ip=170.10.129.124", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1774522061;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\t to:to:cc:cc:mime-version:mime-version:\n\t content-transfer-encoding:content-transfer-encoding:\n\t in-reply-to:in-reply-to:references:references;\n\tbh=qzGei/xBTUYREFiynnCgIfE37SpwP1mzY41m1gTiMBs=;\n\tb=E2WAlz0Ex9ZUUcsGnepr0Q6pWagQBcaalSph4/gfBVImr/Me8lF3oPtELrJEkD+dwMrywX\n\twOmzY12D2FYX8qEvZpVlUQD3gMt/0+tgPUD1H48+FaUPbXto6rPuSX6VcpVKFjYH/kv0e9\n\tjMNBgQAZKvCia93Gz+tUJtDenDpwXDc=", "X-MC-Unique": "m2zo_54vN3yDFY_z3Bv5eA-1", "X-Mimecast-MFC-AGG-ID": "m2zo_54vN3yDFY_z3Bv5eA_1774522055", "From": "David Howells <dhowells@redhat.com>", "To": "Christian Brauner <christian@brauner.io>,\n\tMatthew Wilcox <willy@infradead.org>,\n\tChristoph Hellwig <hch@infradead.org>", "Cc": "David Howells <dhowells@redhat.com>,\n\tPaulo Alcantara <pc@manguebit.com>,\n\tJens Axboe <axboe@kernel.dk>,\n\tLeon Romanovsky <leon@kernel.org>,\n\tSteve French <sfrench@samba.org>,\n\tChenXiaoSong <chenxiaosong@chenxiaosong.com>,\n\tMarc Dionne <marc.dionne@auristor.com>,\n\tEric Van Hensbergen <ericvh@kernel.org>,\n\tDominique Martinet <asmadeus@codewreck.org>,\n\tIlya Dryomov <idryomov@gmail.com>,\n\tTrond Myklebust <trondmy@kernel.org>,\n\tnetfs@lists.linux.dev,\n\tlinux-afs@lists.infradead.org,\n\tlinux-cifs@vger.kernel.org,\n\tlinux-nfs@vger.kernel.org,\n\tceph-devel@vger.kernel.org,\n\tv9fs@lists.linux.dev,\n\tlinux-erofs@lists.ozlabs.org,\n\tlinux-fsdevel@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org,\n\tPaulo Alcantara <pc@manguebit.org>,\n\tlinux-mm@kvack.org", "Subject": "[PATCH 10/26] netfs: Bulk load the readahead-provided folios up front", "Date": "Thu, 26 Mar 2026 10:45:25 +0000", "Message-ID": "<20260326104544.509518-11-dhowells@redhat.com>", "In-Reply-To": "<20260326104544.509518-1-dhowells@redhat.com>", "References": "<20260326104544.509518-1-dhowells@redhat.com>", "Precedence": "bulk", "X-Mailing-List": "linux-cifs@vger.kernel.org", "List-Id": "<linux-cifs.vger.kernel.org>", "List-Subscribe": "<mailto:linux-cifs+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:linux-cifs+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-Scanned-By": "MIMEDefang 3.4.1 on 10.30.177.93" }, "content": "Load all the folios by the VM for readahead up front into the folio queue.\nWith the number of folios provided by the VM, the folio queue can be fully\nallocated first and then the loading happen in one go inside the RCU read\nlock. The folio refs acquired from readahead are dropped in bulk once the\nfirst subrequest is dispatched as it's quite a slow operation.\n\nThis simplifies the buffer handling later and isn't noticeably slower as\nthe xarray doesn't need to be modified and the folios are all already\npre-locked.\n\nSigned-off-by: David Howells <dhowells@redhat.com>\ncc: Paulo Alcantara <pc@manguebit.org>\ncc: Matthew Wilcox <willy@infradead.org>\ncc: netfs@lists.linux.dev\ncc: linux-mm@kvack.org\ncc: linux-fsdevel@vger.kernel.org\n---\n fs/netfs/buffered_read.c | 95 +++++++++++++++++++++-------------\n fs/netfs/rolling_buffer.c | 75 +++++++++++++++++++++++++++\n include/linux/netfs.h | 1 +\n include/linux/rolling_buffer.h | 3 ++\n include/trace/events/netfs.h | 1 +\n 5 files changed, 138 insertions(+), 37 deletions(-)", "diff": "diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c\nindex aee59ccea257..abdc990faaa2 100644\n--- a/fs/netfs/buffered_read.c\n+++ b/fs/netfs/buffered_read.c\n@@ -54,6 +54,40 @@ static void netfs_rreq_expand(struct netfs_io_request *rreq,\n \t}\n }\n \n+/*\n+ * Drop the folio refs acquired from the readahead API.\n+ */\n+static void netfs_bulk_drop_ra_refs(struct netfs_io_request *rreq)\n+{\n+\tstruct folio_batch fbatch;\n+\tstruct folio *folio;\n+\tpgoff_t nr_pages = DIV_ROUND_UP(rreq->len, PAGE_SIZE);\n+\tpgoff_t first = rreq->start / PAGE_SIZE;\n+\tXA_STATE(xas, &rreq->mapping->i_pages, first);\n+\n+\tfolio_batch_init(&fbatch);\n+\n+\trcu_read_lock();\n+\n+\txas_for_each(&xas, folio, first + nr_pages - 1) {\n+\t\tif (xas_retry(&xas, folio))\n+\t\t\tcontinue;\n+\n+\t\tif (!folio_batch_add(&fbatch, folio))\n+\t\t\tfolio_batch_release(&fbatch);\n+\t}\n+\n+\trcu_read_unlock();\n+\tfolio_batch_release(&fbatch);\n+\ttrace_netfs_rreq(rreq, netfs_rreq_trace_ra_put_ref);\n+}\n+\n+static void netfs_maybe_bulk_drop_ra_refs(struct netfs_io_request *rreq)\n+{\n+\tif (test_and_clear_bit(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags))\n+\t\tnetfs_bulk_drop_ra_refs(rreq);\n+}\n+\n /*\n * Begin an operation, and fetch the stored zero point value from the cookie if\n * available.\n@@ -74,12 +108,8 @@ static int netfs_begin_cache_read(struct netfs_io_request *rreq, struct netfs_in\n *\n * Returns the limited size if successful and -ENOMEM if insufficient memory\n * available.\n- *\n- * [!] NOTE: This must be run in the same thread as ->issue_read() was called\n- * in as we access the readahead_control struct.\n */\n-static ssize_t netfs_prepare_read_iterator(struct netfs_io_subrequest *subreq,\n-\t\t\t\t\t struct readahead_control *ractl)\n+static ssize_t netfs_prepare_read_iterator(struct netfs_io_subrequest *subreq)\n {\n \tstruct netfs_io_request *rreq = subreq->rreq;\n \tsize_t rsize = subreq->len;\n@@ -87,28 +117,6 @@ static ssize_t netfs_prepare_read_iterator(struct netfs_io_subrequest *subreq,\n \tif (subreq->source == NETFS_DOWNLOAD_FROM_SERVER)\n \t\trsize = umin(rsize, rreq->io_streams[0].sreq_max_len);\n \n-\tif (ractl) {\n-\t\t/* If we don't have sufficient folios in the rolling buffer,\n-\t\t * extract a folioq's worth from the readahead region at a time\n-\t\t * into the buffer. Note that this acquires a ref on each page\n-\t\t * that we will need to release later - but we don't want to do\n-\t\t * that until after we've started the I/O.\n-\t\t */\n-\t\tstruct folio_batch put_batch;\n-\n-\t\tfolio_batch_init(&put_batch);\n-\t\twhile (rreq->submitted < subreq->start + rsize) {\n-\t\t\tssize_t added;\n-\n-\t\t\tadded = rolling_buffer_load_from_ra(&rreq->buffer, ractl,\n-\t\t\t\t\t\t\t &put_batch);\n-\t\t\tif (added < 0)\n-\t\t\t\treturn added;\n-\t\t\trreq->submitted += added;\n-\t\t}\n-\t\tfolio_batch_release(&put_batch);\n-\t}\n-\n \tsubreq->len = rsize;\n \tif (unlikely(rreq->io_streams[0].sreq_max_segs)) {\n \t\tsize_t limit = netfs_limit_iter(&rreq->buffer.iter, 0, rsize,\n@@ -209,8 +217,7 @@ static void netfs_issue_read(struct netfs_io_request *rreq,\n * slicing up the region to be read according to available cache blocks and\n * network rsize.\n */\n-static void netfs_read_to_pagecache(struct netfs_io_request *rreq,\n-\t\t\t\t struct readahead_control *ractl)\n+static void netfs_read_to_pagecache(struct netfs_io_request *rreq)\n {\n \tstruct fscache_occupancy _occ = {\n \t\t.query_from\t= rreq->start,\n@@ -345,7 +352,7 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq,\n \t\t\ttrace_netfs_sreq(subreq, netfs_sreq_trace_prepare);\n \t\t}\n \n-\t\tslice = netfs_prepare_read_iterator(subreq, ractl);\n+\t\tslice = netfs_prepare_read_iterator(subreq);\n \t\tif (slice < 0) {\n \t\t\tret = slice;\n \t\t\tsubreq->error = ret;\n@@ -362,6 +369,7 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq,\n \n \t\tnetfs_queue_read(rreq, subreq, size <= 0);\n \t\tnetfs_issue_read(rreq, subreq);\n+\t\tnetfs_maybe_bulk_drop_ra_refs(rreq);\n \t\tcond_resched();\n \t} while (size > 0);\n \n@@ -395,6 +403,7 @@ void netfs_readahead(struct readahead_control *ractl)\n \tstruct netfs_io_request *rreq;\n \tstruct netfs_inode *ictx = netfs_inode(ractl->mapping->host);\n \tunsigned long long start = readahead_pos(ractl);\n+\tssize_t added;\n \tsize_t size = readahead_length(ractl);\n \tint ret;\n \n@@ -415,11 +424,23 @@ void netfs_readahead(struct readahead_control *ractl)\n \n \tnetfs_rreq_expand(rreq, ractl);\n \n-\trreq->submitted = rreq->start;\n-\tif (rolling_buffer_init(&rreq->buffer, rreq->debug_id, ITER_DEST) < 0)\n+\t/* Load the folios to be read into a bvecq chain. Note that this\n+\t * acquires a ref on each folio that we will need to release later -\n+\t * but we don't want to do that until after we've started the I/O.\n+\t */\n+\tadded = rolling_buffer_bulk_load_from_ra(&rreq->buffer, ractl, rreq->debug_id);\n+\tif (added < 0) {\n+\t\tret = added;\n \t\tgoto cleanup_free;\n-\tnetfs_read_to_pagecache(rreq, ractl);\n+\t}\n+\t__set_bit(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags);\n+\n+\trreq->submitted = rreq->start + added;\n+\trreq->cleaned_to = rreq->start;\n+\trreq->front_folio_order = folio_order(rreq->buffer.tail->vec.folios[0]);\n \n+\tnetfs_read_to_pagecache(rreq);\n+\tnetfs_maybe_bulk_drop_ra_refs(rreq);\n \treturn netfs_put_request(rreq, netfs_rreq_trace_put_return);\n \n cleanup_free:\n@@ -511,7 +532,7 @@ static int netfs_read_gaps(struct file *file, struct folio *folio)\n \tiov_iter_bvec(&rreq->buffer.iter, ITER_DEST, bvec, i, rreq->len);\n \trreq->submitted = rreq->start + flen;\n \n-\tnetfs_read_to_pagecache(rreq, NULL);\n+\tnetfs_read_to_pagecache(rreq);\n \n \tif (sink)\n \t\tfolio_put(sink);\n@@ -580,7 +601,7 @@ int netfs_read_folio(struct file *file, struct folio *folio)\n \tif (ret < 0)\n \t\tgoto discard;\n \n-\tnetfs_read_to_pagecache(rreq, NULL);\n+\tnetfs_read_to_pagecache(rreq);\n \tret = netfs_wait_for_read(rreq);\n \tnetfs_put_request(rreq, netfs_rreq_trace_put_return);\n \treturn ret < 0 ? ret : 0;\n@@ -737,7 +758,7 @@ int netfs_write_begin(struct netfs_inode *ctx,\n \tif (ret < 0)\n \t\tgoto error_put;\n \n-\tnetfs_read_to_pagecache(rreq, NULL);\n+\tnetfs_read_to_pagecache(rreq);\n \tret = netfs_wait_for_read(rreq);\n \tif (ret < 0)\n \t\tgoto error;\n@@ -802,7 +823,7 @@ int netfs_prefetch_for_write(struct file *file, struct folio *folio,\n \tif (ret < 0)\n \t\tgoto error_put;\n \n-\tnetfs_read_to_pagecache(rreq, NULL);\n+\tnetfs_read_to_pagecache(rreq);\n \tret = netfs_wait_for_read(rreq);\n \tnetfs_put_request(rreq, netfs_rreq_trace_put_return);\n \treturn ret < 0 ? ret : 0;\ndiff --git a/fs/netfs/rolling_buffer.c b/fs/netfs/rolling_buffer.c\nindex a17fbf9853a4..292011c1cacb 100644\n--- a/fs/netfs/rolling_buffer.c\n+++ b/fs/netfs/rolling_buffer.c\n@@ -149,6 +149,81 @@ ssize_t rolling_buffer_load_from_ra(struct rolling_buffer *roll,\n \treturn size;\n }\n \n+/*\n+ * Decant the entire list of folios to read into a rolling buffer.\n+ */\n+ssize_t rolling_buffer_bulk_load_from_ra(struct rolling_buffer *roll,\n+\t\t\t\t\t struct readahead_control *ractl,\n+\t\t\t\t\t unsigned int rreq_id)\n+{\n+\tXA_STATE(xas, &ractl->mapping->i_pages, ractl->_index);\n+\tstruct folio_queue *fq;\n+\tstruct folio *folio;\n+\tssize_t loaded = 0;\n+\tint nr, slot = 0, npages = 0;\n+\n+\t/* First allocate all the folioqs we're going to need to avoid having\n+\t * to deal with ENOMEM later.\n+\t */\n+\tnr = ractl->_nr_folios;\n+\tdo {\n+\t\tfq = netfs_folioq_alloc(rreq_id, GFP_KERNEL,\n+\t\t\t\t\tnetfs_trace_folioq_make_space);\n+\t\tif (!fq) {\n+\t\t\trolling_buffer_clear(roll);\n+\t\t\treturn -ENOMEM;\n+\t\t}\n+\t\tfq->prev = roll->head;\n+\t\tif (!roll->tail)\n+\t\t\troll->tail = fq;\n+\t\telse\n+\t\t\troll->head->next = fq;\n+\t\troll->head = fq;\n+\t\t\t\n+\t\tnr -= folioq_nr_slots(fq);\n+\t} while (nr > 0);\n+\n+\trcu_read_lock();\n+\n+\tfq = roll->tail;\n+\txas_for_each(&xas, folio, ractl->_index + ractl->_nr_pages - 1) {\n+\t\tunsigned int order;\n+\n+\t\tif (xas_retry(&xas, folio))\n+\t\t\tcontinue;\n+\t\tVM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);\n+\n+\t\torder = folio_order(folio);\n+\t\tfq->orders[slot] = order;\n+\t\tfq->vec.folios[slot] = folio;\n+\t\tloaded += PAGE_SIZE << order;\n+\t\tnpages += 1 << order;\n+\t\ttrace_netfs_folio(folio, netfs_folio_trace_read);\n+\n+\t\tslot++;\n+\t\tif (slot >= folioq_nr_slots(fq)) {\n+\t\t\tfq->vec.nr = slot;\n+\t\t\tfq = fq->next;\n+\t\t\tif (!fq) {\n+\t\t\t\tWARN_ON_ONCE(npages < readahead_count(ractl));\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tslot = 0;\n+\t\t}\n+\t}\n+\n+\trcu_read_unlock();\n+\n+\tif (fq)\n+\t\tfq->vec.nr = slot;\n+\n+\tWRITE_ONCE(roll->iter.count, loaded);\n+\tiov_iter_folio_queue(&roll->iter, ITER_DEST, roll->tail, 0, 0, loaded);\n+\tractl->_index += npages;\n+\tractl->_nr_pages -= npages;\n+\treturn loaded;\n+}\n+\n /*\n * Append a folio to the rolling buffer.\n */\ndiff --git a/include/linux/netfs.h b/include/linux/netfs.h\nindex 77238bc4a712..cc56b6512769 100644\n--- a/include/linux/netfs.h\n+++ b/include/linux/netfs.h\n@@ -280,6 +280,7 @@ struct netfs_io_request {\n #define NETFS_RREQ_FOLIO_COPY_TO_CACHE\t10\t/* Copy current folio to cache from read */\n #define NETFS_RREQ_UPLOAD_TO_SERVER\t11\t/* Need to write to the server */\n #define NETFS_RREQ_USE_IO_ITER\t\t12\t/* Use ->io_iter rather than ->i_pages */\n+#define NETFS_RREQ_NEED_PUT_RA_REFS\t13\t/* Need to put the folio refs RA gave us */\n #define NETFS_RREQ_USE_PGPRIV2\t\t31\t/* [DEPRECATED] Use PG_private_2 to mark\n \t\t\t\t\t\t * write to cache on read */\n \tconst struct netfs_request_ops *netfs_ops;\ndiff --git a/include/linux/rolling_buffer.h b/include/linux/rolling_buffer.h\nindex ac15b1ffdd83..b35ef43f325f 100644\n--- a/include/linux/rolling_buffer.h\n+++ b/include/linux/rolling_buffer.h\n@@ -48,6 +48,9 @@ int rolling_buffer_make_space(struct rolling_buffer *roll);\n ssize_t rolling_buffer_load_from_ra(struct rolling_buffer *roll,\n \t\t\t\t struct readahead_control *ractl,\n \t\t\t\t struct folio_batch *put_batch);\n+ssize_t rolling_buffer_bulk_load_from_ra(struct rolling_buffer *roll,\n+\t\t\t\t\t struct readahead_control *ractl,\n+\t\t\t\t\t unsigned int rreq_id);\n ssize_t rolling_buffer_append(struct rolling_buffer *roll, struct folio *folio,\n \t\t\t unsigned int flags);\n struct folio_queue *rolling_buffer_delete_spent(struct rolling_buffer *roll);\ndiff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h\nindex cbe28211106c..b8236f9e940e 100644\n--- a/include/trace/events/netfs.h\n+++ b/include/trace/events/netfs.h\n@@ -59,6 +59,7 @@\n \tEM(netfs_rreq_trace_free,\t\t\"FREE \")\t\\\n \tEM(netfs_rreq_trace_intr,\t\t\"INTR \")\t\\\n \tEM(netfs_rreq_trace_ki_complete,\t\"KI-CMPL\")\t\\\n+\tEM(netfs_rreq_trace_ra_put_ref,\t\t\"RA-PUT \")\t\\\n \tEM(netfs_rreq_trace_recollect,\t\t\"RECLLCT\")\t\\\n \tEM(netfs_rreq_trace_redirty,\t\t\"REDIRTY\")\t\\\n \tEM(netfs_rreq_trace_resubmit,\t\t\"RESUBMT\")\t\\\n", "prefixes": [ "10/26" ] }