Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 47b71abd5846 ("loop: use vfs_getattr_nosec for accurate file size")
Reported-by: kernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202508200409.b2459c02-lkp@intel.com
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20250825093205.3684121-1-yukuai1@huaweicloud.com
[axboe: fix spelling error]
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Yu Kuai and committed by
Jens Axboe
d14469ed 370ac285

+16 -10
+16 -10
drivers/block/loop.c
··· 139 139 140 140 static loff_t lo_calculate_size(struct loop_device *lo, struct file *file) 141 141 { 142 - struct kstat stat; 143 142 loff_t loopsize; 144 143 int ret; 145 144 146 - /* 147 - * Get the accurate file size. This provides better results than 148 - * cached inode data, particularly for network filesystems where 149 - * metadata may be stale. 150 - */ 151 - ret = vfs_getattr_nosec(&file->f_path, &stat, STATX_SIZE, 0); 152 - if (ret) 153 - return 0; 145 + if (S_ISBLK(file_inode(file)->i_mode)) { 146 + loopsize = i_size_read(file->f_mapping->host); 147 + } else { 148 + struct kstat stat; 154 149 155 - loopsize = stat.size; 150 + /* 151 + * Get the accurate file size. This provides better results than 152 + * cached inode data, particularly for network filesystems where 153 + * metadata may be stale. 154 + */ 155 + ret = vfs_getattr_nosec(&file->f_path, &stat, STATX_SIZE, 0); 156 + if (ret) 157 + return 0; 158 + 159 + loopsize = stat.size; 160 + } 161 + 156 162 if (lo->lo_offset > 0) 157 163 loopsize -= lo->lo_offset; 158 164 /* offset is beyond i_size, weird but possible */