loop: use vfs_getattr_nosec for accurate file size
authorRajeev Mishra <rajeevm@hpe.com>
Mon, 18 Aug 2025 18:48:21 +0000 (18:48 +0000)
committerJens Axboe <axboe@kernel.dk>
Mon, 18 Aug 2025 19:10:35 +0000 (13:10 -0600)
Use vfs_getattr_nosec() in lo_calculate_size() for getting the file
size, rather than just read the cached inode size via i_size_read().
This provides better results than cached inode data, particularly for
network filesystems where metadata may be stale.

Signed-off-by: Rajeev Mishra <rajeevm@hpe.com>
Reviewed-by: Yu Kuai <yukuai3@huawei.com>
Link: https://lore.kernel.org/r/20250818184821.115033-3-rajeevm@hpe.com
[axboe: massage commit message]
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/loop.c

index 0e1b9eb9db10600382222d70703d285bbe233f6a..57263c273f0fb4bf2fb1b6612618f290c4dea581 100644 (file)
@@ -139,9 +139,20 @@ 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.
+        */
+       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 */