All of lore.kernel.org
 help / color / mirror / Atom feed
From: Namjae Jeon <linkinjeon@kernel.org>
To: hyc.lee@gmail.com
Cc: linux-fsdevel@vger.kernel.org, Namjae Jeon <linkinjeon@kernel.org>
Subject: [PATCH] ntfs: use page allocation for resident attribute inline data
Date: Wed, 22 Apr 2026 19:46:27 +0900	[thread overview]
Message-ID: <20260422104627.8193-1-linkinjeon@kernel.org> (raw)

The current kmemdup() based allocation for IOMAP_INLINE can result in
inline_data pointer having a non-zero page offset. This causes
iomap_inline_data_valid() to fail the check:

    iomap->length <= PAGE_SIZE - offset_in_page(iomap->inline_data)

and triggers the kernel BUG at fs/iomap/buffered-io.c:1061.

This particularly affects workloads with frequent small file access
(e.g. Firefox Nightly profile on NTFS with bind mount) when using the
new ntfs. This fix this by allocating a full page with alloc_page() so that
page_address() always returns a page-aligned address.

Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
---
 fs/ntfs/iomap.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/fs/ntfs/iomap.c b/fs/ntfs/iomap.c
index 3d1458dea90f..74a4d3e971f4 100644
--- a/fs/ntfs/iomap.c
+++ b/fs/ntfs/iomap.c
@@ -89,6 +89,7 @@ static int ntfs_read_iomap_begin_resident(struct inode *inode, loff_t offset, lo
 	u32 attr_len;
 	int err = 0;
 	char *kattr;
+	struct page *ipage;
 
 	if (NInoAttr(ni))
 		base_ni = ni->ext.base_ntfs_ino;
@@ -129,15 +130,18 @@ static int ntfs_read_iomap_begin_resident(struct inode *inode, loff_t offset, lo
 
 	kattr = (u8 *)ctx->attr + le16_to_cpu(ctx->attr->data.resident.value_offset);
 
-	iomap->inline_data = kmemdup(kattr, attr_len, GFP_KERNEL);
-	if (!iomap->inline_data) {
+	ipage = alloc_page(GFP_NOFS | __GFP_ZERO);
+	if (!ipage) {
 		err = -ENOMEM;
 		goto out;
 	}
 
+	memcpy(page_address(ipage), kattr, attr_len);
 	iomap->type = IOMAP_INLINE;
+	iomap->inline_data = page_address(ipage);
 	iomap->offset = 0;
 	iomap->length = attr_len;
+	iomap->private = ipage;
 
 out:
 	if (ctx)
@@ -285,8 +289,11 @@ static int ntfs_read_iomap_begin(struct inode *inode, loff_t offset, loff_t leng
 static int ntfs_read_iomap_end(struct inode *inode, loff_t pos, loff_t length,
 		ssize_t written, unsigned int flags, struct iomap *iomap)
 {
-	if (iomap->type == IOMAP_INLINE)
-		kfree(iomap->inline_data);
+	if (iomap->type == IOMAP_INLINE) {
+		struct page *ipage = iomap->private;
+
+		put_page(ipage);
+	}
 
 	return written;
 }
@@ -652,6 +659,7 @@ static int ntfs_write_iomap_begin_resident(struct inode *inode, loff_t offset,
 	u32 attr_len;
 	int err = 0;
 	char *kattr;
+	struct page *ipage;
 
 	ctx = ntfs_attr_get_search_ctx(ni, NULL);
 	if (!ctx) {
@@ -672,16 +680,19 @@ static int ntfs_write_iomap_begin_resident(struct inode *inode, loff_t offset,
 	attr_len = le32_to_cpu(a->data.resident.value_length);
 	kattr = (u8 *)a + le16_to_cpu(a->data.resident.value_offset);
 
-	iomap->inline_data = kmemdup(kattr, attr_len, GFP_KERNEL);
-	if (!iomap->inline_data) {
+	ipage = alloc_page(GFP_NOFS | __GFP_ZERO);
+	if (!ipage) {
 		err = -ENOMEM;
 		goto out;
 	}
 
+	memcpy(page_address(ipage), kattr, attr_len);
 	iomap->type = IOMAP_INLINE;
+	iomap->inline_data = page_address(ipage);
 	iomap->offset = 0;
 	/* iomap requires there is only one INLINE_DATA extent */
 	iomap->length = attr_len;
+	iomap->private = ipage;
 
 out:
 	if (ctx)
@@ -771,6 +782,7 @@ static int ntfs_write_iomap_end_resident(struct inode *inode, loff_t pos,
 	u32 attr_len;
 	int err;
 	char *kattr;
+	struct page *ipage = iomap->private;
 
 	mutex_lock(&ni->mrec_lock);
 	ctx = ntfs_attr_get_search_ctx(ni, NULL);
@@ -799,7 +811,7 @@ static int ntfs_write_iomap_end_resident(struct inode *inode, loff_t pos,
 	mark_mft_record_dirty(ctx->ntfs_ino);
 err_out:
 	ntfs_attr_put_search_ctx(ctx);
-	kfree(iomap->inline_data);
+	put_page(ipage);
 	mutex_unlock(&ni->mrec_lock);
 	return written;
 
-- 
2.25.1


             reply	other threads:[~2026-04-22 10:46 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-22 10:46 Namjae Jeon [this message]
2026-04-22 12:55 ` [PATCH] ntfs: use page allocation for resident attribute inline data Matthew Wilcox
2026-04-22 14:35   ` Namjae Jeon
2026-04-22 15:28     ` Darrick J. Wong
2026-04-22 15:36       ` Gao Xiang
2026-04-23  5:20         ` Namjae Jeon
2026-04-23  5:49   ` Christoph Hellwig

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=20260422104627.8193-1-linkinjeon@kernel.org \
    --to=linkinjeon@kernel.org \
    --cc=hyc.lee@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    /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.