hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/fs/f2fs/recovery.c
....@@ -45,6 +45,10 @@
4545
4646 static struct kmem_cache *fsync_entry_slab;
4747
48
+#ifdef CONFIG_UNICODE
49
+extern struct kmem_cache *f2fs_cf_name_slab;
50
+#endif
51
+
4852 bool f2fs_space_for_roll_forward(struct f2fs_sb_info *sbi)
4953 {
5054 s64 nalloc = percpu_counter_sum_positive(&sbi->alloc_valid_block_count);
....@@ -145,7 +149,7 @@
145149 f2fs_hash_filename(dir, fname);
146150 #ifdef CONFIG_UNICODE
147151 /* Case-sensitive match is fine for recovery */
148
- kfree(fname->cf_name.name);
152
+ kmem_cache_free(f2fs_cf_name_slab, fname->cf_name.name);
149153 fname->cf_name.name = NULL;
150154 #endif
151155 } else {
....@@ -447,7 +451,7 @@
447451 struct dnode_of_data tdn = *dn;
448452 nid_t ino, nid;
449453 struct inode *inode;
450
- unsigned int offset;
454
+ unsigned int offset, ofs_in_node, max_addrs;
451455 block_t bidx;
452456 int i;
453457
....@@ -458,6 +462,7 @@
458462 /* Get the previous summary */
459463 for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
460464 struct curseg_info *curseg = CURSEG_I(sbi, i);
465
+
461466 if (curseg->segno == segno) {
462467 sum = curseg->sum_blk->entries[blkoff];
463468 goto got_it;
....@@ -473,15 +478,24 @@
473478 got_it:
474479 /* Use the locked dnode page and inode */
475480 nid = le32_to_cpu(sum.nid);
481
+ ofs_in_node = le16_to_cpu(sum.ofs_in_node);
482
+
483
+ max_addrs = ADDRS_PER_PAGE(dn->node_page, dn->inode);
484
+ if (ofs_in_node >= max_addrs) {
485
+ f2fs_err(sbi, "Inconsistent ofs_in_node:%u in summary, ino:%lu, nid:%u, max:%u",
486
+ ofs_in_node, dn->inode->i_ino, nid, max_addrs);
487
+ return -EFSCORRUPTED;
488
+ }
489
+
476490 if (dn->inode->i_ino == nid) {
477491 tdn.nid = nid;
478492 if (!dn->inode_page_locked)
479493 lock_page(dn->inode_page);
480494 tdn.node_page = dn->inode_page;
481
- tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node);
495
+ tdn.ofs_in_node = ofs_in_node;
482496 goto truncate_out;
483497 } else if (dn->nid == nid) {
484
- tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node);
498
+ tdn.ofs_in_node = ofs_in_node;
485499 goto truncate_out;
486500 }
487501
....@@ -589,7 +603,7 @@
589603
590604 f2fs_wait_on_page_writeback(dn.node_page, NODE, true, true);
591605
592
- err = f2fs_get_node_info(sbi, dn.nid, &ni);
606
+ err = f2fs_get_node_info(sbi, dn.nid, &ni, false);
593607 if (err)
594608 goto err;
595609
....@@ -668,6 +682,14 @@
668682 DEFAULT_IO_TIMEOUT);
669683 goto retry_prev;
670684 }
685
+ goto err;
686
+ }
687
+
688
+ if (f2fs_is_valid_blkaddr(sbi, dest,
689
+ DATA_GENERIC_ENHANCE_UPDATE)) {
690
+ f2fs_err(sbi, "Inconsistent dest blkaddr:%u, ino:%lu, ofs:%u",
691
+ dest, inode->i_ino, dn.ofs_in_node);
692
+ err = -EFSCORRUPTED;
671693 goto err;
672694 }
673695
....@@ -758,7 +780,7 @@
758780 f2fs_put_page(page, 1);
759781 }
760782 if (!err)
761
- f2fs_allocate_new_segments(sbi, NO_CHECK_TYPE);
783
+ f2fs_allocate_new_segments(sbi);
762784 return err;
763785 }
764786
....@@ -770,6 +792,7 @@
770792 int ret = 0;
771793 unsigned long s_flags = sbi->sb->s_flags;
772794 bool need_writecp = false;
795
+ bool fix_curseg_write_pointer = false;
773796 #ifdef CONFIG_QUOTA
774797 int quota_enabled;
775798 #endif
....@@ -786,19 +809,12 @@
786809 quota_enabled = f2fs_enable_quota_files(sbi, s_flags & SB_RDONLY);
787810 #endif
788811
789
- fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
790
- sizeof(struct fsync_inode_entry));
791
- if (!fsync_entry_slab) {
792
- err = -ENOMEM;
793
- goto out;
794
- }
795
-
796812 INIT_LIST_HEAD(&inode_list);
797813 INIT_LIST_HEAD(&tmp_inode_list);
798814 INIT_LIST_HEAD(&dir_list);
799815
800816 /* prevent checkpoint */
801
- mutex_lock(&sbi->cp_mutex);
817
+ f2fs_down_write(&sbi->cp_global_sem);
802818
803819 /* step #1: find fsynced inode numbers */
804820 err = find_fsync_dnodes(sbi, &inode_list, check_only);
....@@ -821,6 +837,8 @@
821837 sbi->sb->s_flags = s_flags;
822838 }
823839 skip:
840
+ fix_curseg_write_pointer = !check_only || list_empty(&inode_list);
841
+
824842 destroy_fsync_dnodes(&inode_list, err);
825843 destroy_fsync_dnodes(&tmp_inode_list, err);
826844
....@@ -831,10 +849,23 @@
831849 if (err) {
832850 truncate_inode_pages_final(NODE_MAPPING(sbi));
833851 truncate_inode_pages_final(META_MAPPING(sbi));
834
- } else {
835
- clear_sbi_flag(sbi, SBI_POR_DOING);
836852 }
837
- mutex_unlock(&sbi->cp_mutex);
853
+
854
+ /*
855
+ * If fsync data succeeds or there is no fsync data to recover,
856
+ * and the f2fs is not read only, check and fix zoned block devices'
857
+ * write pointer consistency.
858
+ */
859
+ if (!err && fix_curseg_write_pointer && !f2fs_readonly(sbi->sb) &&
860
+ f2fs_sb_has_blkzoned(sbi)) {
861
+ err = f2fs_fix_curseg_write_pointer(sbi);
862
+ ret = err;
863
+ }
864
+
865
+ if (!err)
866
+ clear_sbi_flag(sbi, SBI_POR_DOING);
867
+
868
+ f2fs_up_write(&sbi->cp_global_sem);
838869
839870 /* let's drop all the directory inodes for clean checkpoint */
840871 destroy_fsync_dnodes(&dir_list, err);
....@@ -850,8 +881,6 @@
850881 }
851882 }
852883
853
- kmem_cache_destroy(fsync_entry_slab);
854
-out:
855884 #ifdef CONFIG_QUOTA
856885 /* Turn quotas off */
857886 if (quota_enabled)
....@@ -859,5 +888,19 @@
859888 #endif
860889 sbi->sb->s_flags = s_flags; /* Restore SB_RDONLY status */
861890
862
- return ret ? ret: err;
891
+ return ret ? ret : err;
892
+}
893
+
894
+int __init f2fs_create_recovery_cache(void)
895
+{
896
+ fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
897
+ sizeof(struct fsync_inode_entry));
898
+ if (!fsync_entry_slab)
899
+ return -ENOMEM;
900
+ return 0;
901
+}
902
+
903
+void f2fs_destroy_recovery_cache(void)
904
+{
905
+ kmem_cache_destroy(fsync_entry_slab);
863906 }