From: Darrick J. Wong <djwong@xxxxxxxxxx> fstest generic/563 sets up a loop device in front of the SCRATCH_DEV block device to test cgroup I/O accounting, because SCRATCH_DEV could be a partition and cgroup accounting apparently only works on full block devices (e.g. sda, not sda1). If however SCRATCH_DEV is itself a loop device that we've used to simulate 4k LBA block devices, the minimum directio size discovery introduced in commit f4774e92aab85d is wrong -- we should query the logical block size of the underlying block device because file->f_path points whatever filesystem /dev is. Otherwise, you get a weird losetup config: $ losetup -f /dev/sda $ losetup --sector-size 4096 /dev/loop0 $ losetup -f /dev/loop0 $ losetup --raw NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC /dev/loop0 0 0 0 0 /dev/sda 1 4096 /dev/loop1 0 0 0 0 /dev/loop0 1 512 (Note loop1 can try to send 512b writes to loop0 which has a sector size of 4k) and mkfs failures like this: error reading existing superblock: Invalid argument mkfs.xfs: pwrite failed: Invalid argument libxfs_bwrite: write failed on (unknown) bno 0x42a3ef8/0x100, err=22 mkfs.xfs: Releasing dirty buffer to free list! found dirty buffer (bulk) on free list! mkfs.xfs: pwrite failed: Invalid argument libxfs_bwrite: write failed on (unknown) bno 0x0/0x100, err=22 Cc: <stable@xxxxxxxxxxxxxxx> # v6.15-rc1 Fixes: f4774e92aab85d ("loop: take the file system minimum dio alignment into account") Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- drivers/block/loop.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 174e67ac729f3d..59d3e713c574b0 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -443,9 +443,17 @@ static void loop_reread_partitions(struct loop_device *lo) static unsigned int loop_query_min_dio_size(struct loop_device *lo) { struct file *file = lo->lo_backing_file; - struct block_device *sb_bdev = file->f_mapping->host->i_sb->s_bdev; + struct inode *inode = file->f_mapping->host; + struct block_device *sb_bdev = inode->i_sb->s_bdev; struct kstat st; + /* + * If the backing device is a block device, don't send directios + * smaller than its LBA size. + */ + if (S_ISBLK(inode->i_mode)) + return bdev_logical_block_size(I_BDEV(inode)); + /* * Use the minimal dio alignment of the file system if provided. */