Commit e862c848 authored by Yang Erkun's avatar Yang Erkun
Browse files

ext4: flexibly control whether to enable dioread_nolock by default

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IAAPPE



--------------------------------

After commit 244adf64 ("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: 244adf64 ("ext4: make dioread_nolock the default")
Signed-off-by: default avatarYang Erkun <yangerkun@huawei.com>
parent 456b68d7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6326,6 +6326,7 @@ CONFIG_EXT4_FS_SECURITY=y
# CONFIG_EXT4_DEBUG is not set
CONFIG_EXT4_ERROR_REPORT=y
CONFIG_EXT4_MITIGATION_FALSE_SHARING=y
# CONFIG_EXT4_DIOREAD_NOLOCK_PARAM is not set
CONFIG_JBD2=m
# CONFIG_JBD2_DEBUG is not set
CONFIG_FS_MBCACHE=m
+1 −0
Original line number Diff line number Diff line
@@ -7384,6 +7384,7 @@ CONFIG_EXT4_FS_SECURITY=y
# CONFIG_EXT4_DEBUG is not set
CONFIG_EXT4_ERROR_REPORT=y
CONFIG_EXT4_MITIGATION_FALSE_SHARING=y
# CONFIG_EXT4_DIOREAD_NOLOCK_PARAM is not set
CONFIG_JBD2=m
# CONFIG_JBD2_DEBUG is not set
CONFIG_FS_MBCACHE=m
+8 −0
Original line number Diff line number Diff line
@@ -134,3 +134,11 @@ config EXT4_MITIGATION_FALSE_SHARING
	  Enable this to mitigation cacheline false sharing in ext4 inode info.

	  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.
+19 −0
Original line number Diff line number Diff line
@@ -64,6 +64,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;
@@ -4292,8 +4306,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;