summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChao Yu <yuchao0@huawei.com>2019-04-15 03:26:32 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2019-05-09 00:23:13 -0400
commit93770ab7a6e963147a5dbca25278b69ba6c8f8c5 (patch)
tree5030246c51d3885756843c072221be39a7f49deb
parent896285ad02ea1e8a7cedbceb5e5656335b7ae563 (diff)
f2fs: introduce DATA_GENERIC_ENHANCE
Previously, f2fs_is_valid_blkaddr(, blkaddr, DATA_GENERIC) will check whether @blkaddr locates in main area or not. That check is weak, since the block address in range of main area can point to the address which is not valid in segment info table, and we can not detect such condition, we may suffer worse corruption as system continues running. So this patch introduce DATA_GENERIC_ENHANCE to enhance the sanity check which trigger SIT bitmap check rather than only range check. This patch did below changes as wel: - set SBI_NEED_FSCK in f2fs_is_valid_blkaddr(). - get rid of is_valid_data_blkaddr() to avoid panic if blkaddr is invalid. - introduce verify_fio_blkaddr() to wrap fio {new,old}_blkaddr validation check. - spread blkaddr check in: * f2fs_get_node_info() * __read_out_blkaddrs() * f2fs_submit_page_read() * ra_data_block() * do_recover_data() This patch can fix bug reported from bugzilla below: https://bugzilla.kernel.org/show_bug.cgi?id=203215 https://bugzilla.kernel.org/show_bug.cgi?id=203223 https://bugzilla.kernel.org/show_bug.cgi?id=203231 https://bugzilla.kernel.org/show_bug.cgi?id=203235 https://bugzilla.kernel.org/show_bug.cgi?id=203241 = Update by Jaegeuk Kim = DATA_GENERIC_ENHANCE enhanced to validate block addresses on read/write paths. But, xfstest/generic/446 compalins some generated kernel messages saying invalid bitmap was detected when reading a block. The reaons is, when we get the block addresses from extent_cache, there is no lock to synchronize it from truncating the blocks in parallel. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--fs/f2fs/checkpoint.c43
-rw-r--r--fs/f2fs/data.c49
-rw-r--r--fs/f2fs/f2fs.h18
-rw-r--r--fs/f2fs/file.c15
-rw-r--r--fs/f2fs/gc.c11
-rw-r--r--fs/f2fs/inode.c7
-rw-r--r--fs/f2fs/node.c13
-rw-r--r--fs/f2fs/recovery.c12
-rw-r--r--fs/f2fs/segment.c4
-rw-r--r--fs/f2fs/segment.h13
10 files changed, 134 insertions, 51 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index b8614cf77cdd..805a33088e82 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -130,6 +130,30 @@ struct page *f2fs_get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index)
130 return __get_meta_page(sbi, index, false); 130 return __get_meta_page(sbi, index, false);
131} 131}
132 132
133static bool __is_bitmap_valid(struct f2fs_sb_info *sbi, block_t blkaddr,
134 int type)
135{
136 struct seg_entry *se;
137 unsigned int segno, offset;
138 bool exist;
139
140 if (type != DATA_GENERIC_ENHANCE && type != DATA_GENERIC_ENHANCE_READ)
141 return true;
142
143 segno = GET_SEGNO(sbi, blkaddr);
144 offset = GET_BLKOFF_FROM_SEG0(sbi, blkaddr);
145 se = get_seg_entry(sbi, segno);
146
147 exist = f2fs_test_bit(offset, se->cur_valid_map);
148 if (!exist && type == DATA_GENERIC_ENHANCE) {
149 f2fs_msg(sbi->sb, KERN_ERR, "Inconsistent error "
150 "blkaddr:%u, sit bitmap:%d", blkaddr, exist);
151 set_sbi_flag(sbi, SBI_NEED_FSCK);
152 WARN_ON(1);
153 }
154 return exist;
155}
156
133bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi, 157bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
134 block_t blkaddr, int type) 158 block_t blkaddr, int type)
135{ 159{
@@ -151,15 +175,22 @@ bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
151 return false; 175 return false;
152 break; 176 break;
153 case META_POR: 177 case META_POR:
178 if (unlikely(blkaddr >= MAX_BLKADDR(sbi) ||
179 blkaddr < MAIN_BLKADDR(sbi)))
180 return false;
181 break;
154 case DATA_GENERIC: 182 case DATA_GENERIC:
183 case DATA_GENERIC_ENHANCE:
184 case DATA_GENERIC_ENHANCE_READ:
155 if (unlikely(blkaddr >= MAX_BLKADDR(sbi) || 185 if (unlikely(blkaddr >= MAX_BLKADDR(sbi) ||
156 blkaddr < MAIN_BLKADDR(sbi))) { 186 blkaddr < MAIN_BLKADDR(sbi))) {
157 if (type == DATA_GENERIC) { 187 f2fs_msg(sbi->sb, KERN_WARNING,
158 f2fs_msg(sbi->sb, KERN_WARNING, 188 "access invalid blkaddr:%u", blkaddr);
159 "access invalid blkaddr:%u", blkaddr); 189 set_sbi_flag(sbi, SBI_NEED_FSCK);
160 WARN_ON(1); 190 WARN_ON(1);
161 }
162 return false; 191 return false;
192 } else {
193 return __is_bitmap_valid(sbi, blkaddr, type);
163 } 194 }
164 break; 195 break;
165 case META_GENERIC: 196 case META_GENERIC:
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index cf89e36577bf..d32a82f25f5a 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -456,8 +456,8 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
456 fio->encrypted_page : fio->page; 456 fio->encrypted_page : fio->page;
457 457
458 if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr, 458 if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
459 fio->is_por ? META_POR : 459 fio->is_por ? META_POR : (__is_meta_io(fio) ?
460 (__is_meta_io(fio) ? META_GENERIC : DATA_GENERIC))) 460 META_GENERIC : DATA_GENERIC_ENHANCE)))
461 return -EFAULT; 461 return -EFAULT;
462 462
463 trace_f2fs_submit_page_bio(page, fio); 463 trace_f2fs_submit_page_bio(page, fio);
@@ -507,9 +507,7 @@ next:
507 spin_unlock(&io->io_lock); 507 spin_unlock(&io->io_lock);
508 } 508 }
509 509
510 if (__is_valid_data_blkaddr(fio->old_blkaddr)) 510 verify_fio_blkaddr(fio);
511 verify_block_addr(fio, fio->old_blkaddr);
512 verify_block_addr(fio, fio->new_blkaddr);
513 511
514 bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page; 512 bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page;
515 513
@@ -566,9 +564,6 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
566 struct bio_post_read_ctx *ctx; 564 struct bio_post_read_ctx *ctx;
567 unsigned int post_read_steps = 0; 565 unsigned int post_read_steps = 0;
568 566
569 if (!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC))
570 return ERR_PTR(-EFAULT);
571
572 bio = f2fs_bio_alloc(sbi, min_t(int, nr_pages, BIO_MAX_PAGES), false); 567 bio = f2fs_bio_alloc(sbi, min_t(int, nr_pages, BIO_MAX_PAGES), false);
573 if (!bio) 568 if (!bio)
574 return ERR_PTR(-ENOMEM); 569 return ERR_PTR(-ENOMEM);
@@ -596,8 +591,10 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
596static int f2fs_submit_page_read(struct inode *inode, struct page *page, 591static int f2fs_submit_page_read(struct inode *inode, struct page *page,
597 block_t blkaddr) 592 block_t blkaddr)
598{ 593{
599 struct bio *bio = f2fs_grab_read_bio(inode, blkaddr, 1, 0); 594 struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
595 struct bio *bio;
600 596
597 bio = f2fs_grab_read_bio(inode, blkaddr, 1, 0);
601 if (IS_ERR(bio)) 598 if (IS_ERR(bio))
602 return PTR_ERR(bio); 599 return PTR_ERR(bio);
603 600
@@ -609,8 +606,8 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page,
609 return -EFAULT; 606 return -EFAULT;
610 } 607 }
611 ClearPageError(page); 608 ClearPageError(page);
612 inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA); 609 inc_page_count(sbi, F2FS_RD_DATA);
613 __submit_bio(F2FS_I_SB(inode), bio, DATA); 610 __submit_bio(sbi, bio, DATA);
614 return 0; 611 return 0;
615} 612}
616 613
@@ -738,6 +735,11 @@ struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
738 735
739 if (f2fs_lookup_extent_cache(inode, index, &ei)) { 736 if (f2fs_lookup_extent_cache(inode, index, &ei)) {
740 dn.data_blkaddr = ei.blk + index - ei.fofs; 737 dn.data_blkaddr = ei.blk + index - ei.fofs;
738 if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr,
739 DATA_GENERIC_ENHANCE_READ)) {
740 err = -EFAULT;
741 goto put_err;
742 }
741 goto got_it; 743 goto got_it;
742 } 744 }
743 745
@@ -751,6 +753,13 @@ struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
751 err = -ENOENT; 753 err = -ENOENT;
752 goto put_err; 754 goto put_err;
753 } 755 }
756 if (dn.data_blkaddr != NEW_ADDR &&
757 !f2fs_is_valid_blkaddr(F2FS_I_SB(inode),
758 dn.data_blkaddr,
759 DATA_GENERIC_ENHANCE)) {
760 err = -EFAULT;
761 goto put_err;
762 }
754got_it: 763got_it:
755 if (PageUptodate(page)) { 764 if (PageUptodate(page)) {
756 unlock_page(page); 765 unlock_page(page);
@@ -1093,12 +1102,12 @@ next_block:
1093 blkaddr = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node); 1102 blkaddr = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node);
1094 1103
1095 if (__is_valid_data_blkaddr(blkaddr) && 1104 if (__is_valid_data_blkaddr(blkaddr) &&
1096 !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC)) { 1105 !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) {
1097 err = -EFAULT; 1106 err = -EFAULT;
1098 goto sync_out; 1107 goto sync_out;
1099 } 1108 }
1100 1109
1101 if (is_valid_data_blkaddr(sbi, blkaddr)) { 1110 if (__is_valid_data_blkaddr(blkaddr)) {
1102 /* use out-place-update for driect IO under LFS mode */ 1111 /* use out-place-update for driect IO under LFS mode */
1103 if (test_opt(sbi, LFS) && flag == F2FS_GET_BLOCK_DIO && 1112 if (test_opt(sbi, LFS) && flag == F2FS_GET_BLOCK_DIO &&
1104 map->m_may_create) { 1113 map->m_may_create) {
@@ -1563,7 +1572,7 @@ got_it:
1563 } 1572 }
1564 1573
1565 if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr, 1574 if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr,
1566 DATA_GENERIC)) { 1575 DATA_GENERIC_ENHANCE_READ)) {
1567 ret = -EFAULT; 1576 ret = -EFAULT;
1568 goto out; 1577 goto out;
1569 } 1578 }
@@ -1844,7 +1853,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
1844 fio->old_blkaddr = ei.blk + page->index - ei.fofs; 1853 fio->old_blkaddr = ei.blk + page->index - ei.fofs;
1845 1854
1846 if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, 1855 if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
1847 DATA_GENERIC)) 1856 DATA_GENERIC_ENHANCE))
1848 return -EFAULT; 1857 return -EFAULT;
1849 1858
1850 ipu_force = true; 1859 ipu_force = true;
@@ -1871,7 +1880,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
1871got_it: 1880got_it:
1872 if (__is_valid_data_blkaddr(fio->old_blkaddr) && 1881 if (__is_valid_data_blkaddr(fio->old_blkaddr) &&
1873 !f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, 1882 !f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
1874 DATA_GENERIC)) { 1883 DATA_GENERIC_ENHANCE)) {
1875 err = -EFAULT; 1884 err = -EFAULT;
1876 goto out_writepage; 1885 goto out_writepage;
1877 } 1886 }
@@ -1879,7 +1888,8 @@ got_it:
1879 * If current allocation needs SSR, 1888 * If current allocation needs SSR,
1880 * it had better in-place writes for updated data. 1889 * it had better in-place writes for updated data.
1881 */ 1890 */
1882 if (ipu_force || (is_valid_data_blkaddr(fio->sbi, fio->old_blkaddr) && 1891 if (ipu_force ||
1892 (__is_valid_data_blkaddr(fio->old_blkaddr) &&
1883 need_inplace_update(fio))) { 1893 need_inplace_update(fio))) {
1884 err = encrypt_one_page(fio); 1894 err = encrypt_one_page(fio);
1885 if (err) 1895 if (err)
@@ -2524,6 +2534,11 @@ repeat:
2524 zero_user_segment(page, 0, PAGE_SIZE); 2534 zero_user_segment(page, 0, PAGE_SIZE);
2525 SetPageUptodate(page); 2535 SetPageUptodate(page);
2526 } else { 2536 } else {
2537 if (!f2fs_is_valid_blkaddr(sbi, blkaddr,
2538 DATA_GENERIC_ENHANCE_READ)) {
2539 err = -EFAULT;
2540 goto fail;
2541 }
2527 err = f2fs_submit_page_read(inode, page, blkaddr); 2542 err = f2fs_submit_page_read(inode, page, blkaddr);
2528 if (err) 2543 if (err)
2529 goto fail; 2544 goto fail;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 1c814a309748..533fafca68f4 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -210,7 +210,14 @@ enum {
210 META_SSA, 210 META_SSA,
211 META_MAX, 211 META_MAX,
212 META_POR, 212 META_POR,
213 DATA_GENERIC, 213 DATA_GENERIC, /* check range only */
214 DATA_GENERIC_ENHANCE, /* strong check on range and segment bitmap */
215 DATA_GENERIC_ENHANCE_READ, /*
216 * strong check on range and segment
217 * bitmap but no warning due to race
218 * condition of read on truncated area
219 * by extent_cache
220 */
214 META_GENERIC, 221 META_GENERIC,
215}; 222};
216 223
@@ -2864,15 +2871,6 @@ static inline bool __is_valid_data_blkaddr(block_t blkaddr)
2864 return true; 2871 return true;
2865} 2872}
2866 2873
2867static inline bool is_valid_data_blkaddr(struct f2fs_sb_info *sbi,
2868 block_t blkaddr)
2869{
2870 if (!__is_valid_data_blkaddr(blkaddr))
2871 return false;
2872 verify_blkaddr(sbi, blkaddr, DATA_GENERIC);
2873 return true;
2874}
2875
2876static inline void f2fs_set_page_private(struct page *page, 2874static inline void f2fs_set_page_private(struct page *page,
2877 unsigned long data) 2875 unsigned long data)
2878{ 2876{
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index e5fa1940ed3c..3baa39e3e1fd 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -356,7 +356,7 @@ static bool __found_offset(struct f2fs_sb_info *sbi, block_t blkaddr,
356 switch (whence) { 356 switch (whence) {
357 case SEEK_DATA: 357 case SEEK_DATA:
358 if ((blkaddr == NEW_ADDR && dirty == pgofs) || 358 if ((blkaddr == NEW_ADDR && dirty == pgofs) ||
359 is_valid_data_blkaddr(sbi, blkaddr)) 359 __is_valid_data_blkaddr(blkaddr))
360 return true; 360 return true;
361 break; 361 break;
362 case SEEK_HOLE: 362 case SEEK_HOLE:
@@ -422,7 +422,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
422 422
423 if (__is_valid_data_blkaddr(blkaddr) && 423 if (__is_valid_data_blkaddr(blkaddr) &&
424 !f2fs_is_valid_blkaddr(F2FS_I_SB(inode), 424 !f2fs_is_valid_blkaddr(F2FS_I_SB(inode),
425 blkaddr, DATA_GENERIC)) { 425 blkaddr, DATA_GENERIC_ENHANCE)) {
426 f2fs_put_dnode(&dn); 426 f2fs_put_dnode(&dn);
427 goto fail; 427 goto fail;
428 } 428 }
@@ -523,7 +523,8 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count)
523 f2fs_set_data_blkaddr(dn); 523 f2fs_set_data_blkaddr(dn);
524 524
525 if (__is_valid_data_blkaddr(blkaddr) && 525 if (__is_valid_data_blkaddr(blkaddr) &&
526 !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC)) 526 !f2fs_is_valid_blkaddr(sbi, blkaddr,
527 DATA_GENERIC_ENHANCE))
527 continue; 528 continue;
528 529
529 f2fs_invalidate_blocks(sbi, blkaddr); 530 f2fs_invalidate_blocks(sbi, blkaddr);
@@ -1018,6 +1019,14 @@ next_dnode:
1018 for (i = 0; i < done; i++, blkaddr++, do_replace++, dn.ofs_in_node++) { 1019 for (i = 0; i < done; i++, blkaddr++, do_replace++, dn.ofs_in_node++) {
1019 *blkaddr = datablock_addr(dn.inode, 1020 *blkaddr = datablock_addr(dn.inode,
1020 dn.node_page, dn.ofs_in_node); 1021 dn.node_page, dn.ofs_in_node);
1022
1023 if (__is_valid_data_blkaddr(*blkaddr) &&
1024 !f2fs_is_valid_blkaddr(sbi, *blkaddr,
1025 DATA_GENERIC_ENHANCE)) {
1026 f2fs_put_dnode(&dn);
1027 return -EFAULT;
1028 }
1029
1021 if (!f2fs_is_checkpointed_data(sbi, *blkaddr)) { 1030 if (!f2fs_is_checkpointed_data(sbi, *blkaddr)) {
1022 1031
1023 if (test_opt(sbi, LFS)) { 1032 if (test_opt(sbi, LFS)) {
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index ba30ec90952f..963fb4571fd9 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -656,6 +656,11 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
656 656
657 if (f2fs_lookup_extent_cache(inode, index, &ei)) { 657 if (f2fs_lookup_extent_cache(inode, index, &ei)) {
658 dn.data_blkaddr = ei.blk + index - ei.fofs; 658 dn.data_blkaddr = ei.blk + index - ei.fofs;
659 if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
660 DATA_GENERIC_ENHANCE_READ))) {
661 err = -EFAULT;
662 goto put_page;
663 }
659 goto got_it; 664 goto got_it;
660 } 665 }
661 666
@@ -665,8 +670,12 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
665 goto put_page; 670 goto put_page;
666 f2fs_put_dnode(&dn); 671 f2fs_put_dnode(&dn);
667 672
673 if (!__is_valid_data_blkaddr(dn.data_blkaddr)) {
674 err = -ENOENT;
675 goto put_page;
676 }
668 if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr, 677 if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
669 DATA_GENERIC))) { 678 DATA_GENERIC_ENHANCE))) {
670 err = -EFAULT; 679 err = -EFAULT;
671 goto put_page; 680 goto put_page;
672 } 681 }
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index b53952a15ffa..ccb02226dd2c 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -73,7 +73,7 @@ static int __written_first_block(struct f2fs_sb_info *sbi,
73 73
74 if (!__is_valid_data_blkaddr(addr)) 74 if (!__is_valid_data_blkaddr(addr))
75 return 1; 75 return 1;
76 if (!f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC)) 76 if (!f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC_ENHANCE))
77 return -EFAULT; 77 return -EFAULT;
78 return 0; 78 return 0;
79} 79}
@@ -267,9 +267,10 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page)
267 struct extent_info *ei = &F2FS_I(inode)->extent_tree->largest; 267 struct extent_info *ei = &F2FS_I(inode)->extent_tree->largest;
268 268
269 if (ei->len && 269 if (ei->len &&
270 (!f2fs_is_valid_blkaddr(sbi, ei->blk, DATA_GENERIC) || 270 (!f2fs_is_valid_blkaddr(sbi, ei->blk,
271 DATA_GENERIC_ENHANCE) ||
271 !f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1, 272 !f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1,
272 DATA_GENERIC))) { 273 DATA_GENERIC_ENHANCE))) {
273 set_sbi_flag(sbi, SBI_NEED_FSCK); 274 set_sbi_flag(sbi, SBI_NEED_FSCK);
274 f2fs_msg(sbi->sb, KERN_WARNING, 275 f2fs_msg(sbi->sb, KERN_WARNING,
275 "%s: inode (ino=%lx) extent info [%u, %u, %u] " 276 "%s: inode (ino=%lx) extent info [%u, %u, %u] "
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 057362a821a0..a6960b47f394 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -454,7 +454,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
454 new_blkaddr == NULL_ADDR); 454 new_blkaddr == NULL_ADDR);
455 f2fs_bug_on(sbi, nat_get_blkaddr(e) == NEW_ADDR && 455 f2fs_bug_on(sbi, nat_get_blkaddr(e) == NEW_ADDR &&
456 new_blkaddr == NEW_ADDR); 456 new_blkaddr == NEW_ADDR);
457 f2fs_bug_on(sbi, is_valid_data_blkaddr(sbi, nat_get_blkaddr(e)) && 457 f2fs_bug_on(sbi, __is_valid_data_blkaddr(nat_get_blkaddr(e)) &&
458 new_blkaddr == NEW_ADDR); 458 new_blkaddr == NEW_ADDR);
459 459
460 /* increment version no as node is removed */ 460 /* increment version no as node is removed */
@@ -465,7 +465,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
465 465
466 /* change address */ 466 /* change address */
467 nat_set_blkaddr(e, new_blkaddr); 467 nat_set_blkaddr(e, new_blkaddr);
468 if (!is_valid_data_blkaddr(sbi, new_blkaddr)) 468 if (!__is_valid_data_blkaddr(new_blkaddr))
469 set_nat_flag(e, IS_CHECKPOINTED, false); 469 set_nat_flag(e, IS_CHECKPOINTED, false);
470 __set_nat_cache_dirty(nm_i, e); 470 __set_nat_cache_dirty(nm_i, e);
471 471
@@ -526,6 +526,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
526 struct f2fs_nat_entry ne; 526 struct f2fs_nat_entry ne;
527 struct nat_entry *e; 527 struct nat_entry *e;
528 pgoff_t index; 528 pgoff_t index;
529 block_t blkaddr;
529 int i; 530 int i;
530 531
531 ni->nid = nid; 532 ni->nid = nid;
@@ -569,6 +570,11 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
569 node_info_from_raw_nat(ni, &ne); 570 node_info_from_raw_nat(ni, &ne);
570 f2fs_put_page(page, 1); 571 f2fs_put_page(page, 1);
571cache: 572cache:
573 blkaddr = le32_to_cpu(ne.block_addr);
574 if (__is_valid_data_blkaddr(blkaddr) &&
575 !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE))
576 return -EFAULT;
577
572 /* cache nat entry */ 578 /* cache nat entry */
573 cache_nat_entry(sbi, nid, &ne); 579 cache_nat_entry(sbi, nid, &ne);
574 return 0; 580 return 0;
@@ -1548,7 +1554,8 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
1548 } 1554 }
1549 1555
1550 if (__is_valid_data_blkaddr(ni.blk_addr) && 1556 if (__is_valid_data_blkaddr(ni.blk_addr) &&
1551 !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC)) { 1557 !f2fs_is_valid_blkaddr(sbi, ni.blk_addr,
1558 DATA_GENERIC_ENHANCE)) {
1552 up_read(&sbi->node_write); 1559 up_read(&sbi->node_write);
1553 goto redirty_out; 1560 goto redirty_out;
1554 } 1561 }
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index b14c718139a9..e04f82b3f4fc 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -567,6 +567,18 @@ retry_dn:
567 src = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node); 567 src = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node);
568 dest = datablock_addr(dn.inode, page, dn.ofs_in_node); 568 dest = datablock_addr(dn.inode, page, dn.ofs_in_node);
569 569
570 if (__is_valid_data_blkaddr(src) &&
571 !f2fs_is_valid_blkaddr(sbi, src, META_POR)) {
572 err = -EFAULT;
573 goto err;
574 }
575
576 if (__is_valid_data_blkaddr(dest) &&
577 !f2fs_is_valid_blkaddr(sbi, dest, META_POR)) {
578 err = -EFAULT;
579 goto err;
580 }
581
570 /* skip recovering if dest is the same as src */ 582 /* skip recovering if dest is the same as src */
571 if (src == dest) 583 if (src == dest)
572 continue; 584 continue;
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index d3bf7a2abbc9..8388d2abacb5 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2217,7 +2217,7 @@ bool f2fs_is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr)
2217 struct seg_entry *se; 2217 struct seg_entry *se;
2218 bool is_cp = false; 2218 bool is_cp = false;
2219 2219
2220 if (!is_valid_data_blkaddr(sbi, blkaddr)) 2220 if (!__is_valid_data_blkaddr(blkaddr))
2221 return true; 2221 return true;
2222 2222
2223 down_read(&sit_i->sentry_lock); 2223 down_read(&sit_i->sentry_lock);
@@ -3338,7 +3338,7 @@ void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr)
3338 if (!f2fs_post_read_required(inode)) 3338 if (!f2fs_post_read_required(inode))
3339 return; 3339 return;
3340 3340
3341 if (!is_valid_data_blkaddr(sbi, blkaddr)) 3341 if (!__is_valid_data_blkaddr(blkaddr))
3342 return; 3342 return;
3343 3343
3344 cpage = find_lock_page(META_MAPPING(sbi), blkaddr); 3344 cpage = find_lock_page(META_MAPPING(sbi), blkaddr);
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 6f48e0763279..429007b8036e 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -82,7 +82,7 @@
82 (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & ((sbi)->blocks_per_seg - 1)) 82 (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & ((sbi)->blocks_per_seg - 1))
83 83
84#define GET_SEGNO(sbi, blk_addr) \ 84#define GET_SEGNO(sbi, blk_addr) \
85 ((!is_valid_data_blkaddr(sbi, blk_addr)) ? \ 85 ((!__is_valid_data_blkaddr(blk_addr)) ? \
86 NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi), \ 86 NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi), \
87 GET_SEGNO_FROM_SEG0(sbi, blk_addr))) 87 GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
88#define BLKS_PER_SEC(sbi) \ 88#define BLKS_PER_SEC(sbi) \
@@ -656,14 +656,15 @@ static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno)
656 f2fs_bug_on(sbi, segno > TOTAL_SEGS(sbi) - 1); 656 f2fs_bug_on(sbi, segno > TOTAL_SEGS(sbi) - 1);
657} 657}
658 658
659static inline void verify_block_addr(struct f2fs_io_info *fio, block_t blk_addr) 659static inline void verify_fio_blkaddr(struct f2fs_io_info *fio)
660{ 660{
661 struct f2fs_sb_info *sbi = fio->sbi; 661 struct f2fs_sb_info *sbi = fio->sbi;
662 662
663 if (__is_meta_io(fio)) 663 if (__is_valid_data_blkaddr(fio->old_blkaddr))
664 verify_blkaddr(sbi, blk_addr, META_GENERIC); 664 verify_blkaddr(sbi, fio->old_blkaddr, __is_meta_io(fio) ?
665 else 665 META_GENERIC : DATA_GENERIC);
666 verify_blkaddr(sbi, blk_addr, DATA_GENERIC); 666 verify_blkaddr(sbi, fio->new_blkaddr, __is_meta_io(fio) ?
667 META_GENERIC : DATA_GENERIC_ENHANCE);
667} 668}
668 669
669/* 670/*