Commit d14469ed authored by Yu Kuai's avatar Yu Kuai Committed by Jens Axboe
Browse files

loop: fix zero sized loop for block special file



By default, /dev/sda is block special file from devtmpfs, getattr will
return file size as zero, causing loop failed for raw block device.

We can add bdev_statx() to return device size, however this may
introduce changes that are not acknowledged by user. Fix this problem by
reverting changes for block special file, file mapping host is set to
bdev inode while opening, and use i_size_read() directly to get device
size.

Fixes: 47b71abd ("loop: use vfs_getattr_nosec for accurate file size")
Reported-by: default avatarkernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202508200409.b2459c02-lkp@intel.com


Signed-off-by: default avatarYu Kuai <yukuai3@huawei.com>
Reviewed-by: default avatarMing Lei <ming.lei@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20250825093205.3684121-1-yukuai1@huaweicloud.com


[axboe: fix spelling error]
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 370ac285
Loading
Loading
Loading
Loading
+16 −10
Original line number Diff line number Diff line
@@ -139,10 +139,14 @@ static int part_shift;

static loff_t lo_calculate_size(struct loop_device *lo, struct file *file)
{
	struct kstat stat;
	loff_t loopsize;
	int ret;

	if (S_ISBLK(file_inode(file)->i_mode)) {
		loopsize = i_size_read(file->f_mapping->host);
	} else {
		struct kstat stat;

		/*
		 * Get the accurate file size. This provides better results than
		 * cached inode data, particularly for network filesystems where
@@ -153,6 +157,8 @@ static loff_t lo_calculate_size(struct loop_device *lo, struct file *file)
			return 0;

		loopsize = stat.size;
	}

	if (lo->lo_offset > 0)
		loopsize -= lo->lo_offset;
	/* offset is beyond i_size, weird but possible */