Pull f2fs update from Jaegeuk Kim: "In this round, we've mainly modified to support non-power-of-two zone size, which is not required for f2fs by design. In order to avoid arch dependency, we refactored the messy rb_entry structure shared across different extent_cache. In addition to the improvement, we've also fixed several subtle bugs and error cases. Enhancements: - support non-power-of-two zone size for zoned device - remove sharing the rb_entry structure in extent cache - refactor f2fs_gc to call checkpoint in urgent condition - support iopoll Bug fixes: - fix potential corruption when moving a directory - fix to avoid use-after-free for cached IPU bio - fix the folio private usage - avoid kernel warnings or panics in the cp_error case - fix to recover quota data correctly - fix some bugs in atomic operations - fix system crash due to lack of free space in LFS - fix null pointer panic in tracepoint in __replace_atomic_write_block - fix iostat lock protection - fix scheduling while atomic in decompression path - preserve direct write semantics when buffering is forced - fix to call f2fs_wait_on_page_writeback() in f2fs_write_raw_pages()" * tag 'f2fs-for-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (52 commits) f2fs: remove unnessary comment in __may_age_extent_tree f2fs: allocate node blocks for atomic write block replacement f2fs: use cow inode data when updating atomic write f2fs: remove power-of-two limitation of zoned device f2fs: allocate trace path buffer from names_cache f2fs: add has_enough_free_secs() f2fs: relax sanity check if checkpoint is corrupted f2fs: refactor f2fs_gc to call checkpoint in urgent condition f2fs: remove folio_detach_private() in .invalidate_folio and .release_folio f2fs: remove bulk remove_proc_entry() and unnecessary kobject_del() f2fs: support iopoll method f2fs: remove batched_trim_sections node description f2fs: fix to check return value of inc_valid_block_count() f2fs: fix to check return value of f2fs_do_truncate_blocks() f2fs: fix passing relative address when discard zones f2fs: fix potential corruption when moving a directory f2fs: add radix_tree_preload_end in error case f2fs: fix to recover quota data correctly f2fs: fix to check readonly condition correctly docs: f2fs: Correct instruction to disable checkpoint ...
Unified · Split
| @@ -190,12 +190,6 @@ Description: Controls the memory footprint used by free nids and cached · 189 unmodified lines | ||
| 190 | 190 | nat entries. By default, 1 is set, which indicates |
| 191 | 191 | 10 MB / 1 GB RAM. |
| 192 | 192 | |
| 193 | −What: /sys/fs/f2fs/<disk>/batched_trim_sections | |
| 194 | −Date: February 2015 | |
| 195 | −Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> | |
| 196 | −Description: Controls the trimming rate in batch mode. | |
| 197 | − <deprecated> | |
| 198 | − | |
| 199 | 193 | What: /sys/fs/f2fs/<disk>/cp_interval |
| 200 | 194 | Date: October 2015 |
| 201 | 195 | Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> |
| @@ -729,3 +723,20 @@ What: /sys/fs/f2fs/<disk>/last_age_weight · 527 unmodified lines | ||
| 729 | 723 | Date: January 2023 |
| 730 | 724 | Contact: "Ping Xiong" <xiongping1@xiaomi.com> |
| 731 | 725 | Description: When DATA SEPARATION is on, it controls the weight of last data block age. |
| 726 | + | |
| 727 | +What: /sys/fs/f2fs/<disk>/compress_watermark | |
| 728 | +Date: February 2023 | |
| 729 | +Contact: "Yangtao Li" <frank.li@vivo.com> | |
| 730 | +Description: When compress cache is on, it controls free memory watermark | |
| 731 | + in order to limit caching compress page. If free memory is lower | |
| 732 | + than watermark, then deny caching compress page. The value should be in | |
| 733 | + range of (0, 100], by default it was initialized as 20(%). | |
| 734 | + | |
| 735 | +What: /sys/fs/f2fs/<disk>/compress_percent | |
| 736 | +Date: February 2023 | |
| 737 | +Contact: "Yangtao Li" <frank.li@vivo.com> | |
| 738 | +Description: When compress cache is on, it controls cached page | |
| 739 | + percent(compress pages / free_ram) in order to limit caching compress page. | |
| 740 | + If cached page percent exceed threshold, then deny caching compress page. | |
| 741 | + The value should be in range of (0, 100], by default it was initialized | |
| 742 | + as 20(%). | |
| @@ -264,7 +264,7 @@ checkpoint=%s[:%u[%]] Set to "disable" to turn off checkpointing. Set to "enabl · 263 unmodified lines | ||
| 264 | 264 | disabled, any unmounting or unexpected shutdowns will cause |
| 265 | 265 | the filesystem contents to appear as they did when the |
| 266 | 266 | filesystem was mounted with that option. |
| 267 | − While mounting with checkpoint=disabled, the filesystem must | |
| 267 | + While mounting with checkpoint=disable, the filesystem must | |
| 268 | 268 | run garbage collection to ensure that all available space can |
| 269 | 269 | be used. If this takes too much time, the mount may return |
| 270 | 270 | EAGAIN. You may optionally add a value to indicate how much |
| @@ -152,6 +152,11 @@ static bool __is_bitmap_valid(struct f2fs_sb_info *sbi, block_t blkaddr, · 151 unmodified lines | ||
| 152 | 152 | se = get_seg_entry(sbi, segno); |
| 153 | 153 | |
| 154 | 154 | exist = f2fs_test_bit(offset, se->cur_valid_map); |
| 155 | + | |
| 156 | + /* skip data, if we already have an error in checkpoint. */ | |
| 157 | + if (unlikely(f2fs_cp_error(sbi))) | |
| 158 | + return exist; | |
| 159 | + | |
| 155 | 160 | if (exist && type == DATA_GENERIC_ENHANCE_UPDATE) { |
| 156 | 161 | f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d", |
| 157 | 162 | blkaddr, exist); |
| @@ -202,6 +207,11 @@ bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi, · 44 unmodified lines | ||
| 202 | 207 | case DATA_GENERIC_ENHANCE_UPDATE: |
| 203 | 208 | if (unlikely(blkaddr >= MAX_BLKADDR(sbi) || |
| 204 | 209 | blkaddr < MAIN_BLKADDR(sbi))) { |
| 210 | + | |
| 211 | + /* Skip to emit an error message. */ | |
| 212 | + if (unlikely(f2fs_cp_error(sbi))) | |
| 213 | + return false; | |
| 214 | + | |
| 205 | 215 | f2fs_warn(sbi, "access invalid blkaddr:%u", |
| 206 | 216 | blkaddr); |
| 207 | 217 | set_sbi_flag(sbi, SBI_NEED_FSCK); |
| @@ -325,8 +335,15 @@ static int __f2fs_write_meta_page(struct page *page, · 117 unmodified lines | ||
| 325 | 335 | |
| 326 | 336 | trace_f2fs_writepage(page, META); |
| 327 | 337 | |
| 328 | − if (unlikely(f2fs_cp_error(sbi))) | |
| 338 | + if (unlikely(f2fs_cp_error(sbi))) { | |
| 339 | + if (is_sbi_flag_set(sbi, SBI_IS_CLOSE)) { | |
| 340 | + ClearPageUptodate(page); | |
| 341 | + dec_page_count(sbi, F2FS_DIRTY_META); | |
| 342 | + unlock_page(page); | |
| 343 | + return 0; | |
| 344 | + } | |
| 329 | 345 | goto redirty_out; |
| 346 | + } | |
| 330 | 347 | if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) |
| 331 | 348 | goto redirty_out; |
| 332 | 349 | if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0)) |
| @@ -508,6 +525,7 @@ retry: · 175 unmodified lines | ||
| 508 | 525 | if (!e) { |
| 509 | 526 | if (!new) { |
| 510 | 527 | spin_unlock(&im->ino_lock); |
| 528 | + radix_tree_preload_end(); | |
| 511 | 529 | goto retry; |
| 512 | 530 | } |
| 513 | 531 | e = new; |
| @@ -706,32 +724,18 @@ err_out: · 192 unmodified lines | ||
| 706 | 724 | int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi) |
| 707 | 725 | { |
| 708 | 726 | block_t start_blk, orphan_blocks, i, j; |
| 709 | − unsigned int s_flags = sbi->sb->s_flags; | |
| 710 | 727 | int err = 0; |
| 711 | −#ifdef CONFIG_QUOTA | |
| 712 | − int quota_enabled; | |
| 713 | −#endif | |
| 714 | 728 | |
| 715 | 729 | if (!is_set_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG)) |
| 716 | 730 | return 0; |
| 717 | 731 | |
| 718 | − if (bdev_read_only(sbi->sb->s_bdev)) { | |
| 732 | + if (f2fs_hw_is_readonly(sbi)) { | |
| 719 | 733 | f2fs_info(sbi, "write access unavailable, skipping orphan cleanup"); |
| 720 | 734 | return 0; |
| 721 | 735 | } |
| 722 | 736 | |
| 723 | − if (s_flags & SB_RDONLY) { | |
| 737 | + if (is_sbi_flag_set(sbi, SBI_IS_WRITABLE)) | |
| 724 | 738 | f2fs_info(sbi, "orphan cleanup on readonly fs"); |
| 725 | − sbi->sb->s_flags &= ~SB_RDONLY; | |
| 726 | − } | |
| 727 | − | |
| 728 | −#ifdef CONFIG_QUOTA | |
| 729 | − /* | |
| 730 | − * Turn on quotas which were not enabled for read-only mounts if | |
| 731 | − * filesystem has quota feature, so that they are updated correctly. | |
| 732 | − */ | |
| 733 | − quota_enabled = f2fs_enable_quota_files(sbi, s_flags & SB_RDONLY); | |
| 734 | −#endif | |
| 735 | 739 | |
| 736 | 740 | start_blk = __start_cp_addr(sbi) + 1 + __cp_payload(sbi); |
| 737 | 741 | orphan_blocks = __start_sum_addr(sbi) - 1 - __cp_payload(sbi); |
| @@ -765,13 +769,6 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi) · 27 unmodified lines | ||
| 765 | 769 | out: |
| 766 | 770 | set_sbi_flag(sbi, SBI_IS_RECOVERED); |
| 767 | 771 | |
| 768 | −#ifdef CONFIG_QUOTA | |
| 769 | − /* Turn quotas off */ | |
| 770 | − if (quota_enabled) | |
| 771 | − f2fs_quota_off_umount(sbi->sb); | |
| 772 | −#endif | |
| 773 | − sbi->sb->s_flags = s_flags; /* Restore SB_RDONLY status */ | |
| 774 | − | |
| 775 | 772 | return err; |
| 776 | 773 | } |
| 777 | 774 | |
| @@ -982,7 +979,7 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi) · 204 unmodified lines | ||
| 982 | 979 | |
| 983 | 980 | cp_blk_no = le32_to_cpu(fsb->cp_blkaddr); |
| 984 | 981 | if (cur_page == cp2) |
| 985 | − cp_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg); | |
| 982 | + cp_blk_no += BIT(le32_to_cpu(fsb->log_blocks_per_seg)); | |
| 986 | 983 | |
| 987 | 984 | for (i = 1; i < cp_blks; i++) { |
| 988 | 985 | void *sit_bitmap_ptr; |
| @@ -1133,7 +1130,7 @@ retry: · 144 unmodified lines | ||
| 1133 | 1130 | goto retry; |
| 1134 | 1131 | } |
| 1135 | 1132 | |
| 1136 | −int f2fs_sync_inode_meta(struct f2fs_sb_info *sbi) | |
| 1133 | +static int f2fs_sync_inode_meta(struct f2fs_sb_info *sbi) | |
| 1137 | 1134 | { |
| 1138 | 1135 | struct list_head *head = &sbi->inode_list[DIRTY_META]; |
| 1139 | 1136 | struct inode *inode; |
| @@ -1306,7 +1303,8 @@ void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type) · 166 unmodified lines | ||
| 1306 | 1303 | if (!get_pages(sbi, type)) |
| 1307 | 1304 | break; |
| 1308 | 1305 | |
| 1309 | − if (unlikely(f2fs_cp_error(sbi))) | |
| 1306 | + if (unlikely(f2fs_cp_error(sbi) && | |
| 1307 | + !is_sbi_flag_set(sbi, SBI_IS_CLOSE))) | |
| 1310 | 1308 | break; |
| 1311 | 1309 | |
| 1312 | 1310 | if (type == F2FS_DIRTY_META) |
| @@ -264,35 +264,21 @@ static void lz4_destroy_compress_ctx(struct compress_ctx *cc) · 263 unmodified lines | ||
| 264 | 264 | cc->private = NULL; |
| 265 | 265 | } |
| 266 | 266 | |
| 267 | −#ifdef CONFIG_F2FS_FS_LZ4HC | |
| 268 | −static int lz4hc_compress_pages(struct compress_ctx *cc) | |
| 267 | +static int lz4_compress_pages(struct compress_ctx *cc) | |
| 269 | 268 | { |
| 269 | + int len = -EINVAL; | |
| 270 | 270 | unsigned char level = F2FS_I(cc->inode)->i_compress_level; |
| 271 | − int len; | |
| 272 | 271 | |
| 273 | − if (level) | |
| 274 | − len = LZ4_compress_HC(cc->rbuf, cc->cbuf->cdata, cc->rlen, | |
| 275 | − cc->clen, level, cc->private); | |
| 276 | − else | |
| 272 | + if (!level) | |
| 277 | 273 | len = LZ4_compress_default(cc->rbuf, cc->cbuf->cdata, cc->rlen, |
| 278 | 274 | cc->clen, cc->private); |
| 279 | − if (!len) | |
| 280 | − return -EAGAIN; | |
| 281 | − | |
| 282 | − cc->clen = len; | |
| 283 | − return 0; | |
| 284 | −} | |
| 285 | −#endif | |
| 286 | − | |
| 287 | −static int lz4_compress_pages(struct compress_ctx *cc) | |
| 288 | −{ | |
| 289 | − int len; | |
| 290 | − | |
| 291 | 275 | #ifdef CONFIG_F2FS_FS_LZ4HC |
| 292 | − return lz4hc_compress_pages(cc); | |
| 276 | + else | |
| 277 | + len = LZ4_compress_HC(cc->rbuf, cc->cbuf->cdata, cc->rlen, | |
| 278 | + cc->clen, level, cc->private); | |
| 293 | 279 | #endif |
| 294 | − len = LZ4_compress_default(cc->rbuf, cc->cbuf->cdata, cc->rlen, | |
| 295 | − cc->clen, cc->private); | |
| 280 | + if (len < 0) | |
| 281 | + return len; | |
| 296 | 282 | if (!len) |
| 297 | 283 | return -EAGAIN; |
| 298 | 284 | |
| @@ -670,7 +656,7 @@ static int f2fs_compress_pages(struct compress_ctx *cc) · 371 unmodified lines | ||
| 670 | 656 | |
| 671 | 657 | cc->cbuf->clen = cpu_to_le32(cc->clen); |
| 672 | 658 | |
| 673 | − if (fi->i_compress_flag & 1 << COMPRESS_CHKSUM) | |
| 659 | + if (fi->i_compress_flag & BIT(COMPRESS_CHKSUM)) | |
| 674 | 660 | chksum = f2fs_crc32(F2FS_I_SB(cc->inode), |
| 675 | 661 | cc->cbuf->cdata, cc->clen); |
| 676 | 662 | cc->cbuf->chksum = cpu_to_le32(chksum); |
| @@ -755,13 +741,18 @@ void f2fs_decompress_cluster(struct decompress_io_ctx *dic, bool in_task) · 78 unmodified lines | ||
| 755 | 741 | |
| 756 | 742 | if (dic->clen > PAGE_SIZE * dic->nr_cpages - COMPRESS_HEADER_SIZE) { |
| 757 | 743 | ret = -EFSCORRUPTED; |
| 758 | − f2fs_handle_error(sbi, ERROR_FAIL_DECOMPRESSION); | |
| 744 | + | |
| 745 | + /* Avoid f2fs_commit_super in irq context */ | |
| 746 | + if (in_task) | |
| 747 | + f2fs_save_errors(sbi, ERROR_FAIL_DECOMPRESSION); | |
| 748 | + else | |
| 749 | + f2fs_handle_error(sbi, ERROR_FAIL_DECOMPRESSION); | |
| 759 | 750 | goto out_release; |
| 760 | 751 | } |
| 761 | 752 | |
| 762 | 753 | ret = cops->decompress_pages(dic); |
| 763 | 754 | |
| 764 | − if (!ret && (fi->i_compress_flag & 1 << COMPRESS_CHKSUM)) { | |
| 755 | + if (!ret && (fi->i_compress_flag & BIT(COMPRESS_CHKSUM))) { | |
| 765 | 756 | u32 provided = le32_to_cpu(dic->cbuf->chksum); |
| 766 | 757 | u32 calculated = f2fs_crc32(sbi, dic->cbuf->cdata, dic->clen); |
| 767 | 758 | |
| @@ -1456,6 +1447,12 @@ continue_unlock: · 688 unmodified lines | ||
| 1456 | 1447 | if (!PageDirty(cc->rpages[i])) |
| 1457 | 1448 | goto continue_unlock; |
| 1458 | 1449 | |
| 1450 | + if (PageWriteback(cc->rpages[i])) { | |
| 1451 | + if (wbc->sync_mode == WB_SYNC_NONE) | |
| 1452 | + goto continue_unlock; | |
| 1453 | + f2fs_wait_on_page_writeback(cc->rpages[i], DATA, true, true); | |
| 1454 | + } | |
| 1455 | + | |
| 1459 | 1456 | if (!clear_page_dirty_for_io(cc->rpages[i])) |
| 1460 | 1457 | goto continue_unlock; |
| 1461 | 1458 | |
| @@ -93,17 +93,17 @@ static enum count_type __read_io_type(struct page *page) · 92 unmodified lines | ||
| 93 | 93 | /* postprocessing steps for read bios */ |
| 94 | 94 | enum bio_post_read_step { |
| 95 | 95 | #ifdef CONFIG_FS_ENCRYPTION |
| 96 | − STEP_DECRYPT = 1 << 0, | |
| 96 | + STEP_DECRYPT = BIT(0), | |
| 97 | 97 | #else |
| 98 | 98 | STEP_DECRYPT = 0, /* compile out the decryption-related code */ |
| 99 | 99 | #endif |
| 100 | 100 | #ifdef CONFIG_F2FS_FS_COMPRESSION |
| 101 | − STEP_DECOMPRESS = 1 << 1, | |
| 101 | + STEP_DECOMPRESS = BIT(1), | |
| 102 | 102 | #else |
| 103 | 103 | STEP_DECOMPRESS = 0, /* compile out the decompression-related code */ |
| 104 | 104 | #endif |
| 105 | 105 | #ifdef CONFIG_FS_VERITY |
| 106 | − STEP_VERITY = 1 << 2, | |
| 106 | + STEP_VERITY = BIT(2), | |
| 107 | 107 | #else |
| 108 | 108 | STEP_VERITY = 0, /* compile out the verity-related code */ |
| 109 | 109 | #endif |
| @@ -420,7 +420,7 @@ int f2fs_target_device_index(struct f2fs_sb_info *sbi, block_t blkaddr) · 310 unmodified lines | ||
| 420 | 420 | |
| 421 | 421 | static blk_opf_t f2fs_io_flags(struct f2fs_io_info *fio) |
| 422 | 422 | { |
| 423 | − unsigned int temp_mask = (1 << NR_TEMP_TYPE) - 1; | |
| 423 | + unsigned int temp_mask = GENMASK(NR_TEMP_TYPE - 1, 0); | |
| 424 | 424 | unsigned int fua_flag, meta_flag, io_flag; |
| 425 | 425 | blk_opf_t op_flags = 0; |
| 426 | 426 | |
| @@ -442,9 +442,9 @@ static blk_opf_t f2fs_io_flags(struct f2fs_io_info *fio) · 15 unmodified lines | ||
| 442 | 442 | * 5 | 4 | 3 | 2 | 1 | 0 | |
| 443 | 443 | * Cold | Warm | Hot | Cold | Warm | Hot | |
| 444 | 444 | */ |
| 445 | − if ((1 << fio->temp) & meta_flag) | |
| 445 | + if (BIT(fio->temp) & meta_flag) | |
| 446 | 446 | op_flags |= REQ_META; |
| 447 | − if ((1 << fio->temp) & fua_flag) | |
| 447 | + if (BIT(fio->temp) & fua_flag) | |
| 448 | 448 | op_flags |= REQ_FUA; |
| 449 | 449 | return op_flags; |
| 450 | 450 | } |
| @@ -874,6 +874,8 @@ void f2fs_submit_merged_ipu_write(struct f2fs_sb_info *sbi, · 423 unmodified lines | ||
| 874 | 874 | bool found = false; |
| 875 | 875 | struct bio *target = bio ? *bio : NULL; |
| 876 | 876 | |
| 877 | + f2fs_bug_on(sbi, !target && !page); | |
| 878 | + | |
| 877 | 879 | for (temp = HOT; temp < NR_TEMP_TYPE && !found; temp++) { |
| 878 | 880 | struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; |
| 879 | 881 | struct list_head *head = &io->bio_list; |
| @@ -2235,6 +2237,10 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret, · 1355 unmodified lines | ||
| 2235 | 2237 | if (ret) |
| 2236 | 2238 | goto out; |
| 2237 | 2239 | |
| 2240 | + if (unlikely(f2fs_cp_error(sbi))) { | |
| 2241 | + ret = -EIO; | |
| 2242 | + goto out_put_dnode; | |
| 2243 | + } | |
| 2238 | 2244 | f2fs_bug_on(sbi, dn.data_blkaddr != COMPRESS_ADDR); |
| 2239 | 2245 | |
| 2240 | 2246 | skip_reading_dnode: |
| @@ -2798,7 +2804,8 @@ int f2fs_write_single_data_page(struct page *page, int *submitted, · 557 unmodified lines | ||
| 2798 | 2804 | * don't drop any dirty dentry pages for keeping lastest |
| 2799 | 2805 | * directory structure. |
| 2800 | 2806 | */ |
| 2801 | − if (S_ISDIR(inode->i_mode)) | |
| 2807 | + if (S_ISDIR(inode->i_mode) && | |
| 2808 | + !is_sbi_flag_set(sbi, SBI_IS_CLOSE)) | |
| 2802 | 2809 | goto redirty_out; |
| 2803 | 2810 | goto out; |
| 2804 | 2811 | } |
| @@ -2898,7 +2905,8 @@ out: · 93 unmodified lines | ||
| 2898 | 2905 | |
| 2899 | 2906 | if (unlikely(f2fs_cp_error(sbi))) { |
| 2900 | 2907 | f2fs_submit_merged_write(sbi, DATA); |
| 2901 | − f2fs_submit_merged_ipu_write(sbi, bio, NULL); | |
| 2908 | + if (bio && *bio) | |
| 2909 | + f2fs_submit_merged_ipu_write(sbi, bio, NULL); | |
| 2902 | 2910 | submitted = NULL; |
| 2903 | 2911 | } |
| 2904 | 2912 | |
| @@ -3123,12 +3131,9 @@ continue_unlock: · 218 unmodified lines | ||
| 3123 | 3131 | } |
| 3124 | 3132 | |
| 3125 | 3133 | if (folio_test_writeback(folio)) { |
| 3126 | − if (wbc->sync_mode != WB_SYNC_NONE) | |
| 3127 | − f2fs_wait_on_page_writeback( | |
| 3128 | − &folio->page, | |
| 3129 | − DATA, true, true); | |
| 3130 | − else | |
| 3134 | + if (wbc->sync_mode == WB_SYNC_NONE) | |
| 3131 | 3135 | goto continue_unlock; |
| 3136 | + f2fs_wait_on_page_writeback(&folio->page, DATA, true, true); | |
| 3132 | 3137 | } |
| 3133 | 3138 | |
| 3134 | 3139 | if (!folio_clear_dirty_for_io(folio)) |
| @@ -3486,7 +3491,7 @@ unlock_out: · 351 unmodified lines | ||
| 3486 | 3491 | |
| 3487 | 3492 | static int prepare_atomic_write_begin(struct f2fs_sb_info *sbi, |
| 3488 | 3493 | struct page *page, loff_t pos, unsigned int len, |
| 3489 | − block_t *blk_addr, bool *node_changed) | |
| 3494 | + block_t *blk_addr, bool *node_changed, bool *use_cow) | |
| 3490 | 3495 | { |
| 3491 | 3496 | struct inode *inode = page->mapping->host; |
| 3492 | 3497 | struct inode *cow_inode = F2FS_I(inode)->cow_inode; |
| @@ -3500,10 +3505,12 @@ static int prepare_atomic_write_begin(struct f2fs_sb_info *sbi, · 7 unmodified lines | ||
| 3500 | 3505 | |
| 3501 | 3506 | /* Look for the block in COW inode first */ |
| 3502 | 3507 | err = __find_data_block(cow_inode, index, blk_addr); |
| 3503 | − if (err) | |
| 3508 | + if (err) { | |
| 3504 | 3509 | return err; |
| 3505 | − else if (*blk_addr != NULL_ADDR) | |
| 3510 | + } else if (*blk_addr != NULL_ADDR) { | |
| 3511 | + *use_cow = true; | |
| 3506 | 3512 | return 0; |
| 3513 | + } | |
| 3507 | 3514 | |
| 3508 | 3515 | if (is_inode_flag_set(inode, FI_ATOMIC_REPLACE)) |
| 3509 | 3516 | goto reserve_block; |
| @@ -3533,6 +3540,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, · 23 unmodified lines | ||
| 3533 | 3540 | struct page *page = NULL; |
| 3534 | 3541 | pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT; |
| 3535 | 3542 | bool need_balance = false; |
| 3543 | + bool use_cow = false; | |
| 3536 | 3544 | block_t blkaddr = NULL_ADDR; |
| 3537 | 3545 | int err = 0; |
| 3538 | 3546 | |
| @@ -3592,7 +3600,7 @@ repeat: · 53 unmodified lines | ||
| 3592 | 3600 | |
| 3593 | 3601 | if (f2fs_is_atomic_file(inode)) |
| 3594 | 3602 | err = prepare_atomic_write_begin(sbi, page, pos, len, |
| 3595 | − &blkaddr, &need_balance); | |
| 3603 | + &blkaddr, &need_balance, &use_cow); | |
| 3596 | 3604 | else |
| 3597 | 3605 | err = prepare_write_begin(sbi, page, pos, len, |
| 3598 | 3606 | &blkaddr, &need_balance); |
| @@ -3632,7 +3640,9 @@ repeat: · 33 unmodified lines | ||
| 3632 | 3640 | f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR); |
| 3633 | 3641 | goto fail; |
| 3634 | 3642 | } |
| 3635 | − err = f2fs_submit_page_read(inode, page, blkaddr, 0, true); | |
| 3643 | + err = f2fs_submit_page_read(use_cow ? | |
| 3644 | + F2FS_I(inode)->cow_inode : inode, page, | |
| 3645 | + blkaddr, 0, true); | |
| 3636 | 3646 | if (err) |
| 3637 | 3647 | goto fail; |
| 3638 | 3648 | |
| @@ -3725,37 +3735,16 @@ void f2fs_invalidate_folio(struct folio *folio, size_t offset, size_t length) · 86 unmodified lines | ||
| 3725 | 3735 | f2fs_remove_dirty_inode(inode); |
| 3726 | 3736 | } |
| 3727 | 3737 | } |
| 3728 | − | |
| 3729 | − clear_page_private_reference(&folio->page); | |
| 3730 | − clear_page_private_gcing(&folio->page); | |
| 3731 | − | |
| 3732 | − if (test_opt(sbi, COMPRESS_CACHE) && | |
| 3733 | − inode->i_ino == F2FS_COMPRESS_INO(sbi)) | |
| 3734 | − clear_page_private_data(&folio->page); | |
| 3735 | − | |
| 3736 | − folio_detach_private(folio); | |
| 3738 | + clear_page_private_all(&folio->page); | |
| 3737 | 3739 | } |
| 3738 | 3740 | |
| 3739 | 3741 | bool f2fs_release_folio(struct folio *folio, gfp_t wait) |
| 3740 | 3742 | { |
| 3741 | − struct f2fs_sb_info *sbi; | |
| 3742 | − | |
| 3743 | 3743 | /* If this is dirty folio, keep private data */ |
| 3744 | 3744 | if (folio_test_dirty(folio)) |
| 3745 | 3745 | return false; |
| 3746 | 3746 | |
| 3747 | − sbi = F2FS_M_SB(folio->mapping); | |
| 3748 | − if (test_opt(sbi, COMPRESS_CACHE)) { | |
| 3749 | − struct inode *inode = folio->mapping->host; | |
| 3750 | − | |
| 3751 | − if (inode->i_ino == F2FS_COMPRESS_INO(sbi)) | |
| 3752 | − clear_page_private_data(&folio->page); | |
| 3753 | − } | |
| 3754 | − | |
| 3755 | − clear_page_private_reference(&folio->page); | |
| 3756 | − clear_page_private_gcing(&folio->page); | |
| 3757 | − | |
| 3758 | − folio_detach_private(folio); | |
| 3747 | + clear_page_private_all(&folio->page); | |
| 3759 | 3748 | return true; |
| 3760 | 3749 | } |
| 3761 | 3750 | |
| @@ -336,22 +336,23 @@ get_cache: · 335 unmodified lines | ||
| 336 | 336 | #endif |
| 337 | 337 | } |
| 338 | 338 | |
| 339 | −static char *s_flag[] = { | |
| 340 | − [SBI_IS_DIRTY] = " fs_dirty", | |
| 341 | − [SBI_IS_CLOSE] = " closing", | |
| 342 | − [SBI_NEED_FSCK] = " need_fsck", | |
| 343 | − [SBI_POR_DOING] = " recovering", | |
| 344 | − [SBI_NEED_SB_WRITE] = " sb_dirty", | |
| 345 | − [SBI_NEED_CP] = " need_cp", | |
| 346 | − [SBI_IS_SHUTDOWN] = " shutdown", | |
| 347 | − [SBI_IS_RECOVERED] = " recovered", | |
| 348 | − [SBI_CP_DISABLED] = " cp_disabled", | |
| 349 | − [SBI_CP_DISABLED_QUICK] = " cp_disabled_quick", | |
| 350 | − [SBI_QUOTA_NEED_FLUSH] = " quota_need_flush", | |
| 351 | − [SBI_QUOTA_SKIP_FLUSH] = " quota_skip_flush", | |
| 352 | − [SBI_QUOTA_NEED_REPAIR] = " quota_need_repair", | |
| 353 | − [SBI_IS_RESIZEFS] = " resizefs", | |
| 354 | − [SBI_IS_FREEZING] = " freezefs", | |
| 339 | +static const char *s_flag[MAX_SBI_FLAG] = { | |
| 340 | + [SBI_IS_DIRTY] = "fs_dirty", | |
| 341 | + [SBI_IS_CLOSE] = "closing", | |
| 342 | + [SBI_NEED_FSCK] = "need_fsck", | |
| 343 | + [SBI_POR_DOING] = "recovering", | |
| 344 | + [SBI_NEED_SB_WRITE] = "sb_dirty", | |
| 345 | + [SBI_NEED_CP] = "need_cp", | |
| 346 | + [SBI_IS_SHUTDOWN] = "shutdown", | |
| 347 | + [SBI_IS_RECOVERED] = "recovered", | |
| 348 | + [SBI_CP_DISABLED] = "cp_disabled", | |
| 349 | + [SBI_CP_DISABLED_QUICK] = "cp_disabled_quick", | |
| 350 | + [SBI_QUOTA_NEED_FLUSH] = "quota_need_flush", | |
| 351 | + [SBI_QUOTA_SKIP_FLUSH] = "quota_skip_flush", | |
| 352 | + [SBI_QUOTA_NEED_REPAIR] = "quota_need_repair", | |
| 353 | + [SBI_IS_RESIZEFS] = "resizefs", | |
| 354 | + [SBI_IS_FREEZING] = "freezefs", | |
| 355 | + [SBI_IS_WRITABLE] = "writable", | |
| 355 | 356 | }; |
| 356 | 357 | |
| 357 | 358 | static const char *ipu_mode_names[F2FS_IPU_MAX] = { |
| @@ -384,8 +385,8 @@ static int stat_show(struct seq_file *s, void *v) · 26 unmodified lines | ||
| 384 | 385 | "Disabled" : (f2fs_cp_error(sbi) ? "Error" : "Good")); |
| 385 | 386 | if (sbi->s_flag) { |
| 386 | 387 | seq_puts(s, "[SBI:"); |
| 387 | − for_each_set_bit(j, &sbi->s_flag, 32) | |
| 388 | − seq_puts(s, s_flag[j]); | |
| 388 | + for_each_set_bit(j, &sbi->s_flag, MAX_SBI_FLAG) | |
| 389 | + seq_printf(s, " %s", s_flag[j]); | |
| 389 | 390 | seq_puts(s, "]\n"); |
| 390 | 391 | } |
| 391 | 392 | seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ", |
| @@ -29,7 +29,7 @@ static unsigned long dir_blocks(struct inode *inode) · 28 unmodified lines | ||
| 29 | 29 | static unsigned int dir_buckets(unsigned int level, int dir_level) |
| 30 | 30 | { |
| 31 | 31 | if (level + dir_level < MAX_DIR_HASH_DEPTH / 2) |
| 32 | − return 1 << (level + dir_level); | |
| 32 | + return BIT(level + dir_level); | |
| 33 | 33 | else |
| 34 | 34 | return MAX_DIR_BUCKETS; |
| 35 | 35 | } |
| @@ -42,39 +42,6 @@ static unsigned int bucket_blocks(unsigned int level) · 6 unmodified lines | ||
| 42 | 42 | return 4; |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | −static unsigned char f2fs_filetype_table[F2FS_FT_MAX] = { | |
| 46 | − [F2FS_FT_UNKNOWN] = DT_UNKNOWN, | |
| 47 | − [F2FS_FT_REG_FILE] = DT_REG, | |
| 48 | − [F2FS_FT_DIR] = DT_DIR, | |
| 49 | − [F2FS_FT_CHRDEV] = DT_CHR, | |
| 50 | − [F2FS_FT_BLKDEV] = DT_BLK, | |
| 51 | − [F2FS_FT_FIFO] = DT_FIFO, | |
| 52 | − [F2FS_FT_SOCK] = DT_SOCK, | |
| 53 | − [F2FS_FT_SYMLINK] = DT_LNK, | |
| 54 | −}; | |
| 55 | − | |
| 56 | −static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = { | |
| 57 | − [S_IFREG >> S_SHIFT] = F2FS_FT_REG_FILE, | |
| 58 | − [S_IFDIR >> S_SHIFT] = F2FS_FT_DIR, | |
| 59 | − [S_IFCHR >> S_SHIFT] = F2FS_FT_CHRDEV, | |
| 60 | − [S_IFBLK >> S_SHIFT] = F2FS_FT_BLKDEV, | |
| 61 | − [S_IFIFO >> S_SHIFT] = F2FS_FT_FIFO, | |
| 62 | − [S_IFSOCK >> S_SHIFT] = F2FS_FT_SOCK, | |
| 63 | − [S_IFLNK >> S_SHIFT] = F2FS_FT_SYMLINK, | |
| 64 | −}; | |
| 65 | − | |
| 66 | −static void set_de_type(struct f2fs_dir_entry *de, umode_t mode) | |
| 67 | −{ | |
| 68 | − de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT]; | |
| 69 | −} | |
| 70 | − | |
| 71 | −unsigned char f2fs_get_de_type(struct f2fs_dir_entry *de) | |
| 72 | −{ | |
| 73 | − if (de->file_type < F2FS_FT_MAX) | |
| 74 | − return f2fs_filetype_table[de->file_type]; | |
| 75 | − return DT_UNKNOWN; | |
| 76 | −} | |
| 77 | − | |
| 78 | 45 | /* If @dir is casefolded, initialize @fname->cf_name from @fname->usr_fname. */ |
| 79 | 46 | int f2fs_init_casefolded_name(const struct inode *dir, |
| 80 | 47 | struct f2fs_filename *fname) |
| @@ -485,7 +452,7 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de, · 404 unmodified lines | ||
| 485 | 452 | lock_page(page); |
| 486 | 453 | f2fs_wait_on_page_writeback(page, type, true, true); |
| 487 | 454 | de->ino = cpu_to_le32(inode->i_ino); |
| 488 | − set_de_type(de, inode->i_mode); | |
| 455 | + de->file_type = fs_umode_to_ftype(inode->i_mode); | |
| 489 | 456 | set_page_dirty(page); |
| 490 | 457 | |
| 491 | 458 | dir->i_mtime = dir->i_ctime = current_time(dir); |
| @@ -699,7 +666,7 @@ void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *d, · 207 unmodified lines | ||
| 699 | 666 | de->name_len = cpu_to_le16(name->len); |
| 700 | 667 | memcpy(d->filename[bit_pos], name->name, name->len); |
| 701 | 668 | de->ino = cpu_to_le32(ino); |
| 702 | − set_de_type(de, mode); | |
| 669 | + de->file_type = fs_umode_to_ftype(mode); | |
| 703 | 670 | for (i = 0; i < slots; i++) { |
| 704 | 671 | __set_bit_le(bit_pos + i, (void *)d->bitmap); |
| 705 | 672 | /* avoid wrong garbage data for readdir */ |
| @@ -938,14 +905,10 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, · 232 unmodified lines | ||
| 938 | 905 | f2fs_clear_page_cache_dirty_tag(page); |
| 939 | 906 | clear_page_dirty_for_io(page); |
| 940 | 907 | ClearPageUptodate(page); |
| 941 | − | |
| 942 | − clear_page_private_gcing(page); | |
| 908 | + clear_page_private_all(page); | |
| 943 | 909 | |
| 944 | 910 | inode_dec_dirty_pages(dir); |
| 945 | 911 | f2fs_remove_dirty_inode(dir); |
| 946 | − | |
| 947 | − detach_page_private(page); | |
| 948 | − set_page_private(page, 0); | |
| 949 | 912 | } |
| 950 | 913 | f2fs_put_page(page, 1); |
| 951 | 914 | |
| @@ -1036,7 +999,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d, · 84 unmodified lines | ||
| 1036 | 999 | continue; |
| 1037 | 1000 | } |
| 1038 | 1001 | |
| 1039 | − d_type = f2fs_get_de_type(de); | |
| 1002 | + d_type = fs_ftype_to_dtype(de->file_type); | |
| 1040 | 1003 | |
| 1041 | 1004 | de_name.name = d->filename[bit_pos]; |
| 1042 | 1005 | de_name.len = le16_to_cpu(de->name_len); |
| @@ -23,18 +23,26 @@ bool sanity_check_extent_cache(struct inode *inode) · 22 unmodified lines | ||
| 23 | 23 | { |
| 24 | 24 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
| 25 | 25 | struct f2fs_inode_info *fi = F2FS_I(inode); |
| 26 | + struct extent_tree *et = fi->extent_tree[EX_READ]; | |
| 26 | 27 | struct extent_info *ei; |
| 27 | 28 | |
| 28 | − if (!fi->extent_tree[EX_READ]) | |
| 29 | + if (!et) | |
| 30 | + return true; | |
| 31 | + | |
| 32 | + ei = &et->largest; | |
| 33 | + if (!ei->len) | |
| 29 | 34 | return true; |
| 30 | 35 | |
| 31 | − ei = &fi->extent_tree[EX_READ]->largest; | |
| 36 | + /* Let's drop, if checkpoint got corrupted. */ | |
| 37 | + if (is_set_ckpt_flags(sbi, CP_ERROR_FLAG)) { | |
| 38 | + ei->len = 0; | |
| 39 | + et->largest_updated = true; | |
| 40 | + return true; | |
| 41 | + } | |
| 32 | 42 | |
| 33 | − if (ei->len && | |
| 34 | − (!f2fs_is_valid_blkaddr(sbi, ei->blk, | |
| 35 | − DATA_GENERIC_ENHANCE) || | |
| 36 | − !f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1, | |
| 37 | − DATA_GENERIC_ENHANCE))) { | |
| 43 | + if (!f2fs_is_valid_blkaddr(sbi, ei->blk, DATA_GENERIC_ENHANCE) || | |
| 44 | + !f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1, | |
| 45 | + DATA_GENERIC_ENHANCE)) { | |
| 38 | 46 | set_sbi_flag(sbi, SBI_NEED_FSCK); |
| 39 | 47 | f2fs_warn(sbi, "%s: inode (ino=%lx) extent info [%u, %u, %u] is incorrect, run fsck to fix", |
| 40 | 48 | __func__, inode->i_ino, |
| @@ -86,7 +94,6 @@ static bool __may_age_extent_tree(struct inode *inode) · 45 unmodified lines | ||
| 86 | 94 | |
| 87 | 95 | if (!test_opt(sbi, AGE_EXTENT_CACHE)) |
| 88 | 96 | return false; |
| 89 | − /* don't cache block age info for cold file */ | |
| 90 | 97 | if (is_inode_flag_set(inode, FI_COMPRESSED_FILE)) |
| 91 | 98 | return false; |
| 92 | 99 | if (file_is_cold(inode)) |
| @@ -161,118 +168,52 @@ static bool __is_front_mergeable(struct extent_info *cur, · 68 unmodified lines | ||
| 161 | 168 | return __is_extent_mergeable(cur, front, type); |
| 162 | 169 | } |
| 163 | 170 | |
| 164 | −static struct rb_entry *__lookup_rb_tree_fast(struct rb_entry *cached_re, | |
| 165 | − unsigned int ofs) | |
| 166 | −{ | |
| 167 | − if (cached_re) { | |
| 168 | − if (cached_re->ofs <= ofs && | |
| 169 | − cached_re->ofs + cached_re->len > ofs) { | |
| 170 | − return cached_re; | |
| 171 | − } | |
| 172 | − } | |
| 173 | − return NULL; | |
| 174 | −} | |
| 175 | − | |
| 176 | −static struct rb_entry *__lookup_rb_tree_slow(struct rb_root_cached *root, | |
| 177 | − unsigned int ofs) | |
| 171 | +static struct extent_node *__lookup_extent_node(struct rb_root_cached *root, | |
| 172 | + struct extent_node *cached_en, unsigned int fofs) | |
| 178 | 173 | { |
| 179 | 174 | struct rb_node *node = root->rb_root.rb_node; |
| 180 | − struct rb_entry *re; | |
| 175 | + struct extent_node *en; | |
| 181 | 176 | |
| 177 | + /* check a cached entry */ | |
| 178 | + if (cached_en && cached_en->ei.fofs <= fofs && | |
| 179 | + cached_en->ei.fofs + cached_en->ei.len > fofs) | |
| 180 | + return cached_en; | |
| 181 | + | |
| 182 | + /* check rb_tree */ | |
| 182 | 183 | while (node) { |
| 183 | − re = rb_entry(node, struct rb_entry, rb_node); | |
| 184 | + en = rb_entry(node, struct extent_node, rb_node); | |
| 184 | 185 | |
| 185 | − if (ofs < re->ofs) | |
| 186 | + if (fofs < en->ei.fofs) | |
| 186 | 187 | node = node->rb_left; |
| 187 | − else if (ofs >= re->ofs + re->len) | |
| 188 | + else if (fofs >= en->ei.fofs + en->ei.len) | |
| 188 | 189 | node = node->rb_right; |
| 189 | 190 | else |
| 190 | − return re; | |
| 191 | + return en; | |
| 191 | 192 | } |
| 192 | 193 | return NULL; |
| 193 | 194 | } |
| 194 | 195 | |
| 195 | −struct rb_entry *f2fs_lookup_rb_tree(struct rb_root_cached *root, | |
| 196 | − struct rb_entry *cached_re, unsigned int ofs) | |
| 197 | −{ | |
| 198 | − struct rb_entry *re; | |
| 199 | − | |
| 200 | − re = __lookup_rb_tree_fast(cached_re, ofs); | |
| 201 | − if (!re) | |
| 202 | − return __lookup_rb_tree_slow(root, ofs); | |
| 203 | − | |
| 204 | − return re; | |
| 205 | −} | |
| 206 | − | |
| 207 | −struct rb_node **f2fs_lookup_rb_tree_ext(struct f2fs_sb_info *sbi, | |
| 208 | − struct rb_root_cached *root, | |
| 209 | − struct rb_node **parent, | |
| 210 | − unsigned long long key, bool *leftmost) | |
| 211 | −{ | |
| 212 | − struct rb_node **p = &root->rb_root.rb_node; | |
| 213 | − struct rb_entry *re; | |
| 214 | − | |
| 215 | − while (*p) { | |
| 216 | − *parent = *p; | |
| 217 | − re = rb_entry(*parent, struct rb_entry, rb_node); | |
| 218 | − | |
| 219 | − if (key < re->key) { | |
| 220 | − p = &(*p)->rb_left; | |
| 221 | − } else { | |
| 222 | − p = &(*p)->rb_right; | |
| 223 | − *leftmost = false; | |
| 224 | − } | |
| 225 | − } | |
| 226 | − | |
| 227 | − return p; | |
| 228 | −} | |
| 229 | − | |
| 230 | −struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi, | |
| 231 | − struct rb_root_cached *root, | |
| 232 | − struct rb_node **parent, | |
| 233 | − unsigned int ofs, bool *leftmost) | |
| 234 | −{ | |
| 235 | − struct rb_node **p = &root->rb_root.rb_node; | |
| 236 | − struct rb_entry *re; | |
| 237 | − | |
| 238 | − while (*p) { | |
| 239 | − *parent = *p; | |
| 240 | − re = rb_entry(*parent, struct rb_entry, rb_node); | |
| 241 | − | |
| 242 | − if (ofs < re->ofs) { | |
| 243 | − p = &(*p)->rb_left; | |
| 244 | − } else if (ofs >= re->ofs + re->len) { | |
| 245 | − p = &(*p)->rb_right; | |
| 246 | − *leftmost = false; | |
| 247 | − } else { | |
| 248 | − f2fs_bug_on(sbi, 1); | |
| 249 | − } | |
| 250 | − } | |
| 251 | − | |
| 252 | − return p; | |
| 253 | −} | |
| 254 | − | |
| 255 | 196 | /* |
| 256 | − * lookup rb entry in position of @ofs in rb-tree, | |
| 197 | + * lookup rb entry in position of @fofs in rb-tree, | |
| 257 | 198 | * if hit, return the entry, otherwise, return NULL |
| 258 | − * @prev_ex: extent before ofs | |
| 259 | − * @next_ex: extent after ofs | |
| 260 | − * @insert_p: insert point for new extent at ofs | |
| 199 | + * @prev_ex: extent before fofs | |
| 200 | + * @next_ex: extent after fofs | |
| 201 | + * @insert_p: insert point for new extent at fofs | |
| 261 | 202 | * in order to simplify the insertion after. |
| 262 | 203 | * tree must stay unchanged between lookup and insertion. |
| 263 | 204 | */ |
| 264 | −struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root, | |
| 265 | − struct rb_entry *cached_re, | |
| 266 | − unsigned int ofs, | |
| 267 | − struct rb_entry **prev_entry, | |
| 268 | − struct rb_entry **next_entry, | |
| 205 | +static struct extent_node *__lookup_extent_node_ret(struct rb_root_cached *root, | |
| 206 | + struct extent_node *cached_en, | |
| 207 | + unsigned int fofs, | |
| 208 | + struct extent_node **prev_entry, | |
| 209 | + struct extent_node **next_entry, | |
| 269 | 210 | struct rb_node ***insert_p, |
| 270 | 211 | struct rb_node **insert_parent, |
| 271 | − bool force, bool *leftmost) | |
| 212 | + bool *leftmost) | |
| 272 | 213 | { |
| 273 | 214 | struct rb_node **pnode = &root->rb_root.rb_node; |
| 274 | 215 | struct rb_node *parent = NULL, *tmp_node; |
| 275 | − struct rb_entry *re = cached_re; | |
| 216 | + struct extent_node *en = cached_en; | |
| 276 | 217 | |
| 277 | 218 | *insert_p = NULL; |
| 278 | 219 | *insert_parent = NULL; |
| @@ -282,24 +223,20 @@ struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root, · 3 unmodified lines | ||
| 282 | 223 | if (RB_EMPTY_ROOT(&root->rb_root)) |
| 283 | 224 | return NULL; |
| 284 | 225 | |
| 285 | − if (re) { | |
| 286 | − if (re->ofs <= ofs && re->ofs + re->len > ofs) | |
| 287 | − goto lookup_neighbors; | |
| 288 | − } | |
| 226 | + if (en && en->ei.fofs <= fofs && en->ei.fofs + en->ei.len > fofs) | |
| 227 | + goto lookup_neighbors; | |
| 289 | 228 | |
| 290 | − if (leftmost) | |
| 291 | − *leftmost = true; | |
| 229 | + *leftmost = true; | |
| 292 | 230 | |
| 293 | 231 | while (*pnode) { |
| 294 | 232 | parent = *pnode; |
| 295 | − re = rb_entry(*pnode, struct rb_entry, rb_node); | |
| 233 | + en = rb_entry(*pnode, struct extent_node, rb_node); | |
| 296 | 234 | |
| 297 | − if (ofs < re->ofs) { | |
| 235 | + if (fofs < en->ei.fofs) { | |
| 298 | 236 | pnode = &(*pnode)->rb_left; |
| 299 | − } else if (ofs >= re->ofs + re->len) { | |
| 237 | + } else if (fofs >= en->ei.fofs + en->ei.len) { | |
| 300 | 238 | pnode = &(*pnode)->rb_right; |
| 301 | − if (leftmost) | |
| 302 | − *leftmost = false; | |
| 239 | + *leftmost = false; | |
| 303 | 240 | } else { |
| 304 | 241 | goto lookup_neighbors; |
| 305 | 242 | } |
| @@ -308,71 +245,32 @@ struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root, · 2 unmodified lines | ||
| 308 | 245 | *insert_p = pnode; |
| 309 | 246 | *insert_parent = parent; |
| 310 | 247 | |
| 311 | − re = rb_entry(parent, struct rb_entry, rb_node); | |
| 248 | + en = rb_entry(parent, struct extent_node, rb_node); | |
| 312 | 249 | tmp_node = parent; |
| 313 | − if (parent && ofs > re->ofs) | |
| 250 | + if (parent && fofs > en->ei.fofs) | |
| 314 | 251 | tmp_node = rb_next(parent); |
| 315 | − *next_entry = rb_entry_safe(tmp_node, struct rb_entry, rb_node); | |
| 252 | + *next_entry = rb_entry_safe(tmp_node, struct extent_node, rb_node); | |
| 316 | 253 | |
| 317 | 254 | tmp_node = parent; |
| 318 | − if (parent && ofs < re->ofs) | |
| 255 | + if (parent && fofs < en->ei.fofs) | |
| 319 | 256 | tmp_node = rb_prev(parent); |
| 320 | − *prev_entry = rb_entry_safe(tmp_node, struct rb_entry, rb_node); | |
| 257 | + *prev_entry = rb_entry_safe(tmp_node, struct extent_node, rb_node); | |
| 321 | 258 | return NULL; |
| 322 | 259 | |
| 323 | 260 | lookup_neighbors: |
| 324 | − if (ofs == re->ofs || force) { | |
| 261 | + if (fofs == en->ei.fofs) { | |
| 325 | 262 | /* lookup prev node for merging backward later */ |
| 326 | − tmp_node = rb_prev(&re->rb_node); | |
| 327 | − *prev_entry = rb_entry_safe(tmp_node, struct rb_entry, rb_node); | |
| 263 | + tmp_node = rb_prev(&en->rb_node); | |
| 264 | + *prev_entry = rb_entry_safe(tmp_node, | |
| 265 | + struct extent_node, rb_node); | |
| 328 | 266 | } |
| 329 | − if (ofs == re->ofs + re->len - 1 || force) { | |
| 267 | + if (fofs == en->ei.fofs + en->ei.len - 1) { | |
| 330 | 268 | /* lookup next node for merging frontward later */ |
| 331 | − tmp_node = rb_next(&re->rb_node); | |
| 332 | − *next_entry = rb_entry_safe(tmp_node, struct rb_entry, rb_node); | |
| 333 | − } | |
| 334 | − return re; | |
| 335 | −} | |
| 336 | − | |
| 337 | −bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi, | |
| 338 | − struct rb_root_cached *root, bool check_key) | |
| 339 | −{ | |
| 340 | −#ifdef CONFIG_F2FS_CHECK_FS | |
| 341 | − struct rb_node *cur = rb_first_cached(root), *next; | |
| 342 | − struct rb_entry *cur_re, *next_re; | |
| 343 | − | |
| 344 | − if (!cur) | |
| 345 | − return true; | |
| 346 | − | |
| 347 | − while (cur) { | |
| 348 | − next = rb_next(cur); | |
| 349 | − if (!next) | |
| 350 | − return true; | |
| 351 | − | |
| 352 | − cur_re = rb_entry(cur, struct rb_entry, rb_node); | |
| 353 | − next_re = rb_entry(next, struct rb_entry, rb_node); | |
| 354 | − | |
| 355 | − if (check_key) { | |
| 356 | − if (cur_re->key > next_re->key) { | |
| 357 | − f2fs_info(sbi, "inconsistent rbtree, " | |
| 358 | − "cur(%llu) next(%llu)", | |
| 359 | − cur_re->key, next_re->key); | |
| 360 | − return false; | |
| 361 | − } | |
| 362 | − goto next; | |
| 363 | − } | |
| 364 | − | |
| 365 | − if (cur_re->ofs + cur_re->len > next_re->ofs) { | |
| 366 | − f2fs_info(sbi, "inconsistent rbtree, cur(%u, %u) next(%u, %u)", | |
| 367 | − cur_re->ofs, cur_re->len, | |
| 368 | − next_re->ofs, next_re->len); | |
| 369 | − return false; | |
| 370 | − } | |
| 371 | −next: | |
| 372 | − cur = next; | |
| 269 | + tmp_node = rb_next(&en->rb_node); | |
| 270 | + *next_entry = rb_entry_safe(tmp_node, | |
| 271 | + struct extent_node, rb_node); | |
| 373 | 272 | } |
| 374 | −#endif | |
| 375 | − return true; | |
| 273 | + return en; | |
| 376 | 274 | } |
| 377 | 275 | |
| 378 | 276 | static struct kmem_cache *extent_tree_slab; |
| @@ -587,8 +485,7 @@ static bool __lookup_extent_tree(struct inode *inode, pgoff_t pgofs, · 208 unmodified lines | ||
| 587 | 485 | goto out; |
| 588 | 486 | } |
| 589 | 487 | |
| 590 | − en = (struct extent_node *)f2fs_lookup_rb_tree(&et->root, | |
| 591 | − (struct rb_entry *)et->cached_en, pgofs); | |
| 488 | + en = __lookup_extent_node(&et->root, et->cached_en, pgofs); | |
| 592 | 489 | if (!en) |
| 593 | 490 | goto out; |
| 594 | 491 | |
| @@ -662,7 +559,7 @@ static struct extent_node *__insert_extent_tree(struct f2fs_sb_info *sbi, · 67 unmodified lines | ||
| 662 | 559 | bool leftmost) |
| 663 | 560 | { |
| 664 | 561 | struct extent_tree_info *eti = &sbi->extent_tree[et->type]; |
| 665 | − struct rb_node **p; | |
| 562 | + struct rb_node **p = &et->root.rb_root.rb_node; | |
| 666 | 563 | struct rb_node *parent = NULL; |
| 667 | 564 | struct extent_node *en = NULL; |
| 668 | 565 | |
| @@ -674,8 +571,21 @@ static struct extent_node *__insert_extent_tree(struct f2fs_sb_info *sbi, · 5 unmodified lines | ||
| 674 | 571 | |
| 675 | 572 | leftmost = true; |
| 676 | 573 | |
| 677 | − p = f2fs_lookup_rb_tree_for_insert(sbi, &et->root, &parent, | |
| 678 | − ei->fofs, &leftmost); | |
| 574 | + /* look up extent_node in the rb tree */ | |
| 575 | + while (*p) { | |
| 576 | + parent = *p; | |
| 577 | + en = rb_entry(parent, struct extent_node, rb_node); | |
| 578 | + | |
| 579 | + if (ei->fofs < en->ei.fofs) { | |
| 580 | + p = &(*p)->rb_left; | |
| 581 | + } else if (ei->fofs >= en->ei.fofs + en->ei.len) { | |
| 582 | + p = &(*p)->rb_right; | |
| 583 | + leftmost = false; | |
| 584 | + } else { | |
| 585 | + f2fs_bug_on(sbi, 1); | |
| 586 | + } | |
| 587 | + } | |
| 588 | + | |
| 679 | 589 | do_insert: |
| 680 | 590 | en = __attach_extent_node(sbi, et, ei, parent, p, leftmost); |
| 681 | 591 | if (!en) |
| @@ -734,11 +644,10 @@ static void __update_extent_tree_range(struct inode *inode, · 52 unmodified lines | ||
| 734 | 644 | } |
| 735 | 645 | |
| 736 | 646 | /* 1. lookup first extent node in range [fofs, fofs + len - 1] */ |
| 737 | − en = (struct extent_node *)f2fs_lookup_rb_tree_ret(&et->root, | |
| 738 | − (struct rb_entry *)et->cached_en, fofs, | |
| 739 | − (struct rb_entry **)&prev_en, | |
| 740 | − (struct rb_entry **)&next_en, | |
| 741 | − &insert_p, &insert_parent, false, | |
| 647 | + en = __lookup_extent_node_ret(&et->root, | |
| 648 | + et->cached_en, fofs, | |
| 649 | + &prev_en, &next_en, | |
| 650 | + &insert_p, &insert_parent, | |
| 742 | 651 | &leftmost); |
| 743 | 652 | if (!en) |
| 744 | 653 | en = next_en; |
| @@ -876,12 +785,11 @@ void f2fs_update_read_extent_tree_range_compressed(struct inode *inode, · 131 unmodified lines | ||
| 876 | 785 | |
| 877 | 786 | write_lock(&et->lock); |
| 878 | 787 | |
| 879 | − en = (struct extent_node *)f2fs_lookup_rb_tree_ret(&et->root, | |
| 880 | − (struct rb_entry *)et->cached_en, fofs, | |
| 881 | − (struct rb_entry **)&prev_en, | |
| 882 | − (struct rb_entry **)&next_en, | |
| 883 | − &insert_p, &insert_parent, false, | |
| 884 | − &leftmost); | |
| 788 | + en = __lookup_extent_node_ret(&et->root, | |
| 789 | + et->cached_en, fofs, | |
| 790 | + &prev_en, &next_en, | |
| 791 | + &insert_p, &insert_parent, | |
| 792 | + &leftmost); | |
| 885 | 793 | if (en) |
| 886 | 794 | goto unlock_out; |
| 887 | 795 | |
| @@ -65,7 +65,7 @@ enum { · 64 unmodified lines | ||
| 65 | 65 | }; |
| 66 | 66 | |
| 67 | 67 | #ifdef CONFIG_F2FS_FAULT_INJECTION |
| 68 | −#define F2FS_ALL_FAULT_TYPE ((1 << FAULT_MAX) - 1) | |
| 68 | +#define F2FS_ALL_FAULT_TYPE (GENMASK(FAULT_MAX - 1, 0)) | |
| 69 | 69 | |
| 70 | 70 | struct f2fs_fault_info { |
| 71 | 71 | atomic_t inject_ops; |
| @@ -74,7 +74,7 @@ struct f2fs_fault_info { · 2 unmodified lines | ||
| 74 | 74 | }; |
| 75 | 75 | |
| 76 | 76 | extern const char *f2fs_fault_name[FAULT_MAX]; |
| 77 | −#define IS_FAULT_SET(fi, type) ((fi)->inject_type & (1 << (type))) | |
| 77 | +#define IS_FAULT_SET(fi, type) ((fi)->inject_type & BIT(type)) | |
| 78 | 78 | #endif |
| 79 | 79 | |
| 80 | 80 | /* |
| @@ -353,15 +353,7 @@ struct discard_info { · 272 unmodified lines | ||
| 353 | 353 | |
| 354 | 354 | struct discard_cmd { |
| 355 | 355 | struct rb_node rb_node; /* rb node located in rb-tree */ |
| 356 | − union { | |
| 357 | − struct { | |
| 358 | − block_t lstart; /* logical start address */ | |
| 359 | − block_t len; /* length */ | |
| 360 | − block_t start; /* actual start address in dev */ | |
| 361 | − }; | |
| 362 | − struct discard_info di; /* discard info */ | |
| 363 | − | |
| 364 | − }; | |
| 356 | + struct discard_info di; /* discard info */ | |
| 365 | 357 | struct list_head list; /* command list */ |
| 366 | 358 | struct completion wait; /* compleation */ |
| 367 | 359 | struct block_device *bdev; /* bdev */ |
| @@ -628,17 +620,6 @@ enum extent_type { · 260 unmodified lines | ||
| 628 | 620 | NR_EXTENT_CACHES, |
| 629 | 621 | }; |
| 630 | 622 | |
| 631 | −struct rb_entry { | |
| 632 | − struct rb_node rb_node; /* rb node located in rb-tree */ | |
| 633 | − union { | |
| 634 | − struct { | |
| 635 | − unsigned int ofs; /* start offset of the entry */ | |
| 636 | − unsigned int len; /* length of the entry */ | |
| 637 | − }; | |
| 638 | − unsigned long long key; /* 64-bits key */ | |
| 639 | − } __packed; | |
| 640 | −}; | |
| 641 | − | |
| 642 | 623 | struct extent_info { |
| 643 | 624 | unsigned int fofs; /* start offset in a file */ |
| 644 | 625 | unsigned int len; /* length of the extent */ |
| @@ -862,7 +843,7 @@ struct f2fs_inode_info { · 217 unmodified lines | ||
| 862 | 843 | kprojid_t i_projid; /* id for project quota */ |
| 863 | 844 | int i_inline_xattr_size; /* inline xattr size */ |
| 864 | 845 | struct timespec64 i_crtime; /* inode creation time */ |
| 865 | − struct timespec64 i_disk_time[4];/* inode disk times */ | |
| 846 | + struct timespec64 i_disk_time[3];/* inode disk times */ | |
| 866 | 847 | |
| 867 | 848 | /* for file compress */ |
| 868 | 849 | atomic_t i_compr_blocks; /* # of compressed blocks */ |
| @@ -1293,7 +1274,10 @@ struct f2fs_gc_control { · 424 unmodified lines | ||
| 1293 | 1274 | unsigned int nr_free_secs; /* # of free sections to do GC */ |
| 1294 | 1275 | }; |
| 1295 | 1276 | |
| 1296 | −/* For s_flag in struct f2fs_sb_info */ | |
| 1277 | +/* | |
| 1278 | + * For s_flag in struct f2fs_sb_info | |
| 1279 | + * Modification on enum should be synchronized with s_flag array | |
| 1280 | + */ | |
| 1297 | 1281 | enum { |
| 1298 | 1282 | SBI_IS_DIRTY, /* dirty flag for checkpoint */ |
| 1299 | 1283 | SBI_IS_CLOSE, /* specify unmounting */ |
| @@ -1310,6 +1294,8 @@ enum { · 10 unmodified lines | ||
| 1310 | 1294 | SBI_QUOTA_NEED_REPAIR, /* quota file may be corrupted */ |
| 1311 | 1295 | SBI_IS_RESIZEFS, /* resizefs is in process */ |
| 1312 | 1296 | SBI_IS_FREEZING, /* freezefs is in process */ |
| 1297 | + SBI_IS_WRITABLE, /* remove ro mountoption transiently */ | |
| 1298 | + MAX_SBI_FLAG, | |
| 1313 | 1299 | }; |
| 1314 | 1300 | |
| 1315 | 1301 | enum { |
| @@ -1412,86 +1398,6 @@ enum { · 96 unmodified lines | ||
| 1412 | 1398 | PAGE_PRIVATE_MAX |
| 1413 | 1399 | }; |
| 1414 | 1400 | |
| 1415 | −#define PAGE_PRIVATE_GET_FUNC(name, flagname) \ | |
| 1416 | −static inline bool page_private_##name(struct page *page) \ | |
| 1417 | −{ \ | |
| 1418 | − return PagePrivate(page) && \ | |
| 1419 | − test_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)) && \ | |
| 1420 | − test_bit(PAGE_PRIVATE_##flagname, &page_private(page)); \ | |
| 1421 | −} | |
| 1422 | − | |
| 1423 | −#define PAGE_PRIVATE_SET_FUNC(name, flagname) \ | |
| 1424 | −static inline void set_page_private_##name(struct page *page) \ | |
| 1425 | −{ \ | |
| 1426 | − if (!PagePrivate(page)) { \ | |
| 1427 | − get_page(page); \ | |
| 1428 | − SetPagePrivate(page); \ | |
| 1429 | − set_page_private(page, 0); \ | |
| 1430 | − } \ | |
| 1431 | − set_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)); \ | |
| 1432 | − set_bit(PAGE_PRIVATE_##flagname, &page_private(page)); \ | |
| 1433 | −} | |
| 1434 | − | |
| 1435 | −#define PAGE_PRIVATE_CLEAR_FUNC(name, flagname) \ | |
| 1436 | −static inline void clear_page_private_##name(struct page *page) \ | |
| 1437 | −{ \ | |
| 1438 | − clear_bit(PAGE_PRIVATE_##flagname, &page_private(page)); \ | |
| 1439 | − if (page_private(page) == 1 << PAGE_PRIVATE_NOT_POINTER) { \ | |
| 1440 | − set_page_private(page, 0); \ | |
| 1441 | − if (PagePrivate(page)) { \ | |
| 1442 | − ClearPagePrivate(page); \ | |
| 1443 | − put_page(page); \ | |
| 1444 | − }\ | |
| 1445 | − } \ | |
| 1446 | −} | |
| 1447 | − | |
| 1448 | −PAGE_PRIVATE_GET_FUNC(nonpointer, NOT_POINTER); | |
| 1449 | −PAGE_PRIVATE_GET_FUNC(inline, INLINE_INODE); | |
| 1450 | −PAGE_PRIVATE_GET_FUNC(gcing, ONGOING_MIGRATION); | |
| 1451 | −PAGE_PRIVATE_GET_FUNC(dummy, DUMMY_WRITE); | |
| 1452 | − | |
| 1453 | −PAGE_PRIVATE_SET_FUNC(reference, REF_RESOURCE); | |
| 1454 | −PAGE_PRIVATE_SET_FUNC(inline, INLINE_INODE); | |
| 1455 | −PAGE_PRIVATE_SET_FUNC(gcing, ONGOING_MIGRATION); | |
| 1456 | −PAGE_PRIVATE_SET_FUNC(dummy, DUMMY_WRITE); | |
| 1457 | − | |
| 1458 | −PAGE_PRIVATE_CLEAR_FUNC(reference, REF_RESOURCE); | |
| 1459 | −PAGE_PRIVATE_CLEAR_FUNC(inline, INLINE_INODE); | |
| 1460 | −PAGE_PRIVATE_CLEAR_FUNC(gcing, ONGOING_MIGRATION); | |
| 1461 | −PAGE_PRIVATE_CLEAR_FUNC(dummy, DUMMY_WRITE); | |
| 1462 | − | |
| 1463 | −static inline unsigned long get_page_private_data(struct page *page) | |
| 1464 | −{ | |
| 1465 | − unsigned long data = page_private(page); | |
| 1466 | − | |
| 1467 | − if (!test_bit(PAGE_PRIVATE_NOT_POINTER, &data)) | |
| 1468 | − return 0; | |
| 1469 | − return data >> PAGE_PRIVATE_MAX; | |
| 1470 | −} | |
| 1471 | − | |
| 1472 | −static inline void set_page_private_data(struct page *page, unsigned long data) | |
| 1473 | −{ | |
| 1474 | − if (!PagePrivate(page)) { | |
| 1475 | − get_page(page); | |
| 1476 | − SetPagePrivate(page); | |
| 1477 | − set_page_private(page, 0); | |
| 1478 | − } | |
| 1479 | − set_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)); | |
| 1480 | − page_private(page) |= data << PAGE_PRIVATE_MAX; | |
| 1481 | −} | |
| 1482 | − | |
| 1483 | −static inline void clear_page_private_data(struct page *page) | |
| 1484 | −{ | |
| 1485 | − page_private(page) &= (1 << PAGE_PRIVATE_MAX) - 1; | |
| 1486 | − if (page_private(page) == 1 << PAGE_PRIVATE_NOT_POINTER) { | |
| 1487 | − set_page_private(page, 0); | |
| 1488 | − if (PagePrivate(page)) { | |
| 1489 | − ClearPagePrivate(page); | |
| 1490 | − put_page(page); | |
| 1491 | − } | |
| 1492 | − } | |
| 1493 | −} | |
| 1494 | − | |
| 1495 | 1401 | /* For compression */ |
| 1496 | 1402 | enum compress_algorithm_type { |
| 1497 | 1403 | COMPRESS_LZO, |
| @@ -1617,7 +1523,6 @@ struct f2fs_sb_info { · 119 unmodified lines | ||
| 1617 | 1523 | |
| 1618 | 1524 | #ifdef CONFIG_BLK_DEV_ZONED |
| 1619 | 1525 | unsigned int blocks_per_blkz; /* F2FS blocks per zone */ |
| 1620 | − unsigned int log_blocks_per_blkz; /* log2 F2FS blocks per zone */ | |
| 1621 | 1526 | #endif |
| 1622 | 1527 | |
| 1623 | 1528 | /* for node-related operations */ |
| @@ -2386,6 +2291,80 @@ void f2fs_printk(struct f2fs_sb_info *sbi, const char *fmt, ...); · 762 unmodified lines | ||
| 2386 | 2291 | #define f2fs_debug(sbi, fmt, ...) \ |
| 2387 | 2292 | f2fs_printk(sbi, KERN_DEBUG fmt, ##__VA_ARGS__) |
| 2388 | 2293 | |
| 2294 | +#define PAGE_PRIVATE_GET_FUNC(name, flagname) \ | |
| 2295 | +static inline bool page_private_##name(struct page *page) \ | |
| 2296 | +{ \ | |
| 2297 | + return PagePrivate(page) && \ | |
| 2298 | + test_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)) && \ | |
| 2299 | + test_bit(PAGE_PRIVATE_##flagname, &page_private(page)); \ | |
| 2300 | +} | |
| 2301 | + | |
| 2302 | +#define PAGE_PRIVATE_SET_FUNC(name, flagname) \ | |
| 2303 | +static inline void set_page_private_##name(struct page *page) \ | |
| 2304 | +{ \ | |
| 2305 | + if (!PagePrivate(page)) \ | |
| 2306 | + attach_page_private(page, (void *)0); \ | |
| 2307 | + set_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)); \ | |
| 2308 | + set_bit(PAGE_PRIVATE_##flagname, &page_private(page)); \ | |
| 2309 | +} | |
| 2310 | + | |
| 2311 | +#define PAGE_PRIVATE_CLEAR_FUNC(name, flagname) \ | |
| 2312 | +static inline void clear_page_private_##name(struct page *page) \ | |
| 2313 | +{ \ | |
| 2314 | + clear_bit(PAGE_PRIVATE_##flagname, &page_private(page)); \ | |
| 2315 | + if (page_private(page) == BIT(PAGE_PRIVATE_NOT_POINTER)) \ | |
| 2316 | + detach_page_private(page); \ | |
| 2317 | +} | |
| 2318 | + | |
| 2319 | +PAGE_PRIVATE_GET_FUNC(nonpointer, NOT_POINTER); | |
| 2320 | +PAGE_PRIVATE_GET_FUNC(inline, INLINE_INODE); | |
| 2321 | +PAGE_PRIVATE_GET_FUNC(gcing, ONGOING_MIGRATION); | |
| 2322 | +PAGE_PRIVATE_GET_FUNC(dummy, DUMMY_WRITE); | |
| 2323 | + | |
| 2324 | +PAGE_PRIVATE_SET_FUNC(reference, REF_RESOURCE); | |
| 2325 | +PAGE_PRIVATE_SET_FUNC(inline, INLINE_INODE); | |
| 2326 | +PAGE_PRIVATE_SET_FUNC(gcing, ONGOING_MIGRATION); | |
| 2327 | +PAGE_PRIVATE_SET_FUNC(dummy, DUMMY_WRITE); | |
| 2328 | + | |
| 2329 | +PAGE_PRIVATE_CLEAR_FUNC(reference, REF_RESOURCE); | |
| 2330 | +PAGE_PRIVATE_CLEAR_FUNC(inline, INLINE_INODE); | |
| 2331 | +PAGE_PRIVATE_CLEAR_FUNC(gcing, ONGOING_MIGRATION); | |
| 2332 | +PAGE_PRIVATE_CLEAR_FUNC(dummy, DUMMY_WRITE); | |
| 2333 | + | |
| 2334 | +static inline unsigned long get_page_private_data(struct page *page) | |
| 2335 | +{ | |
| 2336 | + unsigned long data = page_private(page); | |
| 2337 | + | |
| 2338 | + if (!test_bit(PAGE_PRIVATE_NOT_POINTER, &data)) | |
| 2339 | + return 0; | |
| 2340 | + return data >> PAGE_PRIVATE_MAX; | |
| 2341 | +} | |
| 2342 | + | |
| 2343 | +static inline void set_page_private_data(struct page *page, unsigned long data) | |
| 2344 | +{ | |
| 2345 | + if (!PagePrivate(page)) | |
| 2346 | + attach_page_private(page, (void *)0); | |
| 2347 | + set_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)); | |
| 2348 | + page_private(page) |= data << PAGE_PRIVATE_MAX; | |
| 2349 | +} | |
| 2350 | + | |
| 2351 | +static inline void clear_page_private_data(struct page *page) | |
| 2352 | +{ | |
| 2353 | + page_private(page) &= GENMASK(PAGE_PRIVATE_MAX - 1, 0); | |
| 2354 | + if (page_private(page) == BIT(PAGE_PRIVATE_NOT_POINTER)) | |
| 2355 | + detach_page_private(page); | |
| 2356 | +} | |
| 2357 | + | |
| 2358 | +static inline void clear_page_private_all(struct page *page) | |
| 2359 | +{ | |
| 2360 | + clear_page_private_data(page); | |
| 2361 | + clear_page_private_reference(page); | |
| 2362 | + clear_page_private_gcing(page); | |
| 2363 | + clear_page_private_inline(page); | |
| 2364 | + | |
| 2365 | + f2fs_bug_on(F2FS_P_SB(page), page_private(page)); | |
| 2366 | +} | |
| 2367 | + | |
| 2389 | 2368 | static inline void dec_valid_block_count(struct f2fs_sb_info *sbi, |
| 2390 | 2369 | struct inode *inode, |
| 2391 | 2370 | block_t count) |
| @@ -2892,7 +2871,7 @@ static inline int f2fs_test_bit(unsigned int nr, char *addr) · 500 unmodified lines | ||
| 2892 | 2871 | int mask; |
| 2893 | 2872 | |
| 2894 | 2873 | addr += (nr >> 3); |
| 2895 | − mask = 1 << (7 - (nr & 0x07)); | |
| 2874 | + mask = BIT(7 - (nr & 0x07)); | |
| 2896 | 2875 | return mask & *addr; |
| 2897 | 2876 | } |
| 2898 | 2877 | |
| @@ -2901,7 +2880,7 @@ static inline void f2fs_set_bit(unsigned int nr, char *addr) · 2 unmodified lines | ||
| 2901 | 2880 | int mask; |
| 2902 | 2881 | |
| 2903 | 2882 | addr += (nr >> 3); |
| 2904 | − mask = 1 << (7 - (nr & 0x07)); | |
| 2883 | + mask = BIT(7 - (nr & 0x07)); | |
| 2905 | 2884 | *addr |= mask; |
| 2906 | 2885 | } |
| 2907 | 2886 | |
| @@ -2910,7 +2889,7 @@ static inline void f2fs_clear_bit(unsigned int nr, char *addr) · 2 unmodified lines | ||
| 2910 | 2889 | int mask; |
| 2911 | 2890 | |
| 2912 | 2891 | addr += (nr >> 3); |
| 2913 | − mask = 1 << (7 - (nr & 0x07)); | |
| 2892 | + mask = BIT(7 - (nr & 0x07)); | |
| 2914 | 2893 | *addr &= ~mask; |
| 2915 | 2894 | } |
| 2916 | 2895 | |
| @@ -2920,7 +2899,7 @@ static inline int f2fs_test_and_set_bit(unsigned int nr, char *addr) · 3 unmodified lines | ||
| 2920 | 2899 | int ret; |
| 2921 | 2900 | |
| 2922 | 2901 | addr += (nr >> 3); |
| 2923 | − mask = 1 << (7 - (nr & 0x07)); | |
| 2902 | + mask = BIT(7 - (nr & 0x07)); | |
| 2924 | 2903 | ret = mask & *addr; |
| 2925 | 2904 | *addr |= mask; |
| 2926 | 2905 | return ret; |
| @@ -2932,7 +2911,7 @@ static inline int f2fs_test_and_clear_bit(unsigned int nr, char *addr) · 5 unmodified lines | ||
| 2932 | 2911 | int ret; |
| 2933 | 2912 | |
| 2934 | 2913 | addr += (nr >> 3); |
| 2935 | − mask = 1 << (7 - (nr & 0x07)); | |
| 2914 | + mask = BIT(7 - (nr & 0x07)); | |
| 2936 | 2915 | ret = mask & *addr; |
| 2937 | 2916 | *addr &= ~mask; |
| 2938 | 2917 | return ret; |
| @@ -2943,7 +2922,7 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr) · 4 unmodified lines | ||
| 2943 | 2922 | int mask; |
| 2944 | 2923 | |
| 2945 | 2924 | addr += (nr >> 3); |
| 2946 | − mask = 1 << (7 - (nr & 0x07)); | |
| 2925 | + mask = BIT(7 - (nr & 0x07)); | |
| 2947 | 2926 | *addr ^= mask; |
| 2948 | 2927 | } |
| 2949 | 2928 | |
| @@ -3307,9 +3286,6 @@ static inline bool f2fs_is_time_consistent(struct inode *inode) · 357 unmodified lines | ||
| 3307 | 3286 | return false; |
| 3308 | 3287 | if (!timespec64_equal(F2FS_I(inode)->i_disk_time + 2, &inode->i_mtime)) |
| 3309 | 3288 | return false; |
| 3310 | − if (!timespec64_equal(F2FS_I(inode)->i_disk_time + 3, | |
| 3311 | − &F2FS_I(inode)->i_crtime)) | |
| 3312 | − return false; | |
| 3313 | 3289 | return true; |
| 3314 | 3290 | } |
| 3315 | 3291 | |
| @@ -3370,6 +3346,19 @@ static inline void *f2fs_kmalloc(struct f2fs_sb_info *sbi, · 54 unmodified lines | ||
| 3370 | 3346 | return kmalloc(size, flags); |
| 3371 | 3347 | } |
| 3372 | 3348 | |
| 3349 | +static inline void *f2fs_getname(struct f2fs_sb_info *sbi) | |
| 3350 | +{ | |
| 3351 | + if (time_to_inject(sbi, FAULT_KMALLOC)) | |
| 3352 | + return NULL; | |
| 3353 | + | |
| 3354 | + return __getname(); | |
| 3355 | +} | |
| 3356 | + | |
| 3357 | +static inline void f2fs_putname(char *buf) | |
| 3358 | +{ | |
| 3359 | + __putname(buf); | |
| 3360 | +} | |
| 3361 | + | |
| 3373 | 3362 | static inline void *f2fs_kzalloc(struct f2fs_sb_info *sbi, |
| 3374 | 3363 | size_t size, gfp_t flags) |
| 3375 | 3364 | { |
| @@ -3489,7 +3478,6 @@ int f2fs_get_tmpfile(struct mnt_idmap *idmap, struct inode *dir, · 113 unmodified lines | ||
| 3489 | 3478 | /* |
| 3490 | 3479 | * dir.c |
| 3491 | 3480 | */ |
| 3492 | −unsigned char f2fs_get_de_type(struct f2fs_dir_entry *de); | |
| 3493 | 3481 | int f2fs_init_casefolded_name(const struct inode *dir, |
| 3494 | 3482 | struct f2fs_filename *fname); |
| 3495 | 3483 | int f2fs_setup_filename(struct inode *dir, const struct qstr *iname, |
| @@ -3554,6 +3542,7 @@ int f2fs_quota_sync(struct super_block *sb, int type); · 58 unmodified lines | ||
| 3554 | 3542 | loff_t max_file_blocks(struct inode *inode); |
| 3555 | 3543 | void f2fs_quota_off_umount(struct super_block *sb); |
| 3556 | 3544 | void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason); |
| 3545 | +void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag); | |
| 3557 | 3546 | void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error); |
| 3558 | 3547 | int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover); |
| 3559 | 3548 | int f2fs_sync_fs(struct super_block *sb, int sync); |
| @@ -3737,7 +3726,6 @@ void f2fs_set_dirty_device(struct f2fs_sb_info *sbi, nid_t ino, · 177 unmodified lines | ||
| 3737 | 3726 | unsigned int devidx, int type); |
| 3738 | 3727 | bool f2fs_is_dirty_device(struct f2fs_sb_info *sbi, nid_t ino, |
| 3739 | 3728 | unsigned int devidx, int type); |
| 3740 | −int f2fs_sync_inode_meta(struct f2fs_sb_info *sbi); | |
| 3741 | 3729 | int f2fs_acquire_orphan_inode(struct f2fs_sb_info *sbi); |
| 3742 | 3730 | void f2fs_release_orphan_inode(struct f2fs_sb_info *sbi); |
| 3743 | 3731 | void f2fs_add_orphan_inode(struct inode *inode); |
| @@ -3830,6 +3818,10 @@ void f2fs_build_gc_manager(struct f2fs_sb_info *sbi); · 86 unmodified lines | ||
| 3830 | 3818 | int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count); |
| 3831 | 3819 | int __init f2fs_create_garbage_collection_cache(void); |
| 3832 | 3820 | void f2fs_destroy_garbage_collection_cache(void); |
| 3821 | +/* victim selection function for cleaning and SSR */ | |
| 3822 | +int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result, | |
| 3823 | + int gc_type, int type, char alloc_mode, | |
| 3824 | + unsigned long long age); | |
| 3833 | 3825 | |
| 3834 | 3826 | /* |
| 3835 | 3827 | * recovery.c |
| @@ -4138,23 +4130,6 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); · 302 unmodified lines | ||
| 4138 | 4130 | * extent_cache.c |
| 4139 | 4131 | */ |
| 4140 | 4132 | bool sanity_check_extent_cache(struct inode *inode); |
| 4141 | −struct rb_entry *f2fs_lookup_rb_tree(struct rb_root_cached *root, | |
| 4142 | − struct rb_entry *cached_re, unsigned int ofs); | |
| 4143 | −struct rb_node **f2fs_lookup_rb_tree_ext(struct f2fs_sb_info *sbi, | |
| 4144 | − struct rb_root_cached *root, | |
| 4145 | − struct rb_node **parent, | |
| 4146 | − unsigned long long key, bool *left_most); | |
| 4147 | −struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi, | |
| 4148 | − struct rb_root_cached *root, | |
| 4149 | − struct rb_node **parent, | |
| 4150 | − unsigned int ofs, bool *leftmost); | |
| 4151 | −struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root, | |
| 4152 | − struct rb_entry *cached_re, unsigned int ofs, | |
| 4153 | − struct rb_entry **prev_entry, struct rb_entry **next_entry, | |
| 4154 | − struct rb_node ***insert_p, struct rb_node **insert_parent, | |
| 4155 | − bool force, bool *leftmost); | |
| 4156 | −bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi, | |
| 4157 | − struct rb_root_cached *root, bool check_key); | |
| 4158 | 4133 | void f2fs_init_extent_tree(struct inode *inode); |
| 4159 | 4134 | void f2fs_drop_extent_tree(struct inode *inode); |
| 4160 | 4135 | void f2fs_destroy_extent_node(struct inode *inode); |
| @@ -4354,9 +4329,9 @@ static inline int set_compress_context(struct inode *inode) · 193 unmodified lines | ||
| 4354 | 4329 | F2FS_OPTION(sbi).compress_log_size; |
| 4355 | 4330 | F2FS_I(inode)->i_compress_flag = |
| 4356 | 4331 | F2FS_OPTION(sbi).compress_chksum ? |
| 4357 | − 1 << COMPRESS_CHKSUM : 0; | |
| 4332 | + BIT(COMPRESS_CHKSUM) : 0; | |
| 4358 | 4333 | F2FS_I(inode)->i_cluster_size = |
| 4359 | − 1 << F2FS_I(inode)->i_log_cluster_size; | |
| 4334 | + BIT(F2FS_I(inode)->i_log_cluster_size); | |
| 4360 | 4335 | if ((F2FS_I(inode)->i_compress_algorithm == COMPRESS_LZ4 || |
| 4361 | 4336 | F2FS_I(inode)->i_compress_algorithm == COMPRESS_ZSTD) && |
| 4362 | 4337 | F2FS_OPTION(sbi).compress_level) |
| @@ -4414,7 +4389,7 @@ F2FS_FEATURE_FUNCS(readonly, RO); · 51 unmodified lines | ||
| 4414 | 4389 | static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi, |
| 4415 | 4390 | block_t blkaddr) |
| 4416 | 4391 | { |
| 4417 | − unsigned int zno = blkaddr >> sbi->log_blocks_per_blkz; | |
| 4392 | + unsigned int zno = blkaddr / sbi->blocks_per_blkz; | |
| 4418 | 4393 | |
| 4419 | 4394 | return test_bit(zno, FDEV(devi).blkz_seq); |
| 4420 | 4395 | } |
| @@ -4462,6 +4437,11 @@ static inline bool f2fs_hw_is_readonly(struct f2fs_sb_info *sbi) · 41 unmodified lines | ||
| 4462 | 4437 | return false; |
| 4463 | 4438 | } |
| 4464 | 4439 | |
| 4440 | +static inline bool f2fs_dev_is_readonly(struct f2fs_sb_info *sbi) | |
| 4441 | +{ | |
| 4442 | + return f2fs_sb_has_readonly(sbi) || f2fs_hw_is_readonly(sbi); | |
| 4443 | +} | |
| 4444 | + | |
| 4465 | 4445 | static inline bool f2fs_lfs_mode(struct f2fs_sb_info *sbi) |
| 4466 | 4446 | { |
| 4467 | 4447 | return F2FS_OPTION(sbi).fs_mode == FS_MODE_LFS; |
| @@ -2113,7 +2113,11 @@ static int f2fs_ioc_start_atomic_write(struct file *filp, bool truncate) · 2112 unmodified lines | ||
| 2113 | 2113 | clear_inode_flag(fi->cow_inode, FI_INLINE_DATA); |
| 2114 | 2114 | } else { |
| 2115 | 2115 | /* Reuse the already created COW inode */ |
| 2116 | − f2fs_do_truncate_blocks(fi->cow_inode, 0, true); | |
| 2116 | + ret = f2fs_do_truncate_blocks(fi->cow_inode, 0, true); | |
| 2117 | + if (ret) { | |
| 2118 | + f2fs_up_write(&fi->i_gc_rwsem[WRITE]); | |
| 2119 | + goto out; | |
| 2120 | + } | |
| 2117 | 2121 | } |
| 2118 | 2122 | |
| 2119 | 2123 | f2fs_write_inode(inode, NULL); |
| @@ -3009,15 +3013,16 @@ int f2fs_transfer_project_quota(struct inode *inode, kprojid_t kprojid) · 889 unmodified lines | ||
| 3009 | 3013 | struct dquot *transfer_to[MAXQUOTAS] = {}; |
| 3010 | 3014 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
| 3011 | 3015 | struct super_block *sb = sbi->sb; |
| 3012 | − int err = 0; | |
| 3016 | + int err; | |
| 3013 | 3017 | |
| 3014 | 3018 | transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid)); |
| 3015 | − if (!IS_ERR(transfer_to[PRJQUOTA])) { | |
| 3016 | − err = __dquot_transfer(inode, transfer_to); | |
| 3017 | − if (err) | |
| 3018 | − set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); | |
| 3019 | − dqput(transfer_to[PRJQUOTA]); | |
| 3020 | − } | |
| 3019 | + if (IS_ERR(transfer_to[PRJQUOTA])) | |
| 3020 | + return PTR_ERR(transfer_to[PRJQUOTA]); | |
| 3021 | + | |
| 3022 | + err = __dquot_transfer(inode, transfer_to); | |
| 3023 | + if (err) | |
| 3024 | + set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); | |
| 3025 | + dqput(transfer_to[PRJQUOTA]); | |
| 3021 | 3026 | return err; |
| 3022 | 3027 | } |
| 3023 | 3028 | |
| @@ -3964,7 +3969,7 @@ static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg) · 940 unmodified lines | ||
| 3964 | 3969 | |
| 3965 | 3970 | F2FS_I(inode)->i_compress_algorithm = option.algorithm; |
| 3966 | 3971 | F2FS_I(inode)->i_log_cluster_size = option.log_cluster_size; |
| 3967 | − F2FS_I(inode)->i_cluster_size = 1 << option.log_cluster_size; | |
| 3972 | + F2FS_I(inode)->i_cluster_size = BIT(option.log_cluster_size); | |
| 3968 | 3973 | f2fs_mark_inode_dirty_sync(inode, true); |
| 3969 | 3974 | |
| 3970 | 3975 | if (!f2fs_is_compress_backend_ready(inode)) |
| @@ -4062,8 +4067,11 @@ static int f2fs_ioc_decompress_file(struct file *filp) · 91 unmodified lines | ||
| 4062 | 4067 | if (ret < 0) |
| 4063 | 4068 | break; |
| 4064 | 4069 | |
| 4065 | − if (get_dirty_pages(inode) >= blk_per_seg) | |
| 4066 | − filemap_fdatawrite(inode->i_mapping); | |
| 4070 | + if (get_dirty_pages(inode) >= blk_per_seg) { | |
| 4071 | + ret = filemap_fdatawrite(inode->i_mapping); | |
| 4072 | + if (ret < 0) | |
| 4073 | + break; | |
| 4074 | + } | |
| 4067 | 4075 | |
| 4068 | 4076 | count -= len; |
| 4069 | 4077 | page_idx += len; |
| @@ -4133,8 +4141,11 @@ static int f2fs_ioc_compress_file(struct file *filp) · 63 unmodified lines | ||
| 4133 | 4141 | if (ret < 0) |
| 4134 | 4142 | break; |
| 4135 | 4143 | |
| 4136 | − if (get_dirty_pages(inode) >= blk_per_seg) | |
| 4137 | − filemap_fdatawrite(inode->i_mapping); | |
| 4144 | + if (get_dirty_pages(inode) >= blk_per_seg) { | |
| 4145 | + ret = filemap_fdatawrite(inode->i_mapping); | |
| 4146 | + if (ret < 0) | |
| 4147 | + break; | |
| 4148 | + } | |
| 4138 | 4149 | |
| 4139 | 4150 | count -= len; |
| 4140 | 4151 | page_idx += len; |
| @@ -4361,7 +4372,7 @@ static void f2fs_trace_rw_file_path(struct kiocb *iocb, size_t count, int rw) · 220 unmodified lines | ||
| 4361 | 4372 | struct inode *inode = file_inode(iocb->ki_filp); |
| 4362 | 4373 | char *buf, *path; |
| 4363 | 4374 | |
| 4364 | − buf = f2fs_kmalloc(F2FS_I_SB(inode), PATH_MAX, GFP_KERNEL); | |
| 4375 | + buf = f2fs_getname(F2FS_I_SB(inode)); | |
| 4365 | 4376 | if (!buf) |
| 4366 | 4377 | return; |
| 4367 | 4378 | path = dentry_path_raw(file_dentry(iocb->ki_filp), buf, PATH_MAX); |
| @@ -4374,7 +4385,7 @@ static void f2fs_trace_rw_file_path(struct kiocb *iocb, size_t count, int rw) · 6 unmodified lines | ||
| 4374 | 4385 | trace_f2fs_dataread_start(inode, iocb->ki_pos, count, |
| 4375 | 4386 | current->pid, path, current->comm); |
| 4376 | 4387 | free_buf: |
| 4377 | − kfree(buf); | |
| 4388 | + f2fs_putname(buf); | |
| 4378 | 4389 | } |
| 4379 | 4390 | |
| 4380 | 4391 | static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) |
| @@ -4534,6 +4545,19 @@ static const struct iomap_dio_ops f2fs_iomap_dio_write_ops = { · 153 unmodified lines | ||
| 4534 | 4545 | .end_io = f2fs_dio_write_end_io, |
| 4535 | 4546 | }; |
| 4536 | 4547 | |
| 4548 | +static void f2fs_flush_buffered_write(struct address_space *mapping, | |
| 4549 | + loff_t start_pos, loff_t end_pos) | |
| 4550 | +{ | |
| 4551 | + int ret; | |
| 4552 | + | |
| 4553 | + ret = filemap_write_and_wait_range(mapping, start_pos, end_pos); | |
| 4554 | + if (ret < 0) | |
| 4555 | + return; | |
| 4556 | + invalidate_mapping_pages(mapping, | |
| 4557 | + start_pos >> PAGE_SHIFT, | |
| 4558 | + end_pos >> PAGE_SHIFT); | |
| 4559 | +} | |
| 4560 | + | |
| 4537 | 4561 | static ssize_t f2fs_dio_write_iter(struct kiocb *iocb, struct iov_iter *from, |
| 4538 | 4562 | bool *may_need_sync) |
| 4539 | 4563 | { |
| @@ -4633,14 +4657,9 @@ static ssize_t f2fs_dio_write_iter(struct kiocb *iocb, struct iov_iter *from, · 93 unmodified lines | ||
| 4633 | 4657 | |
| 4634 | 4658 | ret += ret2; |
| 4635 | 4659 | |
| 4636 | − ret2 = filemap_write_and_wait_range(file->f_mapping, | |
| 4637 | − bufio_start_pos, | |
| 4638 | − bufio_end_pos); | |
| 4639 | − if (ret2 < 0) | |
| 4640 | − goto out; | |
| 4641 | − invalidate_mapping_pages(file->f_mapping, | |
| 4642 | − bufio_start_pos >> PAGE_SHIFT, | |
| 4643 | − bufio_end_pos >> PAGE_SHIFT); | |
| 4660 | + f2fs_flush_buffered_write(file->f_mapping, | |
| 4661 | + bufio_start_pos, | |
| 4662 | + bufio_end_pos); | |
| 4644 | 4663 | } |
| 4645 | 4664 | } else { |
| 4646 | 4665 | /* iomap_dio_rw() already handled the generic_write_sync(). */ |
| @@ -4723,8 +4742,18 @@ out_unlock: · 76 unmodified lines | ||
| 4723 | 4742 | inode_unlock(inode); |
| 4724 | 4743 | out: |
| 4725 | 4744 | trace_f2fs_file_write_iter(inode, orig_pos, orig_count, ret); |
| 4745 | + | |
| 4726 | 4746 | if (ret > 0 && may_need_sync) |
| 4727 | 4747 | ret = generic_write_sync(iocb, ret); |
| 4748 | + | |
| 4749 | + /* If buffered IO was forced, flush and drop the data from | |
| 4750 | + * the page cache to preserve O_DIRECT semantics | |
| 4751 | + */ | |
| 4752 | + if (ret > 0 && !dio && (iocb->ki_flags & IOCB_DIRECT)) | |
| 4753 | + f2fs_flush_buffered_write(iocb->ki_filp->f_mapping, | |
| 4754 | + orig_pos, | |
| 4755 | + orig_pos + ret - 1); | |
| 4756 | + | |
| 4728 | 4757 | return ret; |
| 4729 | 4758 | } |
| 4730 | 4759 | |
| @@ -4879,6 +4908,7 @@ const struct file_operations f2fs_file_operations = { · 148 unmodified lines | ||
| 4879 | 4908 | .llseek = f2fs_llseek, |
| 4880 | 4909 | .read_iter = f2fs_file_read_iter, |
| 4881 | 4910 | .write_iter = f2fs_file_write_iter, |
| 4911 | + .iopoll = iocb_bio_iopoll, | |
| 4882 | 4912 | .open = f2fs_file_open, |
| 4883 | 4913 | .release = f2fs_release_file, |
| 4884 | 4914 | .mmap = f2fs_file_mmap, |
| @@ -390,40 +390,95 @@ static unsigned int count_bits(const unsigned long *addr, · 389 unmodified lines | ||
| 390 | 390 | return sum; |
| 391 | 391 | } |
| 392 | 392 | |
| 393 | −static struct victim_entry *attach_victim_entry(struct f2fs_sb_info *sbi, | |
| 394 | − unsigned long long mtime, unsigned int segno, | |
| 395 | − struct rb_node *parent, struct rb_node **p, | |
| 396 | − bool left_most) | |
| 393 | +static bool f2fs_check_victim_tree(struct f2fs_sb_info *sbi, | |
| 394 | + struct rb_root_cached *root) | |
| 395 | +{ | |
| 396 | +#ifdef CONFIG_F2FS_CHECK_FS | |
| 397 | + struct rb_node *cur = rb_first_cached(root), *next; | |
| 398 | + struct victim_entry *cur_ve, *next_ve; | |
| 399 | + | |
| 400 | + while (cur) { | |
| 401 | + next = rb_next(cur); | |
| 402 | + if (!next) | |
| 403 | + return true; | |
| 404 | + | |
| 405 | + cur_ve = rb_entry(cur, struct victim_entry, rb_node); | |
| 406 | + next_ve = rb_entry(next, struct victim_entry, rb_node); | |
| 407 | + | |
| 408 | + if (cur_ve->mtime > next_ve->mtime) { | |
| 409 | + f2fs_info(sbi, "broken victim_rbtree, " | |
| 410 | + "cur_mtime(%llu) next_mtime(%llu)", | |
| 411 | + cur_ve->mtime, next_ve->mtime); | |
| 412 | + return false; | |
| 413 | + } | |
| 414 | + cur = next; | |
| 415 | + } | |
| 416 | +#endif | |
| 417 | + return true; | |
| 418 | +} | |
| 419 | + | |
| 420 | +static struct victim_entry *__lookup_victim_entry(struct f2fs_sb_info *sbi, | |
| 421 | + unsigned long long mtime) | |
| 422 | +{ | |
| 423 | + struct atgc_management *am = &sbi->am; | |
| 424 | + struct rb_node *node = am->root.rb_root.rb_node; | |
| 425 | + struct victim_entry *ve = NULL; | |
| 426 | + | |
| 427 | + while (node) { | |
| 428 | + ve = rb_entry(node, struct victim_entry, rb_node); | |
| 429 | + | |
| 430 | + if (mtime < ve->mtime) | |
| 431 | + node = node->rb_left; | |
| 432 | + else | |
| 433 | + node = node->rb_right; | |
| 434 | + } | |
| 435 | + return ve; | |
| 436 | +} | |
| 437 | + | |
| 438 | +static struct victim_entry *__create_victim_entry(struct f2fs_sb_info *sbi, | |
| 439 | + unsigned long long mtime, unsigned int segno) | |
| 397 | 440 | { |
| 398 | 441 | struct atgc_management *am = &sbi->am; |
| 399 | 442 | struct victim_entry *ve; |
| 400 | 443 | |
| 401 | − ve = f2fs_kmem_cache_alloc(victim_entry_slab, | |
| 402 | − GFP_NOFS, true, NULL); | |
| 444 | + ve = f2fs_kmem_cache_alloc(victim_entry_slab, GFP_NOFS, true, NULL); | |
| 403 | 445 | |
| 404 | 446 | ve->mtime = mtime; |
| 405 | 447 | ve->segno = segno; |
| 406 | 448 | |
| 407 | − rb_link_node(&ve->rb_node, parent, p); | |
| 408 | − rb_insert_color_cached(&ve->rb_node, &am->root, left_most); | |
| 409 | − | |
| 410 | 449 | list_add_tail(&ve->list, &am->victim_list); |
| 411 | − | |
| 412 | 450 | am->victim_count++; |
| 413 | 451 | |
| 414 | 452 | return ve; |
| 415 | 453 | } |
| 416 | 454 | |
| 417 | −static void insert_victim_entry(struct f2fs_sb_info *sbi, | |
| 455 | +static void __insert_victim_entry(struct f2fs_sb_info *sbi, | |
| 418 | 456 | unsigned long long mtime, unsigned int segno) |
| 419 | 457 | { |
| 420 | 458 | struct atgc_management *am = &sbi->am; |
| 421 | − struct rb_node **p; | |
| 459 | + struct rb_root_cached *root = &am->root; | |
| 460 | + struct rb_node **p = &root->rb_root.rb_node; | |
| 422 | 461 | struct rb_node *parent = NULL; |
| 462 | + struct victim_entry *ve; | |
| 423 | 463 | bool left_most = true; |
| 424 | 464 | |
| 425 | − p = f2fs_lookup_rb_tree_ext(sbi, &am->root, &parent, mtime, &left_most); | |
| 426 | − attach_victim_entry(sbi, mtime, segno, parent, p, left_most); | |
| 465 | + /* look up rb tree to find parent node */ | |
| 466 | + while (*p) { | |
| 467 | + parent = *p; | |
| 468 | + ve = rb_entry(parent, struct victim_entry, rb_node); | |
| 469 | + | |
| 470 | + if (mtime < ve->mtime) { | |
| 471 | + p = &(*p)->rb_left; | |
| 472 | + } else { | |
| 473 | + p = &(*p)->rb_right; | |
| 474 | + left_most = false; | |
| 475 | + } | |
| 476 | + } | |
| 477 | + | |
| 478 | + ve = __create_victim_entry(sbi, mtime, segno); | |
| 479 | + | |
| 480 | + rb_link_node(&ve->rb_node, parent, p); | |
| 481 | + rb_insert_color_cached(&ve->rb_node, root, left_most); | |
| 427 | 482 | } |
| 428 | 483 | |
| 429 | 484 | static void add_victim_entry(struct f2fs_sb_info *sbi, |
| @@ -459,19 +514,7 @@ static void add_victim_entry(struct f2fs_sb_info *sbi, · 29 unmodified lines | ||
| 459 | 514 | if (sit_i->dirty_max_mtime - mtime < p->age_threshold) |
| 460 | 515 | return; |
| 461 | 516 | |
| 462 | − insert_victim_entry(sbi, mtime, segno); | |
| 463 | −} | |
| 464 | − | |
| 465 | −static struct rb_node *lookup_central_victim(struct f2fs_sb_info *sbi, | |
| 466 | − struct victim_sel_policy *p) | |
| 467 | −{ | |
| 468 | − struct atgc_management *am = &sbi->am; | |
| 469 | − struct rb_node *parent = NULL; | |
| 470 | − bool left_most; | |
| 471 | − | |
| 472 | − f2fs_lookup_rb_tree_ext(sbi, &am->root, &parent, p->age, &left_most); | |
| 473 | − | |
| 474 | − return parent; | |
| 517 | + __insert_victim_entry(sbi, mtime, segno); | |
| 475 | 518 | } |
| 476 | 519 | |
| 477 | 520 | static void atgc_lookup_victim(struct f2fs_sb_info *sbi, |
| @@ -481,7 +524,6 @@ static void atgc_lookup_victim(struct f2fs_sb_info *sbi, · 3 unmodified lines | ||
| 481 | 524 | struct atgc_management *am = &sbi->am; |
| 482 | 525 | struct rb_root_cached *root = &am->root; |
| 483 | 526 | struct rb_node *node; |
| 484 | − struct rb_entry *re; | |
| 485 | 527 | struct victim_entry *ve; |
| 486 | 528 | unsigned long long total_time; |
| 487 | 529 | unsigned long long age, u, accu; |
| @@ -508,12 +550,10 @@ static void atgc_lookup_victim(struct f2fs_sb_info *sbi, · 20 unmodified lines | ||
| 508 | 550 | |
| 509 | 551 | node = rb_first_cached(root); |
| 510 | 552 | next: |
| 511 | − re = rb_entry_safe(node, struct rb_entry, rb_node); | |
| 512 | − if (!re) | |
| 553 | + ve = rb_entry_safe(node, struct victim_entry, rb_node); | |
| 554 | + if (!ve) | |
| 513 | 555 | return; |
| 514 | 556 | |
| 515 | − ve = (struct victim_entry *)re; | |
| 516 | − | |
| 517 | 557 | if (ve->mtime >= max_mtime || ve->mtime < min_mtime) |
| 518 | 558 | goto skip; |
| 519 | 559 | |
| @@ -555,8 +595,6 @@ static void atssr_lookup_victim(struct f2fs_sb_info *sbi, · 35 unmodified lines | ||
| 555 | 595 | { |
| 556 | 596 | struct sit_info *sit_i = SIT_I(sbi); |
| 557 | 597 | struct atgc_management *am = &sbi->am; |
| 558 | − struct rb_node *node; | |
| 559 | − struct rb_entry *re; | |
| 560 | 598 | struct victim_entry *ve; |
| 561 | 599 | unsigned long long age; |
| 562 | 600 | unsigned long long max_mtime = sit_i->dirty_max_mtime; |
| @@ -566,25 +604,22 @@ static void atssr_lookup_victim(struct f2fs_sb_info *sbi, · 3 unmodified lines | ||
| 566 | 604 | unsigned int dirty_threshold = max(am->max_candidate_count, |
| 567 | 605 | am->candidate_ratio * |
| 568 | 606 | am->victim_count / 100); |
| 569 | − unsigned int cost; | |
| 570 | − unsigned int iter = 0; | |
| 607 | + unsigned int cost, iter; | |
| 571 | 608 | int stage = 0; |
| 572 | 609 | |
| 573 | 610 | if (max_mtime < min_mtime) |
| 574 | 611 | return; |
| 575 | 612 | max_mtime += 1; |
| 576 | 613 | next_stage: |
| 577 | − node = lookup_central_victim(sbi, p); | |
| 614 | + iter = 0; | |
| 615 | + ve = __lookup_victim_entry(sbi, p->age); | |
| 578 | 616 | next_node: |
| 579 | − re = rb_entry_safe(node, struct rb_entry, rb_node); | |
| 580 | − if (!re) { | |
| 581 | − if (stage == 0) | |
| 582 | − goto skip_stage; | |
| 617 | + if (!ve) { | |
| 618 | + if (stage++ == 0) | |
| 619 | + goto next_stage; | |
| 583 | 620 | return; |
| 584 | 621 | } |
| 585 | 622 | |
| 586 | − ve = (struct victim_entry *)re; | |
| 587 | − | |
| 588 | 623 | if (ve->mtime >= max_mtime || ve->mtime < min_mtime) |
| 589 | 624 | goto skip_node; |
| 590 | 625 | |
| @@ -610,24 +645,20 @@ next_node: · 19 unmodified lines | ||
| 610 | 645 | } |
| 611 | 646 | skip_node: |
| 612 | 647 | if (iter < dirty_threshold) { |
| 613 | − if (stage == 0) | |
| 614 | − node = rb_prev(node); | |
| 615 | − else if (stage == 1) | |
| 616 | − node = rb_next(node); | |
| 648 | + ve = rb_entry(stage == 0 ? rb_prev(&ve->rb_node) : | |
| 649 | + rb_next(&ve->rb_node), | |
| 650 | + struct victim_entry, rb_node); | |
| 617 | 651 | goto next_node; |
| 618 | 652 | } |
| 619 | −skip_stage: | |
| 620 | − if (stage < 1) { | |
| 621 | − stage++; | |
| 622 | − iter = 0; | |
| 653 | + | |
| 654 | + if (stage++ == 0) | |
| 623 | 655 | goto next_stage; |
| 624 | − } | |
| 625 | 656 | } |
| 657 | + | |
| 626 | 658 | static void lookup_victim_by_age(struct f2fs_sb_info *sbi, |
| 627 | 659 | struct victim_sel_policy *p) |
| 628 | 660 | { |
| 629 | − f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi, | |
| 630 | − &sbi->am.root, true)); | |
| 661 | + f2fs_bug_on(sbi, !f2fs_check_victim_tree(sbi, &sbi->am.root)); | |
| 631 | 662 | |
| 632 | 663 | if (p->gc_mode == GC_AT) |
| 633 | 664 | atgc_lookup_victim(sbi, p); |
| @@ -710,9 +741,9 @@ static int f2fs_gc_pinned_control(struct inode *inode, int gc_type, · 76 unmodified lines | ||
| 710 | 741 | * When it is called from SSR segment selection, it finds a segment |
| 711 | 742 | * which has minimum valid blocks and removes it from dirty seglist. |
| 712 | 743 | */ |
| 713 | −static int get_victim_by_default(struct f2fs_sb_info *sbi, | |
| 714 | − unsigned int *result, int gc_type, int type, | |
| 715 | − char alloc_mode, unsigned long long age) | |
| 744 | +int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result, | |
| 745 | + int gc_type, int type, char alloc_mode, | |
| 746 | + unsigned long long age) | |
| 716 | 747 | { |
| 717 | 748 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
| 718 | 749 | struct sit_info *sm = SIT_I(sbi); |
| @@ -906,10 +937,6 @@ out: · 187 unmodified lines | ||
| 906 | 937 | return ret; |
| 907 | 938 | } |
| 908 | 939 | |
| 909 | −static const struct victim_selection default_v_ops = { | |
| 910 | − .get_victim = get_victim_by_default, | |
| 911 | −}; | |
| 912 | − | |
| 913 | 940 | static struct inode *find_gc_inode(struct gc_inode_list *gc_list, nid_t ino) |
| 914 | 941 | { |
| 915 | 942 | struct inode_entry *ie; |
| @@ -1589,14 +1616,14 @@ next_step: · 673 unmodified lines | ||
| 1589 | 1616 | int err; |
| 1590 | 1617 | |
| 1591 | 1618 | if (S_ISREG(inode->i_mode)) { |
| 1592 | − if (!f2fs_down_write_trylock(&fi->i_gc_rwsem[READ])) { | |
| 1619 | + if (!f2fs_down_write_trylock(&fi->i_gc_rwsem[WRITE])) { | |
| 1593 | 1620 | sbi->skipped_gc_rwsem++; |
| 1594 | 1621 | continue; |
| 1595 | 1622 | } |
| 1596 | 1623 | if (!f2fs_down_write_trylock( |
| 1597 | − &fi->i_gc_rwsem[WRITE])) { | |
| 1624 | + &fi->i_gc_rwsem[READ])) { | |
| 1598 | 1625 | sbi->skipped_gc_rwsem++; |
| 1599 | − f2fs_up_write(&fi->i_gc_rwsem[READ]); | |
| 1626 | + f2fs_up_write(&fi->i_gc_rwsem[WRITE]); | |
| 1600 | 1627 | continue; |
| 1601 | 1628 | } |
| 1602 | 1629 | locked = true; |
| @@ -1619,8 +1646,8 @@ next_step: · 16 unmodified lines | ||
| 1619 | 1646 | submitted++; |
| 1620 | 1647 | |
| 1621 | 1648 | if (locked) { |
| 1622 | − f2fs_up_write(&fi->i_gc_rwsem[WRITE]); | |
| 1623 | 1649 | f2fs_up_write(&fi->i_gc_rwsem[READ]); |
| 1650 | + f2fs_up_write(&fi->i_gc_rwsem[WRITE]); | |
| 1624 | 1651 | } |
| 1625 | 1652 | |
| 1626 | 1653 | stat_inc_data_blk_count(sbi, 1, gc_type); |
| @@ -1640,8 +1667,7 @@ static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim, · 13 unmodified lines | ||
| 1640 | 1667 | int ret; |
| 1641 | 1668 | |
| 1642 | 1669 | down_write(&sit_i->sentry_lock); |
| 1643 | − ret = DIRTY_I(sbi)->v_ops->get_victim(sbi, victim, gc_type, | |
| 1644 | − NO_CHECK_TYPE, LFS, 0); | |
| 1670 | + ret = f2fs_get_victim(sbi, victim, gc_type, NO_CHECK_TYPE, LFS, 0); | |
| 1645 | 1671 | up_write(&sit_i->sentry_lock); |
| 1646 | 1672 | return ret; |
| 1647 | 1673 | } |
| @@ -1779,6 +1805,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, struct f2fs_gc_control *gc_control) · 131 unmodified lines | ||
| 1779 | 1805 | .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS), |
| 1780 | 1806 | }; |
| 1781 | 1807 | unsigned int skipped_round = 0, round = 0; |
| 1808 | + unsigned int upper_secs; | |
| 1782 | 1809 | |
| 1783 | 1810 | trace_f2fs_gc_begin(sbi->sb, gc_type, gc_control->no_bg_gc, |
| 1784 | 1811 | gc_control->nr_free_secs, |
| @@ -1791,8 +1818,8 @@ int f2fs_gc(struct f2fs_sb_info *sbi, struct f2fs_gc_control *gc_control) · 6 unmodified lines | ||
| 1791 | 1818 | prefree_segments(sbi)); |
| 1792 | 1819 | |
| 1793 | 1820 | cpc.reason = __get_cp_reason(sbi); |
| 1794 | − sbi->skipped_gc_rwsem = 0; | |
| 1795 | 1821 | gc_more: |
| 1822 | + sbi->skipped_gc_rwsem = 0; | |
| 1796 | 1823 | if (unlikely(!(sbi->sb->s_flags & SB_ACTIVE))) { |
| 1797 | 1824 | ret = -EINVAL; |
| 1798 | 1825 | goto stop; |
| @@ -1802,7 +1829,10 @@ gc_more: · 3 unmodified lines | ||
| 1802 | 1829 | goto stop; |
| 1803 | 1830 | } |
| 1804 | 1831 | |
| 1805 | − if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) { | |
| 1832 | + /* Let's run FG_GC, if we don't have enough space. */ | |
| 1833 | + if (has_not_enough_free_secs(sbi, 0, 0)) { | |
| 1834 | + gc_type = FG_GC; | |
| 1835 | + | |
| 1806 | 1836 | /* |
| 1807 | 1837 | * For example, if there are many prefree_segments below given |
| 1808 | 1838 | * threshold, we can make them free by checkpoint. Then, we |
| @@ -1813,8 +1843,6 @@ gc_more: · 4 unmodified lines | ||
| 1813 | 1843 | if (ret) |
| 1814 | 1844 | goto stop; |
| 1815 | 1845 | } |
| 1816 | − if (has_not_enough_free_secs(sbi, 0, 0)) | |
| 1817 | − gc_type = FG_GC; | |
| 1818 | 1846 | } |
| 1819 | 1847 | |
| 1820 | 1848 | /* f2fs_balance_fs doesn't need to do BG_GC in critical path. */ |
| @@ -1841,19 +1869,15 @@ retry: · 20 unmodified lines | ||
| 1841 | 1869 | if (seg_freed == f2fs_usable_segs_in_sec(sbi, segno)) |
| 1842 | 1870 | sec_freed++; |
| 1843 | 1871 | |
| 1844 | − if (gc_type == FG_GC) | |
| 1872 | + if (gc_type == FG_GC) { | |
| 1845 | 1873 | sbi->cur_victim_sec = NULL_SEGNO; |
| 1846 | 1874 | |
| 1847 | − if (gc_control->init_gc_type == FG_GC || | |
| 1848 | − !has_not_enough_free_secs(sbi, | |
| 1849 | − (gc_type == FG_GC) ? sec_freed : 0, 0)) { | |
| 1850 | − if (gc_type == FG_GC && sec_freed < gc_control->nr_free_secs) | |
| 1851 | − goto go_gc_more; | |
| 1852 | − goto stop; | |
| 1853 | − } | |
| 1854 | − | |
| 1855 | − /* FG_GC stops GC by skip_count */ | |
| 1856 | − if (gc_type == FG_GC) { | |
| 1875 | + if (has_enough_free_secs(sbi, sec_freed, 0)) { | |
| 1876 | + if (!gc_control->no_bg_gc && | |
| 1877 | + sec_freed < gc_control->nr_free_secs) | |
| 1878 | + goto go_gc_more; | |
| 1879 | + goto stop; | |
| 1880 | + } | |
| 1857 | 1881 | if (sbi->skipped_gc_rwsem) |
| 1858 | 1882 | skipped_round++; |
| 1859 | 1883 | round++; |
| @@ -1862,10 +1886,17 @@ retry: · 2 unmodified lines | ||
| 1862 | 1886 | ret = f2fs_write_checkpoint(sbi, &cpc); |
| 1863 | 1887 | goto stop; |
| 1864 | 1888 | } |
| 1889 | + } else if (has_enough_free_secs(sbi, 0, 0)) { | |
| 1890 | + goto stop; | |
| 1865 | 1891 | } |
| 1866 | 1892 | |
| 1867 | − /* Write checkpoint to reclaim prefree segments */ | |
| 1868 | − if (free_sections(sbi) < NR_CURSEG_PERSIST_TYPE && | |
| 1893 | + __get_secs_required(sbi, NULL, &upper_secs, NULL); | |
| 1894 | + | |
| 1895 | + /* | |
| 1896 | + * Write checkpoint to reclaim prefree segments. | |
| 1897 | + * We need more three extra sections for writer's data/node/dentry. | |
| 1898 | + */ | |
| 1899 | + if (free_sections(sbi) <= upper_secs + NR_GC_CHECKPOINT_SECS && | |
| 1869 | 1900 | prefree_segments(sbi)) { |
| 1870 | 1901 | ret = f2fs_write_checkpoint(sbi, &cpc); |
| 1871 | 1902 | if (ret) |
| @@ -1932,8 +1963,6 @@ static void init_atgc_management(struct f2fs_sb_info *sbi) · 60 unmodified lines | ||
| 1932 | 1963 | |
| 1933 | 1964 | void f2fs_build_gc_manager(struct f2fs_sb_info *sbi) |
| 1934 | 1965 | { |
| 1935 | − DIRTY_I(sbi)->v_ops = &default_v_ops; | |
| 1936 | − | |
| 1937 | 1966 | sbi->gc_pin_file_threshold = DEF_GC_FAILED_PINNED_FILES; |
| 1938 | 1967 | |
| 1939 | 1968 | /* give warm/cold data area from slower device */ |
| @@ -2064,8 +2093,8 @@ static void update_fs_metadata(struct f2fs_sb_info *sbi, int secs) · 124 unmodified lines | ||
| 2064 | 2093 | FDEV(last_dev).end_blk = |
| 2065 | 2094 | (long long)FDEV(last_dev).end_blk + blks; |
| 2066 | 2095 | #ifdef CONFIG_BLK_DEV_ZONED |
| 2067 | − FDEV(last_dev).nr_blkz = (int)FDEV(last_dev).nr_blkz + | |
| 2068 | − (int)(blks >> sbi->log_blocks_per_blkz); | |
| 2096 | + FDEV(last_dev).nr_blkz = FDEV(last_dev).nr_blkz + | |
| 2097 | + div_u64(blks, sbi->blocks_per_blkz); | |
| 2069 | 2098 | #endif |
| 2070 | 2099 | } |
| 2071 | 2100 | } |
| @@ -30,6 +30,8 @@ · 29 unmodified lines | ||
| 30 | 30 | /* Search max. number of dirty segments to select a victim segment */ |
| 31 | 31 | #define DEF_MAX_VICTIM_SEARCH 4096 /* covers 8GB */ |
| 32 | 32 | |
| 33 | +#define NR_GC_CHECKPOINT_SECS (3) /* data/node/dentry sections */ | |
| 34 | + | |
| 33 | 35 | struct f2fs_gc_kthread { |
| 34 | 36 | struct task_struct *f2fs_gc_task; |
| 35 | 37 | wait_queue_head_t gc_wait_queue_head; |
| @@ -55,20 +57,10 @@ struct gc_inode_list { · 19 unmodified lines | ||
| 55 | 57 | struct radix_tree_root iroot; |
| 56 | 58 | }; |
| 57 | 59 | |
| 58 | −struct victim_info { | |
| 59 | − unsigned long long mtime; /* mtime of section */ | |
| 60 | − unsigned int segno; /* section No. */ | |
| 61 | −}; | |
| 62 | − | |
| 63 | 60 | struct victim_entry { |
| 64 | 61 | struct rb_node rb_node; /* rb node located in rb-tree */ |
| 65 | − union { | |
| 66 | − struct { | |
| 67 | − unsigned long long mtime; /* mtime of section */ | |
| 68 | − unsigned int segno; /* segment No. */ | |
| 69 | − }; | |
| 70 | − struct victim_info vi; /* victim info */ | |
| 71 | − }; | |
| 62 | + unsigned long long mtime; /* mtime of section */ | |
| 63 | + unsigned int segno; /* segment No. */ | |
| 72 | 64 | struct list_head list; |
| 73 | 65 | }; |
| 74 | 66 | |
| @@ -497,7 +497,7 @@ static int f2fs_add_inline_entries(struct inode *dir, void *inline_dentry) · 496 unmodified lines | ||
| 497 | 497 | fname.hash = de->hash_code; |
| 498 | 498 | |
| 499 | 499 | ino = le32_to_cpu(de->ino); |
| 500 | − fake_mode = f2fs_get_de_type(de) << S_SHIFT; | |
| 500 | + fake_mode = fs_ftype_to_dtype(de->file_type) << S_DT_SHIFT; | |
| 501 | 501 | |
| 502 | 502 | err = f2fs_add_regular_entry(dir, &fname, NULL, ino, fake_mode); |
| 503 | 503 | if (err) |
| @@ -326,7 +326,6 @@ static void init_idisk_time(struct inode *inode) · 325 unmodified lines | ||
| 326 | 326 | fi->i_disk_time[0] = inode->i_atime; |
| 327 | 327 | fi->i_disk_time[1] = inode->i_ctime; |
| 328 | 328 | fi->i_disk_time[2] = inode->i_mtime; |
| 329 | − fi->i_disk_time[3] = fi->i_crtime; | |
| 330 | 329 | } |
| 331 | 330 | |
| 332 | 331 | static int do_read_inode(struct inode *inode) |
| @@ -454,8 +453,8 @@ static int do_read_inode(struct inode *inode) · 121 unmodified lines | ||
| 454 | 453 | fi->i_compress_level = compress_flag >> |
| 455 | 454 | COMPRESS_LEVEL_OFFSET; |
| 456 | 455 | fi->i_compress_flag = compress_flag & |
| 457 | − (BIT(COMPRESS_LEVEL_OFFSET) - 1); | |
| 458 | − fi->i_cluster_size = 1 << fi->i_log_cluster_size; | |
| 456 | + GENMASK(COMPRESS_LEVEL_OFFSET - 1, 0); | |
| 457 | + fi->i_cluster_size = BIT(fi->i_log_cluster_size); | |
| 459 | 458 | set_inode_flag(inode, FI_COMPRESSED_FILE); |
| 460 | 459 | } |
| 461 | 460 | } |
| @@ -22,7 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | #include "acl.h" |
| 23 | 23 | #include <trace/events/f2fs.h> |
| 24 | 24 | |
| 25 | −static inline int is_extension_exist(const unsigned char *s, const char *sub, | |
| 25 | +static inline bool is_extension_exist(const unsigned char *s, const char *sub, | |
| 26 | 26 | bool tmp_ext) |
| 27 | 27 | { |
| 28 | 28 | size_t slen = strlen(s); |
| @@ -30,19 +30,19 @@ static inline int is_extension_exist(const unsigned char *s, const char *sub, · 1 unmodified line | ||
| 30 | 30 | int i; |
| 31 | 31 | |
| 32 | 32 | if (sublen == 1 && *sub == '*') |
| 33 | − return 1; | |
| 33 | + return true; | |
| 34 | 34 | |
| 35 | 35 | /* |
| 36 | 36 | * filename format of multimedia file should be defined as: |
| 37 | 37 | * "filename + '.' + extension + (optional: '.' + temp extension)". |
| 38 | 38 | */ |
| 39 | 39 | if (slen < sublen + 2) |
| 40 | − return 0; | |
| 40 | + return false; | |
| 41 | 41 | |
| 42 | 42 | if (!tmp_ext) { |
| 43 | 43 | /* file has no temp extension */ |
| 44 | 44 | if (s[slen - sublen - 1] != '.') |
| 45 | − return 0; | |
| 45 | + return false; | |
| 46 | 46 | return !strncasecmp(s + slen - sublen, sub, sublen); |
| 47 | 47 | } |
| 48 | 48 | |
| @@ -50,10 +50,10 @@ static inline int is_extension_exist(const unsigned char *s, const char *sub, · 1 unmodified line | ||
| 50 | 50 | if (s[i] != '.') |
| 51 | 51 | continue; |
| 52 | 52 | if (!strncasecmp(s + i + 1, sub, sublen)) |
| 53 | − return 1; | |
| 53 | + return true; | |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | − return 0; | |
| 56 | + return false; | |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | 59 | int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name, |
| @@ -995,12 +995,20 @@ static int f2fs_rename(struct mnt_idmap *idmap, struct inode *old_dir, · 935 unmodified lines | ||
| 995 | 995 | goto out; |
| 996 | 996 | } |
| 997 | 997 | |
| 998 | + /* | |
| 999 | + * Copied from ext4_rename: we need to protect against old.inode | |
| 1000 | + * directory getting converted from inline directory format into | |
| 1001 | + * a normal one. | |
| 1002 | + */ | |
| 1003 | + if (S_ISDIR(old_inode->i_mode)) | |
| 1004 | + inode_lock_nested(old_inode, I_MUTEX_NONDIR2); | |
| 1005 | + | |
| 998 | 1006 | err = -ENOENT; |
| 999 | 1007 | old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page); |
| 1000 | 1008 | if (!old_entry) { |
| 1001 | 1009 | if (IS_ERR(old_page)) |
| 1002 | 1010 | err = PTR_ERR(old_page); |
| 1003 | − goto out; | |
| 1011 | + goto out_unlock_old; | |
| 1004 | 1012 | } |
| 1005 | 1013 | |
| 1006 | 1014 | if (S_ISDIR(old_inode->i_mode)) { |
| @@ -1108,6 +1116,9 @@ static int f2fs_rename(struct mnt_idmap *idmap, struct inode *old_dir, · 101 unmodified lines | ||
| 1108 | 1116 | |
| 1109 | 1117 | f2fs_unlock_op(sbi); |
| 1110 | 1118 | |
| 1119 | + if (S_ISDIR(old_inode->i_mode)) | |
| 1120 | + inode_unlock(old_inode); | |
| 1121 | + | |
| 1111 | 1122 | if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) |
| 1112 | 1123 | f2fs_sync_fs(sbi->sb, 1); |
| 1113 | 1124 | |
| @@ -1122,6 +1133,9 @@ out_dir: · 8 unmodified lines | ||
| 1122 | 1133 | f2fs_put_page(old_dir_page, 0); |
| 1123 | 1134 | out_old: |
| 1124 | 1135 | f2fs_put_page(old_page, 0); |
| 1136 | +out_unlock_old: | |
| 1137 | + if (S_ISDIR(old_inode->i_mode)) | |
| 1138 | + inode_unlock(old_inode); | |
| 1125 | 1139 | out: |
| 1126 | 1140 | iput(whiteout); |
| 1127 | 1141 | return err; |
| @@ -93,17 +93,15 @@ static inline void copy_node_info(struct node_info *dst, · 92 unmodified lines | ||
| 93 | 93 | static inline void set_nat_flag(struct nat_entry *ne, |
| 94 | 94 | unsigned int type, bool set) |
| 95 | 95 | { |
| 96 | − unsigned char mask = 0x01 << type; | |
| 97 | 96 | if (set) |
| 98 | − ne->ni.flag |= mask; | |
| 97 | + ne->ni.flag |= BIT(type); | |
| 99 | 98 | else |
| 100 | − ne->ni.flag &= ~mask; | |
| 99 | + ne->ni.flag &= ~BIT(type); | |
| 101 | 100 | } |
| 102 | 101 | |
| 103 | 102 | static inline bool get_nat_flag(struct nat_entry *ne, unsigned int type) |
| 104 | 103 | { |
| 105 | − unsigned char mask = 0x01 << type; | |
| 106 | − return ne->ni.flag & mask; | |
| 104 | + return ne->ni.flag & BIT(type); | |
| 107 | 105 | } |
| 108 | 106 | |
| 109 | 107 | static inline void nat_reset_flag(struct nat_entry *ne) |
| @@ -225,7 +223,7 @@ static inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi, · 115 unmodified lines | ||
| 225 | 223 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
| 226 | 224 | |
| 227 | 225 | block_addr -= nm_i->nat_blkaddr; |
| 228 | − block_addr ^= 1 << sbi->log_blocks_per_seg; | |
| 226 | + block_addr ^= BIT(sbi->log_blocks_per_seg); | |
| 229 | 227 | return block_addr + nm_i->nat_blkaddr; |
| 230 | 228 | } |
| 231 | 229 | |
| @@ -395,7 +393,7 @@ static inline nid_t get_nid(struct page *p, int off, bool i) · 163 unmodified lines | ||
| 395 | 393 | static inline int is_node(struct page *page, int type) |
| 396 | 394 | { |
| 397 | 395 | struct f2fs_node *rn = F2FS_NODE(page); |
| 398 | − return le32_to_cpu(rn->footer.flag) & (1 << type); | |
| 396 | + return le32_to_cpu(rn->footer.flag) & BIT(type); | |
| 399 | 397 | } |
| 400 | 398 | |
| 401 | 399 | #define is_cold_node(page) is_node(page, COLD_BIT_SHIFT) |
| @@ -408,9 +406,9 @@ static inline void set_cold_node(struct page *page, bool is_dir) · 6 unmodified lines | ||
| 408 | 406 | unsigned int flag = le32_to_cpu(rn->footer.flag); |
| 409 | 407 | |
| 410 | 408 | if (is_dir) |
| 411 | − flag &= ~(0x1 << COLD_BIT_SHIFT); | |
| 409 | + flag &= ~BIT(COLD_BIT_SHIFT); | |
| 412 | 410 | else |
| 413 | − flag |= (0x1 << COLD_BIT_SHIFT); | |
| 411 | + flag |= BIT(COLD_BIT_SHIFT); | |
| 414 | 412 | rn->footer.flag = cpu_to_le32(flag); |
| 415 | 413 | } |
| 416 | 414 | |
| @@ -419,9 +417,9 @@ static inline void set_mark(struct page *page, int mark, int type) · 2 unmodified lines | ||
| 419 | 417 | struct f2fs_node *rn = F2FS_NODE(page); |
| 420 | 418 | unsigned int flag = le32_to_cpu(rn->footer.flag); |
| 421 | 419 | if (mark) |
| 422 | − flag |= (0x1 << type); | |
| 420 | + flag |= BIT(type); | |
| 423 | 421 | else |
| 424 | − flag &= ~(0x1 << type); | |
| 422 | + flag &= ~BIT(type); | |
| 425 | 423 | rn->footer.flag = cpu_to_le32(flag); |
| 426 | 424 | |
| 427 | 425 | #ifdef CONFIG_F2FS_CHECK_FS |
| @@ -825,19 +825,9 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) · 824 unmodified lines | ||
| 825 | 825 | unsigned long s_flags = sbi->sb->s_flags; |
| 826 | 826 | bool need_writecp = false; |
| 827 | 827 | bool fix_curseg_write_pointer = false; |
| 828 | −#ifdef CONFIG_QUOTA | |
| 829 | − int quota_enabled; | |
| 830 | −#endif | |
| 831 | 828 | |
| 832 | − if (s_flags & SB_RDONLY) { | |
| 829 | + if (is_sbi_flag_set(sbi, SBI_IS_WRITABLE)) | |
| 833 | 830 | f2fs_info(sbi, "recover fsync data on readonly fs"); |
| 834 | − sbi->sb->s_flags &= ~SB_RDONLY; | |
| 835 | − } | |
| 836 | − | |
| 837 | −#ifdef CONFIG_QUOTA | |
| 838 | − /* Turn on quotas so that they are updated correctly */ | |
| 839 | − quota_enabled = f2fs_enable_quota_files(sbi, s_flags & SB_RDONLY); | |
| 840 | −#endif | |
| 841 | 831 | |
| 842 | 832 | INIT_LIST_HEAD(&inode_list); |
| 843 | 833 | INIT_LIST_HEAD(&tmp_inode_list); |
| @@ -909,11 +899,6 @@ skip: · 65 unmodified lines | ||
| 909 | 899 | } |
| 910 | 900 | } |
| 911 | 901 | |
| 912 | −#ifdef CONFIG_QUOTA | |
| 913 | − /* Turn quotas off */ | |
| 914 | − if (quota_enabled) | |
| 915 | − f2fs_quota_off_umount(sbi->sb); | |
| 916 | −#endif | |
| 917 | 902 | sbi->sb->s_flags = s_flags; /* Restore SB_RDONLY status */ |
| 918 | 903 | |
| 919 | 904 | return ret ? ret : err; |
| @@ -217,7 +217,7 @@ static int __replace_atomic_write_block(struct inode *inode, pgoff_t index, · 216 unmodified lines | ||
| 217 | 217 | |
| 218 | 218 | retry: |
| 219 | 219 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
| 220 | − err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE_RA); | |
| 220 | + err = f2fs_get_dnode_of_data(&dn, index, ALLOC_NODE); | |
| 221 | 221 | if (err) { |
| 222 | 222 | if (err == -ENOMEM) { |
| 223 | 223 | f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); |
| @@ -246,10 +246,16 @@ retry: · 22 unmodified lines | ||
| 246 | 246 | } else { |
| 247 | 247 | blkcnt_t count = 1; |
| 248 | 248 | |
| 249 | + err = inc_valid_block_count(sbi, inode, &count); | |
| 250 | + if (err) { | |
| 251 | + f2fs_put_dnode(&dn); | |
| 252 | + return err; | |
| 253 | + } | |
| 254 | + | |
| 249 | 255 | *old_addr = dn.data_blkaddr; |
| 250 | 256 | f2fs_truncate_data_blocks_range(&dn, 1); |
| 251 | 257 | dec_valid_block_count(sbi, F2FS_I(inode)->cow_inode, count); |
| 252 | − inc_valid_block_count(sbi, inode, &count); | |
| 258 | + | |
| 253 | 259 | f2fs_replace_block(sbi, &dn, dn.data_blkaddr, new_addr, |
| 254 | 260 | ni.version, true, false); |
| 255 | 261 | } |
| @@ -257,7 +263,7 @@ retry: · 1 unmodified line | ||
| 257 | 263 | f2fs_put_dnode(&dn); |
| 258 | 264 | |
| 259 | 265 | trace_f2fs_replace_atomic_write_block(inode, F2FS_I(inode)->cow_inode, |
| 260 | − index, *old_addr, new_addr, recover); | |
| 266 | + index, old_addr ? *old_addr : 0, new_addr, recover); | |
| 261 | 267 | return 0; |
| 262 | 268 | } |
| 263 | 269 | |
| @@ -406,27 +412,28 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need) · 142 unmodified lines | ||
| 406 | 412 | * We should do GC or end up with checkpoint, if there are so many dirty |
| 407 | 413 | * dir/node pages without enough free segments. |
| 408 | 414 | */ |
| 409 | − if (has_not_enough_free_secs(sbi, 0, 0)) { | |
| 410 | − if (test_opt(sbi, GC_MERGE) && sbi->gc_thread && | |
| 411 | − sbi->gc_thread->f2fs_gc_task) { | |
| 412 | − DEFINE_WAIT(wait); | |
| 413 | − | |
| 414 | − prepare_to_wait(&sbi->gc_thread->fggc_wq, &wait, | |
| 415 | − TASK_UNINTERRUPTIBLE); | |
| 416 | − wake_up(&sbi->gc_thread->gc_wait_queue_head); | |
| 417 | − io_schedule(); | |
| 418 | − finish_wait(&sbi->gc_thread->fggc_wq, &wait); | |
| 419 | − } else { | |
| 420 | − struct f2fs_gc_control gc_control = { | |
| 421 | − .victim_segno = NULL_SEGNO, | |
| 422 | − .init_gc_type = BG_GC, | |
| 423 | − .no_bg_gc = true, | |
| 424 | − .should_migrate_blocks = false, | |
| 425 | − .err_gc_skipped = false, | |
| 426 | − .nr_free_secs = 1 }; | |
| 427 | − f2fs_down_write(&sbi->gc_lock); | |
| 428 | − f2fs_gc(sbi, &gc_control); | |
| 429 | − } | |
| 415 | + if (has_enough_free_secs(sbi, 0, 0)) | |
| 416 | + return; | |
| 417 | + | |
| 418 | + if (test_opt(sbi, GC_MERGE) && sbi->gc_thread && | |
| 419 | + sbi->gc_thread->f2fs_gc_task) { | |
| 420 | + DEFINE_WAIT(wait); | |
| 421 | + | |
| 422 | + prepare_to_wait(&sbi->gc_thread->fggc_wq, &wait, | |
| 423 | + TASK_UNINTERRUPTIBLE); | |
| 424 | + wake_up(&sbi->gc_thread->gc_wait_queue_head); | |
| 425 | + io_schedule(); | |
| 426 | + finish_wait(&sbi->gc_thread->fggc_wq, &wait); | |
| 427 | + } else { | |
| 428 | + struct f2fs_gc_control gc_control = { | |
| 429 | + .victim_segno = NULL_SEGNO, | |
| 430 | + .init_gc_type = BG_GC, | |
| 431 | + .no_bg_gc = true, | |
| 432 | + .should_migrate_blocks = false, | |
| 433 | + .err_gc_skipped = false, | |
| 434 | + .nr_free_secs = 1 }; | |
| 435 | + f2fs_down_write(&sbi->gc_lock); | |
| 436 | + f2fs_gc(sbi, &gc_control); | |
| 430 | 437 | } |
| 431 | 438 | } |
| 432 | 439 | |
| @@ -933,9 +940,9 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi, · 500 unmodified lines | ||
| 933 | 940 | dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS, true, NULL); |
| 934 | 941 | INIT_LIST_HEAD(&dc->list); |
| 935 | 942 | dc->bdev = bdev; |
| 936 | − dc->lstart = lstart; | |
| 937 | − dc->start = start; | |
| 938 | − dc->len = len; | |
| 943 | + dc->di.lstart = lstart; | |
| 944 | + dc->di.start = start; | |
| 945 | + dc->di.len = len; | |
| 939 | 946 | dc->ref = 0; |
| 940 | 947 | dc->state = D_PREP; |
| 941 | 948 | dc->queued = 0; |
| @@ -950,20 +957,108 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi, · 8 unmodified lines | ||
| 950 | 957 | return dc; |
| 951 | 958 | } |
| 952 | 959 | |
| 953 | −static struct discard_cmd *__attach_discard_cmd(struct f2fs_sb_info *sbi, | |
| 954 | − struct block_device *bdev, block_t lstart, | |
| 955 | − block_t start, block_t len, | |
| 956 | − struct rb_node *parent, struct rb_node **p, | |
| 957 | − bool leftmost) | |
| 960 | +static bool f2fs_check_discard_tree(struct f2fs_sb_info *sbi) | |
| 961 | +{ | |
| 962 | +#ifdef CONFIG_F2FS_CHECK_FS | |
| 963 | + struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; | |
| 964 | + struct rb_node *cur = rb_first_cached(&dcc->root), *next; | |
| 965 | + struct discard_cmd *cur_dc, *next_dc; | |
| 966 | + | |
| 967 | + while (cur) { | |
| 968 | + next = rb_next(cur); | |
| 969 | + if (!next) | |
| 970 | + return true; | |
| 971 | + | |
| 972 | + cur_dc = rb_entry(cur, struct discard_cmd, rb_node); | |
| 973 | + next_dc = rb_entry(next, struct discard_cmd, rb_node); | |
| 974 | + | |
| 975 | + if (cur_dc->di.lstart + cur_dc->di.len > next_dc->di.lstart) { | |
| 976 | + f2fs_info(sbi, "broken discard_rbtree, " | |
| 977 | + "cur(%u, %u) next(%u, %u)", | |
| 978 | + cur_dc->di.lstart, cur_dc->di.len, | |
| 979 | + next_dc->di.lstart, next_dc->di.len); | |
| 980 | + return false; | |
| 981 | + } | |
| 982 | + cur = next; | |
| 983 | + } | |
| 984 | +#endif | |
| 985 | + return true; | |
| 986 | +} | |
| 987 | + | |
| 988 | +static struct discard_cmd *__lookup_discard_cmd(struct f2fs_sb_info *sbi, | |
| 989 | + block_t blkaddr) | |
| 958 | 990 | { |
| 959 | 991 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; |
| 992 | + struct rb_node *node = dcc->root.rb_root.rb_node; | |
| 960 | 993 | struct discard_cmd *dc; |
| 961 | 994 | |
| 962 | − dc = __create_discard_cmd(sbi, bdev, lstart, start, len); | |
| 995 | + while (node) { | |
| 996 | + dc = rb_entry(node, struct discard_cmd, rb_node); | |
| 963 | 997 | |
| 964 | − rb_link_node(&dc->rb_node, parent, p); | |
| 965 | − rb_insert_color_cached(&dc->rb_node, &dcc->root, leftmost); | |
| 998 | + if (blkaddr < dc->di.lstart) | |
| 999 | + node = node->rb_left; | |
| 1000 | + else if (blkaddr >= dc->di.lstart + dc->di.len) | |
| 1001 | + node = node->rb_right; | |
| 1002 | + else | |
| 1003 | + return dc; | |
| 1004 | + } | |
| 1005 | + return NULL; | |
| 1006 | +} | |
| 1007 | + | |
| 1008 | +static struct discard_cmd *__lookup_discard_cmd_ret(struct rb_root_cached *root, | |
| 1009 | + block_t blkaddr, | |
| 1010 | + struct discard_cmd **prev_entry, | |
| 1011 | + struct discard_cmd **next_entry, | |
| 1012 | + struct rb_node ***insert_p, | |
| 1013 | + struct rb_node **insert_parent) | |
| 1014 | +{ | |
| 1015 | + struct rb_node **pnode = &root->rb_root.rb_node; | |
| 1016 | + struct rb_node *parent = NULL, *tmp_node; | |
| 1017 | + struct discard_cmd *dc; | |
| 1018 | + | |
| 1019 | + *insert_p = NULL; | |
| 1020 | + *insert_parent = NULL; | |
| 1021 | + *prev_entry = NULL; | |
| 1022 | + *next_entry = NULL; | |
| 1023 | + | |
| 1024 | + if (RB_EMPTY_ROOT(&root->rb_root)) | |
| 1025 | + return NULL; | |
| 1026 | + | |
| 1027 | + while (*pnode) { | |
| 1028 | + parent = *pnode; | |
| 1029 | + dc = rb_entry(*pnode, struct discard_cmd, rb_node); | |
| 1030 | + | |
| 1031 | + if (blkaddr < dc->di.lstart) | |
| 1032 | + pnode = &(*pnode)->rb_left; | |
| 1033 | + else if (blkaddr >= dc->di.lstart + dc->di.len) | |
| 1034 | + pnode = &(*pnode)->rb_right; | |
| 1035 | + else | |
| 1036 | + goto lookup_neighbors; | |
| 1037 | + } | |
| 1038 | + | |
| 1039 | + *insert_p = pnode; | |
| 1040 | + *insert_parent = parent; | |
| 1041 | + | |
| 1042 | + dc = rb_entry(parent, struct discard_cmd, rb_node); | |
| 1043 | + tmp_node = parent; | |
| 1044 | + if (parent && blkaddr > dc->di.lstart) | |
| 1045 | + tmp_node = rb_next(parent); | |
| 1046 | + *next_entry = rb_entry_safe(tmp_node, struct discard_cmd, rb_node); | |
| 1047 | + | |
| 1048 | + tmp_node = parent; | |
| 1049 | + if (parent && blkaddr < dc->di.lstart) | |
| 1050 | + tmp_node = rb_prev(parent); | |
| 1051 | + *prev_entry = rb_entry_safe(tmp_node, struct discard_cmd, rb_node); | |
| 1052 | + return NULL; | |
| 966 | 1053 | |
| 1054 | +lookup_neighbors: | |
| 1055 | + /* lookup prev node for merging backward later */ | |
| 1056 | + tmp_node = rb_prev(&dc->rb_node); | |
| 1057 | + *prev_entry = rb_entry_safe(tmp_node, struct discard_cmd, rb_node); | |
| 1058 | + | |
| 1059 | + /* lookup next node for merging frontward later */ | |
| 1060 | + tmp_node = rb_next(&dc->rb_node); | |
| 1061 | + *next_entry = rb_entry_safe(tmp_node, struct discard_cmd, rb_node); | |
| 967 | 1062 | return dc; |
| 968 | 1063 | } |
| 969 | 1064 | |
| @@ -975,7 +1070,7 @@ static void __detach_discard_cmd(struct discard_cmd_control *dcc, · 5 unmodified lines | ||
| 975 | 1070 | |
| 976 | 1071 | list_del(&dc->list); |
| 977 | 1072 | rb_erase_cached(&dc->rb_node, &dcc->root); |
| 978 | − dcc->undiscard_blks -= dc->len; | |
| 1073 | + dcc->undiscard_blks -= dc->di.len; | |
| 979 | 1074 | |
| 980 | 1075 | kmem_cache_free(discard_cmd_slab, dc); |
| 981 | 1076 | |
| @@ -988,7 +1083,7 @@ static void __remove_discard_cmd(struct f2fs_sb_info *sbi, · 6 unmodified lines | ||
| 988 | 1083 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; |
| 989 | 1084 | unsigned long flags; |
| 990 | 1085 | |
| 991 | − trace_f2fs_remove_discard(dc->bdev, dc->start, dc->len); | |
| 1086 | + trace_f2fs_remove_discard(dc->bdev, dc->di.start, dc->di.len); | |
| 992 | 1087 | |
| 993 | 1088 | spin_lock_irqsave(&dc->lock, flags); |
| 994 | 1089 | if (dc->bio_ref) { |
| @@ -1006,7 +1101,7 @@ static void __remove_discard_cmd(struct f2fs_sb_info *sbi, · 11 unmodified lines | ||
| 1006 | 1101 | printk_ratelimited( |
| 1007 | 1102 | "%sF2FS-fs (%s): Issue discard(%u, %u, %u) failed, ret: %d", |
| 1008 | 1103 | KERN_INFO, sbi->sb->s_id, |
| 1009 | − dc->lstart, dc->start, dc->len, dc->error); | |
| 1104 | + dc->di.lstart, dc->di.start, dc->di.len, dc->error); | |
| 1010 | 1105 | __detach_discard_cmd(dcc, dc); |
| 1011 | 1106 | } |
| 1012 | 1107 | |
| @@ -1122,14 +1217,14 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, · 109 unmodified lines | ||
| 1122 | 1217 | if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) |
| 1123 | 1218 | return 0; |
| 1124 | 1219 | |
| 1125 | − trace_f2fs_issue_discard(bdev, dc->start, dc->len); | |
| 1220 | + trace_f2fs_issue_discard(bdev, dc->di.start, dc->di.len); | |
| 1126 | 1221 | |
| 1127 | − lstart = dc->lstart; | |
| 1128 | − start = dc->start; | |
| 1129 | − len = dc->len; | |
| 1222 | + lstart = dc->di.lstart; | |
| 1223 | + start = dc->di.start; | |
| 1224 | + len = dc->di.len; | |
| 1130 | 1225 | total_len = len; |
| 1131 | 1226 | |
| 1132 | − dc->len = 0; | |
| 1227 | + dc->di.len = 0; | |
| 1133 | 1228 | |
| 1134 | 1229 | while (total_len && *issued < dpolicy->max_requests && !err) { |
| 1135 | 1230 | struct bio *bio = NULL; |
| @@ -1145,7 +1240,7 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, · 9 unmodified lines | ||
| 1145 | 1240 | if (*issued == dpolicy->max_requests) |
| 1146 | 1241 | last = true; |
| 1147 | 1242 | |
| 1148 | − dc->len += len; | |
| 1243 | + dc->di.len += len; | |
| 1149 | 1244 | |
| 1150 | 1245 | if (time_to_inject(sbi, FAULT_DISCARD)) { |
| 1151 | 1246 | err = -EIO; |
| @@ -1207,34 +1302,41 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, · 55 unmodified lines | ||
| 1207 | 1302 | return err; |
| 1208 | 1303 | } |
| 1209 | 1304 | |
| 1210 | −static void __insert_discard_tree(struct f2fs_sb_info *sbi, | |
| 1305 | +static void __insert_discard_cmd(struct f2fs_sb_info *sbi, | |
| 1211 | 1306 | struct block_device *bdev, block_t lstart, |
| 1212 | − block_t start, block_t len, | |
| 1213 | − struct rb_node **insert_p, | |
| 1214 | − struct rb_node *insert_parent) | |
| 1307 | + block_t start, block_t len) | |
| 1215 | 1308 | { |
| 1216 | 1309 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; |
| 1217 | − struct rb_node **p; | |
| 1310 | + struct rb_node **p = &dcc->root.rb_root.rb_node; | |
| 1218 | 1311 | struct rb_node *parent = NULL; |
| 1312 | + struct discard_cmd *dc; | |
| 1219 | 1313 | bool leftmost = true; |
| 1220 | 1314 | |
| 1221 | − if (insert_p && insert_parent) { | |
| 1222 | − parent = insert_parent; | |
| 1223 | − p = insert_p; | |
| 1224 | − goto do_insert; | |
| 1315 | + /* look up rb tree to find parent node */ | |
| 1316 | + while (*p) { | |
| 1317 | + parent = *p; | |
| 1318 | + dc = rb_entry(parent, struct discard_cmd, rb_node); | |
| 1319 | + | |
| 1320 | + if (lstart < dc->di.lstart) { | |
| 1321 | + p = &(*p)->rb_left; | |
| 1322 | + } else if (lstart >= dc->di.lstart + dc->di.len) { | |
| 1323 | + p = &(*p)->rb_right; | |
| 1324 | + leftmost = false; | |
| 1325 | + } else { | |
| 1326 | + f2fs_bug_on(sbi, 1); | |
| 1327 | + } | |
| 1225 | 1328 | } |
| 1226 | 1329 | |
| 1227 | − p = f2fs_lookup_rb_tree_for_insert(sbi, &dcc->root, &parent, | |
| 1228 | − lstart, &leftmost); | |
| 1229 | −do_insert: | |
| 1230 | − __attach_discard_cmd(sbi, bdev, lstart, start, len, parent, | |
| 1231 | − p, leftmost); | |
| 1330 | + dc = __create_discard_cmd(sbi, bdev, lstart, start, len); | |
| 1331 | + | |
| 1332 | + rb_link_node(&dc->rb_node, parent, p); | |
| 1333 | + rb_insert_color_cached(&dc->rb_node, &dcc->root, leftmost); | |
| 1232 | 1334 | } |
| 1233 | 1335 | |
| 1234 | 1336 | static void __relocate_discard_cmd(struct discard_cmd_control *dcc, |
| 1235 | 1337 | struct discard_cmd *dc) |
| 1236 | 1338 | { |
| 1237 | − list_move_tail(&dc->list, &dcc->pend_list[plist_idx(dc->len)]); | |
| 1339 | + list_move_tail(&dc->list, &dcc->pend_list[plist_idx(dc->di.len)]); | |
| 1238 | 1340 | } |
| 1239 | 1341 | |
| 1240 | 1342 | static void __punch_discard_cmd(struct f2fs_sb_info *sbi, |
| @@ -1244,7 +1346,7 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi, · 3 unmodified lines | ||
| 1244 | 1346 | struct discard_info di = dc->di; |
| 1245 | 1347 | bool modified = false; |
| 1246 | 1348 | |
| 1247 | − if (dc->state == D_DONE || dc->len == 1) { | |
| 1349 | + if (dc->state == D_DONE || dc->di.len == 1) { | |
| 1248 | 1350 | __remove_discard_cmd(sbi, dc); |
| 1249 | 1351 | return; |
| 1250 | 1352 | } |
| @@ -1252,23 +1354,22 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi, · 1 unmodified line | ||
| 1252 | 1354 | dcc->undiscard_blks -= di.len; |
| 1253 | 1355 | |
| 1254 | 1356 | if (blkaddr > di.lstart) { |
| 1255 | − dc->len = blkaddr - dc->lstart; | |
| 1256 | − dcc->undiscard_blks += dc->len; | |
| 1357 | + dc->di.len = blkaddr - dc->di.lstart; | |
| 1358 | + dcc->undiscard_blks += dc->di.len; | |
| 1257 | 1359 | __relocate_discard_cmd(dcc, dc); |
| 1258 | 1360 | modified = true; |
| 1259 | 1361 | } |
| 1260 | 1362 | |
| 1261 | 1363 | if (blkaddr < di.lstart + di.len - 1) { |
| 1262 | 1364 | if (modified) { |
| 1263 | − __insert_discard_tree(sbi, dc->bdev, blkaddr + 1, | |
| 1365 | + __insert_discard_cmd(sbi, dc->bdev, blkaddr + 1, | |
| 1264 | 1366 | di.start + blkaddr + 1 - di.lstart, |
| 1265 | − di.lstart + di.len - 1 - blkaddr, | |
| 1266 | − NULL, NULL); | |
| 1367 | + di.lstart + di.len - 1 - blkaddr); | |
| 1267 | 1368 | } else { |
| 1268 | − dc->lstart++; | |
| 1269 | − dc->len--; | |
| 1270 | − dc->start++; | |
| 1271 | − dcc->undiscard_blks += dc->len; | |
| 1369 | + dc->di.lstart++; | |
| 1370 | + dc->di.len--; | |
| 1371 | + dc->di.start++; | |
| 1372 | + dcc->undiscard_blks += dc->di.len; | |
| 1272 | 1373 | __relocate_discard_cmd(dcc, dc); |
| 1273 | 1374 | } |
| 1274 | 1375 | } |
| @@ -1287,17 +1388,14 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi, · 12 unmodified lines | ||
| 1287 | 1388 | SECTOR_TO_BLOCK(bdev_max_discard_sectors(bdev)); |
| 1288 | 1389 | block_t end = lstart + len; |
| 1289 | 1390 | |
| 1290 | − dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root, | |
| 1291 | − NULL, lstart, | |
| 1292 | − (struct rb_entry **)&prev_dc, | |
| 1293 | − (struct rb_entry **)&next_dc, | |
| 1294 | − &insert_p, &insert_parent, true, NULL); | |
| 1391 | + dc = __lookup_discard_cmd_ret(&dcc->root, lstart, | |
| 1392 | + &prev_dc, &next_dc, &insert_p, &insert_parent); | |
| 1295 | 1393 | if (dc) |
| 1296 | 1394 | prev_dc = dc; |
| 1297 | 1395 | |
| 1298 | 1396 | if (!prev_dc) { |
| 1299 | 1397 | di.lstart = lstart; |
| 1300 | − di.len = next_dc ? next_dc->lstart - lstart : len; | |
| 1398 | + di.len = next_dc ? next_dc->di.lstart - lstart : len; | |
| 1301 | 1399 | di.len = min(di.len, len); |
| 1302 | 1400 | di.start = start; |
| 1303 | 1401 | } |
| @@ -1308,16 +1406,16 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi, · 4 unmodified lines | ||
| 1308 | 1406 | struct discard_cmd *tdc = NULL; |
| 1309 | 1407 | |
| 1310 | 1408 | if (prev_dc) { |
| 1311 | − di.lstart = prev_dc->lstart + prev_dc->len; | |
| 1409 | + di.lstart = prev_dc->di.lstart + prev_dc->di.len; | |
| 1312 | 1410 | if (di.lstart < lstart) |
| 1313 | 1411 | di.lstart = lstart; |
| 1314 | 1412 | if (di.lstart >= end) |
| 1315 | 1413 | break; |
| 1316 | 1414 | |
| 1317 | − if (!next_dc || next_dc->lstart > end) | |
| 1415 | + if (!next_dc || next_dc->di.lstart > end) | |
| 1318 | 1416 | di.len = end - di.lstart; |
| 1319 | 1417 | else |
| 1320 | − di.len = next_dc->lstart - di.lstart; | |
| 1418 | + di.len = next_dc->di.lstart - di.lstart; | |
| 1321 | 1419 | di.start = start + di.lstart - lstart; |
| 1322 | 1420 | } |
| 1323 | 1421 | |
| @@ -1350,10 +1448,9 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi, · 26 unmodified lines | ||
| 1350 | 1448 | merged = true; |
| 1351 | 1449 | } |
| 1352 | 1450 | |
| 1353 | − if (!merged) { | |
| 1354 | − __insert_discard_tree(sbi, bdev, di.lstart, di.start, | |
| 1355 | − di.len, NULL, NULL); | |
| 1356 | − } | |
| 1451 | + if (!merged) | |
| 1452 | + __insert_discard_cmd(sbi, bdev, | |
| 1453 | + di.lstart, di.start, di.len); | |
| 1357 | 1454 | next: |
| 1358 | 1455 | prev_dc = next_dc; |
| 1359 | 1456 | if (!prev_dc) |
| @@ -1392,15 +1489,11 @@ static void __issue_discard_cmd_orderly(struct f2fs_sb_info *sbi, · 32 unmodified lines | ||
| 1392 | 1489 | struct rb_node **insert_p = NULL, *insert_parent = NULL; |
| 1393 | 1490 | struct discard_cmd *dc; |
| 1394 | 1491 | struct blk_plug plug; |
| 1395 | − unsigned int pos = dcc->next_pos; | |
| 1396 | 1492 | bool io_interrupted = false; |
| 1397 | 1493 | |
| 1398 | 1494 | mutex_lock(&dcc->cmd_lock); |
| 1399 | − dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root, | |
| 1400 | − NULL, pos, | |
| 1401 | − (struct rb_entry **)&prev_dc, | |
| 1402 | − (struct rb_entry **)&next_dc, | |
| 1403 | − &insert_p, &insert_parent, true, NULL); | |
| 1495 | + dc = __lookup_discard_cmd_ret(&dcc->root, dcc->next_pos, | |
| 1496 | + &prev_dc, &next_dc, &insert_p, &insert_parent); | |
| 1404 | 1497 | if (!dc) |
| 1405 | 1498 | dc = next_dc; |
| 1406 | 1499 | |
| @@ -1418,7 +1511,7 @@ static void __issue_discard_cmd_orderly(struct f2fs_sb_info *sbi, · 11 unmodified lines | ||
| 1418 | 1511 | break; |
| 1419 | 1512 | } |
| 1420 | 1513 | |
| 1421 | − dcc->next_pos = dc->lstart + dc->len; | |
| 1514 | + dcc->next_pos = dc->di.lstart + dc->di.len; | |
| 1422 | 1515 | err = __submit_discard_cmd(sbi, dpolicy, dc, issued); |
| 1423 | 1516 | |
| 1424 | 1517 | if (*issued >= dpolicy->max_requests) |
| @@ -1477,8 +1570,7 @@ retry: · 52 unmodified lines | ||
| 1477 | 1570 | if (list_empty(pend_list)) |
| 1478 | 1571 | goto next; |
| 1479 | 1572 | if (unlikely(dcc->rbtree_check)) |
| 1480 | − f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi, | |
| 1481 | − &dcc->root, false)); | |
| 1573 | + f2fs_bug_on(sbi, !f2fs_check_discard_tree(sbi)); | |
| 1482 | 1574 | blk_start_plug(&plug); |
| 1483 | 1575 | list_for_each_entry_safe(dc, tmp, pend_list, list) { |
| 1484 | 1576 | f2fs_bug_on(sbi, dc->state != D_PREP); |
| @@ -1556,7 +1648,7 @@ static unsigned int __wait_one_discard_bio(struct f2fs_sb_info *sbi, · 71 unmodified lines | ||
| 1556 | 1648 | dc->ref--; |
| 1557 | 1649 | if (!dc->ref) { |
| 1558 | 1650 | if (!dc->error) |
| 1559 | − len = dc->len; | |
| 1651 | + len = dc->di.len; | |
| 1560 | 1652 | __remove_discard_cmd(sbi, dc); |
| 1561 | 1653 | } |
| 1562 | 1654 | mutex_unlock(&dcc->cmd_lock); |
| @@ -1579,14 +1671,15 @@ next: · 16 unmodified lines | ||
| 1579 | 1671 | |
| 1580 | 1672 | mutex_lock(&dcc->cmd_lock); |
| 1581 | 1673 | list_for_each_entry_safe(iter, tmp, wait_list, list) { |
| 1582 | − if (iter->lstart + iter->len <= start || end <= iter->lstart) | |
| 1674 | + if (iter->di.lstart + iter->di.len <= start || | |
| 1675 | + end <= iter->di.lstart) | |
| 1583 | 1676 | continue; |
| 1584 | − if (iter->len < dpolicy->granularity) | |
| 1677 | + if (iter->di.len < dpolicy->granularity) | |
| 1585 | 1678 | continue; |
| 1586 | 1679 | if (iter->state == D_DONE && !iter->ref) { |
| 1587 | 1680 | wait_for_completion_io(&iter->wait); |
| 1588 | 1681 | if (!iter->error) |
| 1589 | − trimmed += iter->len; | |
| 1682 | + trimmed += iter->di.len; | |
| 1590 | 1683 | __remove_discard_cmd(sbi, iter); |
| 1591 | 1684 | } else { |
| 1592 | 1685 | iter->ref++; |
| @@ -1630,8 +1723,7 @@ static void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr) · 37 unmodified lines | ||
| 1630 | 1723 | bool need_wait = false; |
| 1631 | 1724 | |
| 1632 | 1725 | mutex_lock(&dcc->cmd_lock); |
| 1633 | − dc = (struct discard_cmd *)f2fs_lookup_rb_tree(&dcc->root, | |
| 1634 | − NULL, blkaddr); | |
| 1726 | + dc = __lookup_discard_cmd(sbi, blkaddr); | |
| 1635 | 1727 | if (dc) { |
| 1636 | 1728 | if (dc->state == D_PREP) { |
| 1637 | 1729 | __punch_discard_cmd(sbi, dc, blkaddr); |
| @@ -1760,6 +1852,7 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi, · 122 unmodified lines | ||
| 1760 | 1852 | sector_t sector, nr_sects; |
| 1761 | 1853 | block_t lblkstart = blkstart; |
| 1762 | 1854 | int devi = 0; |
| 1855 | + u64 remainder = 0; | |
| 1763 | 1856 | |
| 1764 | 1857 | if (f2fs_is_multi_device(sbi)) { |
| 1765 | 1858 | devi = f2fs_target_device_index(sbi, blkstart); |
| @@ -1775,9 +1868,9 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi, · 9 unmodified lines | ||
| 1775 | 1868 | if (f2fs_blkz_is_seq(sbi, devi, blkstart)) { |
| 1776 | 1869 | sector = SECTOR_FROM_BLOCK(blkstart); |
| 1777 | 1870 | nr_sects = SECTOR_FROM_BLOCK(blklen); |
| 1871 | + div64_u64_rem(sector, bdev_zone_sectors(bdev), &remainder); | |
| 1778 | 1872 | |
| 1779 | − if (sector & (bdev_zone_sectors(bdev) - 1) || | |
| 1780 | − nr_sects != bdev_zone_sectors(bdev)) { | |
| 1873 | + if (remainder || nr_sects != bdev_zone_sectors(bdev)) { | |
| 1781 | 1874 | f2fs_err(sbi, "(%d) %s: Unaligned zone reset attempted (block %x + %x)", |
| 1782 | 1875 | devi, sbi->s_ndevs ? FDEV(devi).path : "", |
| 1783 | 1876 | blkstart, blklen); |
| @@ -1982,9 +2075,11 @@ void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi, · 198 unmodified lines | ||
| 1982 | 2075 | |
| 1983 | 2076 | if (force && start >= cpc->trim_start && |
| 1984 | 2077 | (end - 1) <= cpc->trim_end) |
| 1985 | − continue; | |
| 2078 | + continue; | |
| 1986 | 2079 | |
| 1987 | − if (!f2fs_lfs_mode(sbi) || !__is_large_section(sbi)) { | |
| 2080 | + /* Should cover 2MB zoned device for zone-based reset */ | |
| 2081 | + if (!f2fs_sb_has_blkzoned(sbi) && | |
| 2082 | + (!f2fs_lfs_mode(sbi) || !__is_large_section(sbi))) { | |
| 1988 | 2083 | f2fs_issue_discard(sbi, START_BLOCK(sbi, start), |
| 1989 | 2084 | (end - start) << sbi->log_blocks_per_seg); |
| 1990 | 2085 | continue; |
| @@ -2787,7 +2882,6 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type, · 796 unmodified lines | ||
| 2787 | 2882 | int alloc_mode, unsigned long long age) |
| 2788 | 2883 | { |
| 2789 | 2884 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
| 2790 | − const struct victim_selection *v_ops = DIRTY_I(sbi)->v_ops; | |
| 2791 | 2885 | unsigned segno = NULL_SEGNO; |
| 2792 | 2886 | unsigned short seg_type = curseg->seg_type; |
| 2793 | 2887 | int i, cnt; |
| @@ -2796,7 +2890,7 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type, · 2 unmodified lines | ||
| 2796 | 2890 | sanity_check_seg_type(sbi, seg_type); |
| 2797 | 2891 | |
| 2798 | 2892 | /* f2fs_need_SSR() already forces to do this */ |
| 2799 | − if (!v_ops->get_victim(sbi, &segno, BG_GC, seg_type, alloc_mode, age)) { | |
| 2893 | + if (!f2fs_get_victim(sbi, &segno, BG_GC, seg_type, alloc_mode, age)) { | |
| 2800 | 2894 | curseg->next_segno = segno; |
| 2801 | 2895 | return 1; |
| 2802 | 2896 | } |
| @@ -2823,7 +2917,7 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type, · 20 unmodified lines | ||
| 2823 | 2917 | for (; cnt-- > 0; reversed ? i-- : i++) { |
| 2824 | 2918 | if (i == seg_type) |
| 2825 | 2919 | continue; |
| 2826 | − if (!v_ops->get_victim(sbi, &segno, BG_GC, i, alloc_mode, age)) { | |
| 2920 | + if (!f2fs_get_victim(sbi, &segno, BG_GC, i, alloc_mode, age)) { | |
| 2827 | 2921 | curseg->next_segno = segno; |
| 2828 | 2922 | return 1; |
| 2829 | 2923 | } |
| @@ -2964,24 +3058,20 @@ next: · 134 unmodified lines | ||
| 2964 | 3058 | |
| 2965 | 3059 | mutex_lock(&dcc->cmd_lock); |
| 2966 | 3060 | if (unlikely(dcc->rbtree_check)) |
| 2967 | − f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi, | |
| 2968 | − &dcc->root, false)); | |
| 2969 | − | |
| 2970 | − dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root, | |
| 2971 | − NULL, start, | |
| 2972 | − (struct rb_entry **)&prev_dc, | |
| 2973 | − (struct rb_entry **)&next_dc, | |
| 2974 | − &insert_p, &insert_parent, true, NULL); | |
| 3061 | + f2fs_bug_on(sbi, !f2fs_check_discard_tree(sbi)); | |
| 3062 | + | |
| 3063 | + dc = __lookup_discard_cmd_ret(&dcc->root, start, | |
| 3064 | + &prev_dc, &next_dc, &insert_p, &insert_parent); | |
| 2975 | 3065 | if (!dc) |
| 2976 | 3066 | dc = next_dc; |
| 2977 | 3067 | |
| 2978 | 3068 | blk_start_plug(&plug); |
| 2979 | 3069 | |
| 2980 | − while (dc && dc->lstart <= end) { | |
| 3070 | + while (dc && dc->di.lstart <= end) { | |
| 2981 | 3071 | struct rb_node *node; |
| 2982 | 3072 | int err = 0; |
| 2983 | 3073 | |
| 2984 | − if (dc->len < dpolicy->granularity) | |
| 3074 | + if (dc->di.len < dpolicy->granularity) | |
| 2985 | 3075 | goto skip; |
| 2986 | 3076 | |
| 2987 | 3077 | if (dc->state != D_PREP) { |
| @@ -2992,7 +3082,7 @@ next: · 4 unmodified lines | ||
| 2992 | 3082 | err = __submit_discard_cmd(sbi, dpolicy, dc, &issued); |
| 2993 | 3083 | |
| 2994 | 3084 | if (issued >= dpolicy->max_requests) { |
| 2995 | − start = dc->lstart + dc->len; | |
| 3085 | + start = dc->di.lstart + dc->di.len; | |
| 2996 | 3086 | |
| 2997 | 3087 | if (err) |
| 2998 | 3088 | __remove_discard_cmd(sbi, dc); |
| @@ -4859,9 +4949,8 @@ static int fix_curseg_write_pointer(struct f2fs_sb_info *sbi, int type) · 1860 unmodified lines | ||
| 4859 | 4949 | "New zone for curseg[%d] is not yet discarded. " |
| 4860 | 4950 | "Reset the zone: curseg[0x%x,0x%x]", |
| 4861 | 4951 | type, cs->segno, cs->next_blkoff); |
| 4862 | − err = __f2fs_issue_discard_zone(sbi, zbd->bdev, | |
| 4863 | − zone_sector >> log_sectors_per_block, | |
| 4864 | − zone.len >> log_sectors_per_block); | |
| 4952 | + err = __f2fs_issue_discard_zone(sbi, zbd->bdev, cs_zone_block, | |
| 4953 | + zone.len >> log_sectors_per_block); | |
| 4865 | 4954 | if (err) { |
| 4866 | 4955 | f2fs_err(sbi, "Discard zone failed: %s (errno=%d)", |
| 4867 | 4956 | zbd->path, err); |
| @@ -4920,48 +5009,6 @@ int f2fs_check_write_pointer(struct f2fs_sb_info *sbi) · 52 unmodified lines | ||
| 4920 | 5009 | return 0; |
| 4921 | 5010 | } |
| 4922 | 5011 | |
| 4923 | −static bool is_conv_zone(struct f2fs_sb_info *sbi, unsigned int zone_idx, | |
| 4924 | − unsigned int dev_idx) | |
| 4925 | −{ | |
| 4926 | − if (!bdev_is_zoned(FDEV(dev_idx).bdev)) | |
| 4927 | − return true; | |
| 4928 | − return !test_bit(zone_idx, FDEV(dev_idx).blkz_seq); | |
| 4929 | −} | |
| 4930 | − | |
| 4931 | −/* Return the zone index in the given device */ | |
| 4932 | −static unsigned int get_zone_idx(struct f2fs_sb_info *sbi, unsigned int secno, | |
| 4933 | − int dev_idx) | |
| 4934 | −{ | |
| 4935 | − block_t sec_start_blkaddr = START_BLOCK(sbi, GET_SEG_FROM_SEC(sbi, secno)); | |
| 4936 | − | |
| 4937 | − return (sec_start_blkaddr - FDEV(dev_idx).start_blk) >> | |
| 4938 | − sbi->log_blocks_per_blkz; | |
| 4939 | −} | |
| 4940 | − | |
| 4941 | −/* | |
| 4942 | − * Return the usable segments in a section based on the zone's | |
| 4943 | − * corresponding zone capacity. Zone is equal to a section. | |
| 4944 | − */ | |
| 4945 | −static inline unsigned int f2fs_usable_zone_segs_in_sec( | |
| 4946 | − struct f2fs_sb_info *sbi, unsigned int segno) | |
| 4947 | −{ | |
| 4948 | − unsigned int dev_idx, zone_idx; | |
| 4949 | − | |
| 4950 | − dev_idx = f2fs_target_device_index(sbi, START_BLOCK(sbi, segno)); | |
| 4951 | − zone_idx = get_zone_idx(sbi, GET_SEC_FROM_SEG(sbi, segno), dev_idx); | |
| 4952 | − | |
| 4953 | − /* Conventional zone's capacity is always equal to zone size */ | |
| 4954 | − if (is_conv_zone(sbi, zone_idx, dev_idx)) | |
| 4955 | − return sbi->segs_per_sec; | |
| 4956 | − | |
| 4957 | − if (!sbi->unusable_blocks_per_sec) | |
| 4958 | − return sbi->segs_per_sec; | |
| 4959 | − | |
| 4960 | − /* Get the segment count beyond zone capacity block */ | |
| 4961 | − return sbi->segs_per_sec - (sbi->unusable_blocks_per_sec >> | |
| 4962 | − sbi->log_blocks_per_seg); | |
| 4963 | −} | |
| 4964 | − | |
| 4965 | 5012 | /* |
| 4966 | 5013 | * Return the number of usable blocks in a segment. The number of blocks |
| 4967 | 5014 | * returned is always equal to the number of blocks in a segment for |
| @@ -4974,23 +5021,13 @@ static inline unsigned int f2fs_usable_zone_blks_in_seg( · 6 unmodified lines | ||
| 4974 | 5021 | struct f2fs_sb_info *sbi, unsigned int segno) |
| 4975 | 5022 | { |
| 4976 | 5023 | block_t seg_start, sec_start_blkaddr, sec_cap_blkaddr; |
| 4977 | − unsigned int zone_idx, dev_idx, secno; | |
| 4978 | − | |
| 4979 | − secno = GET_SEC_FROM_SEG(sbi, segno); | |
| 4980 | − seg_start = START_BLOCK(sbi, segno); | |
| 4981 | − dev_idx = f2fs_target_device_index(sbi, seg_start); | |
| 4982 | − zone_idx = get_zone_idx(sbi, secno, dev_idx); | |
| 4983 | − | |
| 4984 | − /* | |
| 4985 | − * Conventional zone's capacity is always equal to zone size, | |
| 4986 | − * so, blocks per segment is unchanged. | |
| 4987 | − */ | |
| 4988 | − if (is_conv_zone(sbi, zone_idx, dev_idx)) | |
| 4989 | − return sbi->blocks_per_seg; | |
| 5024 | + unsigned int secno; | |
| 4990 | 5025 | |
| 4991 | 5026 | if (!sbi->unusable_blocks_per_sec) |
| 4992 | 5027 | return sbi->blocks_per_seg; |
| 4993 | 5028 | |
| 5029 | + secno = GET_SEC_FROM_SEG(sbi, segno); | |
| 5030 | + seg_start = START_BLOCK(sbi, segno); | |
| 4994 | 5031 | sec_start_blkaddr = START_BLOCK(sbi, GET_SEG_FROM_SEC(sbi, secno)); |
| 4995 | 5032 | sec_cap_blkaddr = sec_start_blkaddr + CAP_BLKS_PER_SEC(sbi); |
| 4996 | 5033 | |
| @@ -5024,11 +5061,6 @@ static inline unsigned int f2fs_usable_zone_blks_in_seg(struct f2fs_sb_info *sbi · 27 unmodified lines | ||
| 5024 | 5061 | return 0; |
| 5025 | 5062 | } |
| 5026 | 5063 | |
| 5027 | −static inline unsigned int f2fs_usable_zone_segs_in_sec(struct f2fs_sb_info *sbi, | |
| 5028 | − unsigned int segno) | |
| 5029 | −{ | |
| 5030 | − return 0; | |
| 5031 | −} | |
| 5032 | 5064 | #endif |
| 5033 | 5065 | unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi, |
| 5034 | 5066 | unsigned int segno) |
| @@ -5043,7 +5075,7 @@ unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi, · 8 unmodified lines | ||
| 5043 | 5075 | unsigned int segno) |
| 5044 | 5076 | { |
| 5045 | 5077 | if (f2fs_sb_has_blkzoned(sbi)) |
| 5046 | − return f2fs_usable_zone_segs_in_sec(sbi, segno); | |
| 5078 | + return CAP_SEGS_PER_SEC(sbi); | |
| 5047 | 5079 | |
| 5048 | 5080 | return sbi->segs_per_sec; |
| 5049 | 5081 | } |
| @@ -104,6 +104,9 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi, · 103 unmodified lines | ||
| 104 | 104 | #define CAP_BLKS_PER_SEC(sbi) \ |
| 105 | 105 | ((sbi)->segs_per_sec * (sbi)->blocks_per_seg - \ |
| 106 | 106 | (sbi)->unusable_blocks_per_sec) |
| 107 | +#define CAP_SEGS_PER_SEC(sbi) \ | |
| 108 | + ((sbi)->segs_per_sec - ((sbi)->unusable_blocks_per_sec >>\ | |
| 109 | + (sbi)->log_blocks_per_seg)) | |
| 107 | 110 | #define GET_SEC_FROM_SEG(sbi, segno) \ |
| 108 | 111 | (((segno) == -1) ? -1: (segno) / (sbi)->segs_per_sec) |
| 109 | 112 | #define GET_SEG_FROM_SEC(sbi, secno) \ |
| @@ -286,7 +289,6 @@ enum dirty_type { · 176 unmodified lines | ||
| 286 | 289 | }; |
| 287 | 290 | |
| 288 | 291 | struct dirty_seglist_info { |
| 289 | − const struct victim_selection *v_ops; /* victim selction operation */ | |
| 290 | 292 | unsigned long *dirty_segmap[NR_DIRTY_TYPE]; |
| 291 | 293 | unsigned long *dirty_secmap; |
| 292 | 294 | struct mutex seglist_lock; /* lock for segment bitmaps */ |
| @@ -297,12 +299,6 @@ struct dirty_seglist_info { · 4 unmodified lines | ||
| 297 | 299 | bool enable_pin_section; /* enable pinning section */ |
| 298 | 300 | }; |
| 299 | 301 | |
| 300 | −/* victim selection function for cleaning and SSR */ | |
| 301 | −struct victim_selection { | |
| 302 | − int (*get_victim)(struct f2fs_sb_info *, unsigned int *, | |
| 303 | − int, int, char, unsigned long long); | |
| 304 | −}; | |
| 305 | − | |
| 306 | 302 | /* for active log information */ |
| 307 | 303 | struct curseg_info { |
| 308 | 304 | struct mutex curseg_mutex; /* lock for consistency */ |
| @@ -599,8 +595,12 @@ static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi, · 290 unmodified lines | ||
| 599 | 595 | return true; |
| 600 | 596 | } |
| 601 | 597 | |
| 602 | −static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, | |
| 603 | − int freed, int needed) | |
| 598 | +/* | |
| 599 | + * calculate needed sections for dirty node/dentry | |
| 600 | + * and call has_curseg_enough_space | |
| 601 | + */ | |
| 602 | +static inline void __get_secs_required(struct f2fs_sb_info *sbi, | |
| 603 | + unsigned int *lower_p, unsigned int *upper_p, bool *curseg_p) | |
| 604 | 604 | { |
| 605 | 605 | unsigned int total_node_blocks = get_pages(sbi, F2FS_DIRTY_NODES) + |
| 606 | 606 | get_pages(sbi, F2FS_DIRTY_DENTS) + |
| @@ -610,27 +610,50 @@ static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, · 3 unmodified lines | ||
| 610 | 610 | unsigned int dent_secs = total_dent_blocks / CAP_BLKS_PER_SEC(sbi); |
| 611 | 611 | unsigned int node_blocks = total_node_blocks % CAP_BLKS_PER_SEC(sbi); |
| 612 | 612 | unsigned int dent_blocks = total_dent_blocks % CAP_BLKS_PER_SEC(sbi); |
| 613 | − unsigned int free, need_lower, need_upper; | |
| 613 | + | |
| 614 | + if (lower_p) | |
| 615 | + *lower_p = node_secs + dent_secs; | |
| 616 | + if (upper_p) | |
| 617 | + *upper_p = node_secs + dent_secs + | |
| 618 | + (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0); | |
| 619 | + if (curseg_p) | |
| 620 | + *curseg_p = has_curseg_enough_space(sbi, | |
| 621 | + node_blocks, dent_blocks); | |
| 622 | +} | |
| 623 | + | |
| 624 | +static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, | |
| 625 | + int freed, int needed) | |
| 626 | +{ | |
| 627 | + unsigned int free_secs, lower_secs, upper_secs; | |
| 628 | + bool curseg_space; | |
| 614 | 629 | |
| 615 | 630 | if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) |
| 616 | 631 | return false; |
| 617 | 632 | |
| 618 | − free = free_sections(sbi) + freed; | |
| 619 | − need_lower = node_secs + dent_secs + reserved_sections(sbi) + needed; | |
| 620 | − need_upper = need_lower + (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0); | |
| 633 | + __get_secs_required(sbi, &lower_secs, &upper_secs, &curseg_space); | |
| 634 | + | |
| 635 | + free_secs = free_sections(sbi) + freed; | |
| 636 | + lower_secs += needed + reserved_sections(sbi); | |
| 637 | + upper_secs += needed + reserved_sections(sbi); | |
| 621 | 638 | |
| 622 | − if (free > need_upper) | |
| 639 | + if (free_secs > upper_secs) | |
| 623 | 640 | return false; |
| 624 | − else if (free <= need_lower) | |
| 641 | + else if (free_secs <= lower_secs) | |
| 625 | 642 | return true; |
| 626 | − return !has_curseg_enough_space(sbi, node_blocks, dent_blocks); | |
| 643 | + return !curseg_space; | |
| 644 | +} | |
| 645 | + | |
| 646 | +static inline bool has_enough_free_secs(struct f2fs_sb_info *sbi, | |
| 647 | + int freed, int needed) | |
| 648 | +{ | |
| 649 | + return !has_not_enough_free_secs(sbi, freed, needed); | |
| 627 | 650 | } |
| 628 | 651 | |
| 629 | 652 | static inline bool f2fs_is_checkpoint_ready(struct f2fs_sb_info *sbi) |
| 630 | 653 | { |
| 631 | 654 | if (likely(!is_sbi_flag_set(sbi, SBI_CP_DISABLED))) |
| 632 | 655 | return true; |
| 633 | − if (likely(!has_not_enough_free_secs(sbi, 0, 0))) | |
| 656 | + if (likely(has_enough_free_secs(sbi, 0, 0))) | |
| 634 | 657 | return true; |
| 635 | 658 | return false; |
| 636 | 659 | } |
| @@ -880,8 +880,8 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) · 879 unmodified lines | ||
| 880 | 880 | if (args->from && match_int(args, &arg)) |
| 881 | 881 | return -EINVAL; |
| 882 | 882 | if (arg <= 0 || arg > __ilog2_u32(BIO_MAX_VECS)) { |
| 883 | − f2fs_warn(sbi, "Not support %d, larger than %d", | |
| 884 | − 1 << arg, BIO_MAX_VECS); | |
| 883 | + f2fs_warn(sbi, "Not support %ld, larger than %d", | |
| 884 | + BIT(arg), BIO_MAX_VECS); | |
| 885 | 885 | return -EINVAL; |
| 886 | 886 | } |
| 887 | 887 | F2FS_OPTION(sbi).write_io_size_bits = arg; |
| @@ -1179,9 +1179,17 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) · 291 unmodified lines | ||
| 1179 | 1179 | kfree(name); |
| 1180 | 1180 | break; |
| 1181 | 1181 | case Opt_compress_chksum: |
| 1182 | + if (!f2fs_sb_has_compression(sbi)) { | |
| 1183 | + f2fs_info(sbi, "Image doesn't support compression"); | |
| 1184 | + break; | |
| 1185 | + } | |
| 1182 | 1186 | F2FS_OPTION(sbi).compress_chksum = true; |
| 1183 | 1187 | break; |
| 1184 | 1188 | case Opt_compress_mode: |
| 1189 | + if (!f2fs_sb_has_compression(sbi)) { | |
| 1190 | + f2fs_info(sbi, "Image doesn't support compression"); | |
| 1191 | + break; | |
| 1192 | + } | |
| 1185 | 1193 | name = match_strdup(&args[0]); |
| 1186 | 1194 | if (!name) |
| 1187 | 1195 | return -ENOMEM; |
| @@ -1196,6 +1204,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) · 8 unmodified lines | ||
| 1196 | 1204 | kfree(name); |
| 1197 | 1205 | break; |
| 1198 | 1206 | case Opt_compress_cache: |
| 1207 | + if (!f2fs_sb_has_compression(sbi)) { | |
| 1208 | + f2fs_info(sbi, "Image doesn't support compression"); | |
| 1209 | + break; | |
| 1210 | + } | |
| 1199 | 1211 | set_opt(sbi, COMPRESS_CACHE); |
| 1200 | 1212 | break; |
| 1201 | 1213 | #else |
| @@ -1310,7 +1322,7 @@ default_check: · 108 unmodified lines | ||
| 1310 | 1322 | #endif |
| 1311 | 1323 | |
| 1312 | 1324 | if (F2FS_IO_SIZE_BITS(sbi) && !f2fs_lfs_mode(sbi)) { |
| 1313 | − f2fs_err(sbi, "Should set mode=lfs with %uKB-sized IO", | |
| 1325 | + f2fs_err(sbi, "Should set mode=lfs with %luKB-sized IO", | |
| 1314 | 1326 | F2FS_IO_SIZE_KB(sbi)); |
| 1315 | 1327 | return -EINVAL; |
| 1316 | 1328 | } |
| @@ -2060,10 +2072,12 @@ static void default_options(struct f2fs_sb_info *sbi) · 743 unmodified lines | ||
| 2060 | 2072 | F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX; |
| 2061 | 2073 | F2FS_OPTION(sbi).s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID); |
| 2062 | 2074 | F2FS_OPTION(sbi).s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID); |
| 2063 | − F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZ4; | |
| 2064 | − F2FS_OPTION(sbi).compress_log_size = MIN_COMPRESS_LOG_SIZE; | |
| 2065 | − F2FS_OPTION(sbi).compress_ext_cnt = 0; | |
| 2066 | − F2FS_OPTION(sbi).compress_mode = COMPR_MODE_FS; | |
| 2075 | + if (f2fs_sb_has_compression(sbi)) { | |
| 2076 | + F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZ4; | |
| 2077 | + F2FS_OPTION(sbi).compress_log_size = MIN_COMPRESS_LOG_SIZE; | |
| 2078 | + F2FS_OPTION(sbi).compress_ext_cnt = 0; | |
| 2079 | + F2FS_OPTION(sbi).compress_mode = COMPR_MODE_FS; | |
| 2080 | + } | |
| 2067 | 2081 | F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON; |
| 2068 | 2082 | F2FS_OPTION(sbi).memory_mode = MEMORY_MODE_NORMAL; |
| 2069 | 2083 | |
| @@ -2274,7 +2288,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) · 204 unmodified lines | ||
| 2274 | 2288 | if (f2fs_readonly(sb) && (*flags & SB_RDONLY)) |
| 2275 | 2289 | goto skip; |
| 2276 | 2290 | |
| 2277 | − if (f2fs_sb_has_readonly(sbi) && !(*flags & SB_RDONLY)) { | |
| 2291 | + if (f2fs_dev_is_readonly(sbi) && !(*flags & SB_RDONLY)) { | |
| 2278 | 2292 | err = -EROFS; |
| 2279 | 2293 | goto restore_opts; |
| 2280 | 2294 | } |
| @@ -2487,6 +2501,54 @@ restore_opts: · 206 unmodified lines | ||
| 2487 | 2501 | } |
| 2488 | 2502 | |
| 2489 | 2503 | #ifdef CONFIG_QUOTA |
| 2504 | +static bool f2fs_need_recovery(struct f2fs_sb_info *sbi) | |
| 2505 | +{ | |
| 2506 | + /* need to recovery orphan */ | |
| 2507 | + if (is_set_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG)) | |
| 2508 | + return true; | |
| 2509 | + /* need to recovery data */ | |
| 2510 | + if (test_opt(sbi, DISABLE_ROLL_FORWARD)) | |
| 2511 | + return false; | |
| 2512 | + if (test_opt(sbi, NORECOVERY)) | |
| 2513 | + return false; | |
| 2514 | + return !is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG); | |
| 2515 | +} | |
| 2516 | + | |
| 2517 | +static bool f2fs_recover_quota_begin(struct f2fs_sb_info *sbi) | |
| 2518 | +{ | |
| 2519 | + bool readonly = f2fs_readonly(sbi->sb); | |
| 2520 | + | |
| 2521 | + if (!f2fs_need_recovery(sbi)) | |
| 2522 | + return false; | |
| 2523 | + | |
| 2524 | + /* it doesn't need to check f2fs_sb_has_readonly() */ | |
| 2525 | + if (f2fs_hw_is_readonly(sbi)) | |
| 2526 | + return false; | |
| 2527 | + | |
| 2528 | + if (readonly) { | |
| 2529 | + sbi->sb->s_flags &= ~SB_RDONLY; | |
| 2530 | + set_sbi_flag(sbi, SBI_IS_WRITABLE); | |
| 2531 | + } | |
| 2532 | + | |
| 2533 | + /* | |
| 2534 | + * Turn on quotas which were not enabled for read-only mounts if | |
| 2535 | + * filesystem has quota feature, so that they are updated correctly. | |
| 2536 | + */ | |
| 2537 | + return f2fs_enable_quota_files(sbi, readonly); | |
| 2538 | +} | |
| 2539 | + | |
| 2540 | +static void f2fs_recover_quota_end(struct f2fs_sb_info *sbi, | |
| 2541 | + bool quota_enabled) | |
| 2542 | +{ | |
| 2543 | + if (quota_enabled) | |
| 2544 | + f2fs_quota_off_umount(sbi->sb); | |
| 2545 | + | |
| 2546 | + if (is_sbi_flag_set(sbi, SBI_IS_WRITABLE)) { | |
| 2547 | + clear_sbi_flag(sbi, SBI_IS_WRITABLE); | |
| 2548 | + sbi->sb->s_flags |= SB_RDONLY; | |
| 2549 | + } | |
| 2550 | +} | |
| 2551 | + | |
| 2490 | 2552 | /* Read data from quotafile */ |
| 2491 | 2553 | static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, |
| 2492 | 2554 | size_t len, loff_t off) |
| @@ -3260,7 +3322,7 @@ static inline bool sanity_check_area_boundary(struct f2fs_sb_info *sbi, · 767 unmodified lines | ||
| 3260 | 3322 | raw_super->segment_count = cpu_to_le32((main_end_blkaddr - |
| 3261 | 3323 | segment0_blkaddr) >> log_blocks_per_seg); |
| 3262 | 3324 | |
| 3263 | − if (f2fs_readonly(sb) || bdev_read_only(sb->s_bdev)) { | |
| 3325 | + if (f2fs_readonly(sb) || f2fs_hw_is_readonly(sbi)) { | |
| 3264 | 3326 | set_sbi_flag(sbi, SBI_NEED_SB_WRITE); |
| 3265 | 3327 | res = "internally"; |
| 3266 | 3328 | } else { |
| @@ -3348,7 +3410,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, · 81 unmodified lines | ||
| 3348 | 3410 | total_sections = le32_to_cpu(raw_super->section_count); |
| 3349 | 3411 | |
| 3350 | 3412 | /* blocks_per_seg should be 512, given the above check */ |
| 3351 | − blocks_per_seg = 1 << le32_to_cpu(raw_super->log_blocks_per_seg); | |
| 3413 | + blocks_per_seg = BIT(le32_to_cpu(raw_super->log_blocks_per_seg)); | |
| 3352 | 3414 | |
| 3353 | 3415 | if (segment_count > F2FS_MAX_SEGMENT || |
| 3354 | 3416 | segment_count < F2FS_MIN_SEGMENTS) { |
| @@ -3617,9 +3679,9 @@ static void init_sb_info(struct f2fs_sb_info *sbi) · 262 unmodified lines | ||
| 3617 | 3679 | sbi->log_sectors_per_block = |
| 3618 | 3680 | le32_to_cpu(raw_super->log_sectors_per_block); |
| 3619 | 3681 | sbi->log_blocksize = le32_to_cpu(raw_super->log_blocksize); |
| 3620 | − sbi->blocksize = 1 << sbi->log_blocksize; | |
| 3682 | + sbi->blocksize = BIT(sbi->log_blocksize); | |
| 3621 | 3683 | sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg); |
| 3622 | − sbi->blocks_per_seg = 1 << sbi->log_blocks_per_seg; | |
| 3684 | + sbi->blocks_per_seg = BIT(sbi->log_blocks_per_seg); | |
| 3623 | 3685 | sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec); |
| 3624 | 3686 | sbi->secs_per_zone = le32_to_cpu(raw_super->secs_per_zone); |
| 3625 | 3687 | sbi->total_sections = le32_to_cpu(raw_super->section_count); |
| @@ -3744,12 +3806,8 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi) · 118 unmodified lines | ||
| 3744 | 3806 | SECTOR_TO_BLOCK(zone_sectors)) |
| 3745 | 3807 | return -EINVAL; |
| 3746 | 3808 | sbi->blocks_per_blkz = SECTOR_TO_BLOCK(zone_sectors); |
| 3747 | − if (sbi->log_blocks_per_blkz && sbi->log_blocks_per_blkz != | |
| 3748 | − __ilog2_u32(sbi->blocks_per_blkz)) | |
| 3749 | − return -EINVAL; | |
| 3750 | − sbi->log_blocks_per_blkz = __ilog2_u32(sbi->blocks_per_blkz); | |
| 3751 | − FDEV(devi).nr_blkz = SECTOR_TO_BLOCK(nr_sectors) >> | |
| 3752 | − sbi->log_blocks_per_blkz; | |
| 3809 | + FDEV(devi).nr_blkz = div_u64(SECTOR_TO_BLOCK(nr_sectors), | |
| 3810 | + sbi->blocks_per_blkz); | |
| 3753 | 3811 | if (nr_sectors & (zone_sectors - 1)) |
| 3754 | 3812 | FDEV(devi).nr_blkz++; |
| 3755 | 3813 | |
| @@ -3836,7 +3894,7 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) · 80 unmodified lines | ||
| 3836 | 3894 | int err; |
| 3837 | 3895 | |
| 3838 | 3896 | if ((recover && f2fs_readonly(sbi->sb)) || |
| 3839 | − bdev_read_only(sbi->sb->s_bdev)) { | |
| 3897 | + f2fs_hw_is_readonly(sbi)) { | |
| 3840 | 3898 | set_sbi_flag(sbi, SBI_NEED_SB_WRITE); |
| 3841 | 3899 | return -EROFS; |
| 3842 | 3900 | } |
| @@ -3875,7 +3933,7 @@ void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason) · 32 unmodified lines | ||
| 3875 | 3933 | |
| 3876 | 3934 | f2fs_down_write(&sbi->sb_lock); |
| 3877 | 3935 | |
| 3878 | − if (raw_super->s_stop_reason[reason] < ((1 << BITS_PER_BYTE) - 1)) | |
| 3936 | + if (raw_super->s_stop_reason[reason] < GENMASK(BITS_PER_BYTE - 1, 0)) | |
| 3879 | 3937 | raw_super->s_stop_reason[reason]++; |
| 3880 | 3938 | |
| 3881 | 3939 | err = f2fs_commit_super(sbi, false); |
| @@ -3885,7 +3943,7 @@ void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason) · 3 unmodified lines | ||
| 3885 | 3943 | f2fs_up_write(&sbi->sb_lock); |
| 3886 | 3944 | } |
| 3887 | 3945 | |
| 3888 | −static void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag) | |
| 3946 | +void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag) | |
| 3889 | 3947 | { |
| 3890 | 3948 | spin_lock(&sbi->error_lock); |
| 3891 | 3949 | if (!test_bit(flag, (unsigned long *)sbi->errors)) { |
| @@ -4025,7 +4083,7 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi) · 133 unmodified lines | ||
| 4025 | 4083 | FDEV(i).start_blk, FDEV(i).end_blk); |
| 4026 | 4084 | } |
| 4027 | 4085 | f2fs_info(sbi, |
| 4028 | − "IO Block Size: %8d KB", F2FS_IO_SIZE_KB(sbi)); | |
| 4086 | + "IO Block Size: %8ld KB", F2FS_IO_SIZE_KB(sbi)); | |
| 4029 | 4087 | return 0; |
| 4030 | 4088 | } |
| 4031 | 4089 | |
| @@ -4102,6 +4160,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) · 70 unmodified lines | ||
| 4102 | 4160 | int recovery, i, valid_super_block; |
| 4103 | 4161 | struct curseg_info *seg_i; |
| 4104 | 4162 | int retry_cnt = 1; |
| 4163 | +#ifdef CONFIG_QUOTA | |
| 4164 | + bool quota_enabled = false; | |
| 4165 | +#endif | |
| 4105 | 4166 | |
| 4106 | 4167 | try_onemore: |
| 4107 | 4168 | err = -EINVAL; |
| @@ -4395,6 +4456,8 @@ try_onemore: · 287 unmodified lines | ||
| 4395 | 4456 | if (err) |
| 4396 | 4457 | f2fs_err(sbi, "Cannot turn on quotas: error %d", err); |
| 4397 | 4458 | } |
| 4459 | + | |
| 4460 | + quota_enabled = f2fs_recover_quota_begin(sbi); | |
| 4398 | 4461 | #endif |
| 4399 | 4462 | /* if there are any orphan inodes, free them */ |
| 4400 | 4463 | err = f2fs_recover_orphan_inodes(sbi); |
| @@ -4452,6 +4515,10 @@ try_onemore: · 51 unmodified lines | ||
| 4452 | 4515 | } |
| 4453 | 4516 | } |
| 4454 | 4517 | |
| 4518 | +#ifdef CONFIG_QUOTA | |
| 4519 | + f2fs_recover_quota_end(sbi, quota_enabled); | |
| 4520 | +#endif | |
| 4521 | + | |
| 4455 | 4522 | /* |
| 4456 | 4523 | * If the f2fs is not readonly and fsync data recovery succeeds, |
| 4457 | 4524 | * check zoned block devices' write pointer consistency. |
| @@ -312,19 +312,14 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a, · 311 unmodified lines | ||
| 312 | 312 | |
| 313 | 313 | if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) { |
| 314 | 314 | struct ckpt_req_control *cprc = &sbi->cprc_info; |
| 315 | − int len = 0; | |
| 316 | 315 | int class = IOPRIO_PRIO_CLASS(cprc->ckpt_thread_ioprio); |
| 317 | 316 | int data = IOPRIO_PRIO_DATA(cprc->ckpt_thread_ioprio); |
| 318 | 317 | |
| 319 | − if (class == IOPRIO_CLASS_RT) | |
| 320 | − len += scnprintf(buf + len, PAGE_SIZE - len, "rt,"); | |
| 321 | − else if (class == IOPRIO_CLASS_BE) | |
| 322 | − len += scnprintf(buf + len, PAGE_SIZE - len, "be,"); | |
| 323 | − else | |
| 318 | + if (class != IOPRIO_CLASS_RT && class != IOPRIO_CLASS_BE) | |
| 324 | 319 | return -EINVAL; |
| 325 | 320 | |
| 326 | − len += scnprintf(buf + len, PAGE_SIZE - len, "%d\n", data); | |
| 327 | − return len; | |
| 321 | + return sysfs_emit(buf, "%s,%d\n", | |
| 322 | + class == IOPRIO_CLASS_RT ? "rt" : "be", data); | |
| 328 | 323 | } |
| 329 | 324 | |
| 330 | 325 | #ifdef CONFIG_F2FS_FS_COMPRESSION |
| @@ -452,7 +447,7 @@ out: · 121 unmodified lines | ||
| 452 | 447 | if (ret < 0) |
| 453 | 448 | return ret; |
| 454 | 449 | #ifdef CONFIG_F2FS_FAULT_INJECTION |
| 455 | − if (a->struct_type == FAULT_INFO_TYPE && t >= (1 << FAULT_MAX)) | |
| 450 | + if (a->struct_type == FAULT_INFO_TYPE && t >= BIT(FAULT_MAX)) | |
| 456 | 451 | return -EINVAL; |
| 457 | 452 | if (a->struct_type == FAULT_INFO_RATE && t >= UINT_MAX) |
| 458 | 453 | return -EINVAL; |
| @@ -575,9 +570,9 @@ out: · 116 unmodified lines | ||
| 575 | 570 | if (!strcmp(a->attr.name, "iostat_period_ms")) { |
| 576 | 571 | if (t < MIN_IOSTAT_PERIOD_MS || t > MAX_IOSTAT_PERIOD_MS) |
| 577 | 572 | return -EINVAL; |
| 578 | − spin_lock(&sbi->iostat_lock); | |
| 573 | + spin_lock_irq(&sbi->iostat_lock); | |
| 579 | 574 | sbi->iostat_period_ms = (unsigned int)t; |
| 580 | − spin_unlock(&sbi->iostat_lock); | |
| 575 | + spin_unlock_irq(&sbi->iostat_lock); | |
| 581 | 576 | return count; |
| 582 | 577 | } |
| 583 | 578 | #endif |
| @@ -598,6 +593,20 @@ out: · 14 unmodified lines | ||
| 598 | 593 | sbi->compr_new_inode = 0; |
| 599 | 594 | return count; |
| 600 | 595 | } |
| 596 | + | |
| 597 | + if (!strcmp(a->attr.name, "compress_percent")) { | |
| 598 | + if (t == 0 || t > 100) | |
| 599 | + return -EINVAL; | |
| 600 | + *ui = t; | |
| 601 | + return count; | |
| 602 | + } | |
| 603 | + | |
| 604 | + if (!strcmp(a->attr.name, "compress_watermark")) { | |
| 605 | + if (t == 0 || t > 100) | |
| 606 | + return -EINVAL; | |
| 607 | + *ui = t; | |
| 608 | + return count; | |
| 609 | + } | |
| 601 | 610 | #endif |
| 602 | 611 | |
| 603 | 612 | if (!strcmp(a->attr.name, "atgc_candidate_ratio")) { |
| @@ -950,6 +959,8 @@ F2FS_FEATURE_RO_ATTR(compression); · 346 unmodified lines | ||
| 950 | 959 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_written_block, compr_written_block); |
| 951 | 960 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_saved_block, compr_saved_block); |
| 952 | 961 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_new_inode, compr_new_inode); |
| 962 | +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compress_percent, compress_percent); | |
| 963 | +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compress_watermark, compress_watermark); | |
| 953 | 964 | #endif |
| 954 | 965 | F2FS_FEATURE_RO_ATTR(pin_file); |
| 955 | 966 | |
| @@ -1057,6 +1068,8 @@ static struct attribute *f2fs_attrs[] = { · 101 unmodified lines | ||
| 1057 | 1068 | ATTR_LIST(compr_written_block), |
| 1058 | 1069 | ATTR_LIST(compr_saved_block), |
| 1059 | 1070 | ATTR_LIST(compr_new_inode), |
| 1071 | + ATTR_LIST(compress_percent), | |
| 1072 | + ATTR_LIST(compress_watermark), | |
| 1060 | 1073 | #endif |
| 1061 | 1074 | /* For ATGC */ |
| 1062 | 1075 | ATTR_LIST(atgc_candidate_ratio), |
| @@ -1449,25 +1462,14 @@ put_sb_kobj: · 386 unmodified lines | ||
| 1449 | 1462 | |
| 1450 | 1463 | void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi) |
| 1451 | 1464 | { |
| 1452 | − if (sbi->s_proc) { | |
| 1453 | −#ifdef CONFIG_F2FS_IOSTAT | |
| 1454 | − remove_proc_entry("iostat_info", sbi->s_proc); | |
| 1455 | −#endif | |
| 1456 | − remove_proc_entry("segment_info", sbi->s_proc); | |
| 1457 | − remove_proc_entry("segment_bits", sbi->s_proc); | |
| 1458 | − remove_proc_entry("victim_bits", sbi->s_proc); | |
| 1459 | − remove_proc_entry("discard_plist_info", sbi->s_proc); | |
| 1460 | − remove_proc_entry(sbi->sb->s_id, f2fs_proc_root); | |
| 1461 | − } | |
| 1465 | + if (sbi->s_proc) | |
| 1466 | + remove_proc_subtree(sbi->sb->s_id, f2fs_proc_root); | |
| 1462 | 1467 | |
| 1463 | − kobject_del(&sbi->s_stat_kobj); | |
| 1464 | 1468 | kobject_put(&sbi->s_stat_kobj); |
| 1465 | 1469 | wait_for_completion(&sbi->s_stat_kobj_unregister); |
| 1466 | − kobject_del(&sbi->s_feature_list_kobj); | |
| 1467 | 1470 | kobject_put(&sbi->s_feature_list_kobj); |
| 1468 | 1471 | wait_for_completion(&sbi->s_feature_list_kobj_unregister); |
| 1469 | 1472 | |
| 1470 | − kobject_del(&sbi->s_kobj); | |
| 1471 | 1473 | kobject_put(&sbi->s_kobj); |
| 1472 | 1474 | wait_for_completion(&sbi->s_kobj_unregister); |
| 1473 | 1475 | } |
| @@ -40,9 +40,8 @@ · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | #define F2FS_ENC_UTF8_12_1 1 |
| 42 | 42 | |
| 43 | −#define F2FS_IO_SIZE(sbi) (1 << F2FS_OPTION(sbi).write_io_size_bits) /* Blocks */ | |
| 44 | −#define F2FS_IO_SIZE_KB(sbi) (1 << (F2FS_OPTION(sbi).write_io_size_bits + 2)) /* KB */ | |
| 45 | −#define F2FS_IO_SIZE_BYTES(sbi) (1 << (F2FS_OPTION(sbi).write_io_size_bits + 12)) /* B */ | |
| 43 | +#define F2FS_IO_SIZE(sbi) BIT(F2FS_OPTION(sbi).write_io_size_bits) /* Blocks */ | |
| 44 | +#define F2FS_IO_SIZE_KB(sbi) BIT(F2FS_OPTION(sbi).write_io_size_bits + 2) /* KB */ | |
| 46 | 45 | #define F2FS_IO_SIZE_BITS(sbi) (F2FS_OPTION(sbi).write_io_size_bits) /* power of 2 */ |
| 47 | 46 | #define F2FS_IO_SIZE_MASK(sbi) (F2FS_IO_SIZE(sbi) - 1) |
| 48 | 47 | #define F2FS_IO_ALIGNED(sbi) (F2FS_IO_SIZE(sbi) > 1) |
| @@ -340,7 +339,7 @@ enum { · 291 unmodified lines | ||
| 340 | 339 | OFFSET_BIT_SHIFT |
| 341 | 340 | }; |
| 342 | 341 | |
| 343 | −#define OFFSET_BIT_MASK (0x07) /* (0x01 << OFFSET_BIT_SHIFT) - 1 */ | |
| 342 | +#define OFFSET_BIT_MASK GENMASK(OFFSET_BIT_SHIFT - 1, 0) | |
| 344 | 343 | |
| 345 | 344 | struct node_footer { |
| 346 | 345 | __le32 nid; /* node id */ |
| @@ -545,7 +544,7 @@ typedef __le32 f2fs_hash_t; · 198 unmodified lines | ||
| 545 | 544 | #define MAX_DIR_HASH_DEPTH 63 |
| 546 | 545 | |
| 547 | 546 | /* MAX buckets in one level of dir */ |
| 548 | −#define MAX_DIR_BUCKETS (1 << ((MAX_DIR_HASH_DEPTH / 2) - 1)) | |
| 547 | +#define MAX_DIR_BUCKETS BIT((MAX_DIR_HASH_DEPTH / 2) - 1) | |
| 549 | 548 | |
| 550 | 549 | /* |
| 551 | 550 | * space utilization of regular dentry and inline dentry (w/o extra reservation) |
| @@ -585,21 +584,6 @@ struct f2fs_dentry_block { · 33 unmodified lines | ||
| 585 | 584 | __u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN]; |
| 586 | 585 | } __packed; |
| 587 | 586 | |
| 588 | −/* file types used in inode_info->flags */ | |
| 589 | −enum { | |
| 590 | − F2FS_FT_UNKNOWN, | |
| 591 | − F2FS_FT_REG_FILE, | |
| 592 | − F2FS_FT_DIR, | |
| 593 | − F2FS_FT_CHRDEV, | |
| 594 | − F2FS_FT_BLKDEV, | |
| 595 | − F2FS_FT_FIFO, | |
| 596 | − F2FS_FT_SOCK, | |
| 597 | − F2FS_FT_SYMLINK, | |
| 598 | − F2FS_FT_MAX | |
| 599 | −}; | |
| 600 | − | |
| 601 | −#define S_SHIFT 12 | |
| 602 | − | |
| 603 | 587 | #define F2FS_DEF_PROJID 0 /* default project ID */ |
| 604 | 588 | |
| 605 | 589 | #endif /* _LINUX_F2FS_FS_H */ |