v9fs.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "David Howells" <dhowells@redhat.com>
Cc: v9fs@lists.linux.dev, "Chuck Lever" <cel@kernel.org>,
	"Jeff Layton" <jlayton@kernel.org>,
	"Anna Schumaker" <anna@kernel.org>
Subject: Re: [PATCH v16 03/15] netfs: Add some tools for managing bvecq chains
Date: Sat, 07 Nov 2026 16:46:03 +0000	[thread overview]
Message-ID: <sashiko-outbox-203072@kernel.org> (raw)
In-Reply-To: <20261107160823.1465553-4-dhowells@redhat.com>

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] netfs: mempool deadlock in bvecq_alloc_chain() when
  for_writeback is true
- [Medium] netfs: uninitialized mem_type and bv[] in
  bvecq_alloc_buffer2() when size is 0
--

commit 7b4f77e4cd79aa76c73be1af04e2001e239881a3
Author: David Howells <dhowells@redhat.com>

netfs: Add some tools for managing bvecq chains

This commit adds helper functions for allocating, populating, expanding,
and refcounting bvecq nodes and chains, along with a mempool for writeback
allocations.

> diff --git a/fs/netfs/bvecq.c b/fs/netfs/bvecq.c
> new file mode 100644
> index 0000000000000..06adb44ea93fc
> --- /dev/null
> +++ b/fs/netfs/bvecq.c

[ ... ]

> +struct bvecq *bvecq_alloc_chain(size_t nr_slots, gfp_t gfp, bool for_writeback)
> +{
> +	struct bvecq *head = NULL, *tail = NULL;
> +
> +	_enter("%zu", nr_slots);
> +
> +	for (;;) {
> +		struct bvecq *bq;
> +
> +		bq = bvecq_alloc_one(min(nr_slots, BVECQ_4KB_SLOTS), gfp, for_writeback);
> +		if (!bq)
> +			goto oom;
> +
> +		if (tail)
> +			bvecq_append(tail, bq);
> +		else
> +			head = bq;
> +		tail = bq;
> +		if (tail->max_slots >= nr_slots)
> +			break;
> +		nr_slots -= tail->max_slots;
> +	}
> +
> +	return head;
> +oom:
> +	bvecq_put(head);
> +	return NULL;
> +}
> +EXPORT_SYMBOL(bvecq_alloc_chain);

[Severity: High]
Can bvecq_alloc_chain() deadlock on netfs_bvecq_pool when for_writeback is
true?

Under memory pressure, bvecq_alloc_one() falls back to
mempool_alloc(&netfs_bvecq_pool, gfp).  Because this loop allocates
multiple nodes from the same 100-element pool while holding previously
allocated nodes in head, a single request needing more than 100 pool nodes
(~11.3 MiB) or concurrent writeback threads exhausting the pool midway
through their chains will sleep in mempool_alloc() waiting for elements
that they themselves are pinning.

> +
> +/**
> + * bvecq_alloc_buffer2 - Allocate a bvecq chain and populate with buffers
> + * @size: Target size of the buffer (can be 0 for an empty buffer)
> + * @pre_slots: Number of preamble slots to set aside
> + * @gfp: The allocation constraints.
> + * @for_writeback: True if allocating for writeback
> + *
> + * Allocate a chain of bvecq nodes and populate the slots with sufficient pages
> + * to provide at least the requested amount of space, leaving the first
> + * @pre_slots slots unset.  The pre-slots must all fit into the first bvecq.
> + * Note that any memory segments set in the pre_slots will be freed as
> + * specified by BVECQ_MEM_ALLOCED.
> + *
> + * The caller should assume that the pages allocated may be compound pages
> + * larger than PAGE_SIZE and thus occupy fewer slots.  The pages have their
> + * refcounts set to 1 and can be passed to MSG_SPLICE_PAGES.
> + *
> + * Return: The first node pointer or NULL on allocation failure.
> + */
> +struct bvecq *bvecq_alloc_buffer2(size_t size, unsigned int pre_slots, gfp_t gfp,
> +				  bool for_writeback)
> +{
> +	struct bvecq *head = NULL, *p = NULL;
> +	size_t nr_per_bq = BVECQ_POOL_SLOTS;
> +	size_t count = pre_slots + DIV_ROUND_UP(size, PAGE_SIZE);
> +
> +	_enter("%zx,%zx,%u", size, count, pre_slots);
> +
> +	if (WARN_ON_ONCE(pre_slots > nr_per_bq))
> +		return NULL;
> +
> +	head = bvecq_alloc_chain(count, gfp, for_writeback);
> +	if (!head)
> +		return NULL;
> +
> +	p = head;
> +	do {
> +		struct page **pages;
> +		size_t unused, want, got, slot;
> +
> +		if (!count)
> +			break;
> +		if (WARN_ON_ONCE(!p))
> +			goto oom;
> +
> +		if (p->nr_slots == 0) {
> +			/* Need to clear pre slots and pages[], so just clear all. */
> +			memset(p->bv, 0, p->max_slots * sizeof(p->bv[0]));
> +			p->mem_type = BVECQ_MEM_ALLOCED;
> +			p->nr_slots = pre_slots;
> +			count -= pre_slots;
> +			pre_slots = 0;
> +			if (!count)
> +				break;
> +		}

[Severity: Medium]
Does calling bvecq_alloc_buffer2() with size == 0 and pre_slots == 0 (for
instance via bvecq_alloc_buffer(0, ...)) leave p->bv uninitialised and
p->mem_type set to BVECQ_MEM_EXTERNAL instead of BVECQ_MEM_ALLOCED?

When both size and pre_slots are 0, count is 0, so the first if (!count)
check breaks out of the loop before the p->nr_slots == 0 block zeroes
p->bv and sets p->mem_type = BVECQ_MEM_ALLOCED.  In addition, passing
count == 0 to bvecq_alloc_chain() rounds up sizeof(*bq) alone, which yields
max_slots == 0 on 32-bit architectures (or 1 on 64-bit) when not allocated
from the mempool.  If the caller later populates slots in this node,
bvecq_put() will leak the pages, and bvecq_expand_buffer() will allocate a
new bvecq node leaving the empty head node unused.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261107160823.1465553-1-dhowells@redhat.com?part=3

  reply	other threads:[~2026-11-07 16:46 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-07 16:08 [PATCH v16 00/15] netfs, iov_iter: Use a chain of bio_vec arrays instead of folio_queue David Howells
2026-11-07 16:08 ` [PATCH v16 01/15] Add a function to kmap one page of a multipage bio_vec David Howells
2026-11-07 16:15   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 02/15] iov_iter: Add a segmented queue of bio_vec[] David Howells
2026-11-07 16:31   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 03/15] netfs: Add some tools for managing bvecq chains David Howells
2026-11-07 16:46   ` sashiko-bot [this message]
2026-11-07 16:08 ` [PATCH v16 04/15] iov_iter: Add an API document for the bvecq structure David Howells
2026-11-07 16:47   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 05/15] iov_iter: Add a bvecq kunit test David Howells
2026-11-07 17:01   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 06/15] afs: Fix an inconsistency in the symlink code David Howells
2026-11-07 17:09   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 07/15] netfs: Explicitly pass tail padding to netfs_writeback_single() David Howells
2026-11-07 17:46   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 08/15] netfs: Change netfs_writeback_single() to not look inside the iterator David Howells
2026-11-07 18:09   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 09/15] afs: Use a bvecq to hold dir content rather than folioq David Howells
2026-11-07 18:34   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 10/15] cifs: Use a bvecq for buffering instead of a folioq David Howells
2026-11-07 18:51   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 11/15] smbdirect: Support ITER_BVECQ in smbdirect_map_sges_from_iter() David Howells
2026-11-07 18:57   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 12/15] netfs: Switch folioq to bvecq David Howells
2026-11-07 19:25   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 13/15] smbdirect: Remove support for ITER_FOLIOQ from smbdirect_map_sges_from_iter() David Howells
2026-11-07 19:29   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 14/15] iov_iter: Remove ITER_FOLIOQ David Howells
2026-11-07 19:31   ` sashiko-bot
2026-11-07 16:08 ` [PATCH v16 15/15] netfs: Remove folio_queue David Howells
2026-11-07 19:35   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-203072@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=anna@kernel.org \
    --cc=cel@kernel.org \
    --cc=dhowells@redhat.com \
    --cc=jlayton@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=v9fs@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).