diff mbox series

[05/50] xfs: pass perag to xfs_alloc_read_agf()

Message ID 20220611012659.3418072-6-david@fromorbit.com (mailing list archive)
State Superseded
Headers show
Series xfs: per-ag centric allocation alogrithms | expand

Commit Message

Dave Chinner June 11, 2022, 1:26 a.m. UTC
From: Dave Chinner <dchinner@redhat.com>

xfs_alloc_read_agf() initialises the perag if it hasn't been done
yet, so it makes sense to pass it the perag rather than pull a
reference from the buffer. This allows callers to be per-ag centric
rather than passing mount/agno pairs everywhere.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
 fs/xfs/libxfs/xfs_ag.c             | 19 +++++++--------
 fs/xfs/libxfs/xfs_ag_resv.c        |  2 +-
 fs/xfs/libxfs/xfs_alloc.c          | 30 ++++++++++-------------
 fs/xfs/libxfs/xfs_alloc.h          | 13 ++--------
 fs/xfs/libxfs/xfs_bmap.c           |  2 +-
 fs/xfs/libxfs/xfs_ialloc.c         |  2 +-
 fs/xfs/libxfs/xfs_refcount.c       |  6 ++---
 fs/xfs/libxfs/xfs_refcount_btree.c |  2 +-
 fs/xfs/libxfs/xfs_rmap_btree.c     |  2 +-
 fs/xfs/scrub/agheader_repair.c     |  6 ++---
 fs/xfs/scrub/bmap.c                |  2 +-
 fs/xfs/scrub/common.c              |  2 +-
 fs/xfs/scrub/fscounters.c          |  2 +-
 fs/xfs/scrub/repair.c              |  5 ++--
 fs/xfs/xfs_discard.c               |  2 +-
 fs/xfs/xfs_extfree_item.c          |  6 ++++-
 fs/xfs/xfs_filestream.c            |  2 +-
 fs/xfs/xfs_fsmap.c                 |  3 +--
 fs/xfs/xfs_reflink.c               | 38 +++++++++++++++++-------------
 fs/xfs/xfs_reflink.h               |  3 ---
 20 files changed, 68 insertions(+), 81 deletions(-)

Comments

kernel test robot June 11, 2022, 2:37 a.m. UTC | #1
Hi Dave,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on v5.19-rc1]
[also build test WARNING on next-20220610]
[cannot apply to xfs-linux/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/intel-lab-lkp/linux/commits/Dave-Chinner/xfs-per-ag-centric-allocation-alogrithms/20220611-093037
base:    f2906aa863381afb0015a9eb7fefad885d4e5a56
config: arc-allyesconfig (https://download.01.org/0day-ci/archive/20220611/202206111009.JR28QcIm-lkp@intel.com/config)
compiler: arceb-elf-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/87045504fb13d6263ddf1d7780eef5eda1cee6ad
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Dave-Chinner/xfs-per-ag-centric-allocation-alogrithms/20220611-093037
        git checkout 87045504fb13d6263ddf1d7780eef5eda1cee6ad
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=arc SHELL=/bin/bash fs/xfs/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> fs/xfs/xfs_reflink.c:129:1: warning: no previous prototype for 'xfs_reflink_find_shared' [-Wmissing-prototypes]
     129 | xfs_reflink_find_shared(
         | ^~~~~~~~~~~~~~~~~~~~~~~


vim +/xfs_reflink_find_shared +129 fs/xfs/xfs_reflink.c

3993baeb3c52f4 Darrick J. Wong 2016-10-03   32  
3993baeb3c52f4 Darrick J. Wong 2016-10-03   33  /*
3993baeb3c52f4 Darrick J. Wong 2016-10-03   34   * Copy on Write of Shared Blocks
3993baeb3c52f4 Darrick J. Wong 2016-10-03   35   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   36   * XFS must preserve "the usual" file semantics even when two files share
3993baeb3c52f4 Darrick J. Wong 2016-10-03   37   * the same physical blocks.  This means that a write to one file must not
3993baeb3c52f4 Darrick J. Wong 2016-10-03   38   * alter the blocks in a different file; the way that we'll do that is
3993baeb3c52f4 Darrick J. Wong 2016-10-03   39   * through the use of a copy-on-write mechanism.  At a high level, that
3993baeb3c52f4 Darrick J. Wong 2016-10-03   40   * means that when we want to write to a shared block, we allocate a new
3993baeb3c52f4 Darrick J. Wong 2016-10-03   41   * block, write the data to the new block, and if that succeeds we map the
3993baeb3c52f4 Darrick J. Wong 2016-10-03   42   * new block into the file.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   43   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   44   * XFS provides a "delayed allocation" mechanism that defers the allocation
3993baeb3c52f4 Darrick J. Wong 2016-10-03   45   * of disk blocks to dirty-but-not-yet-mapped file blocks as long as
3993baeb3c52f4 Darrick J. Wong 2016-10-03   46   * possible.  This reduces fragmentation by enabling the filesystem to ask
3993baeb3c52f4 Darrick J. Wong 2016-10-03   47   * for bigger chunks less often, which is exactly what we want for CoW.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   48   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   49   * The delalloc mechanism begins when the kernel wants to make a block
3993baeb3c52f4 Darrick J. Wong 2016-10-03   50   * writable (write_begin or page_mkwrite).  If the offset is not mapped, we
3993baeb3c52f4 Darrick J. Wong 2016-10-03   51   * create a delalloc mapping, which is a regular in-core extent, but without
3993baeb3c52f4 Darrick J. Wong 2016-10-03   52   * a real startblock.  (For delalloc mappings, the startblock encodes both
3993baeb3c52f4 Darrick J. Wong 2016-10-03   53   * a flag that this is a delalloc mapping, and a worst-case estimate of how
3993baeb3c52f4 Darrick J. Wong 2016-10-03   54   * many blocks might be required to put the mapping into the BMBT.)  delalloc
3993baeb3c52f4 Darrick J. Wong 2016-10-03   55   * mappings are a reservation against the free space in the filesystem;
3993baeb3c52f4 Darrick J. Wong 2016-10-03   56   * adjacent mappings can also be combined into fewer larger mappings.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   57   *
5eda43000064a6 Darrick J. Wong 2017-02-02   58   * As an optimization, the CoW extent size hint (cowextsz) creates
5eda43000064a6 Darrick J. Wong 2017-02-02   59   * outsized aligned delalloc reservations in the hope of landing out of
5eda43000064a6 Darrick J. Wong 2017-02-02   60   * order nearby CoW writes in a single extent on disk, thereby reducing
5eda43000064a6 Darrick J. Wong 2017-02-02   61   * fragmentation and improving future performance.
5eda43000064a6 Darrick J. Wong 2017-02-02   62   *
5eda43000064a6 Darrick J. Wong 2017-02-02   63   * D: --RRRRRRSSSRRRRRRRR--- (data fork)
5eda43000064a6 Darrick J. Wong 2017-02-02   64   * C: ------DDDDDDD--------- (CoW fork)
5eda43000064a6 Darrick J. Wong 2017-02-02   65   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   66   * When dirty pages are being written out (typically in writepage), the
5eda43000064a6 Darrick J. Wong 2017-02-02   67   * delalloc reservations are converted into unwritten mappings by
5eda43000064a6 Darrick J. Wong 2017-02-02   68   * allocating blocks and replacing the delalloc mapping with real ones.
5eda43000064a6 Darrick J. Wong 2017-02-02   69   * A delalloc mapping can be replaced by several unwritten ones if the
5eda43000064a6 Darrick J. Wong 2017-02-02   70   * free space is fragmented.
5eda43000064a6 Darrick J. Wong 2017-02-02   71   *
5eda43000064a6 Darrick J. Wong 2017-02-02   72   * D: --RRRRRRSSSRRRRRRRR---
5eda43000064a6 Darrick J. Wong 2017-02-02   73   * C: ------UUUUUUU---------
3993baeb3c52f4 Darrick J. Wong 2016-10-03   74   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   75   * We want to adapt the delalloc mechanism for copy-on-write, since the
3993baeb3c52f4 Darrick J. Wong 2016-10-03   76   * write paths are similar.  The first two steps (creating the reservation
3993baeb3c52f4 Darrick J. Wong 2016-10-03   77   * and allocating the blocks) are exactly the same as delalloc except that
3993baeb3c52f4 Darrick J. Wong 2016-10-03   78   * the mappings must be stored in a separate CoW fork because we do not want
3993baeb3c52f4 Darrick J. Wong 2016-10-03   79   * to disturb the mapping in the data fork until we're sure that the write
3993baeb3c52f4 Darrick J. Wong 2016-10-03   80   * succeeded.  IO completion in this case is the process of removing the old
3993baeb3c52f4 Darrick J. Wong 2016-10-03   81   * mapping from the data fork and moving the new mapping from the CoW fork to
3993baeb3c52f4 Darrick J. Wong 2016-10-03   82   * the data fork.  This will be discussed shortly.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   83   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   84   * For now, unaligned directio writes will be bounced back to the page cache.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   85   * Block-aligned directio writes will use the same mechanism as buffered
3993baeb3c52f4 Darrick J. Wong 2016-10-03   86   * writes.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   87   *
5eda43000064a6 Darrick J. Wong 2017-02-02   88   * Just prior to submitting the actual disk write requests, we convert
5eda43000064a6 Darrick J. Wong 2017-02-02   89   * the extents representing the range of the file actually being written
5eda43000064a6 Darrick J. Wong 2017-02-02   90   * (as opposed to extra pieces created for the cowextsize hint) to real
5eda43000064a6 Darrick J. Wong 2017-02-02   91   * extents.  This will become important in the next step:
5eda43000064a6 Darrick J. Wong 2017-02-02   92   *
5eda43000064a6 Darrick J. Wong 2017-02-02   93   * D: --RRRRRRSSSRRRRRRRR---
5eda43000064a6 Darrick J. Wong 2017-02-02   94   * C: ------UUrrUUU---------
5eda43000064a6 Darrick J. Wong 2017-02-02   95   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   96   * CoW remapping must be done after the data block write completes,
3993baeb3c52f4 Darrick J. Wong 2016-10-03   97   * because we don't want to destroy the old data fork map until we're sure
3993baeb3c52f4 Darrick J. Wong 2016-10-03   98   * the new block has been written.  Since the new mappings are kept in a
3993baeb3c52f4 Darrick J. Wong 2016-10-03   99   * separate fork, we can simply iterate these mappings to find the ones
3993baeb3c52f4 Darrick J. Wong 2016-10-03  100   * that cover the file blocks that we just CoW'd.  For each extent, simply
3993baeb3c52f4 Darrick J. Wong 2016-10-03  101   * unmap the corresponding range in the data fork, map the new range into
5eda43000064a6 Darrick J. Wong 2017-02-02  102   * the data fork, and remove the extent from the CoW fork.  Because of
5eda43000064a6 Darrick J. Wong 2017-02-02  103   * the presence of the cowextsize hint, however, we must be careful
5eda43000064a6 Darrick J. Wong 2017-02-02  104   * only to remap the blocks that we've actually written out --  we must
5eda43000064a6 Darrick J. Wong 2017-02-02  105   * never remap delalloc reservations nor CoW staging blocks that have
5eda43000064a6 Darrick J. Wong 2017-02-02  106   * yet to be written.  This corresponds exactly to the real extents in
5eda43000064a6 Darrick J. Wong 2017-02-02  107   * the CoW fork:
5eda43000064a6 Darrick J. Wong 2017-02-02  108   *
5eda43000064a6 Darrick J. Wong 2017-02-02  109   * D: --RRRRRRrrSRRRRRRRR---
5eda43000064a6 Darrick J. Wong 2017-02-02  110   * C: ------UU--UUU---------
3993baeb3c52f4 Darrick J. Wong 2016-10-03  111   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03  112   * Since the remapping operation can be applied to an arbitrary file
3993baeb3c52f4 Darrick J. Wong 2016-10-03  113   * range, we record the need for the remap step as a flag in the ioend
3993baeb3c52f4 Darrick J. Wong 2016-10-03  114   * instead of declaring a new IO type.  This is required for direct io
3993baeb3c52f4 Darrick J. Wong 2016-10-03  115   * because we only have ioend for the whole dio, and we have to be able to
3993baeb3c52f4 Darrick J. Wong 2016-10-03  116   * remember the presence of unwritten blocks and CoW blocks with a single
3993baeb3c52f4 Darrick J. Wong 2016-10-03  117   * ioend structure.  Better yet, the more ground we can cover with one
3993baeb3c52f4 Darrick J. Wong 2016-10-03  118   * ioend, the better.
3993baeb3c52f4 Darrick J. Wong 2016-10-03  119   */
2a06705cd59540 Darrick J. Wong 2016-10-03  120  
2a06705cd59540 Darrick J. Wong 2016-10-03  121  /*
2a06705cd59540 Darrick J. Wong 2016-10-03  122   * Given an AG extent, find the lowest-numbered run of shared blocks
2a06705cd59540 Darrick J. Wong 2016-10-03  123   * within that range and return the range in fbno/flen.  If
2a06705cd59540 Darrick J. Wong 2016-10-03  124   * find_end_of_shared is true, return the longest contiguous extent of
2a06705cd59540 Darrick J. Wong 2016-10-03  125   * shared blocks.  If there are no shared extents, fbno and flen will
2a06705cd59540 Darrick J. Wong 2016-10-03  126   * be set to NULLAGBLOCK and 0, respectively.
2a06705cd59540 Darrick J. Wong 2016-10-03  127   */
2a06705cd59540 Darrick J. Wong 2016-10-03  128  int
2a06705cd59540 Darrick J. Wong 2016-10-03 @129  xfs_reflink_find_shared(
87045504fb13d6 Dave Chinner    2022-06-11  130  	struct xfs_perag	*pag,
92ff7285f1df55 Darrick J. Wong 2017-06-16  131  	struct xfs_trans	*tp,
2a06705cd59540 Darrick J. Wong 2016-10-03  132  	xfs_agblock_t		agbno,
2a06705cd59540 Darrick J. Wong 2016-10-03  133  	xfs_extlen_t		aglen,
2a06705cd59540 Darrick J. Wong 2016-10-03  134  	xfs_agblock_t		*fbno,
2a06705cd59540 Darrick J. Wong 2016-10-03  135  	xfs_extlen_t		*flen,
2a06705cd59540 Darrick J. Wong 2016-10-03  136  	bool			find_end_of_shared)
2a06705cd59540 Darrick J. Wong 2016-10-03  137  {
2a06705cd59540 Darrick J. Wong 2016-10-03  138  	struct xfs_buf		*agbp;
2a06705cd59540 Darrick J. Wong 2016-10-03  139  	struct xfs_btree_cur	*cur;
2a06705cd59540 Darrick J. Wong 2016-10-03  140  	int			error;
2a06705cd59540 Darrick J. Wong 2016-10-03  141  
87045504fb13d6 Dave Chinner    2022-06-11  142  	error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
2a06705cd59540 Darrick J. Wong 2016-10-03  143  	if (error)
2a06705cd59540 Darrick J. Wong 2016-10-03  144  		return error;
2a06705cd59540 Darrick J. Wong 2016-10-03  145  
87045504fb13d6 Dave Chinner    2022-06-11  146  	cur = xfs_refcountbt_init_cursor(pag->pag_mount, tp, agbp, pag);
2a06705cd59540 Darrick J. Wong 2016-10-03  147  
2a06705cd59540 Darrick J. Wong 2016-10-03  148  	error = xfs_refcount_find_shared(cur, agbno, aglen, fbno, flen,
2a06705cd59540 Darrick J. Wong 2016-10-03  149  			find_end_of_shared);
2a06705cd59540 Darrick J. Wong 2016-10-03  150  
0b04b6b875b32f Darrick J. Wong 2018-07-19  151  	xfs_btree_del_cursor(cur, error);
2a06705cd59540 Darrick J. Wong 2016-10-03  152  
92ff7285f1df55 Darrick J. Wong 2017-06-16  153  	xfs_trans_brelse(tp, agbp);
2a06705cd59540 Darrick J. Wong 2016-10-03  154  	return error;
2a06705cd59540 Darrick J. Wong 2016-10-03  155  }
2a06705cd59540 Darrick J. Wong 2016-10-03  156
kernel test robot June 11, 2022, 12:04 p.m. UTC | #2
Hi Dave,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on v5.19-rc1]
[also build test WARNING on next-20220610]
[cannot apply to xfs-linux/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/intel-lab-lkp/linux/commits/Dave-Chinner/xfs-per-ag-centric-allocation-alogrithms/20220611-093037
base:    f2906aa863381afb0015a9eb7fefad885d4e5a56
config: hexagon-randconfig-r012-20220611 (https://download.01.org/0day-ci/archive/20220611/202206111958.cftnGbOr-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project ff4abe755279a3a47cc416ef80dbc900d9a98a19)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/87045504fb13d6263ddf1d7780eef5eda1cee6ad
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Dave-Chinner/xfs-per-ag-centric-allocation-alogrithms/20220611-093037
        git checkout 87045504fb13d6263ddf1d7780eef5eda1cee6ad
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash fs/xfs/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> fs/xfs/xfs_reflink.c:129:1: warning: no previous prototype for function 'xfs_reflink_find_shared' [-Wmissing-prototypes]
   xfs_reflink_find_shared(
   ^
   fs/xfs/xfs_reflink.c:128:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int
   ^
   static 
   fs/xfs/xfs_reflink.c:1029:12: warning: variable 'qdelta' set but not used [-Wunused-but-set-variable]
           int64_t                 qdelta = 0;
                                   ^
   2 warnings generated.


vim +/xfs_reflink_find_shared +129 fs/xfs/xfs_reflink.c

3993baeb3c52f4 Darrick J. Wong 2016-10-03   32  
3993baeb3c52f4 Darrick J. Wong 2016-10-03   33  /*
3993baeb3c52f4 Darrick J. Wong 2016-10-03   34   * Copy on Write of Shared Blocks
3993baeb3c52f4 Darrick J. Wong 2016-10-03   35   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   36   * XFS must preserve "the usual" file semantics even when two files share
3993baeb3c52f4 Darrick J. Wong 2016-10-03   37   * the same physical blocks.  This means that a write to one file must not
3993baeb3c52f4 Darrick J. Wong 2016-10-03   38   * alter the blocks in a different file; the way that we'll do that is
3993baeb3c52f4 Darrick J. Wong 2016-10-03   39   * through the use of a copy-on-write mechanism.  At a high level, that
3993baeb3c52f4 Darrick J. Wong 2016-10-03   40   * means that when we want to write to a shared block, we allocate a new
3993baeb3c52f4 Darrick J. Wong 2016-10-03   41   * block, write the data to the new block, and if that succeeds we map the
3993baeb3c52f4 Darrick J. Wong 2016-10-03   42   * new block into the file.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   43   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   44   * XFS provides a "delayed allocation" mechanism that defers the allocation
3993baeb3c52f4 Darrick J. Wong 2016-10-03   45   * of disk blocks to dirty-but-not-yet-mapped file blocks as long as
3993baeb3c52f4 Darrick J. Wong 2016-10-03   46   * possible.  This reduces fragmentation by enabling the filesystem to ask
3993baeb3c52f4 Darrick J. Wong 2016-10-03   47   * for bigger chunks less often, which is exactly what we want for CoW.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   48   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   49   * The delalloc mechanism begins when the kernel wants to make a block
3993baeb3c52f4 Darrick J. Wong 2016-10-03   50   * writable (write_begin or page_mkwrite).  If the offset is not mapped, we
3993baeb3c52f4 Darrick J. Wong 2016-10-03   51   * create a delalloc mapping, which is a regular in-core extent, but without
3993baeb3c52f4 Darrick J. Wong 2016-10-03   52   * a real startblock.  (For delalloc mappings, the startblock encodes both
3993baeb3c52f4 Darrick J. Wong 2016-10-03   53   * a flag that this is a delalloc mapping, and a worst-case estimate of how
3993baeb3c52f4 Darrick J. Wong 2016-10-03   54   * many blocks might be required to put the mapping into the BMBT.)  delalloc
3993baeb3c52f4 Darrick J. Wong 2016-10-03   55   * mappings are a reservation against the free space in the filesystem;
3993baeb3c52f4 Darrick J. Wong 2016-10-03   56   * adjacent mappings can also be combined into fewer larger mappings.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   57   *
5eda43000064a6 Darrick J. Wong 2017-02-02   58   * As an optimization, the CoW extent size hint (cowextsz) creates
5eda43000064a6 Darrick J. Wong 2017-02-02   59   * outsized aligned delalloc reservations in the hope of landing out of
5eda43000064a6 Darrick J. Wong 2017-02-02   60   * order nearby CoW writes in a single extent on disk, thereby reducing
5eda43000064a6 Darrick J. Wong 2017-02-02   61   * fragmentation and improving future performance.
5eda43000064a6 Darrick J. Wong 2017-02-02   62   *
5eda43000064a6 Darrick J. Wong 2017-02-02   63   * D: --RRRRRRSSSRRRRRRRR--- (data fork)
5eda43000064a6 Darrick J. Wong 2017-02-02   64   * C: ------DDDDDDD--------- (CoW fork)
5eda43000064a6 Darrick J. Wong 2017-02-02   65   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   66   * When dirty pages are being written out (typically in writepage), the
5eda43000064a6 Darrick J. Wong 2017-02-02   67   * delalloc reservations are converted into unwritten mappings by
5eda43000064a6 Darrick J. Wong 2017-02-02   68   * allocating blocks and replacing the delalloc mapping with real ones.
5eda43000064a6 Darrick J. Wong 2017-02-02   69   * A delalloc mapping can be replaced by several unwritten ones if the
5eda43000064a6 Darrick J. Wong 2017-02-02   70   * free space is fragmented.
5eda43000064a6 Darrick J. Wong 2017-02-02   71   *
5eda43000064a6 Darrick J. Wong 2017-02-02   72   * D: --RRRRRRSSSRRRRRRRR---
5eda43000064a6 Darrick J. Wong 2017-02-02   73   * C: ------UUUUUUU---------
3993baeb3c52f4 Darrick J. Wong 2016-10-03   74   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   75   * We want to adapt the delalloc mechanism for copy-on-write, since the
3993baeb3c52f4 Darrick J. Wong 2016-10-03   76   * write paths are similar.  The first two steps (creating the reservation
3993baeb3c52f4 Darrick J. Wong 2016-10-03   77   * and allocating the blocks) are exactly the same as delalloc except that
3993baeb3c52f4 Darrick J. Wong 2016-10-03   78   * the mappings must be stored in a separate CoW fork because we do not want
3993baeb3c52f4 Darrick J. Wong 2016-10-03   79   * to disturb the mapping in the data fork until we're sure that the write
3993baeb3c52f4 Darrick J. Wong 2016-10-03   80   * succeeded.  IO completion in this case is the process of removing the old
3993baeb3c52f4 Darrick J. Wong 2016-10-03   81   * mapping from the data fork and moving the new mapping from the CoW fork to
3993baeb3c52f4 Darrick J. Wong 2016-10-03   82   * the data fork.  This will be discussed shortly.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   83   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   84   * For now, unaligned directio writes will be bounced back to the page cache.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   85   * Block-aligned directio writes will use the same mechanism as buffered
3993baeb3c52f4 Darrick J. Wong 2016-10-03   86   * writes.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   87   *
5eda43000064a6 Darrick J. Wong 2017-02-02   88   * Just prior to submitting the actual disk write requests, we convert
5eda43000064a6 Darrick J. Wong 2017-02-02   89   * the extents representing the range of the file actually being written
5eda43000064a6 Darrick J. Wong 2017-02-02   90   * (as opposed to extra pieces created for the cowextsize hint) to real
5eda43000064a6 Darrick J. Wong 2017-02-02   91   * extents.  This will become important in the next step:
5eda43000064a6 Darrick J. Wong 2017-02-02   92   *
5eda43000064a6 Darrick J. Wong 2017-02-02   93   * D: --RRRRRRSSSRRRRRRRR---
5eda43000064a6 Darrick J. Wong 2017-02-02   94   * C: ------UUrrUUU---------
5eda43000064a6 Darrick J. Wong 2017-02-02   95   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   96   * CoW remapping must be done after the data block write completes,
3993baeb3c52f4 Darrick J. Wong 2016-10-03   97   * because we don't want to destroy the old data fork map until we're sure
3993baeb3c52f4 Darrick J. Wong 2016-10-03   98   * the new block has been written.  Since the new mappings are kept in a
3993baeb3c52f4 Darrick J. Wong 2016-10-03   99   * separate fork, we can simply iterate these mappings to find the ones
3993baeb3c52f4 Darrick J. Wong 2016-10-03  100   * that cover the file blocks that we just CoW'd.  For each extent, simply
3993baeb3c52f4 Darrick J. Wong 2016-10-03  101   * unmap the corresponding range in the data fork, map the new range into
5eda43000064a6 Darrick J. Wong 2017-02-02  102   * the data fork, and remove the extent from the CoW fork.  Because of
5eda43000064a6 Darrick J. Wong 2017-02-02  103   * the presence of the cowextsize hint, however, we must be careful
5eda43000064a6 Darrick J. Wong 2017-02-02  104   * only to remap the blocks that we've actually written out --  we must
5eda43000064a6 Darrick J. Wong 2017-02-02  105   * never remap delalloc reservations nor CoW staging blocks that have
5eda43000064a6 Darrick J. Wong 2017-02-02  106   * yet to be written.  This corresponds exactly to the real extents in
5eda43000064a6 Darrick J. Wong 2017-02-02  107   * the CoW fork:
5eda43000064a6 Darrick J. Wong 2017-02-02  108   *
5eda43000064a6 Darrick J. Wong 2017-02-02  109   * D: --RRRRRRrrSRRRRRRRR---
5eda43000064a6 Darrick J. Wong 2017-02-02  110   * C: ------UU--UUU---------
3993baeb3c52f4 Darrick J. Wong 2016-10-03  111   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03  112   * Since the remapping operation can be applied to an arbitrary file
3993baeb3c52f4 Darrick J. Wong 2016-10-03  113   * range, we record the need for the remap step as a flag in the ioend
3993baeb3c52f4 Darrick J. Wong 2016-10-03  114   * instead of declaring a new IO type.  This is required for direct io
3993baeb3c52f4 Darrick J. Wong 2016-10-03  115   * because we only have ioend for the whole dio, and we have to be able to
3993baeb3c52f4 Darrick J. Wong 2016-10-03  116   * remember the presence of unwritten blocks and CoW blocks with a single
3993baeb3c52f4 Darrick J. Wong 2016-10-03  117   * ioend structure.  Better yet, the more ground we can cover with one
3993baeb3c52f4 Darrick J. Wong 2016-10-03  118   * ioend, the better.
3993baeb3c52f4 Darrick J. Wong 2016-10-03  119   */
2a06705cd59540 Darrick J. Wong 2016-10-03  120  
2a06705cd59540 Darrick J. Wong 2016-10-03  121  /*
2a06705cd59540 Darrick J. Wong 2016-10-03  122   * Given an AG extent, find the lowest-numbered run of shared blocks
2a06705cd59540 Darrick J. Wong 2016-10-03  123   * within that range and return the range in fbno/flen.  If
2a06705cd59540 Darrick J. Wong 2016-10-03  124   * find_end_of_shared is true, return the longest contiguous extent of
2a06705cd59540 Darrick J. Wong 2016-10-03  125   * shared blocks.  If there are no shared extents, fbno and flen will
2a06705cd59540 Darrick J. Wong 2016-10-03  126   * be set to NULLAGBLOCK and 0, respectively.
2a06705cd59540 Darrick J. Wong 2016-10-03  127   */
2a06705cd59540 Darrick J. Wong 2016-10-03  128  int
2a06705cd59540 Darrick J. Wong 2016-10-03 @129  xfs_reflink_find_shared(
87045504fb13d6 Dave Chinner    2022-06-11  130  	struct xfs_perag	*pag,
92ff7285f1df55 Darrick J. Wong 2017-06-16  131  	struct xfs_trans	*tp,
2a06705cd59540 Darrick J. Wong 2016-10-03  132  	xfs_agblock_t		agbno,
2a06705cd59540 Darrick J. Wong 2016-10-03  133  	xfs_extlen_t		aglen,
2a06705cd59540 Darrick J. Wong 2016-10-03  134  	xfs_agblock_t		*fbno,
2a06705cd59540 Darrick J. Wong 2016-10-03  135  	xfs_extlen_t		*flen,
2a06705cd59540 Darrick J. Wong 2016-10-03  136  	bool			find_end_of_shared)
2a06705cd59540 Darrick J. Wong 2016-10-03  137  {
2a06705cd59540 Darrick J. Wong 2016-10-03  138  	struct xfs_buf		*agbp;
2a06705cd59540 Darrick J. Wong 2016-10-03  139  	struct xfs_btree_cur	*cur;
2a06705cd59540 Darrick J. Wong 2016-10-03  140  	int			error;
2a06705cd59540 Darrick J. Wong 2016-10-03  141  
87045504fb13d6 Dave Chinner    2022-06-11  142  	error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
2a06705cd59540 Darrick J. Wong 2016-10-03  143  	if (error)
2a06705cd59540 Darrick J. Wong 2016-10-03  144  		return error;
2a06705cd59540 Darrick J. Wong 2016-10-03  145  
87045504fb13d6 Dave Chinner    2022-06-11  146  	cur = xfs_refcountbt_init_cursor(pag->pag_mount, tp, agbp, pag);
2a06705cd59540 Darrick J. Wong 2016-10-03  147  
2a06705cd59540 Darrick J. Wong 2016-10-03  148  	error = xfs_refcount_find_shared(cur, agbno, aglen, fbno, flen,
2a06705cd59540 Darrick J. Wong 2016-10-03  149  			find_end_of_shared);
2a06705cd59540 Darrick J. Wong 2016-10-03  150  
0b04b6b875b32f Darrick J. Wong 2018-07-19  151  	xfs_btree_del_cursor(cur, error);
2a06705cd59540 Darrick J. Wong 2016-10-03  152  
92ff7285f1df55 Darrick J. Wong 2017-06-16  153  	xfs_trans_brelse(tp, agbp);
2a06705cd59540 Darrick J. Wong 2016-10-03  154  	return error;
2a06705cd59540 Darrick J. Wong 2016-10-03  155  }
2a06705cd59540 Darrick J. Wong 2016-10-03  156
kernel test robot June 11, 2022, 1:46 p.m. UTC | #3
Hi Dave,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on v5.19-rc1]
[also build test WARNING on next-20220610]
[cannot apply to xfs-linux/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/intel-lab-lkp/linux/commits/Dave-Chinner/xfs-per-ag-centric-allocation-alogrithms/20220611-093037
base:    f2906aa863381afb0015a9eb7fefad885d4e5a56
config: sparc64-randconfig-r034-20220611 (https://download.01.org/0day-ci/archive/20220611/202206112144.aFBVTYv8-lkp@intel.com/config)
compiler: sparc64-linux-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/87045504fb13d6263ddf1d7780eef5eda1cee6ad
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Dave-Chinner/xfs-per-ag-centric-allocation-alogrithms/20220611-093037
        git checkout 87045504fb13d6263ddf1d7780eef5eda1cee6ad
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=sparc64 SHELL=/bin/bash fs/xfs/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   fs/xfs/scrub/repair.c: In function 'xrep_reap_block':
>> fs/xfs/scrub/repair.c:539:41: warning: variable 'agno' set but not used [-Wunused-but-set-variable]
     539 |         xfs_agnumber_t                  agno;
         |                                         ^~~~


vim +/agno +539 fs/xfs/scrub/repair.c

12c6510e2ff17cf Darrick J. Wong 2018-05-29  528  
86d969b425d7ecf Darrick J. Wong 2018-07-30  529  /* Dispose of a single block. */
12c6510e2ff17cf Darrick J. Wong 2018-05-29  530  STATIC int
86d969b425d7ecf Darrick J. Wong 2018-07-30  531  xrep_reap_block(
1d8a748a8aa94a7 Darrick J. Wong 2018-07-19  532  	struct xfs_scrub		*sc,
12c6510e2ff17cf Darrick J. Wong 2018-05-29  533  	xfs_fsblock_t			fsbno,
66e3237e724c665 Darrick J. Wong 2018-12-12  534  	const struct xfs_owner_info	*oinfo,
12c6510e2ff17cf Darrick J. Wong 2018-05-29  535  	enum xfs_ag_resv_type		resv)
12c6510e2ff17cf Darrick J. Wong 2018-05-29  536  {
12c6510e2ff17cf Darrick J. Wong 2018-05-29  537  	struct xfs_btree_cur		*cur;
12c6510e2ff17cf Darrick J. Wong 2018-05-29  538  	struct xfs_buf			*agf_bp = NULL;
12c6510e2ff17cf Darrick J. Wong 2018-05-29 @539  	xfs_agnumber_t			agno;
12c6510e2ff17cf Darrick J. Wong 2018-05-29  540  	xfs_agblock_t			agbno;
12c6510e2ff17cf Darrick J. Wong 2018-05-29  541  	bool				has_other_rmap;
12c6510e2ff17cf Darrick J. Wong 2018-05-29  542  	int				error;
12c6510e2ff17cf Darrick J. Wong 2018-05-29  543  
12c6510e2ff17cf Darrick J. Wong 2018-05-29  544  	agno = XFS_FSB_TO_AGNO(sc->mp, fsbno);
12c6510e2ff17cf Darrick J. Wong 2018-05-29  545  	agbno = XFS_FSB_TO_AGBNO(sc->mp, fsbno);
87045504fb13d62 Dave Chinner    2022-06-11  546  	ASSERT(agno == sc->sa.pag->pag_agno);
12c6510e2ff17cf Darrick J. Wong 2018-05-29  547  
12c6510e2ff17cf Darrick J. Wong 2018-05-29  548  	/*
12c6510e2ff17cf Darrick J. Wong 2018-05-29  549  	 * If we are repairing per-inode metadata, we need to read in the AGF
12c6510e2ff17cf Darrick J. Wong 2018-05-29  550  	 * buffer.  Otherwise, we're repairing a per-AG structure, so reuse
12c6510e2ff17cf Darrick J. Wong 2018-05-29  551  	 * the AGF buffer that the setup functions already grabbed.
12c6510e2ff17cf Darrick J. Wong 2018-05-29  552  	 */
12c6510e2ff17cf Darrick J. Wong 2018-05-29  553  	if (sc->ip) {
87045504fb13d62 Dave Chinner    2022-06-11  554  		error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
12c6510e2ff17cf Darrick J. Wong 2018-05-29  555  		if (error)
12c6510e2ff17cf Darrick J. Wong 2018-05-29  556  			return error;
12c6510e2ff17cf Darrick J. Wong 2018-05-29  557  	} else {
12c6510e2ff17cf Darrick J. Wong 2018-05-29  558  		agf_bp = sc->sa.agf_bp;
12c6510e2ff17cf Darrick J. Wong 2018-05-29  559  	}
fa9c3c197329fda Dave Chinner    2021-06-02  560  	cur = xfs_rmapbt_init_cursor(sc->mp, sc->tp, agf_bp, sc->sa.pag);
12c6510e2ff17cf Darrick J. Wong 2018-05-29  561  
12c6510e2ff17cf Darrick J. Wong 2018-05-29  562  	/* Can we find any other rmappings? */
12c6510e2ff17cf Darrick J. Wong 2018-05-29  563  	error = xfs_rmap_has_other_keys(cur, agbno, 1, oinfo, &has_other_rmap);
ef97ef26d263fb6 Darrick J. Wong 2018-07-19  564  	xfs_btree_del_cursor(cur, error);
12c6510e2ff17cf Darrick J. Wong 2018-05-29  565  	if (error)
ef97ef26d263fb6 Darrick J. Wong 2018-07-19  566  		goto out_free;
12c6510e2ff17cf Darrick J. Wong 2018-05-29  567  
12c6510e2ff17cf Darrick J. Wong 2018-05-29  568  	/*
12c6510e2ff17cf Darrick J. Wong 2018-05-29  569  	 * If there are other rmappings, this block is cross linked and must
12c6510e2ff17cf Darrick J. Wong 2018-05-29  570  	 * not be freed.  Remove the reverse mapping and move on.  Otherwise,
12c6510e2ff17cf Darrick J. Wong 2018-05-29  571  	 * we were the only owner of the block, so free the extent, which will
12c6510e2ff17cf Darrick J. Wong 2018-05-29  572  	 * also remove the rmap.
12c6510e2ff17cf Darrick J. Wong 2018-05-29  573  	 *
12c6510e2ff17cf Darrick J. Wong 2018-05-29  574  	 * XXX: XFS doesn't support detecting the case where a single block
12c6510e2ff17cf Darrick J. Wong 2018-05-29  575  	 * metadata structure is crosslinked with a multi-block structure
12c6510e2ff17cf Darrick J. Wong 2018-05-29  576  	 * because the buffer cache doesn't detect aliasing problems, so we
12c6510e2ff17cf Darrick J. Wong 2018-05-29  577  	 * can't fix 100% of crosslinking problems (yet).  The verifiers will
12c6510e2ff17cf Darrick J. Wong 2018-05-29  578  	 * blow on writeout, the filesystem will shut down, and the admin gets
12c6510e2ff17cf Darrick J. Wong 2018-05-29  579  	 * to run xfs_repair.
12c6510e2ff17cf Darrick J. Wong 2018-05-29  580  	 */
12c6510e2ff17cf Darrick J. Wong 2018-05-29  581  	if (has_other_rmap)
fa9c3c197329fda Dave Chinner    2021-06-02  582  		error = xfs_rmap_free(sc->tp, agf_bp, sc->sa.pag, agbno,
fa9c3c197329fda Dave Chinner    2021-06-02  583  					1, oinfo);
12c6510e2ff17cf Darrick J. Wong 2018-05-29  584  	else if (resv == XFS_AG_RESV_AGFL)
b5e2196e9c72173 Darrick J. Wong 2018-07-19  585  		error = xrep_put_freelist(sc, agbno);
12c6510e2ff17cf Darrick J. Wong 2018-05-29  586  	else
12c6510e2ff17cf Darrick J. Wong 2018-05-29  587  		error = xfs_free_extent(sc->tp, fsbno, 1, oinfo, resv);
12c6510e2ff17cf Darrick J. Wong 2018-05-29  588  	if (agf_bp != sc->sa.agf_bp)
12c6510e2ff17cf Darrick J. Wong 2018-05-29  589  		xfs_trans_brelse(sc->tp, agf_bp);
12c6510e2ff17cf Darrick J. Wong 2018-05-29  590  	if (error)
12c6510e2ff17cf Darrick J. Wong 2018-05-29  591  		return error;
12c6510e2ff17cf Darrick J. Wong 2018-05-29  592  
12c6510e2ff17cf Darrick J. Wong 2018-05-29  593  	if (sc->ip)
12c6510e2ff17cf Darrick J. Wong 2018-05-29  594  		return xfs_trans_roll_inode(&sc->tp, sc->ip);
b5e2196e9c72173 Darrick J. Wong 2018-07-19  595  	return xrep_roll_ag_trans(sc);
12c6510e2ff17cf Darrick J. Wong 2018-05-29  596  
ef97ef26d263fb6 Darrick J. Wong 2018-07-19  597  out_free:
12c6510e2ff17cf Darrick J. Wong 2018-05-29  598  	if (agf_bp != sc->sa.agf_bp)
12c6510e2ff17cf Darrick J. Wong 2018-05-29  599  		xfs_trans_brelse(sc->tp, agf_bp);
12c6510e2ff17cf Darrick J. Wong 2018-05-29  600  	return error;
12c6510e2ff17cf Darrick J. Wong 2018-05-29  601  }
12c6510e2ff17cf Darrick J. Wong 2018-05-29  602
kernel test robot June 14, 2022, 12:17 p.m. UTC | #4
Hi Dave,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on v5.19-rc1]
[also build test WARNING on next-20220614]
[cannot apply to xfs-linux/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/intel-lab-lkp/linux/commits/Dave-Chinner/xfs-per-ag-centric-allocation-alogrithms/20220611-093037
base:    f2906aa863381afb0015a9eb7fefad885d4e5a56
config: arc-randconfig-s032-20220613 (https://download.01.org/0day-ci/archive/20220614/202206142004.Tnmd1NbS-lkp@intel.com/config)
compiler: arc-elf-gcc (GCC) 11.3.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-30-g92122700-dirty
        # https://github.com/intel-lab-lkp/linux/commit/87045504fb13d6263ddf1d7780eef5eda1cee6ad
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Dave-Chinner/xfs-per-ag-centric-allocation-alogrithms/20220611-093037
        git checkout 87045504fb13d6263ddf1d7780eef5eda1cee6ad
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=arc SHELL=/bin/bash fs/xfs/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
>> fs/xfs/xfs_reflink.c:129:1: sparse: sparse: symbol 'xfs_reflink_find_shared' was not declared. Should it be static?

vim +/xfs_reflink_find_shared +129 fs/xfs/xfs_reflink.c

3993baeb3c52f4 Darrick J. Wong 2016-10-03   32  
3993baeb3c52f4 Darrick J. Wong 2016-10-03   33  /*
3993baeb3c52f4 Darrick J. Wong 2016-10-03   34   * Copy on Write of Shared Blocks
3993baeb3c52f4 Darrick J. Wong 2016-10-03   35   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   36   * XFS must preserve "the usual" file semantics even when two files share
3993baeb3c52f4 Darrick J. Wong 2016-10-03   37   * the same physical blocks.  This means that a write to one file must not
3993baeb3c52f4 Darrick J. Wong 2016-10-03   38   * alter the blocks in a different file; the way that we'll do that is
3993baeb3c52f4 Darrick J. Wong 2016-10-03   39   * through the use of a copy-on-write mechanism.  At a high level, that
3993baeb3c52f4 Darrick J. Wong 2016-10-03   40   * means that when we want to write to a shared block, we allocate a new
3993baeb3c52f4 Darrick J. Wong 2016-10-03   41   * block, write the data to the new block, and if that succeeds we map the
3993baeb3c52f4 Darrick J. Wong 2016-10-03   42   * new block into the file.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   43   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   44   * XFS provides a "delayed allocation" mechanism that defers the allocation
3993baeb3c52f4 Darrick J. Wong 2016-10-03   45   * of disk blocks to dirty-but-not-yet-mapped file blocks as long as
3993baeb3c52f4 Darrick J. Wong 2016-10-03   46   * possible.  This reduces fragmentation by enabling the filesystem to ask
3993baeb3c52f4 Darrick J. Wong 2016-10-03   47   * for bigger chunks less often, which is exactly what we want for CoW.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   48   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   49   * The delalloc mechanism begins when the kernel wants to make a block
3993baeb3c52f4 Darrick J. Wong 2016-10-03   50   * writable (write_begin or page_mkwrite).  If the offset is not mapped, we
3993baeb3c52f4 Darrick J. Wong 2016-10-03   51   * create a delalloc mapping, which is a regular in-core extent, but without
3993baeb3c52f4 Darrick J. Wong 2016-10-03   52   * a real startblock.  (For delalloc mappings, the startblock encodes both
3993baeb3c52f4 Darrick J. Wong 2016-10-03   53   * a flag that this is a delalloc mapping, and a worst-case estimate of how
3993baeb3c52f4 Darrick J. Wong 2016-10-03   54   * many blocks might be required to put the mapping into the BMBT.)  delalloc
3993baeb3c52f4 Darrick J. Wong 2016-10-03   55   * mappings are a reservation against the free space in the filesystem;
3993baeb3c52f4 Darrick J. Wong 2016-10-03   56   * adjacent mappings can also be combined into fewer larger mappings.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   57   *
5eda43000064a6 Darrick J. Wong 2017-02-02   58   * As an optimization, the CoW extent size hint (cowextsz) creates
5eda43000064a6 Darrick J. Wong 2017-02-02   59   * outsized aligned delalloc reservations in the hope of landing out of
5eda43000064a6 Darrick J. Wong 2017-02-02   60   * order nearby CoW writes in a single extent on disk, thereby reducing
5eda43000064a6 Darrick J. Wong 2017-02-02   61   * fragmentation and improving future performance.
5eda43000064a6 Darrick J. Wong 2017-02-02   62   *
5eda43000064a6 Darrick J. Wong 2017-02-02   63   * D: --RRRRRRSSSRRRRRRRR--- (data fork)
5eda43000064a6 Darrick J. Wong 2017-02-02   64   * C: ------DDDDDDD--------- (CoW fork)
5eda43000064a6 Darrick J. Wong 2017-02-02   65   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   66   * When dirty pages are being written out (typically in writepage), the
5eda43000064a6 Darrick J. Wong 2017-02-02   67   * delalloc reservations are converted into unwritten mappings by
5eda43000064a6 Darrick J. Wong 2017-02-02   68   * allocating blocks and replacing the delalloc mapping with real ones.
5eda43000064a6 Darrick J. Wong 2017-02-02   69   * A delalloc mapping can be replaced by several unwritten ones if the
5eda43000064a6 Darrick J. Wong 2017-02-02   70   * free space is fragmented.
5eda43000064a6 Darrick J. Wong 2017-02-02   71   *
5eda43000064a6 Darrick J. Wong 2017-02-02   72   * D: --RRRRRRSSSRRRRRRRR---
5eda43000064a6 Darrick J. Wong 2017-02-02   73   * C: ------UUUUUUU---------
3993baeb3c52f4 Darrick J. Wong 2016-10-03   74   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   75   * We want to adapt the delalloc mechanism for copy-on-write, since the
3993baeb3c52f4 Darrick J. Wong 2016-10-03   76   * write paths are similar.  The first two steps (creating the reservation
3993baeb3c52f4 Darrick J. Wong 2016-10-03   77   * and allocating the blocks) are exactly the same as delalloc except that
3993baeb3c52f4 Darrick J. Wong 2016-10-03   78   * the mappings must be stored in a separate CoW fork because we do not want
3993baeb3c52f4 Darrick J. Wong 2016-10-03   79   * to disturb the mapping in the data fork until we're sure that the write
3993baeb3c52f4 Darrick J. Wong 2016-10-03   80   * succeeded.  IO completion in this case is the process of removing the old
3993baeb3c52f4 Darrick J. Wong 2016-10-03   81   * mapping from the data fork and moving the new mapping from the CoW fork to
3993baeb3c52f4 Darrick J. Wong 2016-10-03   82   * the data fork.  This will be discussed shortly.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   83   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   84   * For now, unaligned directio writes will be bounced back to the page cache.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   85   * Block-aligned directio writes will use the same mechanism as buffered
3993baeb3c52f4 Darrick J. Wong 2016-10-03   86   * writes.
3993baeb3c52f4 Darrick J. Wong 2016-10-03   87   *
5eda43000064a6 Darrick J. Wong 2017-02-02   88   * Just prior to submitting the actual disk write requests, we convert
5eda43000064a6 Darrick J. Wong 2017-02-02   89   * the extents representing the range of the file actually being written
5eda43000064a6 Darrick J. Wong 2017-02-02   90   * (as opposed to extra pieces created for the cowextsize hint) to real
5eda43000064a6 Darrick J. Wong 2017-02-02   91   * extents.  This will become important in the next step:
5eda43000064a6 Darrick J. Wong 2017-02-02   92   *
5eda43000064a6 Darrick J. Wong 2017-02-02   93   * D: --RRRRRRSSSRRRRRRRR---
5eda43000064a6 Darrick J. Wong 2017-02-02   94   * C: ------UUrrUUU---------
5eda43000064a6 Darrick J. Wong 2017-02-02   95   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03   96   * CoW remapping must be done after the data block write completes,
3993baeb3c52f4 Darrick J. Wong 2016-10-03   97   * because we don't want to destroy the old data fork map until we're sure
3993baeb3c52f4 Darrick J. Wong 2016-10-03   98   * the new block has been written.  Since the new mappings are kept in a
3993baeb3c52f4 Darrick J. Wong 2016-10-03   99   * separate fork, we can simply iterate these mappings to find the ones
3993baeb3c52f4 Darrick J. Wong 2016-10-03  100   * that cover the file blocks that we just CoW'd.  For each extent, simply
3993baeb3c52f4 Darrick J. Wong 2016-10-03  101   * unmap the corresponding range in the data fork, map the new range into
5eda43000064a6 Darrick J. Wong 2017-02-02  102   * the data fork, and remove the extent from the CoW fork.  Because of
5eda43000064a6 Darrick J. Wong 2017-02-02  103   * the presence of the cowextsize hint, however, we must be careful
5eda43000064a6 Darrick J. Wong 2017-02-02  104   * only to remap the blocks that we've actually written out --  we must
5eda43000064a6 Darrick J. Wong 2017-02-02  105   * never remap delalloc reservations nor CoW staging blocks that have
5eda43000064a6 Darrick J. Wong 2017-02-02  106   * yet to be written.  This corresponds exactly to the real extents in
5eda43000064a6 Darrick J. Wong 2017-02-02  107   * the CoW fork:
5eda43000064a6 Darrick J. Wong 2017-02-02  108   *
5eda43000064a6 Darrick J. Wong 2017-02-02  109   * D: --RRRRRRrrSRRRRRRRR---
5eda43000064a6 Darrick J. Wong 2017-02-02  110   * C: ------UU--UUU---------
3993baeb3c52f4 Darrick J. Wong 2016-10-03  111   *
3993baeb3c52f4 Darrick J. Wong 2016-10-03  112   * Since the remapping operation can be applied to an arbitrary file
3993baeb3c52f4 Darrick J. Wong 2016-10-03  113   * range, we record the need for the remap step as a flag in the ioend
3993baeb3c52f4 Darrick J. Wong 2016-10-03  114   * instead of declaring a new IO type.  This is required for direct io
3993baeb3c52f4 Darrick J. Wong 2016-10-03  115   * because we only have ioend for the whole dio, and we have to be able to
3993baeb3c52f4 Darrick J. Wong 2016-10-03  116   * remember the presence of unwritten blocks and CoW blocks with a single
3993baeb3c52f4 Darrick J. Wong 2016-10-03  117   * ioend structure.  Better yet, the more ground we can cover with one
3993baeb3c52f4 Darrick J. Wong 2016-10-03  118   * ioend, the better.
3993baeb3c52f4 Darrick J. Wong 2016-10-03  119   */
2a06705cd59540 Darrick J. Wong 2016-10-03  120  
2a06705cd59540 Darrick J. Wong 2016-10-03  121  /*
2a06705cd59540 Darrick J. Wong 2016-10-03  122   * Given an AG extent, find the lowest-numbered run of shared blocks
2a06705cd59540 Darrick J. Wong 2016-10-03  123   * within that range and return the range in fbno/flen.  If
2a06705cd59540 Darrick J. Wong 2016-10-03  124   * find_end_of_shared is true, return the longest contiguous extent of
2a06705cd59540 Darrick J. Wong 2016-10-03  125   * shared blocks.  If there are no shared extents, fbno and flen will
2a06705cd59540 Darrick J. Wong 2016-10-03  126   * be set to NULLAGBLOCK and 0, respectively.
2a06705cd59540 Darrick J. Wong 2016-10-03  127   */
2a06705cd59540 Darrick J. Wong 2016-10-03  128  int
2a06705cd59540 Darrick J. Wong 2016-10-03 @129  xfs_reflink_find_shared(
87045504fb13d6 Dave Chinner    2022-06-11  130  	struct xfs_perag	*pag,
92ff7285f1df55 Darrick J. Wong 2017-06-16  131  	struct xfs_trans	*tp,
2a06705cd59540 Darrick J. Wong 2016-10-03  132  	xfs_agblock_t		agbno,
2a06705cd59540 Darrick J. Wong 2016-10-03  133  	xfs_extlen_t		aglen,
2a06705cd59540 Darrick J. Wong 2016-10-03  134  	xfs_agblock_t		*fbno,
2a06705cd59540 Darrick J. Wong 2016-10-03  135  	xfs_extlen_t		*flen,
2a06705cd59540 Darrick J. Wong 2016-10-03  136  	bool			find_end_of_shared)
2a06705cd59540 Darrick J. Wong 2016-10-03  137  {
2a06705cd59540 Darrick J. Wong 2016-10-03  138  	struct xfs_buf		*agbp;
2a06705cd59540 Darrick J. Wong 2016-10-03  139  	struct xfs_btree_cur	*cur;
2a06705cd59540 Darrick J. Wong 2016-10-03  140  	int			error;
2a06705cd59540 Darrick J. Wong 2016-10-03  141  
87045504fb13d6 Dave Chinner    2022-06-11  142  	error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
2a06705cd59540 Darrick J. Wong 2016-10-03  143  	if (error)
2a06705cd59540 Darrick J. Wong 2016-10-03  144  		return error;
2a06705cd59540 Darrick J. Wong 2016-10-03  145  
87045504fb13d6 Dave Chinner    2022-06-11  146  	cur = xfs_refcountbt_init_cursor(pag->pag_mount, tp, agbp, pag);
2a06705cd59540 Darrick J. Wong 2016-10-03  147  
2a06705cd59540 Darrick J. Wong 2016-10-03  148  	error = xfs_refcount_find_shared(cur, agbno, aglen, fbno, flen,
2a06705cd59540 Darrick J. Wong 2016-10-03  149  			find_end_of_shared);
2a06705cd59540 Darrick J. Wong 2016-10-03  150  
0b04b6b875b32f Darrick J. Wong 2018-07-19  151  	xfs_btree_del_cursor(cur, error);
2a06705cd59540 Darrick J. Wong 2016-10-03  152  
92ff7285f1df55 Darrick J. Wong 2017-06-16  153  	xfs_trans_brelse(tp, agbp);
2a06705cd59540 Darrick J. Wong 2016-10-03  154  	return error;
2a06705cd59540 Darrick J. Wong 2016-10-03  155  }
2a06705cd59540 Darrick J. Wong 2016-10-03  156
Christoph Hellwig June 16, 2022, 7:38 a.m. UTC | #5
On Sat, Jun 11, 2022 at 11:26:14AM +1000, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> xfs_alloc_read_agf() initialises the perag if it hasn't been done
> yet, so it makes sense to pass it the perag rather than pull a
> reference from the buffer. This allows callers to be per-ag centric
> rather than passing mount/agno pairs everywhere.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---
>  fs/xfs/libxfs/xfs_ag.c             | 19 +++++++--------
>  fs/xfs/libxfs/xfs_ag_resv.c        |  2 +-
>  fs/xfs/libxfs/xfs_alloc.c          | 30 ++++++++++-------------
>  fs/xfs/libxfs/xfs_alloc.h          | 13 ++--------
>  fs/xfs/libxfs/xfs_bmap.c           |  2 +-
>  fs/xfs/libxfs/xfs_ialloc.c         |  2 +-
>  fs/xfs/libxfs/xfs_refcount.c       |  6 ++---
>  fs/xfs/libxfs/xfs_refcount_btree.c |  2 +-
>  fs/xfs/libxfs/xfs_rmap_btree.c     |  2 +-
>  fs/xfs/scrub/agheader_repair.c     |  6 ++---
>  fs/xfs/scrub/bmap.c                |  2 +-
>  fs/xfs/scrub/common.c              |  2 +-
>  fs/xfs/scrub/fscounters.c          |  2 +-
>  fs/xfs/scrub/repair.c              |  5 ++--
>  fs/xfs/xfs_discard.c               |  2 +-
>  fs/xfs/xfs_extfree_item.c          |  6 ++++-
>  fs/xfs/xfs_filestream.c            |  2 +-
>  fs/xfs/xfs_fsmap.c                 |  3 +--
>  fs/xfs/xfs_reflink.c               | 38 +++++++++++++++++-------------
>  fs/xfs/xfs_reflink.h               |  3 ---
>  20 files changed, 68 insertions(+), 81 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_ag.c b/fs/xfs/libxfs/xfs_ag.c
> index 734ef170936e..c1a1c9f414c3 100644
> --- a/fs/xfs/libxfs/xfs_ag.c
> +++ b/fs/xfs/libxfs/xfs_ag.c
> @@ -120,16 +120,13 @@ xfs_initialize_perag_data(
>  
>  	for (index = 0; index < agcount; index++) {
>  		/*
> -		 * read the agf, then the agi. This gets us
> -		 * all the information we need and populates the
> -		 * per-ag structures for us.
> +		 * Read the AGF and AGI buffers to populate the per-ag
> +		 * structures for us.
>  		 */
> -		error = xfs_alloc_read_agf(mp, NULL, index, 0, NULL);
> -		if (error)
> -			return error;
> -
>  		pag = xfs_perag_get(mp, index);
> -		error = xfs_ialloc_read_agi(pag, NULL, NULL);
> +		error = xfs_alloc_read_agf(pag, NULL, 0, NULL);
> +		if (!error)
> +			error = xfs_ialloc_read_agi(pag, NULL, NULL);
>  		if (error) {
>  			xfs_perag_put(pag);
>  			return error;
> @@ -792,7 +789,7 @@ xfs_ag_shrink_space(
>  
>  	agi = agibp->b_addr;
>  
> -	error = xfs_alloc_read_agf(mp, *tpp, pag->pag_agno, 0, &agfbp);
> +	error = xfs_alloc_read_agf(pag, *tpp, 0, &agfbp);
>  	if (error)
>  		return error;
>  
> @@ -909,7 +906,7 @@ xfs_ag_extend_space(
>  	/*
>  	 * Change agf length.
>  	 */
> -	error = xfs_alloc_read_agf(pag->pag_mount, tp, pag->pag_agno, 0, &bp);
> +	error = xfs_alloc_read_agf(pag, tp, 0, &bp);
>  	if (error)
>  		return error;
>  
> @@ -952,7 +949,7 @@ xfs_ag_get_geometry(
>  	error = xfs_ialloc_read_agi(pag, NULL, &agi_bp);
>  	if (error)
>  		return error;
> -	error = xfs_alloc_read_agf(pag->pag_mount, NULL, pag->pag_agno, 0, &agf_bp);
> +	error = xfs_alloc_read_agf(pag, NULL, 0, &agf_bp);
>  	if (error)
>  		goto out_agi;
>  
> diff --git a/fs/xfs/libxfs/xfs_ag_resv.c b/fs/xfs/libxfs/xfs_ag_resv.c
> index ce28bf8f72dc..5af123d13a63 100644
> --- a/fs/xfs/libxfs/xfs_ag_resv.c
> +++ b/fs/xfs/libxfs/xfs_ag_resv.c
> @@ -322,7 +322,7 @@ xfs_ag_resv_init(
>  	 * address.
>  	 */
>  	if (has_resv) {
> -		error2 = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, NULL);
> +		error2 = xfs_alloc_read_agf(pag, tp, 0, NULL);
>  		if (error2)
>  			return error2;
>  
> diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
> index f7853ab7b962..5d6ca86c4882 100644
> --- a/fs/xfs/libxfs/xfs_alloc.c
> +++ b/fs/xfs/libxfs/xfs_alloc.c
> @@ -2609,7 +2609,7 @@ xfs_alloc_fix_freelist(
>  	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
>  
>  	if (!pag->pagf_init) {
> -		error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp);
> +		error = xfs_alloc_read_agf(pag, tp, flags, &agbp);
>  		if (error) {
>  			/* Couldn't lock the AGF so skip this AG. */
>  			if (error == -EAGAIN)
> @@ -2639,7 +2639,7 @@ xfs_alloc_fix_freelist(
>  	 * Can fail if we're not blocking on locks, and it's held.
>  	 */
>  	if (!agbp) {
> -		error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp);
> +		error = xfs_alloc_read_agf(pag, tp, flags, &agbp);
>  		if (error) {
>  			/* Couldn't lock the AGF so skip this AG. */
>  			if (error == -EAGAIN)
> @@ -3080,34 +3080,30 @@ xfs_read_agf(
>   * perag structure if necessary. If the caller provides @agfbpp, then return the
>   * locked buffer to the caller, otherwise free it.
>   */
> -int					/* error */
> +int
>  xfs_alloc_read_agf(
> -	struct xfs_mount	*mp,	/* mount point structure */
> -	struct xfs_trans	*tp,	/* transaction pointer */
> -	xfs_agnumber_t		agno,	/* allocation group number */
> -	int			flags,	/* XFS_ALLOC_FLAG_... */
> +	struct xfs_perag	*pag,
> +	struct xfs_trans	*tp,
> +	int			flags,
>  	struct xfs_buf		**agfbpp)
>  {
>  	struct xfs_buf		*agfbp;
> -	struct xfs_agf		*agf;		/* ag freelist header */
> -	struct xfs_perag	*pag;		/* per allocation group data */
> +	struct xfs_agf		*agf;
>  	int			error;
>  	int			allocbt_blks;
>  
> -	trace_xfs_alloc_read_agf(mp, agno);
> +	trace_xfs_alloc_read_agf(pag->pag_mount, pag->pag_agno);
>  
>  	/* We don't support trylock when freeing. */
>  	ASSERT((flags & (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)) !=
>  			(XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK));
> -	ASSERT(agno != NULLAGNUMBER);
> -	error = xfs_read_agf(mp, tp, agno,
> +	error = xfs_read_agf(pag->pag_mount, tp, pag->pag_agno,
>  			(flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0,
>  			&agfbp);
>  	if (error)
>  		return error;
>  
>  	agf = agfbp->b_addr;
> -	pag = agfbp->b_pag;
>  	if (!pag->pagf_init) {
>  		pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
>  		pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
> @@ -3121,7 +3117,7 @@ xfs_alloc_read_agf(
>  			be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]);
>  		pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level);
>  		pag->pagf_init = 1;
> -		pag->pagf_agflreset = xfs_agfl_needs_reset(mp, agf);
> +		pag->pagf_agflreset = xfs_agfl_needs_reset(pag->pag_mount, agf);
>  
>  		/*
>  		 * Update the in-core allocbt counter. Filter out the rmapbt
> @@ -3131,13 +3127,13 @@ xfs_alloc_read_agf(
>  		 * counter only tracks non-root blocks.
>  		 */
>  		allocbt_blks = pag->pagf_btreeblks;
> -		if (xfs_has_rmapbt(mp))
> +		if (xfs_has_rmapbt(pag->pag_mount))
>  			allocbt_blks -= be32_to_cpu(agf->agf_rmap_blocks) - 1;
>  		if (allocbt_blks > 0)
> -			atomic64_add(allocbt_blks, &mp->m_allocbt_blks);
> +			atomic64_add(allocbt_blks, &pag->pag_mount->m_allocbt_blks);

Overly long line here.  I think in general this function would benefit
from a local xfs_mount *mp variable anyway.

> diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
> index bea65f2fe657..65c5dfe17ecf 100644
> --- a/fs/xfs/xfs_reflink.h
> +++ b/fs/xfs/xfs_reflink.h
> @@ -16,9 +16,6 @@ static inline bool xfs_is_cow_inode(struct xfs_inode *ip)
>  	return xfs_is_reflink_inode(ip) || xfs_is_always_cow_inode(ip);
>  }
>  
> -extern int xfs_reflink_find_shared(struct xfs_mount *mp, struct xfs_trans *tp,
> -		xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t aglen,
> -		xfs_agblock_t *fbno, xfs_extlen_t *flen, bool find_maximal);

Dropping this extern seems unrelated, and should move into a separate
patch together with actually marking it static.

Otherwise looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>
diff mbox series

Patch

diff --git a/fs/xfs/libxfs/xfs_ag.c b/fs/xfs/libxfs/xfs_ag.c
index 734ef170936e..c1a1c9f414c3 100644
--- a/fs/xfs/libxfs/xfs_ag.c
+++ b/fs/xfs/libxfs/xfs_ag.c
@@ -120,16 +120,13 @@  xfs_initialize_perag_data(
 
 	for (index = 0; index < agcount; index++) {
 		/*
-		 * read the agf, then the agi. This gets us
-		 * all the information we need and populates the
-		 * per-ag structures for us.
+		 * Read the AGF and AGI buffers to populate the per-ag
+		 * structures for us.
 		 */
-		error = xfs_alloc_read_agf(mp, NULL, index, 0, NULL);
-		if (error)
-			return error;
-
 		pag = xfs_perag_get(mp, index);
-		error = xfs_ialloc_read_agi(pag, NULL, NULL);
+		error = xfs_alloc_read_agf(pag, NULL, 0, NULL);
+		if (!error)
+			error = xfs_ialloc_read_agi(pag, NULL, NULL);
 		if (error) {
 			xfs_perag_put(pag);
 			return error;
@@ -792,7 +789,7 @@  xfs_ag_shrink_space(
 
 	agi = agibp->b_addr;
 
-	error = xfs_alloc_read_agf(mp, *tpp, pag->pag_agno, 0, &agfbp);
+	error = xfs_alloc_read_agf(pag, *tpp, 0, &agfbp);
 	if (error)
 		return error;
 
@@ -909,7 +906,7 @@  xfs_ag_extend_space(
 	/*
 	 * Change agf length.
 	 */
-	error = xfs_alloc_read_agf(pag->pag_mount, tp, pag->pag_agno, 0, &bp);
+	error = xfs_alloc_read_agf(pag, tp, 0, &bp);
 	if (error)
 		return error;
 
@@ -952,7 +949,7 @@  xfs_ag_get_geometry(
 	error = xfs_ialloc_read_agi(pag, NULL, &agi_bp);
 	if (error)
 		return error;
-	error = xfs_alloc_read_agf(pag->pag_mount, NULL, pag->pag_agno, 0, &agf_bp);
+	error = xfs_alloc_read_agf(pag, NULL, 0, &agf_bp);
 	if (error)
 		goto out_agi;
 
diff --git a/fs/xfs/libxfs/xfs_ag_resv.c b/fs/xfs/libxfs/xfs_ag_resv.c
index ce28bf8f72dc..5af123d13a63 100644
--- a/fs/xfs/libxfs/xfs_ag_resv.c
+++ b/fs/xfs/libxfs/xfs_ag_resv.c
@@ -322,7 +322,7 @@  xfs_ag_resv_init(
 	 * address.
 	 */
 	if (has_resv) {
-		error2 = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, NULL);
+		error2 = xfs_alloc_read_agf(pag, tp, 0, NULL);
 		if (error2)
 			return error2;
 
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index f7853ab7b962..5d6ca86c4882 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -2609,7 +2609,7 @@  xfs_alloc_fix_freelist(
 	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
 
 	if (!pag->pagf_init) {
-		error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp);
+		error = xfs_alloc_read_agf(pag, tp, flags, &agbp);
 		if (error) {
 			/* Couldn't lock the AGF so skip this AG. */
 			if (error == -EAGAIN)
@@ -2639,7 +2639,7 @@  xfs_alloc_fix_freelist(
 	 * Can fail if we're not blocking on locks, and it's held.
 	 */
 	if (!agbp) {
-		error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp);
+		error = xfs_alloc_read_agf(pag, tp, flags, &agbp);
 		if (error) {
 			/* Couldn't lock the AGF so skip this AG. */
 			if (error == -EAGAIN)
@@ -3080,34 +3080,30 @@  xfs_read_agf(
  * perag structure if necessary. If the caller provides @agfbpp, then return the
  * locked buffer to the caller, otherwise free it.
  */
-int					/* error */
+int
 xfs_alloc_read_agf(
-	struct xfs_mount	*mp,	/* mount point structure */
-	struct xfs_trans	*tp,	/* transaction pointer */
-	xfs_agnumber_t		agno,	/* allocation group number */
-	int			flags,	/* XFS_ALLOC_FLAG_... */
+	struct xfs_perag	*pag,
+	struct xfs_trans	*tp,
+	int			flags,
 	struct xfs_buf		**agfbpp)
 {
 	struct xfs_buf		*agfbp;
-	struct xfs_agf		*agf;		/* ag freelist header */
-	struct xfs_perag	*pag;		/* per allocation group data */
+	struct xfs_agf		*agf;
 	int			error;
 	int			allocbt_blks;
 
-	trace_xfs_alloc_read_agf(mp, agno);
+	trace_xfs_alloc_read_agf(pag->pag_mount, pag->pag_agno);
 
 	/* We don't support trylock when freeing. */
 	ASSERT((flags & (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)) !=
 			(XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK));
-	ASSERT(agno != NULLAGNUMBER);
-	error = xfs_read_agf(mp, tp, agno,
+	error = xfs_read_agf(pag->pag_mount, tp, pag->pag_agno,
 			(flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0,
 			&agfbp);
 	if (error)
 		return error;
 
 	agf = agfbp->b_addr;
-	pag = agfbp->b_pag;
 	if (!pag->pagf_init) {
 		pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
 		pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
@@ -3121,7 +3117,7 @@  xfs_alloc_read_agf(
 			be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]);
 		pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level);
 		pag->pagf_init = 1;
-		pag->pagf_agflreset = xfs_agfl_needs_reset(mp, agf);
+		pag->pagf_agflreset = xfs_agfl_needs_reset(pag->pag_mount, agf);
 
 		/*
 		 * Update the in-core allocbt counter. Filter out the rmapbt
@@ -3131,13 +3127,13 @@  xfs_alloc_read_agf(
 		 * counter only tracks non-root blocks.
 		 */
 		allocbt_blks = pag->pagf_btreeblks;
-		if (xfs_has_rmapbt(mp))
+		if (xfs_has_rmapbt(pag->pag_mount))
 			allocbt_blks -= be32_to_cpu(agf->agf_rmap_blocks) - 1;
 		if (allocbt_blks > 0)
-			atomic64_add(allocbt_blks, &mp->m_allocbt_blks);
+			atomic64_add(allocbt_blks, &pag->pag_mount->m_allocbt_blks);
 	}
 #ifdef DEBUG
-	else if (!xfs_is_shutdown(mp)) {
+	else if (!xfs_is_shutdown(pag->pag_mount)) {
 		ASSERT(pag->pagf_freeblks == be32_to_cpu(agf->agf_freeblks));
 		ASSERT(pag->pagf_btreeblks == be32_to_cpu(agf->agf_btreeblks));
 		ASSERT(pag->pagf_flcount == be32_to_cpu(agf->agf_flcount));
diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h
index 96d5301a5c8b..b8cf5beb26d4 100644
--- a/fs/xfs/libxfs/xfs_alloc.h
+++ b/fs/xfs/libxfs/xfs_alloc.h
@@ -134,17 +134,6 @@  xfs_alloc_put_freelist(
 	xfs_agblock_t	bno,	/* block being freed */
 	int		btreeblk); /* owner was a AGF btree */
 
-/*
- * Read in the allocation group header (free/alloc section).
- */
-int					/* error  */
-xfs_alloc_read_agf(
-	struct xfs_mount *mp,		/* mount point structure */
-	struct xfs_trans *tp,		/* transaction pointer */
-	xfs_agnumber_t	agno,		/* allocation group number */
-	int		flags,		/* XFS_ALLOC_FLAG_... */
-	struct xfs_buf	**bpp);		/* buffer for the ag freelist header */
-
 /*
  * Allocate an extent (variable-size).
  */
@@ -198,6 +187,8 @@  xfs_alloc_get_rec(
 
 int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
 			xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
+int xfs_alloc_read_agf(struct xfs_perag *pag, struct xfs_trans *tp, int flags,
+		struct xfs_buf **agfbpp);
 int xfs_alloc_read_agfl(struct xfs_mount *mp, struct xfs_trans *tp,
 			xfs_agnumber_t agno, struct xfs_buf **bpp);
 int xfs_free_agfl_block(struct xfs_trans *, xfs_agnumber_t, xfs_agblock_t,
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index a76d5894641b..88828fcf0453 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -3185,7 +3185,7 @@  xfs_bmap_longest_free_extent(
 
 	pag = xfs_perag_get(mp, ag);
 	if (!pag->pagf_init) {
-		error = xfs_alloc_read_agf(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK,
+		error = xfs_alloc_read_agf(pag, tp, XFS_ALLOC_FLAG_TRYLOCK,
 				NULL);
 		if (error) {
 			/* Couldn't lock the AGF, so skip this AG. */
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 8e252207b131..dfa8061f65d9 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -1621,7 +1621,7 @@  xfs_dialloc_good_ag(
 		return false;
 
 	if (!pag->pagf_init) {
-		error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, flags, NULL);
+		error = xfs_alloc_read_agf(pag, tp, flags, NULL);
 		if (error)
 			return false;
 	}
diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
index 97e9e6020596..098dac888c22 100644
--- a/fs/xfs/libxfs/xfs_refcount.c
+++ b/fs/xfs/libxfs/xfs_refcount.c
@@ -1177,8 +1177,8 @@  xfs_refcount_finish_one(
 		*pcur = NULL;
 	}
 	if (rcur == NULL) {
-		error = xfs_alloc_read_agf(tp->t_mountp, tp, pag->pag_agno,
-				XFS_ALLOC_FLAG_FREEING, &agbp);
+		error = xfs_alloc_read_agf(pag, tp, XFS_ALLOC_FLAG_FREEING,
+				&agbp);
 		if (error)
 			goto out_drop;
 
@@ -1710,7 +1710,7 @@  xfs_refcount_recover_cow_leftovers(
 	if (error)
 		return error;
 
-	error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, &agbp);
+	error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
 	if (error)
 		goto out_trans;
 	cur = xfs_refcountbt_init_cursor(mp, tp, agbp, pag);
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c
index d14c1720b0fb..1063234df34a 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.c
+++ b/fs/xfs/libxfs/xfs_refcount_btree.c
@@ -493,7 +493,7 @@  xfs_refcountbt_calc_reserves(
 	if (!xfs_has_reflink(mp))
 		return 0;
 
-	error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, &agbp);
+	error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
 	if (error)
 		return error;
 
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c
index 69e104d0277f..d6d45992fe7b 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rmap_btree.c
@@ -652,7 +652,7 @@  xfs_rmapbt_calc_reserves(
 	if (!xfs_has_rmapbt(mp))
 		return 0;
 
-	error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, &agbp);
+	error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
 	if (error)
 		return error;
 
diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c
index 6da7f2ca77de..230bdfe36e80 100644
--- a/fs/xfs/scrub/agheader_repair.c
+++ b/fs/xfs/scrub/agheader_repair.c
@@ -666,8 +666,7 @@  xrep_agfl(
 	 * nothing wrong with the AGF, but all the AG header repair functions
 	 * have this chicken-and-egg problem.
 	 */
-	error = xfs_alloc_read_agf(mp, sc->tp, sc->sa.pag->pag_agno, 0,
-			&agf_bp);
+	error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
 	if (error)
 		return error;
 
@@ -742,8 +741,7 @@  xrep_agi_find_btrees(
 	int				error;
 
 	/* Read the AGF. */
-	error = xfs_alloc_read_agf(mp, sc->tp, sc->sa.pag->pag_agno, 0,
-			&agf_bp);
+	error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
 	if (error)
 		return error;
 
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index 285995ba3947..9353fd060525 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -540,7 +540,7 @@  xchk_bmap_check_ag_rmaps(
 	struct xfs_buf			*agf;
 	int				error;
 
-	error = xfs_alloc_read_agf(sc->mp, sc->tp, pag->pag_agno, 0, &agf);
+	error = xfs_alloc_read_agf(pag, sc->tp, 0, &agf);
 	if (error)
 		return error;
 
diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
index 62997791694a..cd7d4ebd240b 100644
--- a/fs/xfs/scrub/common.c
+++ b/fs/xfs/scrub/common.c
@@ -420,7 +420,7 @@  xchk_ag_read_headers(
 	if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGI))
 		return error;
 
-	error = xfs_alloc_read_agf(mp, sc->tp, agno, 0, &sa->agf_bp);
+	error = xfs_alloc_read_agf(sa->pag, sc->tp, 0, &sa->agf_bp);
 	if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGF))
 		return error;
 
diff --git a/fs/xfs/scrub/fscounters.c b/fs/xfs/scrub/fscounters.c
index bd06a184c81c..6a6f8fe7f87c 100644
--- a/fs/xfs/scrub/fscounters.c
+++ b/fs/xfs/scrub/fscounters.c
@@ -81,7 +81,7 @@  xchk_fscount_warmup(
 		error = xfs_ialloc_read_agi(pag, sc->tp, &agi_bp);
 		if (error)
 			break;
-		error = xfs_alloc_read_agf(mp, sc->tp, agno, 0, &agf_bp);
+		error = xfs_alloc_read_agf(pag, sc->tp, 0, &agf_bp);
 		if (error)
 			break;
 
diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c
index 14acf1df3dd3..1c66f7ee6282 100644
--- a/fs/xfs/scrub/repair.c
+++ b/fs/xfs/scrub/repair.c
@@ -207,7 +207,7 @@  xrep_calc_ag_resblks(
 	}
 
 	/* Now grab the block counters from the AGF. */
-	error = xfs_alloc_read_agf(mp, NULL, sm->sm_agno, 0, &bp);
+	error = xfs_alloc_read_agf(pag, NULL, 0, &bp);
 	if (error) {
 		aglen = xfs_ag_block_count(mp, sm->sm_agno);
 		freelen = aglen;
@@ -543,6 +543,7 @@  xrep_reap_block(
 
 	agno = XFS_FSB_TO_AGNO(sc->mp, fsbno);
 	agbno = XFS_FSB_TO_AGBNO(sc->mp, fsbno);
+	ASSERT(agno == sc->sa.pag->pag_agno);
 
 	/*
 	 * If we are repairing per-inode metadata, we need to read in the AGF
@@ -550,7 +551,7 @@  xrep_reap_block(
 	 * the AGF buffer that the setup functions already grabbed.
 	 */
 	if (sc->ip) {
-		error = xfs_alloc_read_agf(sc->mp, sc->tp, agno, 0, &agf_bp);
+		error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
 		if (error)
 			return error;
 	} else {
diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c
index c6fe3f6ebb6b..bfc829c07f03 100644
--- a/fs/xfs/xfs_discard.c
+++ b/fs/xfs/xfs_discard.c
@@ -45,7 +45,7 @@  xfs_trim_extents(
 	 */
 	xfs_log_force(mp, XFS_LOG_SYNC);
 
-	error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp);
+	error = xfs_alloc_read_agf(pag, NULL, 0, &agbp);
 	if (error)
 		goto out_put_perag;
 	agf = agbp->b_addr;
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 765be054dffe..0d0a0b37d8c5 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -11,6 +11,7 @@ 
 #include "xfs_bit.h"
 #include "xfs_shared.h"
 #include "xfs_mount.h"
+#include "xfs_ag.h"
 #include "xfs_defer.h"
 #include "xfs_trans.h"
 #include "xfs_trans_priv.h"
@@ -551,6 +552,7 @@  xfs_agfl_free_finish_item(
 	xfs_agnumber_t			agno;
 	xfs_agblock_t			agbno;
 	uint				next_extent;
+	struct xfs_perag		*pag;
 
 	free = container_of(item, struct xfs_extent_free_item, xefi_list);
 	ASSERT(free->xefi_blockcount == 1);
@@ -560,9 +562,11 @@  xfs_agfl_free_finish_item(
 
 	trace_xfs_agfl_free_deferred(mp, agno, 0, agbno, free->xefi_blockcount);
 
-	error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
+	pag = xfs_perag_get(mp, agno);
+	error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
 	if (!error)
 		error = xfs_free_agfl_block(tp, agno, agbno, agbp, &oinfo);
+	xfs_perag_put(pag);
 
 	/*
 	 * Mark the transaction dirty, even on error. This ensures the
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
index 6b09a30f8d06..34b21a29c39b 100644
--- a/fs/xfs/xfs_filestream.c
+++ b/fs/xfs/xfs_filestream.c
@@ -126,7 +126,7 @@  xfs_filestream_pick_ag(
 		pag = xfs_perag_get(mp, ag);
 
 		if (!pag->pagf_init) {
-			err = xfs_alloc_read_agf(mp, NULL, ag, trylock, NULL);
+			err = xfs_alloc_read_agf(pag, NULL, trylock, NULL);
 			if (err) {
 				if (err != -EAGAIN) {
 					xfs_perag_put(pag);
diff --git a/fs/xfs/xfs_fsmap.c b/fs/xfs/xfs_fsmap.c
index bb23199f65c3..d8337274c74d 100644
--- a/fs/xfs/xfs_fsmap.c
+++ b/fs/xfs/xfs_fsmap.c
@@ -642,8 +642,7 @@  __xfs_getfsmap_datadev(
 			info->agf_bp = NULL;
 		}
 
-		error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0,
-				&info->agf_bp);
+		error = xfs_alloc_read_agf(pag, tp, 0, &info->agf_bp);
 		if (error)
 			break;
 
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index e7a7c00d93be..d2328cc26ddf 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -127,9 +127,8 @@ 
  */
 int
 xfs_reflink_find_shared(
-	struct xfs_mount	*mp,
+	struct xfs_perag	*pag,
 	struct xfs_trans	*tp,
-	xfs_agnumber_t		agno,
 	xfs_agblock_t		agbno,
 	xfs_extlen_t		aglen,
 	xfs_agblock_t		*fbno,
@@ -140,11 +139,11 @@  xfs_reflink_find_shared(
 	struct xfs_btree_cur	*cur;
 	int			error;
 
-	error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
+	error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
 	if (error)
 		return error;
 
-	cur = xfs_refcountbt_init_cursor(mp, tp, agbp, agbp->b_pag);
+	cur = xfs_refcountbt_init_cursor(pag->pag_mount, tp, agbp, pag);
 
 	error = xfs_refcount_find_shared(cur, agbno, aglen, fbno, flen,
 			find_end_of_shared);
@@ -171,7 +170,8 @@  xfs_reflink_trim_around_shared(
 	struct xfs_bmbt_irec	*irec,
 	bool			*shared)
 {
-	xfs_agnumber_t		agno;
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_perag	*pag;
 	xfs_agblock_t		agbno;
 	xfs_extlen_t		aglen;
 	xfs_agblock_t		fbno;
@@ -186,12 +186,13 @@  xfs_reflink_trim_around_shared(
 
 	trace_xfs_reflink_trim_around_shared(ip, irec);
 
-	agno = XFS_FSB_TO_AGNO(ip->i_mount, irec->br_startblock);
-	agbno = XFS_FSB_TO_AGBNO(ip->i_mount, irec->br_startblock);
+	pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, irec->br_startblock));
+	agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
 	aglen = irec->br_blockcount;
 
-	error = xfs_reflink_find_shared(ip->i_mount, NULL, agno, agbno,
-			aglen, &fbno, &flen, true);
+	error = xfs_reflink_find_shared(pag, NULL, agbno, aglen, &fbno, &flen,
+			true);
+	xfs_perag_put(pag);
 	if (error)
 		return error;
 
@@ -1420,11 +1421,6 @@  xfs_reflink_inode_has_shared_extents(
 	struct xfs_bmbt_irec		got;
 	struct xfs_mount		*mp = ip->i_mount;
 	struct xfs_ifork		*ifp;
-	xfs_agnumber_t			agno;
-	xfs_agblock_t			agbno;
-	xfs_extlen_t			aglen;
-	xfs_agblock_t			rbno;
-	xfs_extlen_t			rlen;
 	struct xfs_iext_cursor		icur;
 	bool				found;
 	int				error;
@@ -1437,17 +1433,25 @@  xfs_reflink_inode_has_shared_extents(
 	*has_shared = false;
 	found = xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got);
 	while (found) {
+		struct xfs_perag	*pag;
+		xfs_agblock_t		agbno;
+		xfs_extlen_t		aglen;
+		xfs_agblock_t		rbno;
+		xfs_extlen_t		rlen;
+
 		if (isnullstartblock(got.br_startblock) ||
 		    got.br_state != XFS_EXT_NORM)
 			goto next;
-		agno = XFS_FSB_TO_AGNO(mp, got.br_startblock);
+
+		pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, got.br_startblock));
 		agbno = XFS_FSB_TO_AGBNO(mp, got.br_startblock);
 		aglen = got.br_blockcount;
-
-		error = xfs_reflink_find_shared(mp, tp, agno, agbno, aglen,
+		error = xfs_reflink_find_shared(pag, tp, agbno, aglen,
 				&rbno, &rlen, false);
+		xfs_perag_put(pag);
 		if (error)
 			return error;
+
 		/* Is there still a shared block here? */
 		if (rbno != NULLAGBLOCK) {
 			*has_shared = true;
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
index bea65f2fe657..65c5dfe17ecf 100644
--- a/fs/xfs/xfs_reflink.h
+++ b/fs/xfs/xfs_reflink.h
@@ -16,9 +16,6 @@  static inline bool xfs_is_cow_inode(struct xfs_inode *ip)
 	return xfs_is_reflink_inode(ip) || xfs_is_always_cow_inode(ip);
 }
 
-extern int xfs_reflink_find_shared(struct xfs_mount *mp, struct xfs_trans *tp,
-		xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t aglen,
-		xfs_agblock_t *fbno, xfs_extlen_t *flen, bool find_maximal);
 extern int xfs_reflink_trim_around_shared(struct xfs_inode *ip,
 		struct xfs_bmbt_irec *irec, bool *shared);
 int xfs_bmap_trim_cow(struct xfs_inode *ip, struct xfs_bmbt_irec *imap,