Merge tag 'qcom-soc-for-3.16-2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / fs / xfs / xfs_bmap.c
index 5b6092e..f0efc7e 100644 (file)
@@ -5413,6 +5413,7 @@ xfs_bmap_shift_extents(
        int                             whichfork = XFS_DATA_FORK;
        int                             logflags;
        xfs_filblks_t                   blockcount = 0;
+       int                             total_extents;
 
        if (unlikely(XFS_TEST_ERROR(
            (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
@@ -5429,7 +5430,6 @@ xfs_bmap_shift_extents(
        ASSERT(current_ext != NULL);
 
        ifp = XFS_IFORK_PTR(ip, whichfork);
-
        if (!(ifp->if_flags & XFS_IFEXTENTS)) {
                /* Read in all the extents */
                error = xfs_iread_extents(tp, ip, whichfork);
@@ -5456,7 +5456,6 @@ xfs_bmap_shift_extents(
 
        /* We are going to change core inode */
        logflags = XFS_ILOG_CORE;
-
        if (ifp->if_flags & XFS_IFBROOT) {
                cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
                cur->bc_private.b.firstblock = *firstblock;
@@ -5467,8 +5466,14 @@ xfs_bmap_shift_extents(
                logflags |= XFS_ILOG_DEXT;
        }
 
-       while (nexts++ < num_exts &&
-              *current_ext <  XFS_IFORK_NEXTENTS(ip, whichfork)) {
+       /*
+        * There may be delalloc extents in the data fork before the range we
+        * are collapsing out, so we cannot
+        * use the count of real extents here. Instead we have to calculate it
+        * from the incore fork.
+        */
+       total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
+       while (nexts++ < num_exts && *current_ext < total_extents) {
 
                gotp = xfs_iext_get_ext(ifp, *current_ext);
                xfs_bmbt_get_all(gotp, &got);
@@ -5556,10 +5561,11 @@ xfs_bmap_shift_extents(
                }
 
                (*current_ext)++;
+               total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
        }
 
        /* Check if we are done */
-       if (*current_ext ==  XFS_IFORK_NEXTENTS(ip, whichfork))
+       if (*current_ext == total_extents)
                *done = 1;
 
 del_cursor:
@@ -5568,6 +5574,5 @@ del_cursor:
                        error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
 
        xfs_trans_log_inode(tp, ip, logflags);
-
        return error;
 }