[PATCH] ntfs: fix sector conversion on 4Kn devices

From: 朱 天浩

Date: Thu Sep 03 2026 - 09:13:12 EST


The NTFS driver was converting byte offsets to bio sector numbers using
the filesystem block size (sb->s_blocksize_bits). However, block layer
sector numbers - bio->bi_iter.bi_sector and sector_t - are always in
units of 512 bytes, independent of the filesystem block size.

On a device with a 4096 byte logical block size (4Kn), sb_min_blocksize()
lifts s_blocksize to 4096, so every MFT writeback bio built by
ntfs_sync_mft_mirror(), write_mft_record_nolock() and
ntfs_mft_writepages() ended up with a sector number eight times too
small. The resulting LBA is not only wrong, it is usually not a
multiple of the logical block size either, and some controllers reject
the write outright, e.g.:

ntfs: (device nvme0n1p3): ntfs_sync_mft_mirror(): I/O error while
writing mft mirror record 0x3!
ntfs: (device nvme0n1p3): write_mft_record_nolock(): I/O error while
writing mft record 0x3! Marking base inode as bad.

Reproduced on an Apple SSD AP0256J (4Kn) with a volume using 4096 byte
sectors, 4096 byte clusters and clusters_per_mft_record = 1; after the
fix a 13 MB file written to the volume is byte-for-byte identical
after a umount/mount cycle.

Fixes: 40796051991d ("ntfs: update in-memory, on-disk structures and headers")
Signed-off-by: Zhu Tianhao <zhutianhao75@xxxxxxxxxxx>
---
fs/ntfs/ntfs.h | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
index df5a75d506f6..b66ce62f67c9 100644
--- a/fs/ntfs/ntfs.h
+++ b/fs/ntfs/ntfs.h
@@ -20,6 +20,7 @@
#include <linux/smp.h>
#include <linux/pagemap.h>
#include <linux/uidgid.h>
+#include <linux/blkdev.h> /* For SECTOR_SHIFT. */

#include "volume.h"
#include "layout.h"
@@ -71,7 +72,11 @@
#define NTFS_CLU_TO_POFS(vol, clu) (((u64)(clu) << (vol)->cluster_size_bits) & \
~PAGE_MASK)

-#define NTFS_B_TO_SECTOR(vol, b) ((b) >> ((vol)->sb)->s_blocksize_bits)
+/*
+ * bio->bi_iter.bi_sector and sector_t are always in 512-byte sectors, even
+ * when the filesystem block size is larger (for example 4KiB).
+ */
+#define NTFS_B_TO_SECTOR(vol, b) ntfs_bytes_to_sector(vol, b)

enum {
NTFS_BLOCK_SIZE = 512,
@@ -154,11 +159,15 @@ static inline u64 ntfs_cluster_to_poff(const struct ntfs_volume *vol,
return (clu << vol->cluster_size_bits) & ~PAGE_MASK;
}

-/* Convert byte offset to sector (block) number. */
+/* Convert byte offset to a block layer sector number. Those are always in
+ * units of 512 bytes, never in units of sb->s_blocksize, which is raised to
+ * the device logical block size on 4Kn devices.
+ */
static inline sector_t ntfs_bytes_to_sector(const struct ntfs_volume *vol,
u64 bytes)
{
- return bytes >> vol->sb->s_blocksize_bits;
+ (void)vol;
+ return bytes >> SECTOR_SHIFT;
}

/* Global variables. */
--
2.51.0