Skip to content

Commit d14469e

Browse files
YuKuai-huaweiaxboe
authored andcommitted
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: 47b71ab ("loop: use vfs_getattr_nosec for accurate file size") Reported-by: kernel test robot <[email protected]> Closes: https://lore.kernel.org/oe-lkp/[email protected] Signed-off-by: Yu Kuai <[email protected]> Reviewed-by: Ming Lei <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Link: https://lore.kernel.org/r/[email protected] [axboe: fix spelling error] Signed-off-by: Jens Axboe <[email protected]>
1 parent 370ac28 commit d14469e

File tree

1 file changed

+16
-10
lines changed

1 file changed

+16
-10
lines changed

drivers/block/loop.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -139,20 +139,26 @@ static int part_shift;
139139

140140
static loff_t lo_calculate_size(struct loop_device *lo, struct file *file)
141141
{
142-
struct kstat stat;
143142
loff_t loopsize;
144143
int ret;
145144

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;
149+
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+
}
154161

155-
loopsize = stat.size;
156162
if (lo->lo_offset > 0)
157163
loopsize -= lo->lo_offset;
158164
/* offset is beyond i_size, weird but possible */

0 commit comments

Comments
 (0)