mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
f2fs: refresh pinned allocation boundary after resize
Online shrink updates MAIN_SECS() but leaves resizable_tail_secno and
pinned_area_max_secno unchanged. The pinned allocation limit can exceed
the new main area when shrinking beyond the reserved tail.
Consume the reserved tail by the number of removed sections, clamping
it to zero, before refreshing the shared pinned allocation boundary.
This preserves the boundary while shrinking within the reservation and
limits it to the new main area otherwise, retaining the zoned limit.
Save the old tail count and restore it before rolling back the geometry
if the final checkpoint fails.
Also bound pinned section allocation by the current MAIN_SECS(). Range
evacuation temporarily reduces it before moving cursegs, while the
cached pinned boundary still describes the old geometry. Otherwise, a
pinned curseg can be reallocated into the range being removed.
Fixes: c966d29e01 ("f2fs: support resizable tail section and unify pinned allocation")
Suggested-by: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Daeho Jeong <daehojeong@google.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
a6ede40545
commit
e4df12e373
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 :
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user