]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
fs/ntfs3: check minimum alignment for direct I/O
authorKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Thu, 30 Oct 2025 20:45:33 +0000 (23:45 +0300)
committerKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Mon, 17 Nov 2025 08:09:13 +0000 (09:09 +0100)
Add a check for minimum alignment when performing direct I/O reads. If the
file offset or user buffer is not aligned to the device's logical block
size, fall back to buffered I/O instead of continuing with unaligned direct I/O.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3/file.c
fs/ntfs3/ntfs_fs.h
fs/ntfs3/super.c

index b9484f48db34f8feb1983e9d812f2336b5ff7266..3b22c73756160edc4467e4138bfee1d33004f644 100644 (file)
@@ -941,6 +941,16 @@ static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
                file->f_ra.ra_pages = 0;
        }
 
+       /* Check minimum alignment for dio. */
+       if (iocb->ki_flags & IOCB_DIRECT) {
+               struct super_block *sb = inode->i_sb;
+               struct ntfs_sb_info *sbi = sb->s_fs_info;
+               if ((iocb->ki_pos | iov_iter_alignment(iter)) &
+                   sbi->bdev_blocksize_mask) {
+                       iocb->ki_flags &= ~IOCB_DIRECT;
+               }
+       }
+
        return generic_file_read_iter(iocb, iter);
 }
 
index 8ff49c5a2973d1d49f3bc16b0d6d693b2907c7a6..a4559c9f64e6865274219883d91ec5bd996b3f10 100644 (file)
@@ -212,6 +212,7 @@ struct ntfs_sb_info {
 
        u32 discard_granularity;
        u64 discard_granularity_mask_inv; // ~(discard_granularity_mask_inv-1)
+       u32 bdev_blocksize_mask; // bdev_logical_block_size(bdev) - 1;
 
        u32 cluster_size; // bytes per cluster
        u32 cluster_mask; // == cluster_size - 1
index 96f56333cf9983af19bf60d6142fdbc1ea2cea76..f481e9df0237ff26faad310a40f35a8a0777460c 100644 (file)
@@ -1075,6 +1075,7 @@ read_boot:
                dev_size += sector_size - 1;
        }
 
+       sbi->bdev_blocksize_mask = max(boot_sector_size, sector_size) - 1;
        sbi->mft.lbo = mlcn << cluster_bits;
        sbi->mft.lbo2 = mlcn2 << cluster_bits;