[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <57264a45aabcf8d789278e09da5db297d2e6b192.1733901374.git.ojaswin@linux.ibm.com>
Date: Wed, 11 Dec 2024 13:27:55 +0530
From: Ojaswin Mujoo <ojaswin@...ux.ibm.com>
To: linux-ext4@...r.kernel.org, "Theodore Ts'o" <tytso@....edu>
Cc: Ritesh Harjani <ritesh.list@...il.com>, linux-kernel@...r.kernel.org,
"Darrick J . Wong" <djwong@...nel.org>, linux-fsdevel@...r.kernel.org,
John Garry <john.g.garry@...cle.com>, dchinner@...hat.com,
Nirjhar Roy <nirjhar@...ux.ibm.com>
Subject: [RFC v2 6/6] ext4: make extsize work with EOF allocations
Make extsize hints work with EOF allocations. We deviate from XFS here
because in case we have blocks left past EOF, we don't truncate them.
There are 2 main reasons:
1. Since the user is opting for extsize allocations, chances are
that they will use the blocks in future.
2. If we start truncating all EOF blocks in ext4_release_file like
XFS, then we will have to always truncate blocks even if they
have been intentionally preallocated using fallocate w/ KEEP_SIZE
which might cause confusion for users. This is mainly because
ext4 doesn't have a way to distinguish if the blocks beyond EOF
have been allocated intentionally. We can work around this by
using an ondisk inode flag like XFS (XFS_DIFLAG_PREALLOC) but
that would be an overkill. It's much simpler to just let the EOF
blocks stick around.
NOTE:
One thing that changes in this patch is that for direct IO we need to
pass the EXT4_GET_BLOCKS_IO_CREATE_EXT even if we are allocating beyond
i_size.
Signed-off-by: Ojaswin Mujoo <ojaswin@...ux.ibm.com>
---
fs/ext4/inode.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index d511282ebdcc..d292e39a050a 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -756,7 +756,6 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
* ext4_extents.h here?
*/
int max_unwrit_len = ((1UL << 15) - 1);
- loff_t end;
align = orig_map->m_lblk % extsize;
len = orig_map->m_len + align;
@@ -765,18 +764,6 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
extsize_map.m_len =
max_t(unsigned int, roundup_pow_of_two(len), extsize);
- /*
- * For now allocations beyond EOF don't use extsize hints so
- * that we can avoid dealing with extra blocks allocated past
- * EOF. We have inode lock since extsize allocations are
- * non-delalloc so i_size can be accessed safely
- */
- end = (extsize_map.m_lblk + (loff_t)extsize_map.m_len) << inode->i_blkbits;
- if (end > inode->i_size) {
- flags = orig_flags & ~EXT4_GET_BLOCKS_EXTSIZE;
- goto set_map;
- }
-
/* Fallback to normal allocation if we go beyond max len */
if (extsize_map.m_len >= max_unwrit_len) {
flags = orig_flags & ~EXT4_GET_BLOCKS_EXTSIZE;
@@ -3641,10 +3628,13 @@ static int ext4_iomap_alloc(struct inode *inode, struct ext4_map_blocks *map,
* i_disksize out to i_size. This could be beyond where direct I/O is
* happening and thus expose allocated blocks to direct I/O reads.
*
- * NOTE for extsize hints: We only support it for writes inside
- * EOF (for now) to not have to deal with blocks past EOF
+ * NOTE: For extsize hint based EOF allocations, we still need
+ * IO_CREATE_EXT flag because we will be allocating more than the write
+ * hence the extra blocks need to be marked unwritten and split before
+ * the I/O.
*/
- else if (((loff_t)map->m_lblk << blkbits) >= i_size_read(inode))
+ else if (((loff_t)map->m_lblk << blkbits) >= i_size_read(inode) &&
+ !ext4_should_use_extsize(inode))
m_flags = EXT4_GET_BLOCKS_CREATE;
else if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
m_flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
--
2.43.5
Powered by blists - more mailing lists