LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_rmap.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 1147 1487 77.1 %
Date: 2023-07-31 20:08:07 Functions: 48 50 96.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (c) 2014 Red Hat, Inc.
       4             :  * All Rights Reserved.
       5             :  */
       6             : #include "xfs.h"
       7             : #include "xfs_fs.h"
       8             : #include "xfs_shared.h"
       9             : #include "xfs_format.h"
      10             : #include "xfs_log_format.h"
      11             : #include "xfs_trans_resv.h"
      12             : #include "xfs_bit.h"
      13             : #include "xfs_mount.h"
      14             : #include "xfs_sb.h"
      15             : #include "xfs_defer.h"
      16             : #include "xfs_btree.h"
      17             : #include "xfs_trans.h"
      18             : #include "xfs_alloc.h"
      19             : #include "xfs_rmap.h"
      20             : #include "xfs_rmap_btree.h"
      21             : #include "xfs_trace.h"
      22             : #include "xfs_errortag.h"
      23             : #include "xfs_error.h"
      24             : #include "xfs_inode.h"
      25             : #include "xfs_ag.h"
      26             : #include "xfs_health.h"
      27             : 
      28             : struct kmem_cache       *xfs_rmap_intent_cache;
      29             : 
      30             : /*
      31             :  * Lookup the first record less than or equal to [bno, len, owner, offset]
      32             :  * in the btree given by cur.
      33             :  */
      34             : int
      35   430531461 : xfs_rmap_lookup_le(
      36             :         struct xfs_btree_cur    *cur,
      37             :         xfs_agblock_t           bno,
      38             :         uint64_t                owner,
      39             :         uint64_t                offset,
      40             :         unsigned int            flags,
      41             :         struct xfs_rmap_irec    *irec,
      42             :         int                     *stat)
      43             : {
      44   430531461 :         int                     get_stat = 0;
      45   430531461 :         int                     error;
      46             : 
      47   430531461 :         cur->bc_rec.r.rm_startblock = bno;
      48   430531461 :         cur->bc_rec.r.rm_blockcount = 0;
      49   430531461 :         cur->bc_rec.r.rm_owner = owner;
      50   430531461 :         cur->bc_rec.r.rm_offset = offset;
      51   430531461 :         cur->bc_rec.r.rm_flags = flags;
      52             : 
      53   430531461 :         error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
      54   430532927 :         if (error || !(*stat) || !irec)
      55             :                 return error;
      56             : 
      57   424540252 :         error = xfs_rmap_get_rec(cur, irec, &get_stat);
      58   424543281 :         if (error)
      59             :                 return error;
      60   424543281 :         if (!get_stat) {
      61           0 :                 xfs_btree_mark_sick(cur);
      62           0 :                 return -EFSCORRUPTED;
      63             :         }
      64             : 
      65             :         return 0;
      66             : }
      67             : 
      68             : /*
      69             :  * Lookup the record exactly matching [bno, len, owner, offset]
      70             :  * in the btree given by cur.
      71             :  */
      72             : int
      73           0 : xfs_rmap_lookup_eq(
      74             :         struct xfs_btree_cur    *cur,
      75             :         xfs_agblock_t           bno,
      76             :         xfs_extlen_t            len,
      77             :         uint64_t                owner,
      78             :         uint64_t                offset,
      79             :         unsigned int            flags,
      80             :         int                     *stat)
      81             : {
      82   247243694 :         cur->bc_rec.r.rm_startblock = bno;
      83   247243694 :         cur->bc_rec.r.rm_blockcount = len;
      84   247243694 :         cur->bc_rec.r.rm_owner = owner;
      85   247243694 :         cur->bc_rec.r.rm_offset = offset;
      86   247243694 :         cur->bc_rec.r.rm_flags = flags;
      87           0 :         return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
      88             : }
      89             : 
      90             : /*
      91             :  * Update the record referred to by cur to the value given
      92             :  * by [bno, len, owner, offset].
      93             :  * This either works (return 0) or gets an EFSCORRUPTED error.
      94             :  */
      95             : STATIC int
      96    32151720 : xfs_rmap_update(
      97             :         struct xfs_btree_cur    *cur,
      98             :         struct xfs_rmap_irec    *irec)
      99             : {
     100    32151720 :         union xfs_btree_rec     rec;
     101    32151720 :         int                     error;
     102             : 
     103    32151720 :         trace_xfs_rmap_update(cur->bc_mp, cur->bc_ag.pag->pag_agno,
     104             :                         irec->rm_startblock, irec->rm_blockcount,
     105             :                         irec->rm_owner, irec->rm_offset, irec->rm_flags);
     106             : 
     107    32151710 :         rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
     108    32151710 :         rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
     109    32151710 :         rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
     110    32151710 :         rec.rmap.rm_offset = cpu_to_be64(
     111             :                         xfs_rmap_irec_offset_pack(irec));
     112    32151710 :         error = xfs_btree_update(cur, &rec);
     113    32151721 :         if (error)
     114           0 :                 trace_xfs_rmap_update_error(cur->bc_mp,
     115           0 :                                 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
     116    32151721 :         return error;
     117             : }
     118             : 
     119             : int
     120    85892310 : xfs_rmap_insert(
     121             :         struct xfs_btree_cur    *rcur,
     122             :         xfs_agblock_t           agbno,
     123             :         xfs_extlen_t            len,
     124             :         uint64_t                owner,
     125             :         uint64_t                offset,
     126             :         unsigned int            flags)
     127             : {
     128    85892310 :         int                     i;
     129    85892310 :         int                     error;
     130             : 
     131    85892310 :         trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
     132             :                         len, owner, offset, flags);
     133             : 
     134    85892431 :         error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
     135    85892510 :         if (error)
     136           0 :                 goto done;
     137    85892510 :         if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
     138           0 :                 xfs_btree_mark_sick(rcur);
     139           0 :                 error = -EFSCORRUPTED;
     140           0 :                 goto done;
     141             :         }
     142             : 
     143    85892510 :         rcur->bc_rec.r.rm_startblock = agbno;
     144    85892510 :         rcur->bc_rec.r.rm_blockcount = len;
     145    85892510 :         rcur->bc_rec.r.rm_owner = owner;
     146    85892510 :         rcur->bc_rec.r.rm_offset = offset;
     147    85892510 :         rcur->bc_rec.r.rm_flags = flags;
     148    85892510 :         error = xfs_btree_insert(rcur, &i);
     149    85892523 :         if (error)
     150         158 :                 goto done;
     151    85892365 :         if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
     152           0 :                 xfs_btree_mark_sick(rcur);
     153           0 :                 error = -EFSCORRUPTED;
     154           0 :                 goto done;
     155             :         }
     156    85892523 : done:
     157    85892523 :         if (error)
     158         158 :                 trace_xfs_rmap_insert_error(rcur->bc_mp,
     159         158 :                                 rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
     160    85892523 :         return error;
     161             : }
     162             : 
     163             : STATIC int
     164    55209268 : xfs_rmap_delete(
     165             :         struct xfs_btree_cur    *rcur,
     166             :         xfs_agblock_t           agbno,
     167             :         xfs_extlen_t            len,
     168             :         uint64_t                owner,
     169             :         uint64_t                offset,
     170             :         unsigned int            flags)
     171             : {
     172    55209268 :         int                     i;
     173    55209268 :         int                     error;
     174             : 
     175    55209268 :         trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
     176             :                         len, owner, offset, flags);
     177             : 
     178    55209282 :         error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
     179    55209342 :         if (error)
     180           0 :                 goto done;
     181    55209342 :         if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
     182           0 :                 xfs_btree_mark_sick(rcur);
     183           0 :                 error = -EFSCORRUPTED;
     184           0 :                 goto done;
     185             :         }
     186             : 
     187    55209342 :         error = xfs_btree_delete(rcur, &i);
     188    55209310 :         if (error)
     189           0 :                 goto done;
     190    55209310 :         if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
     191           0 :                 xfs_btree_mark_sick(rcur);
     192           0 :                 error = -EFSCORRUPTED;
     193           0 :                 goto done;
     194             :         }
     195    55209310 : done:
     196    55209310 :         if (error)
     197           0 :                 trace_xfs_rmap_delete_error(rcur->bc_mp,
     198           0 :                                 rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
     199    55209310 :         return error;
     200             : }
     201             : 
     202             : /* Convert an internal btree record to an rmap record. */
     203             : xfs_failaddr_t
     204 50906426272 : xfs_rmap_btrec_to_irec(
     205             :         const union xfs_btree_rec       *rec,
     206             :         struct xfs_rmap_irec            *irec)
     207             : {
     208 50906426272 :         irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
     209 50906426272 :         irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
     210 50906426272 :         irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
     211 50906426272 :         return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
     212             :                         irec);
     213             : }
     214             : 
     215             : inline xfs_failaddr_t
     216 51208080245 : xfs_rmap_check_perag_irec(
     217             :         struct xfs_perag                *pag,
     218             :         const struct xfs_rmap_irec      *irec)
     219             : {
     220 51208080245 :         struct xfs_mount                *mp = pag->pag_mount;
     221 51208080245 :         bool                            is_inode;
     222 51208080245 :         bool                            is_unwritten;
     223 51208080245 :         bool                            is_bmbt;
     224 51208080245 :         bool                            is_attr;
     225             : 
     226 51208080245 :         if (irec->rm_blockcount == 0)
     227           0 :                 return __this_address;
     228 51208080245 :         if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
     229     2977342 :                 if (irec->rm_owner != XFS_RMAP_OWN_FS)
     230           0 :                         return __this_address;
     231     2977342 :                 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
     232           0 :                         return __this_address;
     233             :         } else {
     234             :                 /* check for valid extent range, including overflow */
     235 51205102903 :                 if (!xfs_verify_agbext(pag, irec->rm_startblock,
     236             :                                             irec->rm_blockcount))
     237           0 :                         return __this_address;
     238             :         }
     239             : 
     240 51208080245 :         if (!(xfs_verify_ino(mp, irec->rm_owner) ||
     241  1208152622 :               (irec->rm_owner <= XFS_RMAP_OWN_FS &&
     242             :                irec->rm_owner >= XFS_RMAP_OWN_MIN)))
     243           0 :                 return __this_address;
     244             : 
     245             :         /* Check flags. */
     246 51235374653 :         is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
     247 51235374653 :         is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
     248 51235374653 :         is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
     249 51235374653 :         is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
     250             : 
     251 51235374653 :         if (is_bmbt && irec->rm_offset != 0)
     252           0 :                 return __this_address;
     253             : 
     254 51235374653 :         if (!is_inode && irec->rm_offset != 0)
     255           0 :                 return __this_address;
     256             : 
     257 51235374653 :         if (is_unwritten && (is_bmbt || !is_inode || is_attr))
     258           0 :                 return __this_address;
     259             : 
     260 51235374653 :         if (!is_inode && (is_bmbt || is_unwritten || is_attr))
     261           0 :                 return __this_address;
     262             : 
     263             :         /* Check for a valid fork offset, if applicable. */
     264 >10038*10^7 :         if (is_inode && !is_bmbt &&
     265 49117316181 :             !xfs_verify_fileext(mp, irec->rm_offset, irec->rm_blockcount))
     266           0 :                 return __this_address;
     267             : 
     268             :         return NULL;
     269             : }
     270             : 
     271             : /* Simple checks for rmap records. */
     272             : xfs_failaddr_t
     273 51237062572 : xfs_rmap_check_irec(
     274             :         struct xfs_btree_cur            *cur,
     275             :         const struct xfs_rmap_irec      *irec)
     276             : {
     277 51237062572 :         if (cur->bc_flags & XFS_BTREE_IN_XFILE)
     278    46959925 :                 return xfs_rmap_check_perag_irec(cur->bc_mem.pag, irec);
     279 51190102647 :         return xfs_rmap_check_perag_irec(cur->bc_ag.pag, irec);
     280             : }
     281             : 
     282             : static inline int
     283           0 : xfs_rmap_complain_bad_rec(
     284             :         struct xfs_btree_cur            *cur,
     285             :         xfs_failaddr_t                  fa,
     286             :         const struct xfs_rmap_irec      *irec)
     287             : {
     288           0 :         struct xfs_mount                *mp = cur->bc_mp;
     289             : 
     290           0 :         if (cur->bc_flags & XFS_BTREE_IN_XFILE)
     291           0 :                 xfs_warn(mp,
     292             :  "In-Memory Reverse Mapping BTree record corruption detected at %pS!", fa);
     293             :         else
     294           0 :                 xfs_warn(mp,
     295             :  "Reverse Mapping BTree record corruption in AG %d detected at %pS!",
     296             :                         cur->bc_ag.pag->pag_agno, fa);
     297           0 :         xfs_warn(mp,
     298             :                 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
     299             :                 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
     300             :                 irec->rm_blockcount);
     301           0 :         xfs_btree_mark_sick(cur);
     302           0 :         return -EFSCORRUPTED;
     303             : }
     304             : 
     305             : /*
     306             :  * Get the data from the pointed-to record.
     307             :  */
     308             : int
     309  1012687897 : xfs_rmap_get_rec(
     310             :         struct xfs_btree_cur    *cur,
     311             :         struct xfs_rmap_irec    *irec,
     312             :         int                     *stat)
     313             : {
     314  1012687897 :         union xfs_btree_rec     *rec;
     315  1012687897 :         xfs_failaddr_t          fa;
     316  1012687897 :         int                     error;
     317             : 
     318  1012687897 :         error = xfs_btree_get_rec(cur, &rec, stat);
     319  1012690731 :         if (error || !*stat)
     320             :                 return error;
     321             : 
     322  1012692430 :         fa = xfs_rmap_btrec_to_irec(rec, irec);
     323  1012694981 :         if (!fa)
     324  1012692792 :                 fa = xfs_rmap_check_irec(cur, irec);
     325  1012696569 :         if (fa)
     326           0 :                 return xfs_rmap_complain_bad_rec(cur, fa, irec);
     327             : 
     328             :         return 0;
     329             : }
     330             : 
     331             : struct xfs_find_left_neighbor_info {
     332             :         struct xfs_rmap_irec    high;
     333             :         struct xfs_rmap_irec    *irec;
     334             : };
     335             : 
     336             : /* For each rmap given, figure out if it matches the key we want. */
     337             : STATIC int
     338   104703641 : xfs_rmap_find_left_neighbor_helper(
     339             :         struct xfs_btree_cur            *cur,
     340             :         const struct xfs_rmap_irec      *rec,
     341             :         void                            *priv)
     342             : {
     343   104703641 :         struct xfs_find_left_neighbor_info      *info = priv;
     344             : 
     345   104703641 :         trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
     346   104703641 :                         cur->bc_ag.pag->pag_agno, rec->rm_startblock,
     347   104703641 :                         rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
     348   104703641 :                         rec->rm_flags);
     349             : 
     350   104703898 :         if (rec->rm_owner != info->high.rm_owner)
     351             :                 return 0;
     352    26973266 :         if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
     353    26973266 :             !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
     354    26954507 :             rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
     355             :                 return 0;
     356             : 
     357     9812275 :         *info->irec = *rec;
     358     9812275 :         return -ECANCELED;
     359             : }
     360             : 
     361             : /*
     362             :  * Find the record to the left of the given extent, being careful only to
     363             :  * return a match with the same owner and adjacent physical and logical
     364             :  * block ranges.
     365             :  */
     366             : STATIC int
     367    89110501 : xfs_rmap_find_left_neighbor(
     368             :         struct xfs_btree_cur    *cur,
     369             :         xfs_agblock_t           bno,
     370             :         uint64_t                owner,
     371             :         uint64_t                offset,
     372             :         unsigned int            flags,
     373             :         struct xfs_rmap_irec    *irec,
     374             :         int                     *stat)
     375             : {
     376    89110501 :         struct xfs_find_left_neighbor_info      info;
     377    89110501 :         int                     found = 0;
     378    89110501 :         int                     error;
     379             : 
     380    89110501 :         *stat = 0;
     381    89110501 :         if (bno == 0)
     382             :                 return 0;
     383    89110501 :         info.high.rm_startblock = bno - 1;
     384    89110501 :         info.high.rm_owner = owner;
     385    89110501 :         if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
     386    89110389 :             !(flags & XFS_RMAP_BMBT_BLOCK)) {
     387    89110501 :                 if (offset == 0)
     388             :                         return 0;
     389    88632948 :                 info.high.rm_offset = offset - 1;
     390             :         } else
     391           0 :                 info.high.rm_offset = 0;
     392    88632948 :         info.high.rm_flags = flags;
     393    88632948 :         info.high.rm_blockcount = 0;
     394    88632948 :         info.irec = irec;
     395             : 
     396    88632948 :         trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
     397    88632948 :                         cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
     398             : 
     399             :         /*
     400             :          * Historically, we always used the range query to walk every reverse
     401             :          * mapping that could possibly overlap the key that the caller asked
     402             :          * for, and filter out the ones that don't.  That is very slow when
     403             :          * there are a lot of records.
     404             :          *
     405             :          * However, there are two scenarios where the classic btree search can
     406             :          * produce correct results -- if the index contains a record that is an
     407             :          * exact match for the lookup key; and if there are no other records
     408             :          * between the record we want and the key we supplied.
     409             :          *
     410             :          * As an optimization, try a non-overlapped lookup first.  This makes
     411             :          * extent conversion and remap operations run a bit faster if the
     412             :          * physical extents aren't being shared.  If we don't find what we
     413             :          * want, we fall back to the overlapped query.
     414             :          */
     415    88632939 :         error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
     416             :                         &found);
     417    88633057 :         if (error)
     418             :                 return error;
     419    88632843 :         if (found)
     420    88633058 :                 error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info);
     421    88632840 :         if (!error)
     422    79183409 :                 error = xfs_rmap_query_range(cur, &info.high, &info.high,
     423             :                                 xfs_rmap_find_left_neighbor_helper, &info);
     424    88632854 :         if (error != -ECANCELED)
     425             :                 return error;
     426             : 
     427     9812275 :         *stat = 1;
     428     9812275 :         trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
     429     9812275 :                         cur->bc_ag.pag->pag_agno, irec->rm_startblock,
     430             :                         irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
     431             :                         irec->rm_flags);
     432     9812275 :         return 0;
     433             : }
     434             : 
     435             : /* For each rmap given, figure out if it matches the key we want. */
     436             : STATIC int
     437   112999935 : xfs_rmap_lookup_le_range_helper(
     438             :         struct xfs_btree_cur            *cur,
     439             :         const struct xfs_rmap_irec      *rec,
     440             :         void                            *priv)
     441             : {
     442   112999935 :         struct xfs_find_left_neighbor_info      *info = priv;
     443             : 
     444   112999935 :         trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
     445   112999935 :                         cur->bc_ag.pag->pag_agno, rec->rm_startblock,
     446   112999935 :                         rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
     447   112999935 :                         rec->rm_flags);
     448             : 
     449   113000077 :         if (rec->rm_owner != info->high.rm_owner)
     450             :                 return 0;
     451   105904340 :         if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
     452   105904340 :             !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
     453   105904340 :             (rec->rm_offset > info->high.rm_offset ||
     454   105887723 :              rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
     455             :                 return 0;
     456             : 
     457   105881907 :         *info->irec = *rec;
     458   105881907 :         return -ECANCELED;
     459             : }
     460             : 
     461             : /*
     462             :  * Find the record to the left of the given extent, being careful only to
     463             :  * return a match with the same owner and overlapping physical and logical
     464             :  * block ranges.  This is the overlapping-interval version of
     465             :  * xfs_rmap_lookup_le.
     466             :  */
     467             : int
     468   105881662 : xfs_rmap_lookup_le_range(
     469             :         struct xfs_btree_cur    *cur,
     470             :         xfs_agblock_t           bno,
     471             :         uint64_t                owner,
     472             :         uint64_t                offset,
     473             :         unsigned int            flags,
     474             :         struct xfs_rmap_irec    *irec,
     475             :         int                     *stat)
     476             : {
     477   105881662 :         struct xfs_find_left_neighbor_info      info;
     478   105881662 :         int                     found = 0;
     479   105881662 :         int                     error;
     480             : 
     481   105881662 :         info.high.rm_startblock = bno;
     482   105881662 :         info.high.rm_owner = owner;
     483   105881662 :         if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
     484   105881662 :                 info.high.rm_offset = offset;
     485             :         else
     486           0 :                 info.high.rm_offset = 0;
     487   105881662 :         info.high.rm_flags = flags;
     488   105881662 :         info.high.rm_blockcount = 0;
     489   105881662 :         *stat = 0;
     490   105881662 :         info.irec = irec;
     491             : 
     492   105881662 :         trace_xfs_rmap_lookup_le_range(cur->bc_mp, cur->bc_ag.pag->pag_agno,
     493             :                         bno, 0, owner, offset, flags);
     494             : 
     495             :         /*
     496             :          * Historically, we always used the range query to walk every reverse
     497             :          * mapping that could possibly overlap the key that the caller asked
     498             :          * for, and filter out the ones that don't.  That is very slow when
     499             :          * there are a lot of records.
     500             :          *
     501             :          * However, there are two scenarios where the classic btree search can
     502             :          * produce correct results -- if the index contains a record that is an
     503             :          * exact match for the lookup key; and if there are no other records
     504             :          * between the record we want and the key we supplied.
     505             :          *
     506             :          * As an optimization, try a non-overlapped lookup first.  This makes
     507             :          * scrub run much faster on most filesystems because bmbt records are
     508             :          * usually an exact match for rmap records.  If we don't find what we
     509             :          * want, we fall back to the overlapped query.
     510             :          */
     511   105881573 :         error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
     512             :                         &found);
     513   105881954 :         if (error)
     514             :                 return error;
     515   105881667 :         if (found)
     516   105881773 :                 error = xfs_rmap_lookup_le_range_helper(cur, irec, &info);
     517   105881864 :         if (!error)
     518       84944 :                 error = xfs_rmap_query_range(cur, &info.high, &info.high,
     519             :                                 xfs_rmap_lookup_le_range_helper, &info);
     520   105881864 :         if (error != -ECANCELED)
     521             :                 return error;
     522             : 
     523   105881870 :         *stat = 1;
     524   105881870 :         trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
     525   105881870 :                         cur->bc_ag.pag->pag_agno, irec->rm_startblock,
     526             :                         irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
     527             :                         irec->rm_flags);
     528   105881870 :         return 0;
     529             : }
     530             : 
     531             : /*
     532             :  * Perform all the relevant owner checks for a removal op.  If we're doing an
     533             :  * unknown-owner removal then we have no owner information to check.
     534             :  */
     535             : static int
     536    43547519 : xfs_rmap_free_check_owner(
     537             :         struct xfs_btree_cur    *cur,
     538             :         uint64_t                ltoff,
     539             :         struct xfs_rmap_irec    *rec,
     540             :         xfs_filblks_t           len,
     541             :         uint64_t                owner,
     542             :         uint64_t                offset,
     543             :         unsigned int            flags)
     544             : {
     545    43547519 :         struct xfs_mount        *mp = cur->bc_mp;
     546    43547519 :         int                     error = 0;
     547             : 
     548    43547519 :         if (owner == XFS_RMAP_OWN_UNKNOWN)
     549             :                 return 0;
     550             : 
     551             :         /* Make sure the unwritten flag matches. */
     552    43547091 :         if (XFS_IS_CORRUPT(mp,
     553             :                            (flags & XFS_RMAP_UNWRITTEN) !=
     554             :                            (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
     555           0 :                 xfs_btree_mark_sick(cur);
     556           0 :                 error = -EFSCORRUPTED;
     557           0 :                 goto out;
     558             :         }
     559             : 
     560             :         /* Make sure the owner matches what we expect to find in the tree. */
     561    43547091 :         if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
     562           0 :                 xfs_btree_mark_sick(cur);
     563           0 :                 error = -EFSCORRUPTED;
     564           0 :                 goto out;
     565             :         }
     566             : 
     567             :         /* Check the offset, if necessary. */
     568    43547091 :         if (XFS_RMAP_NON_INODE_OWNER(owner))
     569     2640944 :                 goto out;
     570             : 
     571    40906147 :         if (flags & XFS_RMAP_BMBT_BLOCK) {
     572      511194 :                 if (XFS_IS_CORRUPT(mp,
     573             :                                    !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
     574           0 :                         xfs_btree_mark_sick(cur);
     575           0 :                         error = -EFSCORRUPTED;
     576           0 :                         goto out;
     577             :                 }
     578             :         } else {
     579    40394953 :                 if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
     580           0 :                         xfs_btree_mark_sick(cur);
     581           0 :                         error = -EFSCORRUPTED;
     582           0 :                         goto out;
     583             :                 }
     584    40394953 :                 if (XFS_IS_CORRUPT(mp,
     585             :                                    offset + len > ltoff + rec->rm_blockcount)) {
     586           0 :                         xfs_btree_mark_sick(cur);
     587           0 :                         error = -EFSCORRUPTED;
     588           0 :                         goto out;
     589             :                 }
     590             :         }
     591             : 
     592             : out:
     593             :         return error;
     594             : }
     595             : 
     596             : /*
     597             :  * Find the extent in the rmap btree and remove it.
     598             :  *
     599             :  * The record we find should always be an exact match for the extent that we're
     600             :  * looking for, since we insert them into the btree without modification.
     601             :  *
     602             :  * Special Case #1: when growing the filesystem, we "free" an extent when
     603             :  * growing the last AG. This extent is new space and so it is not tracked as
     604             :  * used space in the btree. The growfs code will pass in an owner of
     605             :  * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
     606             :  * extent. We verify that - the extent lookup result in a record that does not
     607             :  * overlap.
     608             :  *
     609             :  * Special Case #2: EFIs do not record the owner of the extent, so when
     610             :  * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
     611             :  * btree to ignore the owner (i.e. wildcard match) so we don't trigger
     612             :  * corruption checks during log recovery.
     613             :  */
     614             : STATIC int
     615    43556246 : xfs_rmap_unmap(
     616             :         struct xfs_btree_cur            *cur,
     617             :         xfs_agblock_t                   bno,
     618             :         xfs_extlen_t                    len,
     619             :         bool                            unwritten,
     620             :         const struct xfs_owner_info     *oinfo)
     621             : {
     622    43556246 :         struct xfs_mount                *mp = cur->bc_mp;
     623    43556246 :         struct xfs_rmap_irec            ltrec;
     624    43556246 :         uint64_t                        ltoff;
     625    43556246 :         int                             error = 0;
     626    43556246 :         int                             i;
     627    43556246 :         uint64_t                        owner;
     628    43556246 :         uint64_t                        offset;
     629    43556246 :         unsigned int                    flags;
     630    43556246 :         bool                            ignore_off;
     631             : 
     632    43556246 :         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
     633    43556246 :         ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
     634    40906744 :                         (flags & XFS_RMAP_BMBT_BLOCK);
     635    43556246 :         if (unwritten)
     636     1425178 :                 flags |= XFS_RMAP_UNWRITTEN;
     637    43556246 :         trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
     638             :                         unwritten, oinfo);
     639             : 
     640             :         /*
     641             :          * We should always have a left record because there's a static record
     642             :          * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
     643             :          * will not ever be removed from the tree.
     644             :          */
     645    43556204 :         error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &ltrec, &i);
     646    43555814 :         if (error)
     647          72 :                 goto out_error;
     648    43555742 :         if (XFS_IS_CORRUPT(mp, i != 1)) {
     649           0 :                 xfs_btree_mark_sick(cur);
     650           0 :                 error = -EFSCORRUPTED;
     651           0 :                 goto out_error;
     652             :         }
     653             : 
     654    43555742 :         trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
     655    43555742 :                         cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
     656             :                         ltrec.rm_blockcount, ltrec.rm_owner,
     657             :                         ltrec.rm_offset, ltrec.rm_flags);
     658    43555737 :         ltoff = ltrec.rm_offset;
     659             : 
     660             :         /*
     661             :          * For growfs, the incoming extent must be beyond the left record we
     662             :          * just found as it is new space and won't be used by anyone. This is
     663             :          * just a corruption check as we don't actually do anything with this
     664             :          * extent.  Note that we need to use >= instead of > because it might
     665             :          * be the case that the "left" extent goes all the way to EOFS.
     666             :          */
     667    43555737 :         if (owner == XFS_RMAP_OWN_NULL) {
     668          28 :                 if (XFS_IS_CORRUPT(mp,
     669             :                                    bno <
     670             :                                    ltrec.rm_startblock + ltrec.rm_blockcount)) {
     671           0 :                         xfs_btree_mark_sick(cur);
     672           0 :                         error = -EFSCORRUPTED;
     673           0 :                         goto out_error;
     674             :                 }
     675          28 :                 goto out_done;
     676             :         }
     677             : 
     678             :         /*
     679             :          * If we're doing an unknown-owner removal for EFI recovery, we expect
     680             :          * to find the full range in the rmapbt or nothing at all.  If we
     681             :          * don't find any rmaps overlapping either end of the range, we're
     682             :          * done.  Hopefully this means that the EFI creator already queued
     683             :          * (and finished) a RUI to remove the rmap.
     684             :          */
     685    43555709 :         if (owner == XFS_RMAP_OWN_UNKNOWN &&
     686        8511 :             ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
     687        8083 :                 struct xfs_rmap_irec    rtrec;
     688             : 
     689        8083 :                 error = xfs_btree_increment(cur, 0, &i);
     690        8083 :                 if (error)
     691           0 :                         goto out_error;
     692        8083 :                 if (i == 0)
     693        8081 :                         goto out_done;
     694        8070 :                 error = xfs_rmap_get_rec(cur, &rtrec, &i);
     695        8068 :                 if (error)
     696           0 :                         goto out_error;
     697        8068 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
     698           0 :                         xfs_btree_mark_sick(cur);
     699           0 :                         error = -EFSCORRUPTED;
     700           0 :                         goto out_error;
     701             :                 }
     702        8068 :                 if (rtrec.rm_startblock >= bno + len)
     703        8068 :                         goto out_done;
     704             :         }
     705             : 
     706             :         /* Make sure the extent we found covers the entire freeing range. */
     707    43547626 :         if (XFS_IS_CORRUPT(mp,
     708             :                            ltrec.rm_startblock > bno ||
     709             :                            ltrec.rm_startblock + ltrec.rm_blockcount <
     710             :                            bno + len)) {
     711           0 :                 xfs_btree_mark_sick(cur);
     712           0 :                 error = -EFSCORRUPTED;
     713           0 :                 goto out_error;
     714             :         }
     715             : 
     716             :         /* Check owner information. */
     717    43547626 :         error = xfs_rmap_free_check_owner(cur, ltoff, &ltrec, len, owner,
     718             :                         offset, flags);
     719    43547551 :         if (error)
     720           0 :                 goto out_error;
     721             : 
     722    43547551 :         if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
     723             :                 /* exact match, simply remove the record from rmap tree */
     724    38223638 :                 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
     725             :                                 ltrec.rm_startblock, ltrec.rm_blockcount,
     726             :                                 ltrec.rm_owner, ltrec.rm_offset,
     727             :                                 ltrec.rm_flags);
     728    38223597 :                 error = xfs_btree_delete(cur, &i);
     729    38223682 :                 if (error)
     730           0 :                         goto out_error;
     731    38223682 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
     732           0 :                         xfs_btree_mark_sick(cur);
     733           0 :                         error = -EFSCORRUPTED;
     734           0 :                         goto out_error;
     735             :                 }
     736     5323913 :         } else if (ltrec.rm_startblock == bno) {
     737             :                 /*
     738             :                  * overlap left hand side of extent: move the start, trim the
     739             :                  * length and update the current record.
     740             :                  *
     741             :                  *       ltbno                ltlen
     742             :                  * Orig:    |oooooooooooooooooooo|
     743             :                  * Freeing: |fffffffff|
     744             :                  * Result:            |rrrrrrrrrr|
     745             :                  *         bno       len
     746             :                  */
     747      957078 :                 ltrec.rm_startblock += len;
     748      957078 :                 ltrec.rm_blockcount -= len;
     749      957078 :                 if (!ignore_off)
     750      129033 :                         ltrec.rm_offset += len;
     751      957078 :                 error = xfs_rmap_update(cur, &ltrec);
     752      957068 :                 if (error)
     753           0 :                         goto out_error;
     754     4366835 :         } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
     755             :                 /*
     756             :                  * overlap right hand side of extent: trim the length and update
     757             :                  * the current record.
     758             :                  *
     759             :                  *       ltbno                ltlen
     760             :                  * Orig:    |oooooooooooooooooooo|
     761             :                  * Freeing:            |fffffffff|
     762             :                  * Result:  |rrrrrrrrrr|
     763             :                  *                    bno       len
     764             :                  */
     765      442297 :                 ltrec.rm_blockcount -= len;
     766      442297 :                 error = xfs_rmap_update(cur, &ltrec);
     767      442294 :                 if (error)
     768           0 :                         goto out_error;
     769             :         } else {
     770             : 
     771             :                 /*
     772             :                  * overlap middle of extent: trim the length of the existing
     773             :                  * record to the length of the new left-extent size, increment
     774             :                  * the insertion position so we can insert a new record
     775             :                  * containing the remaining right-extent space.
     776             :                  *
     777             :                  *       ltbno                ltlen
     778             :                  * Orig:    |oooooooooooooooooooo|
     779             :                  * Freeing:       |fffffffff|
     780             :                  * Result:  |rrrrr|         |rrrr|
     781             :                  *               bno       len
     782             :                  */
     783     3924538 :                 xfs_extlen_t    orig_len = ltrec.rm_blockcount;
     784             : 
     785     3924538 :                 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
     786     3924538 :                 error = xfs_rmap_update(cur, &ltrec);
     787     3924539 :                 if (error)
     788           0 :                         goto out_error;
     789             : 
     790     3924539 :                 error = xfs_btree_increment(cur, 0, &i);
     791     3924538 :                 if (error)
     792           0 :                         goto out_error;
     793             : 
     794     3924538 :                 cur->bc_rec.r.rm_startblock = bno + len;
     795     3924538 :                 cur->bc_rec.r.rm_blockcount = orig_len - len -
     796     3924538 :                                                      ltrec.rm_blockcount;
     797     3924538 :                 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
     798     3924538 :                 if (ignore_off)
     799      616323 :                         cur->bc_rec.r.rm_offset = 0;
     800             :                 else
     801     3308215 :                         cur->bc_rec.r.rm_offset = offset + len;
     802     3924538 :                 cur->bc_rec.r.rm_flags = flags;
     803     3924538 :                 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
     804             :                                 cur->bc_rec.r.rm_startblock,
     805             :                                 cur->bc_rec.r.rm_blockcount,
     806             :                                 cur->bc_rec.r.rm_owner,
     807             :                                 cur->bc_rec.r.rm_offset,
     808             :                                 cur->bc_rec.r.rm_flags);
     809     3924537 :                 error = xfs_btree_insert(cur, &i);
     810     3924537 :                 if (error)
     811           0 :                         goto out_error;
     812             :         }
     813             : 
     814     3924537 : out_done:
     815    43555690 :         trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
     816             :                         unwritten, oinfo);
     817    43555557 : out_error:
     818    43555557 :         if (error)
     819          72 :                 trace_xfs_rmap_unmap_error(mp, cur->bc_ag.pag->pag_agno,
     820          72 :                                 error, _RET_IP_);
     821    43555557 :         return error;
     822             : }
     823             : 
     824             : #ifdef CONFIG_XFS_LIVE_HOOKS
     825             : /*
     826             :  * Use a static key here to reduce the overhead of rmapbt live updates.  If
     827             :  * the compiler supports jump labels, the static branch will be replaced by a
     828             :  * nop sled when there are no hook users.  Online fsck is currently the only
     829             :  * caller, so this is a reasonable tradeoff.
     830             :  *
     831             :  * Note: Patching the kernel code requires taking the cpu hotplug lock.  Other
     832             :  * parts of the kernel allocate memory with that lock held, which means that
     833             :  * XFS callers cannot hold any locks that might be used by memory reclaim or
     834             :  * writeback when calling the static_branch_{inc,dec} functions.
     835             :  */
     836             : DEFINE_STATIC_XFS_HOOK_SWITCH(xfs_rmap_hooks_switch);
     837             : 
     838             : void
     839        4493 : xfs_rmap_hook_disable(void)
     840             : {
     841        4493 :         xfs_hooks_switch_off(&xfs_rmap_hooks_switch);
     842        4497 : }
     843             : 
     844             : void
     845        4497 : xfs_rmap_hook_enable(void)
     846             : {
     847        4497 :         xfs_hooks_switch_on(&xfs_rmap_hooks_switch);
     848        4496 : }
     849             : 
     850             : /* Call downstream hooks for a reverse mapping update. */
     851             : static inline void
     852   236962612 : xfs_rmap_update_hook(
     853             :         struct xfs_trans                *tp,
     854             :         struct xfs_perag                *pag,
     855             :         enum xfs_rmap_intent_type       op,
     856             :         xfs_agblock_t                   startblock,
     857             :         xfs_extlen_t                    blockcount,
     858             :         bool                            unwritten,
     859             :         const struct xfs_owner_info     *oinfo)
     860             : {
     861   237867131 :         if (xfs_hooks_switched_on(&xfs_rmap_hooks_switch)) {
     862      904512 :                 struct xfs_rmap_update_params   p = {
     863             :                         .startblock     = startblock,
     864             :                         .blockcount     = blockcount,
     865             :                         .unwritten      = unwritten,
     866             :                         .oinfo          = *oinfo, /* struct copy */
     867             :                 };
     868             : 
     869      904512 :                 if (pag)
     870      904512 :                         xfs_hooks_call(&pag->pag_rmap_update_hooks, op, &p);
     871             :         }
     872   236964071 : }
     873             : 
     874             : /* Call the specified function during a reverse mapping update. */
     875             : int
     876        4468 : xfs_rmap_hook_add(
     877             :         struct xfs_perag        *pag,
     878             :         struct xfs_rmap_hook    *hook)
     879             : {
     880        4468 :         return xfs_hooks_add(&pag->pag_rmap_update_hooks, &hook->update_hook);
     881             : }
     882             : 
     883             : /* Stop calling the specified function during a reverse mapping update. */
     884             : void
     885        4470 : xfs_rmap_hook_del(
     886             :         struct xfs_perag        *pag,
     887             :         struct xfs_rmap_hook    *hook)
     888             : {
     889        4470 :         xfs_hooks_del(&pag->pag_rmap_update_hooks, &hook->update_hook);
     890        4470 : }
     891             : #else
     892             : # define xfs_rmap_update_hook(t, p, o, s, b, u, oi)     do { } while(0)
     893             : #endif /* CONFIG_XFS_LIVE_HOOKS */
     894             : 
     895             : /*
     896             :  * Remove a reference to an extent in the rmap btree.
     897             :  */
     898             : int
     899     1048158 : xfs_rmap_free(
     900             :         struct xfs_trans                *tp,
     901             :         struct xfs_buf                  *agbp,
     902             :         struct xfs_perag                *pag,
     903             :         xfs_agblock_t                   bno,
     904             :         xfs_extlen_t                    len,
     905             :         const struct xfs_owner_info     *oinfo)
     906             : {
     907     1048158 :         struct xfs_mount                *mp = tp->t_mountp;
     908     1048158 :         struct xfs_btree_cur            *cur;
     909     1048158 :         int                             error;
     910             : 
     911     1048158 :         if (!xfs_has_rmapbt(mp))
     912             :                 return 0;
     913             : 
     914      929163 :         cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
     915      929152 :         xfs_rmap_update_hook(tp, pag, XFS_RMAP_UNMAP, bno, len, false, oinfo);
     916      929152 :         error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
     917             : 
     918      929139 :         xfs_btree_del_cursor(cur, error);
     919      929139 :         return error;
     920             : }
     921             : 
     922             : /*
     923             :  * A mergeable rmap must have the same owner and the same values for
     924             :  * the unwritten, attr_fork, and bmbt flags.  The startblock and
     925             :  * offset are checked separately.
     926             :  */
     927             : static bool
     928   109678426 : xfs_rmap_is_mergeable(
     929             :         struct xfs_rmap_irec    *irec,
     930             :         uint64_t                owner,
     931             :         unsigned int            flags)
     932             : {
     933   109678426 :         if (irec->rm_owner == XFS_RMAP_OWN_NULL)
     934             :                 return false;
     935   109678426 :         if (irec->rm_owner != owner)
     936             :                 return false;
     937    56242904 :         if ((flags & XFS_RMAP_UNWRITTEN) ^
     938    56242904 :             (irec->rm_flags & XFS_RMAP_UNWRITTEN))
     939             :                 return false;
     940    54036045 :         if ((flags & XFS_RMAP_ATTR_FORK) ^
     941             :             (irec->rm_flags & XFS_RMAP_ATTR_FORK))
     942             :                 return false;
     943    54031767 :         if ((flags & XFS_RMAP_BMBT_BLOCK) ^
     944             :             (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
     945      161377 :                 return false;
     946             :         return true;
     947             : }
     948             : 
     949             : /*
     950             :  * When we allocate a new block, the first thing we do is add a reference to
     951             :  * the extent in the rmap btree. This takes the form of a [agbno, length,
     952             :  * owner, offset] record.  Flags are encoded in the high bits of the offset
     953             :  * field.
     954             :  */
     955             : STATIC int
     956    52067970 : xfs_rmap_map(
     957             :         struct xfs_btree_cur            *cur,
     958             :         xfs_agblock_t                   bno,
     959             :         xfs_extlen_t                    len,
     960             :         bool                            unwritten,
     961             :         const struct xfs_owner_info     *oinfo)
     962             : {
     963    52067970 :         struct xfs_mount                *mp = cur->bc_mp;
     964    52067970 :         struct xfs_rmap_irec            ltrec;
     965    52067970 :         struct xfs_rmap_irec            gtrec;
     966    52067970 :         int                             have_gt;
     967    52067970 :         int                             have_lt;
     968    52067970 :         int                             error = 0;
     969    52067970 :         int                             i;
     970    52067970 :         uint64_t                        owner;
     971    52067970 :         uint64_t                        offset;
     972    52067970 :         unsigned int                    flags = 0;
     973    52067970 :         bool                            ignore_off;
     974             : 
     975    52067970 :         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
     976    52067970 :         ASSERT(owner != 0);
     977    52067970 :         ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
     978    50670269 :                         (flags & XFS_RMAP_BMBT_BLOCK);
     979    52067970 :         if (unwritten)
     980    12441111 :                 flags |= XFS_RMAP_UNWRITTEN;
     981    52067970 :         trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
     982             :                         unwritten, oinfo);
     983    52068286 :         ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
     984             : 
     985             :         /*
     986             :          * For the initial lookup, look for an exact match or the left-adjacent
     987             :          * record for our insertion point. This will also give us the record for
     988             :          * start block contiguity tests.
     989             :          */
     990    52068286 :         error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &ltrec,
     991             :                         &have_lt);
     992    52068296 :         if (error)
     993         405 :                 goto out_error;
     994    52067891 :         if (have_lt) {
     995    52058308 :                 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
     996    52058308 :                                 cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
     997             :                                 ltrec.rm_blockcount, ltrec.rm_owner,
     998             :                                 ltrec.rm_offset, ltrec.rm_flags);
     999             : 
    1000    52058476 :                 if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
    1001    28539349 :                         have_lt = 0;
    1002             :         }
    1003             : 
    1004    52068059 :         if (XFS_IS_CORRUPT(mp,
    1005             :                            have_lt != 0 &&
    1006             :                            ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
    1007           0 :                 xfs_btree_mark_sick(cur);
    1008           0 :                 error = -EFSCORRUPTED;
    1009           0 :                 goto out_error;
    1010             :         }
    1011             : 
    1012             :         /*
    1013             :          * Increment the cursor to see if we have a right-adjacent record to our
    1014             :          * insertion point. This will give us the record for end block
    1015             :          * contiguity tests.
    1016             :          */
    1017    52068059 :         error = xfs_btree_increment(cur, 0, &have_gt);
    1018    52067034 :         if (error)
    1019           2 :                 goto out_error;
    1020    52067032 :         if (have_gt) {
    1021    46610730 :                 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
    1022    46611685 :                 if (error)
    1023           0 :                         goto out_error;
    1024    46611685 :                 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
    1025           0 :                         xfs_btree_mark_sick(cur);
    1026           0 :                         error = -EFSCORRUPTED;
    1027           0 :                         goto out_error;
    1028             :                 }
    1029    46611685 :                 if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
    1030           0 :                         xfs_btree_mark_sick(cur);
    1031           0 :                         error = -EFSCORRUPTED;
    1032           0 :                         goto out_error;
    1033             :                 }
    1034    46611685 :                 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
    1035    46611685 :                         cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
    1036             :                         gtrec.rm_blockcount, gtrec.rm_owner,
    1037             :                         gtrec.rm_offset, gtrec.rm_flags);
    1038    46611585 :                 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
    1039    26779906 :                         have_gt = 0;
    1040             :         }
    1041             : 
    1042             :         /*
    1043             :          * Note: cursor currently points one record to the right of ltrec, even
    1044             :          * if there is no record in the tree to the right.
    1045             :          */
    1046    52067887 :         if (have_lt &&
    1047    23519381 :             ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
    1048     4635736 :             (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
    1049             :                 /*
    1050             :                  * left edge contiguous, merge into left record.
    1051             :                  *
    1052             :                  *       ltbno     ltlen
    1053             :                  * orig:   |ooooooooo|
    1054             :                  * adding:           |aaaaaaaaa|
    1055             :                  * result: |rrrrrrrrrrrrrrrrrrr|
    1056             :                  *                  bno       len
    1057             :                  */
    1058     3767167 :                 ltrec.rm_blockcount += len;
    1059     3767167 :                 if (have_gt &&
    1060     1331402 :                     bno + len == gtrec.rm_startblock &&
    1061        6000 :                     (ignore_off || offset + len == gtrec.rm_offset) &&
    1062       37531 :                     (unsigned long)ltrec.rm_blockcount + len +
    1063       37531 :                                 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
    1064             :                         /*
    1065             :                          * right edge also contiguous, delete right record
    1066             :                          * and merge into left record.
    1067             :                          *
    1068             :                          *       ltbno     ltlen    gtbno     gtlen
    1069             :                          * orig:   |ooooooooo|         |ooooooooo|
    1070             :                          * adding:           |aaaaaaaaa|
    1071             :                          * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
    1072             :                          */
    1073       37531 :                         ltrec.rm_blockcount += gtrec.rm_blockcount;
    1074       37531 :                         trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
    1075             :                                         gtrec.rm_startblock,
    1076             :                                         gtrec.rm_blockcount,
    1077             :                                         gtrec.rm_owner,
    1078             :                                         gtrec.rm_offset,
    1079             :                                         gtrec.rm_flags);
    1080       37531 :                         error = xfs_btree_delete(cur, &i);
    1081       37531 :                         if (error)
    1082           0 :                                 goto out_error;
    1083       37531 :                         if (XFS_IS_CORRUPT(mp, i != 1)) {
    1084           0 :                                 xfs_btree_mark_sick(cur);
    1085           0 :                                 error = -EFSCORRUPTED;
    1086           0 :                                 goto out_error;
    1087             :                         }
    1088             :                 }
    1089             : 
    1090             :                 /* point the cursor back to the left record and update */
    1091     3767167 :                 error = xfs_btree_decrement(cur, 0, &have_gt);
    1092     3767161 :                 if (error)
    1093           0 :                         goto out_error;
    1094     3767161 :                 error = xfs_rmap_update(cur, &ltrec);
    1095     3767170 :                 if (error)
    1096           0 :                         goto out_error;
    1097    48300720 :         } else if (have_gt &&
    1098    18500447 :                    bno + len == gtrec.rm_startblock &&
    1099      675023 :                    (ignore_off || offset + len == gtrec.rm_offset)) {
    1100             :                 /*
    1101             :                  * right edge contiguous, merge into right record.
    1102             :                  *
    1103             :                  *                 gtbno     gtlen
    1104             :                  * Orig:             |ooooooooo|
    1105             :                  * adding: |aaaaaaaaa|
    1106             :                  * Result: |rrrrrrrrrrrrrrrrrrr|
    1107             :                  *        bno       len
    1108             :                  */
    1109       89358 :                 gtrec.rm_startblock = bno;
    1110       89358 :                 gtrec.rm_blockcount += len;
    1111       89358 :                 if (!ignore_off)
    1112        4469 :                         gtrec.rm_offset = offset;
    1113       89358 :                 error = xfs_rmap_update(cur, &gtrec);
    1114       89359 :                 if (error)
    1115           0 :                         goto out_error;
    1116             :         } else {
    1117             :                 /*
    1118             :                  * no contiguous edge with identical owner, insert
    1119             :                  * new record at current cursor position.
    1120             :                  */
    1121    48211362 :                 cur->bc_rec.r.rm_startblock = bno;
    1122    48211362 :                 cur->bc_rec.r.rm_blockcount = len;
    1123    48211362 :                 cur->bc_rec.r.rm_owner = owner;
    1124    48211362 :                 cur->bc_rec.r.rm_offset = offset;
    1125    48211362 :                 cur->bc_rec.r.rm_flags = flags;
    1126    48211362 :                 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
    1127             :                         owner, offset, flags);
    1128    48211019 :                 error = xfs_btree_insert(cur, &i);
    1129    48211423 :                 if (error)
    1130          28 :                         goto out_error;
    1131    48211395 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1132           0 :                         xfs_btree_mark_sick(cur);
    1133           0 :                         error = -EFSCORRUPTED;
    1134           0 :                         goto out_error;
    1135             :                 }
    1136             :         }
    1137             : 
    1138    52067924 :         trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
    1139             :                         unwritten, oinfo);
    1140    52068254 : out_error:
    1141    52068254 :         if (error)
    1142         435 :                 trace_xfs_rmap_map_error(mp, cur->bc_ag.pag->pag_agno,
    1143         435 :                                 error, _RET_IP_);
    1144    52068254 :         return error;
    1145             : }
    1146             : 
    1147             : /*
    1148             :  * Add a reference to an extent in the rmap btree.
    1149             :  */
    1150             : int
    1151     2152599 : xfs_rmap_alloc(
    1152             :         struct xfs_trans                *tp,
    1153             :         struct xfs_buf                  *agbp,
    1154             :         struct xfs_perag                *pag,
    1155             :         xfs_agblock_t                   bno,
    1156             :         xfs_extlen_t                    len,
    1157             :         const struct xfs_owner_info     *oinfo)
    1158             : {
    1159     2152599 :         struct xfs_mount                *mp = tp->t_mountp;
    1160     2152599 :         struct xfs_btree_cur            *cur;
    1161     2152599 :         int                             error;
    1162             : 
    1163     2152599 :         if (!xfs_has_rmapbt(mp))
    1164             :                 return 0;
    1165             : 
    1166     1745813 :         cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
    1167     1745790 :         xfs_rmap_update_hook(tp, pag, XFS_RMAP_MAP, bno, len, false, oinfo);
    1168     1745790 :         error = xfs_rmap_map(cur, bno, len, false, oinfo);
    1169             : 
    1170     1745812 :         xfs_btree_del_cursor(cur, error);
    1171     1745812 :         return error;
    1172             : }
    1173             : 
    1174             : #define RMAP_LEFT_CONTIG        (1 << 0)
    1175             : #define RMAP_RIGHT_CONTIG       (1 << 1)
    1176             : #define RMAP_LEFT_FILLING       (1 << 2)
    1177             : #define RMAP_RIGHT_FILLING      (1 << 3)
    1178             : #define RMAP_LEFT_VALID         (1 << 6)
    1179             : #define RMAP_RIGHT_VALID        (1 << 7)
    1180             : 
    1181             : #define LEFT            r[0]
    1182             : #define RIGHT           r[1]
    1183             : #define PREV            r[2]
    1184             : #define NEW             r[3]
    1185             : 
    1186             : /*
    1187             :  * Convert an unwritten extent to a real extent or vice versa.
    1188             :  * Does not handle overlapping extents.
    1189             :  */
    1190             : STATIC int
    1191     5982549 : xfs_rmap_convert(
    1192             :         struct xfs_btree_cur            *cur,
    1193             :         xfs_agblock_t                   bno,
    1194             :         xfs_extlen_t                    len,
    1195             :         bool                            unwritten,
    1196             :         const struct xfs_owner_info     *oinfo)
    1197             : {
    1198     5982549 :         struct xfs_mount                *mp = cur->bc_mp;
    1199     5982549 :         struct xfs_rmap_irec            r[4];   /* neighbor extent entries */
    1200             :                                                 /* left is 0, right is 1, */
    1201             :                                                 /* prev is 2, new is 3 */
    1202     5982549 :         uint64_t                owner;
    1203     5982549 :         uint64_t                offset;
    1204     5982549 :         uint64_t                new_endoff;
    1205     5982549 :         unsigned int            oldext;
    1206     5982549 :         unsigned int            newext;
    1207     5982549 :         unsigned int            flags = 0;
    1208     5982549 :         int                     i;
    1209     5982549 :         int                     state = 0;
    1210     5982549 :         int                     error;
    1211             : 
    1212     5982549 :         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
    1213     5982549 :         ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
    1214             :                         (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
    1215     5982549 :         oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
    1216     5982549 :         new_endoff = offset + len;
    1217     5982549 :         trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
    1218             :                         unwritten, oinfo);
    1219             : 
    1220             :         /*
    1221             :          * For the initial lookup, look for an exact match or the left-adjacent
    1222             :          * record for our insertion point. This will also give us the record for
    1223             :          * start block contiguity tests.
    1224             :          */
    1225     5982545 :         error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, &PREV, &i);
    1226     5982512 :         if (error)
    1227           0 :                 goto done;
    1228     5982512 :         if (XFS_IS_CORRUPT(mp, i != 1)) {
    1229           0 :                 xfs_btree_mark_sick(cur);
    1230           0 :                 error = -EFSCORRUPTED;
    1231           0 :                 goto done;
    1232             :         }
    1233             : 
    1234     5982512 :         trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
    1235     5982512 :                         cur->bc_ag.pag->pag_agno, PREV.rm_startblock,
    1236             :                         PREV.rm_blockcount, PREV.rm_owner,
    1237             :                         PREV.rm_offset, PREV.rm_flags);
    1238             : 
    1239     5982506 :         ASSERT(PREV.rm_offset <= offset);
    1240     5982506 :         ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
    1241     5982506 :         ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
    1242     5982506 :         newext = ~oldext & XFS_RMAP_UNWRITTEN;
    1243             : 
    1244             :         /*
    1245             :          * Set flags determining what part of the previous oldext allocation
    1246             :          * extent is being replaced by a newext allocation.
    1247             :          */
    1248     5982506 :         if (PREV.rm_offset == offset)
    1249     5771597 :                 state |= RMAP_LEFT_FILLING;
    1250     5982506 :         if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
    1251     5548841 :                 state |= RMAP_RIGHT_FILLING;
    1252             : 
    1253             :         /*
    1254             :          * Decrement the cursor to see if we have a left-adjacent record to our
    1255             :          * insertion point. This will give us the record for end block
    1256             :          * contiguity tests.
    1257             :          */
    1258     5982506 :         error = xfs_btree_decrement(cur, 0, &i);
    1259     5982536 :         if (error)
    1260           0 :                 goto done;
    1261     5982536 :         if (i) {
    1262     5982536 :                 state |= RMAP_LEFT_VALID;
    1263     5982536 :                 error = xfs_rmap_get_rec(cur, &LEFT, &i);
    1264     5982548 :                 if (error)
    1265           0 :                         goto done;
    1266     5982548 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1267           0 :                         xfs_btree_mark_sick(cur);
    1268           0 :                         error = -EFSCORRUPTED;
    1269           0 :                         goto done;
    1270             :                 }
    1271     5982548 :                 if (XFS_IS_CORRUPT(mp,
    1272             :                                    LEFT.rm_startblock + LEFT.rm_blockcount >
    1273             :                                    bno)) {
    1274           0 :                         xfs_btree_mark_sick(cur);
    1275           0 :                         error = -EFSCORRUPTED;
    1276           0 :                         goto done;
    1277             :                 }
    1278     5982548 :                 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
    1279     5982548 :                                 cur->bc_ag.pag->pag_agno, LEFT.rm_startblock,
    1280             :                                 LEFT.rm_blockcount, LEFT.rm_owner,
    1281             :                                 LEFT.rm_offset, LEFT.rm_flags);
    1282     5982545 :                 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
    1283     5567412 :                     LEFT.rm_offset + LEFT.rm_blockcount == offset &&
    1284      377525 :                     xfs_rmap_is_mergeable(&LEFT, owner, newext))
    1285      373564 :                         state |= RMAP_LEFT_CONTIG;
    1286             :         }
    1287             : 
    1288             :         /*
    1289             :          * Increment the cursor to see if we have a right-adjacent record to our
    1290             :          * insertion point. This will give us the record for end block
    1291             :          * contiguity tests.
    1292             :          */
    1293     5982545 :         error = xfs_btree_increment(cur, 0, &i);
    1294     5982545 :         if (error)
    1295           0 :                 goto done;
    1296     5982545 :         if (XFS_IS_CORRUPT(mp, i != 1)) {
    1297           0 :                 xfs_btree_mark_sick(cur);
    1298           0 :                 error = -EFSCORRUPTED;
    1299           0 :                 goto done;
    1300             :         }
    1301     5982545 :         error = xfs_btree_increment(cur, 0, &i);
    1302     5982552 :         if (error)
    1303           0 :                 goto done;
    1304     5982552 :         if (i) {
    1305     5542480 :                 state |= RMAP_RIGHT_VALID;
    1306     5542480 :                 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
    1307     5542522 :                 if (error)
    1308           0 :                         goto done;
    1309     5542522 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1310           0 :                         xfs_btree_mark_sick(cur);
    1311           0 :                         error = -EFSCORRUPTED;
    1312           0 :                         goto done;
    1313             :                 }
    1314     5542522 :                 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
    1315           0 :                         xfs_btree_mark_sick(cur);
    1316           0 :                         error = -EFSCORRUPTED;
    1317           0 :                         goto done;
    1318             :                 }
    1319     5542522 :                 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
    1320     5542522 :                                 cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
    1321             :                                 RIGHT.rm_blockcount, RIGHT.rm_owner,
    1322             :                                 RIGHT.rm_offset, RIGHT.rm_flags);
    1323     5542517 :                 if (bno + len == RIGHT.rm_startblock &&
    1324     3761454 :                     offset + len == RIGHT.rm_offset &&
    1325       73134 :                     xfs_rmap_is_mergeable(&RIGHT, owner, newext))
    1326       70560 :                         state |= RMAP_RIGHT_CONTIG;
    1327             :         }
    1328             : 
    1329             :         /* check that left + prev + right is not too long */
    1330     5982589 :         if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
    1331             :                          RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
    1332             :             (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
    1333       24640 :              RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
    1334       24640 :             (unsigned long)LEFT.rm_blockcount + len +
    1335       24640 :              RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
    1336           0 :                 state &= ~RMAP_RIGHT_CONTIG;
    1337             : 
    1338     5982542 :         trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
    1339     5982589 :                         _RET_IP_);
    1340             : 
    1341             :         /* reset the cursor back to PREV */
    1342     5982547 :         error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, NULL, &i);
    1343     5982547 :         if (error)
    1344           0 :                 goto done;
    1345     5982547 :         if (XFS_IS_CORRUPT(mp, i != 1)) {
    1346           0 :                 xfs_btree_mark_sick(cur);
    1347           0 :                 error = -EFSCORRUPTED;
    1348           0 :                 goto done;
    1349             :         }
    1350             : 
    1351             :         /*
    1352             :          * Switch out based on the FILLING and CONTIG state bits.
    1353             :          */
    1354     5982547 :         switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
    1355             :                          RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
    1356       24640 :         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
    1357             :              RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
    1358             :                 /*
    1359             :                  * Setting all of a previous oldext extent to newext.
    1360             :                  * The left and right neighbors are both contiguous with new.
    1361             :                  */
    1362       24640 :                 error = xfs_btree_increment(cur, 0, &i);
    1363       24640 :                 if (error)
    1364           0 :                         goto done;
    1365       24640 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1366           0 :                         xfs_btree_mark_sick(cur);
    1367           0 :                         error = -EFSCORRUPTED;
    1368           0 :                         goto done;
    1369             :                 }
    1370       24640 :                 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
    1371             :                                 RIGHT.rm_startblock, RIGHT.rm_blockcount,
    1372             :                                 RIGHT.rm_owner, RIGHT.rm_offset,
    1373             :                                 RIGHT.rm_flags);
    1374       24640 :                 error = xfs_btree_delete(cur, &i);
    1375       24640 :                 if (error)
    1376           0 :                         goto done;
    1377       24640 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1378           0 :                         xfs_btree_mark_sick(cur);
    1379           0 :                         error = -EFSCORRUPTED;
    1380           0 :                         goto done;
    1381             :                 }
    1382       24640 :                 error = xfs_btree_decrement(cur, 0, &i);
    1383       24640 :                 if (error)
    1384           0 :                         goto done;
    1385       24640 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1386           0 :                         xfs_btree_mark_sick(cur);
    1387           0 :                         error = -EFSCORRUPTED;
    1388           0 :                         goto done;
    1389             :                 }
    1390       24640 :                 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
    1391             :                                 PREV.rm_startblock, PREV.rm_blockcount,
    1392             :                                 PREV.rm_owner, PREV.rm_offset,
    1393             :                                 PREV.rm_flags);
    1394       24640 :                 error = xfs_btree_delete(cur, &i);
    1395       24640 :                 if (error)
    1396           0 :                         goto done;
    1397       24640 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1398           0 :                         xfs_btree_mark_sick(cur);
    1399           0 :                         error = -EFSCORRUPTED;
    1400           0 :                         goto done;
    1401             :                 }
    1402       24640 :                 error = xfs_btree_decrement(cur, 0, &i);
    1403       24640 :                 if (error)
    1404           0 :                         goto done;
    1405       24640 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1406           0 :                         xfs_btree_mark_sick(cur);
    1407           0 :                         error = -EFSCORRUPTED;
    1408           0 :                         goto done;
    1409             :                 }
    1410       24640 :                 NEW = LEFT;
    1411       24640 :                 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
    1412       24640 :                 error = xfs_rmap_update(cur, &NEW);
    1413       24640 :                 if (error)
    1414           0 :                         goto done;
    1415             :                 break;
    1416             : 
    1417      228081 :         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
    1418             :                 /*
    1419             :                  * Setting all of a previous oldext extent to newext.
    1420             :                  * The left neighbor is contiguous, the right is not.
    1421             :                  */
    1422      228081 :                 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
    1423             :                                 PREV.rm_startblock, PREV.rm_blockcount,
    1424             :                                 PREV.rm_owner, PREV.rm_offset,
    1425             :                                 PREV.rm_flags);
    1426      228081 :                 error = xfs_btree_delete(cur, &i);
    1427      228081 :                 if (error)
    1428           0 :                         goto done;
    1429      228081 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1430           0 :                         xfs_btree_mark_sick(cur);
    1431           0 :                         error = -EFSCORRUPTED;
    1432           0 :                         goto done;
    1433             :                 }
    1434      228081 :                 error = xfs_btree_decrement(cur, 0, &i);
    1435      228081 :                 if (error)
    1436           0 :                         goto done;
    1437      228081 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1438           0 :                         xfs_btree_mark_sick(cur);
    1439           0 :                         error = -EFSCORRUPTED;
    1440           0 :                         goto done;
    1441             :                 }
    1442      228081 :                 NEW = LEFT;
    1443      228081 :                 NEW.rm_blockcount += PREV.rm_blockcount;
    1444      228081 :                 error = xfs_rmap_update(cur, &NEW);
    1445      228081 :                 if (error)
    1446           0 :                         goto done;
    1447             :                 break;
    1448             : 
    1449       22137 :         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
    1450             :                 /*
    1451             :                  * Setting all of a previous oldext extent to newext.
    1452             :                  * The right neighbor is contiguous, the left is not.
    1453             :                  */
    1454       22137 :                 error = xfs_btree_increment(cur, 0, &i);
    1455       22137 :                 if (error)
    1456           0 :                         goto done;
    1457       22137 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1458           0 :                         xfs_btree_mark_sick(cur);
    1459           0 :                         error = -EFSCORRUPTED;
    1460           0 :                         goto done;
    1461             :                 }
    1462       22137 :                 trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
    1463             :                                 RIGHT.rm_startblock, RIGHT.rm_blockcount,
    1464             :                                 RIGHT.rm_owner, RIGHT.rm_offset,
    1465             :                                 RIGHT.rm_flags);
    1466       22137 :                 error = xfs_btree_delete(cur, &i);
    1467       22137 :                 if (error)
    1468           0 :                         goto done;
    1469       22137 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1470           0 :                         xfs_btree_mark_sick(cur);
    1471           0 :                         error = -EFSCORRUPTED;
    1472           0 :                         goto done;
    1473             :                 }
    1474       22137 :                 error = xfs_btree_decrement(cur, 0, &i);
    1475       22137 :                 if (error)
    1476           0 :                         goto done;
    1477       22137 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1478           0 :                         xfs_btree_mark_sick(cur);
    1479           0 :                         error = -EFSCORRUPTED;
    1480           0 :                         goto done;
    1481             :                 }
    1482       22137 :                 NEW = PREV;
    1483       22137 :                 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
    1484       22137 :                 NEW.rm_flags = newext;
    1485       22137 :                 error = xfs_rmap_update(cur, &NEW);
    1486       22137 :                 if (error)
    1487           0 :                         goto done;
    1488             :                 break;
    1489             : 
    1490     5197218 :         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
    1491             :                 /*
    1492             :                  * Setting all of a previous oldext extent to newext.
    1493             :                  * Neither the left nor right neighbors are contiguous with
    1494             :                  * the new one.
    1495             :                  */
    1496     5197218 :                 NEW = PREV;
    1497     5197218 :                 NEW.rm_flags = newext;
    1498     5197218 :                 error = xfs_rmap_update(cur, &NEW);
    1499     5197202 :                 if (error)
    1500           0 :                         goto done;
    1501             :                 break;
    1502             : 
    1503      120843 :         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
    1504             :                 /*
    1505             :                  * Setting the first part of a previous oldext extent to newext.
    1506             :                  * The left neighbor is contiguous.
    1507             :                  */
    1508      120843 :                 NEW = PREV;
    1509      120843 :                 NEW.rm_offset += len;
    1510      120843 :                 NEW.rm_startblock += len;
    1511      120843 :                 NEW.rm_blockcount -= len;
    1512      120843 :                 error = xfs_rmap_update(cur, &NEW);
    1513      120843 :                 if (error)
    1514           0 :                         goto done;
    1515      120843 :                 error = xfs_btree_decrement(cur, 0, &i);
    1516      120843 :                 if (error)
    1517           0 :                         goto done;
    1518      120843 :                 NEW = LEFT;
    1519      120843 :                 NEW.rm_blockcount += len;
    1520      120843 :                 error = xfs_rmap_update(cur, &NEW);
    1521      120843 :                 if (error)
    1522           0 :                         goto done;
    1523             :                 break;
    1524             : 
    1525      178728 :         case RMAP_LEFT_FILLING:
    1526             :                 /*
    1527             :                  * Setting the first part of a previous oldext extent to newext.
    1528             :                  * The left neighbor is not contiguous.
    1529             :                  */
    1530      178728 :                 NEW = PREV;
    1531      178728 :                 NEW.rm_startblock += len;
    1532      178728 :                 NEW.rm_offset += len;
    1533      178728 :                 NEW.rm_blockcount -= len;
    1534      178728 :                 error = xfs_rmap_update(cur, &NEW);
    1535      178728 :                 if (error)
    1536           0 :                         goto done;
    1537      178728 :                 NEW.rm_startblock = bno;
    1538      178728 :                 NEW.rm_owner = owner;
    1539      178728 :                 NEW.rm_offset = offset;
    1540      178728 :                 NEW.rm_blockcount = len;
    1541      178728 :                 NEW.rm_flags = newext;
    1542      178728 :                 cur->bc_rec.r = NEW;
    1543      178728 :                 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
    1544             :                                 len, owner, offset, newext);
    1545      178728 :                 error = xfs_btree_insert(cur, &i);
    1546      178727 :                 if (error)
    1547           0 :                         goto done;
    1548      178727 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1549           0 :                         xfs_btree_mark_sick(cur);
    1550           0 :                         error = -EFSCORRUPTED;
    1551           0 :                         goto done;
    1552             :                 }
    1553             :                 break;
    1554             : 
    1555       23783 :         case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
    1556             :                 /*
    1557             :                  * Setting the last part of a previous oldext extent to newext.
    1558             :                  * The right neighbor is contiguous with the new allocation.
    1559             :                  */
    1560       23783 :                 NEW = PREV;
    1561       23783 :                 NEW.rm_blockcount -= len;
    1562       23783 :                 error = xfs_rmap_update(cur, &NEW);
    1563       23783 :                 if (error)
    1564           0 :                         goto done;
    1565       23783 :                 error = xfs_btree_increment(cur, 0, &i);
    1566       23783 :                 if (error)
    1567           0 :                         goto done;
    1568       23783 :                 NEW = RIGHT;
    1569       23783 :                 NEW.rm_offset = offset;
    1570       23783 :                 NEW.rm_startblock = bno;
    1571       23783 :                 NEW.rm_blockcount += len;
    1572       23783 :                 error = xfs_rmap_update(cur, &NEW);
    1573       23783 :                 if (error)
    1574           0 :                         goto done;
    1575             :                 break;
    1576             : 
    1577       53019 :         case RMAP_RIGHT_FILLING:
    1578             :                 /*
    1579             :                  * Setting the last part of a previous oldext extent to newext.
    1580             :                  * The right neighbor is not contiguous.
    1581             :                  */
    1582       53019 :                 NEW = PREV;
    1583       53019 :                 NEW.rm_blockcount -= len;
    1584       53019 :                 error = xfs_rmap_update(cur, &NEW);
    1585       53019 :                 if (error)
    1586           0 :                         goto done;
    1587       53019 :                 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
    1588             :                                 oldext, &i);
    1589       53019 :                 if (error)
    1590           0 :                         goto done;
    1591       53019 :                 if (XFS_IS_CORRUPT(mp, i != 0)) {
    1592           0 :                         xfs_btree_mark_sick(cur);
    1593           0 :                         error = -EFSCORRUPTED;
    1594           0 :                         goto done;
    1595             :                 }
    1596       53019 :                 NEW.rm_startblock = bno;
    1597       53019 :                 NEW.rm_owner = owner;
    1598       53019 :                 NEW.rm_offset = offset;
    1599       53019 :                 NEW.rm_blockcount = len;
    1600       53019 :                 NEW.rm_flags = newext;
    1601       53019 :                 cur->bc_rec.r = NEW;
    1602       53019 :                 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
    1603             :                                 len, owner, offset, newext);
    1604       53019 :                 error = xfs_btree_insert(cur, &i);
    1605       53019 :                 if (error)
    1606           0 :                         goto done;
    1607       53019 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1608           0 :                         xfs_btree_mark_sick(cur);
    1609           0 :                         error = -EFSCORRUPTED;
    1610           0 :                         goto done;
    1611             :                 }
    1612             :                 break;
    1613             : 
    1614      134098 :         case 0:
    1615             :                 /*
    1616             :                  * Setting the middle part of a previous oldext extent to
    1617             :                  * newext.  Contiguity is impossible here.
    1618             :                  * One extent becomes three extents.
    1619             :                  */
    1620             :                 /* new right extent - oldext */
    1621      134098 :                 NEW.rm_startblock = bno + len;
    1622      134098 :                 NEW.rm_owner = owner;
    1623      134098 :                 NEW.rm_offset = new_endoff;
    1624      134098 :                 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
    1625             :                                 new_endoff;
    1626      134098 :                 NEW.rm_flags = PREV.rm_flags;
    1627      134098 :                 error = xfs_rmap_update(cur, &NEW);
    1628      134098 :                 if (error)
    1629           0 :                         goto done;
    1630             :                 /* new left extent - oldext */
    1631      134098 :                 NEW = PREV;
    1632      134098 :                 NEW.rm_blockcount = offset - PREV.rm_offset;
    1633      134098 :                 cur->bc_rec.r = NEW;
    1634      134098 :                 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
    1635             :                                 NEW.rm_startblock, NEW.rm_blockcount,
    1636             :                                 NEW.rm_owner, NEW.rm_offset,
    1637             :                                 NEW.rm_flags);
    1638      134098 :                 error = xfs_btree_insert(cur, &i);
    1639      134098 :                 if (error)
    1640           0 :                         goto done;
    1641      134098 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1642           0 :                         xfs_btree_mark_sick(cur);
    1643           0 :                         error = -EFSCORRUPTED;
    1644           0 :                         goto done;
    1645             :                 }
    1646             :                 /*
    1647             :                  * Reset the cursor to the position of the new extent
    1648             :                  * we are about to insert as we can't trust it after
    1649             :                  * the previous insert.
    1650             :                  */
    1651      134098 :                 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
    1652             :                                 oldext, &i);
    1653      134098 :                 if (error)
    1654           0 :                         goto done;
    1655      134098 :                 if (XFS_IS_CORRUPT(mp, i != 0)) {
    1656           0 :                         xfs_btree_mark_sick(cur);
    1657           0 :                         error = -EFSCORRUPTED;
    1658           0 :                         goto done;
    1659             :                 }
    1660             :                 /* new middle extent - newext */
    1661      134098 :                 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
    1662      134098 :                 cur->bc_rec.r.rm_flags |= newext;
    1663      134098 :                 trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
    1664             :                                 owner, offset, newext);
    1665      134098 :                 error = xfs_btree_insert(cur, &i);
    1666      134098 :                 if (error)
    1667           0 :                         goto done;
    1668      134098 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1669           0 :                         xfs_btree_mark_sick(cur);
    1670           0 :                         error = -EFSCORRUPTED;
    1671           0 :                         goto done;
    1672             :                 }
    1673             :                 break;
    1674             : 
    1675           0 :         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
    1676             :         case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
    1677             :         case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
    1678             :         case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
    1679             :         case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
    1680             :         case RMAP_LEFT_CONTIG:
    1681             :         case RMAP_RIGHT_CONTIG:
    1682             :                 /*
    1683             :                  * These cases are all impossible.
    1684             :                  */
    1685           0 :                 ASSERT(0);
    1686             :         }
    1687             : 
    1688     5982530 :         trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
    1689             :                         unwritten, oinfo);
    1690     5982521 : done:
    1691     5982521 :         if (error)
    1692           0 :                 trace_xfs_rmap_convert_error(cur->bc_mp,
    1693           0 :                                 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
    1694     5982521 :         return error;
    1695             : }
    1696             : 
    1697             : /*
    1698             :  * Convert an unwritten extent to a real extent or vice versa.  If there is no
    1699             :  * possibility of overlapping extents, delegate to the simpler convert
    1700             :  * function.
    1701             :  */
    1702             : STATIC int
    1703    12368541 : xfs_rmap_convert_shared(
    1704             :         struct xfs_btree_cur            *cur,
    1705             :         xfs_agblock_t                   bno,
    1706             :         xfs_extlen_t                    len,
    1707             :         bool                            unwritten,
    1708             :         const struct xfs_owner_info     *oinfo)
    1709             : {
    1710    12368541 :         struct xfs_mount                *mp = cur->bc_mp;
    1711    12368541 :         struct xfs_rmap_irec            r[4];   /* neighbor extent entries */
    1712             :                                                 /* left is 0, right is 1, */
    1713             :                                                 /* prev is 2, new is 3 */
    1714    12368541 :         uint64_t                owner;
    1715    12368541 :         uint64_t                offset;
    1716    12368541 :         uint64_t                new_endoff;
    1717    12368541 :         unsigned int            oldext;
    1718    12368541 :         unsigned int            newext;
    1719    12368541 :         unsigned int            flags = 0;
    1720    12368541 :         int                     i;
    1721    12368541 :         int                     state = 0;
    1722    12368541 :         int                     error;
    1723             : 
    1724    12368541 :         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
    1725    12368541 :         ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
    1726             :                         (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
    1727    12368541 :         oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
    1728    12368541 :         new_endoff = offset + len;
    1729    12368541 :         trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
    1730             :                         unwritten, oinfo);
    1731             : 
    1732             :         /*
    1733             :          * For the initial lookup, look for and exact match or the left-adjacent
    1734             :          * record for our insertion point. This will also give us the record for
    1735             :          * start block contiguity tests.
    1736             :          */
    1737    12368541 :         error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
    1738             :                         &PREV, &i);
    1739    12368534 :         if (error)
    1740           2 :                 goto done;
    1741    12368532 :         if (XFS_IS_CORRUPT(mp, i != 1)) {
    1742           0 :                 xfs_btree_mark_sick(cur);
    1743           0 :                 error = -EFSCORRUPTED;
    1744           0 :                 goto done;
    1745             :         }
    1746             : 
    1747    12368532 :         ASSERT(PREV.rm_offset <= offset);
    1748    12368532 :         ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
    1749    12368532 :         ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
    1750    12368532 :         newext = ~oldext & XFS_RMAP_UNWRITTEN;
    1751             : 
    1752             :         /*
    1753             :          * Set flags determining what part of the previous oldext allocation
    1754             :          * extent is being replaced by a newext allocation.
    1755             :          */
    1756    12368532 :         if (PREV.rm_offset == offset)
    1757    12014317 :                 state |= RMAP_LEFT_FILLING;
    1758    12368532 :         if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
    1759    10034426 :                 state |= RMAP_RIGHT_FILLING;
    1760             : 
    1761             :         /* Is there a left record that abuts our range? */
    1762    12368532 :         error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
    1763             :                         &LEFT, &i);
    1764    12368540 :         if (error)
    1765           0 :                 goto done;
    1766    12368540 :         if (i) {
    1767      249249 :                 state |= RMAP_LEFT_VALID;
    1768      249249 :                 if (XFS_IS_CORRUPT(mp,
    1769             :                                    LEFT.rm_startblock + LEFT.rm_blockcount >
    1770             :                                    bno)) {
    1771           0 :                         xfs_btree_mark_sick(cur);
    1772           0 :                         error = -EFSCORRUPTED;
    1773           0 :                         goto done;
    1774             :                 }
    1775      249249 :                 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
    1776      249248 :                         state |= RMAP_LEFT_CONTIG;
    1777             :         }
    1778             : 
    1779             :         /* Is there a right record that abuts our range? */
    1780    12368540 :         error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
    1781             :                         newext, &i);
    1782    12368540 :         if (error)
    1783           0 :                 goto done;
    1784    12368540 :         if (i) {
    1785      126831 :                 state |= RMAP_RIGHT_VALID;
    1786      126831 :                 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
    1787      126831 :                 if (error)
    1788           0 :                         goto done;
    1789      126831 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1790           0 :                         xfs_btree_mark_sick(cur);
    1791           0 :                         error = -EFSCORRUPTED;
    1792           0 :                         goto done;
    1793             :                 }
    1794      126831 :                 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
    1795           0 :                         xfs_btree_mark_sick(cur);
    1796           0 :                         error = -EFSCORRUPTED;
    1797           0 :                         goto done;
    1798             :                 }
    1799      126831 :                 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
    1800      126831 :                                 cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
    1801             :                                 RIGHT.rm_blockcount, RIGHT.rm_owner,
    1802             :                                 RIGHT.rm_offset, RIGHT.rm_flags);
    1803      126831 :                 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
    1804      126831 :                         state |= RMAP_RIGHT_CONTIG;
    1805             :         }
    1806             : 
    1807             :         /* check that left + prev + right is not too long */
    1808    12368540 :         if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
    1809             :                          RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
    1810             :             (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
    1811       26057 :              RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
    1812       26057 :             (unsigned long)LEFT.rm_blockcount + len +
    1813       26057 :              RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
    1814           0 :                 state &= ~RMAP_RIGHT_CONTIG;
    1815             : 
    1816    12368540 :         trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
    1817    12368540 :                         _RET_IP_);
    1818             :         /*
    1819             :          * Switch out based on the FILLING and CONTIG state bits.
    1820             :          */
    1821    12368540 :         switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
    1822             :                          RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
    1823       26057 :         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
    1824             :              RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
    1825             :                 /*
    1826             :                  * Setting all of a previous oldext extent to newext.
    1827             :                  * The left and right neighbors are both contiguous with new.
    1828             :                  */
    1829       26057 :                 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
    1830             :                                 RIGHT.rm_blockcount, RIGHT.rm_owner,
    1831             :                                 RIGHT.rm_offset, RIGHT.rm_flags);
    1832       26057 :                 if (error)
    1833           0 :                         goto done;
    1834       26057 :                 error = xfs_rmap_delete(cur, PREV.rm_startblock,
    1835             :                                 PREV.rm_blockcount, PREV.rm_owner,
    1836             :                                 PREV.rm_offset, PREV.rm_flags);
    1837       26057 :                 if (error)
    1838           0 :                         goto done;
    1839       26057 :                 NEW = LEFT;
    1840       26057 :                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
    1841             :                                 NEW.rm_blockcount, NEW.rm_owner,
    1842             :                                 NEW.rm_offset, NEW.rm_flags, &i);
    1843       26057 :                 if (error)
    1844           0 :                         goto done;
    1845       26057 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1846           0 :                         xfs_btree_mark_sick(cur);
    1847           0 :                         error = -EFSCORRUPTED;
    1848           0 :                         goto done;
    1849             :                 }
    1850       26057 :                 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
    1851       26057 :                 error = xfs_rmap_update(cur, &NEW);
    1852       26057 :                 if (error)
    1853           0 :                         goto done;
    1854             :                 break;
    1855             : 
    1856      171369 :         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
    1857             :                 /*
    1858             :                  * Setting all of a previous oldext extent to newext.
    1859             :                  * The left neighbor is contiguous, the right is not.
    1860             :                  */
    1861      171369 :                 error = xfs_rmap_delete(cur, PREV.rm_startblock,
    1862             :                                 PREV.rm_blockcount, PREV.rm_owner,
    1863             :                                 PREV.rm_offset, PREV.rm_flags);
    1864      171369 :                 if (error)
    1865           0 :                         goto done;
    1866      171369 :                 NEW = LEFT;
    1867      171369 :                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
    1868             :                                 NEW.rm_blockcount, NEW.rm_owner,
    1869             :                                 NEW.rm_offset, NEW.rm_flags, &i);
    1870      171369 :                 if (error)
    1871           0 :                         goto done;
    1872      171369 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1873           0 :                         xfs_btree_mark_sick(cur);
    1874           0 :                         error = -EFSCORRUPTED;
    1875           0 :                         goto done;
    1876             :                 }
    1877      171369 :                 NEW.rm_blockcount += PREV.rm_blockcount;
    1878      171369 :                 error = xfs_rmap_update(cur, &NEW);
    1879      171369 :                 if (error)
    1880           0 :                         goto done;
    1881             :                 break;
    1882             : 
    1883       89397 :         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
    1884             :                 /*
    1885             :                  * Setting all of a previous oldext extent to newext.
    1886             :                  * The right neighbor is contiguous, the left is not.
    1887             :                  */
    1888       89397 :                 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
    1889             :                                 RIGHT.rm_blockcount, RIGHT.rm_owner,
    1890             :                                 RIGHT.rm_offset, RIGHT.rm_flags);
    1891       89397 :                 if (error)
    1892           0 :                         goto done;
    1893       89397 :                 NEW = PREV;
    1894       89397 :                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
    1895             :                                 NEW.rm_blockcount, NEW.rm_owner,
    1896             :                                 NEW.rm_offset, NEW.rm_flags, &i);
    1897       89397 :                 if (error)
    1898           0 :                         goto done;
    1899       89397 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1900           0 :                         xfs_btree_mark_sick(cur);
    1901           0 :                         error = -EFSCORRUPTED;
    1902           0 :                         goto done;
    1903             :                 }
    1904       89397 :                 NEW.rm_blockcount += RIGHT.rm_blockcount;
    1905       89397 :                 NEW.rm_flags = RIGHT.rm_flags;
    1906       89397 :                 error = xfs_rmap_update(cur, &NEW);
    1907       89397 :                 if (error)
    1908           0 :                         goto done;
    1909             :                 break;
    1910             : 
    1911     9561049 :         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
    1912             :                 /*
    1913             :                  * Setting all of a previous oldext extent to newext.
    1914             :                  * Neither the left nor right neighbors are contiguous with
    1915             :                  * the new one.
    1916             :                  */
    1917     9561049 :                 NEW = PREV;
    1918     9561049 :                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
    1919             :                                 NEW.rm_blockcount, NEW.rm_owner,
    1920             :                                 NEW.rm_offset, NEW.rm_flags, &i);
    1921     9561049 :                 if (error)
    1922           0 :                         goto done;
    1923     9561049 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1924           0 :                         xfs_btree_mark_sick(cur);
    1925           0 :                         error = -EFSCORRUPTED;
    1926           0 :                         goto done;
    1927             :                 }
    1928     9561049 :                 NEW.rm_flags = newext;
    1929     9561049 :                 error = xfs_rmap_update(cur, &NEW);
    1930     9561048 :                 if (error)
    1931           0 :                         goto done;
    1932             :                 break;
    1933             : 
    1934       51822 :         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
    1935             :                 /*
    1936             :                  * Setting the first part of a previous oldext extent to newext.
    1937             :                  * The left neighbor is contiguous.
    1938             :                  */
    1939       51822 :                 NEW = PREV;
    1940       51822 :                 error = xfs_rmap_delete(cur, NEW.rm_startblock,
    1941             :                                 NEW.rm_blockcount, NEW.rm_owner,
    1942             :                                 NEW.rm_offset, NEW.rm_flags);
    1943       51822 :                 if (error)
    1944           0 :                         goto done;
    1945       51822 :                 NEW.rm_offset += len;
    1946       51822 :                 NEW.rm_startblock += len;
    1947       51822 :                 NEW.rm_blockcount -= len;
    1948       51822 :                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
    1949             :                                 NEW.rm_blockcount, NEW.rm_owner,
    1950             :                                 NEW.rm_offset, NEW.rm_flags);
    1951       51822 :                 if (error)
    1952           0 :                         goto done;
    1953       51822 :                 NEW = LEFT;
    1954       51822 :                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
    1955             :                                 NEW.rm_blockcount, NEW.rm_owner,
    1956             :                                 NEW.rm_offset, NEW.rm_flags, &i);
    1957       51822 :                 if (error)
    1958           0 :                         goto done;
    1959       51822 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    1960           0 :                         xfs_btree_mark_sick(cur);
    1961           0 :                         error = -EFSCORRUPTED;
    1962           0 :                         goto done;
    1963             :                 }
    1964       51822 :                 NEW.rm_blockcount += len;
    1965       51822 :                 error = xfs_rmap_update(cur, &NEW);
    1966       51822 :                 if (error)
    1967           0 :                         goto done;
    1968             :                 break;
    1969             : 
    1970     2114624 :         case RMAP_LEFT_FILLING:
    1971             :                 /*
    1972             :                  * Setting the first part of a previous oldext extent to newext.
    1973             :                  * The left neighbor is not contiguous.
    1974             :                  */
    1975     2114624 :                 NEW = PREV;
    1976     2114624 :                 error = xfs_rmap_delete(cur, NEW.rm_startblock,
    1977             :                                 NEW.rm_blockcount, NEW.rm_owner,
    1978             :                                 NEW.rm_offset, NEW.rm_flags);
    1979     2114624 :                 if (error)
    1980           0 :                         goto done;
    1981     2114624 :                 NEW.rm_offset += len;
    1982     2114624 :                 NEW.rm_startblock += len;
    1983     2114624 :                 NEW.rm_blockcount -= len;
    1984     2114624 :                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
    1985             :                                 NEW.rm_blockcount, NEW.rm_owner,
    1986             :                                 NEW.rm_offset, NEW.rm_flags);
    1987     2114624 :                 if (error)
    1988           0 :                         goto done;
    1989     2114624 :                 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
    1990     2114624 :                 if (error)
    1991           0 :                         goto done;
    1992             :                 break;
    1993             : 
    1994       11377 :         case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
    1995             :                 /*
    1996             :                  * Setting the last part of a previous oldext extent to newext.
    1997             :                  * The right neighbor is contiguous with the new allocation.
    1998             :                  */
    1999       11377 :                 NEW = PREV;
    2000       11377 :                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
    2001             :                                 NEW.rm_blockcount, NEW.rm_owner,
    2002             :                                 NEW.rm_offset, NEW.rm_flags, &i);
    2003       11377 :                 if (error)
    2004           0 :                         goto done;
    2005       11377 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    2006           0 :                         xfs_btree_mark_sick(cur);
    2007           0 :                         error = -EFSCORRUPTED;
    2008           0 :                         goto done;
    2009             :                 }
    2010       11377 :                 NEW.rm_blockcount = offset - NEW.rm_offset;
    2011       11377 :                 error = xfs_rmap_update(cur, &NEW);
    2012       11377 :                 if (error)
    2013           0 :                         goto done;
    2014       11377 :                 NEW = RIGHT;
    2015       11377 :                 error = xfs_rmap_delete(cur, NEW.rm_startblock,
    2016             :                                 NEW.rm_blockcount, NEW.rm_owner,
    2017             :                                 NEW.rm_offset, NEW.rm_flags);
    2018       11377 :                 if (error)
    2019           0 :                         goto done;
    2020       11377 :                 NEW.rm_offset = offset;
    2021       11377 :                 NEW.rm_startblock = bno;
    2022       11377 :                 NEW.rm_blockcount += len;
    2023       11377 :                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
    2024             :                                 NEW.rm_blockcount, NEW.rm_owner,
    2025             :                                 NEW.rm_offset, NEW.rm_flags);
    2026       11377 :                 if (error)
    2027           0 :                         goto done;
    2028             :                 break;
    2029             : 
    2030      175177 :         case RMAP_RIGHT_FILLING:
    2031             :                 /*
    2032             :                  * Setting the last part of a previous oldext extent to newext.
    2033             :                  * The right neighbor is not contiguous.
    2034             :                  */
    2035      175177 :                 NEW = PREV;
    2036      175177 :                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
    2037             :                                 NEW.rm_blockcount, NEW.rm_owner,
    2038             :                                 NEW.rm_offset, NEW.rm_flags, &i);
    2039      175177 :                 if (error)
    2040           0 :                         goto done;
    2041      175177 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    2042           0 :                         xfs_btree_mark_sick(cur);
    2043           0 :                         error = -EFSCORRUPTED;
    2044           0 :                         goto done;
    2045             :                 }
    2046      175177 :                 NEW.rm_blockcount -= len;
    2047      175177 :                 error = xfs_rmap_update(cur, &NEW);
    2048      175177 :                 if (error)
    2049           0 :                         goto done;
    2050      175177 :                 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
    2051      175177 :                 if (error)
    2052           0 :                         goto done;
    2053             :                 break;
    2054             : 
    2055      167668 :         case 0:
    2056             :                 /*
    2057             :                  * Setting the middle part of a previous oldext extent to
    2058             :                  * newext.  Contiguity is impossible here.
    2059             :                  * One extent becomes three extents.
    2060             :                  */
    2061             :                 /* new right extent - oldext */
    2062      167668 :                 NEW.rm_startblock = bno + len;
    2063      167668 :                 NEW.rm_owner = owner;
    2064      167668 :                 NEW.rm_offset = new_endoff;
    2065      167668 :                 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
    2066             :                                 new_endoff;
    2067      167668 :                 NEW.rm_flags = PREV.rm_flags;
    2068      167668 :                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
    2069             :                                 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
    2070             :                                 NEW.rm_flags);
    2071      167668 :                 if (error)
    2072           0 :                         goto done;
    2073             :                 /* new left extent - oldext */
    2074      167668 :                 NEW = PREV;
    2075      167668 :                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
    2076             :                                 NEW.rm_blockcount, NEW.rm_owner,
    2077             :                                 NEW.rm_offset, NEW.rm_flags, &i);
    2078      167668 :                 if (error)
    2079           0 :                         goto done;
    2080      167668 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    2081           0 :                         xfs_btree_mark_sick(cur);
    2082           0 :                         error = -EFSCORRUPTED;
    2083           0 :                         goto done;
    2084             :                 }
    2085      167668 :                 NEW.rm_blockcount = offset - NEW.rm_offset;
    2086      167668 :                 error = xfs_rmap_update(cur, &NEW);
    2087      167668 :                 if (error)
    2088           0 :                         goto done;
    2089             :                 /* new middle extent - newext */
    2090      167668 :                 NEW.rm_startblock = bno;
    2091      167668 :                 NEW.rm_blockcount = len;
    2092      167668 :                 NEW.rm_owner = owner;
    2093      167668 :                 NEW.rm_offset = offset;
    2094      167668 :                 NEW.rm_flags = newext;
    2095      167668 :                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
    2096             :                                 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
    2097             :                                 NEW.rm_flags);
    2098      167668 :                 if (error)
    2099           0 :                         goto done;
    2100             :                 break;
    2101             : 
    2102           0 :         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
    2103             :         case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
    2104             :         case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
    2105             :         case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
    2106             :         case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
    2107             :         case RMAP_LEFT_CONTIG:
    2108             :         case RMAP_RIGHT_CONTIG:
    2109             :                 /*
    2110             :                  * These cases are all impossible.
    2111             :                  */
    2112           0 :                 ASSERT(0);
    2113             :         }
    2114             : 
    2115    12368539 :         trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
    2116             :                         unwritten, oinfo);
    2117    12368541 : done:
    2118    12368541 :         if (error)
    2119           2 :                 trace_xfs_rmap_convert_error(cur->bc_mp,
    2120           2 :                                 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
    2121    12368541 :         return error;
    2122             : }
    2123             : 
    2124             : #undef  NEW
    2125             : #undef  LEFT
    2126             : #undef  RIGHT
    2127             : #undef  PREV
    2128             : 
    2129             : /*
    2130             :  * Find an extent in the rmap btree and unmap it.  For rmap extent types that
    2131             :  * can overlap (data fork rmaps on reflink filesystems) we must be careful
    2132             :  * that the prev/next records in the btree might belong to another owner.
    2133             :  * Therefore we must use delete+insert to alter any of the key fields.
    2134             :  *
    2135             :  * For every other situation there can only be one owner for a given extent,
    2136             :  * so we can call the regular _free function.
    2137             :  */
    2138             : STATIC int
    2139    57341005 : xfs_rmap_unmap_shared(
    2140             :         struct xfs_btree_cur            *cur,
    2141             :         xfs_agblock_t                   bno,
    2142             :         xfs_extlen_t                    len,
    2143             :         bool                            unwritten,
    2144             :         const struct xfs_owner_info     *oinfo)
    2145             : {
    2146    57341005 :         struct xfs_mount                *mp = cur->bc_mp;
    2147    57341005 :         struct xfs_rmap_irec            ltrec;
    2148    57341005 :         uint64_t                        ltoff;
    2149    57341005 :         int                             error = 0;
    2150    57341005 :         int                             i;
    2151    57341005 :         uint64_t                        owner;
    2152    57341005 :         uint64_t                        offset;
    2153    57341005 :         unsigned int                    flags;
    2154             : 
    2155    57341005 :         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
    2156    57341005 :         if (unwritten)
    2157     6062565 :                 flags |= XFS_RMAP_UNWRITTEN;
    2158    57341005 :         trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
    2159             :                         unwritten, oinfo);
    2160             : 
    2161             :         /*
    2162             :          * We should always have a left record because there's a static record
    2163             :          * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
    2164             :          * will not ever be removed from the tree.
    2165             :          */
    2166    57341062 :         error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
    2167             :                         &ltrec, &i);
    2168    57341051 :         if (error)
    2169         285 :                 goto out_error;
    2170    57340766 :         if (XFS_IS_CORRUPT(mp, i != 1)) {
    2171           0 :                 xfs_btree_mark_sick(cur);
    2172           0 :                 error = -EFSCORRUPTED;
    2173           0 :                 goto out_error;
    2174             :         }
    2175    57340766 :         ltoff = ltrec.rm_offset;
    2176             : 
    2177             :         /* Make sure the extent we found covers the entire freeing range. */
    2178    57340766 :         if (XFS_IS_CORRUPT(mp,
    2179             :                            ltrec.rm_startblock > bno ||
    2180             :                            ltrec.rm_startblock + ltrec.rm_blockcount <
    2181             :                            bno + len)) {
    2182           0 :                 xfs_btree_mark_sick(cur);
    2183           0 :                 error = -EFSCORRUPTED;
    2184           0 :                 goto out_error;
    2185             :         }
    2186             : 
    2187             :         /* Make sure the owner matches what we expect to find in the tree. */
    2188    57340766 :         if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
    2189           0 :                 xfs_btree_mark_sick(cur);
    2190           0 :                 error = -EFSCORRUPTED;
    2191           0 :                 goto out_error;
    2192             :         }
    2193             : 
    2194             :         /* Make sure the unwritten flag matches. */
    2195    57340766 :         if (XFS_IS_CORRUPT(mp,
    2196             :                            (flags & XFS_RMAP_UNWRITTEN) !=
    2197             :                            (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
    2198           0 :                 xfs_btree_mark_sick(cur);
    2199           0 :                 error = -EFSCORRUPTED;
    2200           0 :                 goto out_error;
    2201             :         }
    2202             : 
    2203             :         /* Check the offset. */
    2204    57340766 :         if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
    2205           0 :                 xfs_btree_mark_sick(cur);
    2206           0 :                 error = -EFSCORRUPTED;
    2207           0 :                 goto out_error;
    2208             :         }
    2209    57340766 :         if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
    2210           0 :                 xfs_btree_mark_sick(cur);
    2211           0 :                 error = -EFSCORRUPTED;
    2212           0 :                 goto out_error;
    2213             :         }
    2214             : 
    2215    57340766 :         if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
    2216             :                 /* Exact match, simply remove the record from rmap tree. */
    2217    50425565 :                 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
    2218             :                                 ltrec.rm_blockcount, ltrec.rm_owner,
    2219             :                                 ltrec.rm_offset, ltrec.rm_flags);
    2220    50425562 :                 if (error)
    2221           0 :                         goto out_error;
    2222     6915201 :         } else if (ltrec.rm_startblock == bno) {
    2223             :                 /*
    2224             :                  * Overlap left hand side of extent: move the start, trim the
    2225             :                  * length and update the current record.
    2226             :                  *
    2227             :                  *       ltbno                ltlen
    2228             :                  * Orig:    |oooooooooooooooooooo|
    2229             :                  * Freeing: |fffffffff|
    2230             :                  * Result:            |rrrrrrrrrr|
    2231             :                  *         bno       len
    2232             :                  */
    2233             : 
    2234             :                 /* Delete prev rmap. */
    2235     1782170 :                 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
    2236             :                                 ltrec.rm_blockcount, ltrec.rm_owner,
    2237             :                                 ltrec.rm_offset, ltrec.rm_flags);
    2238     1782171 :                 if (error)
    2239           0 :                         goto out_error;
    2240             : 
    2241             :                 /* Add an rmap at the new offset. */
    2242     1782171 :                 ltrec.rm_startblock += len;
    2243     1782171 :                 ltrec.rm_blockcount -= len;
    2244     1782171 :                 ltrec.rm_offset += len;
    2245     1782171 :                 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
    2246             :                                 ltrec.rm_blockcount, ltrec.rm_owner,
    2247             :                                 ltrec.rm_offset, ltrec.rm_flags);
    2248     1782170 :                 if (error)
    2249           0 :                         goto out_error;
    2250     5133031 :         } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
    2251             :                 /*
    2252             :                  * Overlap right hand side of extent: trim the length and
    2253             :                  * update the current record.
    2254             :                  *
    2255             :                  *       ltbno                ltlen
    2256             :                  * Orig:    |oooooooooooooooooooo|
    2257             :                  * Freeing:            |fffffffff|
    2258             :                  * Result:  |rrrrrrrrrr|
    2259             :                  *                    bno       len
    2260             :                  */
    2261     1110564 :                 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
    2262             :                                 ltrec.rm_blockcount, ltrec.rm_owner,
    2263             :                                 ltrec.rm_offset, ltrec.rm_flags, &i);
    2264     1110565 :                 if (error)
    2265           0 :                         goto out_error;
    2266     1110565 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    2267           0 :                         xfs_btree_mark_sick(cur);
    2268           0 :                         error = -EFSCORRUPTED;
    2269           0 :                         goto out_error;
    2270             :                 }
    2271     1110565 :                 ltrec.rm_blockcount -= len;
    2272     1110565 :                 error = xfs_rmap_update(cur, &ltrec);
    2273     1110565 :                 if (error)
    2274           0 :                         goto out_error;
    2275             :         } else {
    2276             :                 /*
    2277             :                  * Overlap middle of extent: trim the length of the existing
    2278             :                  * record to the length of the new left-extent size, increment
    2279             :                  * the insertion position so we can insert a new record
    2280             :                  * containing the remaining right-extent space.
    2281             :                  *
    2282             :                  *       ltbno                ltlen
    2283             :                  * Orig:    |oooooooooooooooooooo|
    2284             :                  * Freeing:       |fffffffff|
    2285             :                  * Result:  |rrrrr|         |rrrr|
    2286             :                  *               bno       len
    2287             :                  */
    2288     4022467 :                 xfs_extlen_t    orig_len = ltrec.rm_blockcount;
    2289             : 
    2290             :                 /* Shrink the left side of the rmap */
    2291     4022467 :                 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
    2292             :                                 ltrec.rm_blockcount, ltrec.rm_owner,
    2293             :                                 ltrec.rm_offset, ltrec.rm_flags, &i);
    2294     4022471 :                 if (error)
    2295           0 :                         goto out_error;
    2296     4022471 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    2297           0 :                         xfs_btree_mark_sick(cur);
    2298           0 :                         error = -EFSCORRUPTED;
    2299           0 :                         goto out_error;
    2300             :                 }
    2301     4022471 :                 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
    2302     4022471 :                 error = xfs_rmap_update(cur, &ltrec);
    2303     4022467 :                 if (error)
    2304           0 :                         goto out_error;
    2305             : 
    2306             :                 /* Add an rmap at the new offset */
    2307     4022467 :                 error = xfs_rmap_insert(cur, bno + len,
    2308     4022467 :                                 orig_len - len - ltrec.rm_blockcount,
    2309             :                                 ltrec.rm_owner, offset + len,
    2310             :                                 ltrec.rm_flags);
    2311     4022470 :                 if (error)
    2312           0 :                         goto out_error;
    2313             :         }
    2314             : 
    2315    57340767 :         trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
    2316             :                         unwritten, oinfo);
    2317    57341019 : out_error:
    2318    57341019 :         if (error)
    2319         285 :                 trace_xfs_rmap_unmap_error(cur->bc_mp,
    2320         285 :                                 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
    2321    57341019 :         return error;
    2322             : }
    2323             : 
    2324             : /*
    2325             :  * Find an extent in the rmap btree and map it.  For rmap extent types that
    2326             :  * can overlap (data fork rmaps on reflink filesystems) we must be careful
    2327             :  * that the prev/next records in the btree might belong to another owner.
    2328             :  * Therefore we must use delete+insert to alter any of the key fields.
    2329             :  *
    2330             :  * For every other situation there can only be one owner for a given extent,
    2331             :  * so we can call the regular _alloc function.
    2332             :  */
    2333             : STATIC int
    2334    76742293 : xfs_rmap_map_shared(
    2335             :         struct xfs_btree_cur            *cur,
    2336             :         xfs_agblock_t                   bno,
    2337             :         xfs_extlen_t                    len,
    2338             :         bool                            unwritten,
    2339             :         const struct xfs_owner_info     *oinfo)
    2340             : {
    2341    76742293 :         struct xfs_mount                *mp = cur->bc_mp;
    2342    76742293 :         struct xfs_rmap_irec            ltrec;
    2343    76742293 :         struct xfs_rmap_irec            gtrec;
    2344    76742293 :         int                             have_gt;
    2345    76742293 :         int                             have_lt;
    2346    76742293 :         int                             error = 0;
    2347    76742293 :         int                             i;
    2348    76742293 :         uint64_t                        owner;
    2349    76742293 :         uint64_t                        offset;
    2350    76742293 :         unsigned int                    flags = 0;
    2351             : 
    2352    76742293 :         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
    2353    76742293 :         if (unwritten)
    2354    14837909 :                 flags |= XFS_RMAP_UNWRITTEN;
    2355    76742293 :         trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
    2356             :                         unwritten, oinfo);
    2357             : 
    2358             :         /* Is there a left record that abuts our range? */
    2359    76742348 :         error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
    2360             :                         &ltrec, &have_lt);
    2361    76742386 :         if (error)
    2362         214 :                 goto out_error;
    2363    76742172 :         if (have_lt &&
    2364     9563026 :             !xfs_rmap_is_mergeable(&ltrec, owner, flags))
    2365      374944 :                 have_lt = 0;
    2366             : 
    2367             :         /* Is there a right record that abuts our range? */
    2368    76742172 :         error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
    2369             :                         flags, &have_gt);
    2370    76742189 :         if (error)
    2371           1 :                 goto out_error;
    2372    76742188 :         if (have_gt) {
    2373      619018 :                 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
    2374      619018 :                 if (error)
    2375           0 :                         goto out_error;
    2376      619018 :                 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
    2377           0 :                         xfs_btree_mark_sick(cur);
    2378           0 :                         error = -EFSCORRUPTED;
    2379           0 :                         goto out_error;
    2380             :                 }
    2381      619018 :                 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
    2382      619018 :                         cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
    2383             :                         gtrec.rm_blockcount, gtrec.rm_owner,
    2384             :                         gtrec.rm_offset, gtrec.rm_flags);
    2385             : 
    2386      619018 :                 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
    2387      108138 :                         have_gt = 0;
    2388             :         }
    2389             : 
    2390    76742188 :         if (have_lt &&
    2391     9188082 :             ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
    2392     1457205 :             ltrec.rm_offset + ltrec.rm_blockcount == offset) {
    2393             :                 /*
    2394             :                  * Left edge contiguous, merge into left record.
    2395             :                  *
    2396             :                  *       ltbno     ltlen
    2397             :                  * orig:   |ooooooooo|
    2398             :                  * adding:           |aaaaaaaaa|
    2399             :                  * result: |rrrrrrrrrrrrrrrrrrr|
    2400             :                  *                  bno       len
    2401             :                  */
    2402     1457205 :                 ltrec.rm_blockcount += len;
    2403     1457205 :                 if (have_gt &&
    2404      333331 :                     bno + len == gtrec.rm_startblock &&
    2405      333331 :                     offset + len == gtrec.rm_offset) {
    2406             :                         /*
    2407             :                          * Right edge also contiguous, delete right record
    2408             :                          * and merge into left record.
    2409             :                          *
    2410             :                          *       ltbno     ltlen    gtbno     gtlen
    2411             :                          * orig:   |ooooooooo|         |ooooooooo|
    2412             :                          * adding:           |aaaaaaaaa|
    2413             :                          * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
    2414             :                          */
    2415      333331 :                         ltrec.rm_blockcount += gtrec.rm_blockcount;
    2416      333331 :                         error = xfs_rmap_delete(cur, gtrec.rm_startblock,
    2417             :                                         gtrec.rm_blockcount, gtrec.rm_owner,
    2418             :                                         gtrec.rm_offset, gtrec.rm_flags);
    2419      333331 :                         if (error)
    2420           0 :                                 goto out_error;
    2421             :                 }
    2422             : 
    2423             :                 /* Point the cursor back to the left record and update. */
    2424     1457205 :                 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
    2425             :                                 ltrec.rm_blockcount, ltrec.rm_owner,
    2426             :                                 ltrec.rm_offset, ltrec.rm_flags, &i);
    2427     1457205 :                 if (error)
    2428           0 :                         goto out_error;
    2429     1457205 :                 if (XFS_IS_CORRUPT(mp, i != 1)) {
    2430           0 :                         xfs_btree_mark_sick(cur);
    2431           0 :                         error = -EFSCORRUPTED;
    2432           0 :                         goto out_error;
    2433             :                 }
    2434             : 
    2435     1457205 :                 error = xfs_rmap_update(cur, &ltrec);
    2436     1457205 :                 if (error)
    2437           0 :                         goto out_error;
    2438    75284983 :         } else if (have_gt &&
    2439      177549 :                    bno + len == gtrec.rm_startblock &&
    2440      177549 :                    offset + len == gtrec.rm_offset) {
    2441             :                 /*
    2442             :                  * Right edge contiguous, merge into right record.
    2443             :                  *
    2444             :                  *                 gtbno     gtlen
    2445             :                  * Orig:             |ooooooooo|
    2446             :                  * adding: |aaaaaaaaa|
    2447             :                  * Result: |rrrrrrrrrrrrrrrrrrr|
    2448             :                  *        bno       len
    2449             :                  */
    2450             :                 /* Delete the old record. */
    2451      177549 :                 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
    2452             :                                 gtrec.rm_blockcount, gtrec.rm_owner,
    2453             :                                 gtrec.rm_offset, gtrec.rm_flags);
    2454      177549 :                 if (error)
    2455           0 :                         goto out_error;
    2456             : 
    2457             :                 /* Move the start and re-add it. */
    2458      177549 :                 gtrec.rm_startblock = bno;
    2459      177549 :                 gtrec.rm_blockcount += len;
    2460      177549 :                 gtrec.rm_offset = offset;
    2461      177549 :                 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
    2462             :                                 gtrec.rm_blockcount, gtrec.rm_owner,
    2463             :                                 gtrec.rm_offset, gtrec.rm_flags);
    2464      177549 :                 if (error)
    2465           0 :                         goto out_error;
    2466             :         } else {
    2467             :                 /*
    2468             :                  * No contiguous edge with identical owner, insert
    2469             :                  * new record at current cursor position.
    2470             :                  */
    2471    75107434 :                 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
    2472    75107417 :                 if (error)
    2473         158 :                         goto out_error;
    2474             :         }
    2475             : 
    2476    76742013 :         trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
    2477             :                         unwritten, oinfo);
    2478    76742390 : out_error:
    2479    76742390 :         if (error)
    2480         373 :                 trace_xfs_rmap_map_error(cur->bc_mp,
    2481         373 :                                 cur->bc_ag.pag->pag_agno, error, _RET_IP_);
    2482    76742390 :         return error;
    2483             : }
    2484             : 
    2485             : /* Insert a raw rmap into the rmapbt. */
    2486             : int
    2487    10996062 : xfs_rmap_map_raw(
    2488             :         struct xfs_btree_cur    *cur,
    2489             :         struct xfs_rmap_irec    *rmap)
    2490             : {
    2491    10996062 :         struct xfs_owner_info   oinfo;
    2492             : 
    2493    10996062 :         xfs_owner_info_pack(&oinfo, rmap->rm_owner, rmap->rm_offset,
    2494             :                         rmap->rm_flags);
    2495             : 
    2496    10996062 :         if ((rmap->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK |
    2497     8106343 :                                XFS_RMAP_UNWRITTEN)) ||
    2498     8106343 :             XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
    2499     3022902 :                 return xfs_rmap_map(cur, rmap->rm_startblock,
    2500             :                                 rmap->rm_blockcount,
    2501     3022902 :                                 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
    2502             :                                 &oinfo);
    2503             : 
    2504     7973160 :         return xfs_rmap_map_shared(cur, rmap->rm_startblock,
    2505             :                         rmap->rm_blockcount,
    2506     7973160 :                         rmap->rm_flags & XFS_RMAP_UNWRITTEN,
    2507             :                         &oinfo);
    2508             : }
    2509             : 
    2510             : struct xfs_rmap_query_range_info {
    2511             :         xfs_rmap_query_range_fn fn;
    2512             :         void                            *priv;
    2513             : };
    2514             : 
    2515             : /* Format btree record and pass to our callback. */
    2516             : STATIC int
    2517 49242179020 : xfs_rmap_query_range_helper(
    2518             :         struct xfs_btree_cur            *cur,
    2519             :         const union xfs_btree_rec       *rec,
    2520             :         void                            *priv)
    2521             : {
    2522 49242179020 :         struct xfs_rmap_query_range_info        *query = priv;
    2523 49242179020 :         struct xfs_rmap_irec                    irec;
    2524 49242179020 :         xfs_failaddr_t                          fa;
    2525             : 
    2526 49242179020 :         fa = xfs_rmap_btrec_to_irec(rec, &irec);
    2527 49430083802 :         if (!fa)
    2528 49423828110 :                 fa = xfs_rmap_check_irec(cur, &irec);
    2529 49527449054 :         if (fa)
    2530           0 :                 return xfs_rmap_complain_bad_rec(cur, fa, &irec);
    2531             : 
    2532 49527449054 :         return query->fn(cur, &irec, query->priv);
    2533             : }
    2534             : 
    2535             : /* Find all rmaps between two keys. */
    2536             : int
    2537   505984600 : xfs_rmap_query_range(
    2538             :         struct xfs_btree_cur                    *cur,
    2539             :         const struct xfs_rmap_irec              *low_rec,
    2540             :         const struct xfs_rmap_irec              *high_rec,
    2541             :         xfs_rmap_query_range_fn                 fn,
    2542             :         void                                    *priv)
    2543             : {
    2544   505984600 :         union xfs_btree_irec                    low_brec = { .r = *low_rec };
    2545   505984600 :         union xfs_btree_irec                    high_brec = { .r = *high_rec };
    2546   505984600 :         struct xfs_rmap_query_range_info        query = { .priv = priv, .fn = fn };
    2547             : 
    2548   505984600 :         return xfs_btree_query_range(cur, &low_brec, &high_brec,
    2549             :                         xfs_rmap_query_range_helper, &query);
    2550             : }
    2551             : 
    2552             : /* Find all rmaps. */
    2553             : int
    2554     1679473 : xfs_rmap_query_all(
    2555             :         struct xfs_btree_cur                    *cur,
    2556             :         xfs_rmap_query_range_fn                 fn,
    2557             :         void                                    *priv)
    2558             : {
    2559     1679473 :         struct xfs_rmap_query_range_info        query;
    2560             : 
    2561     1679473 :         query.priv = priv;
    2562     1679473 :         query.fn = fn;
    2563     1679473 :         return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
    2564             : }
    2565             : 
    2566             : /* Clean up after calling xfs_rmap_finish_one. */
    2567             : void
    2568   214694853 : xfs_rmap_finish_one_cleanup(
    2569             :         struct xfs_trans        *tp,
    2570             :         struct xfs_btree_cur    *rcur,
    2571             :         int                     error)
    2572             : {
    2573   214696118 :         struct xfs_buf          *agbp;
    2574             : 
    2575   214694853 :         if (rcur == NULL)
    2576             :                 return;
    2577   214695081 :         agbp = rcur->bc_ag.agbp;
    2578   214693816 :         xfs_btree_del_cursor(rcur, error);
    2579   214696428 :         if (error)
    2580        1080 :                 xfs_trans_brelse(tp, agbp);
    2581             : }
    2582             : 
    2583             : /* Commit an rmap operation into the ondisk tree. */
    2584             : int
    2585   234387015 : __xfs_rmap_finish_intent(
    2586             :         struct xfs_btree_cur            *rcur,
    2587             :         enum xfs_rmap_intent_type       op,
    2588             :         xfs_agblock_t                   bno,
    2589             :         xfs_extlen_t                    len,
    2590             :         const struct xfs_owner_info     *oinfo,
    2591             :         bool                            unwritten)
    2592             : {
    2593   234387015 :         switch (op) {
    2594    47298676 :         case XFS_RMAP_ALLOC:
    2595             :         case XFS_RMAP_MAP:
    2596    47298676 :                 return xfs_rmap_map(rcur, bno, len, unwritten, oinfo);
    2597    68769149 :         case XFS_RMAP_MAP_SHARED:
    2598    68769149 :                 return xfs_rmap_map_shared(rcur, bno, len, unwritten, oinfo);
    2599    42627057 :         case XFS_RMAP_FREE:
    2600             :         case XFS_RMAP_UNMAP:
    2601    42627057 :                 return xfs_rmap_unmap(rcur, bno, len, unwritten, oinfo);
    2602    57341045 :         case XFS_RMAP_UNMAP_SHARED:
    2603    57341045 :                 return xfs_rmap_unmap_shared(rcur, bno, len, unwritten, oinfo);
    2604     5982550 :         case XFS_RMAP_CONVERT:
    2605     5982550 :                 return xfs_rmap_convert(rcur, bno, len, !unwritten, oinfo);
    2606    12368538 :         case XFS_RMAP_CONVERT_SHARED:
    2607    12368538 :                 return xfs_rmap_convert_shared(rcur, bno, len, !unwritten,
    2608    12368538 :                                 oinfo);
    2609           0 :         default:
    2610           0 :                 ASSERT(0);
    2611           0 :                 return -EFSCORRUPTED;
    2612             :         }
    2613             : }
    2614             : 
    2615             : /*
    2616             :  * Process one of the deferred rmap operations.  We pass back the
    2617             :  * btree cursor to maintain our lock on the rmapbt between calls.
    2618             :  * This saves time and eliminates a buffer deadlock between the
    2619             :  * superblock and the AGF because we'll always grab them in the same
    2620             :  * order.
    2621             :  */
    2622             : int
    2623   234291065 : xfs_rmap_finish_one(
    2624             :         struct xfs_trans                *tp,
    2625             :         struct xfs_rmap_intent          *ri,
    2626             :         struct xfs_btree_cur            **pcur)
    2627             : {
    2628   234291065 :         struct xfs_mount                *mp = tp->t_mountp;
    2629   234291065 :         struct xfs_btree_cur            *rcur;
    2630   234291065 :         struct xfs_buf                  *agbp = NULL;
    2631   234291065 :         int                             error = 0;
    2632   234291065 :         struct xfs_owner_info           oinfo;
    2633   234291065 :         xfs_agblock_t                   bno;
    2634   234291065 :         bool                            unwritten;
    2635             : 
    2636   234291065 :         bno = XFS_FSB_TO_AGBNO(mp, ri->ri_bmap.br_startblock);
    2637             : 
    2638   234291065 :         trace_xfs_rmap_deferred(mp, ri->ri_pag->pag_agno, ri->ri_type, bno,
    2639             :                         ri->ri_owner, ri->ri_whichfork,
    2640             :                         ri->ri_bmap.br_startoff, ri->ri_bmap.br_blockcount,
    2641             :                         ri->ri_bmap.br_state);
    2642             : 
    2643   234293230 :         if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE))
    2644             :                 return -EIO;
    2645             : 
    2646             :         /*
    2647             :          * If we haven't gotten a cursor or the cursor AG doesn't match
    2648             :          * the startblock, get one now.
    2649             :          */
    2650   234291315 :         rcur = *pcur;
    2651   234291315 :         if (rcur != NULL && rcur->bc_ag.pag != ri->ri_pag) {
    2652        1265 :                 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
    2653        1265 :                 rcur = NULL;
    2654        1265 :                 *pcur = NULL;
    2655             :         }
    2656   234291315 :         if (rcur == NULL) {
    2657             :                 /*
    2658             :                  * Refresh the freelist before we start changing the
    2659             :                  * rmapbt, because a shape change could cause us to
    2660             :                  * allocate blocks.
    2661             :                  */
    2662   214697574 :                 error = xfs_free_extent_fix_freelist(tp, ri->ri_pag, &agbp);
    2663   214698855 :                 if (error) {
    2664        1031 :                         xfs_ag_mark_sick(ri->ri_pag, XFS_SICK_AG_AGFL);
    2665        1031 :                         return error;
    2666             :                 }
    2667   214697824 :                 if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) {
    2668           0 :                         xfs_ag_mark_sick(ri->ri_pag, XFS_SICK_AG_AGFL);
    2669           0 :                         return -EFSCORRUPTED;
    2670             :                 }
    2671             : 
    2672   214697824 :                 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, ri->ri_pag);
    2673             :         }
    2674   234291343 :         *pcur = rcur;
    2675             : 
    2676   234291343 :         xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork,
    2677             :                         ri->ri_bmap.br_startoff);
    2678   234291343 :         unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN;
    2679   234291343 :         bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, ri->ri_bmap.br_startblock);
    2680             : 
    2681   234291343 :         error = __xfs_rmap_finish_intent(rcur, ri->ri_type, bno,
    2682   234291343 :                         ri->ri_bmap.br_blockcount, &oinfo, unwritten);
    2683   234290398 :         if (error)
    2684             :                 return error;
    2685             : 
    2686   234287612 :         xfs_rmap_update_hook(tp, ri->ri_pag, ri->ri_type, bno,
    2687   234287612 :                         ri->ri_bmap.br_blockcount, unwritten, &oinfo);
    2688   234287612 :         return 0;
    2689             : }
    2690             : 
    2691             : /*
    2692             :  * Don't defer an rmap if we aren't an rmap filesystem.
    2693             :  */
    2694             : static bool
    2695             : xfs_rmap_update_is_needed(
    2696             :         struct xfs_mount        *mp,
    2697             :         int                     whichfork)
    2698             : {
    2699   233692170 :         return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
    2700             : }
    2701             : 
    2702             : /*
    2703             :  * Record a rmap intent; the list is kept sorted first by AG and then by
    2704             :  * increasing age.
    2705             :  */
    2706             : static void
    2707   234281278 : __xfs_rmap_add(
    2708             :         struct xfs_trans                *tp,
    2709             :         enum xfs_rmap_intent_type       type,
    2710             :         uint64_t                        owner,
    2711             :         int                             whichfork,
    2712             :         struct xfs_bmbt_irec            *bmap)
    2713             : {
    2714   234281278 :         struct xfs_rmap_intent          *ri;
    2715             : 
    2716   234281278 :         trace_xfs_rmap_defer(tp->t_mountp,
    2717   234281278 :                         XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
    2718             :                         type,
    2719             :                         XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
    2720             :                         owner, whichfork,
    2721             :                         bmap->br_startoff,
    2722             :                         bmap->br_blockcount,
    2723             :                         bmap->br_state);
    2724             : 
    2725   234280223 :         ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_NOFS | __GFP_NOFAIL);
    2726   234277156 :         INIT_LIST_HEAD(&ri->ri_list);
    2727   234277156 :         ri->ri_type = type;
    2728   234277156 :         ri->ri_owner = owner;
    2729   234277156 :         ri->ri_whichfork = whichfork;
    2730   234277156 :         ri->ri_bmap = *bmap;
    2731             : 
    2732   234277156 :         xfs_rmap_update_get_group(tp->t_mountp, ri);
    2733   234277115 :         xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
    2734   234281616 : }
    2735             : 
    2736             : /* Map an extent into a file. */
    2737             : void
    2738   138003614 : xfs_rmap_map_extent(
    2739             :         struct xfs_trans        *tp,
    2740             :         struct xfs_inode        *ip,
    2741             :         int                     whichfork,
    2742             :         struct xfs_bmbt_irec    *PREV)
    2743             : {
    2744   138003614 :         enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
    2745             : 
    2746   276007228 :         if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
    2747             :                 return;
    2748             : 
    2749   115660943 :         if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
    2750    68738879 :                 type = XFS_RMAP_MAP_SHARED;
    2751             : 
    2752   115660943 :         __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
    2753             : }
    2754             : 
    2755             : /* Unmap an extent out of a file. */
    2756             : void
    2757   114255000 : xfs_rmap_unmap_extent(
    2758             :         struct xfs_trans        *tp,
    2759             :         struct xfs_inode        *ip,
    2760             :         int                     whichfork,
    2761             :         struct xfs_bmbt_irec    *PREV)
    2762             : {
    2763   114255000 :         enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
    2764             : 
    2765   228510000 :         if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
    2766             :                 return;
    2767             : 
    2768    97708837 :         if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
    2769    57317434 :                 type = XFS_RMAP_UNMAP_SHARED;
    2770             : 
    2771    97708837 :         __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
    2772             : }
    2773             : 
    2774             : /*
    2775             :  * Convert a data fork extent from unwritten to real or vice versa.
    2776             :  *
    2777             :  * Note that tp can be NULL here as no transaction is used for COW fork
    2778             :  * unwritten conversion.
    2779             :  */
    2780             : void
    2781    26536244 : xfs_rmap_convert_extent(
    2782             :         struct xfs_mount        *mp,
    2783             :         struct xfs_trans        *tp,
    2784             :         struct xfs_inode        *ip,
    2785             :         int                     whichfork,
    2786             :         struct xfs_bmbt_irec    *PREV)
    2787             : {
    2788    26536244 :         enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
    2789             : 
    2790    53072488 :         if (!xfs_rmap_update_is_needed(mp, whichfork))
    2791             :                 return;
    2792             : 
    2793    18325387 :         if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
    2794    12345973 :                 type = XFS_RMAP_CONVERT_SHARED;
    2795             : 
    2796    18325387 :         __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
    2797             : }
    2798             : 
    2799             : /* Schedule the creation of an rmap for non-file data. */
    2800             : void
    2801      359509 : xfs_rmap_alloc_extent(
    2802             :         struct xfs_trans        *tp,
    2803             :         xfs_agnumber_t          agno,
    2804             :         xfs_agblock_t           bno,
    2805             :         xfs_extlen_t            len,
    2806             :         uint64_t                owner)
    2807             : {
    2808      359509 :         struct xfs_bmbt_irec    bmap;
    2809             : 
    2810      359509 :         if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
    2811           0 :                 return;
    2812             : 
    2813      359509 :         bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
    2814      359509 :         bmap.br_blockcount = len;
    2815      359509 :         bmap.br_startoff = 0;
    2816      359509 :         bmap.br_state = XFS_EXT_NORM;
    2817             : 
    2818      359509 :         __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
    2819             : }
    2820             : 
    2821             : /* Schedule the deletion of an rmap for non-file data. */
    2822             : void
    2823     2230826 : xfs_rmap_free_extent(
    2824             :         struct xfs_trans        *tp,
    2825             :         xfs_agnumber_t          agno,
    2826             :         xfs_agblock_t           bno,
    2827             :         xfs_extlen_t            len,
    2828             :         uint64_t                owner)
    2829             : {
    2830     2230826 :         struct xfs_bmbt_irec    bmap;
    2831             : 
    2832     2230826 :         if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
    2833           0 :                 return;
    2834             : 
    2835     2230826 :         bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
    2836     2230826 :         bmap.br_blockcount = len;
    2837     2230826 :         bmap.br_startoff = 0;
    2838     2230826 :         bmap.br_state = XFS_EXT_NORM;
    2839             : 
    2840     2230826 :         __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
    2841             : }
    2842             : 
    2843             : /* Compare rmap records.  Returns -1 if a < b, 1 if a > b, and 0 if equal. */
    2844             : int
    2845    47555525 : xfs_rmap_compare(
    2846             :         const struct xfs_rmap_irec      *a,
    2847             :         const struct xfs_rmap_irec      *b)
    2848             : {
    2849    47555525 :         __u64                           oa;
    2850    47555525 :         __u64                           ob;
    2851             : 
    2852    47555525 :         oa = xfs_rmap_irec_offset_pack(a);
    2853    47555525 :         ob = xfs_rmap_irec_offset_pack(b);
    2854             : 
    2855    47555525 :         if (a->rm_startblock < b->rm_startblock)
    2856             :                 return -1;
    2857    47552508 :         else if (a->rm_startblock > b->rm_startblock)
    2858             :                 return 1;
    2859     7842385 :         else if (a->rm_owner < b->rm_owner)
    2860             :                 return -1;
    2861     7763476 :         else if (a->rm_owner > b->rm_owner)
    2862             :                 return 1;
    2863     7658428 :         else if (oa < ob)
    2864             :                 return -1;
    2865     7605525 :         else if (oa > ob)
    2866             :                 return 1;
    2867             :         else
    2868        3714 :                 return 0;
    2869             : }
    2870             : 
    2871             : /*
    2872             :  * Scan the physical storage part of the keyspace of the reverse mapping index
    2873             :  * and tell us if the area has no records, is fully mapped by records, or is
    2874             :  * partially filled.
    2875             :  */
    2876             : int
    2877   382396471 : xfs_rmap_has_records(
    2878             :         struct xfs_btree_cur    *cur,
    2879             :         xfs_agblock_t           bno,
    2880             :         xfs_extlen_t            len,
    2881             :         enum xbtree_recpacking  *outcome)
    2882             : {
    2883   382396471 :         union xfs_btree_key     mask = {
    2884             :                 .rmap.rm_startblock = cpu_to_be32(-1U),
    2885             :         };
    2886   382396471 :         union xfs_btree_irec    low;
    2887   382396471 :         union xfs_btree_irec    high;
    2888             : 
    2889   382396471 :         memset(&low, 0, sizeof(low));
    2890   382396471 :         low.r.rm_startblock = bno;
    2891   382396471 :         memset(&high, 0xFF, sizeof(high));
    2892   382396471 :         high.r.rm_startblock = bno + len - 1;
    2893             : 
    2894   382396471 :         return xfs_btree_has_records(cur, &low, &high, &mask, outcome);
    2895             : }
    2896             : 
    2897             : struct xfs_rmap_ownercount {
    2898             :         /* Owner that we're looking for. */
    2899             :         struct xfs_rmap_irec    good;
    2900             : 
    2901             :         /* rmap search keys */
    2902             :         struct xfs_rmap_irec    low;
    2903             :         struct xfs_rmap_irec    high;
    2904             : 
    2905             :         struct xfs_rmap_matches *results;
    2906             : 
    2907             :         /* Stop early if we find a nonmatch? */
    2908             :         bool                    stop_on_nonmatch;
    2909             : };
    2910             : 
    2911             : /* Does this rmap represent space that can have multiple owners? */
    2912             : static inline bool
    2913             : xfs_rmap_shareable(
    2914             :         struct xfs_mount                *mp,
    2915             :         const struct xfs_rmap_irec      *rmap)
    2916             : {
    2917    45751786 :         if (!xfs_has_reflink(mp))
    2918             :                 return false;
    2919    91503497 :         if (XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
    2920             :                 return false;
    2921    45106961 :         if (rmap->rm_flags & (XFS_RMAP_ATTR_FORK |
    2922             :                               XFS_RMAP_BMBT_BLOCK))
    2923      878193 :                 return false;
    2924             :         return true;
    2925             : }
    2926             : 
    2927             : static inline void
    2928   401385577 : xfs_rmap_ownercount_init(
    2929             :         struct xfs_rmap_ownercount      *roc,
    2930             :         xfs_agblock_t                   bno,
    2931             :         xfs_extlen_t                    len,
    2932             :         const struct xfs_owner_info     *oinfo,
    2933             :         struct xfs_rmap_matches         *results)
    2934             : {
    2935   401385577 :         memset(roc, 0, sizeof(*roc));
    2936   401385577 :         roc->results = results;
    2937             : 
    2938   401385577 :         roc->low.rm_startblock = bno;
    2939   401385577 :         memset(&roc->high, 0xFF, sizeof(roc->high));
    2940   401385577 :         roc->high.rm_startblock = bno + len - 1;
    2941             : 
    2942   401385577 :         memset(results, 0, sizeof(*results));
    2943   401385577 :         roc->good.rm_startblock = bno;
    2944   401385577 :         roc->good.rm_blockcount = len;
    2945   401385577 :         roc->good.rm_owner = oinfo->oi_owner;
    2946   401385577 :         roc->good.rm_offset = oinfo->oi_offset;
    2947   401385577 :         if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
    2948      906843 :                 roc->good.rm_flags |= XFS_RMAP_ATTR_FORK;
    2949   401385577 :         if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
    2950     1138709 :                 roc->good.rm_flags |= XFS_RMAP_BMBT_BLOCK;
    2951   401385577 : }
    2952             : 
    2953             : /* Figure out if this is a match for the owner. */
    2954             : STATIC int
    2955   431165206 : xfs_rmap_count_owners_helper(
    2956             :         struct xfs_btree_cur            *cur,
    2957             :         const struct xfs_rmap_irec      *rec,
    2958             :         void                            *priv)
    2959             : {
    2960   431165206 :         struct xfs_rmap_ownercount      *roc = priv;
    2961   431165206 :         struct xfs_rmap_irec            check = *rec;
    2962   431165206 :         unsigned int                    keyflags;
    2963   431165206 :         bool                            filedata;
    2964   431165206 :         int64_t                         delta;
    2965             : 
    2966   431165206 :         filedata = !XFS_RMAP_NON_INODE_OWNER(check.rm_owner) &&
    2967   174675118 :                    !(check.rm_flags & XFS_RMAP_BMBT_BLOCK);
    2968             : 
    2969             :         /* Trim the part of check that comes before the comparison range. */
    2970   431165206 :         delta = (int64_t)roc->good.rm_startblock - check.rm_startblock;
    2971   431165206 :         if (delta > 0) {
    2972   174069136 :                 check.rm_startblock += delta;
    2973   174069136 :                 check.rm_blockcount -= delta;
    2974   174069136 :                 if (filedata)
    2975     1386539 :                         check.rm_offset += delta;
    2976             :         }
    2977             : 
    2978             :         /* Trim the part of check that comes after the comparison range. */
    2979   431165206 :         delta = (check.rm_startblock + check.rm_blockcount) -
    2980   431165206 :                 (roc->good.rm_startblock + roc->good.rm_blockcount);
    2981   431165206 :         if (delta > 0)
    2982   209112820 :                 check.rm_blockcount -= delta;
    2983             : 
    2984             :         /* Don't care about unwritten status for establishing ownership. */
    2985   431165206 :         keyflags = check.rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK);
    2986             : 
    2987   431165206 :         if (check.rm_startblock == roc->good.rm_startblock &&
    2988   399773270 :             check.rm_blockcount == roc->good.rm_blockcount &&
    2989   399773270 :             check.rm_owner      == roc->good.rm_owner &&
    2990   385413412 :             check.rm_offset     == roc->good.rm_offset &&
    2991   385413461 :             keyflags            == roc->good.rm_flags) {
    2992   385413420 :                 roc->results->matches++;
    2993             :         } else {
    2994    45751786 :                 roc->results->non_owner_matches++;
    2995    91503572 :                 if (xfs_rmap_shareable(cur->bc_mp, &roc->good) ^
    2996             :                     xfs_rmap_shareable(cur->bc_mp, &check))
    2997    44228772 :                         roc->results->bad_non_owner_matches++;
    2998             :         }
    2999             : 
    3000   431165206 :         if (roc->results->non_owner_matches && roc->stop_on_nonmatch)
    3001           0 :                 return -ECANCELED;
    3002             : 
    3003             :         return 0;
    3004             : }
    3005             : 
    3006             : /* Count the number of owners and non-owners of this range of blocks. */
    3007             : int
    3008   400412551 : xfs_rmap_count_owners(
    3009             :         struct xfs_btree_cur            *cur,
    3010             :         xfs_agblock_t                   bno,
    3011             :         xfs_extlen_t                    len,
    3012             :         const struct xfs_owner_info     *oinfo,
    3013             :         struct xfs_rmap_matches         *results)
    3014             : {
    3015   400412551 :         struct xfs_rmap_ownercount      roc;
    3016   400412551 :         int                             error;
    3017             : 
    3018   400412551 :         xfs_rmap_ownercount_init(&roc, bno, len, oinfo, results);
    3019   400413594 :         error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
    3020             :                         xfs_rmap_count_owners_helper, &roc);
    3021   400414215 :         if (error)
    3022             :                 return error;
    3023             : 
    3024             :         /*
    3025             :          * There can't be any non-owner rmaps that conflict with the given
    3026             :          * owner if we didn't find any rmaps matching the owner.
    3027             :          */
    3028   400414215 :         if (!results->matches)
    3029    15885268 :                 results->bad_non_owner_matches = 0;
    3030             : 
    3031             :         return 0;
    3032             : }
    3033             : 
    3034             : /*
    3035             :  * Given an extent and some owner info, can we find records overlapping
    3036             :  * the extent whose owner info does not match the given owner?
    3037             :  */
    3038             : int
    3039      972523 : xfs_rmap_has_other_keys(
    3040             :         struct xfs_btree_cur            *cur,
    3041             :         xfs_agblock_t                   bno,
    3042             :         xfs_extlen_t                    len,
    3043             :         const struct xfs_owner_info     *oinfo,
    3044             :         bool                            *has_other)
    3045             : {
    3046      972523 :         struct xfs_rmap_matches         res;
    3047      972523 :         struct xfs_rmap_ownercount      roc;
    3048      972523 :         int                             error;
    3049             : 
    3050      972523 :         xfs_rmap_ownercount_init(&roc, bno, len, oinfo, &res);
    3051      972522 :         roc.stop_on_nonmatch = true;
    3052             : 
    3053      972522 :         error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
    3054             :                         xfs_rmap_count_owners_helper, &roc);
    3055      972531 :         if (error == -ECANCELED) {
    3056           0 :                 *has_other = true;
    3057           0 :                 return 0;
    3058             :         }
    3059      972531 :         if (error)
    3060             :                 return error;
    3061             : 
    3062      972531 :         *has_other = false;
    3063      972531 :         return 0;
    3064             : }
    3065             : 
    3066             : const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
    3067             :         .oi_owner = XFS_RMAP_OWN_NULL,
    3068             : };
    3069             : const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
    3070             :         .oi_owner = XFS_RMAP_OWN_UNKNOWN,
    3071             : };
    3072             : const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
    3073             :         .oi_owner = XFS_RMAP_OWN_FS,
    3074             : };
    3075             : const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
    3076             :         .oi_owner = XFS_RMAP_OWN_LOG,
    3077             : };
    3078             : const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
    3079             :         .oi_owner = XFS_RMAP_OWN_AG,
    3080             : };
    3081             : const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
    3082             :         .oi_owner = XFS_RMAP_OWN_INOBT,
    3083             : };
    3084             : const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
    3085             :         .oi_owner = XFS_RMAP_OWN_INODES,
    3086             : };
    3087             : const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
    3088             :         .oi_owner = XFS_RMAP_OWN_REFC,
    3089             : };
    3090             : const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
    3091             :         .oi_owner = XFS_RMAP_OWN_COW,
    3092             : };
    3093             : 
    3094             : int __init
    3095          12 : xfs_rmap_intent_init_cache(void)
    3096             : {
    3097          12 :         xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent",
    3098             :                         sizeof(struct xfs_rmap_intent),
    3099             :                         0, 0, NULL);
    3100             : 
    3101          12 :         return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM;
    3102             : }
    3103             : 
    3104             : void
    3105          12 : xfs_rmap_intent_destroy_cache(void)
    3106             : {
    3107          12 :         kmem_cache_destroy(xfs_rmap_intent_cache);
    3108          12 :         xfs_rmap_intent_cache = NULL;
    3109          12 : }

Generated by: LCOV version 1.14