All of lore.kernel.org
 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 v17 08/17] netfs: Explicitly pass tail padding to netfs_writeback_single()
Date: Wed, 11 Nov 2026 23:17:54 +0000	[thread overview]
Message-ID: <sashiko-outbox-209850@kernel.org> (raw)
In-Reply-To: <20261111203034.2126314-9-dhowells@redhat.com>

Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] afs: i_size exceeding directory_size in writepages triggers
  WARN_ON_ONCE()
--

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

netfs: Explicitly pass tail padding to netfs_writeback_single()

This commit adds an explicit content length parameter to
netfs_writeback_single() so the caller provides a padded buffer via the
iterator while specifying the actual content size separately, and updates
AFS directory and symlink writeback to zero tail padding and pass both
sizes.

> diff --git a/fs/afs/dir.c b/fs/afs/dir.c
> index 75f8f70cfeff0..51c158d8f723f 100644
> --- a/fs/afs/dir.c
> +++ b/fs/afs/dir.c
[ ... ]
> @@ -2228,9 +2236,10 @@ static int afs_dir_writepages(struct address_space *mapping,
>  	}
>  
>  	if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
> -		iov_iter_folio_queue(&iter, ITER_SOURCE, dvnode->directory, 0, 0,
> -				     i_size_read(&dvnode->netfs.inode));
> -		ret = netfs_writeback_single(mapping, wbc, &iter);
> +		iov_iter_folio_queue(&iter, ITER_SOURCE, dvnode->directory,
> +				     0, 0, dvnode->directory_size);
> +		ret = netfs_writeback_single(mapping, wbc, &iter,
> +					     i_size_read(&dvnode->netfs.inode));
>  		if (ret == 1)
>  			ret = 0; /* Skipped write due to lock conflict. */
>  	}
> diff --git a/fs/afs/symlink.c b/fs/afs/symlink.c
> index a1dbd552ddff0..c18e4f8064234 100644
> --- a/fs/afs/symlink.c
> +++ b/fs/afs/symlink.c
[ ... ]
> @@ -247,9 +251,17 @@ int afs_symlink_writepages(struct address_space *mapping,
>  
>  	if (vnode->directory &&
>  	    atomic64_read(&vnode->cb_expires_at) != AFS_NO_CB_PROMISE) {
> +		size_t i_size = i_size_read(&vnode->netfs.inode);
> +
> +		if (i_size < vnode->directory_size) {
> +			iov_iter_folio_queue(&iter, ITER_DEST, vnode->directory, 0, 0,
> +					     vnode->directory_size);
> +			iov_iter_advance(&iter, i_size);
> +			iov_iter_zero(vnode->directory_size - i_size, &iter);
> +		}
>  		iov_iter_folio_queue(&iter, ITER_SOURCE, vnode->directory, 0, 0,
> -				     i_size_read(&vnode->netfs.inode));
> -		ret = netfs_writeback_single(mapping, wbc, &iter);
> +				     vnode->directory_size);
> +		ret = netfs_writeback_single(mapping, wbc, &iter, i_size);
>  	}
>  
>  	if (ret == 0) {
> diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c
> index b8237e1314d8a..e041023811ed0 100644
> --- a/fs/netfs/write_issue.c
> +++ b/fs/netfs/write_issue.c
[ ... ]
> @@ -747,26 +747,33 @@ static int netfs_write_folio_single(struct netfs_io_request *wreq,
>  int netfs_writeback_single(struct address_space *mapping,
>  			   struct writeback_control *wbc,
> -			   struct iov_iter *iter)
> +			   struct iov_iter *iter, size_t len)
>  {
>  	struct netfs_io_request *wreq;
>  	struct netfs_inode *ictx = netfs_inode(mapping->host);
>  	struct folio_queue *fq;
> -	size_t size = iov_iter_count(iter);
> +	size_t size = len;
>  	int ret;
>  
>  	if (WARN_ON_ONCE(!iov_iter_is_folioq(iter)))
>  		return -EIO;
> +	if (WARN_ON_ONCE(iov_iter_count(iter) < len))
> +		return -EIO;

[Severity: Medium]
Can i_size exceed directory_size in afs_dir_writepages() or
afs_symlink_writepages() and trigger the new
WARN_ON_ONCE(iov_iter_count(iter) < len) in netfs_writeback_single()?

In afs_dir_writepages(), dvnode->validate_lock is held shared while
checking AFS_VNODE_DIR_VALID and reading dvnode->directory_size and
inode->i_size.  A concurrent RPC completion such as
afs_do_lookup_success() calls afs_vnode_commit_status() ->
afs_apply_status() under cb_lock and i_lock without holding validate_lock.
If a third party grew the directory on the server beyond
dvnode->directory_size, afs_apply_status() clears AFS_VNODE_DIR_VALID and
updates inode->i_size without updating dvnode->directory_size:

CPU0                              CPU1
afs_dir_writepages()
  down_read(&dvnode->validate_lock)
  test_bit(AFS_VNODE_DIR_VALID, ...)
                                  afs_vnode_commit_status()
                                    afs_apply_status()
                                      afs_invalidate_dir()
                                        clear_bit(AFS_VNODE_DIR_VALID, ...)
                                      i_size_write(inode, status->size)
  iov_iter_folio_queue(...,
    dvnode->directory_size)
  netfs_writeback_single(...,
    i_size_read(...))
    WARN_ON_ONCE(iov_iter_count(iter) < len)  <-- triggers warning

Even after commit "afs: Use a bvecq to hold dir content rather than
folioq" later in this series reads i_size and directory_size under
dvnode->cb_lock, test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) is still
checked before acquiring cb_lock, so the same race window remains.

Similarly, afs_do_read_symlink() allocates vnode->directory to PAGE_SIZE.
If the server returns a symlink status with size > PAGE_SIZE in
netfs_read_single() (or a concurrent status update grows inode->i_size
past PAGE_SIZE and sets AFS_VNODE_ZAP_DATA), netfs_rreq_assess_single()
still marks the inode dirty before afs_do_read_symlink() returns -EFBIG.
When afs_symlink_writepages() runs, it does not check AFS_VNODE_ZAP_DATA
or whether i_size <= vnode->directory_size, hitting the same
WARN_ON_ONCE() and returning -EIO (which also skips freeing
vnode->directory until eviction).

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

  reply	other threads:[~2026-11-11 23:17 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-11 20:30 [PATCH v17 00/17] netfs, iov_iter: Use a chain of bio_vec arrays instead of folio_queue David Howells
2026-11-11 20:30 ` [PATCH v17 01/17] iov_iter: Fix kunit test to remove __init and __refdata marks David Howells
2026-11-11 21:23   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 02/17] Add a function to kmap one page of a multipage bio_vec David Howells
2026-11-11 21:26   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 03/17] iov_iter: Add a segmented queue of bio_vec[] David Howells
2026-11-11 21:46   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 04/17] netfs: Add some tools for managing bvecq chains David Howells
2026-11-11 22:17   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 05/17] iov_iter: Add an API document for the bvecq structure David Howells
2026-11-11 22:22   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 06/17] iov_iter: Add a bvecq kunit test David Howells
2026-11-11 22:31   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 07/17] afs: Fix an inconsistency in the symlink code David Howells
2026-11-11 22:45   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 08/17] netfs: Explicitly pass tail padding to netfs_writeback_single() David Howells
2026-11-11 23:17   ` sashiko-bot [this message]
2026-11-11 20:30 ` [PATCH v17 09/17] netfs: Change netfs_writeback_single() to not look inside the iterator David Howells
2026-11-11 23:36   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 10/17] netfs: Pass the write length to request creation where appropriate David Howells
2026-11-11 23:39   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 11/17] afs: Use a bvecq to hold dir content rather than folioq David Howells
2026-11-12  0:06   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 12/17] cifs: Use a bvecq for buffering instead of a folioq David Howells
2026-11-12  0:20   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 13/17] smbdirect: Support ITER_BVECQ in smbdirect_map_sges_from_iter() David Howells
2026-11-12  0:27   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 14/17] netfs: Switch folioq to bvecq David Howells
2026-11-12  1:03   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 15/17] smbdirect: Remove support for ITER_FOLIOQ from smbdirect_map_sges_from_iter() David Howells
2026-11-12  1:06   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 16/17] iov_iter: Remove ITER_FOLIOQ David Howells
2026-11-12  1:11   ` sashiko-bot
2026-11-11 20:30 ` [PATCH v17 17/17] netfs: Remove folio_queue David Howells
2026-11-12  1:14   ` 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-209850@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.