diff mbox series

[f2fs-dev,v2,3/3] fsck.f2fs: support to tune linear lookup feature

Message ID 20250407020727.1810288-1-chao@kernel.org (mailing list archive)
State New
Headers show
Series None | expand

Commit Message

Chao Yu April 7, 2025, 2:07 a.m. UTC
Support a new option --nolinear-lookup=X for fsck.f2fs to tune
linear lookup fallback conditionally, X=1: disable linear lookup,
X=0: enable linear lookup.

This can help to 1) add a regression testcase to check kernel
whether linear lookup fallback has fixed unicode red heart lookup
issue, 2) once unicode bug has been fixed, we can use this option
to disable linear lookup for performance recovery.

Cc: Daniel Lee <chullee@google.com>
Signed-off-by: Chao Yu <chao@kernel.org>
---
v2:
- add description in fsck manual
 fsck/fsck.c       | 26 +++++++++++++++++++++++++-
 fsck/fsck.h       |  1 +
 fsck/main.c       | 10 ++++++++++
 include/f2fs_fs.h |  8 ++++++--
 man/fsck.f2fs.8   |  3 +++
 5 files changed, 45 insertions(+), 3 deletions(-)

Comments

Zhiguo Niu April 11, 2025, 2:07 a.m. UTC | #1
Chao Yu via Linux-f2fs-devel <linux-f2fs-devel@lists.sourceforge.net>
于2025年4月7日周一 10:11写道:
>
> Support a new option --nolinear-lookup=X for fsck.f2fs to tune
> linear lookup fallback conditionally, X=1: disable linear lookup,
> X=0: enable linear lookup.
>
> This can help to 1) add a regression testcase to check kernel
> whether linear lookup fallback has fixed unicode red heart lookup
> issue, 2) once unicode bug has been fixed, we can use this option
> to disable linear lookup for performance recovery.
>
> Cc: Daniel Lee <chullee@google.com>
> Signed-off-by: Chao Yu <chao@kernel.org>
> ---
> v2:
> - add description in fsck manual
>  fsck/fsck.c       | 26 +++++++++++++++++++++++++-
>  fsck/fsck.h       |  1 +
>  fsck/main.c       | 10 ++++++++++
>  include/f2fs_fs.h |  8 ++++++--
>  man/fsck.f2fs.8   |  3 +++
>  5 files changed, 45 insertions(+), 3 deletions(-)
>
> diff --git a/fsck/fsck.c b/fsck/fsck.c
> index 8155cbd..059ba61 100644
> --- a/fsck/fsck.c
> +++ b/fsck/fsck.c
> @@ -2357,6 +2357,30 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
>         return ret;
>  }
>
> +void fsck_update_sb_flags(struct f2fs_sb_info *sbi)
> +{
> +       struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
> +       u16 flags = get_sb(s_encoding_flags);
> +
> +       if (c.nolinear_lookup) {
> +               if (!(flags & F2FS_ENC_NO_COMPAT_FALLBACK_FL)) {
> +                       flags |= F2FS_ENC_NO_COMPAT_FALLBACK_FL;
> +                       set_sb(s_encoding_flags, flags);
> +                       c.fix_on = 1;
> +                       c.invalid_sb |= SB_ENCODE_FLAG;
> +                       DBG(0, "Casefold: enable nolinear lookup\n");
> +               }
> +       } else {
> +               if (flags & F2FS_ENC_NO_COMPAT_FALLBACK_FL) {
> +                       flags &= ~F2FS_ENC_NO_COMPAT_FALLBACK_FL;
> +                       set_sb(s_encoding_flags, flags);
> +                       c.fix_on = 1;
> +                       c.invalid_sb |= SB_ENCODE_FLAG;
> +                       DBG(0, "Casefold: disable nolinear lookup\n");
> +               }
> +       }
> +}
> +
>  int fsck_chk_meta(struct f2fs_sb_info *sbi)
>  {
>         struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
> @@ -3770,7 +3794,7 @@ int fsck_verify(struct f2fs_sb_info *sbi)
>                 if (c.invalid_sb & SB_FS_ERRORS)
>                         memset(sb->s_errors, 0, MAX_F2FS_ERRORS);
>
> -               if (c.invalid_sb & SB_NEED_FIX)
> +               if (c.invalid_sb & (SB_NEED_FIX | SB_ENCODE_FLAG))
>                         update_superblock(sb, SB_MASK_ALL);
>
>                 /* to return FSCK_ERROR_CORRECTED */
> diff --git a/fsck/fsck.h b/fsck/fsck.h
> index b581d3e..40cb6d9 100644
> --- a/fsck/fsck.h
> +++ b/fsck/fsck.h
> @@ -188,6 +188,7 @@ extern int fsck_chk_dentry_blk(struct f2fs_sb_info *, int,
>  int fsck_chk_inline_dentries(struct f2fs_sb_info *, struct f2fs_node *,
>                 struct child_info *);
>  void fsck_chk_checkpoint(struct f2fs_sb_info *sbi);
> +void fsck_update_sb_flags(struct f2fs_sb_info *sbi);
>  int fsck_chk_meta(struct f2fs_sb_info *sbi);
>  void fsck_chk_and_fix_write_pointers(struct f2fs_sb_info *);
>  int fsck_chk_curseg_info(struct f2fs_sb_info *);
> diff --git a/fsck/main.c b/fsck/main.c
> index 47ba6c9..524dbb1 100644
> --- a/fsck/main.c
> +++ b/fsck/main.c
> @@ -91,6 +91,7 @@ void fsck_usage()
>         MSG(0, "  --no-kernel-check skips detecting kernel change\n");
>         MSG(0, "  --kernel-check checks kernel change\n");
>         MSG(0, "  --debug-cache to debug cache when -c is used\n");
> +       MSG(0, "  --nolinear-lookup=X X=1: disable linear lookup, X=0: enable linear lookup\n");
>         exit(1);
>  }
>
> @@ -263,6 +264,7 @@ void f2fs_parse_options(int argc, char *argv[])
>                         {"no-kernel-check", no_argument, 0, 2},
>                         {"kernel-check", no_argument, 0, 3},
>                         {"debug-cache", no_argument, 0, 4},
> +                       {"nolinear-lookup", required_argument, 0, 5},
>                         {0, 0, 0, 0}
>                 };
>
> @@ -287,6 +289,12 @@ void f2fs_parse_options(int argc, char *argv[])
>                         case 4:
>                                 c.cache_config.dbg_en = true;
>                                 break;
> +                       case 5:
> +                               if (!optarg || !strcmp(optarg, "0"))
> +                                       c.nolinear_lookup = 0;
> +                               else
> +                                       c.nolinear_lookup = 1;
> +                               break;
Hi Chao
I also encountered the same performance regression problem in Android
device as kernel commit
51dc491a0855("f2fs: support to disable linear lookup fallback") shown.

so because we also need to update this commit about fsck to avoid
performance regressions.
Is it appropriate to set this parameter  disable linear_lookup by
default (c.nolinear_lookup = 1)?
This also fits most of the scenarios.
If other users want to enable this feature, they can control it
through parameters.
thanks!
>                         case 'a':
>                                 c.auto_fix = 1;
>                                 MSG(0, "Info: Automatic fix mode enabled.\n");
> @@ -990,6 +998,8 @@ static int do_fsck(struct f2fs_sb_info *sbi)
>                         F2FS_FT_DIR, TYPE_INODE, &blk_cnt, &cbc, &child);
>         fsck_chk_quota_files(sbi);
>
> +       fsck_update_sb_flags(sbi);
> +
>         ret = fsck_verify(sbi);
>         fsck_free(sbi);
>
> diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
> index f206994..7e3f25b 100644
> --- a/include/f2fs_fs.h
> +++ b/include/f2fs_fs.h
> @@ -682,7 +682,8 @@ enum {
>  #define IS_DEVICE_ALIASING(fi) ((fi)->i_flags & cpu_to_le32(F2FS_DEVICE_ALIAS_FL))
>
>  #define F2FS_ENC_UTF8_12_1     1
> -#define F2FS_ENC_STRICT_MODE_FL        (1 << 0)
> +#define F2FS_ENC_STRICT_MODE_FL                (1 << 0)
> +#define F2FS_ENC_NO_COMPAT_FALLBACK_FL (1 << 1)
>
>  /* This flag is used by node and meta inodes, and by recovery */
>  #define GFP_F2FS_ZERO  (GFP_NOFS | __GFP_ZERO)
> @@ -1467,7 +1468,9 @@ enum {
>  #define SB_ABNORMAL_STOP       0x2     /* s_stop_reason is set except shutdown */
>  #define SB_FS_ERRORS           0x4     /* s_erros is set */
>  #define SB_INVALID             0x8     /* sb is invalid */
> -#define SB_NEED_FIX (SB_ABNORMAL_STOP | SB_FS_ERRORS | SB_INVALID)
> +#define SB_ENCODE_FLAG         0x16    /* encode_flag */
> +#define SB_NEED_FIX            (SB_ABNORMAL_STOP | SB_FS_ERRORS |      \
> +                               SB_INVALID | SB_ENCODE_FLAG)
>
>  #define MAX_CACHE_SUMS                 8
>
> @@ -1541,6 +1544,7 @@ struct f2fs_configuration {
>         int preserve_limits;            /* preserve quota limits */
>         int large_nat_bitmap;
>         int fix_chksum;                 /* fix old cp.chksum position */
> +       int nolinear_lookup;            /* disable linear lookup */
>         unsigned int feature;                   /* defined features */
>         unsigned int disabled_feature;  /* disabled feature, used for Android only */
>         unsigned int quota_bits;        /* quota bits */
> diff --git a/man/fsck.f2fs.8 b/man/fsck.f2fs.8
> index e39a846..606e288 100644
> --- a/man/fsck.f2fs.8
> +++ b/man/fsck.f2fs.8
> @@ -67,6 +67,9 @@ Enable to show every directory entries in the partition.
>  Specify the level of debugging options.
>  The default number is 0, which shows basic debugging messages.
>  .TP
> +.BI \--nolinear-lookup
> +Tune linear lookup fallback, must specify an argument, 0: enable linear lookup, 1: disable linear lookup.
> +.TP
>  .SH AUTHOR
>  Initial checking code was written by Byoung Geun Kim <bgbg.kim@samsung.com>.
>  Jaegeuk Kim <jaegeuk@kernel.org> reworked most parts of the codes to support
> --
> 2.49.0
>
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Chao Yu April 11, 2025, 10:32 a.m. UTC | #2
On 2025/4/11 10:07, Zhiguo Niu wrote:
> Chao Yu via Linux-f2fs-devel <linux-f2fs-devel@lists.sourceforge.net>
> 于2025年4月7日周一 10:11写道:
>>
>> Support a new option --nolinear-lookup=X for fsck.f2fs to tune
>> linear lookup fallback conditionally, X=1: disable linear lookup,
>> X=0: enable linear lookup.
>>
>> This can help to 1) add a regression testcase to check kernel
>> whether linear lookup fallback has fixed unicode red heart lookup
>> issue, 2) once unicode bug has been fixed, we can use this option
>> to disable linear lookup for performance recovery.
>>
>> Cc: Daniel Lee <chullee@google.com>
>> Signed-off-by: Chao Yu <chao@kernel.org>
>> ---
>> v2:
>> - add description in fsck manual
>>   fsck/fsck.c       | 26 +++++++++++++++++++++++++-
>>   fsck/fsck.h       |  1 +
>>   fsck/main.c       | 10 ++++++++++
>>   include/f2fs_fs.h |  8 ++++++--
>>   man/fsck.f2fs.8   |  3 +++
>>   5 files changed, 45 insertions(+), 3 deletions(-)
>>
>> diff --git a/fsck/fsck.c b/fsck/fsck.c
>> index 8155cbd..059ba61 100644
>> --- a/fsck/fsck.c
>> +++ b/fsck/fsck.c
>> @@ -2357,6 +2357,30 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
>>          return ret;
>>   }
>>
>> +void fsck_update_sb_flags(struct f2fs_sb_info *sbi)
>> +{
>> +       struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
>> +       u16 flags = get_sb(s_encoding_flags);
>> +
>> +       if (c.nolinear_lookup) {
>> +               if (!(flags & F2FS_ENC_NO_COMPAT_FALLBACK_FL)) {
>> +                       flags |= F2FS_ENC_NO_COMPAT_FALLBACK_FL;
>> +                       set_sb(s_encoding_flags, flags);
>> +                       c.fix_on = 1;
>> +                       c.invalid_sb |= SB_ENCODE_FLAG;
>> +                       DBG(0, "Casefold: enable nolinear lookup\n");
>> +               }
>> +       } else {
>> +               if (flags & F2FS_ENC_NO_COMPAT_FALLBACK_FL) {
>> +                       flags &= ~F2FS_ENC_NO_COMPAT_FALLBACK_FL;
>> +                       set_sb(s_encoding_flags, flags);
>> +                       c.fix_on = 1;
>> +                       c.invalid_sb |= SB_ENCODE_FLAG;
>> +                       DBG(0, "Casefold: disable nolinear lookup\n");
>> +               }
>> +       }
>> +}
>> +
>>   int fsck_chk_meta(struct f2fs_sb_info *sbi)
>>   {
>>          struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
>> @@ -3770,7 +3794,7 @@ int fsck_verify(struct f2fs_sb_info *sbi)
>>                  if (c.invalid_sb & SB_FS_ERRORS)
>>                          memset(sb->s_errors, 0, MAX_F2FS_ERRORS);
>>
>> -               if (c.invalid_sb & SB_NEED_FIX)
>> +               if (c.invalid_sb & (SB_NEED_FIX | SB_ENCODE_FLAG))
>>                          update_superblock(sb, SB_MASK_ALL);
>>
>>                  /* to return FSCK_ERROR_CORRECTED */
>> diff --git a/fsck/fsck.h b/fsck/fsck.h
>> index b581d3e..40cb6d9 100644
>> --- a/fsck/fsck.h
>> +++ b/fsck/fsck.h
>> @@ -188,6 +188,7 @@ extern int fsck_chk_dentry_blk(struct f2fs_sb_info *, int,
>>   int fsck_chk_inline_dentries(struct f2fs_sb_info *, struct f2fs_node *,
>>                  struct child_info *);
>>   void fsck_chk_checkpoint(struct f2fs_sb_info *sbi);
>> +void fsck_update_sb_flags(struct f2fs_sb_info *sbi);
>>   int fsck_chk_meta(struct f2fs_sb_info *sbi);
>>   void fsck_chk_and_fix_write_pointers(struct f2fs_sb_info *);
>>   int fsck_chk_curseg_info(struct f2fs_sb_info *);
>> diff --git a/fsck/main.c b/fsck/main.c
>> index 47ba6c9..524dbb1 100644
>> --- a/fsck/main.c
>> +++ b/fsck/main.c
>> @@ -91,6 +91,7 @@ void fsck_usage()
>>          MSG(0, "  --no-kernel-check skips detecting kernel change\n");
>>          MSG(0, "  --kernel-check checks kernel change\n");
>>          MSG(0, "  --debug-cache to debug cache when -c is used\n");
>> +       MSG(0, "  --nolinear-lookup=X X=1: disable linear lookup, X=0: enable linear lookup\n");
>>          exit(1);
>>   }
>>
>> @@ -263,6 +264,7 @@ void f2fs_parse_options(int argc, char *argv[])
>>                          {"no-kernel-check", no_argument, 0, 2},
>>                          {"kernel-check", no_argument, 0, 3},
>>                          {"debug-cache", no_argument, 0, 4},
>> +                       {"nolinear-lookup", required_argument, 0, 5},
>>                          {0, 0, 0, 0}
>>                  };
>>
>> @@ -287,6 +289,12 @@ void f2fs_parse_options(int argc, char *argv[])
>>                          case 4:
>>                                  c.cache_config.dbg_en = true;
>>                                  break;
>> +                       case 5:
>> +                               if (!optarg || !strcmp(optarg, "0"))
>> +                                       c.nolinear_lookup = 0;
>> +                               else
>> +                                       c.nolinear_lookup = 1;
>> +                               break;
> Hi Chao
> I also encountered the same performance regression problem in Android
> device as kernel commit
> 51dc491a0855("f2fs: support to disable linear lookup fallback") shown.
> 
> so because we also need to update this commit about fsck to avoid
> performance regressions.
> Is it appropriate to set this parameter  disable linear_lookup by
> default (c.nolinear_lookup = 1)?
> This also fits most of the scenarios.
> If other users want to enable this feature, they can control it
> through parameters.

Zhiguo,

There are two conditions user will lost their file which has specified
charactors, like red heart ❤️.

case #1
- create file named red_heart ❤️
- apply 5c26d2f1d3f5 ("unicode: Don't special case ignorable code points")
- stat red_heart ❤️ --> No such file or directory

case #2
- apply 5c26d2f1d3f5 ("unicode: Don't special case ignorable code points")
- create file named red_heart ❤️
- revert 5c26d2f1d3f5 ("unicode: Don't special case ignorable code points")
- stat red_heart ❤️ --> No such file or directory

If you does not matched any of above cases, I guess it's fine for you to
disable linear fallback.

I prefer to wait for the formal fix for specified unicode charactor
handling, and then disable linear fallback, as I don't know the condition
of our user.

> thanks!
>>                          case 'a':
>>                                  c.auto_fix = 1;
>>                                  MSG(0, "Info: Automatic fix mode enabled.\n");
>> @@ -990,6 +998,8 @@ static int do_fsck(struct f2fs_sb_info *sbi)
>>                          F2FS_FT_DIR, TYPE_INODE, &blk_cnt, &cbc, &child);
>>          fsck_chk_quota_files(sbi);
>>
>> +       fsck_update_sb_flags(sbi);
>> +
>>          ret = fsck_verify(sbi);
>>          fsck_free(sbi);
>>
>> diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
>> index f206994..7e3f25b 100644
>> --- a/include/f2fs_fs.h
>> +++ b/include/f2fs_fs.h
>> @@ -682,7 +682,8 @@ enum {
>>   #define IS_DEVICE_ALIASING(fi) ((fi)->i_flags & cpu_to_le32(F2FS_DEVICE_ALIAS_FL))
>>
>>   #define F2FS_ENC_UTF8_12_1     1
>> -#define F2FS_ENC_STRICT_MODE_FL        (1 << 0)
>> +#define F2FS_ENC_STRICT_MODE_FL                (1 << 0)
>> +#define F2FS_ENC_NO_COMPAT_FALLBACK_FL (1 << 1)
>>
>>   /* This flag is used by node and meta inodes, and by recovery */
>>   #define GFP_F2FS_ZERO  (GFP_NOFS | __GFP_ZERO)
>> @@ -1467,7 +1468,9 @@ enum {
>>   #define SB_ABNORMAL_STOP       0x2     /* s_stop_reason is set except shutdown */
>>   #define SB_FS_ERRORS           0x4     /* s_erros is set */
>>   #define SB_INVALID             0x8     /* sb is invalid */
>> -#define SB_NEED_FIX (SB_ABNORMAL_STOP | SB_FS_ERRORS | SB_INVALID)
>> +#define SB_ENCODE_FLAG         0x16    /* encode_flag */
>> +#define SB_NEED_FIX            (SB_ABNORMAL_STOP | SB_FS_ERRORS |      \
>> +                               SB_INVALID | SB_ENCODE_FLAG)
>>
>>   #define MAX_CACHE_SUMS                 8
>>
>> @@ -1541,6 +1544,7 @@ struct f2fs_configuration {
>>          int preserve_limits;            /* preserve quota limits */
>>          int large_nat_bitmap;
>>          int fix_chksum;                 /* fix old cp.chksum position */
>> +       int nolinear_lookup;            /* disable linear lookup */
>>          unsigned int feature;                   /* defined features */
>>          unsigned int disabled_feature;  /* disabled feature, used for Android only */
>>          unsigned int quota_bits;        /* quota bits */
>> diff --git a/man/fsck.f2fs.8 b/man/fsck.f2fs.8
>> index e39a846..606e288 100644
>> --- a/man/fsck.f2fs.8
>> +++ b/man/fsck.f2fs.8
>> @@ -67,6 +67,9 @@ Enable to show every directory entries in the partition.
>>   Specify the level of debugging options.
>>   The default number is 0, which shows basic debugging messages.
>>   .TP
>> +.BI \--nolinear-lookup
>> +Tune linear lookup fallback, must specify an argument, 0: enable linear lookup, 1: disable linear lookup.
>> +.TP
>>   .SH AUTHOR
>>   Initial checking code was written by Byoung Geun Kim <bgbg.kim@samsung.com>.
>>   Jaegeuk Kim <jaegeuk@kernel.org> reworked most parts of the codes to support
>> --
>> 2.49.0
>>
>>
>>
>> _______________________________________________
>> Linux-f2fs-devel mailing list
>> Linux-f2fs-devel@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
diff mbox series

Patch

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 8155cbd..059ba61 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -2357,6 +2357,30 @@  int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
 	return ret;
 }
 
+void fsck_update_sb_flags(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
+	u16 flags = get_sb(s_encoding_flags);
+
+	if (c.nolinear_lookup) {
+		if (!(flags & F2FS_ENC_NO_COMPAT_FALLBACK_FL)) {
+			flags |= F2FS_ENC_NO_COMPAT_FALLBACK_FL;
+			set_sb(s_encoding_flags, flags);
+			c.fix_on = 1;
+			c.invalid_sb |= SB_ENCODE_FLAG;
+			DBG(0, "Casefold: enable nolinear lookup\n");
+		}
+	} else {
+		if (flags & F2FS_ENC_NO_COMPAT_FALLBACK_FL) {
+			flags &= ~F2FS_ENC_NO_COMPAT_FALLBACK_FL;
+			set_sb(s_encoding_flags, flags);
+			c.fix_on = 1;
+			c.invalid_sb |= SB_ENCODE_FLAG;
+			DBG(0, "Casefold: disable nolinear lookup\n");
+		}
+	}
+}
+
 int fsck_chk_meta(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
@@ -3770,7 +3794,7 @@  int fsck_verify(struct f2fs_sb_info *sbi)
 		if (c.invalid_sb & SB_FS_ERRORS)
 			memset(sb->s_errors, 0, MAX_F2FS_ERRORS);
 
-		if (c.invalid_sb & SB_NEED_FIX)
+		if (c.invalid_sb & (SB_NEED_FIX | SB_ENCODE_FLAG))
 			update_superblock(sb, SB_MASK_ALL);
 
 		/* to return FSCK_ERROR_CORRECTED */
diff --git a/fsck/fsck.h b/fsck/fsck.h
index b581d3e..40cb6d9 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -188,6 +188,7 @@  extern int fsck_chk_dentry_blk(struct f2fs_sb_info *, int,
 int fsck_chk_inline_dentries(struct f2fs_sb_info *, struct f2fs_node *,
 		struct child_info *);
 void fsck_chk_checkpoint(struct f2fs_sb_info *sbi);
+void fsck_update_sb_flags(struct f2fs_sb_info *sbi);
 int fsck_chk_meta(struct f2fs_sb_info *sbi);
 void fsck_chk_and_fix_write_pointers(struct f2fs_sb_info *);
 int fsck_chk_curseg_info(struct f2fs_sb_info *);
diff --git a/fsck/main.c b/fsck/main.c
index 47ba6c9..524dbb1 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -91,6 +91,7 @@  void fsck_usage()
 	MSG(0, "  --no-kernel-check skips detecting kernel change\n");
 	MSG(0, "  --kernel-check checks kernel change\n");
 	MSG(0, "  --debug-cache to debug cache when -c is used\n");
+	MSG(0, "  --nolinear-lookup=X X=1: disable linear lookup, X=0: enable linear lookup\n");
 	exit(1);
 }
 
@@ -263,6 +264,7 @@  void f2fs_parse_options(int argc, char *argv[])
 			{"no-kernel-check", no_argument, 0, 2},
 			{"kernel-check", no_argument, 0, 3},
 			{"debug-cache", no_argument, 0, 4},
+			{"nolinear-lookup", required_argument, 0, 5},
 			{0, 0, 0, 0}
 		};
 
@@ -287,6 +289,12 @@  void f2fs_parse_options(int argc, char *argv[])
 			case 4:
 				c.cache_config.dbg_en = true;
 				break;
+			case 5:
+				if (!optarg || !strcmp(optarg, "0"))
+					c.nolinear_lookup = 0;
+				else
+					c.nolinear_lookup = 1;
+				break;
 			case 'a':
 				c.auto_fix = 1;
 				MSG(0, "Info: Automatic fix mode enabled.\n");
@@ -990,6 +998,8 @@  static int do_fsck(struct f2fs_sb_info *sbi)
 			F2FS_FT_DIR, TYPE_INODE, &blk_cnt, &cbc, &child);
 	fsck_chk_quota_files(sbi);
 
+	fsck_update_sb_flags(sbi);
+
 	ret = fsck_verify(sbi);
 	fsck_free(sbi);
 
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index f206994..7e3f25b 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -682,7 +682,8 @@  enum {
 #define IS_DEVICE_ALIASING(fi)	((fi)->i_flags & cpu_to_le32(F2FS_DEVICE_ALIAS_FL))
 
 #define F2FS_ENC_UTF8_12_1	1
-#define F2FS_ENC_STRICT_MODE_FL	(1 << 0)
+#define F2FS_ENC_STRICT_MODE_FL		(1 << 0)
+#define F2FS_ENC_NO_COMPAT_FALLBACK_FL	(1 << 1)
 
 /* This flag is used by node and meta inodes, and by recovery */
 #define GFP_F2FS_ZERO	(GFP_NOFS | __GFP_ZERO)
@@ -1467,7 +1468,9 @@  enum {
 #define SB_ABNORMAL_STOP	0x2	/* s_stop_reason is set except shutdown */
 #define SB_FS_ERRORS		0x4	/* s_erros is set */
 #define SB_INVALID		0x8	/* sb is invalid */
-#define SB_NEED_FIX (SB_ABNORMAL_STOP | SB_FS_ERRORS | SB_INVALID)
+#define SB_ENCODE_FLAG		0x16	/* encode_flag */
+#define SB_NEED_FIX		(SB_ABNORMAL_STOP | SB_FS_ERRORS |	\
+				SB_INVALID | SB_ENCODE_FLAG)
 
 #define MAX_CACHE_SUMS			8
 
@@ -1541,6 +1544,7 @@  struct f2fs_configuration {
 	int preserve_limits;		/* preserve quota limits */
 	int large_nat_bitmap;
 	int fix_chksum;			/* fix old cp.chksum position */
+	int nolinear_lookup;		/* disable linear lookup */
 	unsigned int feature;			/* defined features */
 	unsigned int disabled_feature;	/* disabled feature, used for Android only */
 	unsigned int quota_bits;	/* quota bits */
diff --git a/man/fsck.f2fs.8 b/man/fsck.f2fs.8
index e39a846..606e288 100644
--- a/man/fsck.f2fs.8
+++ b/man/fsck.f2fs.8
@@ -67,6 +67,9 @@  Enable to show every directory entries in the partition.
 Specify the level of debugging options.
 The default number is 0, which shows basic debugging messages.
 .TP
+.BI \--nolinear-lookup
+Tune linear lookup fallback, must specify an argument, 0: enable linear lookup, 1: disable linear lookup.
+.TP
 .SH AUTHOR
 Initial checking code was written by Byoung Geun Kim <bgbg.kim@samsung.com>.
 Jaegeuk Kim <jaegeuk@kernel.org> reworked most parts of the codes to support