[XFS] hole not shown when file is created with resvsp
authorVlad Apostolov <vapo@sgi.com>
Thu, 16 Aug 2007 05:20:25 +0000 (15:20 +1000)
committerTim Shimmin <tes@chook.melbourne.sgi.com>
Mon, 15 Oct 2007 06:24:21 +0000 (16:24 +1000)
SGI-PV: 967674
SGI-Modid: xfs-linux-melb:xfs-kern:29211a

Signed-off-by: Vlad Apostolov <vapo@sgi.com>
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Tim Shimmin <tes@sgi.com>
fs/xfs/xfs_bmap.c

index 94b5c5fe2681cb6fda698f01ed1cce7f0a97b838..aa19e1fee11fe159f7368d71313f388097cd8db6 100644 (file)
@@ -5742,6 +5742,39 @@ error0:
        return error;
 }
 
+/*
+ * returns 1 for success, 0 if we failed to map the extent.
+ */
+STATIC int
+xfs_getbmapx_fix_eof_hole(
+       xfs_inode_t             *ip,            /* xfs incore inode pointer */
+       struct getbmap          *out,           /* output structure */
+       int                     prealloced,     /* this is a file with
+                                               * preallocated data space */
+       __int64_t               end,            /* last block requested */
+       xfs_fsblock_t           startblock)
+{
+       __int64_t               fixlen;
+       xfs_mount_t             *mp;            /* file system mount point */
+
+       if (startblock == HOLESTARTBLOCK) {
+               mp = ip->i_mount;
+               out->bmv_block = -1;
+               fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, ip->i_size));
+               fixlen -= out->bmv_offset;
+               if (prealloced && out->bmv_offset + out->bmv_length == end) {
+                       /* Came to hole at EOF. Trim it. */
+                       if (fixlen <= 0)
+                               return 0;
+                       out->bmv_length = fixlen;
+               }
+       } else {
+               out->bmv_block = XFS_FSB_TO_DB(ip, startblock);
+       }
+
+       return 1;
+}
+
 /*
  * Fcntl interface to xfs_bmapi.
  */
@@ -5904,18 +5937,15 @@ xfs_getbmap(
                        out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
                        ASSERT(map[i].br_startblock != DELAYSTARTBLOCK);
                         if (map[i].br_startblock == HOLESTARTBLOCK &&
-                           ((prealloced && out.bmv_offset + out.bmv_length == bmvend) ||
-                             whichfork == XFS_ATTR_FORK )) {
-                                /*
-                                 * came to hole at end of file or the end of
-                                   attribute fork
-                                 */
+                           whichfork == XFS_ATTR_FORK) {
+                               /* came to the end of attribute fork */
                                goto unlock_and_return;
                        } else {
-                               out.bmv_block =
-                                   (map[i].br_startblock == HOLESTARTBLOCK) ?
-                                       -1 :
-                                       XFS_FSB_TO_DB(ip, map[i].br_startblock);
+                               if (!xfs_getbmapx_fix_eof_hole(ip, &out,
+                                                       prealloced, bmvend,
+                                                       map[i].br_startblock)) {
+                                       goto unlock_and_return;
+                               }
 
                                /* return either getbmap/getbmapx structure. */
                                if (interface & BMV_IF_EXTENDED) {