All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] f2fs: support pinned boundary section and unify pinned allocation
@ 2026-08-18 19:51 ` Daeho Jeong
  0 siblings, 0 replies; 4+ messages in thread
From: Daeho Jeong @ 2026-08-18 19:51 UTC (permalink / raw)
  To: linux-kernel, linux-f2fs-devel, kernel-team; +Cc: Daeho Jeong, Sunmin Jeong

From: Daeho Jeong <daehojeong@google.com>

Currently, zoned block devices restrict pinned file allocations to
conventional zones at the beginning of the storage (before
first_seq_zone_segno), triggering range GC when conventional space is
exhausted.

To support pinned area boundary configuration on regular block devices
as well, introduce a unified `pinned_area_max_secno` boundary
abstraction in `f2fs_sb_info`:
1. Add `-o pinned_boundary_secno=%u` mount option to allow configuring
   the pinned area upper bound at mount time.
2. In `f2fs_fill_super()`, initialize `sbi->pinned_area_max_secno` as:
   min(MAIN_SECS(sbi), zoned_max_sec, boundary_opt_sec).
3. In `get_new_segment()`, restrict segment allocation for pinned files
   (`pinning == true`) to `0 .. sbi->pinned_area_max_secno - 1`. If no
   free section is available in the pinned area, return -EAGAIN.
4. In `f2fs_allocate_pinning_section()`, unify the range GC trigger to
   run `f2fs_gc_range()` up to `sbi->pinned_area_max_secno` whenever
   `sbi->pinned_area_max_secno < MAIN_SECS(sbi)` and allocation
   returns -EAGAIN.
5. Expose `/sys/fs/f2fs/<dev>/pinned_area_max_secno` as a read-only
   sysfs node.

Signed-off-by: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Sunmin Jeong <s_min.jeong@samsung.com>
---
 Documentation/ABI/testing/sysfs-fs-f2fs |  7 +++++
 Documentation/filesystems/f2fs.rst      |  5 ++++
 fs/f2fs/f2fs.h                          |  2 ++
 fs/f2fs/segment.c                       | 39 ++++++++++++++-----------
 fs/f2fs/segment.h                       |  1 +
 fs/f2fs/super.c                         | 36 +++++++++++++++++++++++
 fs/f2fs/sysfs.c                         |  2 ++
 7 files changed, 75 insertions(+), 17 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
index 39ac8566822a..9e021312d6ae 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -1011,3 +1011,10 @@ Description:	Every time a write operation completes f2fs_write_end_io() is
 		e.g. from inside an interrupt handler. This attribute controls
 		the maximum size of a write bio that is completed in atomic
 		(atc) context.
+
+What:		/sys/fs/f2fs/<disk>/pinned_area_max_secno
+Date:		August 2026
+Contact:	"Daeho Jeong" <daehojeong@google.com>
+Description:	This is a read-only entry to show the upper bound section number
+		for pinned files. Pinned files will only be allocated within
+		sections 0 to pinned_area_max_secno - 1.
diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
index 8c4a14ae444f..f71a23c079be 100644
--- a/Documentation/filesystems/f2fs.rst
+++ b/Documentation/filesystems/f2fs.rst
@@ -418,6 +418,11 @@ lookup_mode=%s		 Control the directory lookup behavior for casefolded
 					        on-disk `SB_ENC_NO_COMPAT_FALLBACK_FL`
 					        flag.
 			     ================== ========================================
+pinned_boundary_secno=%u Control the upper bound section number for pinned files.
+			 Pinned files will only be allocated within sections
+			 0 to pinned_boundary_secno - 1. If set to 0 (default),
+			 there is no boundary restriction unless running on a
+			 zoned block device where conventional zones are used.
 ======================== ============================================================
 
 Debugfs Entries
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index f1774d4e18d2..021407186af8 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -254,6 +254,7 @@ struct f2fs_mount_info {
 	block_t unusable_cap;		/* Amount of space allowed to be
 					 * unusable when disabling checkpoint
 					 */
+	unsigned int pinned_boundary_secno;	/* upper bound section for pinned files */
 
 	/* For compression */
 	unsigned char compress_algorithm;	/* algorithm type */
@@ -1970,6 +1971,7 @@ struct f2fs_sb_info {
 	spinlock_t dev_lock;			/* protect dirty_device */
 	bool aligned_blksize;			/* all devices has the same logical blksize */
 	unsigned int first_seq_zone_segno;	/* first segno in sequential zone */
+	unsigned int pinned_area_max_secno;	/* upper bound section for pinned files */
 	unsigned int bggc_io_aware;		/* For adjust the BG_GC priority when pending IO */
 	unsigned int allocate_section_hint;	/* the boundary position between devices */
 	unsigned int allocate_section_policy;	/* determine the section writing priority */
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index d71ddb3ee918..12a561d8f8c2 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2777,6 +2777,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
 	unsigned int old_zoneno = GET_ZONE_FROM_SEG(sbi, *newseg);
 	unsigned int alloc_policy = sbi->allocate_section_policy;
 	unsigned int alloc_hint = sbi->allocate_section_hint;
+	unsigned int max_secno = MAIN_SECS(sbi);
 	bool init = true;
 	int i;
 	int ret = 0;
@@ -2802,7 +2803,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
 	 */
 	if (f2fs_sb_has_blkzoned(sbi)) {
 		/* Prioritize writing to conventional zones */
-		if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_PRIOR_CONV || pinning)
+		if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_PRIOR_CONV)
 			segno = 0;
 		else
 			segno = max(sbi->first_seq_zone_segno, *newseg);
@@ -2818,18 +2819,22 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
 		alloc_hint > MAIN_SECS(sbi))
 		alloc_hint = MAIN_SECS(sbi);
 
-	if (alloc_policy == ALLOCATE_FORWARD_FROM_HINT &&
-		hint < alloc_hint)
+	if (pinning) {
+		max_secno = sbi->pinned_area_max_secno;
+		hint = 0;
+	} else if (alloc_policy == ALLOCATE_FORWARD_FROM_HINT &&
+		hint < alloc_hint) {
 		hint = alloc_hint;
-	else if (alloc_policy == ALLOCATE_FORWARD_WITHIN_HINT &&
-			hint >= alloc_hint)
+	} else if (alloc_policy == ALLOCATE_FORWARD_WITHIN_HINT &&
+			hint >= alloc_hint) {
 		hint = 0;
+	}
 
 find_other_zone:
-	secno = find_next_zero_bit(free_i->free_secmap, MAIN_SECS(sbi), hint);
+	secno = find_next_zero_bit(free_i->free_secmap, max_secno, hint);
 
 #ifdef CONFIG_BLK_DEV_ZONED
-	if (secno >= MAIN_SECS(sbi) && f2fs_sb_has_blkzoned(sbi)) {
+	if (secno >= max_secno && f2fs_sb_has_blkzoned(sbi) && !pinning) {
 		/* Write only to sequential zones */
 		if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_ONLY_SEQ) {
 			hint = GET_SEC_FROM_SEG(sbi, sbi->first_seq_zone_segno);
@@ -2845,11 +2850,11 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
 	}
 #endif
 
-	if (secno >= MAIN_SECS(sbi)) {
-		secno = find_first_zero_bit(free_i->free_secmap,
-							MAIN_SECS(sbi));
-		if (secno >= MAIN_SECS(sbi)) {
-			ret = -ENOSPC;
+	if (secno >= max_secno) {
+		secno = find_first_zero_bit(free_i->free_secmap, max_secno);
+		if (secno >= max_secno) {
+			ret = (pinning && has_pinned_area(sbi)) ?
+					-EAGAIN : -ENOSPC;
 			f2fs_bug_on(sbi, !pinning);
 			goto out_unlock;
 		}
@@ -2886,9 +2891,8 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
 		goto out_unlock;
 	}
 
-	/* no free section in conventional device or conventional zone */
-	if (new_sec && pinning &&
-		f2fs_is_sequential_zone_area(sbi, START_BLOCK(sbi, segno))) {
+	/* no free section in pinned area */
+	if (new_sec && pinning && secno >= sbi->pinned_area_max_secno) {
 		ret = -EAGAIN;
 		goto out_unlock;
 	}
@@ -3357,9 +3361,10 @@ int f2fs_allocate_pinning_section(struct f2fs_sb_info *sbi)
 	err = f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
 	f2fs_unlock_op(sbi, &lc);
 
-	if (f2fs_sb_has_blkzoned(sbi) && err == -EAGAIN && gc_required) {
+	if (has_pinned_area(sbi) && err == -EAGAIN && gc_required) {
 		f2fs_down_write_trace(&sbi->gc_lock, &lc);
-		err = f2fs_gc_range(sbi, 0, sbi->first_seq_zone_segno - 1,
+		err = f2fs_gc_range(sbi, 0,
+				sbi->pinned_area_max_secno * SEGS_PER_SEC(sbi) - 1,
 				true, ZONED_PIN_SEC_REQUIRED_COUNT);
 		f2fs_up_write_trace(&sbi->gc_lock, &lc);
 
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index b0c06b3580b4..057139107935 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -43,6 +43,7 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
 
 #define MAIN_SEGS(sbi)	(SM_I(sbi)->main_segments)
 #define MAIN_SECS(sbi)	((sbi)->total_sections)
+#define has_pinned_area(sbi)	((sbi)->pinned_area_max_secno < MAIN_SECS(sbi))
 
 #define TOTAL_SEGS(sbi)							\
 	(SM_I(sbi) ? SM_I(sbi)->segment_count : 				\
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index c448d992ff2a..746c003f3aad 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -235,6 +235,7 @@ enum {
 	Opt_jqfmt,
 	Opt_checkpoint,
 	Opt_lookup_mode,
+	Opt_pinned_boundary_secno,
 	Opt_err,
 };
 
@@ -366,6 +367,7 @@ static const struct fs_parameter_spec f2fs_param_specs[] = {
 	fsparam_flag("age_extent_cache", Opt_age_extent_cache),
 	fsparam_enum("errors", Opt_errors, f2fs_param_errors),
 	fsparam_enum("lookup_mode", Opt_lookup_mode, f2fs_param_lookup_mode),
+	fsparam_u32("pinned_boundary_secno", Opt_pinned_boundary_secno),
 	{}
 };
 
@@ -551,6 +553,17 @@ 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).pinned_boundary_secno)
+		sbi->pinned_area_max_secno = min(sbi->pinned_area_max_secno,
+				F2FS_OPTION(sbi).pinned_boundary_secno);
+}
+
 static void init_once(void *foo)
 {
 	struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo;
@@ -1235,6 +1248,9 @@ static int f2fs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 		F2FS_CTX_INFO(ctx).lookup_mode = result.uint_32;
 		ctx->spec_mask |= F2FS_SPEC_lookup_mode;
 		break;
+	case Opt_pinned_boundary_secno:
+		F2FS_CTX_INFO(ctx).pinned_boundary_secno = result.uint_32;
+		break;
 	}
 	return 0;
 }
@@ -1771,6 +1787,12 @@ static void f2fs_apply_options(struct fs_context *fc, struct super_block *sb)
 
 static int f2fs_sanity_check_options(struct f2fs_sb_info *sbi, bool remount)
 {
+	if (remount &&
+	    F2FS_OPTION(sbi).pinned_boundary_secno >= MAIN_SECS(sbi)) {
+		f2fs_err(sbi, "Option pinned_boundary_secno is larger than or equal to total sections (%u >= %u)",
+				F2FS_OPTION(sbi).pinned_boundary_secno, MAIN_SECS(sbi));
+		return -EINVAL;
+	}
 	if (f2fs_sb_has_device_alias(sbi) &&
 	    !test_opt(sbi, READ_EXTENT_CACHE)) {
 		f2fs_err(sbi, "device aliasing requires extent cache");
@@ -2543,6 +2565,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 	else if (F2FS_OPTION(sbi).lookup_mode == LOOKUP_AUTO)
 		seq_show_option(seq, "lookup_mode", "auto");
 
+	if (F2FS_OPTION(sbi).pinned_boundary_secno)
+		seq_printf(seq, ",pinned_boundary_secno=%u",
+				F2FS_OPTION(sbi).pinned_boundary_secno);
+
 	return 0;
 }
 
@@ -2585,6 +2611,7 @@ static void default_options(struct f2fs_sb_info *sbi, bool remount)
 	F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON;
 	F2FS_OPTION(sbi).memory_mode = MEMORY_MODE_NORMAL;
 	F2FS_OPTION(sbi).errors = MOUNT_ERRORS_CONTINUE;
+	F2FS_OPTION(sbi).pinned_boundary_secno = 0;
 
 	set_opt(sbi, INLINE_XATTR);
 	set_opt(sbi, INLINE_DATA);
@@ -3042,6 +3069,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);
 	limit_reserve_root(sbi);
 	fc->sb_flags = (flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME);
 
@@ -5251,6 +5279,14 @@ 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);
 
+	if (F2FS_OPTION(sbi).pinned_boundary_secno >= MAIN_SECS(sbi)) {
+		f2fs_err(sbi, "Option pinned_boundary_secno is larger than or equal to total sections (%u >= %u)",
+				F2FS_OPTION(sbi).pinned_boundary_secno, MAIN_SECS(sbi));
+		err = -EINVAL;
+		goto free_nm;
+	}
+	adjust_pinned_area_boundary(sbi);
+
 	sbi->reserved_pin_section = f2fs_sb_has_blkzoned(sbi) ?
 			ZONED_PIN_SEC_REQUIRED_COUNT :
 			GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi));
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 47b378ccf07a..e0c51f9ec7eb 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -1311,6 +1311,7 @@ F2FS_SBI_GENERAL_RW_ATTR(blkzone_alloc_policy);
 #endif
 F2FS_SBI_GENERAL_RW_ATTR(carve_out);
 F2FS_SBI_GENERAL_RW_ATTR(reserved_pin_section);
+F2FS_SBI_GENERAL_RO_ATTR(pinned_area_max_secno);
 F2FS_SBI_GENERAL_RW_ATTR(bggc_io_aware);
 F2FS_SBI_GENERAL_RW_ATTR(max_lock_elapsed_time);
 F2FS_SBI_GENERAL_RW_ATTR(lock_duration_priority);
@@ -1523,6 +1524,7 @@ static struct attribute *f2fs_attrs[] = {
 	ATTR_LIST(max_read_extent_count),
 	ATTR_LIST(carve_out),
 	ATTR_LIST(reserved_pin_section),
+	ATTR_LIST(pinned_area_max_secno),
 	ATTR_LIST(allocate_section_hint),
 	ATTR_LIST(allocate_section_policy),
 	ATTR_LIST(max_lock_elapsed_time),
-- 
2.55.0.691.gc56d675ccc-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [f2fs-dev] [PATCH] f2fs: support pinned boundary section and unify pinned allocation
@ 2026-08-18 19:51 ` Daeho Jeong
  0 siblings, 0 replies; 4+ messages in thread
From: Daeho Jeong @ 2026-08-18 19:51 UTC (permalink / raw)
  To: linux-kernel, linux-f2fs-devel, kernel-team; +Cc: Daeho Jeong

From: Daeho Jeong <daehojeong@google.com>

Currently, zoned block devices restrict pinned file allocations to
conventional zones at the beginning of the storage (before
first_seq_zone_segno), triggering range GC when conventional space is
exhausted.

To support pinned area boundary configuration on regular block devices
as well, introduce a unified `pinned_area_max_secno` boundary
abstraction in `f2fs_sb_info`:
1. Add `-o pinned_boundary_secno=%u` mount option to allow configuring
   the pinned area upper bound at mount time.
2. In `f2fs_fill_super()`, initialize `sbi->pinned_area_max_secno` as:
   min(MAIN_SECS(sbi), zoned_max_sec, boundary_opt_sec).
3. In `get_new_segment()`, restrict segment allocation for pinned files
   (`pinning == true`) to `0 .. sbi->pinned_area_max_secno - 1`. If no
   free section is available in the pinned area, return -EAGAIN.
4. In `f2fs_allocate_pinning_section()`, unify the range GC trigger to
   run `f2fs_gc_range()` up to `sbi->pinned_area_max_secno` whenever
   `sbi->pinned_area_max_secno < MAIN_SECS(sbi)` and allocation
   returns -EAGAIN.
5. Expose `/sys/fs/f2fs/<dev>/pinned_area_max_secno` as a read-only
   sysfs node.

Signed-off-by: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Sunmin Jeong <s_min.jeong@samsung.com>
---
 Documentation/ABI/testing/sysfs-fs-f2fs |  7 +++++
 Documentation/filesystems/f2fs.rst      |  5 ++++
 fs/f2fs/f2fs.h                          |  2 ++
 fs/f2fs/segment.c                       | 39 ++++++++++++++-----------
 fs/f2fs/segment.h                       |  1 +
 fs/f2fs/super.c                         | 36 +++++++++++++++++++++++
 fs/f2fs/sysfs.c                         |  2 ++
 7 files changed, 75 insertions(+), 17 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
index 39ac8566822a..9e021312d6ae 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -1011,3 +1011,10 @@ Description:	Every time a write operation completes f2fs_write_end_io() is
 		e.g. from inside an interrupt handler. This attribute controls
 		the maximum size of a write bio that is completed in atomic
 		(atc) context.
+
+What:		/sys/fs/f2fs/<disk>/pinned_area_max_secno
+Date:		August 2026
+Contact:	"Daeho Jeong" <daehojeong@google.com>
+Description:	This is a read-only entry to show the upper bound section number
+		for pinned files. Pinned files will only be allocated within
+		sections 0 to pinned_area_max_secno - 1.
diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
index 8c4a14ae444f..f71a23c079be 100644
--- a/Documentation/filesystems/f2fs.rst
+++ b/Documentation/filesystems/f2fs.rst
@@ -418,6 +418,11 @@ lookup_mode=%s		 Control the directory lookup behavior for casefolded
 					        on-disk `SB_ENC_NO_COMPAT_FALLBACK_FL`
 					        flag.
 			     ================== ========================================
+pinned_boundary_secno=%u Control the upper bound section number for pinned files.
+			 Pinned files will only be allocated within sections
+			 0 to pinned_boundary_secno - 1. If set to 0 (default),
+			 there is no boundary restriction unless running on a
+			 zoned block device where conventional zones are used.
 ======================== ============================================================
 
 Debugfs Entries
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index f1774d4e18d2..021407186af8 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -254,6 +254,7 @@ struct f2fs_mount_info {
 	block_t unusable_cap;		/* Amount of space allowed to be
 					 * unusable when disabling checkpoint
 					 */
+	unsigned int pinned_boundary_secno;	/* upper bound section for pinned files */
 
 	/* For compression */
 	unsigned char compress_algorithm;	/* algorithm type */
@@ -1970,6 +1971,7 @@ struct f2fs_sb_info {
 	spinlock_t dev_lock;			/* protect dirty_device */
 	bool aligned_blksize;			/* all devices has the same logical blksize */
 	unsigned int first_seq_zone_segno;	/* first segno in sequential zone */
+	unsigned int pinned_area_max_secno;	/* upper bound section for pinned files */
 	unsigned int bggc_io_aware;		/* For adjust the BG_GC priority when pending IO */
 	unsigned int allocate_section_hint;	/* the boundary position between devices */
 	unsigned int allocate_section_policy;	/* determine the section writing priority */
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index d71ddb3ee918..12a561d8f8c2 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2777,6 +2777,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
 	unsigned int old_zoneno = GET_ZONE_FROM_SEG(sbi, *newseg);
 	unsigned int alloc_policy = sbi->allocate_section_policy;
 	unsigned int alloc_hint = sbi->allocate_section_hint;
+	unsigned int max_secno = MAIN_SECS(sbi);
 	bool init = true;
 	int i;
 	int ret = 0;
@@ -2802,7 +2803,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
 	 */
 	if (f2fs_sb_has_blkzoned(sbi)) {
 		/* Prioritize writing to conventional zones */
-		if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_PRIOR_CONV || pinning)
+		if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_PRIOR_CONV)
 			segno = 0;
 		else
 			segno = max(sbi->first_seq_zone_segno, *newseg);
@@ -2818,18 +2819,22 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
 		alloc_hint > MAIN_SECS(sbi))
 		alloc_hint = MAIN_SECS(sbi);
 
-	if (alloc_policy == ALLOCATE_FORWARD_FROM_HINT &&
-		hint < alloc_hint)
+	if (pinning) {
+		max_secno = sbi->pinned_area_max_secno;
+		hint = 0;
+	} else if (alloc_policy == ALLOCATE_FORWARD_FROM_HINT &&
+		hint < alloc_hint) {
 		hint = alloc_hint;
-	else if (alloc_policy == ALLOCATE_FORWARD_WITHIN_HINT &&
-			hint >= alloc_hint)
+	} else if (alloc_policy == ALLOCATE_FORWARD_WITHIN_HINT &&
+			hint >= alloc_hint) {
 		hint = 0;
+	}
 
 find_other_zone:
-	secno = find_next_zero_bit(free_i->free_secmap, MAIN_SECS(sbi), hint);
+	secno = find_next_zero_bit(free_i->free_secmap, max_secno, hint);
 
 #ifdef CONFIG_BLK_DEV_ZONED
-	if (secno >= MAIN_SECS(sbi) && f2fs_sb_has_blkzoned(sbi)) {
+	if (secno >= max_secno && f2fs_sb_has_blkzoned(sbi) && !pinning) {
 		/* Write only to sequential zones */
 		if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_ONLY_SEQ) {
 			hint = GET_SEC_FROM_SEG(sbi, sbi->first_seq_zone_segno);
@@ -2845,11 +2850,11 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
 	}
 #endif
 
-	if (secno >= MAIN_SECS(sbi)) {
-		secno = find_first_zero_bit(free_i->free_secmap,
-							MAIN_SECS(sbi));
-		if (secno >= MAIN_SECS(sbi)) {
-			ret = -ENOSPC;
+	if (secno >= max_secno) {
+		secno = find_first_zero_bit(free_i->free_secmap, max_secno);
+		if (secno >= max_secno) {
+			ret = (pinning && has_pinned_area(sbi)) ?
+					-EAGAIN : -ENOSPC;
 			f2fs_bug_on(sbi, !pinning);
 			goto out_unlock;
 		}
@@ -2886,9 +2891,8 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
 		goto out_unlock;
 	}
 
-	/* no free section in conventional device or conventional zone */
-	if (new_sec && pinning &&
-		f2fs_is_sequential_zone_area(sbi, START_BLOCK(sbi, segno))) {
+	/* no free section in pinned area */
+	if (new_sec && pinning && secno >= sbi->pinned_area_max_secno) {
 		ret = -EAGAIN;
 		goto out_unlock;
 	}
@@ -3357,9 +3361,10 @@ int f2fs_allocate_pinning_section(struct f2fs_sb_info *sbi)
 	err = f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
 	f2fs_unlock_op(sbi, &lc);
 
-	if (f2fs_sb_has_blkzoned(sbi) && err == -EAGAIN && gc_required) {
+	if (has_pinned_area(sbi) && err == -EAGAIN && gc_required) {
 		f2fs_down_write_trace(&sbi->gc_lock, &lc);
-		err = f2fs_gc_range(sbi, 0, sbi->first_seq_zone_segno - 1,
+		err = f2fs_gc_range(sbi, 0,
+				sbi->pinned_area_max_secno * SEGS_PER_SEC(sbi) - 1,
 				true, ZONED_PIN_SEC_REQUIRED_COUNT);
 		f2fs_up_write_trace(&sbi->gc_lock, &lc);
 
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index b0c06b3580b4..057139107935 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -43,6 +43,7 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
 
 #define MAIN_SEGS(sbi)	(SM_I(sbi)->main_segments)
 #define MAIN_SECS(sbi)	((sbi)->total_sections)
+#define has_pinned_area(sbi)	((sbi)->pinned_area_max_secno < MAIN_SECS(sbi))
 
 #define TOTAL_SEGS(sbi)							\
 	(SM_I(sbi) ? SM_I(sbi)->segment_count : 				\
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index c448d992ff2a..746c003f3aad 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -235,6 +235,7 @@ enum {
 	Opt_jqfmt,
 	Opt_checkpoint,
 	Opt_lookup_mode,
+	Opt_pinned_boundary_secno,
 	Opt_err,
 };
 
@@ -366,6 +367,7 @@ static const struct fs_parameter_spec f2fs_param_specs[] = {
 	fsparam_flag("age_extent_cache", Opt_age_extent_cache),
 	fsparam_enum("errors", Opt_errors, f2fs_param_errors),
 	fsparam_enum("lookup_mode", Opt_lookup_mode, f2fs_param_lookup_mode),
+	fsparam_u32("pinned_boundary_secno", Opt_pinned_boundary_secno),
 	{}
 };
 
@@ -551,6 +553,17 @@ 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).pinned_boundary_secno)
+		sbi->pinned_area_max_secno = min(sbi->pinned_area_max_secno,
+				F2FS_OPTION(sbi).pinned_boundary_secno);
+}
+
 static void init_once(void *foo)
 {
 	struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo;
@@ -1235,6 +1248,9 @@ static int f2fs_parse_param(struct fs_context *fc, struct fs_parameter *param)
 		F2FS_CTX_INFO(ctx).lookup_mode = result.uint_32;
 		ctx->spec_mask |= F2FS_SPEC_lookup_mode;
 		break;
+	case Opt_pinned_boundary_secno:
+		F2FS_CTX_INFO(ctx).pinned_boundary_secno = result.uint_32;
+		break;
 	}
 	return 0;
 }
@@ -1771,6 +1787,12 @@ static void f2fs_apply_options(struct fs_context *fc, struct super_block *sb)
 
 static int f2fs_sanity_check_options(struct f2fs_sb_info *sbi, bool remount)
 {
+	if (remount &&
+	    F2FS_OPTION(sbi).pinned_boundary_secno >= MAIN_SECS(sbi)) {
+		f2fs_err(sbi, "Option pinned_boundary_secno is larger than or equal to total sections (%u >= %u)",
+				F2FS_OPTION(sbi).pinned_boundary_secno, MAIN_SECS(sbi));
+		return -EINVAL;
+	}
 	if (f2fs_sb_has_device_alias(sbi) &&
 	    !test_opt(sbi, READ_EXTENT_CACHE)) {
 		f2fs_err(sbi, "device aliasing requires extent cache");
@@ -2543,6 +2565,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 	else if (F2FS_OPTION(sbi).lookup_mode == LOOKUP_AUTO)
 		seq_show_option(seq, "lookup_mode", "auto");
 
+	if (F2FS_OPTION(sbi).pinned_boundary_secno)
+		seq_printf(seq, ",pinned_boundary_secno=%u",
+				F2FS_OPTION(sbi).pinned_boundary_secno);
+
 	return 0;
 }
 
@@ -2585,6 +2611,7 @@ static void default_options(struct f2fs_sb_info *sbi, bool remount)
 	F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON;
 	F2FS_OPTION(sbi).memory_mode = MEMORY_MODE_NORMAL;
 	F2FS_OPTION(sbi).errors = MOUNT_ERRORS_CONTINUE;
+	F2FS_OPTION(sbi).pinned_boundary_secno = 0;
 
 	set_opt(sbi, INLINE_XATTR);
 	set_opt(sbi, INLINE_DATA);
@@ -3042,6 +3069,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);
 	limit_reserve_root(sbi);
 	fc->sb_flags = (flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME);
 
@@ -5251,6 +5279,14 @@ 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);
 
+	if (F2FS_OPTION(sbi).pinned_boundary_secno >= MAIN_SECS(sbi)) {
+		f2fs_err(sbi, "Option pinned_boundary_secno is larger than or equal to total sections (%u >= %u)",
+				F2FS_OPTION(sbi).pinned_boundary_secno, MAIN_SECS(sbi));
+		err = -EINVAL;
+		goto free_nm;
+	}
+	adjust_pinned_area_boundary(sbi);
+
 	sbi->reserved_pin_section = f2fs_sb_has_blkzoned(sbi) ?
 			ZONED_PIN_SEC_REQUIRED_COUNT :
 			GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi));
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 47b378ccf07a..e0c51f9ec7eb 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -1311,6 +1311,7 @@ F2FS_SBI_GENERAL_RW_ATTR(blkzone_alloc_policy);
 #endif
 F2FS_SBI_GENERAL_RW_ATTR(carve_out);
 F2FS_SBI_GENERAL_RW_ATTR(reserved_pin_section);
+F2FS_SBI_GENERAL_RO_ATTR(pinned_area_max_secno);
 F2FS_SBI_GENERAL_RW_ATTR(bggc_io_aware);
 F2FS_SBI_GENERAL_RW_ATTR(max_lock_elapsed_time);
 F2FS_SBI_GENERAL_RW_ATTR(lock_duration_priority);
@@ -1523,6 +1524,7 @@ static struct attribute *f2fs_attrs[] = {
 	ATTR_LIST(max_read_extent_count),
 	ATTR_LIST(carve_out),
 	ATTR_LIST(reserved_pin_section),
+	ATTR_LIST(pinned_area_max_secno),
 	ATTR_LIST(allocate_section_hint),
 	ATTR_LIST(allocate_section_policy),
 	ATTR_LIST(max_lock_elapsed_time),
-- 
2.55.0.691.gc56d675ccc-goog



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [f2fs-dev] [PATCH] f2fs: support pinned boundary section and unify pinned allocation
  2026-08-18 19:51 ` [f2fs-dev] " Daeho Jeong
@ 2026-08-24 15:31   ` Jaegeuk Kim
  -1 siblings, 0 replies; 4+ messages in thread
From: Jaegeuk Kim via Linux-f2fs-devel @ 2026-08-24 15:31 UTC (permalink / raw)
  To: Daeho Jeong; +Cc: Daeho Jeong, kernel-team, linux-kernel, linux-f2fs-devel

Hi Daeho,

Could you please rebase on top of dev-test?

Thanks,

On 08/18, Daeho Jeong wrote:
> From: Daeho Jeong <daehojeong@google.com>
> 
> Currently, zoned block devices restrict pinned file allocations to
> conventional zones at the beginning of the storage (before
> first_seq_zone_segno), triggering range GC when conventional space is
> exhausted.
> 
> To support pinned area boundary configuration on regular block devices
> as well, introduce a unified `pinned_area_max_secno` boundary
> abstraction in `f2fs_sb_info`:
> 1. Add `-o pinned_boundary_secno=%u` mount option to allow configuring
>    the pinned area upper bound at mount time.
> 2. In `f2fs_fill_super()`, initialize `sbi->pinned_area_max_secno` as:
>    min(MAIN_SECS(sbi), zoned_max_sec, boundary_opt_sec).
> 3. In `get_new_segment()`, restrict segment allocation for pinned files
>    (`pinning == true`) to `0 .. sbi->pinned_area_max_secno - 1`. If no
>    free section is available in the pinned area, return -EAGAIN.
> 4. In `f2fs_allocate_pinning_section()`, unify the range GC trigger to
>    run `f2fs_gc_range()` up to `sbi->pinned_area_max_secno` whenever
>    `sbi->pinned_area_max_secno < MAIN_SECS(sbi)` and allocation
>    returns -EAGAIN.
> 5. Expose `/sys/fs/f2fs/<dev>/pinned_area_max_secno` as a read-only
>    sysfs node.
> 
> Signed-off-by: Daeho Jeong <daehojeong@google.com>
> Signed-off-by: Sunmin Jeong <s_min.jeong@samsung.com>
> ---
>  Documentation/ABI/testing/sysfs-fs-f2fs |  7 +++++
>  Documentation/filesystems/f2fs.rst      |  5 ++++
>  fs/f2fs/f2fs.h                          |  2 ++
>  fs/f2fs/segment.c                       | 39 ++++++++++++++-----------
>  fs/f2fs/segment.h                       |  1 +
>  fs/f2fs/super.c                         | 36 +++++++++++++++++++++++
>  fs/f2fs/sysfs.c                         |  2 ++
>  7 files changed, 75 insertions(+), 17 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
> index 39ac8566822a..9e021312d6ae 100644
> --- a/Documentation/ABI/testing/sysfs-fs-f2fs
> +++ b/Documentation/ABI/testing/sysfs-fs-f2fs
> @@ -1011,3 +1011,10 @@ Description:	Every time a write operation completes f2fs_write_end_io() is
>  		e.g. from inside an interrupt handler. This attribute controls
>  		the maximum size of a write bio that is completed in atomic
>  		(atc) context.
> +
> +What:		/sys/fs/f2fs/<disk>/pinned_area_max_secno
> +Date:		August 2026
> +Contact:	"Daeho Jeong" <daehojeong@google.com>
> +Description:	This is a read-only entry to show the upper bound section number
> +		for pinned files. Pinned files will only be allocated within
> +		sections 0 to pinned_area_max_secno - 1.
> diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
> index 8c4a14ae444f..f71a23c079be 100644
> --- a/Documentation/filesystems/f2fs.rst
> +++ b/Documentation/filesystems/f2fs.rst
> @@ -418,6 +418,11 @@ lookup_mode=%s		 Control the directory lookup behavior for casefolded
>  					        on-disk `SB_ENC_NO_COMPAT_FALLBACK_FL`
>  					        flag.
>  			     ================== ========================================
> +pinned_boundary_secno=%u Control the upper bound section number for pinned files.
> +			 Pinned files will only be allocated within sections
> +			 0 to pinned_boundary_secno - 1. If set to 0 (default),
> +			 there is no boundary restriction unless running on a
> +			 zoned block device where conventional zones are used.
>  ======================== ============================================================
>  
>  Debugfs Entries
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index f1774d4e18d2..021407186af8 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -254,6 +254,7 @@ struct f2fs_mount_info {
>  	block_t unusable_cap;		/* Amount of space allowed to be
>  					 * unusable when disabling checkpoint
>  					 */
> +	unsigned int pinned_boundary_secno;	/* upper bound section for pinned files */
>  
>  	/* For compression */
>  	unsigned char compress_algorithm;	/* algorithm type */
> @@ -1970,6 +1971,7 @@ struct f2fs_sb_info {
>  	spinlock_t dev_lock;			/* protect dirty_device */
>  	bool aligned_blksize;			/* all devices has the same logical blksize */
>  	unsigned int first_seq_zone_segno;	/* first segno in sequential zone */
> +	unsigned int pinned_area_max_secno;	/* upper bound section for pinned files */
>  	unsigned int bggc_io_aware;		/* For adjust the BG_GC priority when pending IO */
>  	unsigned int allocate_section_hint;	/* the boundary position between devices */
>  	unsigned int allocate_section_policy;	/* determine the section writing priority */
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index d71ddb3ee918..12a561d8f8c2 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2777,6 +2777,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
>  	unsigned int old_zoneno = GET_ZONE_FROM_SEG(sbi, *newseg);
>  	unsigned int alloc_policy = sbi->allocate_section_policy;
>  	unsigned int alloc_hint = sbi->allocate_section_hint;
> +	unsigned int max_secno = MAIN_SECS(sbi);
>  	bool init = true;
>  	int i;
>  	int ret = 0;
> @@ -2802,7 +2803,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
>  	 */
>  	if (f2fs_sb_has_blkzoned(sbi)) {
>  		/* Prioritize writing to conventional zones */
> -		if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_PRIOR_CONV || pinning)
> +		if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_PRIOR_CONV)
>  			segno = 0;
>  		else
>  			segno = max(sbi->first_seq_zone_segno, *newseg);
> @@ -2818,18 +2819,22 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
>  		alloc_hint > MAIN_SECS(sbi))
>  		alloc_hint = MAIN_SECS(sbi);
>  
> -	if (alloc_policy == ALLOCATE_FORWARD_FROM_HINT &&
> -		hint < alloc_hint)
> +	if (pinning) {
> +		max_secno = sbi->pinned_area_max_secno;
> +		hint = 0;
> +	} else if (alloc_policy == ALLOCATE_FORWARD_FROM_HINT &&
> +		hint < alloc_hint) {
>  		hint = alloc_hint;
> -	else if (alloc_policy == ALLOCATE_FORWARD_WITHIN_HINT &&
> -			hint >= alloc_hint)
> +	} else if (alloc_policy == ALLOCATE_FORWARD_WITHIN_HINT &&
> +			hint >= alloc_hint) {
>  		hint = 0;
> +	}
>  
>  find_other_zone:
> -	secno = find_next_zero_bit(free_i->free_secmap, MAIN_SECS(sbi), hint);
> +	secno = find_next_zero_bit(free_i->free_secmap, max_secno, hint);
>  
>  #ifdef CONFIG_BLK_DEV_ZONED
> -	if (secno >= MAIN_SECS(sbi) && f2fs_sb_has_blkzoned(sbi)) {
> +	if (secno >= max_secno && f2fs_sb_has_blkzoned(sbi) && !pinning) {
>  		/* Write only to sequential zones */
>  		if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_ONLY_SEQ) {
>  			hint = GET_SEC_FROM_SEG(sbi, sbi->first_seq_zone_segno);
> @@ -2845,11 +2850,11 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
>  	}
>  #endif
>  
> -	if (secno >= MAIN_SECS(sbi)) {
> -		secno = find_first_zero_bit(free_i->free_secmap,
> -							MAIN_SECS(sbi));
> -		if (secno >= MAIN_SECS(sbi)) {
> -			ret = -ENOSPC;
> +	if (secno >= max_secno) {
> +		secno = find_first_zero_bit(free_i->free_secmap, max_secno);
> +		if (secno >= max_secno) {
> +			ret = (pinning && has_pinned_area(sbi)) ?
> +					-EAGAIN : -ENOSPC;
>  			f2fs_bug_on(sbi, !pinning);
>  			goto out_unlock;
>  		}
> @@ -2886,9 +2891,8 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
>  		goto out_unlock;
>  	}
>  
> -	/* no free section in conventional device or conventional zone */
> -	if (new_sec && pinning &&
> -		f2fs_is_sequential_zone_area(sbi, START_BLOCK(sbi, segno))) {
> +	/* no free section in pinned area */
> +	if (new_sec && pinning && secno >= sbi->pinned_area_max_secno) {
>  		ret = -EAGAIN;
>  		goto out_unlock;
>  	}
> @@ -3357,9 +3361,10 @@ int f2fs_allocate_pinning_section(struct f2fs_sb_info *sbi)
>  	err = f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
>  	f2fs_unlock_op(sbi, &lc);
>  
> -	if (f2fs_sb_has_blkzoned(sbi) && err == -EAGAIN && gc_required) {
> +	if (has_pinned_area(sbi) && err == -EAGAIN && gc_required) {
>  		f2fs_down_write_trace(&sbi->gc_lock, &lc);
> -		err = f2fs_gc_range(sbi, 0, sbi->first_seq_zone_segno - 1,
> +		err = f2fs_gc_range(sbi, 0,
> +				sbi->pinned_area_max_secno * SEGS_PER_SEC(sbi) - 1,
>  				true, ZONED_PIN_SEC_REQUIRED_COUNT);
>  		f2fs_up_write_trace(&sbi->gc_lock, &lc);
>  
> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> index b0c06b3580b4..057139107935 100644
> --- a/fs/f2fs/segment.h
> +++ b/fs/f2fs/segment.h
> @@ -43,6 +43,7 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
>  
>  #define MAIN_SEGS(sbi)	(SM_I(sbi)->main_segments)
>  #define MAIN_SECS(sbi)	((sbi)->total_sections)
> +#define has_pinned_area(sbi)	((sbi)->pinned_area_max_secno < MAIN_SECS(sbi))
>  
>  #define TOTAL_SEGS(sbi)							\
>  	(SM_I(sbi) ? SM_I(sbi)->segment_count : 				\
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index c448d992ff2a..746c003f3aad 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -235,6 +235,7 @@ enum {
>  	Opt_jqfmt,
>  	Opt_checkpoint,
>  	Opt_lookup_mode,
> +	Opt_pinned_boundary_secno,
>  	Opt_err,
>  };
>  
> @@ -366,6 +367,7 @@ static const struct fs_parameter_spec f2fs_param_specs[] = {
>  	fsparam_flag("age_extent_cache", Opt_age_extent_cache),
>  	fsparam_enum("errors", Opt_errors, f2fs_param_errors),
>  	fsparam_enum("lookup_mode", Opt_lookup_mode, f2fs_param_lookup_mode),
> +	fsparam_u32("pinned_boundary_secno", Opt_pinned_boundary_secno),
>  	{}
>  };
>  
> @@ -551,6 +553,17 @@ 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).pinned_boundary_secno)
> +		sbi->pinned_area_max_secno = min(sbi->pinned_area_max_secno,
> +				F2FS_OPTION(sbi).pinned_boundary_secno);
> +}
> +
>  static void init_once(void *foo)
>  {
>  	struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo;
> @@ -1235,6 +1248,9 @@ static int f2fs_parse_param(struct fs_context *fc, struct fs_parameter *param)
>  		F2FS_CTX_INFO(ctx).lookup_mode = result.uint_32;
>  		ctx->spec_mask |= F2FS_SPEC_lookup_mode;
>  		break;
> +	case Opt_pinned_boundary_secno:
> +		F2FS_CTX_INFO(ctx).pinned_boundary_secno = result.uint_32;
> +		break;
>  	}
>  	return 0;
>  }
> @@ -1771,6 +1787,12 @@ static void f2fs_apply_options(struct fs_context *fc, struct super_block *sb)
>  
>  static int f2fs_sanity_check_options(struct f2fs_sb_info *sbi, bool remount)
>  {
> +	if (remount &&
> +	    F2FS_OPTION(sbi).pinned_boundary_secno >= MAIN_SECS(sbi)) {
> +		f2fs_err(sbi, "Option pinned_boundary_secno is larger than or equal to total sections (%u >= %u)",
> +				F2FS_OPTION(sbi).pinned_boundary_secno, MAIN_SECS(sbi));
> +		return -EINVAL;
> +	}
>  	if (f2fs_sb_has_device_alias(sbi) &&
>  	    !test_opt(sbi, READ_EXTENT_CACHE)) {
>  		f2fs_err(sbi, "device aliasing requires extent cache");
> @@ -2543,6 +2565,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
>  	else if (F2FS_OPTION(sbi).lookup_mode == LOOKUP_AUTO)
>  		seq_show_option(seq, "lookup_mode", "auto");
>  
> +	if (F2FS_OPTION(sbi).pinned_boundary_secno)
> +		seq_printf(seq, ",pinned_boundary_secno=%u",
> +				F2FS_OPTION(sbi).pinned_boundary_secno);
> +
>  	return 0;
>  }
>  
> @@ -2585,6 +2611,7 @@ static void default_options(struct f2fs_sb_info *sbi, bool remount)
>  	F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON;
>  	F2FS_OPTION(sbi).memory_mode = MEMORY_MODE_NORMAL;
>  	F2FS_OPTION(sbi).errors = MOUNT_ERRORS_CONTINUE;
> +	F2FS_OPTION(sbi).pinned_boundary_secno = 0;
>  
>  	set_opt(sbi, INLINE_XATTR);
>  	set_opt(sbi, INLINE_DATA);
> @@ -3042,6 +3069,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);
>  	limit_reserve_root(sbi);
>  	fc->sb_flags = (flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME);
>  
> @@ -5251,6 +5279,14 @@ 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);
>  
> +	if (F2FS_OPTION(sbi).pinned_boundary_secno >= MAIN_SECS(sbi)) {
> +		f2fs_err(sbi, "Option pinned_boundary_secno is larger than or equal to total sections (%u >= %u)",
> +				F2FS_OPTION(sbi).pinned_boundary_secno, MAIN_SECS(sbi));
> +		err = -EINVAL;
> +		goto free_nm;
> +	}
> +	adjust_pinned_area_boundary(sbi);
> +
>  	sbi->reserved_pin_section = f2fs_sb_has_blkzoned(sbi) ?
>  			ZONED_PIN_SEC_REQUIRED_COUNT :
>  			GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi));
> diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
> index 47b378ccf07a..e0c51f9ec7eb 100644
> --- a/fs/f2fs/sysfs.c
> +++ b/fs/f2fs/sysfs.c
> @@ -1311,6 +1311,7 @@ F2FS_SBI_GENERAL_RW_ATTR(blkzone_alloc_policy);
>  #endif
>  F2FS_SBI_GENERAL_RW_ATTR(carve_out);
>  F2FS_SBI_GENERAL_RW_ATTR(reserved_pin_section);
> +F2FS_SBI_GENERAL_RO_ATTR(pinned_area_max_secno);
>  F2FS_SBI_GENERAL_RW_ATTR(bggc_io_aware);
>  F2FS_SBI_GENERAL_RW_ATTR(max_lock_elapsed_time);
>  F2FS_SBI_GENERAL_RW_ATTR(lock_duration_priority);
> @@ -1523,6 +1524,7 @@ static struct attribute *f2fs_attrs[] = {
>  	ATTR_LIST(max_read_extent_count),
>  	ATTR_LIST(carve_out),
>  	ATTR_LIST(reserved_pin_section),
> +	ATTR_LIST(pinned_area_max_secno),
>  	ATTR_LIST(allocate_section_hint),
>  	ATTR_LIST(allocate_section_policy),
>  	ATTR_LIST(max_lock_elapsed_time),
> -- 
> 2.55.0.691.gc56d675ccc-goog
> 


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] f2fs: support pinned boundary section and unify pinned allocation
@ 2026-08-24 15:31   ` Jaegeuk Kim
  0 siblings, 0 replies; 4+ messages in thread
From: Jaegeuk Kim @ 2026-08-24 15:31 UTC (permalink / raw)
  To: Daeho Jeong
  Cc: linux-kernel, linux-f2fs-devel, kernel-team, Daeho Jeong,
	Sunmin Jeong

Hi Daeho,

Could you please rebase on top of dev-test?

Thanks,

On 08/18, Daeho Jeong wrote:
> From: Daeho Jeong <daehojeong@google.com>
> 
> Currently, zoned block devices restrict pinned file allocations to
> conventional zones at the beginning of the storage (before
> first_seq_zone_segno), triggering range GC when conventional space is
> exhausted.
> 
> To support pinned area boundary configuration on regular block devices
> as well, introduce a unified `pinned_area_max_secno` boundary
> abstraction in `f2fs_sb_info`:
> 1. Add `-o pinned_boundary_secno=%u` mount option to allow configuring
>    the pinned area upper bound at mount time.
> 2. In `f2fs_fill_super()`, initialize `sbi->pinned_area_max_secno` as:
>    min(MAIN_SECS(sbi), zoned_max_sec, boundary_opt_sec).
> 3. In `get_new_segment()`, restrict segment allocation for pinned files
>    (`pinning == true`) to `0 .. sbi->pinned_area_max_secno - 1`. If no
>    free section is available in the pinned area, return -EAGAIN.
> 4. In `f2fs_allocate_pinning_section()`, unify the range GC trigger to
>    run `f2fs_gc_range()` up to `sbi->pinned_area_max_secno` whenever
>    `sbi->pinned_area_max_secno < MAIN_SECS(sbi)` and allocation
>    returns -EAGAIN.
> 5. Expose `/sys/fs/f2fs/<dev>/pinned_area_max_secno` as a read-only
>    sysfs node.
> 
> Signed-off-by: Daeho Jeong <daehojeong@google.com>
> Signed-off-by: Sunmin Jeong <s_min.jeong@samsung.com>
> ---
>  Documentation/ABI/testing/sysfs-fs-f2fs |  7 +++++
>  Documentation/filesystems/f2fs.rst      |  5 ++++
>  fs/f2fs/f2fs.h                          |  2 ++
>  fs/f2fs/segment.c                       | 39 ++++++++++++++-----------
>  fs/f2fs/segment.h                       |  1 +
>  fs/f2fs/super.c                         | 36 +++++++++++++++++++++++
>  fs/f2fs/sysfs.c                         |  2 ++
>  7 files changed, 75 insertions(+), 17 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
> index 39ac8566822a..9e021312d6ae 100644
> --- a/Documentation/ABI/testing/sysfs-fs-f2fs
> +++ b/Documentation/ABI/testing/sysfs-fs-f2fs
> @@ -1011,3 +1011,10 @@ Description:	Every time a write operation completes f2fs_write_end_io() is
>  		e.g. from inside an interrupt handler. This attribute controls
>  		the maximum size of a write bio that is completed in atomic
>  		(atc) context.
> +
> +What:		/sys/fs/f2fs/<disk>/pinned_area_max_secno
> +Date:		August 2026
> +Contact:	"Daeho Jeong" <daehojeong@google.com>
> +Description:	This is a read-only entry to show the upper bound section number
> +		for pinned files. Pinned files will only be allocated within
> +		sections 0 to pinned_area_max_secno - 1.
> diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
> index 8c4a14ae444f..f71a23c079be 100644
> --- a/Documentation/filesystems/f2fs.rst
> +++ b/Documentation/filesystems/f2fs.rst
> @@ -418,6 +418,11 @@ lookup_mode=%s		 Control the directory lookup behavior for casefolded
>  					        on-disk `SB_ENC_NO_COMPAT_FALLBACK_FL`
>  					        flag.
>  			     ================== ========================================
> +pinned_boundary_secno=%u Control the upper bound section number for pinned files.
> +			 Pinned files will only be allocated within sections
> +			 0 to pinned_boundary_secno - 1. If set to 0 (default),
> +			 there is no boundary restriction unless running on a
> +			 zoned block device where conventional zones are used.
>  ======================== ============================================================
>  
>  Debugfs Entries
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index f1774d4e18d2..021407186af8 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -254,6 +254,7 @@ struct f2fs_mount_info {
>  	block_t unusable_cap;		/* Amount of space allowed to be
>  					 * unusable when disabling checkpoint
>  					 */
> +	unsigned int pinned_boundary_secno;	/* upper bound section for pinned files */
>  
>  	/* For compression */
>  	unsigned char compress_algorithm;	/* algorithm type */
> @@ -1970,6 +1971,7 @@ struct f2fs_sb_info {
>  	spinlock_t dev_lock;			/* protect dirty_device */
>  	bool aligned_blksize;			/* all devices has the same logical blksize */
>  	unsigned int first_seq_zone_segno;	/* first segno in sequential zone */
> +	unsigned int pinned_area_max_secno;	/* upper bound section for pinned files */
>  	unsigned int bggc_io_aware;		/* For adjust the BG_GC priority when pending IO */
>  	unsigned int allocate_section_hint;	/* the boundary position between devices */
>  	unsigned int allocate_section_policy;	/* determine the section writing priority */
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index d71ddb3ee918..12a561d8f8c2 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2777,6 +2777,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
>  	unsigned int old_zoneno = GET_ZONE_FROM_SEG(sbi, *newseg);
>  	unsigned int alloc_policy = sbi->allocate_section_policy;
>  	unsigned int alloc_hint = sbi->allocate_section_hint;
> +	unsigned int max_secno = MAIN_SECS(sbi);
>  	bool init = true;
>  	int i;
>  	int ret = 0;
> @@ -2802,7 +2803,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
>  	 */
>  	if (f2fs_sb_has_blkzoned(sbi)) {
>  		/* Prioritize writing to conventional zones */
> -		if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_PRIOR_CONV || pinning)
> +		if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_PRIOR_CONV)
>  			segno = 0;
>  		else
>  			segno = max(sbi->first_seq_zone_segno, *newseg);
> @@ -2818,18 +2819,22 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
>  		alloc_hint > MAIN_SECS(sbi))
>  		alloc_hint = MAIN_SECS(sbi);
>  
> -	if (alloc_policy == ALLOCATE_FORWARD_FROM_HINT &&
> -		hint < alloc_hint)
> +	if (pinning) {
> +		max_secno = sbi->pinned_area_max_secno;
> +		hint = 0;
> +	} else if (alloc_policy == ALLOCATE_FORWARD_FROM_HINT &&
> +		hint < alloc_hint) {
>  		hint = alloc_hint;
> -	else if (alloc_policy == ALLOCATE_FORWARD_WITHIN_HINT &&
> -			hint >= alloc_hint)
> +	} else if (alloc_policy == ALLOCATE_FORWARD_WITHIN_HINT &&
> +			hint >= alloc_hint) {
>  		hint = 0;
> +	}
>  
>  find_other_zone:
> -	secno = find_next_zero_bit(free_i->free_secmap, MAIN_SECS(sbi), hint);
> +	secno = find_next_zero_bit(free_i->free_secmap, max_secno, hint);
>  
>  #ifdef CONFIG_BLK_DEV_ZONED
> -	if (secno >= MAIN_SECS(sbi) && f2fs_sb_has_blkzoned(sbi)) {
> +	if (secno >= max_secno && f2fs_sb_has_blkzoned(sbi) && !pinning) {
>  		/* Write only to sequential zones */
>  		if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_ONLY_SEQ) {
>  			hint = GET_SEC_FROM_SEG(sbi, sbi->first_seq_zone_segno);
> @@ -2845,11 +2850,11 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
>  	}
>  #endif
>  
> -	if (secno >= MAIN_SECS(sbi)) {
> -		secno = find_first_zero_bit(free_i->free_secmap,
> -							MAIN_SECS(sbi));
> -		if (secno >= MAIN_SECS(sbi)) {
> -			ret = -ENOSPC;
> +	if (secno >= max_secno) {
> +		secno = find_first_zero_bit(free_i->free_secmap, max_secno);
> +		if (secno >= max_secno) {
> +			ret = (pinning && has_pinned_area(sbi)) ?
> +					-EAGAIN : -ENOSPC;
>  			f2fs_bug_on(sbi, !pinning);
>  			goto out_unlock;
>  		}
> @@ -2886,9 +2891,8 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
>  		goto out_unlock;
>  	}
>  
> -	/* no free section in conventional device or conventional zone */
> -	if (new_sec && pinning &&
> -		f2fs_is_sequential_zone_area(sbi, START_BLOCK(sbi, segno))) {
> +	/* no free section in pinned area */
> +	if (new_sec && pinning && secno >= sbi->pinned_area_max_secno) {
>  		ret = -EAGAIN;
>  		goto out_unlock;
>  	}
> @@ -3357,9 +3361,10 @@ int f2fs_allocate_pinning_section(struct f2fs_sb_info *sbi)
>  	err = f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
>  	f2fs_unlock_op(sbi, &lc);
>  
> -	if (f2fs_sb_has_blkzoned(sbi) && err == -EAGAIN && gc_required) {
> +	if (has_pinned_area(sbi) && err == -EAGAIN && gc_required) {
>  		f2fs_down_write_trace(&sbi->gc_lock, &lc);
> -		err = f2fs_gc_range(sbi, 0, sbi->first_seq_zone_segno - 1,
> +		err = f2fs_gc_range(sbi, 0,
> +				sbi->pinned_area_max_secno * SEGS_PER_SEC(sbi) - 1,
>  				true, ZONED_PIN_SEC_REQUIRED_COUNT);
>  		f2fs_up_write_trace(&sbi->gc_lock, &lc);
>  
> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> index b0c06b3580b4..057139107935 100644
> --- a/fs/f2fs/segment.h
> +++ b/fs/f2fs/segment.h
> @@ -43,6 +43,7 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
>  
>  #define MAIN_SEGS(sbi)	(SM_I(sbi)->main_segments)
>  #define MAIN_SECS(sbi)	((sbi)->total_sections)
> +#define has_pinned_area(sbi)	((sbi)->pinned_area_max_secno < MAIN_SECS(sbi))
>  
>  #define TOTAL_SEGS(sbi)							\
>  	(SM_I(sbi) ? SM_I(sbi)->segment_count : 				\
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index c448d992ff2a..746c003f3aad 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -235,6 +235,7 @@ enum {
>  	Opt_jqfmt,
>  	Opt_checkpoint,
>  	Opt_lookup_mode,
> +	Opt_pinned_boundary_secno,
>  	Opt_err,
>  };
>  
> @@ -366,6 +367,7 @@ static const struct fs_parameter_spec f2fs_param_specs[] = {
>  	fsparam_flag("age_extent_cache", Opt_age_extent_cache),
>  	fsparam_enum("errors", Opt_errors, f2fs_param_errors),
>  	fsparam_enum("lookup_mode", Opt_lookup_mode, f2fs_param_lookup_mode),
> +	fsparam_u32("pinned_boundary_secno", Opt_pinned_boundary_secno),
>  	{}
>  };
>  
> @@ -551,6 +553,17 @@ 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).pinned_boundary_secno)
> +		sbi->pinned_area_max_secno = min(sbi->pinned_area_max_secno,
> +				F2FS_OPTION(sbi).pinned_boundary_secno);
> +}
> +
>  static void init_once(void *foo)
>  {
>  	struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo;
> @@ -1235,6 +1248,9 @@ static int f2fs_parse_param(struct fs_context *fc, struct fs_parameter *param)
>  		F2FS_CTX_INFO(ctx).lookup_mode = result.uint_32;
>  		ctx->spec_mask |= F2FS_SPEC_lookup_mode;
>  		break;
> +	case Opt_pinned_boundary_secno:
> +		F2FS_CTX_INFO(ctx).pinned_boundary_secno = result.uint_32;
> +		break;
>  	}
>  	return 0;
>  }
> @@ -1771,6 +1787,12 @@ static void f2fs_apply_options(struct fs_context *fc, struct super_block *sb)
>  
>  static int f2fs_sanity_check_options(struct f2fs_sb_info *sbi, bool remount)
>  {
> +	if (remount &&
> +	    F2FS_OPTION(sbi).pinned_boundary_secno >= MAIN_SECS(sbi)) {
> +		f2fs_err(sbi, "Option pinned_boundary_secno is larger than or equal to total sections (%u >= %u)",
> +				F2FS_OPTION(sbi).pinned_boundary_secno, MAIN_SECS(sbi));
> +		return -EINVAL;
> +	}
>  	if (f2fs_sb_has_device_alias(sbi) &&
>  	    !test_opt(sbi, READ_EXTENT_CACHE)) {
>  		f2fs_err(sbi, "device aliasing requires extent cache");
> @@ -2543,6 +2565,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
>  	else if (F2FS_OPTION(sbi).lookup_mode == LOOKUP_AUTO)
>  		seq_show_option(seq, "lookup_mode", "auto");
>  
> +	if (F2FS_OPTION(sbi).pinned_boundary_secno)
> +		seq_printf(seq, ",pinned_boundary_secno=%u",
> +				F2FS_OPTION(sbi).pinned_boundary_secno);
> +
>  	return 0;
>  }
>  
> @@ -2585,6 +2611,7 @@ static void default_options(struct f2fs_sb_info *sbi, bool remount)
>  	F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON;
>  	F2FS_OPTION(sbi).memory_mode = MEMORY_MODE_NORMAL;
>  	F2FS_OPTION(sbi).errors = MOUNT_ERRORS_CONTINUE;
> +	F2FS_OPTION(sbi).pinned_boundary_secno = 0;
>  
>  	set_opt(sbi, INLINE_XATTR);
>  	set_opt(sbi, INLINE_DATA);
> @@ -3042,6 +3069,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);
>  	limit_reserve_root(sbi);
>  	fc->sb_flags = (flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME);
>  
> @@ -5251,6 +5279,14 @@ 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);
>  
> +	if (F2FS_OPTION(sbi).pinned_boundary_secno >= MAIN_SECS(sbi)) {
> +		f2fs_err(sbi, "Option pinned_boundary_secno is larger than or equal to total sections (%u >= %u)",
> +				F2FS_OPTION(sbi).pinned_boundary_secno, MAIN_SECS(sbi));
> +		err = -EINVAL;
> +		goto free_nm;
> +	}
> +	adjust_pinned_area_boundary(sbi);
> +
>  	sbi->reserved_pin_section = f2fs_sb_has_blkzoned(sbi) ?
>  			ZONED_PIN_SEC_REQUIRED_COUNT :
>  			GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi));
> diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
> index 47b378ccf07a..e0c51f9ec7eb 100644
> --- a/fs/f2fs/sysfs.c
> +++ b/fs/f2fs/sysfs.c
> @@ -1311,6 +1311,7 @@ F2FS_SBI_GENERAL_RW_ATTR(blkzone_alloc_policy);
>  #endif
>  F2FS_SBI_GENERAL_RW_ATTR(carve_out);
>  F2FS_SBI_GENERAL_RW_ATTR(reserved_pin_section);
> +F2FS_SBI_GENERAL_RO_ATTR(pinned_area_max_secno);
>  F2FS_SBI_GENERAL_RW_ATTR(bggc_io_aware);
>  F2FS_SBI_GENERAL_RW_ATTR(max_lock_elapsed_time);
>  F2FS_SBI_GENERAL_RW_ATTR(lock_duration_priority);
> @@ -1523,6 +1524,7 @@ static struct attribute *f2fs_attrs[] = {
>  	ATTR_LIST(max_read_extent_count),
>  	ATTR_LIST(carve_out),
>  	ATTR_LIST(reserved_pin_section),
> +	ATTR_LIST(pinned_area_max_secno),
>  	ATTR_LIST(allocate_section_hint),
>  	ATTR_LIST(allocate_section_policy),
>  	ATTR_LIST(max_lock_elapsed_time),
> -- 
> 2.55.0.691.gc56d675ccc-goog
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-08-24 15:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-18 19:51 [PATCH] f2fs: support pinned boundary section and unify pinned allocation Daeho Jeong
2026-08-18 19:51 ` [f2fs-dev] " Daeho Jeong
2026-08-24 15:31 ` Jaegeuk Kim via Linux-f2fs-devel
2026-08-24 15:31   ` Jaegeuk Kim

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.