]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/xfs/xfs_bmap_util.c
Merge branch 'xfs-buf-iosubmit' into for-next
[karo-tx-linux.git] / fs / xfs / xfs_bmap_util.c
index aa70620e0e62dffb649cc760ab4268d9e314bf86..c2aaa58e59eea7392341533b80159a0befda4c2c 100644 (file)
@@ -1179,6 +1179,7 @@ xfs_free_file_space(
        xfs_bmap_free_t         free_list;
        xfs_bmbt_irec_t         imap;
        xfs_off_t               ioffset;
+       xfs_off_t               iendoffset;
        xfs_extlen_t            mod=0;
        xfs_mount_t             *mp;
        int                     nimap;
@@ -1207,12 +1208,13 @@ xfs_free_file_space(
        inode_dio_wait(VFS_I(ip));
 
        rounding = max_t(xfs_off_t, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
-       ioffset = offset & ~(rounding - 1);
-       error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
-                                             ioffset, -1);
+       ioffset = round_down(offset, rounding);
+       iendoffset = round_up(offset + len, rounding) - 1;
+       error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, ioffset,
+                                            iendoffset);
        if (error)
                goto out;
-       truncate_pagecache_range(VFS_I(ip), ioffset, -1);
+       truncate_pagecache_range(VFS_I(ip), ioffset, iendoffset);
 
        /*
         * Need to zero the stuff we're not freeing, on disk.
@@ -1430,24 +1432,50 @@ xfs_collapse_file_space(
        struct xfs_mount        *mp = ip->i_mount;
        struct xfs_trans        *tp;
        int                     error;
-       xfs_extnum_t            current_ext = 0;
        struct xfs_bmap_free    free_list;
        xfs_fsblock_t           first_block;
        int                     committed;
        xfs_fileoff_t           start_fsb;
+       xfs_fileoff_t           next_fsb;
        xfs_fileoff_t           shift_fsb;
 
        ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
 
        trace_xfs_collapse_file_space(ip);
 
-       start_fsb = XFS_B_TO_FSB(mp, offset + len);
+       next_fsb = XFS_B_TO_FSB(mp, offset + len);
        shift_fsb = XFS_B_TO_FSB(mp, len);
 
        error = xfs_free_file_space(ip, offset, len);
        if (error)
                return error;
 
+       /*
+        * Trim eofblocks to avoid shifting uninitialized post-eof preallocation
+        * into the accessible region of the file.
+        */
+       if (xfs_can_free_eofblocks(ip, true)) {
+               error = xfs_free_eofblocks(mp, ip, false);
+               if (error)
+                       return error;
+       }
+
+       /*
+        * Writeback and invalidate cache for the remainder of the file as we're
+        * about to shift down every extent from the collapse range to EOF. The
+        * free of the collapse range above might have already done some of
+        * this, but we shouldn't rely on it to do anything outside of the range
+        * that was freed.
+        */
+       error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
+                                            offset + len, -1);
+       if (error)
+               return error;
+       error = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping,
+                                       (offset + len) >> PAGE_CACHE_SHIFT, -1);
+       if (error)
+               return error;
+
        while (!error && !done) {
                tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
                /*
@@ -1479,10 +1507,10 @@ xfs_collapse_file_space(
                 * We are using the write transaction in which max 2 bmbt
                 * updates are allowed
                 */
-               error = xfs_bmap_shift_extents(tp, ip, &done, start_fsb,
-                                              shift_fsb, &current_ext,
-                                              &first_block, &free_list,
-                                              XFS_BMAP_MAX_SHIFT_EXTENTS);
+               start_fsb = next_fsb;
+               error = xfs_bmap_shift_extents(tp, ip, start_fsb, shift_fsb,
+                               &done, &next_fsb, &first_block, &free_list,
+                               XFS_BMAP_MAX_SHIFT_EXTENTS);
                if (error)
                        goto out;
 
@@ -1592,7 +1620,7 @@ xfs_swap_extents_check_format(
        return 0;
 }
 
-int
+static int
 xfs_swap_extent_flush(
        struct xfs_inode        *ip)
 {