ext4: remove extent cache entries when truncating inline data

Conditionally remove all cached extents belonging to an inode
when truncating its inline data. It's only necessary to attempt to
remove cached extents when a conversion from inline to extent storage
has been initiated (!EXT4_STATE_MAY_INLINE_DATA). This avoids
unnecessary es lock overhead in the more common inline case.

Signed-off-by: Eric Whitney <enwlinux@gmail.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Link: https://lore.kernel.org/r/20210819144927.25163-2-enwlinux@gmail.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>

authored by Eric Whitney and committed by Theodore Ts'o 0add491d 11ef08c9

+19
+19
fs/ext4/inline.c
··· 7 7 #include <linux/iomap.h> 8 8 #include <linux/fiemap.h> 9 9 #include <linux/iversion.h> 10 + #include <linux/backing-dev.h> 10 11 11 12 #include "ext4_jbd2.h" 12 13 #include "ext4.h" ··· 1919 1918 EXT4_I(inode)->i_disksize = i_size; 1920 1919 1921 1920 if (i_size < inline_size) { 1921 + /* 1922 + * if there's inline data to truncate and this file was 1923 + * converted to extents after that inline data was written, 1924 + * the extent status cache must be cleared to avoid leaving 1925 + * behind stale delayed allocated extent entries 1926 + */ 1927 + if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { 1928 + retry: 1929 + err = ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS); 1930 + if (err == -ENOMEM) { 1931 + cond_resched(); 1932 + congestion_wait(BLK_RW_ASYNC, HZ/50); 1933 + goto retry; 1934 + } 1935 + if (err) 1936 + goto out_error; 1937 + } 1938 + 1922 1939 /* Clear the content in the xattr space. */ 1923 1940 if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) { 1924 1941 if ((err = ext4_xattr_ibody_find(inode, &i, &is)) != 0)