diff options
author | Icenowy Zheng <icenowy@aosc.io> | 2019-07-24 23:08:52 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2019-07-29 01:59:14 -0400 |
commit | 38fb6d0ea34299d97b031ed64fe994158b6f8eb3 (patch) | |
tree | 94250e27b6a2b7453443f3ed37d9a724e655b8bd /fs/f2fs/super.c | |
parent | 543b8c468f55f27f3c0178a22a91a51aabbbc428 (diff) |
f2fs: use EINVAL for superblock with invalid magic
The kernel mount_block_root() function expects -EACESS or -EINVAL for a
unmountable filesystem when trying to mount the root with different
filesystem types.
However, in 5.3-rc1 the behavior when F2FS code cannot find valid block
changed to return -EFSCORRUPTED(-EUCLEAN), and this error code makes
mount_block_root() fail when trying to probe F2FS.
When the magic number of the superblock mismatches, it has a high
probability that it's just not a F2FS. In this case return -EINVAL seems
to be a better result, and this return value can make mount_block_root()
probing work again.
Return -EINVAL when the superblock has magic mismatch, -EFSCORRUPTED in
other cases (the magic matches but the superblock cannot be recognized).
Fixes: 10f966bbf521 ("f2fs: use generic EFSBADCRC/EFSCORRUPTED")
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/super.c')
-rw-r--r-- | fs/f2fs/super.c | 48 |
1 files changed, 24 insertions, 24 deletions
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index d95a681ef7c9..1838dd852a50 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -2422,6 +2422,12 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, | |||
2422 | size_t crc_offset = 0; | 2422 | size_t crc_offset = 0; |
2423 | __u32 crc = 0; | 2423 | __u32 crc = 0; |
2424 | 2424 | ||
2425 | if (le32_to_cpu(raw_super->magic) != F2FS_SUPER_MAGIC) { | ||
2426 | f2fs_info(sbi, "Magic Mismatch, valid(0x%x) - read(0x%x)", | ||
2427 | F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic)); | ||
2428 | return -EINVAL; | ||
2429 | } | ||
2430 | |||
2425 | /* Check checksum_offset and crc in superblock */ | 2431 | /* Check checksum_offset and crc in superblock */ |
2426 | if (__F2FS_HAS_FEATURE(raw_super, F2FS_FEATURE_SB_CHKSUM)) { | 2432 | if (__F2FS_HAS_FEATURE(raw_super, F2FS_FEATURE_SB_CHKSUM)) { |
2427 | crc_offset = le32_to_cpu(raw_super->checksum_offset); | 2433 | crc_offset = le32_to_cpu(raw_super->checksum_offset); |
@@ -2429,26 +2435,20 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, | |||
2429 | offsetof(struct f2fs_super_block, crc)) { | 2435 | offsetof(struct f2fs_super_block, crc)) { |
2430 | f2fs_info(sbi, "Invalid SB checksum offset: %zu", | 2436 | f2fs_info(sbi, "Invalid SB checksum offset: %zu", |
2431 | crc_offset); | 2437 | crc_offset); |
2432 | return 1; | 2438 | return -EFSCORRUPTED; |
2433 | } | 2439 | } |
2434 | crc = le32_to_cpu(raw_super->crc); | 2440 | crc = le32_to_cpu(raw_super->crc); |
2435 | if (!f2fs_crc_valid(sbi, crc, raw_super, crc_offset)) { | 2441 | if (!f2fs_crc_valid(sbi, crc, raw_super, crc_offset)) { |
2436 | f2fs_info(sbi, "Invalid SB checksum value: %u", crc); | 2442 | f2fs_info(sbi, "Invalid SB checksum value: %u", crc); |
2437 | return 1; | 2443 | return -EFSCORRUPTED; |
2438 | } | 2444 | } |
2439 | } | 2445 | } |
2440 | 2446 | ||
2441 | if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) { | ||
2442 | f2fs_info(sbi, "Magic Mismatch, valid(0x%x) - read(0x%x)", | ||
2443 | F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic)); | ||
2444 | return 1; | ||
2445 | } | ||
2446 | |||
2447 | /* Currently, support only 4KB page cache size */ | 2447 | /* Currently, support only 4KB page cache size */ |
2448 | if (F2FS_BLKSIZE != PAGE_SIZE) { | 2448 | if (F2FS_BLKSIZE != PAGE_SIZE) { |
2449 | f2fs_info(sbi, "Invalid page_cache_size (%lu), supports only 4KB", | 2449 | f2fs_info(sbi, "Invalid page_cache_size (%lu), supports only 4KB", |
2450 | PAGE_SIZE); | 2450 | PAGE_SIZE); |
2451 | return 1; | 2451 | return -EFSCORRUPTED; |
2452 | } | 2452 | } |
2453 | 2453 | ||
2454 | /* Currently, support only 4KB block size */ | 2454 | /* Currently, support only 4KB block size */ |
@@ -2456,14 +2456,14 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, | |||
2456 | if (blocksize != F2FS_BLKSIZE) { | 2456 | if (blocksize != F2FS_BLKSIZE) { |
2457 | f2fs_info(sbi, "Invalid blocksize (%u), supports only 4KB", | 2457 | f2fs_info(sbi, "Invalid blocksize (%u), supports only 4KB", |
2458 | blocksize); | 2458 | blocksize); |
2459 | return 1; | 2459 | return -EFSCORRUPTED; |
2460 | } | 2460 | } |
2461 | 2461 | ||
2462 | /* check log blocks per segment */ | 2462 | /* check log blocks per segment */ |
2463 | if (le32_to_cpu(raw_super->log_blocks_per_seg) != 9) { | 2463 | if (le32_to_cpu(raw_super->log_blocks_per_seg) != 9) { |
2464 | f2fs_info(sbi, "Invalid log blocks per segment (%u)", | 2464 | f2fs_info(sbi, "Invalid log blocks per segment (%u)", |
2465 | le32_to_cpu(raw_super->log_blocks_per_seg)); | 2465 | le32_to_cpu(raw_super->log_blocks_per_seg)); |
2466 | return 1; | 2466 | return -EFSCORRUPTED; |
2467 | } | 2467 | } |
2468 | 2468 | ||
2469 | /* Currently, support 512/1024/2048/4096 bytes sector size */ | 2469 | /* Currently, support 512/1024/2048/4096 bytes sector size */ |
@@ -2473,7 +2473,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, | |||
2473 | F2FS_MIN_LOG_SECTOR_SIZE) { | 2473 | F2FS_MIN_LOG_SECTOR_SIZE) { |
2474 | f2fs_info(sbi, "Invalid log sectorsize (%u)", | 2474 | f2fs_info(sbi, "Invalid log sectorsize (%u)", |
2475 | le32_to_cpu(raw_super->log_sectorsize)); | 2475 | le32_to_cpu(raw_super->log_sectorsize)); |
2476 | return 1; | 2476 | return -EFSCORRUPTED; |
2477 | } | 2477 | } |
2478 | if (le32_to_cpu(raw_super->log_sectors_per_block) + | 2478 | if (le32_to_cpu(raw_super->log_sectors_per_block) + |
2479 | le32_to_cpu(raw_super->log_sectorsize) != | 2479 | le32_to_cpu(raw_super->log_sectorsize) != |
@@ -2481,7 +2481,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, | |||
2481 | f2fs_info(sbi, "Invalid log sectors per block(%u) log sectorsize(%u)", | 2481 | f2fs_info(sbi, "Invalid log sectors per block(%u) log sectorsize(%u)", |
2482 | le32_to_cpu(raw_super->log_sectors_per_block), | 2482 | le32_to_cpu(raw_super->log_sectors_per_block), |
2483 | le32_to_cpu(raw_super->log_sectorsize)); | 2483 | le32_to_cpu(raw_super->log_sectorsize)); |
2484 | return 1; | 2484 | return -EFSCORRUPTED; |
2485 | } | 2485 | } |
2486 | 2486 | ||
2487 | segment_count = le32_to_cpu(raw_super->segment_count); | 2487 | segment_count = le32_to_cpu(raw_super->segment_count); |
@@ -2495,7 +2495,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, | |||
2495 | if (segment_count > F2FS_MAX_SEGMENT || | 2495 | if (segment_count > F2FS_MAX_SEGMENT || |
2496 | segment_count < F2FS_MIN_SEGMENTS) { | 2496 | segment_count < F2FS_MIN_SEGMENTS) { |
2497 | f2fs_info(sbi, "Invalid segment count (%u)", segment_count); | 2497 | f2fs_info(sbi, "Invalid segment count (%u)", segment_count); |
2498 | return 1; | 2498 | return -EFSCORRUPTED; |
2499 | } | 2499 | } |
2500 | 2500 | ||
2501 | if (total_sections > segment_count || | 2501 | if (total_sections > segment_count || |
@@ -2503,25 +2503,25 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, | |||
2503 | segs_per_sec > segment_count || !segs_per_sec) { | 2503 | segs_per_sec > segment_count || !segs_per_sec) { |
2504 | f2fs_info(sbi, "Invalid segment/section count (%u, %u x %u)", | 2504 | f2fs_info(sbi, "Invalid segment/section count (%u, %u x %u)", |
2505 | segment_count, total_sections, segs_per_sec); | 2505 | segment_count, total_sections, segs_per_sec); |
2506 | return 1; | 2506 | return -EFSCORRUPTED; |
2507 | } | 2507 | } |
2508 | 2508 | ||
2509 | if ((segment_count / segs_per_sec) < total_sections) { | 2509 | if ((segment_count / segs_per_sec) < total_sections) { |
2510 | f2fs_info(sbi, "Small segment_count (%u < %u * %u)", | 2510 | f2fs_info(sbi, "Small segment_count (%u < %u * %u)", |
2511 | segment_count, segs_per_sec, total_sections); | 2511 | segment_count, segs_per_sec, total_sections); |
2512 | return 1; | 2512 | return -EFSCORRUPTED; |
2513 | } | 2513 | } |
2514 | 2514 | ||
2515 | if (segment_count > (le64_to_cpu(raw_super->block_count) >> 9)) { | 2515 | if (segment_count > (le64_to_cpu(raw_super->block_count) >> 9)) { |
2516 | f2fs_info(sbi, "Wrong segment_count / block_count (%u > %llu)", | 2516 | f2fs_info(sbi, "Wrong segment_count / block_count (%u > %llu)", |
2517 | segment_count, le64_to_cpu(raw_super->block_count)); | 2517 | segment_count, le64_to_cpu(raw_super->block_count)); |
2518 | return 1; | 2518 | return -EFSCORRUPTED; |
2519 | } | 2519 | } |
2520 | 2520 | ||
2521 | if (secs_per_zone > total_sections || !secs_per_zone) { | 2521 | if (secs_per_zone > total_sections || !secs_per_zone) { |
2522 | f2fs_info(sbi, "Wrong secs_per_zone / total_sections (%u, %u)", | 2522 | f2fs_info(sbi, "Wrong secs_per_zone / total_sections (%u, %u)", |
2523 | secs_per_zone, total_sections); | 2523 | secs_per_zone, total_sections); |
2524 | return 1; | 2524 | return -EFSCORRUPTED; |
2525 | } | 2525 | } |
2526 | if (le32_to_cpu(raw_super->extension_count) > F2FS_MAX_EXTENSION || | 2526 | if (le32_to_cpu(raw_super->extension_count) > F2FS_MAX_EXTENSION || |
2527 | raw_super->hot_ext_count > F2FS_MAX_EXTENSION || | 2527 | raw_super->hot_ext_count > F2FS_MAX_EXTENSION || |
@@ -2531,7 +2531,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, | |||
2531 | le32_to_cpu(raw_super->extension_count), | 2531 | le32_to_cpu(raw_super->extension_count), |
2532 | raw_super->hot_ext_count, | 2532 | raw_super->hot_ext_count, |
2533 | F2FS_MAX_EXTENSION); | 2533 | F2FS_MAX_EXTENSION); |
2534 | return 1; | 2534 | return -EFSCORRUPTED; |
2535 | } | 2535 | } |
2536 | 2536 | ||
2537 | if (le32_to_cpu(raw_super->cp_payload) > | 2537 | if (le32_to_cpu(raw_super->cp_payload) > |
@@ -2539,7 +2539,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, | |||
2539 | f2fs_info(sbi, "Insane cp_payload (%u > %u)", | 2539 | f2fs_info(sbi, "Insane cp_payload (%u > %u)", |
2540 | le32_to_cpu(raw_super->cp_payload), | 2540 | le32_to_cpu(raw_super->cp_payload), |
2541 | blocks_per_seg - F2FS_CP_PACKS); | 2541 | blocks_per_seg - F2FS_CP_PACKS); |
2542 | return 1; | 2542 | return -EFSCORRUPTED; |
2543 | } | 2543 | } |
2544 | 2544 | ||
2545 | /* check reserved ino info */ | 2545 | /* check reserved ino info */ |
@@ -2550,12 +2550,12 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, | |||
2550 | le32_to_cpu(raw_super->node_ino), | 2550 | le32_to_cpu(raw_super->node_ino), |
2551 | le32_to_cpu(raw_super->meta_ino), | 2551 | le32_to_cpu(raw_super->meta_ino), |
2552 | le32_to_cpu(raw_super->root_ino)); | 2552 | le32_to_cpu(raw_super->root_ino)); |
2553 | return 1; | 2553 | return -EFSCORRUPTED; |
2554 | } | 2554 | } |
2555 | 2555 | ||
2556 | /* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */ | 2556 | /* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */ |
2557 | if (sanity_check_area_boundary(sbi, bh)) | 2557 | if (sanity_check_area_boundary(sbi, bh)) |
2558 | return 1; | 2558 | return -EFSCORRUPTED; |
2559 | 2559 | ||
2560 | return 0; | 2560 | return 0; |
2561 | } | 2561 | } |
@@ -2872,10 +2872,10 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi, | |||
2872 | } | 2872 | } |
2873 | 2873 | ||
2874 | /* sanity checking of raw super */ | 2874 | /* sanity checking of raw super */ |
2875 | if (sanity_check_raw_super(sbi, bh)) { | 2875 | err = sanity_check_raw_super(sbi, bh); |
2876 | if (err) { | ||
2876 | f2fs_err(sbi, "Can't find valid F2FS filesystem in %dth superblock", | 2877 | f2fs_err(sbi, "Can't find valid F2FS filesystem in %dth superblock", |
2877 | block + 1); | 2878 | block + 1); |
2878 | err = -EFSCORRUPTED; | ||
2879 | brelse(bh); | 2879 | brelse(bh); |
2880 | continue; | 2880 | continue; |
2881 | } | 2881 | } |