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 86f6cfaafa85..2d6b37def3fb 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -6207,6 +6207,7 @@ CONFIG_EXT4_USE_FOR_EXT2=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y # CONFIG_EXT4_DEBUG is not set +# 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 686e5cdfc801..27b1f9def28d 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -7292,6 +7292,7 @@ CONFIG_EXT4_USE_FOR_EXT2=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y # CONFIG_EXT4_DEBUG is not set +# 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 86699c8cab28..72913ea5343f 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig @@ -117,3 +117,11 @@ config EXT4_KUNIT_TESTS to the KUnit documentation in Documentation/dev-tools/kunit/.
If unsure, say N. + +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 ac032f517a60..5dbe420487e4 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -62,6 +62,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 struct mutex ext4_li_mtx; static struct ratelimit_state ext4_mount_msg_ratelimit; @@ -4272,8 +4286,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
blocksize = EXT4_MIN_BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
+#ifdef CONFIG_EXT4_DIOREAD_NOLOCK_PARAM + if (blocksize == PAGE_SIZE && default_dioread_nolock) + set_opt(sb, DIOREAD_NOLOCK); +#else if (blocksize == PAGE_SIZE) set_opt(sb, DIOREAD_NOLOCK); +#endif
if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) { sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;