From: Rajeev Mishra <rajeevm@xxxxxxx> In lo_calculate_size(), use vfs_getattr_nosec() for non-block files. For block files, continue using i_size_read(). This improves size accuracy on network and distributed filesystems. Signed-off-by: Rajeev Mishra <rajeevm@xxxxxxx> --- drivers/block/loop.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 0e1b9eb9db10..a6214ae40ef0 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -139,9 +139,24 @@ static int part_shift; static loff_t lo_calculate_size(struct loop_device *lo, struct file *file) { + struct kstat stat; loff_t loopsize; - /* Compute loopsize in bytes */ - loopsize = i_size_read(file->f_mapping->host); + int ret; + + /* + * Get the accurate file size. This provides better results than + * cached inode data, particularly for network filesystems where + * metadata may be stale. + */ + if (S_ISBLK(file->f_inode->i_mode)) { + loopsize = i_size_read(file->f_mapping->host); + } else { + ret = vfs_getattr_nosec(&file->f_path, &stat, STATX_SIZE, 0); + if (ret) + return 0; + loopsize = stat.size; + } + if (lo->lo_offset > 0) loopsize -= lo->lo_offset; /* offset is beyond i_size, weird but possible */ -- 2.47.3