Skip to content

Commit 95fa90c

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: support recording errors into superblock
This patch supports to record detail reason of FSCORRUPTED error into f2fs_super_block.s_errors[]. Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent a9cfee0 commit 95fa90c

File tree

16 files changed

+150
-9
lines changed

16 files changed

+150
-9
lines changed

fs/f2fs/compress.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,7 @@ void f2fs_decompress_cluster(struct decompress_io_ctx *dic, bool in_task)
762762

763763
if (dic->clen > PAGE_SIZE * dic->nr_cpages - COMPRESS_HEADER_SIZE) {
764764
ret = -EFSCORRUPTED;
765+
f2fs_handle_error(sbi, ERROR_FAIL_DECOMPRESSION);
765766
goto out_release;
766767
}
767768

@@ -950,6 +951,7 @@ static int __f2fs_cluster_blocks(struct inode *inode,
950951

951952
if (f2fs_sanity_check_cluster(&dn)) {
952953
ret = -EFSCORRUPTED;
954+
f2fs_handle_error(F2FS_I_SB(inode), ERROR_CORRUPTED_CLUSTER);
953955
goto fail;
954956
}
955957

fs/f2fs/data.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -705,8 +705,10 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
705705

706706
if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
707707
fio->is_por ? META_POR : (__is_meta_io(fio) ?
708-
META_GENERIC : DATA_GENERIC_ENHANCE)))
708+
META_GENERIC : DATA_GENERIC_ENHANCE))) {
709+
f2fs_handle_error(fio->sbi, ERROR_INVALID_BLKADDR);
709710
return -EFSCORRUPTED;
711+
}
710712

711713
trace_f2fs_submit_page_bio(page, fio);
712714

@@ -906,8 +908,10 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
906908
fio->encrypted_page : fio->page;
907909

908910
if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
909-
__is_meta_io(fio) ? META_GENERIC : DATA_GENERIC))
911+
__is_meta_io(fio) ? META_GENERIC : DATA_GENERIC)) {
912+
f2fs_handle_error(fio->sbi, ERROR_INVALID_BLKADDR);
910913
return -EFSCORRUPTED;
914+
}
911915

912916
trace_f2fs_submit_page_bio(page, fio);
913917

@@ -1217,6 +1221,8 @@ struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
12171221
if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr,
12181222
DATA_GENERIC_ENHANCE_READ)) {
12191223
err = -EFSCORRUPTED;
1224+
f2fs_handle_error(F2FS_I_SB(inode),
1225+
ERROR_INVALID_BLKADDR);
12201226
goto put_err;
12211227
}
12221228
goto got_it;
@@ -1237,6 +1243,8 @@ struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
12371243
dn.data_blkaddr,
12381244
DATA_GENERIC_ENHANCE)) {
12391245
err = -EFSCORRUPTED;
1246+
f2fs_handle_error(F2FS_I_SB(inode),
1247+
ERROR_INVALID_BLKADDR);
12401248
goto put_err;
12411249
}
12421250
got_it:
@@ -1550,6 +1558,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
15501558
if (__is_valid_data_blkaddr(blkaddr) &&
15511559
!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) {
15521560
err = -EFSCORRUPTED;
1561+
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
15531562
goto sync_out;
15541563
}
15551564

@@ -1595,6 +1604,8 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
15951604
(flag != F2FS_GET_BLOCK_FIEMAP ||
15961605
IS_ENABLED(CONFIG_F2FS_CHECK_FS))) {
15971606
err = -EFSCORRUPTED;
1607+
f2fs_handle_error(sbi,
1608+
ERROR_CORRUPTED_CLUSTER);
15981609
goto sync_out;
15991610
}
16001611
if (flag == F2FS_GET_BLOCK_BMAP) {
@@ -2076,6 +2087,8 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page,
20762087
if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr,
20772088
DATA_GENERIC_ENHANCE_READ)) {
20782089
ret = -EFSCORRUPTED;
2090+
f2fs_handle_error(F2FS_I_SB(inode),
2091+
ERROR_INVALID_BLKADDR);
20792092
goto out;
20802093
}
20812094
} else {
@@ -2619,8 +2632,11 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
26192632
fio->old_blkaddr = ei.blk + page->index - ei.fofs;
26202633

26212634
if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
2622-
DATA_GENERIC_ENHANCE))
2635+
DATA_GENERIC_ENHANCE)) {
2636+
f2fs_handle_error(fio->sbi,
2637+
ERROR_INVALID_BLKADDR);
26232638
return -EFSCORRUPTED;
2639+
}
26242640

26252641
ipu_force = true;
26262642
fio->need_lock = LOCK_DONE;
@@ -2648,6 +2664,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
26482664
!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
26492665
DATA_GENERIC_ENHANCE)) {
26502666
err = -EFSCORRUPTED;
2667+
f2fs_handle_error(fio->sbi, ERROR_INVALID_BLKADDR);
26512668
goto out_writepage;
26522669
}
26532670

@@ -3561,6 +3578,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
35613578
if (!f2fs_is_valid_blkaddr(sbi, blkaddr,
35623579
DATA_GENERIC_ENHANCE_READ)) {
35633580
err = -EFSCORRUPTED;
3581+
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
35643582
goto fail;
35653583
}
35663584
err = f2fs_submit_page_read(inode, page, blkaddr, 0, true);

fs/f2fs/dir.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
10411041
__func__, le16_to_cpu(de->name_len));
10421042
set_sbi_flag(sbi, SBI_NEED_FSCK);
10431043
err = -EFSCORRUPTED;
1044+
f2fs_handle_error(sbi, ERROR_CORRUPTED_DIRENT);
10441045
goto out;
10451046
}
10461047

fs/f2fs/f2fs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,6 +1815,10 @@ struct f2fs_sb_info {
18151815

18161816
struct workqueue_struct *post_read_wq; /* post read workqueue */
18171817

1818+
unsigned char errors[MAX_F2FS_ERRORS]; /* error flags */
1819+
spinlock_t error_lock; /* protect errors array */
1820+
bool error_dirty; /* errors of sb is dirty */
1821+
18181822
struct kmem_cache *inline_xattr_slab; /* inline xattr entry */
18191823
unsigned int inline_xattr_slab_size; /* default inline xattr slab size */
18201824

@@ -3557,6 +3561,7 @@ int f2fs_quota_sync(struct super_block *sb, int type);
35573561
loff_t max_file_blocks(struct inode *inode);
35583562
void f2fs_quota_off_umount(struct super_block *sb);
35593563
void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason);
3564+
void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error);
35603565
int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
35613566
int f2fs_sync_fs(struct super_block *sb, int sync);
35623567
int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);

fs/f2fs/file.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,7 @@ static int __read_out_blkaddrs(struct inode *inode, block_t *blkaddr,
11561156
!f2fs_is_valid_blkaddr(sbi, *blkaddr,
11571157
DATA_GENERIC_ENHANCE)) {
11581158
f2fs_put_dnode(&dn);
1159+
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
11591160
return -EFSCORRUPTED;
11601161
}
11611162

@@ -1440,6 +1441,7 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start,
14401441
if (!f2fs_is_valid_blkaddr(sbi, dn->data_blkaddr,
14411442
DATA_GENERIC_ENHANCE)) {
14421443
ret = -EFSCORRUPTED;
1444+
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
14431445
break;
14441446
}
14451447

@@ -3323,8 +3325,10 @@ static int release_compress_blocks(struct dnode_of_data *dn, pgoff_t count)
33233325
if (!__is_valid_data_blkaddr(blkaddr))
33243326
continue;
33253327
if (unlikely(!f2fs_is_valid_blkaddr(sbi, blkaddr,
3326-
DATA_GENERIC_ENHANCE)))
3328+
DATA_GENERIC_ENHANCE))) {
3329+
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
33273330
return -EFSCORRUPTED;
3331+
}
33283332
}
33293333

33303334
while (count) {
@@ -3485,8 +3489,10 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count)
34853489
if (!__is_valid_data_blkaddr(blkaddr))
34863490
continue;
34873491
if (unlikely(!f2fs_is_valid_blkaddr(sbi, blkaddr,
3488-
DATA_GENERIC_ENHANCE)))
3492+
DATA_GENERIC_ENHANCE))) {
3493+
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
34893494
return -EFSCORRUPTED;
3495+
}
34903496
}
34913497

34923498
while (count) {
@@ -3758,6 +3764,8 @@ static int f2fs_sec_trim_file(struct file *filp, unsigned long arg)
37583764
DATA_GENERIC_ENHANCE)) {
37593765
ret = -EFSCORRUPTED;
37603766
f2fs_put_dnode(&dn);
3767+
f2fs_handle_error(sbi,
3768+
ERROR_INVALID_BLKADDR);
37613769
goto out;
37623770
}
37633771

fs/f2fs/gc.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
11641164
if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
11651165
DATA_GENERIC_ENHANCE_READ))) {
11661166
err = -EFSCORRUPTED;
1167+
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
11671168
goto put_page;
11681169
}
11691170
goto got_it;
@@ -1182,6 +1183,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
11821183
if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
11831184
DATA_GENERIC_ENHANCE))) {
11841185
err = -EFSCORRUPTED;
1186+
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
11851187
goto put_page;
11861188
}
11871189
got_it:

fs/f2fs/inline.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)
160160
set_sbi_flag(fio.sbi, SBI_NEED_FSCK);
161161
f2fs_warn(fio.sbi, "%s: corrupted inline inode ino=%lx, i_addr[0]:0x%x, run fsck to fix.",
162162
__func__, dn->inode->i_ino, dn->data_blkaddr);
163+
f2fs_handle_error(fio.sbi, ERROR_INVALID_BLKADDR);
163164
return -EFSCORRUPTED;
164165
}
165166

@@ -412,6 +413,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,
412413
set_sbi_flag(F2FS_P_SB(page), SBI_NEED_FSCK);
413414
f2fs_warn(F2FS_P_SB(page), "%s: corrupted inline inode ino=%lx, i_addr[0]:0x%x, run fsck to fix.",
414415
__func__, dir->i_ino, dn.data_blkaddr);
416+
f2fs_handle_error(F2FS_P_SB(page), ERROR_INVALID_BLKADDR);
415417
err = -EFSCORRUPTED;
416418
goto out;
417419
}

fs/f2fs/inode.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,10 @@ static int __written_first_block(struct f2fs_sb_info *sbi,
8181

8282
if (!__is_valid_data_blkaddr(addr))
8383
return 1;
84-
if (!f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC_ENHANCE))
84+
if (!f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC_ENHANCE)) {
85+
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
8586
return -EFSCORRUPTED;
87+
}
8688
return 0;
8789
}
8890

@@ -415,6 +417,7 @@ static int do_read_inode(struct inode *inode)
415417

416418
if (!sanity_check_inode(inode, node_page)) {
417419
f2fs_put_page(node_page, 1);
420+
f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
418421
return -EFSCORRUPTED;
419422
}
420423

@@ -510,6 +513,7 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
510513
ret = -EFSCORRUPTED;
511514
trace_f2fs_iget_exit(inode, ret);
512515
iput(inode);
516+
f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
513517
return ERR_PTR(ret);
514518
}
515519

fs/f2fs/node.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ int f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
3636
set_sbi_flag(sbi, SBI_NEED_FSCK);
3737
f2fs_warn(sbi, "%s: out-of-range nid=%x, run fsck to fix.",
3838
__func__, nid);
39+
f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
3940
return -EFSCORRUPTED;
4041
}
4142
return 0;
@@ -1295,6 +1296,7 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs)
12951296
if (unlikely(new_ni.blk_addr != NULL_ADDR)) {
12961297
err = -EFSCORRUPTED;
12971298
set_sbi_flag(sbi, SBI_NEED_FSCK);
1299+
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
12981300
goto fail;
12991301
}
13001302
#endif

fs/f2fs/recovery.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
507507
if (ofs_in_node >= max_addrs) {
508508
f2fs_err(sbi, "Inconsistent ofs_in_node:%u in summary, ino:%lu, nid:%u, max:%u",
509509
ofs_in_node, dn->inode->i_ino, nid, max_addrs);
510+
f2fs_handle_error(sbi, ERROR_INCONSISTENT_SUMMARY);
510511
return -EFSCORRUPTED;
511512
}
512513

@@ -637,6 +638,7 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
637638
inode->i_ino, ofs_of_node(dn.node_page),
638639
ofs_of_node(page));
639640
err = -EFSCORRUPTED;
641+
f2fs_handle_error(sbi, ERROR_INCONSISTENT_FOOTER);
640642
goto err;
641643
}
642644

@@ -649,12 +651,14 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
649651
if (__is_valid_data_blkaddr(src) &&
650652
!f2fs_is_valid_blkaddr(sbi, src, META_POR)) {
651653
err = -EFSCORRUPTED;
654+
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
652655
goto err;
653656
}
654657

655658
if (__is_valid_data_blkaddr(dest) &&
656659
!f2fs_is_valid_blkaddr(sbi, dest, META_POR)) {
657660
err = -EFSCORRUPTED;
661+
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
658662
goto err;
659663
}
660664

@@ -712,6 +716,8 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
712716
f2fs_err(sbi, "Inconsistent dest blkaddr:%u, ino:%lu, ofs:%u",
713717
dest, inode->i_ino, dn.ofs_in_node);
714718
err = -EFSCORRUPTED;
719+
f2fs_handle_error(sbi,
720+
ERROR_INVALID_BLKADDR);
715721
goto err;
716722
}
717723

0 commit comments

Comments
 (0)