mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] f2fs-tools: set the block size of zoned devices to the logical block size
@ 2026-11-13 20:09 Daeho Jeong
  0 siblings, 0 replies; only message in thread
From: Daeho Jeong @ 2026-11-13 20:09 UTC (permalink / raw)
  To: linux-kernel, linux-f2fs-devel, kernel-team; +Cc: Daeho Jeong

From: Daeho Jeong <daehojeong@google.com>

The kernel caches a block device in units of its soft block size, which
is set to the largest power of two that divides the device size, up to
PAGE_SIZE. On a 16KB page kernel, it is 16KB even for a 4KB logical
block device, so a buffered 4KB write is written back as a whole 16KB
unit.

On a host-managed zoned device, the first write in a unit then moves the
write pointer of the sequential zone beyond the written data, and the
next write in the same unit is rejected as an unaligned write, e.g.

  Buffer I/O error on dev nvme0n1, logical block 24576, lost async page write
  Error: While writing the quota_blk to disk!!!

Set the soft block size of zoned devices to their logical block size
with BLKBSZSET, so that each write covers whole units. If it cannot be
set and the current one is larger, fail right away instead of failing in
the middle of the writes. Skip it for dump.f2fs and --dry-run, which do
not write to the device, and when the page size is not larger than the
logical block size, as the soft block size is not larger then either.

Signed-off-by: Daeho Jeong <daehojeong@google.com>
---
 lib/libf2fs.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index 93f36ca..b0cdf09 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -922,6 +922,14 @@ void get_kernel_uname_version(__u8 *version)
 #define BLKSSZGET	_IO(0x12,104)
 #endif
 
+#if defined(__linux__) && defined(_IOR) && !defined(BLKBSZGET)
+#define BLKBSZGET	_IOR(0x12,112, size_t)
+#endif
+
+#if defined(__linux__) && defined(_IOW) && !defined(BLKBSZSET)
+#define BLKBSZSET	_IOW(0x12,113, size_t)
+#endif
+
 #if defined(__APPLE__)
 #include <sys/disk.h>
 #define BLKGETSIZE	DKIOCGETBLOCKCOUNT
@@ -1047,6 +1055,34 @@ int get_device_info(int i)
 		else if (dev->sector_size < sector_size)
 			dev->sector_size = sector_size;
 #endif
+#if defined(BLKBSZGET) && defined(BLKBSZSET)
+		/*
+		 * The page cache of a block device is managed in units of its
+		 * soft block size, which can be as large as PAGE_SIZE. A
+		 * smaller write is then written back as a whole unit, which
+		 * moves the write pointer of a sequential zone beyond the
+		 * written data, and makes the next write in the same unit
+		 * fail. Use the logical block size for zoned devices, and do
+		 * not go on to write to the device if it cannot be set. The
+		 * soft block size is larger than the logical block size only
+		 * when PAGE_SIZE is, so leave it alone otherwise.
+		 */
+		if (dev->zoned_model == F2FS_ZONED_HM &&
+				c.func != DUMP && !c.dry_run &&
+				sysconf(_SC_PAGESIZE) > (long)dev->sector_size) {
+			int bsz = dev->sector_size;
+			int cur_bsz = 0;
+
+			if (ioctl(fd, BLKBSZSET, &bsz) < 0 &&
+			    (ioctl(fd, BLKBSZGET, &cur_bsz) < 0 ||
+			     cur_bsz > bsz)) {
+				MSG(0, "\tError: Cannot set the block size "
+					"of %s to %d\n", dev->path, bsz);
+				free(stat_buf);
+				return -1;
+			}
+		}
+#endif
 #ifdef BLKGETSIZE64
 		if (ioctl(fd, BLKGETSIZE64, &dev->total_sectors) < 0) {
 			MSG(0, "\tError: Cannot get the device size\n");
-- 
2.56.0.611.g1030f0b940-goog


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-11-13 20:09 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-13 20:09 [PATCH] f2fs-tools: set the block size of zoned devices to the logical block size Daeho Jeong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®