1. 24 Mar, 2018 14 commits
  2. 15 Mar, 2018 6 commits
  3. 14 Mar, 2018 6 commits
  4. 12 Mar, 2018 14 commits
    • Brian Foster's avatar
      xfs: account only rmapbt-used blocks against rmapbt perag res · 0ab32086
      Brian Foster authored
      The rmapbt perag metadata reservation reserves blocks for the
      reverse mapping btree (rmapbt). Since the rmapbt uses blocks from
      the agfl and perag accounting is updated as blocks are allocated
      from the allocation btrees, the reservation actually accounts blocks
      as they are allocated to (or freed from) the agfl rather than the
      rmapbt itself.
      
      While this works for blocks that are eventually used for the rmapbt,
      not all agfl blocks are destined for the rmapbt. Blocks that are
      allocated to the agfl (and thus "reserved" for the rmapbt) but then
      used by another structure leads to a growing inconsistency over time
      between the runtime tracking of rmapbt usage vs. actual rmapbt
      usage. Since the runtime tracking thinks all agfl blocks are rmapbt
      blocks, it essentially believes that less future reservation is
      required to satisfy the rmapbt than what is actually necessary.
      
      The inconsistency is rectified across mount cycles because the perag
      reservation is initialized based on the actual rmapbt usage at mount
      time. The problem, however, is that the excessive drain of the
      reservation at runtime opens a window to allocate blocks for other
      purposes that might be required for the rmapbt on a subsequent
      mount. This problem can be demonstrated by a simple test that runs
      an allocation workload to consume agfl blocks over time and then
      observe the difference in the agfl reservation requirement across an
      unmount/mount cycle:
      
        mount ...: xfs_ag_resv_init: ... resv 3193 ask 3194 len 3194
        ...
        ...      : xfs_ag_resv_alloc_extent: ... resv 2957 ask 3194 len 1
        umount...: xfs_ag_resv_free: ... resv 2956 ask 3194 len 0
        mount ...: xfs_ag_resv_init: ... resv 3052 ask 3194 len 3194
      
      As the above tracepoints show, the reservation requirement reduces
      from 3194 blocks to 2956 blocks as the workload runs.  Without any
      other changes in the filesystem, the same reservation requirement
      jumps from 2956 to 3052 blocks over a umount/mount cycle.
      
      To address this divergence, update the RMAPBT reservation to account
      blocks used for the rmapbt only rather than all blocks filled into
      the agfl. This patch makes several high-level changes toward that
      end:
      
      1.) Reintroduce an AGFL reservation type to serve as an accounting
          no-op for blocks allocated to (or freed from) the AGFL.
      2.) Invoke RMAPBT usage accounting from the actual rmapbt block
          allocation path rather than the AGFL allocation path.
      
      The first change is required because agfl blocks are considered free
      blocks throughout their lifetime. The perag reservation subsystem is
      invoked unconditionally by the allocation subsystem, so we need a
      way to tell the perag subsystem (via the allocation subsystem) to
      not make any accounting changes for blocks filled into the AGFL.
      
      The second change causes the in-core RMAPBT reservation usage
      accounting to remain consistent with the on-disk state at all times
      and eliminates the risk of leaving the rmapbt reservation
      underfilled.
      Signed-off-by: default avatarBrian Foster <bfoster@redhat.com>
      Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      0ab32086
    • Brian Foster's avatar
      xfs: rename agfl perag res type to rmapbt · 21592863
      Brian Foster authored
      The AGFL perag reservation type accounts all allocations that feed
      into (or are released from) the allocation group free list (agfl).
      The purpose of the reservation is to support worst case conditions
      for the reverse mapping btree (rmapbt). As such, the agfl
      reservation usage accounting only considers rmapbt usage when the
      in-core counters are initialized at mount time.
      
      This implementation inconsistency leads to divergence of the in-core
      and on-disk usage accounting over time. In preparation to resolve
      this inconsistency and adjust the AGFL reservation into an rmapbt
      specific reservation, rename the AGFL reservation type and
      associated accounting fields to something more rmapbt-specific. Also
      fix up a couple tracepoints that incorrectly use the AGFL
      reservation type to pass the agfl state of the associated extent
      where the raw reservation type is expected.
      
      Note that this patch does not change perag reservation behavior.
      Signed-off-by: default avatarBrian Foster <bfoster@redhat.com>
      Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      21592863
    • Brian Foster's avatar
      xfs: account format bouncing into rmapbt swapext tx reservation · b3fed434
      Brian Foster authored
      The extent swap mechanism requires a unique implementation for
      rmapbt enabled filesystems. Because the rmapbt tracks extent owner
      information, extent swap must individually unmap and remap each
      extent between the two inodes.
      
      The rmapbt extent swap transaction block reservation currently
      accounts for the worst case bmapbt block and rmapbt block
      consumption based on the extent count of each inode. There is a
      corner case that exists due to the extent swap implementation that
      is not covered by this reservation, however.
      
      If one of the associated inodes is just over the max extent count
      used for extent format inodes (i.e., the inode is in btree format by
      a single extent), the unmap/remap cycle of the extent swap can
      bounce the inode between extent and btree format multiple times,
      almost as many times as there are extents in the inode (if the
      opposing inode happens to have one less, for example). Each back and
      forth cycle involves a block free and allocation, which isn't a
      problem except for that the initial transaction reservation must
      account for the total number of block allocations performed by the
      chain of deferred operations. If not, a block reservation overrun
      occurs and the filesystem shuts down.
      
      Update the rmapbt extent swap block reservation to check for this
      situation and add some block reservation slop to ensure the entire
      operation succeeds. We'd never likely require reservation for both
      inodes as fsr wouldn't defrag the file in that case, but the
      additional reservation is constrained by the data fork size so be
      cautious and check for both.
      Signed-off-by: default avatarBrian Foster <bfoster@redhat.com>
      Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      b3fed434
    • Brian Foster's avatar
      xfs: shutdown if block allocation overruns tx reservation · 3e78b9a4
      Brian Foster authored
      The ->t_blk_res_used field tracks how many blocks have been used in
      the current transaction. This should never exceed the block
      reservation (->t_blk_res) for a particular transaction. We currently
      assert this condition in the transaction block accounting code, but
      otherwise take no additional action should this situation occur.
      
      The overrun generally has no effect if space ends up being available
      and the associated transaction commits. If the transaction is
      duplicated, however, the current block usage is used to determine
      the remaining block reservation to be transferred to the new
      transaction. If usage exceeds reservation, this calculation
      underflows and creates a transaction with an invalid and excessive
      reservation. When the second transaction commits, the release of
      unused blocks corrupts the in-core free space counters. With lazy
      superblock accounting enabled, this inconsistency eventually
      trickles to the on-disk superblock and corrupts the filesystem.
      
      Replace the transaction block usage accounting assert with an
      explicit overrun check. If the transaction overruns the reservation,
      shutdown the filesystem immediately to prevent corruption. Add a new
      assert to xfs_trans_dup() to catch any callers that might induce
      this invalid state in the future.
      Signed-off-by: default avatarBrian Foster <bfoster@redhat.com>
      Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      3e78b9a4
    • Matthew Wilcox's avatar
      xfs: Rename xa_ elements to ail_ · 57e80956
      Matthew Wilcox authored
      This is a simple rename, except that xa_ail becomes ail_head.
      Signed-off-by: default avatarMatthew Wilcox <mawilcox@microsoft.com>
      Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      57e80956
    • Dave Chinner's avatar
      inode: don't memset the inode address space twice · ae23395d
      Dave Chinner authored
      Noticed when looking at why cycling 600k inodes/s through the inode
      cache was taking a total of 8% cpu in memset() during inode
      initialisation.  There is no need to zero the inode.i_data structure
      twice.
      
      This increases single threaded bulkstat throughput from ~200,000
      inodes/s to ~220,000 inodes/s, so we save a substantial amount of
      CPU time per inode init by doing this.
      Signed-Off-By: default avatarDave Chinner <dchinner@redhat.com>
      Reviewed-by: default avatarJan Kara <jack@suse.cz>
      Reviewed-by: default avatarCarlos Maiolino <cmaiolino@redhat.com>
      Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      ae23395d
    • Dave Chinner's avatar
      xfs: convert XFS_AGFL_SIZE to a helper function · a78ee256
      Dave Chinner authored
      The AGFL size calculation is about to get more complex, so lets turn
      the macro into a function first and remove the macro.
      Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
      [darrick: forward port to newer kernel, simplify the helper]
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
      a78ee256
    • Darrick J. Wong's avatar
      xfs: check for cow blocks before trying to clear them · 6231848c
      Darrick J. Wong authored
      There's no point in allocating a transaction and locking the inode in
      preparation to clear cow blocks if there actually are any cow fork
      extents.  Therefore, move the xfs_reflink_cancel_cow_range hunk to
      xfs_inactive and check the cow ifp first.  This makes inode reclamation
      run faster.
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
      6231848c
    • Darrick J. Wong's avatar
      xfs: convert a few more directory asserts to corruption · 3f883f5b
      Darrick J. Wong authored
      Yet another round of playing whack-a-mole with directory code that
      asserts on corrupt on-disk metadata when it really should be returning
      -EFSCORRUPTED instead of ASSERTing.  Found by a xfs/391 crash while
      lastbit fuzzing of ltail.bestcount.
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
      3f883f5b
    • Darrick J. Wong's avatar
      xfs: don't iunlock the quota ip when quota block · 8241f7f9
      Darrick J. Wong authored
      In xfs_qm_dqalloc, we join the locked quota inode to the transaction we
      use to allocate blocks.  If the allocation or mapping fails, we're not
      allowed to unlock the inode because the transaction code is in charge of
      unlocking it for us.  Therefore, remove the iunlock call to avoid
      blowing asserts about unbalanced locking + mount hang.
      
      Found by corrupting the AGF and allocating space in the filesystem
      (quotacheck) immediately after mount.  The upcoming agfl wrapping fixup
      test will trigger this scenario.
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
      8241f7f9
    • Vratislav Bendel's avatar
      xfs: Correctly invert xfs_buftarg LRU isolation logic · 19957a18
      Vratislav Bendel authored
      Due to an inverted logic mistake in xfs_buftarg_isolate()
      the xfs_buffers with zero b_lru_ref will take another trip
      around LRU, while isolating buffers with non-zero b_lru_ref.
      
      Additionally those isolated buffers end up right back on the LRU
      once they are released, because b_lru_ref remains elevated.
      
      Fix that circuitous route by leaving them on the LRU
      as originally intended.
      Signed-off-by: default avatarVratislav Bendel <vbendel@redhat.com>
      Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
      Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
      Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      19957a18
    • Dave Chinner's avatar
      xfs: fix transaction allocation deadlock in IO path · 4df0f7f1
      Dave Chinner authored
      xfs_trans_alloc() does GFP_KERNEL allocation, and we can call it
      while holding pages locked for writeback in the ->writepages path.
      The memory allocation is allowed to wait on pages under writeback,
      and so can wait on pages that are tagged as writeback by the
      caller.
      
      This affects both pre-IO submission and post-IO submission paths.
      Hence xfs_setsize_trans_alloc(), xfs_reflink_end_cow(),
      xfs_iomap_write_unwritten() and xfs_reflink_cancel_cow_range().
      xfs_iomap_write_unwritten() already does the right thing, but the
      others don't. Fix them.
      Signed-Off-By: default avatarDave Chinner <dchinner@redhat.com>
      Fixes: 281627df ("xfs: log file size updates at I/O completion time")
      Fixes: 43caeb18 ("xfs: move mappings from cow fork to data fork after copy-write)"
      Reviewed-by: default avatarEric Sandeen <sandeen@redhat.com>
      Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
      Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      4df0f7f1
    • Christoph Hellwig's avatar
      xfs: implement the lazytime mount option · c3b1b131
      Christoph Hellwig authored
      Use the VFS dirty inode tracking for lazytime inodes only, and just
      log them in ->dirty_inode.
      Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
      Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
      Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      c3b1b131
    • Christoph Hellwig's avatar
      fs: don't clear I_DIRTY_TIME before calling mark_inode_dirty_sync · 0d07e557
      Christoph Hellwig authored
      __mark_inode_dirty already takes care of that, and for the XFS lazytime
      implementation we need to know that ->dirty_inode was called because
      I_DIRTY_TIME was set.
      Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
      Reviewed-by: default avatarJan Kara <jack@suse.cz>
      Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
      0d07e557