hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/f2fs/gc.c
....@@ -7,6 +7,7 @@
77 */
88 #include <linux/fs.h>
99 #include <linux/module.h>
10
+#include <linux/mount.h>
1011 #include <linux/backing-dev.h>
1112 #include <linux/init.h>
1213 #include <linux/f2fs_fs.h>
....@@ -90,7 +91,8 @@
9091 * invalidated soon after by user update or deletion.
9192 * So, I'd like to wait some time to collect dirty segments.
9293 */
93
- if (sbi->gc_mode == GC_URGENT_HIGH) {
94
+ if (sbi->gc_mode == GC_URGENT_HIGH ||
95
+ sbi->gc_mode == GC_URGENT_MID) {
9496 wait_ms = gc_th->urgent_sleep_time;
9597 f2fs_down_write(&sbi->gc_lock);
9698 goto do_gc;
....@@ -627,6 +629,54 @@
627629 f2fs_bug_on(sbi, !list_empty(&am->victim_list));
628630 }
629631
632
+static bool f2fs_pin_section(struct f2fs_sb_info *sbi, unsigned int segno)
633
+{
634
+ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
635
+ unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
636
+
637
+ if (!dirty_i->enable_pin_section)
638
+ return false;
639
+ if (!test_and_set_bit(secno, dirty_i->pinned_secmap))
640
+ dirty_i->pinned_secmap_cnt++;
641
+ return true;
642
+}
643
+
644
+static bool f2fs_pinned_section_exists(struct dirty_seglist_info *dirty_i)
645
+{
646
+ return dirty_i->pinned_secmap_cnt;
647
+}
648
+
649
+static bool f2fs_section_is_pinned(struct dirty_seglist_info *dirty_i,
650
+ unsigned int secno)
651
+{
652
+ return dirty_i->enable_pin_section &&
653
+ f2fs_pinned_section_exists(dirty_i) &&
654
+ test_bit(secno, dirty_i->pinned_secmap);
655
+}
656
+
657
+static void f2fs_unpin_all_sections(struct f2fs_sb_info *sbi, bool enable)
658
+{
659
+ unsigned int bitmap_size = f2fs_bitmap_size(MAIN_SECS(sbi));
660
+
661
+ if (f2fs_pinned_section_exists(DIRTY_I(sbi))) {
662
+ memset(DIRTY_I(sbi)->pinned_secmap, 0, bitmap_size);
663
+ DIRTY_I(sbi)->pinned_secmap_cnt = 0;
664
+ }
665
+ DIRTY_I(sbi)->enable_pin_section = enable;
666
+}
667
+
668
+static int f2fs_gc_pinned_control(struct inode *inode, int gc_type,
669
+ unsigned int segno)
670
+{
671
+ if (!f2fs_is_pinned_file(inode))
672
+ return 0;
673
+ if (gc_type != FG_GC)
674
+ return -EBUSY;
675
+ if (!f2fs_pin_section(F2FS_I_SB(inode), segno))
676
+ f2fs_pin_file_control(inode, true);
677
+ return -EAGAIN;
678
+}
679
+
630680 /*
631681 * This function is called from two paths.
632682 * One is garbage collection and the other is SSR segment selection.
....@@ -766,6 +816,9 @@
766816 }
767817
768818 if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
819
+ goto next;
820
+
821
+ if (gc_type == FG_GC && f2fs_section_is_pinned(dirty_i, secno))
769822 goto next;
770823
771824 if (is_atgc) {
....@@ -1000,7 +1053,7 @@
10001053 {
10011054 struct page *node_page;
10021055 nid_t nid;
1003
- unsigned int ofs_in_node, max_addrs;
1056
+ unsigned int ofs_in_node, max_addrs, base;
10041057 block_t source_blkaddr;
10051058
10061059 nid = le32_to_cpu(sum->nid);
....@@ -1026,11 +1079,18 @@
10261079 return false;
10271080 }
10281081
1029
- max_addrs = IS_INODE(node_page) ? DEF_ADDRS_PER_INODE :
1030
- DEF_ADDRS_PER_BLOCK;
1031
- if (ofs_in_node >= max_addrs) {
1032
- f2fs_err(sbi, "Inconsistent ofs_in_node:%u in summary, ino:%u, nid:%u, max:%u",
1033
- ofs_in_node, dni->ino, dni->nid, max_addrs);
1082
+ if (IS_INODE(node_page)) {
1083
+ base = offset_in_addr(F2FS_INODE(node_page));
1084
+ max_addrs = DEF_ADDRS_PER_INODE;
1085
+ } else {
1086
+ base = 0;
1087
+ max_addrs = DEF_ADDRS_PER_BLOCK;
1088
+ }
1089
+
1090
+ if (base + ofs_in_node >= max_addrs) {
1091
+ f2fs_err(sbi, "Inconsistent blkaddr offset: base:%u, ofs_in_node:%u, max:%u, ino:%u, nid:%u",
1092
+ base, ofs_in_node, max_addrs, dni->ino, dni->nid);
1093
+ f2fs_put_page(node_page, 1);
10341094 return false;
10351095 }
10361096
....@@ -1189,12 +1249,9 @@
11891249 goto out;
11901250 }
11911251
1192
- if (f2fs_is_pinned_file(inode)) {
1193
- if (gc_type == FG_GC)
1194
- f2fs_pin_file_control(inode, true);
1195
- err = -EAGAIN;
1252
+ err = f2fs_gc_pinned_control(inode, gc_type, segno);
1253
+ if (err)
11961254 goto out;
1197
- }
11981255
11991256 set_new_dnode(&dn, inode, NULL, NULL, 0);
12001257 err = f2fs_get_dnode_of_data(&dn, bidx, LOOKUP_NODE);
....@@ -1339,12 +1396,9 @@
13391396 err = -EAGAIN;
13401397 goto out;
13411398 }
1342
- if (f2fs_is_pinned_file(inode)) {
1343
- if (gc_type == FG_GC)
1344
- f2fs_pin_file_control(inode, true);
1345
- err = -EAGAIN;
1399
+ err = f2fs_gc_pinned_control(inode, gc_type, segno);
1400
+ if (err)
13461401 goto out;
1347
- }
13481402
13491403 if (gc_type == BG_GC) {
13501404 if (PageWriteback(page)) {
....@@ -1465,9 +1519,17 @@
14651519 ofs_in_node = le16_to_cpu(entry->ofs_in_node);
14661520
14671521 if (phase == 3) {
1522
+ int err;
1523
+
14681524 inode = f2fs_iget(sb, dni.ino);
14691525 if (IS_ERR(inode) || is_bad_inode(inode))
14701526 continue;
1527
+
1528
+ err = f2fs_gc_pinned_control(inode, gc_type, segno);
1529
+ if (err == -EAGAIN) {
1530
+ iput(inode);
1531
+ return submitted;
1532
+ }
14711533
14721534 if (!f2fs_down_write_trylock(
14731535 &F2FS_I(inode)->i_gc_rwsem[WRITE])) {
....@@ -1672,8 +1734,9 @@
16721734 get_valid_blocks(sbi, segno, false) == 0)
16731735 seg_freed++;
16741736
1675
- if (__is_large_section(sbi) && segno + 1 < end_segno)
1676
- sbi->next_victim_seg[gc_type] = segno + 1;
1737
+ if (__is_large_section(sbi))
1738
+ sbi->next_victim_seg[gc_type] =
1739
+ (segno + 1 < end_segno) ? segno + 1 : NULL_SEGNO;
16771740 skip:
16781741 f2fs_put_page(sum_page, 0);
16791742 }
....@@ -1748,9 +1811,17 @@
17481811 ret = -EINVAL;
17491812 goto stop;
17501813 }
1814
+retry:
17511815 ret = __get_victim(sbi, &segno, gc_type);
1752
- if (ret)
1816
+ if (ret) {
1817
+ /* allow to search victim from sections has pinned data */
1818
+ if (ret == -ENODATA && gc_type == FG_GC &&
1819
+ f2fs_pinned_section_exists(DIRTY_I(sbi))) {
1820
+ f2fs_unpin_all_sections(sbi, false);
1821
+ goto retry;
1822
+ }
17531823 goto stop;
1824
+ }
17541825
17551826 seg_freed = do_garbage_collect(sbi, segno, &gc_list, gc_type, force);
17561827 if (gc_type == FG_GC &&
....@@ -1800,6 +1871,9 @@
18001871 stop:
18011872 SIT_I(sbi)->last_victim[ALLOC_NEXT] = 0;
18021873 SIT_I(sbi)->last_victim[FLUSH_DEVICE] = init_segno;
1874
+
1875
+ if (gc_type == FG_GC)
1876
+ f2fs_unpin_all_sections(sbi, true);
18031877
18041878 trace_f2fs_gc_end(sbi->sb, ret, total_freed, sec_freed,
18051879 get_pages(sbi, F2FS_DIRTY_NODES),
....@@ -1991,8 +2065,9 @@
19912065 }
19922066 }
19932067
1994
-int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count)
2068
+int f2fs_resize_fs(struct file *filp, __u64 block_count)
19952069 {
2070
+ struct f2fs_sb_info *sbi = F2FS_I_SB(file_inode(filp));
19962071 __u64 old_block_count, shrunk_blocks;
19972072 struct cp_control cpc = { CP_RESIZE, 0, 0, 0 };
19982073 unsigned int secs;
....@@ -2030,12 +2105,18 @@
20302105 return -EINVAL;
20312106 }
20322107
2108
+ err = mnt_want_write_file(filp);
2109
+ if (err)
2110
+ return err;
2111
+
20332112 shrunk_blocks = old_block_count - block_count;
20342113 secs = div_u64(shrunk_blocks, BLKS_PER_SEC(sbi));
20352114
20362115 /* stop other GC */
2037
- if (!f2fs_down_write_trylock(&sbi->gc_lock))
2038
- return -EAGAIN;
2116
+ if (!f2fs_down_write_trylock(&sbi->gc_lock)) {
2117
+ err = -EAGAIN;
2118
+ goto out_drop_write;
2119
+ }
20392120
20402121 /* stop CP to protect MAIN_SEC in free_segment_range */
20412122 f2fs_lock_op(sbi);
....@@ -2055,12 +2136,18 @@
20552136 out_unlock:
20562137 f2fs_unlock_op(sbi);
20572138 f2fs_up_write(&sbi->gc_lock);
2139
+out_drop_write:
2140
+ mnt_drop_write_file(filp);
20582141 if (err)
20592142 return err;
20602143
2061
- set_sbi_flag(sbi, SBI_IS_RESIZEFS);
2062
-
20632144 freeze_super(sbi->sb);
2145
+
2146
+ if (f2fs_readonly(sbi->sb)) {
2147
+ thaw_super(sbi->sb);
2148
+ return -EROFS;
2149
+ }
2150
+
20642151 f2fs_down_write(&sbi->gc_lock);
20652152 f2fs_down_write(&sbi->cp_global_sem);
20662153
....@@ -2075,6 +2162,7 @@
20752162 if (err)
20762163 goto out_err;
20772164
2165
+ set_sbi_flag(sbi, SBI_IS_RESIZEFS);
20782166 err = free_segment_range(sbi, secs, false);
20792167 if (err)
20802168 goto recover_out;
....@@ -2098,6 +2186,7 @@
20982186 f2fs_commit_super(sbi, false);
20992187 }
21002188 recover_out:
2189
+ clear_sbi_flag(sbi, SBI_IS_RESIZEFS);
21012190 if (err) {
21022191 set_sbi_flag(sbi, SBI_NEED_FSCK);
21032192 f2fs_err(sbi, "resize_fs failed, should run fsck to repair!");
....@@ -2110,6 +2199,5 @@
21102199 f2fs_up_write(&sbi->cp_global_sem);
21112200 f2fs_up_write(&sbi->gc_lock);
21122201 thaw_super(sbi->sb);
2113
- clear_sbi_flag(sbi, SBI_IS_RESIZEFS);
21142202 return err;
21152203 }