ntfs: compute bi_sector in 512-byte units

bi_sector counts in 512 byte sectors and not in multiples of the
volume's sector size. Under "normal" circumstances (with 512 byte
sectors in NTFS) the current code works as is; however, when we have
a 4k sector size on the volume the current usage of NTFS_B_TO_SECTOR()
and ntfs_bytes_to_sector() end up converting to the number of 4k
sectors after mount.

Reads work today on 4k volumes as bdev-io.c as performing the shift
correctly inline. With writes, we end up with significant silent disk
corruption on these volumes.

This fixes changes to use the new ntfs_bytes_to_bio_sector() function
everywhere we're performing this calculation (including the existing
read path). For the change in inode.c it removes a dead code block
rather than updating.

Fixes: 4079605199 ("ntfs: update in-memory, on-disk structures and headers")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Dennis Tighe <dennis.tighe@gmail.com>
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
Dennis Tighe 2026-08-23 00:13:25 -07:00 committed by Namjae Jeon
parent 323751a604
commit 6faa235a64
5 changed files with 14 additions and 22 deletions

View File

@ -34,7 +34,7 @@ int ntfs_bdev_read(struct block_device *bdev, char *data, loff_t start, size_t s
int error;
struct bio *bio;
blk_opf_t op;
sector_t sector = start >> SECTOR_SHIFT;
sector_t sector = ntfs_bytes_to_bio_sector(start);
if (start & (SECTOR_SIZE - 1))
return -EINVAL;

View File

@ -1414,7 +1414,7 @@ static int ntfs_write_cb(struct ntfs_inode *ni, loff_t pos, struct page **pages,
bio_pos = ntfs_cluster_to_bytes(vol, bio_lcn);
bio = bio_alloc(vol->sb->s_bdev, DIV_ROUND_UP(bio_size, PAGE_SIZE),
REQ_OP_WRITE, GFP_NOIO);
bio->bi_iter.bi_sector = ntfs_bytes_to_sector(vol, bio_pos);
bio->bi_iter.bi_sector = ntfs_bytes_to_bio_sector(bio_pos);
for (i = 0; bio_size; i++) {
unsigned int len = min_t(unsigned int, bio_size, PAGE_SIZE);

View File

@ -1852,7 +1852,7 @@ int ntfs_read_inode_mount(struct inode *vi)
struct mft_record *m = NULL;
struct attr_record *a;
struct ntfs_attr_search_ctx *ctx;
unsigned int i, nr_blocks;
unsigned int i;
int err;
size_t new_rl_count;
@ -1896,11 +1896,6 @@ int ntfs_read_inode_mount(struct inode *vi)
goto err_out;
}
/* Determine the first block of the $MFT/$DATA attribute. */
nr_blocks = ntfs_bytes_to_sector(vol, vol->mft_record_size);
if (!nr_blocks)
nr_blocks = 1;
/* Load $MFT/$DATA's first mft record. */
err = ntfs_bdev_read(sb->s_bdev, (char *)m,
ntfs_cluster_to_bytes(vol, vol->mft_lcn), i);
@ -3780,8 +3775,7 @@ static s64 __ntfs_inode_non_resident_attr_pwrite(struct inode *vi,
bio = bio_alloc(vol->sb->s_bdev, 1, REQ_OP_WRITE,
GFP_NOIO);
bio->bi_iter.bi_sector =
ntfs_bytes_to_sector(vol,
ntfs_cluster_to_bytes(vol, lcn) +
ntfs_bytes_to_bio_sector(ntfs_cluster_to_bytes(vol, lcn) +
lcn_folio_off);
length = min_t(unsigned long,

View File

@ -499,8 +499,8 @@ int ntfs_sync_mft_mirror(struct ntfs_volume *vol, const u64 mft_no,
bio = bio_alloc(vol->sb->s_bdev, 1, REQ_OP_WRITE, GFP_NOIO);
bio->bi_iter.bi_sector =
NTFS_B_TO_SECTOR(vol, NTFS_CLU_TO_B(vol, vol->mftmirr_lcn) +
lcn_folio_off + folio_ofs);
ntfs_bytes_to_bio_sector(NTFS_CLU_TO_B(vol, vol->mftmirr_lcn) +
lcn_folio_off + folio_ofs);
if (bio_add_folio(bio, folio, vol->mft_record_size, folio_ofs))
err = submit_bio_wait(bio);
@ -592,8 +592,8 @@ int write_mft_record_nolock(struct ntfs_inode *ni, struct mft_record *m, int syn
bio = bio_alloc(vol->sb->s_bdev, 1, REQ_OP_WRITE, GFP_NOIO);
bio->bi_iter.bi_sector =
NTFS_B_TO_SECTOR(vol, NTFS_CLU_TO_B(vol, ni->mft_lcn[i]) +
clu_off);
ntfs_bytes_to_bio_sector(NTFS_CLU_TO_B(vol, ni->mft_lcn[i]) +
clu_off);
if (!bio_add_folio(bio, folio, folio_size,
ni->folio_ofs + offset)) {
@ -2742,8 +2742,8 @@ static int ntfs_write_mft_block(struct folio *folio, struct writeback_control *w
bio = bio_alloc(vol->sb->s_bdev, 1, REQ_OP_WRITE,
GFP_NOIO);
bio->bi_iter.bi_sector =
ntfs_bytes_to_sector(vol,
ntfs_cluster_to_bytes(vol, lcn) + off);
ntfs_bytes_to_bio_sector(
ntfs_cluster_to_bytes(vol, lcn) + off);
}
if (vol->cluster_size == NTFS_BLOCK_SIZE &&

View File

@ -19,6 +19,7 @@
#include <linux/nls.h>
#include <linux/smp.h>
#include <linux/pagemap.h>
#include <linux/blk_types.h>
#include <linux/uidgid.h>
#include "volume.h"
@ -71,8 +72,6 @@
#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)
enum {
NTFS_BLOCK_SIZE = 512,
NTFS_BLOCK_SIZE_BITS = 9,
@ -154,11 +153,10 @@ 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. */
static inline sector_t ntfs_bytes_to_sector(const struct ntfs_volume *vol,
u64 bytes)
/* Convert a byte offset on the volume to a bio sector number. */
static inline sector_t ntfs_bytes_to_bio_sector(u64 bytes)
{
return bytes >> vol->sb->s_blocksize_bits;
return bytes >> SECTOR_SHIFT;
}
/* Global variables. */