All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hyunchul Lee <hyc.lee@gmail.com>
To: Hongling Zeng <zenghongling@kylinos.cn>
Cc: linkinjeon@kernel.org, ntfs@lists.linux.dev,
	linux-kernel@vger.kernel.org, zhongling0719@126.com
Subject: Re: [PATCH 2/2] ntfs: fix a self-deadlock on writes to non-resident named streams
Date: Thu, 29 Oct 2026 13:28:33 +0900	[thread overview]
Message-ID: <auLLcf9BK7-rIGPz@hyunchul-PC02> (raw)
In-Reply-To: <20261028080656.1027283-2-zenghongling@kylinos.cn>

On Wed, Oct 28, 2026 at 04:06:56PM +0800, Hongling Zeng wrote:
> The stream write ioctl holds the stream mapping's invalidate lock
> across ntfs_inode_attr_pwrite(), which calls
> ntfs_extend_initialized_size() for named streams, and that function
> takes the same lock again, before the check that could skip the
> extension.  A write to a non-resident named stream through
> NTFS_IOC_STREAM_WRITE deadlocks on itself.
> 
> The ioctl is the only caller that reaches the named stream branch of
> ntfs_inode_attr_pwrite(), and it always holds the lock there, so
> split off __ntfs_extend_initialized_size(), which expects the caller
> to hold the invalidate lock, and call it from that branch.  The write
> and mmap paths keep taking the lock themselves.
> 
> Fixes: 3f11c48d4f94 ("ntfs: add pathname access for named streams")
> Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>

Looks good to me.

Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
> ---
>  fs/ntfs/inode.c | 30 +++++++++++++++++++++++++-----
>  1 file changed, 25 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
> index ac13e8776909..9275ebfebe3d 100644
> --- a/fs/ntfs/inode.c
> +++ b/fs/ntfs/inode.c
> @@ -2554,8 +2554,12 @@ int ntfs_show_options(struct seq_file *sf, struct dentry *root)
>  	return 0;
>  }
>  
> -int ntfs_extend_initialized_size(struct inode *vi, const loff_t offset,
> -				 const loff_t new_size)
> +/*
> + * The caller must hold @vi's mapping invalidate lock.
> + */
> +static int __ntfs_extend_initialized_size(struct inode *vi,
> +					  const loff_t offset,
> +					  const loff_t new_size)
>  {
>  	struct ntfs_inode *ni = NTFS_I(vi);
>  	struct ntfs_inode *mrec_ni = ntfs_base_inode(ni);
> @@ -2563,10 +2567,11 @@ int ntfs_extend_initialized_size(struct inode *vi, const loff_t offset,
>  	unsigned long flags;
>  	int err = 0;
>  
> +	lockdep_assert_held_write(&vi->i_mapping->invalidate_lock);
> +
>  	if (!NInoNonResident(ni))
>  		return -EINVAL;
>  
> -	filemap_invalidate_lock(vi->i_mapping);
>  	read_lock_irqsave(&ni->size_lock, flags);
>  	old_init_size = ni->initialized_size;
>  	read_unlock_irqrestore(&ni->size_lock, flags);
> @@ -2600,6 +2605,16 @@ int ntfs_extend_initialized_size(struct inode *vi, const loff_t offset,
>  	err = ntfs_attr_set_initialized_size(ni, new_size);
>  	mutex_unlock(&mrec_ni->mrec_lock);
>  out:
> +	return err;
> +}
> +
> +int ntfs_extend_initialized_size(struct inode *vi, const loff_t offset,
> +				 const loff_t new_size)
> +{
> +	int err;
> +
> +	filemap_invalidate_lock(vi->i_mapping);
> +	err = __ntfs_extend_initialized_size(vi, offset, new_size);
>  	filemap_invalidate_unlock(vi->i_mapping);
>  	return err;
>  }
> @@ -4085,8 +4100,13 @@ s64 ntfs_inode_attr_pwrite(struct inode *vi, s64 pos, s64 count, u8 *buf, bool s
>  	mutex_unlock(&mrec_ni->mrec_lock);
>  	/* Attribute writes bypass iomap's delayed-allocation preparation. */
>  	if (ntfs_inode_is_named_stream(ni)) {
> -		/* A failed write must not expose any newly initialized data. */
> -		ret = ntfs_extend_initialized_size(vi, pos + count, pos + count);
> +		/*
> +		 * A failed write must not expose any newly initialized
> +		 * data.  The stream ioctl caller holds the mapping
> +		 * invalidate lock.
> +		 */
> +		ret = __ntfs_extend_initialized_size(vi, pos + count,
> +				pos + count);
>  		modified |= ni->initialized_size != old_init_size;
>  		if (!ret)
>  			ret = ntfs_attr_fallocate(ni, pos, count, true);
> -- 
> 2.25.1
> 

-- 
Thanks,
Hyunchul

  parent reply	other threads:[~2026-10-29  4:28 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-28  8:06 [PATCH 1/2] ntfs: keep the file size on a failed initialized-size extension Hongling Zeng
2026-10-28  8:06 ` [PATCH 2/2] ntfs: fix a self-deadlock on writes to non-resident named streams Hongling Zeng
2026-10-28  8:41   ` liubaolin
2026-10-29  4:28   ` Hyunchul Lee [this message]
2026-10-29  8:52   ` Namjae Jeon
2026-10-28  8:41 ` [PATCH 1/2] ntfs: keep the file size on a failed initialized-size extension liubaolin
2026-10-29  4:28 ` Hyunchul Lee
2026-10-29  8:52 ` Namjae Jeon

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=auLLcf9BK7-rIGPz@hyunchul-PC02 \
    --to=hyc.lee@gmail.com \
    --cc=linkinjeon@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ntfs@lists.linux.dev \
    --cc=zenghongling@kylinos.cn \
    --cc=zhongling0719@126.com \
    /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.