diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst index 771216f45207..55798421f2c4 100644 --- a/Documentation/filesystems/f2fs.rst +++ b/Documentation/filesystems/f2fs.rst @@ -421,7 +421,8 @@ resizable_tail_secno=%u Control the number of sections at the tail of the (MAIN_SECS - resizable_tail_secno) - 1. If set to 0 (default), there is no tail restriction unless running on a zoned block device where conventional zones are - used. + used. Online shrink consumes this reservation, reducing + the value by the number of removed sections, down to zero. ======================== ============================================================ Debugfs Entries diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 926e6976bc22..540769ad58ac 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -2342,6 +2342,7 @@ static void update_fs_metadata(struct f2fs_sb_info *sbi, int secs) SM_I(sbi)->segment_count = (int)SM_I(sbi)->segment_count + segs; MAIN_SEGS(sbi) = (int)MAIN_SEGS(sbi) + segs; MAIN_SECS(sbi) += secs; + f2fs_adjust_pinned_area_boundary(sbi); if (sbi->allocate_section_hint > MAIN_SECS(sbi)) sbi->allocate_section_hint = MAIN_SECS(sbi); FREE_I(sbi)->free_sections = (int)FREE_I(sbi)->free_sections + secs; @@ -2373,7 +2374,7 @@ int f2fs_resize_fs(struct file *filp, __u64 block_count) struct f2fs_lock_context lc; struct f2fs_lock_context glc; struct f2fs_lock_context clc; - unsigned int secs; + unsigned int secs, old_tail; int err = 0; __u32 rem; @@ -2482,6 +2483,8 @@ int f2fs_resize_fs(struct file *filp, __u64 block_count) goto recover_out; } + old_tail = F2FS_OPTION(sbi).resizable_tail_secno; + F2FS_OPTION(sbi).resizable_tail_secno -= min(old_tail, secs); update_fs_metadata(sbi, -secs); clear_sbi_flag(sbi, SBI_IS_RESIZEFS); set_sbi_flag(sbi, SBI_IS_DIRTY); @@ -2489,6 +2492,7 @@ int f2fs_resize_fs(struct file *filp, __u64 block_count) stat_inc_cp_call_count(sbi, TOTAL_CALL); err = f2fs_write_checkpoint(sbi, &cpc); if (err) { + F2FS_OPTION(sbi).resizable_tail_secno = old_tail; update_fs_metadata(sbi, secs); update_sb_metadata(sbi, secs); f2fs_commit_super(sbi, false); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index bf8d07fcce33..f6e1cb1c0b71 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2983,7 +2983,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi, alloc_hint = MAIN_SECS(sbi); if (pinning) { - max_secno = sbi->pinned_area_max_secno; + max_secno = min(sbi->pinned_area_max_secno, MAIN_SECS(sbi)); hint = 0; } else if (alloc_policy == ALLOCATE_FORWARD_FROM_HINT && hint < alloc_hint) { diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 526764ba31ae..918bc4452ad0 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -91,6 +91,17 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi, #define GET_ZONE_FROM_SEG(sbi, segno) \ GET_ZONE_FROM_SEC(sbi, GET_SEC_FROM_SEG(sbi, segno)) +static inline void f2fs_adjust_pinned_area_boundary(struct f2fs_sb_info *sbi) +{ + sbi->pinned_area_max_secno = MAIN_SECS(sbi); + if (f2fs_sb_has_blkzoned(sbi) && sbi->first_seq_zone_segno != NULL_SEGNO) + sbi->pinned_area_max_secno = min(sbi->pinned_area_max_secno, + GET_SEC_FROM_SEG(sbi, sbi->first_seq_zone_segno)); + if (F2FS_OPTION(sbi).resizable_tail_secno) + sbi->pinned_area_max_secno = min(sbi->pinned_area_max_secno, + MAIN_SECS(sbi) - F2FS_OPTION(sbi).resizable_tail_secno); +} + #define GET_SUM_BLOCK(sbi, segno) \ (SM_I(sbi)->ssa_blkaddr + (segno / (sbi)->sums_per_block)) #define GET_SUM_BLKOFF(sbi, segno) (segno % (sbi)->sums_per_block) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 773b12ea29c0..f323d9705aeb 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -554,17 +554,6 @@ static inline void adjust_unusable_cap_perc(struct f2fs_sb_info *sbi) F2FS_OPTION(sbi).unusable_cap_perc); } -static inline void adjust_pinned_area_boundary(struct f2fs_sb_info *sbi) -{ - sbi->pinned_area_max_secno = MAIN_SECS(sbi); - if (f2fs_sb_has_blkzoned(sbi) && sbi->first_seq_zone_segno != NULL_SEGNO) - sbi->pinned_area_max_secno = min(sbi->pinned_area_max_secno, - GET_SEC_FROM_SEG(sbi, sbi->first_seq_zone_segno)); - if (F2FS_OPTION(sbi).resizable_tail_secno) - sbi->pinned_area_max_secno = min(sbi->pinned_area_max_secno, - MAIN_SECS(sbi) - F2FS_OPTION(sbi).resizable_tail_secno); -} - static void init_once(void *foo) { struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo; @@ -3103,7 +3092,7 @@ static int __f2fs_remount(struct fs_context *fc, struct super_block *sb) sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | (test_opt(sbi, POSIX_ACL) ? SB_POSIXACL : 0); - adjust_pinned_area_boundary(sbi); + f2fs_adjust_pinned_area_boundary(sbi); limit_reserve_root(sbi); fc->sb_flags = (flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME); @@ -5440,7 +5429,7 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc) /* get segno of first zoned block device */ sbi->first_seq_zone_segno = get_first_seq_zone_segno(sbi); - adjust_pinned_area_boundary(sbi); + f2fs_adjust_pinned_area_boundary(sbi); sbi->reserved_pin_section = f2fs_sb_has_blkzoned(sbi) ? ZONED_PIN_SEC_REQUIRED_COUNT :