mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ojaswin Mujoo <ojaswin@linux.ibm.com>
To: linux-ext4@vger.kernel.org, "Theodore Ts'o" <tytso@mit.edu>
Cc: Jan Kara <jack@suse.cz>, Baokun Li <libaokun1@huawei.com>,
	Ritesh Harjani <ritesh.list@gmail.com>,
	Zhang Yi <yi.zhang@huawei.com>,
	linux-kernel@vger.kernel.org,
	"Darrick J . Wong" <djwong@kernel.org>,
	linux-fsdevel@vger.kernel.org
Subject: [RFC v4 7/7] ext4: add ext4_map_blocks_extsize() wrapper to handle overwrites
Date: Mon, 21 Jul 2025 02:27:33 +0530	[thread overview]
Message-ID: <4531e266d4b26b1c3d51da732ff305869e56dcf3.1753044253.git.ojaswin@linux.ibm.com> (raw)
In-Reply-To: <cover.1753044253.git.ojaswin@linux.ibm.com>

Currently, with the extsize hints, if we consider a scenario where
the hint is set to 16k and we do a write of (0,4k) we get the below
mapping:

[  4k written ] [       12k unwritten      ]

Now, if we do a (4k,4k) write, ext4_map_blocks will again try for a
extsize aligned write, adjust the range to (0, 16k) and then run into
issues since the new range is already has a mapping in it. Although this
does not lead to a failure since we eventually fallback to a non extsize
allocation, this is not a good approach.

Hence, implement a wrapper over ext4_map_blocks() which detects if a
mapping already exists for an extsize based allocation and then reuses
the same mapping.

In case the mapping completely covers the original request we simply
disable extsize allocation and call map_blocks to correctly process the
mapping and set the map flags. Otherwise, if there is a hole or partial
mapping, then we just let ext4_map_blocks() handle the allocation.

Signed-off-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
 fs/ext4/inode.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 43 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 1b60e45a593e..010ca890b29c 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -772,6 +772,41 @@ static inline void ext4_extsize_reset_map(struct ext4_map_blocks *map,
 	map->m_flags = 0;
 }
 
+static int ext4_map_blocks_extsize(handle_t *handle, struct inode *inode,
+		    struct ext4_map_blocks *map, int flags)
+{
+	int orig_mlen = map->m_len;
+	int ret = 0;
+	int tmp_flags;
+
+	WARN_ON(!ext4_inode_get_extsize(EXT4_I(inode)));
+	WARN_ON(!(flags & EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT));
+
+	/*
+	 * First check if there are any existing allocations
+	 */
+	ret = ext4_map_blocks(handle, inode, map, 0);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * the present mapping fully covers the requested range. In this
+	 * case just go for a non extsize based allocation. Note that we won't
+	 * really be allocating new blocks but the call to ext4_map_blocks is
+	 * important to ensure things like extent splitting and proper map flags
+	 * are taken care of. For all other cases, just let ext4_map_blocks handle
+	 * the allocations
+	 */
+	if (ret > 0 && map->m_len == orig_mlen)
+		tmp_flags = flags & ~EXT4_GET_BLOCKS_EXTSIZE;
+	else
+		tmp_flags = flags;
+
+	ret = ext4_map_blocks(handle, inode, map, tmp_flags);
+
+	return ret;
+}
+
 /*
  * The ext4_map_blocks() function tries to look up the requested blocks,
  * and returns if the blocks are already mapped.
@@ -1153,8 +1188,12 @@ static int _ext4_get_block(struct inode *inode, sector_t iblock,
 	map.m_lblk = iblock;
 	map.m_len = orig_mlen;
 
-	ret = ext4_map_blocks(ext4_journal_current_handle(), inode, &map,
-			      flags);
+	if ((flags & EXT4_GET_BLOCKS_CREATE) && ext4_should_use_extsize(inode))
+		ret = ext4_map_blocks_extsize(ext4_journal_current_handle(), inode,
+				      &map, flags);
+	else
+		ret = ext4_map_blocks(ext4_journal_current_handle(), inode,
+				      &map, flags);
 	if (ret > 0) {
 		map_bh(bh, inode->i_sb, map.m_pblk);
 		ext4_update_bh_state(bh, map.m_flags);
@@ -4016,6 +4055,8 @@ static int ext4_iomap_alloc(struct inode *inode, struct ext4_map_blocks *map,
 	if (flags & IOMAP_ATOMIC)
 		ret = ext4_map_blocks_atomic_write(handle, inode, map, m_flags,
 						   &force_commit);
+	else if (ext4_should_use_extsize(inode))
+		ret = ext4_map_blocks_extsize(handle, inode, map, m_flags);
 	else
 		ret = ext4_map_blocks(handle, inode, map, m_flags);
 
-- 
2.49.0


      parent reply	other threads:[~2025-07-20 20:58 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-20 20:57 [RFC v4 0/7] ext4: Add extsize support Ojaswin Mujoo
2025-07-20 20:57 ` [RFC v4 1/7] ext4: add aligned allocation hint in mballoc Ojaswin Mujoo
2025-07-20 20:57 ` [RFC v4 2/7] ext4: allow inode preallocation for aligned alloc Ojaswin Mujoo
2025-07-20 20:57 ` [RFC v4 3/7] ext4: support for extsize hint using FS_IOC_FS(GET/SET)XATTR Ojaswin Mujoo
2025-07-20 20:57 ` [RFC v4 4/7] ext4: pass lblk and len explicitly to ext4_split_extent*() Ojaswin Mujoo
2025-07-20 20:57 ` [RFC v4 5/7] ext4: add extsize hint support Ojaswin Mujoo
2025-07-20 20:57 ` [RFC v4 6/7] ext4: make extsize work with EOF allocations Ojaswin Mujoo
2025-07-20 20:57 ` Ojaswin Mujoo [this message]

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=4531e266d4b26b1c3d51da732ff305869e56dcf3.1753044253.git.ojaswin@linux.ibm.com \
    --to=ojaswin@linux.ibm.com \
    --cc=djwong@kernel.org \
    --cc=jack@suse.cz \
    --cc=libaokun1@huawei.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ritesh.list@gmail.com \
    --cc=tytso@mit.edu \
    --cc=yi.zhang@huawei.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®