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-rc4-xfsa @ Mon Jul 31 20:08:27 PDT 2023 Lines: 1193 1538 77.6 %
Date: 2023-07-31 20:08:27 Functions: 51 53 96.2 %

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

Generated by: LCOV version 1.14