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 | nat entries. By default, 1 is set, which indicates | 190 | nat entries. By default, 1 is set, which indicates |
| 191 | 10 MB / 1 GB RAM. | 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 | What: /sys/fs/f2fs/<disk>/cp_interval | 193 | What: /sys/fs/f2fs/<disk>/cp_interval |
| 200 | Date: October 2015 | 194 | Date: October 2015 |
| 201 | Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> | 195 | Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> |
| @@ -729,3 +723,20 @@ What: /sys/fs/f2fs/<disk>/last_age_weight · 527 unmodified lines | |||
| 729 | Date: January 2023 | 723 | Date: January 2023 |
| 730 | Contact: "Ping Xiong" <xiongping1@xiaomi.com> | 724 | Contact: "Ping Xiong" <xiongping1@xiaomi.com> |
| 731 | Description: When DATA SEPARATION is on, it controls the weight of last data block age. | 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 | disabled, any unmounting or unexpected shutdowns will cause | 264 | disabled, any unmounting or unexpected shutdowns will cause |
| 265 | the filesystem contents to appear as they did when the | 265 | the filesystem contents to appear as they did when the |
| 266 | filesystem was mounted with that option. | 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 | run garbage collection to ensure that all available space can | 268 | run garbage collection to ensure that all available space can |
| 269 | be used. If this takes too much time, the mount may return | 269 | be used. If this takes too much time, the mount may return |
| 270 | EAGAIN. You may optionally add a value to indicate how much | 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 | se = get_seg_entry(sbi, segno); | 152 | se = get_seg_entry(sbi, segno); |
| 153 | 153 | ||
| 154 | exist = f2fs_test_bit(offset, se->cur_valid_map); | 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 | if (exist && type == DATA_GENERIC_ENHANCE_UPDATE) { | 160 | if (exist && type == DATA_GENERIC_ENHANCE_UPDATE) { |
| 156 | f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d", | 161 | f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d", |
| 157 | blkaddr, exist); | 162 | blkaddr, exist); |
| @@ -202,6 +207,11 @@ bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi, · 44 unmodified lines | |||
| 202 | case DATA_GENERIC_ENHANCE_UPDATE: | 207 | case DATA_GENERIC_ENHANCE_UPDATE: |
| 203 | if (unlikely(blkaddr >= MAX_BLKADDR(sbi) || | 208 | if (unlikely(blkaddr >= MAX_BLKADDR(sbi) || |
| 204 | blkaddr < MAIN_BLKADDR(sbi))) { | 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 | f2fs_warn(sbi, "access invalid blkaddr:%u", | 215 | f2fs_warn(sbi, "access invalid blkaddr:%u", |
| 206 | blkaddr); | 216 | blkaddr); |
| 207 | set_sbi_flag(sbi, SBI_NEED_FSCK); | 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 | trace_f2fs_writepage(page, META); | 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 | goto redirty_out; | 345 | goto redirty_out; |
| 346 | } | ||
| 330 | if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) | 347 | if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) |
| 331 | goto redirty_out; | 348 | goto redirty_out; |
| 332 | if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0)) | 349 | if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0)) |
| @@ -508,6 +525,7 @@ retry: · 175 unmodified lines | |||
| 508 | if (!e) { | 525 | if (!e) { |
| 509 | if (!new) { | 526 | if (!new) { |
| 510 | spin_unlock(&im->ino_lock); | 527 | spin_unlock(&im->ino_lock); |
| 528 | radix_tree_preload_end(); | ||
| 511 | goto retry; | 529 | goto retry; |
| 512 | } | 530 | } |
| 513 | e = new; | 531 | e = new; |
| @@ -706,32 +724,18 @@ err_out: · 192 unmodified lines | |||
| 706 | int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi) | 724 | int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi) |
| 707 | { | 725 | { |
| 708 | block_t start_blk, orphan_blocks, i, j; | 726 | block_t start_blk, orphan_blocks, i, j; |
| 709 | unsigned int s_flags = sbi->sb->s_flags; | ||
| 710 | int err = 0; | 727 | int err = 0; |
| 711 | #ifdef CONFIG_QUOTA | ||
| 712 | int quota_enabled; | ||
| 713 | #endif | ||
| 714 | 728 | ||
| 715 | if (!is_set_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG)) | 729 | if (!is_set_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG)) |
| 716 | return 0; | 730 | return 0; |
| 717 | 731 | ||
| 718 | if (bdev_read_only(sbi->sb->s_bdev)) { | 732 | if (f2fs_hw_is_readonly(sbi)) { |
| 719 | f2fs_info(sbi, "write access unavailable, skipping orphan cleanup"); | 733 | f2fs_info(sbi, "write access unavailable, skipping orphan cleanup"); |
| 720 | return 0; | 734 | return 0; |
| 721 | } | 735 | } |
| 722 | 736 | ||
| 723 | if (s_flags & SB_RDONLY) { | 737 | if (is_sbi_flag_set(sbi, SBI_IS_WRITABLE)) |
| 724 | f2fs_info(sbi, "orphan cleanup on readonly fs"); | 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 | start_blk = __start_cp_addr(sbi) + 1 + __cp_payload(sbi); | 740 | start_blk = __start_cp_addr(sbi) + 1 + __cp_payload(sbi); |
| 737 | orphan_blocks = __start_sum_addr(sbi) - 1 - __cp_payload(sbi); | 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 | out: | 769 | out: |
| 766 | set_sbi_flag(sbi, SBI_IS_RECOVERED); | 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 | return err; | 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 | cp_blk_no = le32_to_cpu(fsb->cp_blkaddr); | 980 | cp_blk_no = le32_to_cpu(fsb->cp_blkaddr); |
| 984 | if (cur_page == cp2) | 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 | for (i = 1; i < cp_blks; i++) { | 984 | for (i = 1; i < cp_blks; i++) { |
| 988 | void *sit_bitmap_ptr; | 985 | void *sit_bitmap_ptr; |
| @@ -1133,7 +1130,7 @@ retry: · 144 unmodified lines | |||
| 1133 | goto retry; | 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 | struct list_head *head = &sbi->inode_list[DIRTY_META]; | 1135 | struct list_head *head = &sbi->inode_list[DIRTY_META]; |
| 1139 | struct inode *inode; | 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 | if (!get_pages(sbi, type)) | 1303 | if (!get_pages(sbi, type)) |
| 1307 | break; | 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 | break; | 1308 | break; |
| 1311 | 1309 | ||
| 1312 | if (type == F2FS_DIRTY_META) | 1310 | if (type == F2FS_DIRTY_META) |
| @@ -264,35 +264,21 @@ static void lz4_destroy_compress_ctx(struct compress_ctx *cc) · 263 unmodified lines | |||
| 264 | cc->private = NULL; | 264 | cc->private = NULL; |
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | #ifdef CONFIG_F2FS_FS_LZ4HC | 267 | static int lz4_compress_pages(struct compress_ctx *cc) |
| 268 | static int lz4hc_compress_pages(struct compress_ctx *cc) | ||
| 269 | { | 268 | { |
| 269 | int len = -EINVAL; | ||
| 270 | unsigned char level = F2FS_I(cc->inode)->i_compress_level; | 270 | unsigned char level = F2FS_I(cc->inode)->i_compress_level; |
| 271 | int len; | ||
| 272 | 271 | ||
| 273 | if (level) | 272 | if (!level) |
| 274 | len = LZ4_compress_HC(cc->rbuf, cc->cbuf->cdata, cc->rlen, | ||
| 275 | cc->clen, level, cc->private); | ||
| 276 | else | ||
| 277 | len = LZ4_compress_default(cc->rbuf, cc->cbuf->cdata, cc->rlen, | 273 | len = LZ4_compress_default(cc->rbuf, cc->cbuf->cdata, cc->rlen, |
| 278 | cc->clen, cc->private); | 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 | #ifdef CONFIG_F2FS_FS_LZ4HC | 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 | #endif | 279 | #endif |
| 294 | len = LZ4_compress_default(cc->rbuf, cc->cbuf->cdata, cc->rlen, | 280 | if (len < 0) |
| 295 | cc->clen, cc->private); | 281 | return len; |
| 296 | if (!len) | 282 | if (!len) |
| 297 | return -EAGAIN; | 283 | return -EAGAIN; |
| 298 | 284 | ||
| @@ -670,7 +656,7 @@ static int f2fs_compress_pages(struct compress_ctx *cc) · 371 unmodified lines | |||
| 670 | 656 | ||
| 671 | cc->cbuf->clen = cpu_to_le32(cc->clen); | 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 | chksum = f2fs_crc32(F2FS_I_SB(cc->inode), | 660 | chksum = f2fs_crc32(F2FS_I_SB(cc->inode), |
| 675 | cc->cbuf->cdata, cc->clen); | 661 | cc->cbuf->cdata, cc->clen); |
| 676 | cc->cbuf->chksum = cpu_to_le32(chksum); | 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 | if (dic->clen > PAGE_SIZE * dic->nr_cpages - COMPRESS_HEADER_SIZE) { | 742 | if (dic->clen > PAGE_SIZE * dic->nr_cpages - COMPRESS_HEADER_SIZE) { |
| 757 | ret = -EFSCORRUPTED; | 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 | goto out_release; | 750 | goto out_release; |
| 760 | } | 751 | } |
| 761 | 752 | ||
| 762 | ret = cops->decompress_pages(dic); | 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 | u32 provided = le32_to_cpu(dic->cbuf->chksum); | 756 | u32 provided = le32_to_cpu(dic->cbuf->chksum); |
| 766 | u32 calculated = f2fs_crc32(sbi, dic->cbuf->cdata, dic->clen); | 757 | u32 calculated = f2fs_crc32(sbi, dic->cbuf->cdata, dic->clen); |
| 767 | 758 | ||
| @@ -1456,6 +1447,12 @@ continue_unlock: · 688 unmodified lines | |||
| 1456 | if (!PageDirty(cc->rpages[i])) | 1447 | if (!PageDirty(cc->rpages[i])) |
| 1457 | goto continue_unlock; | 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 | if (!clear_page_dirty_for_io(cc->rpages[i])) | 1456 | if (!clear_page_dirty_for_io(cc->rpages[i])) |
| 1460 | goto continue_unlock; | 1457 | goto continue_unlock; |
| 1461 | 1458 | ||
| @@ -93,17 +93,17 @@ static enum count_type __read_io_type(struct page *page) · 92 unmodified lines | |||
| 93 | /* postprocessing steps for read bios */ | 93 | /* postprocessing steps for read bios */ |
| 94 | enum bio_post_read_step { | 94 | enum bio_post_read_step { |
| 95 | #ifdef CONFIG_FS_ENCRYPTION | 95 | #ifdef CONFIG_FS_ENCRYPTION |
| 96 | STEP_DECRYPT = 1 << 0, | 96 | STEP_DECRYPT = BIT(0), |
| 97 | #else | 97 | #else |
| 98 | STEP_DECRYPT = 0, /* compile out the decryption-related code */ | 98 | STEP_DECRYPT = 0, /* compile out the decryption-related code */ |
| 99 | #endif | 99 | #endif |
| 100 | #ifdef CONFIG_F2FS_FS_COMPRESSION | 100 | #ifdef CONFIG_F2FS_FS_COMPRESSION |
| 101 | STEP_DECOMPRESS = 1 << 1, | 101 | STEP_DECOMPRESS = BIT(1), |
| 102 | #else | 102 | #else |
| 103 | STEP_DECOMPRESS = 0, /* compile out the decompression-related code */ | 103 | STEP_DECOMPRESS = 0, /* compile out the decompression-related code */ |
| 104 | #endif | 104 | #endif |
| 105 | #ifdef CONFIG_FS_VERITY | 105 | #ifdef CONFIG_FS_VERITY |
| 106 | STEP_VERITY = 1 << 2, | 106 | STEP_VERITY = BIT(2), |
| 107 | #else | 107 | #else |
| 108 | STEP_VERITY = 0, /* compile out the verity-related code */ | 108 | STEP_VERITY = 0, /* compile out the verity-related code */ |
| 109 | #endif | 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 | static blk_opf_t f2fs_io_flags(struct f2fs_io_info *fio) | 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 | unsigned int fua_flag, meta_flag, io_flag; | 424 | unsigned int fua_flag, meta_flag, io_flag; |
| 425 | blk_opf_t op_flags = 0; | 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 | * 5 | 4 | 3 | 2 | 1 | 0 | | 442 | * 5 | 4 | 3 | 2 | 1 | 0 | |
| 443 | * Cold | Warm | Hot | Cold | Warm | Hot | | 443 | * Cold | Warm | Hot | Cold | Warm | Hot | |
| 444 | */ | 444 | */ |
| 445 | if ((1 << fio->temp) & meta_flag) | 445 | if (BIT(fio->temp) & meta_flag) |
| 446 | op_flags |= REQ_META; | 446 | op_flags |= REQ_META; |
| 447 | if ((1 << fio->temp) & fua_flag) | 447 | if (BIT(fio->temp) & fua_flag) |
| 448 | op_flags |= REQ_FUA; | 448 | op_flags |= REQ_FUA; |
| 449 | return op_flags; | 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 | bool found = false; | 874 | bool found = false; |
| 875 | struct bio *target = bio ? *bio : NULL; | 875 | struct bio *target = bio ? *bio : NULL; |
| 876 | 876 | ||
| 877 | f2fs_bug_on(sbi, !target && !page); | ||
| 878 | |||
| 877 | for (temp = HOT; temp < NR_TEMP_TYPE && !found; temp++) { | 879 | for (temp = HOT; temp < NR_TEMP_TYPE && !found; temp++) { |
| 878 | struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; | 880 | struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; |
| 879 | struct list_head *head = &io->bio_list; | 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 | if (ret) | 2237 | if (ret) |
| 2236 | goto out; | 2238 | goto out; |
| 2237 | 2239 | ||
| 2240 | if (unlikely(f2fs_cp_error(sbi))) { | ||
| 2241 | ret = -EIO; | ||
| 2242 | goto out_put_dnode; | ||
| 2243 | } | ||
| 2238 | f2fs_bug_on(sbi, dn.data_blkaddr != COMPRESS_ADDR); | 2244 | f2fs_bug_on(sbi, dn.data_blkaddr != COMPRESS_ADDR); |
| 2239 | 2245 | ||
| 2240 | skip_reading_dnode: | 2246 | skip_reading_dnode: |
| @@ -2798,7 +2804,8 @@ int f2fs_write_single_data_page(struct page *page, int *submitted, · 557 unmodified lines | |||
| 2798 | * don't drop any dirty dentry pages for keeping lastest | 2804 | * don't drop any dirty dentry pages for keeping lastest |
| 2799 | * directory structure. | 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 | goto redirty_out; | 2809 | goto redirty_out; |
| 2803 | goto out; | 2810 | goto out; |
| 2804 | } | 2811 | } |
| @@ -2898,7 +2905,8 @@ out: · 93 unmodified lines | |||
| 2898 | 2905 | ||
| 2899 | if (unlikely(f2fs_cp_error(sbi))) { | 2906 | if (unlikely(f2fs_cp_error(sbi))) { |
| 2900 | f2fs_submit_merged_write(sbi, DATA); | 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 | submitted = NULL; | 2910 | submitted = NULL; |
| 2903 | } | 2911 | } |
| 2904 | 2912 | ||
| @@ -3123,12 +3131,9 @@ continue_unlock: · 218 unmodified lines | |||
| 3123 | } | 3131 | } |
| 3124 | 3132 | ||
| 3125 | if (folio_test_writeback(folio)) { | 3133 | if (folio_test_writeback(folio)) { |
| 3126 | if (wbc->sync_mode != WB_SYNC_NONE) | 3134 | if (wbc->sync_mode == WB_SYNC_NONE) |
| 3127 | f2fs_wait_on_page_writeback( | ||
| 3128 | &folio->page, | ||
| 3129 | DATA, true, true); | ||
| 3130 | else | ||
| 3131 | goto continue_unlock; | 3135 | goto continue_unlock; |
| 3136 | f2fs_wait_on_page_writeback(&folio->page, DATA, true, true); | ||
| 3132 | } | 3137 | } |
| 3133 | 3138 | ||
| 3134 | if (!folio_clear_dirty_for_io(folio)) | 3139 | if (!folio_clear_dirty_for_io(folio)) |
| @@ -3486,7 +3491,7 @@ unlock_out: · 351 unmodified lines | |||
| 3486 | 3491 | ||
| 3487 | static int prepare_atomic_write_begin(struct f2fs_sb_info *sbi, | 3492 | static int prepare_atomic_write_begin(struct f2fs_sb_info *sbi, |
| 3488 | struct page *page, loff_t pos, unsigned int len, | 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 | struct inode *inode = page->mapping->host; | 3496 | struct inode *inode = page->mapping->host; |
| 3492 | struct inode *cow_inode = F2FS_I(inode)->cow_inode; | 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 | /* Look for the block in COW inode first */ | 3506 | /* Look for the block in COW inode first */ |
| 3502 | err = __find_data_block(cow_inode, index, blk_addr); | 3507 | err = __find_data_block(cow_inode, index, blk_addr); |
| 3503 | if (err) | 3508 | if (err) { |
| 3504 | return err; | 3509 | return err; |
| 3505 | else if (*blk_addr != NULL_ADDR) | 3510 | } else if (*blk_addr != NULL_ADDR) { |
| 3511 | *use_cow = true; | ||
| 3506 | return 0; | 3512 | return 0; |
| 3513 | } | ||
| 3507 | 3514 | ||
| 3508 | if (is_inode_flag_set(inode, FI_ATOMIC_REPLACE)) | 3515 | if (is_inode_flag_set(inode, FI_ATOMIC_REPLACE)) |
| 3509 | goto reserve_block; | 3516 | goto reserve_block; |
| @@ -3533,6 +3540,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, · 23 unmodified lines | |||
| 3533 | struct page *page = NULL; | 3540 | struct page *page = NULL; |
| 3534 | pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT; | 3541 | pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT; |
| 3535 | bool need_balance = false; | 3542 | bool need_balance = false; |
| 3543 | bool use_cow = false; | ||
| 3536 | block_t blkaddr = NULL_ADDR; | 3544 | block_t blkaddr = NULL_ADDR; |
| 3537 | int err = 0; | 3545 | int err = 0; |
| 3538 | 3546 | ||
| @@ -3592,7 +3600,7 @@ repeat: · 53 unmodified lines | |||
| 3592 | 3600 | ||
| 3593 | if (f2fs_is_atomic_file(inode)) | 3601 | if (f2fs_is_atomic_file(inode)) |
| 3594 | err = prepare_atomic_write_begin(sbi, page, pos, len, | 3602 | err = prepare_atomic_write_begin(sbi, page, pos, len, |
| 3595 | &blkaddr, &need_balance); | 3603 | &blkaddr, &need_balance, &use_cow); |
| 3596 | else | 3604 | else |
| 3597 | err = prepare_write_begin(sbi, page, pos, len, | 3605 | err = prepare_write_begin(sbi, page, pos, len, |
| 3598 | &blkaddr, &need_balance); | 3606 | &blkaddr, &need_balance); |
| @@ -3632,7 +3640,9 @@ repeat: · 33 unmodified lines | |||
| 3632 | f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR); | 3640 | f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR); |
| 3633 | goto fail; | 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 | if (err) | 3646 | if (err) |
| 3637 | goto fail; | 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 | f2fs_remove_dirty_inode(inode); | 3735 | f2fs_remove_dirty_inode(inode); |
| 3726 | } | 3736 | } |
| 3727 | } | 3737 | } |
| 3728 | 3738 | clear_page_private_all(&folio->page); | |
| 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); | ||
| 3737 | } | 3739 | } |
| 3738 | 3740 | ||
| 3739 | bool f2fs_release_folio(struct folio *folio, gfp_t wait) | 3741 | bool f2fs_release_folio(struct folio *folio, gfp_t wait) |
| 3740 | { | 3742 | { |
| 3741 | struct f2fs_sb_info *sbi; | ||
| 3742 | |||
| 3743 | /* If this is dirty folio, keep private data */ | 3743 | /* If this is dirty folio, keep private data */ |
| 3744 | if (folio_test_dirty(folio)) | 3744 | if (folio_test_dirty(folio)) |
| 3745 | return false; | 3745 | return false; |
| 3746 | 3746 | ||
| 3747 | sbi = F2FS_M_SB(folio->mapping); | 3747 | clear_page_private_all(&folio->page); |
| 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); | ||
| 3759 | return true; | 3748 | return true; |
| 3760 | } | 3749 | } |
| 3761 | 3750 | ||
| @@ -336,22 +336,23 @@ get_cache: · 335 unmodified lines | |||
| 336 | #endif | 336 | #endif |
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | static char *s_flag[] = { | 339 | static const char *s_flag[MAX_SBI_FLAG] = { |
| 340 | [SBI_IS_DIRTY] = " fs_dirty", | 340 | [SBI_IS_DIRTY] = "fs_dirty", |
| 341 | [SBI_IS_CLOSE] = " closing", | 341 | [SBI_IS_CLOSE] = "closing", |
| 342 | [SBI_NEED_FSCK] = " need_fsck", | 342 | [SBI_NEED_FSCK] = "need_fsck", |
| 343 | [SBI_POR_DOING] = " recovering", | 343 | [SBI_POR_DOING] = "recovering", |
| 344 | [SBI_NEED_SB_WRITE] = " sb_dirty", | 344 | [SBI_NEED_SB_WRITE] = "sb_dirty", |
| 345 | [SBI_NEED_CP] = " need_cp", | 345 | [SBI_NEED_CP] = "need_cp", |
| 346 | [SBI_IS_SHUTDOWN] = " shutdown", | 346 | [SBI_IS_SHUTDOWN] = "shutdown", |
| 347 | [SBI_IS_RECOVERED] = " recovered", | 347 | [SBI_IS_RECOVERED] = "recovered", |
| 348 | [SBI_CP_DISABLED] = " cp_disabled", | 348 | [SBI_CP_DISABLED] = "cp_disabled", |
| 349 | [SBI_CP_DISABLED_QUICK] = " cp_disabled_quick", | 349 | [SBI_CP_DISABLED_QUICK] = "cp_disabled_quick", |
| 350 | [SBI_QUOTA_NEED_FLUSH] = " quota_need_flush", | 350 | [SBI_QUOTA_NEED_FLUSH] = "quota_need_flush", |
| 351 | [SBI_QUOTA_SKIP_FLUSH] = " quota_skip_flush", | 351 | [SBI_QUOTA_SKIP_FLUSH] = "quota_skip_flush", |
| 352 | [SBI_QUOTA_NEED_REPAIR] = " quota_need_repair", | 352 | [SBI_QUOTA_NEED_REPAIR] = "quota_need_repair", |
| 353 | [SBI_IS_RESIZEFS] = " resizefs", | 353 | [SBI_IS_RESIZEFS] = "resizefs", |
| 354 | [SBI_IS_FREEZING] = " freezefs", | 354 | [SBI_IS_FREEZING] = "freezefs", |
| 355 | [SBI_IS_WRITABLE] = "writable", | ||
| 355 | }; | 356 | }; |
| 356 | 357 | ||
| 357 | static const char *ipu_mode_names[F2FS_IPU_MAX] = { | 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 | "Disabled" : (f2fs_cp_error(sbi) ? "Error" : "Good")); | 385 | "Disabled" : (f2fs_cp_error(sbi) ? "Error" : "Good")); |
| 385 | if (sbi->s_flag) { | 386 | if (sbi->s_flag) { |
| 386 | seq_puts(s, "[SBI:"); | 387 | seq_puts(s, "[SBI:"); |
| 387 | for_each_set_bit(j, &sbi->s_flag, 32) | 388 | for_each_set_bit(j, &sbi->s_flag, MAX_SBI_FLAG) |
| 388 | seq_puts(s, s_flag[j]); | 389 | seq_printf(s, " %s", s_flag[j]); |
| 389 | seq_puts(s, "]\n"); | 390 | seq_puts(s, "]\n"); |
| 390 | } | 391 | } |
| 391 | seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ", | 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 | static unsigned int dir_buckets(unsigned int level, int dir_level) | 29 | static unsigned int dir_buckets(unsigned int level, int dir_level) |
| 30 | { | 30 | { |
| 31 | if (level + dir_level < MAX_DIR_HASH_DEPTH / 2) | 31 | if (level + dir_level < MAX_DIR_HASH_DEPTH / 2) |
| 32 | return 1 << (level + dir_level); | 32 | return BIT(level + dir_level); |
| 33 | else | 33 | else |
| 34 | return MAX_DIR_BUCKETS; | 34 | return MAX_DIR_BUCKETS; |
| 35 | } | 35 | } |
| @@ -42,39 +42,6 @@ static unsigned int bucket_blocks(unsigned int level) · 6 unmodified lines | |||
| 42 | return 4; | 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 | /* If @dir is casefolded, initialize @fname->cf_name from @fname->usr_fname. */ | 45 | /* If @dir is casefolded, initialize @fname->cf_name from @fname->usr_fname. */ |
| 79 | int f2fs_init_casefolded_name(const struct inode *dir, | 46 | int f2fs_init_casefolded_name(const struct inode *dir, |
| 80 | struct f2fs_filename *fname) | 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 | lock_page(page); | 452 | lock_page(page); |
| 486 | f2fs_wait_on_page_writeback(page, type, true, true); | 453 | f2fs_wait_on_page_writeback(page, type, true, true); |
| 487 | de->ino = cpu_to_le32(inode->i_ino); | 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 | set_page_dirty(page); | 456 | set_page_dirty(page); |
| 490 | 457 | ||
| 491 | dir->i_mtime = dir->i_ctime = current_time(dir); | 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 | de->name_len = cpu_to_le16(name->len); | 666 | de->name_len = cpu_to_le16(name->len); |
| 700 | memcpy(d->filename[bit_pos], name->name, name->len); | 667 | memcpy(d->filename[bit_pos], name->name, name->len); |
| 701 | de->ino = cpu_to_le32(ino); | 668 | de->ino = cpu_to_le32(ino); |
| 702 | set_de_type(de, mode); | 669 | de->file_type = fs_umode_to_ftype(mode); |
| 703 | for (i = 0; i < slots; i++) { | 670 | for (i = 0; i < slots; i++) { |
| 704 | __set_bit_le(bit_pos + i, (void *)d->bitmap); | 671 | __set_bit_le(bit_pos + i, (void *)d->bitmap); |
| 705 | /* avoid wrong garbage data for readdir */ | 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 | f2fs_clear_page_cache_dirty_tag(page); | 905 | f2fs_clear_page_cache_dirty_tag(page); |
| 939 | clear_page_dirty_for_io(page); | 906 | clear_page_dirty_for_io(page); |
| 940 | ClearPageUptodate(page); | 907 | ClearPageUptodate(page); |
| 941 | 908 | clear_page_private_all(page); | |
| 942 | clear_page_private_gcing(page); | ||
| 943 | 909 | ||
| 944 | inode_dec_dirty_pages(dir); | 910 | inode_dec_dirty_pages(dir); |
| 945 | f2fs_remove_dirty_inode(dir); | 911 | f2fs_remove_dirty_inode(dir); |
| 946 | |||
| 947 | detach_page_private(page); | ||
| 948 | set_page_private(page, 0); | ||
| 949 | } | 912 | } |
| 950 | f2fs_put_page(page, 1); | 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 | continue; | 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 | de_name.name = d->filename[bit_pos]; | 1004 | de_name.name = d->filename[bit_pos]; |
| 1042 | de_name.len = le16_to_cpu(de->name_len); | 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 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | 24 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
| 25 | struct f2fs_inode_info *fi = F2FS_I(inode); | 25 | struct f2fs_inode_info *fi = F2FS_I(inode); |
| 26 | struct extent_tree *et = fi->extent_tree[EX_READ]; | ||
| 26 | struct extent_info *ei; | 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 | return true; | 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 && | 43 | if (!f2fs_is_valid_blkaddr(sbi, ei->blk, DATA_GENERIC_ENHANCE) || |
| 34 | (!f2fs_is_valid_blkaddr(sbi, ei->blk, | 44 | !f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1, |
| 35 | DATA_GENERIC_ENHANCE) || | 45 | DATA_GENERIC_ENHANCE)) { |
| 36 | !f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1, | ||
| 37 | DATA_GENERIC_ENHANCE))) { | ||
| 38 | set_sbi_flag(sbi, SBI_NEED_FSCK); | 46 | set_sbi_flag(sbi, SBI_NEED_FSCK); |
| 39 | f2fs_warn(sbi, "%s: inode (ino=%lx) extent info [%u, %u, %u] is incorrect, run fsck to fix", | 47 | f2fs_warn(sbi, "%s: inode (ino=%lx) extent info [%u, %u, %u] is incorrect, run fsck to fix", |
| 40 | __func__, inode->i_ino, | 48 | __func__, inode->i_ino, |
| @@ -86,7 +94,6 @@ static bool __may_age_extent_tree(struct inode *inode) · 45 unmodified lines | |||
| 86 | 94 | ||
| 87 | if (!test_opt(sbi, AGE_EXTENT_CACHE)) | 95 | if (!test_opt(sbi, AGE_EXTENT_CACHE)) |
| 88 | return false; | 96 | return false; |
| 89 | /* don't cache block age info for cold file */ | ||
| 90 | if (is_inode_flag_set(inode, FI_COMPRESSED_FILE)) | 97 | if (is_inode_flag_set(inode, FI_COMPRESSED_FILE)) |
| 91 | return false; | 98 | return false; |
| 92 | if (file_is_cold(inode)) | 99 | if (file_is_cold(inode)) |
| @@ -161,118 +168,52 @@ static bool __is_front_mergeable(struct extent_info *cur, · 68 unmodified lines | |||
| 161 | return __is_extent_mergeable(cur, front, type); | 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, | 171 | static struct extent_node *__lookup_extent_node(struct rb_root_cached *root, |
| 165 | unsigned int ofs) | 172 | struct extent_node *cached_en, unsigned int fofs) |
| 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) | ||
| 178 | { | 173 | { |
| 179 | struct rb_node *node = root->rb_root.rb_node; | 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 | while (node) { | 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 | node = node->rb_left; | 187 | node = node->rb_left; |
| 187 | else if (ofs >= re->ofs + re->len) | 188 | else if (fofs >= en->ei.fofs + en->ei.len) |
| 188 | node = node->rb_right; | 189 | node = node->rb_right; |
| 189 | else | 190 | else |
| 190 | return re; | 191 | return en; |
| 191 | } | 192 | } |
| 192 | return NULL; | 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 | * if hit, return the entry, otherwise, return NULL | 198 | * if hit, return the entry, otherwise, return NULL |
| 258 | * @prev_ex: extent before ofs | 199 | * @prev_ex: extent before fofs |
| 259 | * @next_ex: extent after ofs | 200 | * @next_ex: extent after fofs |
| 260 | * @insert_p: insert point for new extent at ofs | 201 | * @insert_p: insert point for new extent at fofs |
| 261 | * in order to simplify the insertion after. | 202 | * in order to simplify the insertion after. |
| 262 | * tree must stay unchanged between lookup and insertion. | 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, | 205 | static struct extent_node *__lookup_extent_node_ret(struct rb_root_cached *root, |
| 265 | struct rb_entry *cached_re, | 206 | struct extent_node *cached_en, |
| 266 | unsigned int ofs, | 207 | unsigned int fofs, |
| 267 | struct rb_entry **prev_entry, | 208 | struct extent_node **prev_entry, |
| 268 | struct rb_entry **next_entry, | 209 | struct extent_node **next_entry, |
| 269 | struct rb_node ***insert_p, | 210 | struct rb_node ***insert_p, |
| 270 | struct rb_node **insert_parent, | 211 | struct rb_node **insert_parent, |
| 271 | bool force, bool *leftmost) | 212 | bool *leftmost) |
| 272 | { | 213 | { |
| 273 | struct rb_node **pnode = &root->rb_root.rb_node; | 214 | struct rb_node **pnode = &root->rb_root.rb_node; |
| 274 | struct rb_node *parent = NULL, *tmp_node; | 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 | *insert_p = NULL; | 218 | *insert_p = NULL; |
| 278 | *insert_parent = NULL; | 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 | if (RB_EMPTY_ROOT(&root->rb_root)) | 223 | if (RB_EMPTY_ROOT(&root->rb_root)) |
| 283 | return NULL; | 224 | return NULL; |
| 284 | 225 | ||
| 285 | if (re) { | 226 | if (en && en->ei.fofs <= fofs && en->ei.fofs + en->ei.len > fofs) |
| 286 | if (re->ofs <= ofs && re->ofs + re->len > ofs) | 227 | goto lookup_neighbors; |
| 287 | goto lookup_neighbors; | ||
| 288 | } | ||
| 289 | 228 | ||
| 290 | if (leftmost) | 229 | *leftmost = true; |
| 291 | *leftmost = true; | ||
| 292 | 230 | ||
| 293 | while (*pnode) { | 231 | while (*pnode) { |
| 294 | parent = *pnode; | 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 | pnode = &(*pnode)->rb_left; | 236 | pnode = &(*pnode)->rb_left; |
| 299 | } else if (ofs >= re->ofs + re->len) { | 237 | } else if (fofs >= en->ei.fofs + en->ei.len) { |
| 300 | pnode = &(*pnode)->rb_right; | 238 | pnode = &(*pnode)->rb_right; |
| 301 | if (leftmost) | 239 | *leftmost = false; |
| 302 | *leftmost = false; | ||
| 303 | } else { | 240 | } else { |
| 304 | goto lookup_neighbors; | 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 | *insert_p = pnode; | 245 | *insert_p = pnode; |
| 309 | *insert_parent = parent; | 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 | tmp_node = parent; | 249 | tmp_node = parent; |
| 313 | if (parent && ofs > re->ofs) | 250 | if (parent && fofs > en->ei.fofs) |
| 314 | tmp_node = rb_next(parent); | 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 | tmp_node = parent; | 254 | tmp_node = parent; |
| 318 | if (parent && ofs < re->ofs) | 255 | if (parent && fofs < en->ei.fofs) |
| 319 | tmp_node = rb_prev(parent); | 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 | return NULL; | 258 | return NULL; |
| 322 | 259 | ||
| 323 | lookup_neighbors: | 260 | lookup_neighbors: |
| 324 | if (ofs == re->ofs || force) { | 261 | if (fofs == en->ei.fofs) { |
| 325 | /* lookup prev node for merging backward later */ | 262 | /* lookup prev node for merging backward later */ |
| 326 | tmp_node = rb_prev(&re->rb_node); | 263 | tmp_node = rb_prev(&en->rb_node); |
| 327 | *prev_entry = rb_entry_safe(tmp_node, struct rb_entry, 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 | /* lookup next node for merging frontward later */ | 268 | /* lookup next node for merging frontward later */ |
| 331 | tmp_node = rb_next(&re->rb_node); | 269 | tmp_node = rb_next(&en->rb_node); |
| 332 | *next_entry = rb_entry_safe(tmp_node, struct rb_entry, rb_node); | 270 | *next_entry = rb_entry_safe(tmp_node, |
| 333 | } | 271 | struct extent_node, rb_node); |
| 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; | ||
| 373 | } | 272 | } |
| 374 | #endif | 273 | return en; |
| 375 | return true; | ||
| 376 | } | 274 | } |
| 377 | 275 | ||
| 378 | static struct kmem_cache *extent_tree_slab; | 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 | goto out; | 485 | goto out; |
| 588 | } | 486 | } |
| 589 | 487 | ||
| 590 | en = (struct extent_node *)f2fs_lookup_rb_tree(&et->root, | 488 | en = __lookup_extent_node(&et->root, et->cached_en, pgofs); |
| 591 | (struct rb_entry *)et->cached_en, pgofs); | ||
| 592 | if (!en) | 489 | if (!en) |
| 593 | goto out; | 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 | bool leftmost) | 559 | bool leftmost) |
| 663 | { | 560 | { |
| 664 | struct extent_tree_info *eti = &sbi->extent_tree[et->type]; | 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 | struct rb_node *parent = NULL; | 563 | struct rb_node *parent = NULL; |
| 667 | struct extent_node *en = NULL; | 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 | leftmost = true; | 572 | leftmost = true; |
| 676 | 573 | ||
| 677 | p = f2fs_lookup_rb_tree_for_insert(sbi, &et->root, &parent, | 574 | /* look up extent_node in the rb tree */ |
| 678 | ei->fofs, &leftmost); | 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 | do_insert: | 589 | do_insert: |
| 680 | en = __attach_extent_node(sbi, et, ei, parent, p, leftmost); | 590 | en = __attach_extent_node(sbi, et, ei, parent, p, leftmost); |
| 681 | if (!en) | 591 | if (!en) |
| @@ -734,11 +644,10 @@ static void __update_extent_tree_range(struct inode *inode, · 52 unmodified lines | |||
| 734 | } | 644 | } |
| 735 | 645 | ||
| 736 | /* 1. lookup first extent node in range [fofs, fofs + len - 1] */ | 646 | /* 1. lookup first extent node in range [fofs, fofs + len - 1] */ |
| 737 | en = (struct extent_node *)f2fs_lookup_rb_tree_ret(&et->root, | 647 | en = __lookup_extent_node_ret(&et->root, |
| 738 | (struct rb_entry *)et->cached_en, fofs, | 648 | et->cached_en, fofs, |
| 739 | (struct rb_entry **)&prev_en, | 649 | &prev_en, &next_en, |
| 740 | (struct rb_entry **)&next_en, | 650 | &insert_p, &insert_parent, |
| 741 | &insert_p, &insert_parent, false, | ||
| 742 | &leftmost); | 651 | &leftmost); |
| 743 | if (!en) | 652 | if (!en) |
| 744 | en = next_en; | 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 | write_lock(&et->lock); | 786 | write_lock(&et->lock); |
| 878 | 787 | ||
| 879 | en = (struct extent_node *)f2fs_lookup_rb_tree_ret(&et->root, | 788 | en = __lookup_extent_node_ret(&et->root, |
| 880 | (struct rb_entry *)et->cached_en, fofs, | 789 | et->cached_en, fofs, |
| 881 | (struct rb_entry **)&prev_en, | 790 | &prev_en, &next_en, |
| 882 | (struct rb_entry **)&next_en, | 791 | &insert_p, &insert_parent, |
| 883 | &insert_p, &insert_parent, false, | 792 | &leftmost); |
| 884 | &leftmost); | ||
| 885 | if (en) | 793 | if (en) |
| 886 | goto unlock_out; | 794 | goto unlock_out; |
| 887 | 795 | ||
| @@ -65,7 +65,7 @@ enum { · 64 unmodified lines | |||
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | #ifdef CONFIG_F2FS_FAULT_INJECTION | 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 | struct f2fs_fault_info { | 70 | struct f2fs_fault_info { |
| 71 | atomic_t inject_ops; | 71 | atomic_t inject_ops; |
| @@ -74,7 +74,7 @@ struct f2fs_fault_info { · 2 unmodified lines | |||
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| 76 | extern const char *f2fs_fault_name[FAULT_MAX]; | 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 | #endif | 78 | #endif |
| 79 | 79 | ||
| 80 | /* | 80 | /* |
| @@ -353,15 +353,7 @@ struct discard_info { · 272 unmodified lines | |||
| 353 | 353 | ||
| 354 | struct discard_cmd { | 354 | struct discard_cmd { |
| 355 | struct rb_node rb_node; /* rb node located in rb-tree */ | 355 | struct rb_node rb_node; /* rb node located in rb-tree */ |
| 356 | union { | 356 | struct discard_info di; /* discard info */ |
| 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 | }; | ||
| 365 | struct list_head list; /* command list */ | 357 | struct list_head list; /* command list */ |
| 366 | struct completion wait; /* compleation */ | 358 | struct completion wait; /* compleation */ |
| 367 | struct block_device *bdev; /* bdev */ | 359 | struct block_device *bdev; /* bdev */ |
| @@ -628,17 +620,6 @@ enum extent_type { · 260 unmodified lines | |||
| 628 | NR_EXTENT_CACHES, | 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 | struct extent_info { | 623 | struct extent_info { |
| 643 | unsigned int fofs; /* start offset in a file */ | 624 | unsigned int fofs; /* start offset in a file */ |
| 644 | unsigned int len; /* length of the extent */ | 625 | unsigned int len; /* length of the extent */ |
| @@ -862,7 +843,7 @@ struct f2fs_inode_info { · 217 unmodified lines | |||
| 862 | kprojid_t i_projid; /* id for project quota */ | 843 | kprojid_t i_projid; /* id for project quota */ |
| 863 | int i_inline_xattr_size; /* inline xattr size */ | 844 | int i_inline_xattr_size; /* inline xattr size */ |
| 864 | struct timespec64 i_crtime; /* inode creation time */ | 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 | /* for file compress */ | 848 | /* for file compress */ |
| 868 | atomic_t i_compr_blocks; /* # of compressed blocks */ | 849 | atomic_t i_compr_blocks; /* # of compressed blocks */ |
| @@ -1293,7 +1274,10 @@ struct f2fs_gc_control { · 424 unmodified lines | |||
| 1293 | unsigned int nr_free_secs; /* # of free sections to do GC */ | 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 | enum { | 1281 | enum { |
| 1298 | SBI_IS_DIRTY, /* dirty flag for checkpoint */ | 1282 | SBI_IS_DIRTY, /* dirty flag for checkpoint */ |
| 1299 | SBI_IS_CLOSE, /* specify unmounting */ | 1283 | SBI_IS_CLOSE, /* specify unmounting */ |
| @@ -1310,6 +1294,8 @@ enum { · 10 unmodified lines | |||
| 1310 | SBI_QUOTA_NEED_REPAIR, /* quota file may be corrupted */ | 1294 | SBI_QUOTA_NEED_REPAIR, /* quota file may be corrupted */ |
| 1311 | SBI_IS_RESIZEFS, /* resizefs is in process */ | 1295 | SBI_IS_RESIZEFS, /* resizefs is in process */ |
| 1312 | SBI_IS_FREEZING, /* freezefs is in process */ | 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 | enum { | 1301 | enum { |
| @@ -1412,86 +1398,6 @@ enum { · 96 unmodified lines | |||
| 1412 | PAGE_PRIVATE_MAX | 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 | /* For compression */ | 1401 | /* For compression */ |
| 1496 | enum compress_algorithm_type { | 1402 | enum compress_algorithm_type { |
| 1497 | COMPRESS_LZO, | 1403 | COMPRESS_LZO, |
| @@ -1617,7 +1523,6 @@ struct f2fs_sb_info { · 119 unmodified lines | |||
| 1617 | 1523 | ||
| 1618 | #ifdef CONFIG_BLK_DEV_ZONED | 1524 | #ifdef CONFIG_BLK_DEV_ZONED |
| 1619 | unsigned int blocks_per_blkz; /* F2FS blocks per zone */ | 1525 | unsigned int blocks_per_blkz; /* F2FS blocks per zone */ |
| 1620 | unsigned int log_blocks_per_blkz; /* log2 F2FS blocks per zone */ | ||
| 1621 | #endif | 1526 | #endif |
| 1622 | 1527 | ||
| 1623 | /* for node-related operations */ | 1528 | /* for node-related operations */ |
| @@ -2386,6 +2291,80 @@ void f2fs_printk(struct f2fs_sb_info *sbi, const char *fmt, ...); · 762 unmodified lines | |||
| 2386 | #define f2fs_debug(sbi, fmt, ...) \ | 2291 | #define f2fs_debug(sbi, fmt, ...) \ |
| 2387 | f2fs_printk(sbi, KERN_DEBUG fmt, ##__VA_ARGS__) | 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 | static inline void dec_valid_block_count(struct f2fs_sb_info *sbi, | 2368 | static inline void dec_valid_block_count(struct f2fs_sb_info *sbi, |
| 2390 | struct inode *inode, | 2369 | struct inode *inode, |
| 2391 | block_t count) | 2370 | block_t count) |
| @@ -2892,7 +2871,7 @@ static inline int f2fs_test_bit(unsigned int nr, char *addr) · 500 unmodified lines | |||
| 2892 | int mask; | 2871 | int mask; |
| 2893 | 2872 | ||
| 2894 | addr += (nr >> 3); | 2873 | addr += (nr >> 3); |
| 2895 | mask = 1 << (7 - (nr & 0x07)); | 2874 | mask = BIT(7 - (nr & 0x07)); |
| 2896 | return mask & *addr; | 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 | int mask; | 2880 | int mask; |
| 2902 | 2881 | ||
| 2903 | addr += (nr >> 3); | 2882 | addr += (nr >> 3); |
| 2904 | mask = 1 << (7 - (nr & 0x07)); | 2883 | mask = BIT(7 - (nr & 0x07)); |
| 2905 | *addr |= mask; | 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 | int mask; | 2889 | int mask; |
| 2911 | 2890 | ||
| 2912 | addr += (nr >> 3); | 2891 | addr += (nr >> 3); |
| 2913 | mask = 1 << (7 - (nr & 0x07)); | 2892 | mask = BIT(7 - (nr & 0x07)); |
| 2914 | *addr &= ~mask; | 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 | int ret; | 2899 | int ret; |
| 2921 | 2900 | ||
| 2922 | addr += (nr >> 3); | 2901 | addr += (nr >> 3); |
| 2923 | mask = 1 << (7 - (nr & 0x07)); | 2902 | mask = BIT(7 - (nr & 0x07)); |
| 2924 | ret = mask & *addr; | 2903 | ret = mask & *addr; |
| 2925 | *addr |= mask; | 2904 | *addr |= mask; |
| 2926 | return ret; | 2905 | return ret; |
| @@ -2932,7 +2911,7 @@ static inline int f2fs_test_and_clear_bit(unsigned int nr, char *addr) · 5 unmodified lines | |||
| 2932 | int ret; | 2911 | int ret; |
| 2933 | 2912 | ||
| 2934 | addr += (nr >> 3); | 2913 | addr += (nr >> 3); |
| 2935 | mask = 1 << (7 - (nr & 0x07)); | 2914 | mask = BIT(7 - (nr & 0x07)); |
| 2936 | ret = mask & *addr; | 2915 | ret = mask & *addr; |
| 2937 | *addr &= ~mask; | 2916 | *addr &= ~mask; |
| 2938 | return ret; | 2917 | return ret; |
| @@ -2943,7 +2922,7 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr) · 4 unmodified lines | |||
| 2943 | int mask; | 2922 | int mask; |
| 2944 | 2923 | ||
| 2945 | addr += (nr >> 3); | 2924 | addr += (nr >> 3); |
| 2946 | mask = 1 << (7 - (nr & 0x07)); | 2925 | mask = BIT(7 - (nr & 0x07)); |
| 2947 | *addr ^= mask; | 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 | return false; | 3286 | return false; |
| 3308 | if (!timespec64_equal(F2FS_I(inode)->i_disk_time + 2, &inode->i_mtime)) | 3287 | if (!timespec64_equal(F2FS_I(inode)->i_disk_time + 2, &inode->i_mtime)) |
| 3309 | return false; | 3288 | return false; |
| 3310 | if (!timespec64_equal(F2FS_I(inode)->i_disk_time + 3, | ||
| 3311 | &F2FS_I(inode)->i_crtime)) | ||
| 3312 | return false; | ||
| 3313 | return true; | 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 | return kmalloc(size, flags); | 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 | static inline void *f2fs_kzalloc(struct f2fs_sb_info *sbi, | 3362 | static inline void *f2fs_kzalloc(struct f2fs_sb_info *sbi, |
| 3374 | size_t size, gfp_t flags) | 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 | * dir.c | 3479 | * dir.c |
| 3491 | */ | 3480 | */ |
| 3492 | unsigned char f2fs_get_de_type(struct f2fs_dir_entry *de); | ||
| 3493 | int f2fs_init_casefolded_name(const struct inode *dir, | 3481 | int f2fs_init_casefolded_name(const struct inode *dir, |
| 3494 | struct f2fs_filename *fname); | 3482 | struct f2fs_filename *fname); |
| 3495 | int f2fs_setup_filename(struct inode *dir, const struct qstr *iname, | 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 | loff_t max_file_blocks(struct inode *inode); | 3542 | loff_t max_file_blocks(struct inode *inode); |
| 3555 | void f2fs_quota_off_umount(struct super_block *sb); | 3543 | void f2fs_quota_off_umount(struct super_block *sb); |
| 3556 | void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason); | 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 | void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error); | 3546 | void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error); |
| 3558 | int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover); | 3547 | int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover); |
| 3559 | int f2fs_sync_fs(struct super_block *sb, int sync); | 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 | unsigned int devidx, int type); | 3726 | unsigned int devidx, int type); |
| 3738 | bool f2fs_is_dirty_device(struct f2fs_sb_info *sbi, nid_t ino, | 3727 | bool f2fs_is_dirty_device(struct f2fs_sb_info *sbi, nid_t ino, |
| 3739 | unsigned int devidx, int type); | 3728 | unsigned int devidx, int type); |
| 3740 | int f2fs_sync_inode_meta(struct f2fs_sb_info *sbi); | ||
| 3741 | int f2fs_acquire_orphan_inode(struct f2fs_sb_info *sbi); | 3729 | int f2fs_acquire_orphan_inode(struct f2fs_sb_info *sbi); |
| 3742 | void f2fs_release_orphan_inode(struct f2fs_sb_info *sbi); | 3730 | void f2fs_release_orphan_inode(struct f2fs_sb_info *sbi); |
| 3743 | void f2fs_add_orphan_inode(struct inode *inode); | 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 | int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count); | 3818 | int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count); |
| 3831 | int __init f2fs_create_garbage_collection_cache(void); | 3819 | int __init f2fs_create_garbage_collection_cache(void); |
| 3832 | void f2fs_destroy_garbage_collection_cache(void); | 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 | * recovery.c | 3827 | * recovery.c |
| @@ -4138,23 +4130,6 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); · 302 unmodified lines | |||
| 4138 | * extent_cache.c | 4130 | * extent_cache.c |
| 4139 | */ | 4131 | */ |
| 4140 | bool sanity_check_extent_cache(struct inode *inode); | 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 | void f2fs_init_extent_tree(struct inode *inode); | 4133 | void f2fs_init_extent_tree(struct inode *inode); |
| 4159 | void f2fs_drop_extent_tree(struct inode *inode); | 4134 | void f2fs_drop_extent_tree(struct inode *inode); |
| 4160 | void f2fs_destroy_extent_node(struct inode *inode); | 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 | F2FS_OPTION(sbi).compress_log_size; | 4329 | F2FS_OPTION(sbi).compress_log_size; |
| 4355 | F2FS_I(inode)->i_compress_flag = | 4330 | F2FS_I(inode)->i_compress_flag = |
| 4356 | F2FS_OPTION(sbi).compress_chksum ? | 4331 | F2FS_OPTION(sbi).compress_chksum ? |
| 4357 | 1 << COMPRESS_CHKSUM : 0; | 4332 | BIT(COMPRESS_CHKSUM) : 0; |
| 4358 | F2FS_I(inode)->i_cluster_size = | 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 | if ((F2FS_I(inode)->i_compress_algorithm == COMPRESS_LZ4 || | 4335 | if ((F2FS_I(inode)->i_compress_algorithm == COMPRESS_LZ4 || |
| 4361 | F2FS_I(inode)->i_compress_algorithm == COMPRESS_ZSTD) && | 4336 | F2FS_I(inode)->i_compress_algorithm == COMPRESS_ZSTD) && |
| 4362 | F2FS_OPTION(sbi).compress_level) | 4337 | F2FS_OPTION(sbi).compress_level) |
| @@ -4414,7 +4389,7 @@ F2FS_FEATURE_FUNCS(readonly, RO); · 51 unmodified lines | |||
| 4414 | static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi, | 4389 | static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi, |
| 4415 | block_t blkaddr) | 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 | return test_bit(zno, FDEV(devi).blkz_seq); | 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 | return false; | 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 | static inline bool f2fs_lfs_mode(struct f2fs_sb_info *sbi) | 4445 | static inline bool f2fs_lfs_mode(struct f2fs_sb_info *sbi) |
| 4466 | { | 4446 | { |
| 4467 | return F2FS_OPTION(sbi).fs_mode == FS_MODE_LFS; | 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 | clear_inode_flag(fi->cow_inode, FI_INLINE_DATA); | 2113 | clear_inode_flag(fi->cow_inode, FI_INLINE_DATA); |
| 2114 | } else { | 2114 | } else { |
| 2115 | /* Reuse the already created COW inode */ | 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 | f2fs_write_inode(inode, NULL); | 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 | struct dquot *transfer_to[MAXQUOTAS] = {}; | 3013 | struct dquot *transfer_to[MAXQUOTAS] = {}; |
| 3010 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | 3014 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
| 3011 | struct super_block *sb = sbi->sb; | 3015 | struct super_block *sb = sbi->sb; |
| 3012 | int err = 0; | 3016 | int err; |
| 3013 | 3017 | ||
| 3014 | transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid)); | 3018 | transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid)); |
| 3015 | if (!IS_ERR(transfer_to[PRJQUOTA])) { | 3019 | if (IS_ERR(transfer_to[PRJQUOTA])) |
| 3016 | err = __dquot_transfer(inode, transfer_to); | 3020 | return PTR_ERR(transfer_to[PRJQUOTA]); |
| 3017 | if (err) | 3021 | |
| 3018 | set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); | 3022 | err = __dquot_transfer(inode, transfer_to); |
| 3019 | dqput(transfer_to[PRJQUOTA]); | 3023 | if (err) |
| 3020 | } | 3024 | set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); |
| 3025 | dqput(transfer_to[PRJQUOTA]); | ||
| 3021 | return err; | 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 | F2FS_I(inode)->i_compress_algorithm = option.algorithm; | 3970 | F2FS_I(inode)->i_compress_algorithm = option.algorithm; |
| 3966 | F2FS_I(inode)->i_log_cluster_size = option.log_cluster_size; | 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 | f2fs_mark_inode_dirty_sync(inode, true); | 3973 | f2fs_mark_inode_dirty_sync(inode, true); |
| 3969 | 3974 | ||
| 3970 | if (!f2fs_is_compress_backend_ready(inode)) | 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 | if (ret < 0) | 4067 | if (ret < 0) |
| 4063 | break; | 4068 | break; |
| 4064 | 4069 | ||
| 4065 | if (get_dirty_pages(inode) >= blk_per_seg) | 4070 | if (get_dirty_pages(inode) >= blk_per_seg) { |
| 4066 | filemap_fdatawrite(inode->i_mapping); | 4071 | ret = filemap_fdatawrite(inode->i_mapping); |
| 4072 | if (ret < 0) | ||
| 4073 | break; | ||
| 4074 | } | ||
| 4067 | 4075 | ||
| 4068 | count -= len; | 4076 | count -= len; |
| 4069 | page_idx += len; | 4077 | page_idx += len; |
| @@ -4133,8 +4141,11 @@ static int f2fs_ioc_compress_file(struct file *filp) · 63 unmodified lines | |||
| 4133 | if (ret < 0) | 4141 | if (ret < 0) |
| 4134 | break; | 4142 | break; |
| 4135 | 4143 | ||
| 4136 | if (get_dirty_pages(inode) >= blk_per_seg) | 4144 | if (get_dirty_pages(inode) >= blk_per_seg) { |
| 4137 | filemap_fdatawrite(inode->i_mapping); | 4145 | ret = filemap_fdatawrite(inode->i_mapping); |
| 4146 | if (ret < 0) | ||
| 4147 | break; | ||
| 4148 | } | ||
| 4138 | 4149 | ||
| 4139 | count -= len; | 4150 | count -= len; |
| 4140 | page_idx += len; | 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 | struct inode *inode = file_inode(iocb->ki_filp); | 4372 | struct inode *inode = file_inode(iocb->ki_filp); |
| 4362 | char *buf, *path; | 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 | if (!buf) | 4376 | if (!buf) |
| 4366 | return; | 4377 | return; |
| 4367 | path = dentry_path_raw(file_dentry(iocb->ki_filp), buf, PATH_MAX); | 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 | trace_f2fs_dataread_start(inode, iocb->ki_pos, count, | 4385 | trace_f2fs_dataread_start(inode, iocb->ki_pos, count, |
| 4375 | current->pid, path, current->comm); | 4386 | current->pid, path, current->comm); |
| 4376 | free_buf: | 4387 | free_buf: |
| 4377 | kfree(buf); | 4388 | f2fs_putname(buf); |
| 4378 | } | 4389 | } |
| 4379 | 4390 | ||
| 4380 | static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) | 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 | .end_io = f2fs_dio_write_end_io, | 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 | static ssize_t f2fs_dio_write_iter(struct kiocb *iocb, struct iov_iter *from, | 4561 | static ssize_t f2fs_dio_write_iter(struct kiocb *iocb, struct iov_iter *from, |
| 4538 | bool *may_need_sync) | 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 | ret += ret2; | 4658 | ret += ret2; |
| 4635 | 4659 | ||
| 4636 | ret2 = filemap_write_and_wait_range(file->f_mapping, | 4660 | f2fs_flush_buffered_write(file->f_mapping, |
| 4637 | bufio_start_pos, | 4661 | bufio_start_pos, |
| 4638 | bufio_end_pos); | 4662 | 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); | ||
| 4644 | } | 4663 | } |
| 4645 | } else { | 4664 | } else { |
| 4646 | /* iomap_dio_rw() already handled the generic_write_sync(). */ | 4665 | /* iomap_dio_rw() already handled the generic_write_sync(). */ |
| @@ -4723,8 +4742,18 @@ out_unlock: · 76 unmodified lines | |||
| 4723 | inode_unlock(inode); | 4742 | inode_unlock(inode); |
| 4724 | out: | 4743 | out: |
| 4725 | trace_f2fs_file_write_iter(inode, orig_pos, orig_count, ret); | 4744 | trace_f2fs_file_write_iter(inode, orig_pos, orig_count, ret); |
| 4745 | |||
| 4726 | if (ret > 0 && may_need_sync) | 4746 | if (ret > 0 && may_need_sync) |
| 4727 | ret = generic_write_sync(iocb, ret); | 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 | return ret; | 4757 | return ret; |
| 4729 | } | 4758 | } |
| 4730 | 4759 | ||
| @@ -4879,6 +4908,7 @@ const struct file_operations f2fs_file_operations = { · 148 unmodified lines | |||
| 4879 | .llseek = f2fs_llseek, | 4908 | .llseek = f2fs_llseek, |
| 4880 | .read_iter = f2fs_file_read_iter, | 4909 | .read_iter = f2fs_file_read_iter, |
| 4881 | .write_iter = f2fs_file_write_iter, | 4910 | .write_iter = f2fs_file_write_iter, |
| 4911 | .iopoll = iocb_bio_iopoll, | ||
| 4882 | .open = f2fs_file_open, | 4912 | .open = f2fs_file_open, |
| 4883 | .release = f2fs_release_file, | 4913 | .release = f2fs_release_file, |
| 4884 | .mmap = f2fs_file_mmap, | 4914 | .mmap = f2fs_file_mmap, |
| @@ -390,40 +390,95 @@ static unsigned int count_bits(const unsigned long *addr, · 389 unmodified lines | |||
| 390 | return sum; | 390 | return sum; |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | static struct victim_entry *attach_victim_entry(struct f2fs_sb_info *sbi, | 393 | static bool f2fs_check_victim_tree(struct f2fs_sb_info *sbi, |
| 394 | unsigned long long mtime, unsigned int segno, | 394 | struct rb_root_cached *root) |
| 395 | struct rb_node *parent, struct rb_node **p, | 395 | { |
| 396 | bool left_most) | 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 | struct atgc_management *am = &sbi->am; | 441 | struct atgc_management *am = &sbi->am; |
| 399 | struct victim_entry *ve; | 442 | struct victim_entry *ve; |
| 400 | 443 | ||
| 401 | ve = f2fs_kmem_cache_alloc(victim_entry_slab, | 444 | ve = f2fs_kmem_cache_alloc(victim_entry_slab, GFP_NOFS, true, NULL); |
| 402 | GFP_NOFS, true, NULL); | ||
| 403 | 445 | ||
| 404 | ve->mtime = mtime; | 446 | ve->mtime = mtime; |
| 405 | ve->segno = segno; | 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 | list_add_tail(&ve->list, &am->victim_list); | 449 | list_add_tail(&ve->list, &am->victim_list); |
| 411 | |||
| 412 | am->victim_count++; | 450 | am->victim_count++; |
| 413 | 451 | ||
| 414 | return ve; | 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 | unsigned long long mtime, unsigned int segno) | 456 | unsigned long long mtime, unsigned int segno) |
| 419 | { | 457 | { |
| 420 | struct atgc_management *am = &sbi->am; | 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 | struct rb_node *parent = NULL; | 461 | struct rb_node *parent = NULL; |
| 462 | struct victim_entry *ve; | ||
| 423 | bool left_most = true; | 463 | bool left_most = true; |
| 424 | 464 | ||
| 425 | p = f2fs_lookup_rb_tree_ext(sbi, &am->root, &parent, mtime, &left_most); | 465 | /* look up rb tree to find parent node */ |
| 426 | attach_victim_entry(sbi, mtime, segno, parent, p, left_most); | 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 | static void add_victim_entry(struct f2fs_sb_info *sbi, | 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 | if (sit_i->dirty_max_mtime - mtime < p->age_threshold) | 514 | if (sit_i->dirty_max_mtime - mtime < p->age_threshold) |
| 460 | return; | 515 | return; |
| 461 | 516 | ||
| 462 | insert_victim_entry(sbi, mtime, segno); | 517 | __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; | ||
| 475 | } | 518 | } |
| 476 | 519 | ||
| 477 | static void atgc_lookup_victim(struct f2fs_sb_info *sbi, | 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 | struct atgc_management *am = &sbi->am; | 524 | struct atgc_management *am = &sbi->am; |
| 482 | struct rb_root_cached *root = &am->root; | 525 | struct rb_root_cached *root = &am->root; |
| 483 | struct rb_node *node; | 526 | struct rb_node *node; |
| 484 | struct rb_entry *re; | ||
| 485 | struct victim_entry *ve; | 527 | struct victim_entry *ve; |
| 486 | unsigned long long total_time; | 528 | unsigned long long total_time; |
| 487 | unsigned long long age, u, accu; | 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 | node = rb_first_cached(root); | 551 | node = rb_first_cached(root); |
| 510 | next: | 552 | next: |
| 511 | re = rb_entry_safe(node, struct rb_entry, rb_node); | 553 | ve = rb_entry_safe(node, struct victim_entry, rb_node); |
| 512 | if (!re) | 554 | if (!ve) |
| 513 | return; | 555 | return; |
| 514 | 556 | ||
| 515 | ve = (struct victim_entry *)re; | ||
| 516 | |||
| 517 | if (ve->mtime >= max_mtime || ve->mtime < min_mtime) | 557 | if (ve->mtime >= max_mtime || ve->mtime < min_mtime) |
| 518 | goto skip; | 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 | struct sit_info *sit_i = SIT_I(sbi); | 596 | struct sit_info *sit_i = SIT_I(sbi); |
| 557 | struct atgc_management *am = &sbi->am; | 597 | struct atgc_management *am = &sbi->am; |
| 558 | struct rb_node *node; | ||
| 559 | struct rb_entry *re; | ||
| 560 | struct victim_entry *ve; | 598 | struct victim_entry *ve; |
| 561 | unsigned long long age; | 599 | unsigned long long age; |
| 562 | unsigned long long max_mtime = sit_i->dirty_max_mtime; | 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 | unsigned int dirty_threshold = max(am->max_candidate_count, | 604 | unsigned int dirty_threshold = max(am->max_candidate_count, |
| 567 | am->candidate_ratio * | 605 | am->candidate_ratio * |
| 568 | am->victim_count / 100); | 606 | am->victim_count / 100); |
| 569 | unsigned int cost; | 607 | unsigned int cost, iter; |
| 570 | unsigned int iter = 0; | ||
| 571 | int stage = 0; | 608 | int stage = 0; |
| 572 | 609 | ||
| 573 | if (max_mtime < min_mtime) | 610 | if (max_mtime < min_mtime) |
| 574 | return; | 611 | return; |
| 575 | max_mtime += 1; | 612 | max_mtime += 1; |
| 576 | next_stage: | 613 | next_stage: |
| 577 | node = lookup_central_victim(sbi, p); | 614 | iter = 0; |
| 615 | ve = __lookup_victim_entry(sbi, p->age); | ||
| 578 | next_node: | 616 | next_node: |
| 579 | re = rb_entry_safe(node, struct rb_entry, rb_node); | 617 | if (!ve) { |
| 580 | if (!re) { | 618 | if (stage++ == 0) |
| 581 | if (stage == 0) | 619 | goto next_stage; |
| 582 | goto skip_stage; | ||
| 583 | return; | 620 | return; |
| 584 | } | 621 | } |
| 585 | 622 | ||
| 586 | ve = (struct victim_entry *)re; | ||
| 587 | |||
| 588 | if (ve->mtime >= max_mtime || ve->mtime < min_mtime) | 623 | if (ve->mtime >= max_mtime || ve->mtime < min_mtime) |
| 589 | goto skip_node; | 624 | goto skip_node; |
| 590 | 625 | ||
| @@ -610,24 +645,20 @@ next_node: · 19 unmodified lines | |||
| 610 | } | 645 | } |
| 611 | skip_node: | 646 | skip_node: |
| 612 | if (iter < dirty_threshold) { | 647 | if (iter < dirty_threshold) { |
| 613 | if (stage == 0) | 648 | ve = rb_entry(stage == 0 ? rb_prev(&ve->rb_node) : |
| 614 | node = rb_prev(node); | 649 | rb_next(&ve->rb_node), |
| 615 | else if (stage == 1) | 650 | struct victim_entry, rb_node); |
| 616 | node = rb_next(node); | ||
| 617 | goto next_node; | 651 | goto next_node; |
| 618 | } | 652 | } |
| 619 | skip_stage: | 653 | |
| 620 | if (stage < 1) { | 654 | if (stage++ == 0) |
| 621 | stage++; | ||
| 622 | iter = 0; | ||
| 623 | goto next_stage; | 655 | goto next_stage; |
| 624 | } | ||
| 625 | } | 656 | } |
| 657 | |||
| 626 | static void lookup_victim_by_age(struct f2fs_sb_info *sbi, | 658 | static void lookup_victim_by_age(struct f2fs_sb_info *sbi, |
| 627 | struct victim_sel_policy *p) | 659 | struct victim_sel_policy *p) |
| 628 | { | 660 | { |
| 629 | f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi, | 661 | f2fs_bug_on(sbi, !f2fs_check_victim_tree(sbi, &sbi->am.root)); |
| 630 | &sbi->am.root, true)); | ||
| 631 | 662 | ||
| 632 | if (p->gc_mode == GC_AT) | 663 | if (p->gc_mode == GC_AT) |
| 633 | atgc_lookup_victim(sbi, p); | 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 | * When it is called from SSR segment selection, it finds a segment | 741 | * When it is called from SSR segment selection, it finds a segment |
| 711 | * which has minimum valid blocks and removes it from dirty seglist. | 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, | 744 | int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result, |
| 714 | unsigned int *result, int gc_type, int type, | 745 | int gc_type, int type, char alloc_mode, |
| 715 | char alloc_mode, unsigned long long age) | 746 | unsigned long long age) |
| 716 | { | 747 | { |
| 717 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 748 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
| 718 | struct sit_info *sm = SIT_I(sbi); | 749 | struct sit_info *sm = SIT_I(sbi); |
| @@ -906,10 +937,6 @@ out: · 187 unmodified lines | |||
| 906 | return ret; | 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 | static struct inode *find_gc_inode(struct gc_inode_list *gc_list, nid_t ino) | 940 | static struct inode *find_gc_inode(struct gc_inode_list *gc_list, nid_t ino) |
| 914 | { | 941 | { |
| 915 | struct inode_entry *ie; | 942 | struct inode_entry *ie; |
| @@ -1589,14 +1616,14 @@ next_step: · 673 unmodified lines | |||
| 1589 | int err; | 1616 | int err; |
| 1590 | 1617 | ||
| 1591 | if (S_ISREG(inode->i_mode)) { | 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 | sbi->skipped_gc_rwsem++; | 1620 | sbi->skipped_gc_rwsem++; |
| 1594 | continue; | 1621 | continue; |
| 1595 | } | 1622 | } |
| 1596 | if (!f2fs_down_write_trylock( | 1623 | if (!f2fs_down_write_trylock( |
| 1597 | &fi->i_gc_rwsem[WRITE])) { | 1624 | &fi->i_gc_rwsem[READ])) { |
| 1598 | sbi->skipped_gc_rwsem++; | 1625 | sbi->skipped_gc_rwsem++; |
| 1599 | f2fs_up_write(&fi->i_gc_rwsem[READ]); | 1626 | f2fs_up_write(&fi->i_gc_rwsem[WRITE]); |
| 1600 | continue; | 1627 | continue; |
| 1601 | } | 1628 | } |
| 1602 | locked = true; | 1629 | locked = true; |
| @@ -1619,8 +1646,8 @@ next_step: · 16 unmodified lines | |||
| 1619 | submitted++; | 1646 | submitted++; |
| 1620 | 1647 | ||
| 1621 | if (locked) { | 1648 | if (locked) { |
| 1622 | f2fs_up_write(&fi->i_gc_rwsem[WRITE]); | ||
| 1623 | f2fs_up_write(&fi->i_gc_rwsem[READ]); | 1649 | f2fs_up_write(&fi->i_gc_rwsem[READ]); |
| 1650 | f2fs_up_write(&fi->i_gc_rwsem[WRITE]); | ||
| 1624 | } | 1651 | } |
| 1625 | 1652 | ||
| 1626 | stat_inc_data_blk_count(sbi, 1, gc_type); | 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 | int ret; | 1667 | int ret; |
| 1641 | 1668 | ||
| 1642 | down_write(&sit_i->sentry_lock); | 1669 | down_write(&sit_i->sentry_lock); |
| 1643 | ret = DIRTY_I(sbi)->v_ops->get_victim(sbi, victim, gc_type, | 1670 | ret = f2fs_get_victim(sbi, victim, gc_type, NO_CHECK_TYPE, LFS, 0); |
| 1644 | NO_CHECK_TYPE, LFS, 0); | ||
| 1645 | up_write(&sit_i->sentry_lock); | 1671 | up_write(&sit_i->sentry_lock); |
| 1646 | return ret; | 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 | .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS), | 1805 | .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS), |
| 1780 | }; | 1806 | }; |
| 1781 | unsigned int skipped_round = 0, round = 0; | 1807 | unsigned int skipped_round = 0, round = 0; |
| 1808 | unsigned int upper_secs; | ||
| 1782 | 1809 | ||
| 1783 | trace_f2fs_gc_begin(sbi->sb, gc_type, gc_control->no_bg_gc, | 1810 | trace_f2fs_gc_begin(sbi->sb, gc_type, gc_control->no_bg_gc, |
| 1784 | gc_control->nr_free_secs, | 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 | prefree_segments(sbi)); | 1818 | prefree_segments(sbi)); |
| 1792 | 1819 | ||
| 1793 | cpc.reason = __get_cp_reason(sbi); | 1820 | cpc.reason = __get_cp_reason(sbi); |
| 1794 | sbi->skipped_gc_rwsem = 0; | ||
| 1795 | gc_more: | 1821 | gc_more: |
| 1822 | sbi->skipped_gc_rwsem = 0; | ||
| 1796 | if (unlikely(!(sbi->sb->s_flags & SB_ACTIVE))) { | 1823 | if (unlikely(!(sbi->sb->s_flags & SB_ACTIVE))) { |
| 1797 | ret = -EINVAL; | 1824 | ret = -EINVAL; |
| 1798 | goto stop; | 1825 | goto stop; |
| @@ -1802,7 +1829,10 @@ gc_more: · 3 unmodified lines | |||
| 1802 | goto stop; | 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 | * For example, if there are many prefree_segments below given | 1837 | * For example, if there are many prefree_segments below given |
| 1808 | * threshold, we can make them free by checkpoint. Then, we | 1838 | * threshold, we can make them free by checkpoint. Then, we |
| @@ -1813,8 +1843,6 @@ gc_more: · 4 unmodified lines | |||
| 1813 | if (ret) | 1843 | if (ret) |
| 1814 | goto stop; | 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 | /* f2fs_balance_fs doesn't need to do BG_GC in critical path. */ | 1848 | /* f2fs_balance_fs doesn't need to do BG_GC in critical path. */ |
| @@ -1841,19 +1869,15 @@ retry: · 20 unmodified lines | |||
| 1841 | if (seg_freed == f2fs_usable_segs_in_sec(sbi, segno)) | 1869 | if (seg_freed == f2fs_usable_segs_in_sec(sbi, segno)) |
| 1842 | sec_freed++; | 1870 | sec_freed++; |
| 1843 | 1871 | ||
| 1844 | if (gc_type == FG_GC) | 1872 | if (gc_type == FG_GC) { |
| 1845 | sbi->cur_victim_sec = NULL_SEGNO; | 1873 | sbi->cur_victim_sec = NULL_SEGNO; |
| 1846 | 1874 | ||
| 1847 | if (gc_control->init_gc_type == FG_GC || | 1875 | if (has_enough_free_secs(sbi, sec_freed, 0)) { |
| 1848 | !has_not_enough_free_secs(sbi, | 1876 | if (!gc_control->no_bg_gc && |
| 1849 | (gc_type == FG_GC) ? sec_freed : 0, 0)) { | 1877 | sec_freed < gc_control->nr_free_secs) |
| 1850 | if (gc_type == FG_GC && sec_freed < gc_control->nr_free_secs) | 1878 | goto go_gc_more; |
| 1851 | goto go_gc_more; | 1879 | goto stop; |
| 1852 | goto stop; | 1880 | } |
| 1853 | } | ||
| 1854 | |||
| 1855 | /* FG_GC stops GC by skip_count */ | ||
| 1856 | if (gc_type == FG_GC) { | ||
| 1857 | if (sbi->skipped_gc_rwsem) | 1881 | if (sbi->skipped_gc_rwsem) |
| 1858 | skipped_round++; | 1882 | skipped_round++; |
| 1859 | round++; | 1883 | round++; |
| @@ -1862,10 +1886,17 @@ retry: · 2 unmodified lines | |||
| 1862 | ret = f2fs_write_checkpoint(sbi, &cpc); | 1886 | ret = f2fs_write_checkpoint(sbi, &cpc); |
| 1863 | goto stop; | 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 */ | 1893 | __get_secs_required(sbi, NULL, &upper_secs, NULL); |
| 1868 | if (free_sections(sbi) < NR_CURSEG_PERSIST_TYPE && | 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 | prefree_segments(sbi)) { | 1900 | prefree_segments(sbi)) { |
| 1870 | ret = f2fs_write_checkpoint(sbi, &cpc); | 1901 | ret = f2fs_write_checkpoint(sbi, &cpc); |
| 1871 | if (ret) | 1902 | if (ret) |
| @@ -1932,8 +1963,6 @@ static void init_atgc_management(struct f2fs_sb_info *sbi) · 60 unmodified lines | |||
| 1932 | 1963 | ||
| 1933 | void f2fs_build_gc_manager(struct f2fs_sb_info *sbi) | 1964 | void f2fs_build_gc_manager(struct f2fs_sb_info *sbi) |
| 1934 | { | 1965 | { |
| 1935 | DIRTY_I(sbi)->v_ops = &default_v_ops; | ||
| 1936 | |||
| 1937 | sbi->gc_pin_file_threshold = DEF_GC_FAILED_PINNED_FILES; | 1966 | sbi->gc_pin_file_threshold = DEF_GC_FAILED_PINNED_FILES; |
| 1938 | 1967 | ||
| 1939 | /* give warm/cold data area from slower device */ | 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 | FDEV(last_dev).end_blk = | 2093 | FDEV(last_dev).end_blk = |
| 2065 | (long long)FDEV(last_dev).end_blk + blks; | 2094 | (long long)FDEV(last_dev).end_blk + blks; |
| 2066 | #ifdef CONFIG_BLK_DEV_ZONED | 2095 | #ifdef CONFIG_BLK_DEV_ZONED |
| 2067 | FDEV(last_dev).nr_blkz = (int)FDEV(last_dev).nr_blkz + | 2096 | FDEV(last_dev).nr_blkz = FDEV(last_dev).nr_blkz + |
| 2068 | (int)(blks >> sbi->log_blocks_per_blkz); | 2097 | div_u64(blks, sbi->blocks_per_blkz); |
| 2069 | #endif | 2098 | #endif |
| 2070 | } | 2099 | } |
| 2071 | } | 2100 | } |
| @@ -30,6 +30,8 @@ · 29 unmodified lines | |||
| 30 | /* Search max. number of dirty segments to select a victim segment */ | 30 | /* Search max. number of dirty segments to select a victim segment */ |
| 31 | #define DEF_MAX_VICTIM_SEARCH 4096 /* covers 8GB */ | 31 | #define DEF_MAX_VICTIM_SEARCH 4096 /* covers 8GB */ |
| 32 | 32 | ||
| 33 | #define NR_GC_CHECKPOINT_SECS (3) /* data/node/dentry sections */ | ||
| 34 | |||
| 33 | struct f2fs_gc_kthread { | 35 | struct f2fs_gc_kthread { |
| 34 | struct task_struct *f2fs_gc_task; | 36 | struct task_struct *f2fs_gc_task; |
| 35 | wait_queue_head_t gc_wait_queue_head; | 37 | wait_queue_head_t gc_wait_queue_head; |
| @@ -55,20 +57,10 @@ struct gc_inode_list { · 19 unmodified lines | |||
| 55 | struct radix_tree_root iroot; | 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 | struct victim_entry { | 60 | struct victim_entry { |
| 64 | struct rb_node rb_node; /* rb node located in rb-tree */ | 61 | struct rb_node rb_node; /* rb node located in rb-tree */ |
| 65 | union { | 62 | unsigned long long mtime; /* mtime of section */ |
| 66 | struct { | 63 | unsigned int segno; /* segment No. */ |
| 67 | unsigned long long mtime; /* mtime of section */ | ||
| 68 | unsigned int segno; /* segment No. */ | ||
| 69 | }; | ||
| 70 | struct victim_info vi; /* victim info */ | ||
| 71 | }; | ||
| 72 | struct list_head list; | 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 | fname.hash = de->hash_code; | 497 | fname.hash = de->hash_code; |
| 498 | 498 | ||
| 499 | ino = le32_to_cpu(de->ino); | 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 | err = f2fs_add_regular_entry(dir, &fname, NULL, ino, fake_mode); | 502 | err = f2fs_add_regular_entry(dir, &fname, NULL, ino, fake_mode); |
| 503 | if (err) | 503 | if (err) |
| @@ -326,7 +326,6 @@ static void init_idisk_time(struct inode *inode) · 325 unmodified lines | |||
| 326 | fi->i_disk_time[0] = inode->i_atime; | 326 | fi->i_disk_time[0] = inode->i_atime; |
| 327 | fi->i_disk_time[1] = inode->i_ctime; | 327 | fi->i_disk_time[1] = inode->i_ctime; |
| 328 | fi->i_disk_time[2] = inode->i_mtime; | 328 | fi->i_disk_time[2] = inode->i_mtime; |
| 329 | fi->i_disk_time[3] = fi->i_crtime; | ||
| 330 | } | 329 | } |
| 331 | 330 | ||
| 332 | static int do_read_inode(struct inode *inode) | 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 | fi->i_compress_level = compress_flag >> | 453 | fi->i_compress_level = compress_flag >> |
| 455 | COMPRESS_LEVEL_OFFSET; | 454 | COMPRESS_LEVEL_OFFSET; |
| 456 | fi->i_compress_flag = compress_flag & | 455 | fi->i_compress_flag = compress_flag & |
| 457 | (BIT(COMPRESS_LEVEL_OFFSET) - 1); | 456 | GENMASK(COMPRESS_LEVEL_OFFSET - 1, 0); |
| 458 | fi->i_cluster_size = 1 << fi->i_log_cluster_size; | 457 | fi->i_cluster_size = BIT(fi->i_log_cluster_size); |
| 459 | set_inode_flag(inode, FI_COMPRESSED_FILE); | 458 | set_inode_flag(inode, FI_COMPRESSED_FILE); |
| 460 | } | 459 | } |
| 461 | } | 460 | } |
| @@ -22,7 +22,7 @@ · 21 unmodified lines | |||
| 22 | #include "acl.h" | 22 | #include "acl.h" |
| 23 | #include <trace/events/f2fs.h> | 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 | bool tmp_ext) | 26 | bool tmp_ext) |
| 27 | { | 27 | { |
| 28 | size_t slen = strlen(s); | 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 | int i; | 30 | int i; |
| 31 | 31 | ||
| 32 | if (sublen == 1 && *sub == '*') | 32 | if (sublen == 1 && *sub == '*') |
| 33 | return 1; | 33 | return true; |
| 34 | 34 | ||
| 35 | /* | 35 | /* |
| 36 | * filename format of multimedia file should be defined as: | 36 | * filename format of multimedia file should be defined as: |
| 37 | * "filename + '.' + extension + (optional: '.' + temp extension)". | 37 | * "filename + '.' + extension + (optional: '.' + temp extension)". |
| 38 | */ | 38 | */ |
| 39 | if (slen < sublen + 2) | 39 | if (slen < sublen + 2) |
| 40 | return 0; | 40 | return false; |
| 41 | 41 | ||
| 42 | if (!tmp_ext) { | 42 | if (!tmp_ext) { |
| 43 | /* file has no temp extension */ | 43 | /* file has no temp extension */ |
| 44 | if (s[slen - sublen - 1] != '.') | 44 | if (s[slen - sublen - 1] != '.') |
| 45 | return 0; | 45 | return false; |
| 46 | return !strncasecmp(s + slen - sublen, sub, sublen); | 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 | if (s[i] != '.') | 50 | if (s[i] != '.') |
| 51 | continue; | 51 | continue; |
| 52 | if (!strncasecmp(s + i + 1, sub, sublen)) | 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 | int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name, | 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 | goto out; | 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 | err = -ENOENT; | 1006 | err = -ENOENT; |
| 999 | old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page); | 1007 | old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page); |
| 1000 | if (!old_entry) { | 1008 | if (!old_entry) { |
| 1001 | if (IS_ERR(old_page)) | 1009 | if (IS_ERR(old_page)) |
| 1002 | err = PTR_ERR(old_page); | 1010 | err = PTR_ERR(old_page); |
| 1003 | goto out; | 1011 | goto out_unlock_old; |
| 1004 | } | 1012 | } |
| 1005 | 1013 | ||
| 1006 | if (S_ISDIR(old_inode->i_mode)) { | 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 | f2fs_unlock_op(sbi); | 1117 | f2fs_unlock_op(sbi); |
| 1110 | 1118 | ||
| 1119 | if (S_ISDIR(old_inode->i_mode)) | ||
| 1120 | inode_unlock(old_inode); | ||
| 1121 | |||
| 1111 | if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) | 1122 | if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) |
| 1112 | f2fs_sync_fs(sbi->sb, 1); | 1123 | f2fs_sync_fs(sbi->sb, 1); |
| 1113 | 1124 | ||
| @@ -1122,6 +1133,9 @@ out_dir: · 8 unmodified lines | |||
| 1122 | f2fs_put_page(old_dir_page, 0); | 1133 | f2fs_put_page(old_dir_page, 0); |
| 1123 | out_old: | 1134 | out_old: |
| 1124 | f2fs_put_page(old_page, 0); | 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 | out: | 1139 | out: |
| 1126 | iput(whiteout); | 1140 | iput(whiteout); |
| 1127 | return err; | 1141 | return err; |
| @@ -93,17 +93,15 @@ static inline void copy_node_info(struct node_info *dst, · 92 unmodified lines | |||
| 93 | static inline void set_nat_flag(struct nat_entry *ne, | 93 | static inline void set_nat_flag(struct nat_entry *ne, |
| 94 | unsigned int type, bool set) | 94 | unsigned int type, bool set) |
| 95 | { | 95 | { |
| 96 | unsigned char mask = 0x01 << type; | ||
| 97 | if (set) | 96 | if (set) |
| 98 | ne->ni.flag |= mask; | 97 | ne->ni.flag |= BIT(type); |
| 99 | else | 98 | else |
| 100 | ne->ni.flag &= ~mask; | 99 | ne->ni.flag &= ~BIT(type); |
| 101 | } | 100 | } |
| 102 | 101 | ||
| 103 | static inline bool get_nat_flag(struct nat_entry *ne, unsigned int type) | 102 | static inline bool get_nat_flag(struct nat_entry *ne, unsigned int type) |
| 104 | { | 103 | { |
| 105 | unsigned char mask = 0x01 << type; | 104 | return ne->ni.flag & BIT(type); |
| 106 | return ne->ni.flag & mask; | ||
| 107 | } | 105 | } |
| 108 | 106 | ||
| 109 | static inline void nat_reset_flag(struct nat_entry *ne) | 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 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 223 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
| 226 | 224 | ||
| 227 | block_addr -= nm_i->nat_blkaddr; | 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 | return block_addr + nm_i->nat_blkaddr; | 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 | static inline int is_node(struct page *page, int type) | 393 | static inline int is_node(struct page *page, int type) |
| 396 | { | 394 | { |
| 397 | struct f2fs_node *rn = F2FS_NODE(page); | 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 | #define is_cold_node(page) is_node(page, COLD_BIT_SHIFT) | 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 | unsigned int flag = le32_to_cpu(rn->footer.flag); | 406 | unsigned int flag = le32_to_cpu(rn->footer.flag); |
| 409 | 407 | ||
| 410 | if (is_dir) | 408 | if (is_dir) |
| 411 | flag &= ~(0x1 << COLD_BIT_SHIFT); | 409 | flag &= ~BIT(COLD_BIT_SHIFT); |
| 412 | else | 410 | else |
| 413 | flag |= (0x1 << COLD_BIT_SHIFT); | 411 | flag |= BIT(COLD_BIT_SHIFT); |
| 414 | rn->footer.flag = cpu_to_le32(flag); | 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 | struct f2fs_node *rn = F2FS_NODE(page); | 417 | struct f2fs_node *rn = F2FS_NODE(page); |
| 420 | unsigned int flag = le32_to_cpu(rn->footer.flag); | 418 | unsigned int flag = le32_to_cpu(rn->footer.flag); |
| 421 | if (mark) | 419 | if (mark) |
| 422 | flag |= (0x1 << type); | 420 | flag |= BIT(type); |
| 423 | else | 421 | else |
| 424 | flag &= ~(0x1 << type); | 422 | flag &= ~BIT(type); |
| 425 | rn->footer.flag = cpu_to_le32(flag); | 423 | rn->footer.flag = cpu_to_le32(flag); |
| 426 | 424 | ||
| 427 | #ifdef CONFIG_F2FS_CHECK_FS | 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 | unsigned long s_flags = sbi->sb->s_flags; | 825 | unsigned long s_flags = sbi->sb->s_flags; |
| 826 | bool need_writecp = false; | 826 | bool need_writecp = false; |
| 827 | bool fix_curseg_write_pointer = false; | 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 | f2fs_info(sbi, "recover fsync data on readonly fs"); | 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 | INIT_LIST_HEAD(&inode_list); | 832 | INIT_LIST_HEAD(&inode_list); |
| 843 | INIT_LIST_HEAD(&tmp_inode_list); | 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 | sbi->sb->s_flags = s_flags; /* Restore SB_RDONLY status */ | 902 | sbi->sb->s_flags = s_flags; /* Restore SB_RDONLY status */ |
| 918 | 903 | ||
| 919 | return ret ? ret : err; | 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 | retry: | 218 | retry: |
| 219 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 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 | if (err) { | 221 | if (err) { |
| 222 | if (err == -ENOMEM) { | 222 | if (err == -ENOMEM) { |
| 223 | f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); | 223 | f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); |
| @@ -246,10 +246,16 @@ retry: · 22 unmodified lines | |||
| 246 | } else { | 246 | } else { |
| 247 | blkcnt_t count = 1; | 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 | *old_addr = dn.data_blkaddr; | 255 | *old_addr = dn.data_blkaddr; |
| 250 | f2fs_truncate_data_blocks_range(&dn, 1); | 256 | f2fs_truncate_data_blocks_range(&dn, 1); |
| 251 | dec_valid_block_count(sbi, F2FS_I(inode)->cow_inode, count); | 257 | dec_valid_block_count(sbi, F2FS_I(inode)->cow_inode, count); |
| 252 | inc_valid_block_count(sbi, inode, &count); | 258 | |
| 253 | f2fs_replace_block(sbi, &dn, dn.data_blkaddr, new_addr, | 259 | f2fs_replace_block(sbi, &dn, dn.data_blkaddr, new_addr, |
| 254 | ni.version, true, false); | 260 | ni.version, true, false); |
| 255 | } | 261 | } |
| @@ -257,7 +263,7 @@ retry: · 1 unmodified line | |||
| 257 | f2fs_put_dnode(&dn); | 263 | f2fs_put_dnode(&dn); |
| 258 | 264 | ||
| 259 | trace_f2fs_replace_atomic_write_block(inode, F2FS_I(inode)->cow_inode, | 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 | return 0; | 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 | * We should do GC or end up with checkpoint, if there are so many dirty | 412 | * We should do GC or end up with checkpoint, if there are so many dirty |
| 407 | * dir/node pages without enough free segments. | 413 | * dir/node pages without enough free segments. |
| 408 | */ | 414 | */ |
| 409 | if (has_not_enough_free_secs(sbi, 0, 0)) { | 415 | if (has_enough_free_secs(sbi, 0, 0)) |
| 410 | if (test_opt(sbi, GC_MERGE) && sbi->gc_thread && | 416 | return; |
| 411 | sbi->gc_thread->f2fs_gc_task) { | 417 | |
| 412 | DEFINE_WAIT(wait); | 418 | if (test_opt(sbi, GC_MERGE) && sbi->gc_thread && |
| 413 | 419 | sbi->gc_thread->f2fs_gc_task) { | |
| 414 | prepare_to_wait(&sbi->gc_thread->fggc_wq, &wait, | 420 | DEFINE_WAIT(wait); |
| 415 | TASK_UNINTERRUPTIBLE); | 421 | |
| 416 | wake_up(&sbi->gc_thread->gc_wait_queue_head); | 422 | prepare_to_wait(&sbi->gc_thread->fggc_wq, &wait, |
| 417 | io_schedule(); | 423 | TASK_UNINTERRUPTIBLE); |
| 418 | finish_wait(&sbi->gc_thread->fggc_wq, &wait); | 424 | wake_up(&sbi->gc_thread->gc_wait_queue_head); |
| 419 | } else { | 425 | io_schedule(); |
| 420 | struct f2fs_gc_control gc_control = { | 426 | finish_wait(&sbi->gc_thread->fggc_wq, &wait); |
| 421 | .victim_segno = NULL_SEGNO, | 427 | } else { |
| 422 | .init_gc_type = BG_GC, | 428 | struct f2fs_gc_control gc_control = { |
| 423 | .no_bg_gc = true, | 429 | .victim_segno = NULL_SEGNO, |
| 424 | .should_migrate_blocks = false, | 430 | .init_gc_type = BG_GC, |
| 425 | .err_gc_skipped = false, | 431 | .no_bg_gc = true, |
| 426 | .nr_free_secs = 1 }; | 432 | .should_migrate_blocks = false, |
| 427 | f2fs_down_write(&sbi->gc_lock); | 433 | .err_gc_skipped = false, |
| 428 | f2fs_gc(sbi, &gc_control); | 434 | .nr_free_secs = 1 }; |
| 429 | } | 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 | dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS, true, NULL); | 940 | dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS, true, NULL); |
| 934 | INIT_LIST_HEAD(&dc->list); | 941 | INIT_LIST_HEAD(&dc->list); |
| 935 | dc->bdev = bdev; | 942 | dc->bdev = bdev; |
| 936 | dc->lstart = lstart; | 943 | dc->di.lstart = lstart; |
| 937 | dc->start = start; | 944 | dc->di.start = start; |
| 938 | dc->len = len; | 945 | dc->di.len = len; |
| 939 | dc->ref = 0; | 946 | dc->ref = 0; |
| 940 | dc->state = D_PREP; | 947 | dc->state = D_PREP; |
| 941 | dc->queued = 0; | 948 | dc->queued = 0; |
| @@ -950,20 +957,108 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi, · 8 unmodified lines | |||
| 950 | return dc; | 957 | return dc; |
| 951 | } | 958 | } |
| 952 | 959 | ||
| 953 | static struct discard_cmd *__attach_discard_cmd(struct f2fs_sb_info *sbi, | 960 | static bool f2fs_check_discard_tree(struct f2fs_sb_info *sbi) |
| 954 | struct block_device *bdev, block_t lstart, | 961 | { |
| 955 | block_t start, block_t len, | 962 | #ifdef CONFIG_F2FS_CHECK_FS |
| 956 | struct rb_node *parent, struct rb_node **p, | 963 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; |
| 957 | bool leftmost) | 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 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; | 991 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; |
| 992 | struct rb_node *node = dcc->root.rb_root.rb_node; | ||
| 960 | struct discard_cmd *dc; | 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); | 998 | if (blkaddr < dc->di.lstart) |
| 965 | rb_insert_color_cached(&dc->rb_node, &dcc->root, leftmost); | 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 | return dc; | 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 | list_del(&dc->list); | 1071 | list_del(&dc->list); |
| 977 | rb_erase_cached(&dc->rb_node, &dcc->root); | 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 | kmem_cache_free(discard_cmd_slab, dc); | 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 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; | 1083 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; |
| 989 | unsigned long flags; | 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 | spin_lock_irqsave(&dc->lock, flags); | 1088 | spin_lock_irqsave(&dc->lock, flags); |
| 994 | if (dc->bio_ref) { | 1089 | if (dc->bio_ref) { |
| @@ -1006,7 +1101,7 @@ static void __remove_discard_cmd(struct f2fs_sb_info *sbi, · 11 unmodified lines | |||
| 1006 | printk_ratelimited( | 1101 | printk_ratelimited( |
| 1007 | "%sF2FS-fs (%s): Issue discard(%u, %u, %u) failed, ret: %d", | 1102 | "%sF2FS-fs (%s): Issue discard(%u, %u, %u) failed, ret: %d", |
| 1008 | KERN_INFO, sbi->sb->s_id, | 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 | __detach_discard_cmd(dcc, dc); | 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 | if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) | 1217 | if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) |
| 1123 | return 0; | 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; | 1222 | lstart = dc->di.lstart; |
| 1128 | start = dc->start; | 1223 | start = dc->di.start; |
| 1129 | len = dc->len; | 1224 | len = dc->di.len; |
| 1130 | total_len = len; | 1225 | total_len = len; |
| 1131 | 1226 | ||
| 1132 | dc->len = 0; | 1227 | dc->di.len = 0; |
| 1133 | 1228 | ||
| 1134 | while (total_len && *issued < dpolicy->max_requests && !err) { | 1229 | while (total_len && *issued < dpolicy->max_requests && !err) { |
| 1135 | struct bio *bio = NULL; | 1230 | struct bio *bio = NULL; |
| @@ -1145,7 +1240,7 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, · 9 unmodified lines | |||
| 1145 | if (*issued == dpolicy->max_requests) | 1240 | if (*issued == dpolicy->max_requests) |
| 1146 | last = true; | 1241 | last = true; |
| 1147 | 1242 | ||
| 1148 | dc->len += len; | 1243 | dc->di.len += len; |
| 1149 | 1244 | ||
| 1150 | if (time_to_inject(sbi, FAULT_DISCARD)) { | 1245 | if (time_to_inject(sbi, FAULT_DISCARD)) { |
| 1151 | err = -EIO; | 1246 | err = -EIO; |
| @@ -1207,34 +1302,41 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, · 55 unmodified lines | |||
| 1207 | return err; | 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 | struct block_device *bdev, block_t lstart, | 1306 | struct block_device *bdev, block_t lstart, |
| 1212 | block_t start, block_t len, | 1307 | block_t start, block_t len) |
| 1213 | struct rb_node **insert_p, | ||
| 1214 | struct rb_node *insert_parent) | ||
| 1215 | { | 1308 | { |
| 1216 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; | 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 | struct rb_node *parent = NULL; | 1311 | struct rb_node *parent = NULL; |
| 1312 | struct discard_cmd *dc; | ||
| 1219 | bool leftmost = true; | 1313 | bool leftmost = true; |
| 1220 | 1314 | ||
| 1221 | if (insert_p && insert_parent) { | 1315 | /* look up rb tree to find parent node */ |
| 1222 | parent = insert_parent; | 1316 | while (*p) { |
| 1223 | p = insert_p; | 1317 | parent = *p; |
| 1224 | goto do_insert; | 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, | 1330 | dc = __create_discard_cmd(sbi, bdev, lstart, start, len); |
| 1228 | lstart, &leftmost); | 1331 | |
| 1229 | do_insert: | 1332 | rb_link_node(&dc->rb_node, parent, p); |
| 1230 | __attach_discard_cmd(sbi, bdev, lstart, start, len, parent, | 1333 | rb_insert_color_cached(&dc->rb_node, &dcc->root, leftmost); |
| 1231 | p, leftmost); | ||
| 1232 | } | 1334 | } |
| 1233 | 1335 | ||
| 1234 | static void __relocate_discard_cmd(struct discard_cmd_control *dcc, | 1336 | static void __relocate_discard_cmd(struct discard_cmd_control *dcc, |
| 1235 | struct discard_cmd *dc) | 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 | static void __punch_discard_cmd(struct f2fs_sb_info *sbi, | 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 | struct discard_info di = dc->di; | 1346 | struct discard_info di = dc->di; |
| 1245 | bool modified = false; | 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 | __remove_discard_cmd(sbi, dc); | 1350 | __remove_discard_cmd(sbi, dc); |
| 1249 | return; | 1351 | return; |
| 1250 | } | 1352 | } |
| @@ -1252,23 +1354,22 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi, · 1 unmodified line | |||
| 1252 | dcc->undiscard_blks -= di.len; | 1354 | dcc->undiscard_blks -= di.len; |
| 1253 | 1355 | ||
| 1254 | if (blkaddr > di.lstart) { | 1356 | if (blkaddr > di.lstart) { |
| 1255 | dc->len = blkaddr - dc->lstart; | 1357 | dc->di.len = blkaddr - dc->di.lstart; |
| 1256 | dcc->undiscard_blks += dc->len; | 1358 | dcc->undiscard_blks += dc->di.len; |
| 1257 | __relocate_discard_cmd(dcc, dc); | 1359 | __relocate_discard_cmd(dcc, dc); |
| 1258 | modified = true; | 1360 | modified = true; |
| 1259 | } | 1361 | } |
| 1260 | 1362 | ||
| 1261 | if (blkaddr < di.lstart + di.len - 1) { | 1363 | if (blkaddr < di.lstart + di.len - 1) { |
| 1262 | if (modified) { | 1364 | if (modified) { |
| 1263 | __insert_discard_tree(sbi, dc->bdev, blkaddr + 1, | 1365 | __insert_discard_cmd(sbi, dc->bdev, blkaddr + 1, |
| 1264 | di.start + blkaddr + 1 - di.lstart, | 1366 | di.start + blkaddr + 1 - di.lstart, |
| 1265 | di.lstart + di.len - 1 - blkaddr, | 1367 | di.lstart + di.len - 1 - blkaddr); |
| 1266 | NULL, NULL); | ||
| 1267 | } else { | 1368 | } else { |
| 1268 | dc->lstart++; | 1369 | dc->di.lstart++; |
| 1269 | dc->len--; | 1370 | dc->di.len--; |
| 1270 | dc->start++; | 1371 | dc->di.start++; |
| 1271 | dcc->undiscard_blks += dc->len; | 1372 | dcc->undiscard_blks += dc->di.len; |
| 1272 | __relocate_discard_cmd(dcc, dc); | 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 | SECTOR_TO_BLOCK(bdev_max_discard_sectors(bdev)); | 1388 | SECTOR_TO_BLOCK(bdev_max_discard_sectors(bdev)); |
| 1288 | block_t end = lstart + len; | 1389 | block_t end = lstart + len; |
| 1289 | 1390 | ||
| 1290 | dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root, | 1391 | dc = __lookup_discard_cmd_ret(&dcc->root, lstart, |
| 1291 | NULL, lstart, | 1392 | &prev_dc, &next_dc, &insert_p, &insert_parent); |
| 1292 | (struct rb_entry **)&prev_dc, | ||
| 1293 | (struct rb_entry **)&next_dc, | ||
| 1294 | &insert_p, &insert_parent, true, NULL); | ||
| 1295 | if (dc) | 1393 | if (dc) |
| 1296 | prev_dc = dc; | 1394 | prev_dc = dc; |
| 1297 | 1395 | ||
| 1298 | if (!prev_dc) { | 1396 | if (!prev_dc) { |
| 1299 | di.lstart = lstart; | 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 | di.len = min(di.len, len); | 1399 | di.len = min(di.len, len); |
| 1302 | di.start = start; | 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 | struct discard_cmd *tdc = NULL; | 1406 | struct discard_cmd *tdc = NULL; |
| 1309 | 1407 | ||
| 1310 | if (prev_dc) { | 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 | if (di.lstart < lstart) | 1410 | if (di.lstart < lstart) |
| 1313 | di.lstart = lstart; | 1411 | di.lstart = lstart; |
| 1314 | if (di.lstart >= end) | 1412 | if (di.lstart >= end) |
| 1315 | break; | 1413 | break; |
| 1316 | 1414 | ||
| 1317 | if (!next_dc || next_dc->lstart > end) | 1415 | if (!next_dc || next_dc->di.lstart > end) |
| 1318 | di.len = end - di.lstart; | 1416 | di.len = end - di.lstart; |
| 1319 | else | 1417 | else |
| 1320 | di.len = next_dc->lstart - di.lstart; | 1418 | di.len = next_dc->di.lstart - di.lstart; |
| 1321 | di.start = start + di.lstart - lstart; | 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 | merged = true; | 1448 | merged = true; |
| 1351 | } | 1449 | } |
| 1352 | 1450 | ||
| 1353 | if (!merged) { | 1451 | if (!merged) |
| 1354 | __insert_discard_tree(sbi, bdev, di.lstart, di.start, | 1452 | __insert_discard_cmd(sbi, bdev, |
| 1355 | di.len, NULL, NULL); | 1453 | di.lstart, di.start, di.len); |
| 1356 | } | ||
| 1357 | next: | 1454 | next: |
| 1358 | prev_dc = next_dc; | 1455 | prev_dc = next_dc; |
| 1359 | if (!prev_dc) | 1456 | if (!prev_dc) |
| @@ -1392,15 +1489,11 @@ static void __issue_discard_cmd_orderly(struct f2fs_sb_info *sbi, · 32 unmodified lines | |||
| 1392 | struct rb_node **insert_p = NULL, *insert_parent = NULL; | 1489 | struct rb_node **insert_p = NULL, *insert_parent = NULL; |
| 1393 | struct discard_cmd *dc; | 1490 | struct discard_cmd *dc; |
| 1394 | struct blk_plug plug; | 1491 | struct blk_plug plug; |
| 1395 | unsigned int pos = dcc->next_pos; | ||
| 1396 | bool io_interrupted = false; | 1492 | bool io_interrupted = false; |
| 1397 | 1493 | ||
| 1398 | mutex_lock(&dcc->cmd_lock); | 1494 | mutex_lock(&dcc->cmd_lock); |
| 1399 | dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root, | 1495 | dc = __lookup_discard_cmd_ret(&dcc->root, dcc->next_pos, |
| 1400 | NULL, pos, | 1496 | &prev_dc, &next_dc, &insert_p, &insert_parent); |
| 1401 | (struct rb_entry **)&prev_dc, | ||
| 1402 | (struct rb_entry **)&next_dc, | ||
| 1403 | &insert_p, &insert_parent, true, NULL); | ||
| 1404 | if (!dc) | 1497 | if (!dc) |
| 1405 | dc = next_dc; | 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 | break; | 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 | err = __submit_discard_cmd(sbi, dpolicy, dc, issued); | 1515 | err = __submit_discard_cmd(sbi, dpolicy, dc, issued); |
| 1423 | 1516 | ||
| 1424 | if (*issued >= dpolicy->max_requests) | 1517 | if (*issued >= dpolicy->max_requests) |
| @@ -1477,8 +1570,7 @@ retry: · 52 unmodified lines | |||
| 1477 | if (list_empty(pend_list)) | 1570 | if (list_empty(pend_list)) |
| 1478 | goto next; | 1571 | goto next; |
| 1479 | if (unlikely(dcc->rbtree_check)) | 1572 | if (unlikely(dcc->rbtree_check)) |
| 1480 | f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi, | 1573 | f2fs_bug_on(sbi, !f2fs_check_discard_tree(sbi)); |
| 1481 | &dcc->root, false)); | ||
| 1482 | blk_start_plug(&plug); | 1574 | blk_start_plug(&plug); |
| 1483 | list_for_each_entry_safe(dc, tmp, pend_list, list) { | 1575 | list_for_each_entry_safe(dc, tmp, pend_list, list) { |
| 1484 | f2fs_bug_on(sbi, dc->state != D_PREP); | 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 | dc->ref--; | 1648 | dc->ref--; |
| 1557 | if (!dc->ref) { | 1649 | if (!dc->ref) { |
| 1558 | if (!dc->error) | 1650 | if (!dc->error) |
| 1559 | len = dc->len; | 1651 | len = dc->di.len; |
| 1560 | __remove_discard_cmd(sbi, dc); | 1652 | __remove_discard_cmd(sbi, dc); |
| 1561 | } | 1653 | } |
| 1562 | mutex_unlock(&dcc->cmd_lock); | 1654 | mutex_unlock(&dcc->cmd_lock); |
| @@ -1579,14 +1671,15 @@ next: · 16 unmodified lines | |||
| 1579 | 1671 | ||
| 1580 | mutex_lock(&dcc->cmd_lock); | 1672 | mutex_lock(&dcc->cmd_lock); |
| 1581 | list_for_each_entry_safe(iter, tmp, wait_list, list) { | 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 | continue; | 1676 | continue; |
| 1584 | if (iter->len < dpolicy->granularity) | 1677 | if (iter->di.len < dpolicy->granularity) |
| 1585 | continue; | 1678 | continue; |
| 1586 | if (iter->state == D_DONE && !iter->ref) { | 1679 | if (iter->state == D_DONE && !iter->ref) { |
| 1587 | wait_for_completion_io(&iter->wait); | 1680 | wait_for_completion_io(&iter->wait); |
| 1588 | if (!iter->error) | 1681 | if (!iter->error) |
| 1589 | trimmed += iter->len; | 1682 | trimmed += iter->di.len; |
| 1590 | __remove_discard_cmd(sbi, iter); | 1683 | __remove_discard_cmd(sbi, iter); |
| 1591 | } else { | 1684 | } else { |
| 1592 | iter->ref++; | 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 | bool need_wait = false; | 1723 | bool need_wait = false; |
| 1631 | 1724 | ||
| 1632 | mutex_lock(&dcc->cmd_lock); | 1725 | mutex_lock(&dcc->cmd_lock); |
| 1633 | dc = (struct discard_cmd *)f2fs_lookup_rb_tree(&dcc->root, | 1726 | dc = __lookup_discard_cmd(sbi, blkaddr); |
| 1634 | NULL, blkaddr); | ||
| 1635 | if (dc) { | 1727 | if (dc) { |
| 1636 | if (dc->state == D_PREP) { | 1728 | if (dc->state == D_PREP) { |
| 1637 | __punch_discard_cmd(sbi, dc, blkaddr); | 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 | sector_t sector, nr_sects; | 1852 | sector_t sector, nr_sects; |
| 1761 | block_t lblkstart = blkstart; | 1853 | block_t lblkstart = blkstart; |
| 1762 | int devi = 0; | 1854 | int devi = 0; |
| 1855 | u64 remainder = 0; | ||
| 1763 | 1856 | ||
| 1764 | if (f2fs_is_multi_device(sbi)) { | 1857 | if (f2fs_is_multi_device(sbi)) { |
| 1765 | devi = f2fs_target_device_index(sbi, blkstart); | 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 | if (f2fs_blkz_is_seq(sbi, devi, blkstart)) { | 1868 | if (f2fs_blkz_is_seq(sbi, devi, blkstart)) { |
| 1776 | sector = SECTOR_FROM_BLOCK(blkstart); | 1869 | sector = SECTOR_FROM_BLOCK(blkstart); |
| 1777 | nr_sects = SECTOR_FROM_BLOCK(blklen); | 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) || | 1873 | if (remainder || nr_sects != bdev_zone_sectors(bdev)) { |
| 1780 | nr_sects != bdev_zone_sectors(bdev)) { | ||
| 1781 | f2fs_err(sbi, "(%d) %s: Unaligned zone reset attempted (block %x + %x)", | 1874 | f2fs_err(sbi, "(%d) %s: Unaligned zone reset attempted (block %x + %x)", |
| 1782 | devi, sbi->s_ndevs ? FDEV(devi).path : "", | 1875 | devi, sbi->s_ndevs ? FDEV(devi).path : "", |
| 1783 | blkstart, blklen); | 1876 | blkstart, blklen); |
| @@ -1982,9 +2075,11 @@ void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi, · 198 unmodified lines | |||
| 1982 | 2075 | ||
| 1983 | if (force && start >= cpc->trim_start && | 2076 | if (force && start >= cpc->trim_start && |
| 1984 | (end - 1) <= cpc->trim_end) | 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 | f2fs_issue_discard(sbi, START_BLOCK(sbi, start), | 2083 | f2fs_issue_discard(sbi, START_BLOCK(sbi, start), |
| 1989 | (end - start) << sbi->log_blocks_per_seg); | 2084 | (end - start) << sbi->log_blocks_per_seg); |
| 1990 | continue; | 2085 | continue; |
| @@ -2787,7 +2882,6 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type, · 796 unmodified lines | |||
| 2787 | int alloc_mode, unsigned long long age) | 2882 | int alloc_mode, unsigned long long age) |
| 2788 | { | 2883 | { |
| 2789 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 2884 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
| 2790 | const struct victim_selection *v_ops = DIRTY_I(sbi)->v_ops; | ||
| 2791 | unsigned segno = NULL_SEGNO; | 2885 | unsigned segno = NULL_SEGNO; |
| 2792 | unsigned short seg_type = curseg->seg_type; | 2886 | unsigned short seg_type = curseg->seg_type; |
| 2793 | int i, cnt; | 2887 | int i, cnt; |
| @@ -2796,7 +2890,7 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type, · 2 unmodified lines | |||
| 2796 | sanity_check_seg_type(sbi, seg_type); | 2890 | sanity_check_seg_type(sbi, seg_type); |
| 2797 | 2891 | ||
| 2798 | /* f2fs_need_SSR() already forces to do this */ | 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 | curseg->next_segno = segno; | 2894 | curseg->next_segno = segno; |
| 2801 | return 1; | 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 | for (; cnt-- > 0; reversed ? i-- : i++) { | 2917 | for (; cnt-- > 0; reversed ? i-- : i++) { |
| 2824 | if (i == seg_type) | 2918 | if (i == seg_type) |
| 2825 | continue; | 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 | curseg->next_segno = segno; | 2921 | curseg->next_segno = segno; |
| 2828 | return 1; | 2922 | return 1; |
| 2829 | } | 2923 | } |
| @@ -2964,24 +3058,20 @@ next: · 134 unmodified lines | |||
| 2964 | 3058 | ||
| 2965 | mutex_lock(&dcc->cmd_lock); | 3059 | mutex_lock(&dcc->cmd_lock); |
| 2966 | if (unlikely(dcc->rbtree_check)) | 3060 | if (unlikely(dcc->rbtree_check)) |
| 2967 | f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi, | 3061 | f2fs_bug_on(sbi, !f2fs_check_discard_tree(sbi)); |
| 2968 | &dcc->root, false)); | 3062 | |
| 2969 | 3063 | dc = __lookup_discard_cmd_ret(&dcc->root, start, | |
| 2970 | dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root, | 3064 | &prev_dc, &next_dc, &insert_p, &insert_parent); |
| 2971 | NULL, start, | ||
| 2972 | (struct rb_entry **)&prev_dc, | ||
| 2973 | (struct rb_entry **)&next_dc, | ||
| 2974 | &insert_p, &insert_parent, true, NULL); | ||
| 2975 | if (!dc) | 3065 | if (!dc) |
| 2976 | dc = next_dc; | 3066 | dc = next_dc; |
| 2977 | 3067 | ||
| 2978 | blk_start_plug(&plug); | 3068 | blk_start_plug(&plug); |
| 2979 | 3069 | ||
| 2980 | while (dc && dc->lstart <= end) { | 3070 | while (dc && dc->di.lstart <= end) { |
| 2981 | struct rb_node *node; | 3071 | struct rb_node *node; |
| 2982 | int err = 0; | 3072 | int err = 0; |
| 2983 | 3073 | ||
| 2984 | if (dc->len < dpolicy->granularity) | 3074 | if (dc->di.len < dpolicy->granularity) |
| 2985 | goto skip; | 3075 | goto skip; |
| 2986 | 3076 | ||
| 2987 | if (dc->state != D_PREP) { | 3077 | if (dc->state != D_PREP) { |
| @@ -2992,7 +3082,7 @@ next: · 4 unmodified lines | |||
| 2992 | err = __submit_discard_cmd(sbi, dpolicy, dc, &issued); | 3082 | err = __submit_discard_cmd(sbi, dpolicy, dc, &issued); |
| 2993 | 3083 | ||
| 2994 | if (issued >= dpolicy->max_requests) { | 3084 | if (issued >= dpolicy->max_requests) { |
| 2995 | start = dc->lstart + dc->len; | 3085 | start = dc->di.lstart + dc->di.len; |
| 2996 | 3086 | ||
| 2997 | if (err) | 3087 | if (err) |
| 2998 | __remove_discard_cmd(sbi, dc); | 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 | "New zone for curseg[%d] is not yet discarded. " | 4949 | "New zone for curseg[%d] is not yet discarded. " |
| 4860 | "Reset the zone: curseg[0x%x,0x%x]", | 4950 | "Reset the zone: curseg[0x%x,0x%x]", |
| 4861 | type, cs->segno, cs->next_blkoff); | 4951 | type, cs->segno, cs->next_blkoff); |
| 4862 | err = __f2fs_issue_discard_zone(sbi, zbd->bdev, | 4952 | err = __f2fs_issue_discard_zone(sbi, zbd->bdev, cs_zone_block, |
| 4863 | zone_sector >> log_sectors_per_block, | 4953 | zone.len >> log_sectors_per_block); |
| 4864 | zone.len >> log_sectors_per_block); | ||
| 4865 | if (err) { | 4954 | if (err) { |
| 4866 | f2fs_err(sbi, "Discard zone failed: %s (errno=%d)", | 4955 | f2fs_err(sbi, "Discard zone failed: %s (errno=%d)", |
| 4867 | zbd->path, err); | 4956 | zbd->path, err); |
| @@ -4920,48 +5009,6 @@ int f2fs_check_write_pointer(struct f2fs_sb_info *sbi) · 52 unmodified lines | |||
| 4920 | return 0; | 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 | * Return the number of usable blocks in a segment. The number of blocks | 5013 | * Return the number of usable blocks in a segment. The number of blocks |
| 4967 | * returned is always equal to the number of blocks in a segment for | 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 | struct f2fs_sb_info *sbi, unsigned int segno) | 5021 | struct f2fs_sb_info *sbi, unsigned int segno) |
| 4975 | { | 5022 | { |
| 4976 | block_t seg_start, sec_start_blkaddr, sec_cap_blkaddr; | 5023 | block_t seg_start, sec_start_blkaddr, sec_cap_blkaddr; |
| 4977 | unsigned int zone_idx, dev_idx, secno; | 5024 | unsigned int 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; | ||
| 4990 | 5025 | ||
| 4991 | if (!sbi->unusable_blocks_per_sec) | 5026 | if (!sbi->unusable_blocks_per_sec) |
| 4992 | return sbi->blocks_per_seg; | 5027 | return sbi->blocks_per_seg; |
| 4993 | 5028 | ||
| 5029 | secno = GET_SEC_FROM_SEG(sbi, segno); | ||
| 5030 | seg_start = START_BLOCK(sbi, segno); | ||
| 4994 | sec_start_blkaddr = START_BLOCK(sbi, GET_SEG_FROM_SEC(sbi, secno)); | 5031 | sec_start_blkaddr = START_BLOCK(sbi, GET_SEG_FROM_SEC(sbi, secno)); |
| 4995 | sec_cap_blkaddr = sec_start_blkaddr + CAP_BLKS_PER_SEC(sbi); | 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 | return 0; | 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 | #endif | 5064 | #endif |
| 5033 | unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi, | 5065 | unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi, |
| 5034 | unsigned int segno) | 5066 | unsigned int segno) |
| @@ -5043,7 +5075,7 @@ unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi, · 8 unmodified lines | |||
| 5043 | unsigned int segno) | 5075 | unsigned int segno) |
| 5044 | { | 5076 | { |
| 5045 | if (f2fs_sb_has_blkzoned(sbi)) | 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 | return sbi->segs_per_sec; | 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 | #define CAP_BLKS_PER_SEC(sbi) \ | 104 | #define CAP_BLKS_PER_SEC(sbi) \ |
| 105 | ((sbi)->segs_per_sec * (sbi)->blocks_per_seg - \ | 105 | ((sbi)->segs_per_sec * (sbi)->blocks_per_seg - \ |
| 106 | (sbi)->unusable_blocks_per_sec) | 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 | #define GET_SEC_FROM_SEG(sbi, segno) \ | 110 | #define GET_SEC_FROM_SEG(sbi, segno) \ |
| 108 | (((segno) == -1) ? -1: (segno) / (sbi)->segs_per_sec) | 111 | (((segno) == -1) ? -1: (segno) / (sbi)->segs_per_sec) |
| 109 | #define GET_SEG_FROM_SEC(sbi, secno) \ | 112 | #define GET_SEG_FROM_SEC(sbi, secno) \ |
| @@ -286,7 +289,6 @@ enum dirty_type { · 176 unmodified lines | |||
| 286 | }; | 289 | }; |
| 287 | 290 | ||
| 288 | struct dirty_seglist_info { | 291 | struct dirty_seglist_info { |
| 289 | const struct victim_selection *v_ops; /* victim selction operation */ | ||
| 290 | unsigned long *dirty_segmap[NR_DIRTY_TYPE]; | 292 | unsigned long *dirty_segmap[NR_DIRTY_TYPE]; |
| 291 | unsigned long *dirty_secmap; | 293 | unsigned long *dirty_secmap; |
| 292 | struct mutex seglist_lock; /* lock for segment bitmaps */ | 294 | struct mutex seglist_lock; /* lock for segment bitmaps */ |
| @@ -297,12 +299,6 @@ struct dirty_seglist_info { · 4 unmodified lines | |||
| 297 | bool enable_pin_section; /* enable pinning section */ | 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 | /* for active log information */ | 302 | /* for active log information */ |
| 307 | struct curseg_info { | 303 | struct curseg_info { |
| 308 | struct mutex curseg_mutex; /* lock for consistency */ | 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 | return true; | 595 | return true; |
| 600 | } | 596 | } |
| 601 | 597 | ||
| 602 | static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, | 598 | /* |
| 603 | int freed, int needed) | 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 | unsigned int total_node_blocks = get_pages(sbi, F2FS_DIRTY_NODES) + | 605 | unsigned int total_node_blocks = get_pages(sbi, F2FS_DIRTY_NODES) + |
| 606 | get_pages(sbi, F2FS_DIRTY_DENTS) + | 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 | unsigned int dent_secs = total_dent_blocks / CAP_BLKS_PER_SEC(sbi); | 610 | unsigned int dent_secs = total_dent_blocks / CAP_BLKS_PER_SEC(sbi); |
| 611 | unsigned int node_blocks = total_node_blocks % CAP_BLKS_PER_SEC(sbi); | 611 | unsigned int node_blocks = total_node_blocks % CAP_BLKS_PER_SEC(sbi); |
| 612 | unsigned int dent_blocks = total_dent_blocks % CAP_BLKS_PER_SEC(sbi); | 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 | if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) | 630 | if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) |
| 616 | return false; | 631 | return false; |
| 617 | 632 | ||
| 618 | free = free_sections(sbi) + freed; | 633 | __get_secs_required(sbi, &lower_secs, &upper_secs, &curseg_space); |
| 619 | need_lower = node_secs + dent_secs + reserved_sections(sbi) + needed; | 634 | |
| 620 | need_upper = need_lower + (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0); | 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 | return false; | 640 | return false; |
| 624 | else if (free <= need_lower) | 641 | else if (free_secs <= lower_secs) |
| 625 | return true; | 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 | static inline bool f2fs_is_checkpoint_ready(struct f2fs_sb_info *sbi) | 652 | static inline bool f2fs_is_checkpoint_ready(struct f2fs_sb_info *sbi) |
| 630 | { | 653 | { |
| 631 | if (likely(!is_sbi_flag_set(sbi, SBI_CP_DISABLED))) | 654 | if (likely(!is_sbi_flag_set(sbi, SBI_CP_DISABLED))) |
| 632 | return true; | 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 | return true; | 657 | return true; |
| 635 | return false; | 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 | if (args->from && match_int(args, &arg)) | 880 | if (args->from && match_int(args, &arg)) |
| 881 | return -EINVAL; | 881 | return -EINVAL; |
| 882 | if (arg <= 0 || arg > __ilog2_u32(BIO_MAX_VECS)) { | 882 | if (arg <= 0 || arg > __ilog2_u32(BIO_MAX_VECS)) { |
| 883 | f2fs_warn(sbi, "Not support %d, larger than %d", | 883 | f2fs_warn(sbi, "Not support %ld, larger than %d", |
| 884 | 1 << arg, BIO_MAX_VECS); | 884 | BIT(arg), BIO_MAX_VECS); |
| 885 | return -EINVAL; | 885 | return -EINVAL; |
| 886 | } | 886 | } |
| 887 | F2FS_OPTION(sbi).write_io_size_bits = arg; | 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 | kfree(name); | 1179 | kfree(name); |
| 1180 | break; | 1180 | break; |
| 1181 | case Opt_compress_chksum: | 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 | F2FS_OPTION(sbi).compress_chksum = true; | 1186 | F2FS_OPTION(sbi).compress_chksum = true; |
| 1183 | break; | 1187 | break; |
| 1184 | case Opt_compress_mode: | 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 | name = match_strdup(&args[0]); | 1193 | name = match_strdup(&args[0]); |
| 1186 | if (!name) | 1194 | if (!name) |
| 1187 | return -ENOMEM; | 1195 | return -ENOMEM; |
| @@ -1196,6 +1204,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) · 8 unmodified lines | |||
| 1196 | kfree(name); | 1204 | kfree(name); |
| 1197 | break; | 1205 | break; |
| 1198 | case Opt_compress_cache: | 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 | set_opt(sbi, COMPRESS_CACHE); | 1211 | set_opt(sbi, COMPRESS_CACHE); |
| 1200 | break; | 1212 | break; |
| 1201 | #else | 1213 | #else |
| @@ -1310,7 +1322,7 @@ default_check: · 108 unmodified lines | |||
| 1310 | #endif | 1322 | #endif |
| 1311 | 1323 | ||
| 1312 | if (F2FS_IO_SIZE_BITS(sbi) && !f2fs_lfs_mode(sbi)) { | 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 | F2FS_IO_SIZE_KB(sbi)); | 1326 | F2FS_IO_SIZE_KB(sbi)); |
| 1315 | return -EINVAL; | 1327 | return -EINVAL; |
| 1316 | } | 1328 | } |
| @@ -2060,10 +2072,12 @@ static void default_options(struct f2fs_sb_info *sbi) · 743 unmodified lines | |||
| 2060 | F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX; | 2072 | F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX; |
| 2061 | F2FS_OPTION(sbi).s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID); | 2073 | F2FS_OPTION(sbi).s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID); |
| 2062 | F2FS_OPTION(sbi).s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID); | 2074 | F2FS_OPTION(sbi).s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID); |
| 2063 | F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZ4; | 2075 | if (f2fs_sb_has_compression(sbi)) { |
| 2064 | F2FS_OPTION(sbi).compress_log_size = MIN_COMPRESS_LOG_SIZE; | 2076 | F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZ4; |
| 2065 | F2FS_OPTION(sbi).compress_ext_cnt = 0; | 2077 | F2FS_OPTION(sbi).compress_log_size = MIN_COMPRESS_LOG_SIZE; |
| 2066 | F2FS_OPTION(sbi).compress_mode = COMPR_MODE_FS; | 2078 | F2FS_OPTION(sbi).compress_ext_cnt = 0; |
| 2079 | F2FS_OPTION(sbi).compress_mode = COMPR_MODE_FS; | ||
| 2080 | } | ||
| 2067 | F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON; | 2081 | F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON; |
| 2068 | F2FS_OPTION(sbi).memory_mode = MEMORY_MODE_NORMAL; | 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 | if (f2fs_readonly(sb) && (*flags & SB_RDONLY)) | 2288 | if (f2fs_readonly(sb) && (*flags & SB_RDONLY)) |
| 2275 | goto skip; | 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 | err = -EROFS; | 2292 | err = -EROFS; |
| 2279 | goto restore_opts; | 2293 | goto restore_opts; |
| 2280 | } | 2294 | } |
| @@ -2487,6 +2501,54 @@ restore_opts: · 206 unmodified lines | |||
| 2487 | } | 2501 | } |
| 2488 | 2502 | ||
| 2489 | #ifdef CONFIG_QUOTA | 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 | /* Read data from quotafile */ | 2552 | /* Read data from quotafile */ |
| 2491 | static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, | 2553 | static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, |
| 2492 | size_t len, loff_t off) | 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 | raw_super->segment_count = cpu_to_le32((main_end_blkaddr - | 3322 | raw_super->segment_count = cpu_to_le32((main_end_blkaddr - |
| 3261 | segment0_blkaddr) >> log_blocks_per_seg); | 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 | set_sbi_flag(sbi, SBI_NEED_SB_WRITE); | 3326 | set_sbi_flag(sbi, SBI_NEED_SB_WRITE); |
| 3265 | res = "internally"; | 3327 | res = "internally"; |
| 3266 | } else { | 3328 | } else { |
| @@ -3348,7 +3410,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, · 81 unmodified lines | |||
| 3348 | total_sections = le32_to_cpu(raw_super->section_count); | 3410 | total_sections = le32_to_cpu(raw_super->section_count); |
| 3349 | 3411 | ||
| 3350 | /* blocks_per_seg should be 512, given the above check */ | 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 | if (segment_count > F2FS_MAX_SEGMENT || | 3415 | if (segment_count > F2FS_MAX_SEGMENT || |
| 3354 | segment_count < F2FS_MIN_SEGMENTS) { | 3416 | segment_count < F2FS_MIN_SEGMENTS) { |
| @@ -3617,9 +3679,9 @@ static void init_sb_info(struct f2fs_sb_info *sbi) · 262 unmodified lines | |||
| 3617 | sbi->log_sectors_per_block = | 3679 | sbi->log_sectors_per_block = |
| 3618 | le32_to_cpu(raw_super->log_sectors_per_block); | 3680 | le32_to_cpu(raw_super->log_sectors_per_block); |
| 3619 | sbi->log_blocksize = le32_to_cpu(raw_super->log_blocksize); | 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 | sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg); | 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 | sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec); | 3685 | sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec); |
| 3624 | sbi->secs_per_zone = le32_to_cpu(raw_super->secs_per_zone); | 3686 | sbi->secs_per_zone = le32_to_cpu(raw_super->secs_per_zone); |
| 3625 | sbi->total_sections = le32_to_cpu(raw_super->section_count); | 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 | SECTOR_TO_BLOCK(zone_sectors)) | 3806 | SECTOR_TO_BLOCK(zone_sectors)) |
| 3745 | return -EINVAL; | 3807 | return -EINVAL; |
| 3746 | sbi->blocks_per_blkz = SECTOR_TO_BLOCK(zone_sectors); | 3808 | sbi->blocks_per_blkz = SECTOR_TO_BLOCK(zone_sectors); |
| 3747 | if (sbi->log_blocks_per_blkz && sbi->log_blocks_per_blkz != | 3809 | FDEV(devi).nr_blkz = div_u64(SECTOR_TO_BLOCK(nr_sectors), |
| 3748 | __ilog2_u32(sbi->blocks_per_blkz)) | 3810 | 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; | ||
| 3753 | if (nr_sectors & (zone_sectors - 1)) | 3811 | if (nr_sectors & (zone_sectors - 1)) |
| 3754 | FDEV(devi).nr_blkz++; | 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 | int err; | 3894 | int err; |
| 3837 | 3895 | ||
| 3838 | if ((recover && f2fs_readonly(sbi->sb)) || | 3896 | if ((recover && f2fs_readonly(sbi->sb)) || |
| 3839 | bdev_read_only(sbi->sb->s_bdev)) { | 3897 | f2fs_hw_is_readonly(sbi)) { |
| 3840 | set_sbi_flag(sbi, SBI_NEED_SB_WRITE); | 3898 | set_sbi_flag(sbi, SBI_NEED_SB_WRITE); |
| 3841 | return -EROFS; | 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 | f2fs_down_write(&sbi->sb_lock); | 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 | raw_super->s_stop_reason[reason]++; | 3937 | raw_super->s_stop_reason[reason]++; |
| 3880 | 3938 | ||
| 3881 | err = f2fs_commit_super(sbi, false); | 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 | f2fs_up_write(&sbi->sb_lock); | 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 | spin_lock(&sbi->error_lock); | 3948 | spin_lock(&sbi->error_lock); |
| 3891 | if (!test_bit(flag, (unsigned long *)sbi->errors)) { | 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 | FDEV(i).start_blk, FDEV(i).end_blk); | 4083 | FDEV(i).start_blk, FDEV(i).end_blk); |
| 4026 | } | 4084 | } |
| 4027 | f2fs_info(sbi, | 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 | return 0; | 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 | int recovery, i, valid_super_block; | 4160 | int recovery, i, valid_super_block; |
| 4103 | struct curseg_info *seg_i; | 4161 | struct curseg_info *seg_i; |
| 4104 | int retry_cnt = 1; | 4162 | int retry_cnt = 1; |
| 4163 | #ifdef CONFIG_QUOTA | ||
| 4164 | bool quota_enabled = false; | ||
| 4165 | #endif | ||
| 4105 | 4166 | ||
| 4106 | try_onemore: | 4167 | try_onemore: |
| 4107 | err = -EINVAL; | 4168 | err = -EINVAL; |
| @@ -4395,6 +4456,8 @@ try_onemore: · 287 unmodified lines | |||
| 4395 | if (err) | 4456 | if (err) |
| 4396 | f2fs_err(sbi, "Cannot turn on quotas: error %d", err); | 4457 | f2fs_err(sbi, "Cannot turn on quotas: error %d", err); |
| 4397 | } | 4458 | } |
| 4459 | |||
| 4460 | quota_enabled = f2fs_recover_quota_begin(sbi); | ||
| 4398 | #endif | 4461 | #endif |
| 4399 | /* if there are any orphan inodes, free them */ | 4462 | /* if there are any orphan inodes, free them */ |
| 4400 | err = f2fs_recover_orphan_inodes(sbi); | 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 | * If the f2fs is not readonly and fsync data recovery succeeds, | 4523 | * If the f2fs is not readonly and fsync data recovery succeeds, |
| 4457 | * check zoned block devices' write pointer consistency. | 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 | if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) { | 313 | if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) { |
| 314 | struct ckpt_req_control *cprc = &sbi->cprc_info; | 314 | struct ckpt_req_control *cprc = &sbi->cprc_info; |
| 315 | int len = 0; | ||
| 316 | int class = IOPRIO_PRIO_CLASS(cprc->ckpt_thread_ioprio); | 315 | int class = IOPRIO_PRIO_CLASS(cprc->ckpt_thread_ioprio); |
| 317 | int data = IOPRIO_PRIO_DATA(cprc->ckpt_thread_ioprio); | 316 | int data = IOPRIO_PRIO_DATA(cprc->ckpt_thread_ioprio); |
| 318 | 317 | ||
| 319 | if (class == IOPRIO_CLASS_RT) | 318 | if (class != IOPRIO_CLASS_RT && class != IOPRIO_CLASS_BE) |
| 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 | ||
| 324 | return -EINVAL; | 319 | return -EINVAL; |
| 325 | 320 | ||
| 326 | len += scnprintf(buf + len, PAGE_SIZE - len, "%d\n", data); | 321 | return sysfs_emit(buf, "%s,%d\n", |
| 327 | return len; | 322 | class == IOPRIO_CLASS_RT ? "rt" : "be", data); |
| 328 | } | 323 | } |
| 329 | 324 | ||
| 330 | #ifdef CONFIG_F2FS_FS_COMPRESSION | 325 | #ifdef CONFIG_F2FS_FS_COMPRESSION |
| @@ -452,7 +447,7 @@ out: · 121 unmodified lines | |||
| 452 | if (ret < 0) | 447 | if (ret < 0) |
| 453 | return ret; | 448 | return ret; |
| 454 | #ifdef CONFIG_F2FS_FAULT_INJECTION | 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 | return -EINVAL; | 451 | return -EINVAL; |
| 457 | if (a->struct_type == FAULT_INFO_RATE && t >= UINT_MAX) | 452 | if (a->struct_type == FAULT_INFO_RATE && t >= UINT_MAX) |
| 458 | return -EINVAL; | 453 | return -EINVAL; |
| @@ -575,9 +570,9 @@ out: · 116 unmodified lines | |||
| 575 | if (!strcmp(a->attr.name, "iostat_period_ms")) { | 570 | if (!strcmp(a->attr.name, "iostat_period_ms")) { |
| 576 | if (t < MIN_IOSTAT_PERIOD_MS || t > MAX_IOSTAT_PERIOD_MS) | 571 | if (t < MIN_IOSTAT_PERIOD_MS || t > MAX_IOSTAT_PERIOD_MS) |
| 577 | return -EINVAL; | 572 | return -EINVAL; |
| 578 | spin_lock(&sbi->iostat_lock); | 573 | spin_lock_irq(&sbi->iostat_lock); |
| 579 | sbi->iostat_period_ms = (unsigned int)t; | 574 | sbi->iostat_period_ms = (unsigned int)t; |
| 580 | spin_unlock(&sbi->iostat_lock); | 575 | spin_unlock_irq(&sbi->iostat_lock); |
| 581 | return count; | 576 | return count; |
| 582 | } | 577 | } |
| 583 | #endif | 578 | #endif |
| @@ -598,6 +593,20 @@ out: · 14 unmodified lines | |||
| 598 | sbi->compr_new_inode = 0; | 593 | sbi->compr_new_inode = 0; |
| 599 | return count; | 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 | #endif | 610 | #endif |
| 602 | 611 | ||
| 603 | if (!strcmp(a->attr.name, "atgc_candidate_ratio")) { | 612 | if (!strcmp(a->attr.name, "atgc_candidate_ratio")) { |
| @@ -950,6 +959,8 @@ F2FS_FEATURE_RO_ATTR(compression); · 346 unmodified lines | |||
| 950 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_written_block, compr_written_block); | 959 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_written_block, compr_written_block); |
| 951 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_saved_block, compr_saved_block); | 960 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_saved_block, compr_saved_block); |
| 952 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_new_inode, compr_new_inode); | 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 | #endif | 964 | #endif |
| 954 | F2FS_FEATURE_RO_ATTR(pin_file); | 965 | F2FS_FEATURE_RO_ATTR(pin_file); |
| 955 | 966 | ||
| @@ -1057,6 +1068,8 @@ static struct attribute *f2fs_attrs[] = { · 101 unmodified lines | |||
| 1057 | ATTR_LIST(compr_written_block), | 1068 | ATTR_LIST(compr_written_block), |
| 1058 | ATTR_LIST(compr_saved_block), | 1069 | ATTR_LIST(compr_saved_block), |
| 1059 | ATTR_LIST(compr_new_inode), | 1070 | ATTR_LIST(compr_new_inode), |
| 1071 | ATTR_LIST(compress_percent), | ||
| 1072 | ATTR_LIST(compress_watermark), | ||
| 1060 | #endif | 1073 | #endif |
| 1061 | /* For ATGC */ | 1074 | /* For ATGC */ |
| 1062 | ATTR_LIST(atgc_candidate_ratio), | 1075 | ATTR_LIST(atgc_candidate_ratio), |
| @@ -1449,25 +1462,14 @@ put_sb_kobj: · 386 unmodified lines | |||
| 1449 | 1462 | ||
| 1450 | void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi) | 1463 | void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi) |
| 1451 | { | 1464 | { |
| 1452 | if (sbi->s_proc) { | 1465 | if (sbi->s_proc) |
| 1453 | #ifdef CONFIG_F2FS_IOSTAT | 1466 | remove_proc_subtree(sbi->sb->s_id, f2fs_proc_root); |
| 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 | } | ||
| 1462 | 1467 | ||
| 1463 | kobject_del(&sbi->s_stat_kobj); | ||
| 1464 | kobject_put(&sbi->s_stat_kobj); | 1468 | kobject_put(&sbi->s_stat_kobj); |
| 1465 | wait_for_completion(&sbi->s_stat_kobj_unregister); | 1469 | wait_for_completion(&sbi->s_stat_kobj_unregister); |
| 1466 | kobject_del(&sbi->s_feature_list_kobj); | ||
| 1467 | kobject_put(&sbi->s_feature_list_kobj); | 1470 | kobject_put(&sbi->s_feature_list_kobj); |
| 1468 | wait_for_completion(&sbi->s_feature_list_kobj_unregister); | 1471 | wait_for_completion(&sbi->s_feature_list_kobj_unregister); |
| 1469 | 1472 | ||
| 1470 | kobject_del(&sbi->s_kobj); | ||
| 1471 | kobject_put(&sbi->s_kobj); | 1473 | kobject_put(&sbi->s_kobj); |
| 1472 | wait_for_completion(&sbi->s_kobj_unregister); | 1474 | wait_for_completion(&sbi->s_kobj_unregister); |
| 1473 | } | 1475 | } |
| @@ -40,9 +40,8 @@ · 39 unmodified lines | |||
| 40 | 40 | ||
| 41 | #define F2FS_ENC_UTF8_12_1 1 | 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 */ | 43 | #define F2FS_IO_SIZE(sbi) BIT(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 */ | 44 | #define F2FS_IO_SIZE_KB(sbi) BIT(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 */ | ||
| 46 | #define F2FS_IO_SIZE_BITS(sbi) (F2FS_OPTION(sbi).write_io_size_bits) /* power of 2 */ | 45 | #define F2FS_IO_SIZE_BITS(sbi) (F2FS_OPTION(sbi).write_io_size_bits) /* power of 2 */ |
| 47 | #define F2FS_IO_SIZE_MASK(sbi) (F2FS_IO_SIZE(sbi) - 1) | 46 | #define F2FS_IO_SIZE_MASK(sbi) (F2FS_IO_SIZE(sbi) - 1) |
| 48 | #define F2FS_IO_ALIGNED(sbi) (F2FS_IO_SIZE(sbi) > 1) | 47 | #define F2FS_IO_ALIGNED(sbi) (F2FS_IO_SIZE(sbi) > 1) |
| @@ -340,7 +339,7 @@ enum { · 291 unmodified lines | |||
| 340 | OFFSET_BIT_SHIFT | 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 | struct node_footer { | 344 | struct node_footer { |
| 346 | __le32 nid; /* node id */ | 345 | __le32 nid; /* node id */ |
| @@ -545,7 +544,7 @@ typedef __le32 f2fs_hash_t; · 198 unmodified lines | |||
| 545 | #define MAX_DIR_HASH_DEPTH 63 | 544 | #define MAX_DIR_HASH_DEPTH 63 |
| 546 | 545 | ||
| 547 | /* MAX buckets in one level of dir */ | 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 | * space utilization of regular dentry and inline dentry (w/o extra reservation) | 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 | __u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN]; | 584 | __u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN]; |
| 586 | } __packed; | 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 | #define F2FS_DEF_PROJID 0 /* default project ID */ | 587 | #define F2FS_DEF_PROJID 0 /* default project ID */ |
| 604 | 588 | ||
| 605 | #endif /* _LINUX_F2FS_FS_H */ | 589 | #endif /* _LINUX_F2FS_FS_H */ |