hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IAAPPE
--------------------------------
After commit 244adf6426ee ("ext4: make dioread_nolock the default"), writeback for ext4 mounted with dioread_nolock will first start journal, then get a unwritten extent, change i_size and mark inode dirty. Besides, we won't call ext4_jbd2_inode_add_write since the extent is unwritten, so when jbd2 try do commit journal, we will not wait stable data. And combine with a poweroff before data writepage success, we will find a file with size has already been update but the content still keep zero since the extent is unwritten. This is really intolerable for some production. So we need give a choice to decided does we really need default enable dioread_nolock.
Back to why we default enable dioread_nolock, the upper commit give some description, the most import problem is that dioread parallel with fault write(and writepage for fault write has alloc the block) will read some stale data. But the case dioread parallel with fault write is really rarely used, so it seems little impact now.
We now give a more flexible way to control how to default enable dioread_nolock or not: - set CONFIG_EXT4_DIOREAD_NOLOCK_PARAM to N, still default enable dioread_nlock - set CONFIG_EXT4_DIOREAD_NOLOCK_PARAM to Y, default disable dioread_nolock, also we give a module param default_dioread_nolock to control it, it you want default enable dioread_nlock, set default_dioread_nolock to 1.
Fixes: 244adf6426ee ("ext4: make dioread_nolock the default") Signed-off-by: Yang Erkun yangerkun@huawei.com --- arch/arm64/configs/openeuler_defconfig | 1 + arch/x86/configs/openeuler_defconfig | 1 + fs/ext4/Kconfig | 8 ++++++++ fs/ext4/super.c | 19 +++++++++++++++++++ 4 files changed, 29 insertions(+)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 072d26fcc238..650fe88cbb04 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -6954,6 +6954,7 @@ CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y # CONFIG_EXT4_DEBUG is not set CONFIG_EXT4_ERROR_REPORT=y +# CONFIG_EXT4_DIOREAD_NOLOCK_PARAM is not set CONFIG_JBD2=m # CONFIG_JBD2_DEBUG is not set CONFIG_FS_MBCACHE=m diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index f86f22d8b397..b3403ba040bf 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -8117,6 +8117,7 @@ CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y # CONFIG_EXT4_DEBUG is not set CONFIG_EXT4_ERROR_REPORT=y +# CONFIG_EXT4_DIOREAD_NOLOCK_PARAM is not set CONFIG_JBD2=m # CONFIG_JBD2_DEBUG is not set CONFIG_FS_MBCACHE=m diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index 3b095c5aa1d3..68270899fc81 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig @@ -126,3 +126,11 @@ config EXT4_ERROR_REPORT help Implement the ext3/ext4 file system error report. Report error to userspace by netlink + +config EXT4_DIOREAD_NOLOCK_PARAM + bool "Ext4 default_dioread_nolock module param support" + depends on EXT4_FS + default n + help + Support to enable default_dioread_nolock module param, be attention to + that we default disable dioread_nolock with this config set to Y. diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0ef4b804e18e..9f3c7855095d 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -66,6 +66,20 @@ #define CREATE_TRACE_POINTS #include <trace/events/ext4.h>
+#ifdef CONFIG_EXT4_DIOREAD_NOLOCK_PARAM +/* + * After 244adf6426ee ("ext4: make dioread_nolock the default"), we will enable + * dioread_nolock by default, but this options may lead data lose combine with + * poweroff(Since we may first update i_size, and then unwritten extent convert + * to written extent). For this case, we give a param to help control does we + * really default enable dioread_nolock and we default disable dioread_nolock, + * enable it with ext4.default_dioread_nolock=1 if you want. + */ +int default_dioread_nolock; +module_param_named(default_dioread_nolock, default_dioread_nolock, int, 0644); +MODULE_PARM_DESC(default_dioread_nolock, "Default enable dioread_nolock"); +#endif + static struct ext4_lazy_init *ext4_li_info; static DEFINE_MUTEX(ext4_li_mtx); static struct ratelimit_state ext4_mount_msg_ratelimit; @@ -4472,8 +4486,13 @@ static void ext4_set_def_opts(struct super_block *sb, ((def_mount_opts & EXT4_DEFM_NODELALLOC) == 0)) set_opt(sb, DELALLOC);
+#ifdef CONFIG_EXT4_DIOREAD_NOLOCK_PARAM + if (sb->s_blocksize == PAGE_SIZE && default_dioread_nolock) + set_opt(sb, DIOREAD_NOLOCK); +#else if (sb->s_blocksize == PAGE_SIZE) set_opt(sb, DIOREAD_NOLOCK); +#endif
/* Use iomap for buffered IO path on 4k pagesize */ if (PAGE_SIZE == SZ_4K)