Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2216367/?format=api
{ "id": 2216367, "url": "http://patchwork.ozlabs.org/api/patches/2216367/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260326104544.509518-16-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-16-dhowells@redhat.com>", "list_archive_url": null, "date": "2026-03-26T10:45:30", "name": "[15/26] afs: Use a bvecq to hold dir content rather than folioq", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "553d62ff4c84a1254bee4ae298cb692afebe2ac2", "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-16-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/2216367/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2216367/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <linux-cifs+bounces-10538-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=hgrdaPKj;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-cifs+bounces-10538-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=\"hgrdaPKj\"", "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 sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::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 4fhLfn4G5Bz1y1G\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 26 Mar 2026 22:10:41 +1100 (AEDT)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id EE049319CF0D\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 26 Mar 2026 10:52:18 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id DDCD63EF66E;\n\tThu, 26 Mar 2026 10:48:26 +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 EF3C93E4C7F\n\tfor <linux-cifs@vger.kernel.org>; Thu, 26 Mar 2026 10:48:23 +0000 (UTC)", "from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-281-FUHGgS5pPEqdKsGUd4H_9w-1; Thu,\n 26 Mar 2026 06:48:19 -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-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id E2F7F19560B8;\n\tThu, 26 Mar 2026 10:48:16 +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 8CBA81800671;\n\tThu, 26 Mar 2026 10:48:10 +0000 (UTC)" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1774522106; cv=none;\n b=rw0icpmInQx0yZoFWxFJbxekzEc0GY4jcpt2t09XwtgJtdEVSi5w12532rgdolR8HGS4hXVKepLB/Qg0qOv6CK+y9LZtG2SbDgY3Km3YzMMEA9kaHSIaKuQPYENt3SHqTNynQA6ocH/JdDPXxn0FGxL/g8s3nvrBEeusQ4foK1g=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1774522106; c=relaxed/simple;\n\tbh=5QJhZ/6Fp0Lhe/y9iPccdIFdjXMOmEQBt0aJl8EquS4=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=nnyJXfEAjKU1Guq5bZRYlaZ63yq54B2T8J/1EGwLkYz653Fnd/63XthGqNJt6DhyZdaSGpEm+9FeJK+nHJdquR0Vrz5G23nhxkcG+NSL4FsTfvlNYeRJkUATOrhscJPuYqefhkzHnR0xMhDO62MgMUXQxKKDyPr3YOwYXRnZmHE=", "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=hgrdaPKj; 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=1774522103;\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=Is9VHSESh2LYKPQp2EQ9HQmWLZBLQlOGumcQU3ROqrk=;\n\tb=hgrdaPKjAuqHihGjLE4j97rM3IJV0/EQhNsjIhdzr/2xjOX1+GqWh8lwXNPpoJegBNMGiV\n\tKg0xwP0FBImuJmNeHVqf9Dy48yFazHxkgIx3hfzE1MxI9Vm+hbbc6t2Ax8Alae1i1uwiUR\n\tZxcg5JPLV24bGNuOqG0AMFF2nAd/9SU=", "X-MC-Unique": "FUHGgS5pPEqdKsGUd4H_9w-1", "X-Mimecast-MFC-AGG-ID": "FUHGgS5pPEqdKsGUd4H_9w_1774522097", "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>", "Subject": "[PATCH 15/26] afs: Use a bvecq to hold dir content rather than folioq", "Date": "Thu, 26 Mar 2026 10:45:30 +0000", "Message-ID": "<20260326104544.509518-16-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": "Use a bvecq to hold the contents of a directory rather than the folioq so\nthat the latter can be phased out.\n\nSigned-off-by: David Howells <dhowells@redhat.com>\ncc: Paulo Alcantara <pc@manguebit.org>\ncc: Matthew Wilcox <willy@infradead.org>\ncc: Christoph Hellwig <hch@infradead.org>\ncc: Marc Dionne <marc.dionne@auristor.com>\ncc: linux-afs@lists.infradead.org\ncc: netfs@lists.linux.dev\ncc: linux-fsdevel@vger.kernel.org\n---\n fs/afs/dir.c | 39 +++++------\n fs/afs/dir_edit.c | 42 +++++------\n fs/afs/dir_search.c | 33 ++++-----\n fs/afs/inode.c | 20 +++---\n fs/afs/internal.h | 6 +-\n fs/netfs/write_issue.c | 156 ++++++-----------------------------------\n 6 files changed, 88 insertions(+), 208 deletions(-)", "diff": "diff --git a/fs/afs/dir.c b/fs/afs/dir.c\nindex 78caef3f1338..6627a0d38e73 100644\n--- a/fs/afs/dir.c\n+++ b/fs/afs/dir.c\n@@ -136,9 +136,9 @@ static void afs_dir_dump(struct afs_vnode *dvnode)\n \tpr_warn(\"DIR %llx:%llx is=%llx\\n\",\n \t\tdvnode->fid.vid, dvnode->fid.vnode, i_size);\n \n-\tiov_iter_folio_queue(&iter, ITER_SOURCE, dvnode->directory, 0, 0, i_size);\n-\titerate_folioq(&iter, iov_iter_count(&iter), NULL, NULL,\n-\t\t afs_dir_dump_step);\n+\tiov_iter_bvec_queue(&iter, ITER_SOURCE, dvnode->directory, 0, 0, i_size);\n+\titerate_bvecq(&iter, iov_iter_count(&iter), NULL, NULL,\n+\t\t afs_dir_dump_step);\n }\n \n /*\n@@ -199,9 +199,9 @@ static int afs_dir_check(struct afs_vnode *dvnode)\n \tif (unlikely(!i_size))\n \t\treturn 0;\n \n-\tiov_iter_folio_queue(&iter, ITER_SOURCE, dvnode->directory, 0, 0, i_size);\n-\tchecked = iterate_folioq(&iter, iov_iter_count(&iter), dvnode, NULL,\n-\t\t\t\t afs_dir_check_step);\n+\tiov_iter_bvec_queue(&iter, ITER_SOURCE, dvnode->directory, 0, 0, i_size);\n+\tchecked = iterate_bvecq(&iter, iov_iter_count(&iter), dvnode, NULL,\n+\t\t\t\tafs_dir_check_step);\n \tif (checked != i_size) {\n \t\tafs_dir_dump(dvnode);\n \t\treturn -EIO;\n@@ -255,15 +255,14 @@ static ssize_t afs_do_read_single(struct afs_vnode *dvnode, struct file *file)\n \tif (dvnode->directory_size < i_size) {\n \t\tsize_t cur_size = dvnode->directory_size;\n \n-\t\tret = netfs_alloc_folioq_buffer(NULL,\n-\t\t\t\t\t\t&dvnode->directory, &cur_size, i_size,\n-\t\t\t\t\t\tmapping_gfp_mask(dvnode->netfs.inode.i_mapping));\n+\t\tret = bvecq_expand_buffer(&dvnode->directory, &cur_size, i_size,\n+\t\t\t\t\t mapping_gfp_mask(dvnode->netfs.inode.i_mapping));\n \t\tdvnode->directory_size = cur_size;\n \t\tif (ret < 0)\n \t\t\treturn ret;\n \t}\n \n-\tiov_iter_folio_queue(&iter, ITER_DEST, dvnode->directory, 0, 0, dvnode->directory_size);\n+\tiov_iter_bvec_queue(&iter, ITER_DEST, dvnode->directory, 0, 0, dvnode->directory_size);\n \n \t/* AFS requires us to perform the read of a directory synchronously as\n \t * a single unit to avoid issues with the directory contents being\n@@ -282,9 +281,9 @@ static ssize_t afs_do_read_single(struct afs_vnode *dvnode, struct file *file)\n \n \t\t\tif (ret2 < 0)\n \t\t\t\tret = ret2;\n-\t\t} else if (i_size < folioq_folio_size(dvnode->directory, 0)) {\n+\t\t} else if (i_size < PAGE_SIZE) {\n \t\t\t/* NUL-terminate a symlink. */\n-\t\t\tchar *symlink = kmap_local_folio(folioq_folio(dvnode->directory, 0), 0);\n+\t\t\tchar *symlink = kmap_local_bvec(&dvnode->directory->bv[0], 0);\n \n \t\t\tsymlink[i_size] = 0;\n \t\t\tkunmap_local(symlink);\n@@ -305,8 +304,8 @@ ssize_t afs_read_single(struct afs_vnode *dvnode, struct file *file)\n }\n \n /*\n- * Read the directory into a folio_queue buffer in one go, scrubbing the\n- * previous contents. We return -ESTALE if the caller needs to call us again.\n+ * Read the directory into the buffer in one go, scrubbing the previous\n+ * contents. We return -ESTALE if the caller needs to call us again.\n */\n ssize_t afs_read_dir(struct afs_vnode *dvnode, struct file *file)\n \t__acquires(&dvnode->validate_lock)\n@@ -487,7 +486,7 @@ static size_t afs_dir_iterate_step(void *iter_base, size_t progress, size_t len,\n }\n \n /*\n- * Iterate through the directory folios.\n+ * Iterate through the directory content.\n */\n static int afs_dir_iterate_contents(struct inode *dir, struct dir_context *dir_ctx)\n {\n@@ -502,11 +501,11 @@ static int afs_dir_iterate_contents(struct inode *dir, struct dir_context *dir_c\n \tif (i_size <= 0 || dir_ctx->pos >= i_size)\n \t\treturn 0;\n \n-\tiov_iter_folio_queue(&iter, ITER_SOURCE, dvnode->directory, 0, 0, i_size);\n+\tiov_iter_bvec_queue(&iter, ITER_SOURCE, dvnode->directory, 0, 0, i_size);\n \tiov_iter_advance(&iter, round_down(dir_ctx->pos, AFS_DIR_BLOCK_SIZE));\n \n-\titerate_folioq(&iter, iov_iter_count(&iter), dvnode, &ctx,\n-\t\t afs_dir_iterate_step);\n+\titerate_bvecq(&iter, iov_iter_count(&iter), dvnode, &ctx,\n+\t\t afs_dir_iterate_step);\n \n \tif (ctx.error == -ESTALE)\n \t\tafs_invalidate_dir(dvnode, afs_dir_invalid_iter_stale);\n@@ -2211,8 +2210,8 @@ int afs_single_writepages(struct address_space *mapping,\n \tif (is_dir ?\n \t test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) :\n \t atomic64_read(&dvnode->cb_expires_at) != AFS_NO_CB_PROMISE) {\n-\t\tiov_iter_folio_queue(&iter, ITER_SOURCE, dvnode->directory, 0, 0,\n-\t\t\t\t i_size_read(&dvnode->netfs.inode));\n+\t\tiov_iter_bvec_queue(&iter, ITER_SOURCE, dvnode->directory, 0, 0,\n+\t\t\t\t i_size_read(&dvnode->netfs.inode));\n \t\tret = netfs_writeback_single(mapping, wbc, &iter);\n \t}\n \ndiff --git a/fs/afs/dir_edit.c b/fs/afs/dir_edit.c\nindex fd3aa9f97ce6..59d3decf7692 100644\n--- a/fs/afs/dir_edit.c\n+++ b/fs/afs/dir_edit.c\n@@ -110,9 +110,8 @@ static void afs_clear_contig_bits(union afs_xdr_dir_block *block,\n */\n static union afs_xdr_dir_block *afs_dir_get_block(struct afs_dir_iter *iter, size_t block)\n {\n-\tstruct folio_queue *fq;\n \tstruct afs_vnode *dvnode = iter->dvnode;\n-\tstruct folio *folio;\n+\tstruct bvecq *bq;\n \tsize_t blpos = block * AFS_DIR_BLOCK_SIZE;\n \tsize_t blend = (block + 1) * AFS_DIR_BLOCK_SIZE, fpos = iter->fpos;\n \tint ret;\n@@ -120,41 +119,38 @@ static union afs_xdr_dir_block *afs_dir_get_block(struct afs_dir_iter *iter, siz\n \tif (dvnode->directory_size < blend) {\n \t\tsize_t cur_size = dvnode->directory_size;\n \n-\t\tret = netfs_alloc_folioq_buffer(\n-\t\t\tNULL, &dvnode->directory, &cur_size, blend,\n-\t\t\tmapping_gfp_mask(dvnode->netfs.inode.i_mapping));\n+\t\tret = bvecq_expand_buffer(&dvnode->directory, &cur_size, blend,\n+\t\t\t\t\t mapping_gfp_mask(dvnode->netfs.inode.i_mapping));\n \t\tdvnode->directory_size = cur_size;\n \t\tif (ret < 0)\n \t\t\tgoto fail;\n \t}\n \n-\tfq = iter->fq;\n-\tif (!fq)\n-\t\tfq = dvnode->directory;\n+\tbq = iter->bq;\n+\tif (!bq)\n+\t\tbq = dvnode->directory;\n \n-\t/* Search the folio queue for the folio containing the block... */\n-\tfor (; fq; fq = fq->next) {\n-\t\tfor (int s = iter->fq_slot; s < folioq_count(fq); s++) {\n-\t\t\tsize_t fsize = folioq_folio_size(fq, s);\n+\t/* Search the contents for the region containing the block... */\n+\tfor (; bq; bq = bq->next) {\n+\t\tfor (int s = iter->bq_slot; s < bq->nr_slots; s++) {\n+\t\t\tstruct bio_vec *bv = &bq->bv[s];\n+\t\t\tsize_t bsize = bv->bv_len;\n \n-\t\t\tif (blend <= fpos + fsize) {\n+\t\t\tif (blend <= fpos + bsize) {\n \t\t\t\t/* ... and then return the mapped block. */\n-\t\t\t\tfolio = folioq_folio(fq, s);\n-\t\t\t\tif (WARN_ON_ONCE(folio_pos(folio) != fpos))\n-\t\t\t\t\tgoto fail;\n-\t\t\t\titer->fq = fq;\n-\t\t\t\titer->fq_slot = s;\n+\t\t\t\titer->bq = bq;\n+\t\t\t\titer->bq_slot = s;\n \t\t\t\titer->fpos = fpos;\n-\t\t\t\treturn kmap_local_folio(folio, blpos - fpos);\n+\t\t\t\treturn kmap_local_bvec(bv, blpos - fpos);\n \t\t\t}\n-\t\t\tfpos += fsize;\n+\t\t\tfpos += bsize;\n \t\t}\n-\t\titer->fq_slot = 0;\n+\t\titer->bq_slot = 0;\n \t}\n \n fail:\n-\titer->fq = NULL;\n-\titer->fq_slot = 0;\n+\titer->bq = NULL;\n+\titer->bq_slot = 0;\n \tafs_invalidate_dir(dvnode, afs_dir_invalid_edit_get_block);\n \treturn NULL;\n }\ndiff --git a/fs/afs/dir_search.c b/fs/afs/dir_search.c\nindex d2516e55b5ed..f1d2b49bc6f0 100644\n--- a/fs/afs/dir_search.c\n+++ b/fs/afs/dir_search.c\n@@ -66,12 +66,11 @@ bool afs_dir_init_iter(struct afs_dir_iter *iter, const struct qstr *name)\n */\n union afs_xdr_dir_block *afs_dir_find_block(struct afs_dir_iter *iter, size_t block)\n {\n-\tstruct folio_queue *fq = iter->fq;\n \tstruct afs_vnode *dvnode = iter->dvnode;\n-\tstruct folio *folio;\n+\tstruct bvecq *bq = iter->bq;\n \tsize_t blpos = block * AFS_DIR_BLOCK_SIZE;\n \tsize_t blend = (block + 1) * AFS_DIR_BLOCK_SIZE, fpos = iter->fpos;\n-\tint slot = iter->fq_slot;\n+\tint slot = iter->bq_slot;\n \n \t_enter(\"%zx,%d\", block, slot);\n \n@@ -83,36 +82,34 @@ union afs_xdr_dir_block *afs_dir_find_block(struct afs_dir_iter *iter, size_t bl\n \tif (dvnode->directory_size < blend)\n \t\tgoto fail;\n \n-\tif (!fq || blpos < fpos) {\n-\t\tfq = dvnode->directory;\n+\tif (!bq || blpos < fpos) {\n+\t\tbq = dvnode->directory;\n \t\tslot = 0;\n \t\tfpos = 0;\n \t}\n \n \t/* Search the folio queue for the folio containing the block... */\n-\tfor (; fq; fq = fq->next) {\n-\t\tfor (; slot < folioq_count(fq); slot++) {\n-\t\t\tsize_t fsize = folioq_folio_size(fq, slot);\n+\tfor (; bq; bq = bq->next) {\n+\t\tfor (; slot < bq->nr_slots; slot++) {\n+\t\t\tstruct bio_vec *bv = &bq->bv[slot];\n+\t\t\tsize_t bsize = bv->bv_len;\n \n-\t\t\tif (blend <= fpos + fsize) {\n+\t\t\tif (blend <= fpos + bsize) {\n \t\t\t\t/* ... and then return the mapped block. */\n-\t\t\t\tfolio = folioq_folio(fq, slot);\n-\t\t\t\tif (WARN_ON_ONCE(folio_pos(folio) != fpos))\n-\t\t\t\t\tgoto fail;\n-\t\t\t\titer->fq = fq;\n-\t\t\t\titer->fq_slot = slot;\n+\t\t\t\titer->bq = bq;\n+\t\t\t\titer->bq_slot = slot;\n \t\t\t\titer->fpos = fpos;\n-\t\t\t\titer->block = kmap_local_folio(folio, blpos - fpos);\n+\t\t\t\titer->block = kmap_local_bvec(bv, blpos - fpos);\n \t\t\t\treturn iter->block;\n \t\t\t}\n-\t\t\tfpos += fsize;\n+\t\t\tfpos += bsize;\n \t\t}\n \t\tslot = 0;\n \t}\n \n fail:\n-\titer->fq = NULL;\n-\titer->fq_slot = 0;\n+\titer->bq = NULL;\n+\titer->bq_slot = 0;\n \tafs_invalidate_dir(dvnode, afs_dir_invalid_edit_get_block);\n \treturn NULL;\n }\ndiff --git a/fs/afs/inode.c b/fs/afs/inode.c\nindex dde1857fcabb..94e3442da849 100644\n--- a/fs/afs/inode.c\n+++ b/fs/afs/inode.c\n@@ -31,12 +31,12 @@ void afs_init_new_symlink(struct afs_vnode *vnode, struct afs_operation *op)\n \tsize_t dsize = 0;\n \tchar *p;\n \n-\tif (netfs_alloc_folioq_buffer(NULL, &vnode->directory, &dsize, size,\n-\t\t\t\t mapping_gfp_mask(vnode->netfs.inode.i_mapping)) < 0)\n+\tif (bvecq_expand_buffer(&vnode->directory, &dsize, size,\n+\t\t\t\tmapping_gfp_mask(vnode->netfs.inode.i_mapping)) < 0)\n \t\treturn;\n \n \tvnode->directory_size = dsize;\n-\tp = kmap_local_folio(folioq_folio(vnode->directory, 0), 0);\n+\tp = kmap_local_bvec(&vnode->directory->bv[0], 0);\n \tmemcpy(p, op->create.symlink, size);\n \tkunmap_local(p);\n \tset_bit(AFS_VNODE_DIR_READ, &vnode->flags);\n@@ -45,17 +45,17 @@ void afs_init_new_symlink(struct afs_vnode *vnode, struct afs_operation *op)\n \n static void afs_put_link(void *arg)\n {\n-\tstruct folio *folio = virt_to_folio(arg);\n+\tstruct page *page = virt_to_page(arg);\n \n \tkunmap_local(arg);\n-\tfolio_put(folio);\n+\tput_page(page);\n }\n \n const char *afs_get_link(struct dentry *dentry, struct inode *inode,\n \t\t\t struct delayed_call *callback)\n {\n \tstruct afs_vnode *vnode = AFS_FS_I(inode);\n-\tstruct folio *folio;\n+\tstruct page *page;\n \tchar *content;\n \tssize_t ret;\n \n@@ -84,9 +84,9 @@ const char *afs_get_link(struct dentry *dentry, struct inode *inode,\n \tset_bit(AFS_VNODE_DIR_READ, &vnode->flags);\n \n good:\n-\tfolio = folioq_folio(vnode->directory, 0);\n-\tfolio_get(folio);\n-\tcontent = kmap_local_folio(folio, 0);\n+\tpage = vnode->directory->bv[0].bv_page;\n+\tget_page(page);\n+\tcontent = kmap_local_page(page);\n \tset_delayed_call(callback, afs_put_link, content);\n \treturn content;\n }\n@@ -761,7 +761,7 @@ void afs_evict_inode(struct inode *inode)\n \n \tnetfs_wait_for_outstanding_io(inode);\n \ttruncate_inode_pages_final(&inode->i_data);\n-\tnetfs_free_folioq_buffer(vnode->directory);\n+\tbvecq_put(vnode->directory);\n \n \tafs_set_cache_aux(vnode, &aux);\n \tnetfs_clear_inode_writeback(inode, &aux);\ndiff --git a/fs/afs/internal.h b/fs/afs/internal.h\nindex 009064b8d661..9bf5d2f1dbc4 100644\n--- a/fs/afs/internal.h\n+++ b/fs/afs/internal.h\n@@ -710,7 +710,7 @@ struct afs_vnode {\n #define AFS_VNODE_MODIFYING\t10\t\t/* Set if we're performing a modification op */\n #define AFS_VNODE_DIR_READ\t11\t\t/* Set if we've read a dir's contents */\n \n-\tstruct folio_queue\t*directory;\t/* Directory contents */\n+\tstruct bvecq\t\t*directory;\t/* Directory contents */\n \tstruct list_head\twb_keys;\t/* List of keys available for writeback */\n \tstruct list_head\tpending_locks;\t/* locks waiting to be granted */\n \tstruct list_head\tgranted_locks;\t/* locks granted on this file */\n@@ -983,9 +983,9 @@ static inline void afs_invalidate_cache(struct afs_vnode *vnode, unsigned int fl\n struct afs_dir_iter {\n \tstruct afs_vnode\t*dvnode;\n \tunion afs_xdr_dir_block *block;\n-\tstruct folio_queue\t*fq;\n+\tstruct bvecq\t\t*bq;\n \tunsigned int\t\tfpos;\n-\tint\t\t\tfq_slot;\n+\tint\t\t\tbq_slot;\n \tunsigned int\t\tloop_check;\n \tu8\t\t\tnr_slots;\n \tu8\t\t\tbucket;\ndiff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c\nindex 2de6b8621e11..9ca2c780f469 100644\n--- a/fs/netfs/write_issue.c\n+++ b/fs/netfs/write_issue.c\n@@ -700,124 +700,11 @@ ssize_t netfs_end_writethrough(struct netfs_io_request *wreq, struct writeback_c\n \treturn ret;\n }\n \n-/*\n- * Write some of a pending folio data back to the server and/or the cache.\n- */\n-static int netfs_write_folio_single(struct netfs_io_request *wreq,\n-\t\t\t\t struct folio *folio)\n-{\n-\tstruct netfs_io_stream *upload = &wreq->io_streams[0];\n-\tstruct netfs_io_stream *cache = &wreq->io_streams[1];\n-\tstruct netfs_io_stream *stream;\n-\tsize_t iter_off = 0;\n-\tsize_t fsize = folio_size(folio), flen;\n-\tloff_t fpos = folio_pos(folio);\n-\tbool to_eof = false;\n-\tbool no_debug = false;\n-\n-\t_enter(\"\");\n-\n-\tflen = folio_size(folio);\n-\tif (flen > wreq->i_size - fpos) {\n-\t\tflen = wreq->i_size - fpos;\n-\t\tfolio_zero_segment(folio, flen, fsize);\n-\t\tto_eof = true;\n-\t} else if (flen == wreq->i_size - fpos) {\n-\t\tto_eof = true;\n-\t}\n-\n-\t_debug(\"folio %zx/%zx\", flen, fsize);\n-\n-\tif (!upload->avail && !cache->avail) {\n-\t\ttrace_netfs_folio(folio, netfs_folio_trace_cancel_store);\n-\t\treturn 0;\n-\t}\n-\n-\tif (!upload->construct)\n-\t\ttrace_netfs_folio(folio, netfs_folio_trace_store);\n-\telse\n-\t\ttrace_netfs_folio(folio, netfs_folio_trace_store_plus);\n-\n-\t/* Attach the folio to the rolling buffer. */\n-\tfolio_get(folio);\n-\trolling_buffer_append(&wreq->buffer, folio, NETFS_ROLLBUF_PUT_MARK);\n-\n-\t/* Move the submission point forward to allow for write-streaming data\n-\t * not starting at the front of the page. We don't do write-streaming\n-\t * with the cache as the cache requires DIO alignment.\n-\t *\n-\t * Also skip uploading for data that's been read and just needs copying\n-\t * to the cache.\n-\t */\n-\tfor (int s = 0; s < NR_IO_STREAMS; s++) {\n-\t\tstream = &wreq->io_streams[s];\n-\t\tstream->submit_off = 0;\n-\t\tstream->submit_len = flen;\n-\t\tif (!stream->avail) {\n-\t\t\tstream->submit_off = UINT_MAX;\n-\t\t\tstream->submit_len = 0;\n-\t\t}\n-\t}\n-\n-\t/* Attach the folio to one or more subrequests. For a big folio, we\n-\t * could end up with thousands of subrequests if the wsize is small -\n-\t * but we might need to wait during the creation of subrequests for\n-\t * network resources (eg. SMB credits).\n-\t */\n-\tfor (;;) {\n-\t\tssize_t part;\n-\t\tsize_t lowest_off = ULONG_MAX;\n-\t\tint choose_s = -1;\n-\n-\t\t/* Always add to the lowest-submitted stream first. */\n-\t\tfor (int s = 0; s < NR_IO_STREAMS; s++) {\n-\t\t\tstream = &wreq->io_streams[s];\n-\t\t\tif (stream->submit_len > 0 &&\n-\t\t\t stream->submit_off < lowest_off) {\n-\t\t\t\tlowest_off = stream->submit_off;\n-\t\t\t\tchoose_s = s;\n-\t\t\t}\n-\t\t}\n-\n-\t\tif (choose_s < 0)\n-\t\t\tbreak;\n-\t\tstream = &wreq->io_streams[choose_s];\n-\n-\t\t/* Advance the iterator(s). */\n-\t\tif (stream->submit_off > iter_off) {\n-\t\t\trolling_buffer_advance(&wreq->buffer, stream->submit_off - iter_off);\n-\t\t\titer_off = stream->submit_off;\n-\t\t}\n-\n-\t\tatomic64_set(&wreq->issued_to, fpos + stream->submit_off);\n-\t\tstream->submit_extendable_to = fsize - stream->submit_off;\n-\t\tpart = netfs_advance_write(wreq, stream, fpos + stream->submit_off,\n-\t\t\t\t\t stream->submit_len, to_eof);\n-\t\tstream->submit_off += part;\n-\t\tif (part > stream->submit_len)\n-\t\t\tstream->submit_len = 0;\n-\t\telse\n-\t\t\tstream->submit_len -= part;\n-\t\tif (part > 0)\n-\t\t\tno_debug = true;\n-\t}\n-\n-\twreq->buffer.iter.iov_offset = 0;\n-\tif (fsize > iter_off)\n-\t\trolling_buffer_advance(&wreq->buffer, fsize - iter_off);\n-\tatomic64_set(&wreq->issued_to, fpos + fsize);\n-\n-\tif (!no_debug)\n-\t\tkdebug(\"R=%x: No submit\", wreq->debug_id);\n-\t_leave(\" = 0\");\n-\treturn 0;\n-}\n-\n /**\n * netfs_writeback_single - Write back a monolithic payload\n * @mapping: The mapping to write from\n * @wbc: Hints from the VM\n- * @iter: Data to write, must be ITER_FOLIOQ.\n+ * @iter: Data to write.\n *\n * Write a monolithic, non-pagecache object back to the server and/or\n * the cache.\n@@ -828,13 +715,8 @@ int netfs_writeback_single(struct address_space *mapping,\n {\n \tstruct netfs_io_request *wreq;\n \tstruct netfs_inode *ictx = netfs_inode(mapping->host);\n-\tstruct folio_queue *fq;\n-\tsize_t size = iov_iter_count(iter);\n \tint ret;\n \n-\tif (WARN_ON_ONCE(!iov_iter_is_folioq(iter)))\n-\t\treturn -EIO;\n-\n \tif (!mutex_trylock(&ictx->wb_lock)) {\n \t\tif (wbc->sync_mode == WB_SYNC_NONE) {\n \t\t\tnetfs_stat(&netfs_n_wb_lock_skip);\n@@ -850,6 +732,9 @@ int netfs_writeback_single(struct address_space *mapping,\n \t\tgoto couldnt_start;\n \t}\n \n+\twreq->buffer.iter = *iter;\n+\twreq->len = iov_iter_count(iter);\n+\n \t__set_bit(NETFS_RREQ_OFFLOAD_COLLECTION, &wreq->flags);\n \ttrace_netfs_write(wreq, netfs_write_trace_writeback_single);\n \tnetfs_stat(&netfs_n_wh_writepages);\n@@ -857,31 +742,34 @@ int netfs_writeback_single(struct address_space *mapping,\n \tif (__test_and_set_bit(NETFS_RREQ_UPLOAD_TO_SERVER, &wreq->flags))\n \t\twreq->netfs_ops->begin_writeback(wreq);\n \n-\tfor (fq = (struct folio_queue *)iter->folioq; fq; fq = fq->next) {\n-\t\tfor (int slot = 0; slot < folioq_count(fq); slot++) {\n-\t\t\tstruct folio *folio = folioq_folio(fq, slot);\n-\t\t\tsize_t part = umin(folioq_folio_size(fq, slot), size);\n+\tfor (int s = 0; s < NR_IO_STREAMS; s++) {\n+\t\tstruct netfs_io_subrequest *subreq;\n+\t\tstruct netfs_io_stream *stream = &wreq->io_streams[s];\n+\n+\t\tif (!stream->avail)\n+\t\t\tcontinue;\n \n-\t\t\t_debug(\"wbiter %lx %llx\", folio->index, atomic64_read(&wreq->issued_to));\n+\t\tnetfs_prepare_write(wreq, stream, 0);\n \n-\t\t\tret = netfs_write_folio_single(wreq, folio);\n-\t\t\tif (ret < 0)\n-\t\t\t\tgoto stop;\n-\t\t\tsize -= part;\n-\t\t\tif (size <= 0)\n-\t\t\t\tgoto stop;\n-\t\t}\n+\t\tsubreq = stream->construct;\n+\t\tsubreq->len = wreq->len;\n+\t\tstream->submit_len = subreq->len;\n+\t\tstream->submit_extendable_to = round_up(wreq->len, PAGE_SIZE);\n+\n+\t\tnetfs_issue_write(wreq, stream);\n \t}\n \n-stop:\n-\tfor (int s = 0; s < NR_IO_STREAMS; s++)\n-\t\tnetfs_issue_write(wreq, &wreq->io_streams[s]);\n \tsmp_wmb(); /* Write lists before ALL_QUEUED. */\n \tset_bit(NETFS_RREQ_ALL_QUEUED, &wreq->flags);\n \n \tmutex_unlock(&ictx->wb_lock);\n \tnetfs_wake_collector(wreq);\n \n+\t/* TODO: Might want to be async here if WB_SYNC_NONE, but then need to\n+\t * wait before modifying.\n+\t */\n+\tret = netfs_wait_for_write(wreq);\n+\n \tnetfs_put_request(wreq, netfs_rreq_trace_put_return);\n \t_leave(\" = %d\", ret);\n \treturn ret;\n", "prefixes": [ "15/26" ] }