| .. | .. |
|---|
| 7 | 7 | */ |
|---|
| 8 | 8 | #include <linux/fs.h> |
|---|
| 9 | 9 | #include <linux/module.h> |
|---|
| 10 | +#include <linux/mount.h> |
|---|
| 10 | 11 | #include <linux/backing-dev.h> |
|---|
| 11 | 12 | #include <linux/init.h> |
|---|
| 12 | 13 | #include <linux/f2fs_fs.h> |
|---|
| .. | .. |
|---|
| 90 | 91 | * invalidated soon after by user update or deletion. |
|---|
| 91 | 92 | * So, I'd like to wait some time to collect dirty segments. |
|---|
| 92 | 93 | */ |
|---|
| 93 | | - if (sbi->gc_mode == GC_URGENT_HIGH) { |
|---|
| 94 | + if (sbi->gc_mode == GC_URGENT_HIGH || |
|---|
| 95 | + sbi->gc_mode == GC_URGENT_MID) { |
|---|
| 94 | 96 | wait_ms = gc_th->urgent_sleep_time; |
|---|
| 95 | 97 | f2fs_down_write(&sbi->gc_lock); |
|---|
| 96 | 98 | goto do_gc; |
|---|
| .. | .. |
|---|
| 627 | 629 | f2fs_bug_on(sbi, !list_empty(&am->victim_list)); |
|---|
| 628 | 630 | } |
|---|
| 629 | 631 | |
|---|
| 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 | + |
|---|
| 630 | 680 | /* |
|---|
| 631 | 681 | * This function is called from two paths. |
|---|
| 632 | 682 | * One is garbage collection and the other is SSR segment selection. |
|---|
| .. | .. |
|---|
| 766 | 816 | } |
|---|
| 767 | 817 | |
|---|
| 768 | 818 | 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)) |
|---|
| 769 | 822 | goto next; |
|---|
| 770 | 823 | |
|---|
| 771 | 824 | if (is_atgc) { |
|---|
| .. | .. |
|---|
| 1000 | 1053 | { |
|---|
| 1001 | 1054 | struct page *node_page; |
|---|
| 1002 | 1055 | nid_t nid; |
|---|
| 1003 | | - unsigned int ofs_in_node, max_addrs; |
|---|
| 1056 | + unsigned int ofs_in_node, max_addrs, base; |
|---|
| 1004 | 1057 | block_t source_blkaddr; |
|---|
| 1005 | 1058 | |
|---|
| 1006 | 1059 | nid = le32_to_cpu(sum->nid); |
|---|
| .. | .. |
|---|
| 1026 | 1079 | return false; |
|---|
| 1027 | 1080 | } |
|---|
| 1028 | 1081 | |
|---|
| 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); |
|---|
| 1034 | 1094 | return false; |
|---|
| 1035 | 1095 | } |
|---|
| 1036 | 1096 | |
|---|
| .. | .. |
|---|
| 1189 | 1249 | goto out; |
|---|
| 1190 | 1250 | } |
|---|
| 1191 | 1251 | |
|---|
| 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) |
|---|
| 1196 | 1254 | goto out; |
|---|
| 1197 | | - } |
|---|
| 1198 | 1255 | |
|---|
| 1199 | 1256 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
|---|
| 1200 | 1257 | err = f2fs_get_dnode_of_data(&dn, bidx, LOOKUP_NODE); |
|---|
| .. | .. |
|---|
| 1339 | 1396 | err = -EAGAIN; |
|---|
| 1340 | 1397 | goto out; |
|---|
| 1341 | 1398 | } |
|---|
| 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) |
|---|
| 1346 | 1401 | goto out; |
|---|
| 1347 | | - } |
|---|
| 1348 | 1402 | |
|---|
| 1349 | 1403 | if (gc_type == BG_GC) { |
|---|
| 1350 | 1404 | if (PageWriteback(page)) { |
|---|
| .. | .. |
|---|
| 1465 | 1519 | ofs_in_node = le16_to_cpu(entry->ofs_in_node); |
|---|
| 1466 | 1520 | |
|---|
| 1467 | 1521 | if (phase == 3) { |
|---|
| 1522 | + int err; |
|---|
| 1523 | + |
|---|
| 1468 | 1524 | inode = f2fs_iget(sb, dni.ino); |
|---|
| 1469 | 1525 | if (IS_ERR(inode) || is_bad_inode(inode)) |
|---|
| 1470 | 1526 | continue; |
|---|
| 1527 | + |
|---|
| 1528 | + err = f2fs_gc_pinned_control(inode, gc_type, segno); |
|---|
| 1529 | + if (err == -EAGAIN) { |
|---|
| 1530 | + iput(inode); |
|---|
| 1531 | + return submitted; |
|---|
| 1532 | + } |
|---|
| 1471 | 1533 | |
|---|
| 1472 | 1534 | if (!f2fs_down_write_trylock( |
|---|
| 1473 | 1535 | &F2FS_I(inode)->i_gc_rwsem[WRITE])) { |
|---|
| .. | .. |
|---|
| 1672 | 1734 | get_valid_blocks(sbi, segno, false) == 0) |
|---|
| 1673 | 1735 | seg_freed++; |
|---|
| 1674 | 1736 | |
|---|
| 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; |
|---|
| 1677 | 1740 | skip: |
|---|
| 1678 | 1741 | f2fs_put_page(sum_page, 0); |
|---|
| 1679 | 1742 | } |
|---|
| .. | .. |
|---|
| 1748 | 1811 | ret = -EINVAL; |
|---|
| 1749 | 1812 | goto stop; |
|---|
| 1750 | 1813 | } |
|---|
| 1814 | +retry: |
|---|
| 1751 | 1815 | 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 | + } |
|---|
| 1753 | 1823 | goto stop; |
|---|
| 1824 | + } |
|---|
| 1754 | 1825 | |
|---|
| 1755 | 1826 | seg_freed = do_garbage_collect(sbi, segno, &gc_list, gc_type, force); |
|---|
| 1756 | 1827 | if (gc_type == FG_GC && |
|---|
| .. | .. |
|---|
| 1800 | 1871 | stop: |
|---|
| 1801 | 1872 | SIT_I(sbi)->last_victim[ALLOC_NEXT] = 0; |
|---|
| 1802 | 1873 | SIT_I(sbi)->last_victim[FLUSH_DEVICE] = init_segno; |
|---|
| 1874 | + |
|---|
| 1875 | + if (gc_type == FG_GC) |
|---|
| 1876 | + f2fs_unpin_all_sections(sbi, true); |
|---|
| 1803 | 1877 | |
|---|
| 1804 | 1878 | trace_f2fs_gc_end(sbi->sb, ret, total_freed, sec_freed, |
|---|
| 1805 | 1879 | get_pages(sbi, F2FS_DIRTY_NODES), |
|---|
| .. | .. |
|---|
| 1991 | 2065 | } |
|---|
| 1992 | 2066 | } |
|---|
| 1993 | 2067 | |
|---|
| 1994 | | -int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count) |
|---|
| 2068 | +int f2fs_resize_fs(struct file *filp, __u64 block_count) |
|---|
| 1995 | 2069 | { |
|---|
| 2070 | + struct f2fs_sb_info *sbi = F2FS_I_SB(file_inode(filp)); |
|---|
| 1996 | 2071 | __u64 old_block_count, shrunk_blocks; |
|---|
| 1997 | 2072 | struct cp_control cpc = { CP_RESIZE, 0, 0, 0 }; |
|---|
| 1998 | 2073 | unsigned int secs; |
|---|
| .. | .. |
|---|
| 2030 | 2105 | return -EINVAL; |
|---|
| 2031 | 2106 | } |
|---|
| 2032 | 2107 | |
|---|
| 2108 | + err = mnt_want_write_file(filp); |
|---|
| 2109 | + if (err) |
|---|
| 2110 | + return err; |
|---|
| 2111 | + |
|---|
| 2033 | 2112 | shrunk_blocks = old_block_count - block_count; |
|---|
| 2034 | 2113 | secs = div_u64(shrunk_blocks, BLKS_PER_SEC(sbi)); |
|---|
| 2035 | 2114 | |
|---|
| 2036 | 2115 | /* 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 | + } |
|---|
| 2039 | 2120 | |
|---|
| 2040 | 2121 | /* stop CP to protect MAIN_SEC in free_segment_range */ |
|---|
| 2041 | 2122 | f2fs_lock_op(sbi); |
|---|
| .. | .. |
|---|
| 2055 | 2136 | out_unlock: |
|---|
| 2056 | 2137 | f2fs_unlock_op(sbi); |
|---|
| 2057 | 2138 | f2fs_up_write(&sbi->gc_lock); |
|---|
| 2139 | +out_drop_write: |
|---|
| 2140 | + mnt_drop_write_file(filp); |
|---|
| 2058 | 2141 | if (err) |
|---|
| 2059 | 2142 | return err; |
|---|
| 2060 | 2143 | |
|---|
| 2061 | | - set_sbi_flag(sbi, SBI_IS_RESIZEFS); |
|---|
| 2062 | | - |
|---|
| 2063 | 2144 | freeze_super(sbi->sb); |
|---|
| 2145 | + |
|---|
| 2146 | + if (f2fs_readonly(sbi->sb)) { |
|---|
| 2147 | + thaw_super(sbi->sb); |
|---|
| 2148 | + return -EROFS; |
|---|
| 2149 | + } |
|---|
| 2150 | + |
|---|
| 2064 | 2151 | f2fs_down_write(&sbi->gc_lock); |
|---|
| 2065 | 2152 | f2fs_down_write(&sbi->cp_global_sem); |
|---|
| 2066 | 2153 | |
|---|
| .. | .. |
|---|
| 2075 | 2162 | if (err) |
|---|
| 2076 | 2163 | goto out_err; |
|---|
| 2077 | 2164 | |
|---|
| 2165 | + set_sbi_flag(sbi, SBI_IS_RESIZEFS); |
|---|
| 2078 | 2166 | err = free_segment_range(sbi, secs, false); |
|---|
| 2079 | 2167 | if (err) |
|---|
| 2080 | 2168 | goto recover_out; |
|---|
| .. | .. |
|---|
| 2098 | 2186 | f2fs_commit_super(sbi, false); |
|---|
| 2099 | 2187 | } |
|---|
| 2100 | 2188 | recover_out: |
|---|
| 2189 | + clear_sbi_flag(sbi, SBI_IS_RESIZEFS); |
|---|
| 2101 | 2190 | if (err) { |
|---|
| 2102 | 2191 | set_sbi_flag(sbi, SBI_NEED_FSCK); |
|---|
| 2103 | 2192 | f2fs_err(sbi, "resize_fs failed, should run fsck to repair!"); |
|---|
| .. | .. |
|---|
| 2110 | 2199 | f2fs_up_write(&sbi->cp_global_sem); |
|---|
| 2111 | 2200 | f2fs_up_write(&sbi->gc_lock); |
|---|
| 2112 | 2201 | thaw_super(sbi->sb); |
|---|
| 2113 | | - clear_sbi_flag(sbi, SBI_IS_RESIZEFS); |
|---|
| 2114 | 2202 | return err; |
|---|
| 2115 | 2203 | } |
|---|