]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
HGFS: Fix Linux client inode 512B block count
authorVMware, Inc <>
Wed, 18 Sep 2013 03:32:57 +0000 (20:32 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 23 Sep 2013 05:19:59 +0000 (22:19 -0700)
The Linux HGFS client miscalculated the number of 512 byte blocks to set
in the inode for the file size. It was incorrectly using the HGFS
hardcoded block size instead of 512, which was 1024. This causes the
block count to be half the correct number and so du on a file reports
the incorrect size.  fstat also retrieves this block count in the stat
structure so it is likely more applications will break.

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/modules/linux/vmhgfs/fsutil.c

index 65a3647d0751974c0cf5fe04fb86b655c6fe78c3..4ce77ab7c2eb66e820367e9b94d3d1e2d6bbb7b3 100644 (file)
@@ -545,6 +545,43 @@ HgfsUnpackCommonAttr(HgfsReq *req,            // IN: Reply packet
 }
 
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsChangeFileAttributes --
+ *
+ *    Calculate the number of 512 byte blocks used.
+ *
+ *    Round the size to the next whole block and divide by the block size
+ *    to get the number of 512 byte blocks.
+ *    Note, this is taken from the nfs client and is simply performing:
+ *    (size + 512-1)/ 512)
+ *
+ * Results:
+ *    The number of 512 byte blocks for the size.
+ *
+ * Side effects:
+ *    None
+ *
+ *----------------------------------------------------------------------
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
+static inline blkcnt_t
+HgfsCalcBlockSize(uint64 tsize)
+{
+   blkcnt_t used = (tsize + 511) >> 9;
+   return (used > ULONG_MAX) ? ULONG_MAX : used;
+}
+#else
+static inline unsigned long
+HgfsCalcBlockSize(uint64 tsize)
+{
+   loff_t used = (tsize + 511) >> 9;
+   return (used > ULONG_MAX) ? ULONG_MAX : used;
+}
+#endif
+
+
 /*
  *----------------------------------------------------------------------
  *
@@ -663,7 +700,7 @@ HgfsChangeFileAttributes(struct inode *inode,          // IN/OUT: Inode
     */
    if (attr->mask & HGFS_ATTR_VALID_SIZE) {
       loff_t oldSize = compat_i_size_read(inode);
-      inode->i_blocks = (attr->size + HGFS_BLOCKSIZE - 1) / HGFS_BLOCKSIZE;
+      inode->i_blocks = HgfsCalcBlockSize(attr->size);
       if (oldSize != attr->size) {
          LOG(4, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: new file "
                  "size: %"FMT64"u, old file size: %Lu\n", attr->size, oldSize));