[PATCH] loop: fix min directio size detection for nested loop devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.
 	 */




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux