Re: [PATCH v3] loop: use vfs_getattr_nosec() for accurate file size

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

在 2025/08/13 4:07, Rajeev Mishra 写道:
This commit includes the following changes:
  1. Renamed get_size to lo_calculate_size.
  2. Merged the functionality of get_size and
     get_loop_size into lo_calculate_size.
  3  Updated callers of the above functions
     to use lo_calculate_size.
  4. Replaced i_size_read with vfs_getattr_nosec()
     to obtain a more accurate file size for
      network filesystems where cached metadata may be stale

Please split 1-3 to a seperate patch.

Signed-off-by: Rajeev Mishra <rajeevm@xxxxxxx>
---
  drivers/block/loop.c | 53 +++++++++++++++++++++++++++++---------------
  1 file changed, 35 insertions(+), 18 deletions(-)

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 1b6ee91f8eb9..6bfec38275b0 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -137,20 +137,43 @@ static void loop_global_unlock(struct loop_device *lo, bool global)
  static int max_part;
  static int part_shift;
-static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file)
+/**
+ * lo_calculate_size - calculate the effective size of a loop device
+ * @lo: loop device
+ * @file: backing file
+ *
+ * Calculate the effective size of the loop device based on backing file size,
+ * offset, and size limit. Uses vfs_getattr_nosec() for accurate file size
+ * information, particularly important for network filesystems where cached
+ * metadata may be stale.
+ *
+ * Returns: size in 512-byte sectors, or 0 on error
+ */

I feel this internal function comment is not necessary, the name can
explain itself, and you explain getattr below as well.

Otherwise this patch LGTM.

Thanks,
Kuai

+static loff_t lo_calculate_size(struct loop_device *lo, struct file *file)
  {
+	struct kstat stat;
  	loff_t loopsize;
+	int ret;
- /* Compute loopsize in bytes */
-	loopsize = i_size_read(file->f_mapping->host);
-	if (offset > 0)
-		loopsize -= offset;
-	/* offset is beyond i_size, weird but possible */
+	/*
+	 * 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 file size, weird but possible */
  	if (loopsize < 0)
  		return 0;
- if (sizelimit > 0 && sizelimit < loopsize)
-		loopsize = sizelimit;
+	if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize)
+		loopsize = lo->lo_sizelimit;
  	/*
  	 * Unfortunately, if we want to do I/O on the device,
  	 * the number of 512-byte sectors has to fit into a sector_t.
@@ -158,11 +181,6 @@ static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file)
  	return loopsize >> 9;
  }
-static loff_t get_loop_size(struct loop_device *lo, struct file *file)
-{
-	return get_size(lo->lo_offset, lo->lo_sizelimit, file);
-}
-
  /*
   * We support direct I/O only if lo_offset is aligned with the logical I/O size
   * of backing device, and the logical block size of loop is bigger than that of
@@ -569,7 +587,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
  	error = -EINVAL;
/* size of the new backing store needs to be the same */
-	if (get_loop_size(lo, file) != get_loop_size(lo, old_file))
+	if (lo_calculate_size(lo, file) != lo_calculate_size(lo, old_file))
  		goto out_err;
/*
@@ -1063,7 +1081,7 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
  	loop_update_dio(lo);
  	loop_sysfs_init(lo);
- size = get_loop_size(lo, file);
+	size = lo_calculate_size(lo, file);
  	loop_set_size(lo, size);
/* Order wrt reading lo_state in loop_validate_file(). */
@@ -1255,8 +1273,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
  	if (partscan)
  		clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state);
  	if (!err && size_changed) {
-		loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit,
-					   lo->lo_backing_file);
+		loff_t new_size = lo_calculate_size(lo, lo->lo_backing_file);
  		loop_set_size(lo, new_size);
  	}
  out_unlock:
@@ -1399,7 +1416,7 @@ static int loop_set_capacity(struct loop_device *lo)
  	if (unlikely(lo->lo_state != Lo_bound))
  		return -ENXIO;
- size = get_loop_size(lo, lo->lo_backing_file);
+	size = lo_calculate_size(lo, lo->lo_backing_file);
  	loop_set_size(lo, size);
return 0;






[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux