xfs: merge xfs_ag.h into xfs_format.h
[firefly-linux-kernel-4.4.55.git] / fs / xfs / xfs_bmap_util.c
index 1707980f9a4b564842cd435d9efc70571a5a9b18..6df4730ef5c308bfbd33c143c2d0faab309b411d 100644 (file)
@@ -24,7 +24,6 @@
 #include "xfs_trans_resv.h"
 #include "xfs_bit.h"
 #include "xfs_sb.h"
-#include "xfs_ag.h"
 #include "xfs_mount.h"
 #include "xfs_da_format.h"
 #include "xfs_inode.h"
@@ -42,7 +41,6 @@
 #include "xfs_trace.h"
 #include "xfs_icache.h"
 #include "xfs_log.h"
-#include "xfs_dinode.h"
 
 /* Kernel only BMAP related definitions and functions */
 
@@ -1122,14 +1120,6 @@ xfs_zero_remaining_bytes(
        if (endoff > XFS_ISIZE(ip))
                endoff = XFS_ISIZE(ip);
 
-       bp = xfs_buf_get_uncached(XFS_IS_REALTIME_INODE(ip) ?
-                                       mp->m_rtdev_targp : mp->m_ddev_targp,
-                                 BTOBB(mp->m_sb.sb_blocksize), 0);
-       if (!bp)
-               return -ENOMEM;
-
-       xfs_buf_unlock(bp);
-
        for (offset = startoff; offset <= endoff; offset = lastoffset + 1) {
                uint lock_mode;
 
@@ -1152,42 +1142,24 @@ xfs_zero_remaining_bytes(
                ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
                if (imap.br_state == XFS_EXT_UNWRITTEN)
                        continue;
-               XFS_BUF_UNDONE(bp);
-               XFS_BUF_UNWRITE(bp);
-               XFS_BUF_READ(bp);
-               XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock));
 
-               if (XFS_FORCED_SHUTDOWN(mp)) {
-                       error = -EIO;
-                       break;
-               }
-               xfs_buf_iorequest(bp);
-               error = xfs_buf_iowait(bp);
-               if (error) {
-                       xfs_buf_ioerror_alert(bp,
-                                       "xfs_zero_remaining_bytes(read)");
-                       break;
-               }
+               error = xfs_buf_read_uncached(XFS_IS_REALTIME_INODE(ip) ?
+                               mp->m_rtdev_targp : mp->m_ddev_targp,
+                               xfs_fsb_to_db(ip, imap.br_startblock),
+                               BTOBB(mp->m_sb.sb_blocksize),
+                               0, &bp, NULL);
+               if (error)
+                       return error;
+
                memset(bp->b_addr +
-                       (offset - XFS_FSB_TO_B(mp, imap.br_startoff)),
-                     0, lastoffset - offset + 1);
-               XFS_BUF_UNDONE(bp);
-               XFS_BUF_UNREAD(bp);
-               XFS_BUF_WRITE(bp);
-
-               if (XFS_FORCED_SHUTDOWN(mp)) {
-                       error = -EIO;
-                       break;
-               }
-               xfs_buf_iorequest(bp);
-               error = xfs_buf_iowait(bp);
-               if (error) {
-                       xfs_buf_ioerror_alert(bp,
-                                       "xfs_zero_remaining_bytes(write)");
-                       break;
-               }
+                               (offset - XFS_FSB_TO_B(mp, imap.br_startoff)),
+                      0, lastoffset - offset + 1);
+
+               error = xfs_bwrite(bp);
+               xfs_buf_relse(bp);
+               if (error)
+                       return error;
        }
-       xfs_buf_free(bp);
        return error;
 }
 
@@ -1205,6 +1177,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;
@@ -1233,12 +1206,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.
@@ -1392,14 +1366,14 @@ xfs_zero_file_space(
 
        if (start_boundary < end_boundary - 1) {
                /*
-                * punch out delayed allocation blocks and the page cache over
-                * the conversion range
+                * Writeback the range to ensure any inode size updates due to
+                * appending writes make it to disk (otherwise we could just
+                * punch out the delalloc blocks).
                 */
-               xfs_ilock(ip, XFS_ILOCK_EXCL);
-               error = xfs_bmap_punch_delalloc_range(ip,
-                               XFS_B_TO_FSBT(mp, start_boundary),
-                               XFS_B_TO_FSB(mp, end_boundary - start_boundary));
-               xfs_iunlock(ip, XFS_ILOCK_EXCL);
+               error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
+                               start_boundary, end_boundary - 1);
+               if (error)
+                       goto out;
                truncate_pagecache_range(VFS_I(ip), start_boundary,
                                         end_boundary - 1);
 
@@ -1456,41 +1430,47 @@ 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);
 
-       /*
-        * Writeback the entire file and force remove any post-eof blocks. The
-        * writeback prevents changes to the extent list via concurrent
-        * writeback and the eofblocks trim prevents the extent shift algorithm
-        * from running into a post-eof delalloc extent.
-        *
-        * XXX: This is a temporary fix until the extent shift loop below is
-        * converted to use offsets and lookups within the ILOCK rather than
-        * carrying around the index into the extent list for the next
-        * iteration.
-        */
-       error = filemap_write_and_wait(VFS_I(ip)->i_mapping);
+       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;
        }
 
-       error = xfs_free_file_space(ip, offset, len);
+       /*
+        * 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;
 
@@ -1525,10 +1505,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;
 
@@ -1638,7 +1618,7 @@ xfs_swap_extents_check_format(
        return 0;
 }
 
-int
+static int
 xfs_swap_extent_flush(
        struct xfs_inode        *ip)
 {