ext4: make ext4_map_blocks() distinguish delalloc only extent
authorZhang Yi <yi.zhang@huawei.com>
Sat, 27 Jan 2024 01:58:04 +0000 (09:58 +0800)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 2 Feb 2024 04:59:21 +0000 (23:59 -0500)
Add a new map flag EXT4_MAP_DELAYED to indicate the mapping range is a
delayed allocated only (not unwritten) one, and making
ext4_map_blocks() can distinguish it, no longer mixing it with holes.

Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20240127015825.1608160-6-yi.zhang@huaweicloud.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/inode.c

index 786b685..023571f 100644 (file)
@@ -252,8 +252,10 @@ struct ext4_allocation_request {
 #define EXT4_MAP_MAPPED                BIT(BH_Mapped)
 #define EXT4_MAP_UNWRITTEN     BIT(BH_Unwritten)
 #define EXT4_MAP_BOUNDARY      BIT(BH_Boundary)
+#define EXT4_MAP_DELAYED       BIT(BH_Delay)
 #define EXT4_MAP_FLAGS         (EXT4_MAP_NEW | EXT4_MAP_MAPPED |\
-                                EXT4_MAP_UNWRITTEN | EXT4_MAP_BOUNDARY)
+                                EXT4_MAP_UNWRITTEN | EXT4_MAP_BOUNDARY |\
+                                EXT4_MAP_DELAYED)
 
 struct ext4_map_blocks {
        ext4_fsblk_t m_pblk;
index c5b54fb..7669d15 100644 (file)
@@ -4076,8 +4076,11 @@ again:
                /*
                 * The delalloc extent containing lblk, it must have been
                 * added after ext4_map_blocks() checked the extent status
-                * tree, adjust the length to the delalloc extent's after
-                * lblk.
+                * tree so we are not holding i_rwsem and delalloc info is
+                * only stabilized by i_data_sem we are going to release
+                * soon. Don't modify the extent status tree and report
+                * extent as a hole, just adjust the length to the delalloc
+                * extent's after lblk.
                 */
                len = es.es_lblk + es.es_len - lblk;
                return len;
index af205b4..60f0d2d 100644 (file)
@@ -515,6 +515,8 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
                        map->m_len = retval;
                } else if (ext4_es_is_delayed(&es) || ext4_es_is_hole(&es)) {
                        map->m_pblk = 0;
+                       map->m_flags |= ext4_es_is_delayed(&es) ?
+                                       EXT4_MAP_DELAYED : 0;
                        retval = es.es_len - (map->m_lblk - es.es_lblk);
                        if (retval > map->m_len)
                                retval = map->m_len;