ext4: reorder map.m_flags checks within ext4_iomap_begin()
authorMatthew Bobrowski <mbobrowski@mbobrowski.org>
Tue, 5 Nov 2019 11:58:55 +0000 (22:58 +1100)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 5 Nov 2019 16:31:39 +0000 (11:31 -0500)
For the direct I/O changes that follow in this patch series, we need
to accommodate for the case where the block mapping flags passed
through to ext4_map_blocks() result in m_flags having both
EXT4_MAP_MAPPED and EXT4_MAP_UNWRITTEN bits set. In order for any
allocated unwritten extents to be converted correctly in the
->end_io() handler, the iomap->type must be set to IOMAP_UNWRITTEN for
cases where the EXT4_MAP_UNWRITTEN bit has been set within
m_flags. Hence the reason why we need to reshuffle this conditional
statement around.

This change is a no-op for DAX as the block mapping flags passed
through to ext4_map_blocks() i.e. EXT4_GET_BLOCKS_CREATE_ZERO never
results in both EXT4_MAP_MAPPED and EXT4_MAP_UNWRITTEN being set at
once.

Signed-off-by: Matthew Bobrowski <mbobrowski@mbobrowski.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ritesh Harjani <riteshh@linux.ibm.com>
Link: https://lore.kernel.org/r/1309ad80d31a637b2deed55a85283d582a54a26a.1572949325.git.mbobrowski@mbobrowski.org
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/inode.c

index 0d8971b819e99577386ed7f23143e30e61b21a81..e4b0722717b3cfbf15373906166bfbdda1ef8ece 100644 (file)
@@ -3577,10 +3577,20 @@ retry:
                iomap->type = delalloc ? IOMAP_DELALLOC : IOMAP_HOLE;
                iomap->addr = IOMAP_NULL_ADDR;
        } else {
-               if (map.m_flags & EXT4_MAP_MAPPED) {
-                       iomap->type = IOMAP_MAPPED;
-               } else if (map.m_flags & EXT4_MAP_UNWRITTEN) {
+               /*
+                * Flags passed into ext4_map_blocks() for direct I/O writes
+                * can result in m_flags having both EXT4_MAP_MAPPED and
+                * EXT4_MAP_UNWRITTEN bits set. In order for any allocated
+                * unwritten extents to be converted into written extents
+                * correctly within the ->end_io() handler, we need to ensure
+                * that the iomap->type is set appropriately. Hence the reason
+                * why we need to check whether EXT4_MAP_UNWRITTEN is set
+                * first.
+                */
+               if (map.m_flags & EXT4_MAP_UNWRITTEN) {
                        iomap->type = IOMAP_UNWRITTEN;
+               } else if (map.m_flags & EXT4_MAP_MAPPED) {
+                       iomap->type = IOMAP_MAPPED;
                } else {
                        WARN_ON_ONCE(1);
                        return -EIO;