Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

f2fs: add lookup_mode mount option

For casefolded directories, f2fs may fall back to a linear search if
a hash-based lookup fails. This can cause severe performance
regressions.

While this behavior can be controlled by userspace tools (e.g. mkfs,
fsck) by setting an on-disk flag, a kernel-level solution is needed
to guarantee the lookup behavior regardless of the on-disk state.

This commit introduces the 'lookup_mode' mount option to provide this
kernel-side control.

The option accepts three values:
- perf: (Default) Enforces a hash-only lookup. The linear fallback
is always disabled.
- compat: Enables the linear search fallback for compatibility with
directory entries from older kernels.
- auto: Determines the mode based on the on-disk flag, preserving the
userspace-based behavior.

Signed-off-by: Daniel Lee <chullee@google.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

authored by

Daniel Lee and committed by
Jaegeuk Kim
632f0b6c 76bb6a72

+67 -1
+19
Documentation/filesystems/f2fs.rst
··· 370 370 ====================== =============== =============== ======== 371 371 nat_bits Enable nat_bits feature to enhance full/empty nat blocks access, 372 372 by default it's disabled. 373 + lookup_mode=%s Control the directory lookup behavior for casefolded 374 + directories. This option has no effect on directories 375 + that do not have the casefold feature enabled. 376 + 377 + ================== ======================================== 378 + Value Description 379 + ================== ======================================== 380 + perf (Default) Enforces a hash-only lookup. 381 + The linear search fallback is always 382 + disabled, ignoring the on-disk flag. 383 + compat Enables the linear search fallback for 384 + compatibility with directory entries 385 + created by older kernel that used a 386 + different case-folding algorithm. 387 + This mode ignores the on-disk flag. 388 + auto F2FS determines the mode based on the 389 + on-disk `SB_ENC_NO_COMPAT_FALLBACK_FL` 390 + flag. 391 + ================== ======================================== 373 392 ======================== ============================================================ 374 393 375 394 Debugfs Entries
+16 -1
fs/f2fs/dir.c
··· 16 16 #include "xattr.h" 17 17 #include <trace/events/f2fs.h> 18 18 19 + static inline bool f2fs_should_fallback_to_linear(struct inode *dir) 20 + { 21 + struct f2fs_sb_info *sbi = F2FS_I_SB(dir); 22 + 23 + switch (F2FS_OPTION(sbi).lookup_mode) { 24 + case LOOKUP_PERF: 25 + return false; 26 + case LOOKUP_COMPAT: 27 + return true; 28 + case LOOKUP_AUTO: 29 + return !sb_no_casefold_compat_fallback(sbi->sb); 30 + } 31 + return false; 32 + } 33 + 19 34 #if IS_ENABLED(CONFIG_UNICODE) 20 35 extern struct kmem_cache *f2fs_cf_name_slab; 21 36 #endif ··· 381 366 382 367 out: 383 368 #if IS_ENABLED(CONFIG_UNICODE) 384 - if (!sb_no_casefold_compat_fallback(dir->i_sb) && 369 + if (f2fs_should_fallback_to_linear(dir) && 385 370 IS_CASEFOLDED(dir) && !de && use_hash) { 386 371 use_hash = false; 387 372 goto start_find_entry;
+7
fs/f2fs/f2fs.h
··· 212 212 int compress_mode; /* compression mode */ 213 213 unsigned char extensions[COMPRESS_EXT_NUM][F2FS_EXTENSION_LEN]; /* extensions */ 214 214 unsigned char noextensions[COMPRESS_EXT_NUM][F2FS_EXTENSION_LEN]; /* extensions */ 215 + unsigned int lookup_mode; 215 216 }; 216 217 217 218 #define F2FS_FEATURE_ENCRYPT 0x00000001 ··· 1474 1473 FOREGROUND, 1475 1474 MAX_CALL_TYPE, 1476 1475 TOTAL_CALL = FOREGROUND, 1476 + }; 1477 + 1478 + enum f2fs_lookup_mode { 1479 + LOOKUP_PERF, 1480 + LOOKUP_COMPAT, 1481 + LOOKUP_AUTO, 1477 1482 }; 1478 1483 1479 1484 static inline int f2fs_test_bit(unsigned int nr, char *addr);
+25
fs/f2fs/super.c
··· 181 181 Opt_nat_bits, 182 182 Opt_jqfmt, 183 183 Opt_checkpoint, 184 + Opt_lookup_mode, 184 185 Opt_err, 185 186 }; 186 187 ··· 245 244 {} 246 245 }; 247 246 247 + static const struct constant_table f2fs_param_lookup_mode[] = { 248 + {"perf", LOOKUP_PERF}, 249 + {"compat", LOOKUP_COMPAT}, 250 + {"auto", LOOKUP_AUTO}, 251 + {} 252 + }; 253 + 248 254 static const struct fs_parameter_spec f2fs_param_specs[] = { 249 255 fsparam_enum("background_gc", Opt_gc_background, f2fs_param_background_gc), 250 256 fsparam_flag("disable_roll_forward", Opt_disable_roll_forward), ··· 308 300 fsparam_enum("memory", Opt_memory_mode, f2fs_param_memory_mode), 309 301 fsparam_flag("age_extent_cache", Opt_age_extent_cache), 310 302 fsparam_enum("errors", Opt_errors, f2fs_param_errors), 303 + fsparam_enum("lookup_mode", Opt_lookup_mode, f2fs_param_lookup_mode), 311 304 {} 312 305 }; 313 306 ··· 345 336 #define F2FS_SPEC_discard_unit (1 << 21) 346 337 #define F2FS_SPEC_memory_mode (1 << 22) 347 338 #define F2FS_SPEC_errors (1 << 23) 339 + #define F2FS_SPEC_lookup_mode (1 << 24) 348 340 349 341 struct f2fs_fs_context { 350 342 struct f2fs_mount_info info; ··· 1153 1143 case Opt_nat_bits: 1154 1144 ctx_set_opt(ctx, F2FS_MOUNT_NAT_BITS); 1155 1145 break; 1146 + case Opt_lookup_mode: 1147 + F2FS_CTX_INFO(ctx).lookup_mode = result.uint_32; 1148 + ctx->spec_mask |= F2FS_SPEC_lookup_mode; 1149 + break; 1156 1150 } 1157 1151 return 0; 1158 1152 } ··· 1666 1652 F2FS_OPTION(sbi).memory_mode = F2FS_CTX_INFO(ctx).memory_mode; 1667 1653 if (ctx->spec_mask & F2FS_SPEC_errors) 1668 1654 F2FS_OPTION(sbi).errors = F2FS_CTX_INFO(ctx).errors; 1655 + if (ctx->spec_mask & F2FS_SPEC_lookup_mode) 1656 + F2FS_OPTION(sbi).lookup_mode = F2FS_CTX_INFO(ctx).lookup_mode; 1669 1657 1670 1658 f2fs_apply_compression(fc, sb); 1671 1659 f2fs_apply_test_dummy_encryption(fc, sb); ··· 2432 2416 if (test_opt(sbi, NAT_BITS)) 2433 2417 seq_puts(seq, ",nat_bits"); 2434 2418 2419 + if (F2FS_OPTION(sbi).lookup_mode == LOOKUP_PERF) 2420 + seq_show_option(seq, "lookup_mode", "perf"); 2421 + else if (F2FS_OPTION(sbi).lookup_mode == LOOKUP_COMPAT) 2422 + seq_show_option(seq, "lookup_mode", "compat"); 2423 + else if (F2FS_OPTION(sbi).lookup_mode == LOOKUP_AUTO) 2424 + seq_show_option(seq, "lookup_mode", "auto"); 2425 + 2435 2426 return 0; 2436 2427 } 2437 2428 ··· 2503 2480 #endif 2504 2481 2505 2482 f2fs_build_fault_attr(sbi, 0, 0, FAULT_ALL); 2483 + 2484 + F2FS_OPTION(sbi).lookup_mode = LOOKUP_PERF; 2506 2485 } 2507 2486 2508 2487 #ifdef CONFIG_QUOTA