LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_rmap_btree.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwx @ Mon Jul 31 20:08:22 PDT 2023 Lines: 245 280 87.5 %
Date: 2023-07-31 20:08:22 Functions: 26 30 86.7 %

          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_mount.h"
      13             : #include "xfs_trans.h"
      14             : #include "xfs_alloc.h"
      15             : #include "xfs_btree.h"
      16             : #include "xfs_btree_staging.h"
      17             : #include "xfs_rmap.h"
      18             : #include "xfs_rmap_btree.h"
      19             : #include "xfs_trace.h"
      20             : #include "xfs_error.h"
      21             : #include "xfs_extent_busy.h"
      22             : #include "xfs_ag.h"
      23             : #include "xfs_ag_resv.h"
      24             : 
      25             : static struct kmem_cache        *xfs_rmapbt_cur_cache;
      26             : 
      27             : /*
      28             :  * Reverse map btree.
      29             :  *
      30             :  * This is a per-ag tree used to track the owner(s) of a given extent. With
      31             :  * reflink it is possible for there to be multiple owners, which is a departure
      32             :  * from classic XFS. Owner records for data extents are inserted when the
      33             :  * extent is mapped and removed when an extent is unmapped.  Owner records for
      34             :  * all other block types (i.e. metadata) are inserted when an extent is
      35             :  * allocated and removed when an extent is freed. There can only be one owner
      36             :  * of a metadata extent, usually an inode or some other metadata structure like
      37             :  * an AG btree.
      38             :  *
      39             :  * The rmap btree is part of the free space management, so blocks for the tree
      40             :  * are sourced from the agfl. Hence we need transaction reservation support for
      41             :  * this tree so that the freelist is always large enough. This also impacts on
      42             :  * the minimum space we need to leave free in the AG.
      43             :  *
      44             :  * The tree is ordered by [ag block, owner, offset]. This is a large key size,
      45             :  * but it is the only way to enforce unique keys when a block can be owned by
      46             :  * multiple files at any offset. There's no need to order/search by extent
      47             :  * size for online updating/management of the tree. It is intended that most
      48             :  * reverse lookups will be to find the owner(s) of a particular block, or to
      49             :  * try to recover tree and file data from corrupt primary metadata.
      50             :  */
      51             : 
      52             : static struct xfs_btree_cur *
      53    64328717 : xfs_rmapbt_dup_cursor(
      54             :         struct xfs_btree_cur    *cur)
      55             : {
      56    64328717 :         return xfs_rmapbt_init_cursor(cur->bc_mp, cur->bc_tp,
      57             :                                 cur->bc_ag.agbp, cur->bc_ag.pag);
      58             : }
      59             : 
      60             : STATIC void
      61       43706 : xfs_rmapbt_set_root(
      62             :         struct xfs_btree_cur            *cur,
      63             :         const union xfs_btree_ptr       *ptr,
      64             :         int                             inc)
      65             : {
      66       43706 :         struct xfs_buf          *agbp = cur->bc_ag.agbp;
      67       43706 :         struct xfs_agf          *agf = agbp->b_addr;
      68       43706 :         int                     btnum = cur->bc_btnum;
      69             : 
      70       43706 :         ASSERT(ptr->s != 0);
      71             : 
      72       43706 :         agf->agf_roots[btnum] = ptr->s;
      73       43706 :         be32_add_cpu(&agf->agf_levels[btnum], inc);
      74       43706 :         cur->bc_ag.pag->pagf_levels[btnum] += inc;
      75             : 
      76       43706 :         xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
      77       43706 : }
      78             : 
      79             : STATIC int
      80      650390 : xfs_rmapbt_alloc_block(
      81             :         struct xfs_btree_cur            *cur,
      82             :         const union xfs_btree_ptr       *start,
      83             :         union xfs_btree_ptr             *new,
      84             :         int                             *stat)
      85             : {
      86      650390 :         struct xfs_buf          *agbp = cur->bc_ag.agbp;
      87      650390 :         struct xfs_agf          *agf = agbp->b_addr;
      88      650390 :         struct xfs_perag        *pag = cur->bc_ag.pag;
      89      650390 :         int                     error;
      90      650390 :         xfs_agblock_t           bno;
      91             : 
      92             :         /* Allocate the new block from the freelist. If we can't, give up.  */
      93      650390 :         error = xfs_alloc_get_freelist(pag, cur->bc_tp, cur->bc_ag.agbp,
      94             :                                        &bno, 1);
      95      650390 :         if (error)
      96             :                 return error;
      97             : 
      98      650390 :         trace_xfs_rmapbt_alloc_block(cur->bc_mp, pag->pag_agno, bno, 1);
      99      650390 :         if (bno == NULLAGBLOCK) {
     100           0 :                 *stat = 0;
     101           0 :                 return 0;
     102             :         }
     103             : 
     104      650390 :         xfs_extent_busy_reuse(cur->bc_mp, pag, bno, 1, false);
     105             : 
     106      650390 :         new->s = cpu_to_be32(bno);
     107      650390 :         be32_add_cpu(&agf->agf_rmap_blocks, 1);
     108      650390 :         xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_RMAP_BLOCKS);
     109             : 
     110      650390 :         xfs_ag_resv_rmapbt_alloc(cur->bc_mp, pag->pag_agno);
     111             : 
     112      650390 :         *stat = 1;
     113      650390 :         return 0;
     114             : }
     115             : 
     116             : STATIC int
     117      183878 : xfs_rmapbt_free_block(
     118             :         struct xfs_btree_cur    *cur,
     119             :         struct xfs_buf          *bp)
     120             : {
     121      183878 :         struct xfs_buf          *agbp = cur->bc_ag.agbp;
     122      183878 :         struct xfs_agf          *agf = agbp->b_addr;
     123      183878 :         struct xfs_perag        *pag = cur->bc_ag.pag;
     124      183878 :         xfs_agblock_t           bno;
     125      183878 :         int                     error;
     126             : 
     127      183878 :         bno = xfs_daddr_to_agbno(cur->bc_mp, xfs_buf_daddr(bp));
     128      183876 :         trace_xfs_rmapbt_free_block(cur->bc_mp, pag->pag_agno,
     129             :                         bno, 1);
     130      183876 :         be32_add_cpu(&agf->agf_rmap_blocks, -1);
     131      183876 :         xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_RMAP_BLOCKS);
     132      183878 :         error = xfs_alloc_put_freelist(pag, cur->bc_tp, agbp, NULL, bno, 1);
     133      183878 :         if (error)
     134             :                 return error;
     135             : 
     136      183878 :         xfs_extent_busy_insert(cur->bc_tp, pag, bno, 1,
     137             :                               XFS_EXTENT_BUSY_SKIP_DISCARD);
     138             : 
     139      183878 :         xfs_ag_resv_free_extent(pag, XFS_AG_RESV_RMAPBT, NULL, 1);
     140      183878 :         return 0;
     141             : }
     142             : 
     143             : STATIC int
     144   166640854 : xfs_rmapbt_get_minrecs(
     145             :         struct xfs_btree_cur    *cur,
     146             :         int                     level)
     147             : {
     148   166640854 :         return cur->bc_mp->m_rmap_mnr[level != 0];
     149             : }
     150             : 
     151             : STATIC int
     152 >12994*10^7 : xfs_rmapbt_get_maxrecs(
     153             :         struct xfs_btree_cur    *cur,
     154             :         int                     level)
     155             : {
     156 >12994*10^7 :         return cur->bc_mp->m_rmap_mxr[level != 0];
     157             : }
     158             : 
     159             : /*
     160             :  * Convert the ondisk record's offset field into the ondisk key's offset field.
     161             :  * Fork and bmbt are significant parts of the rmap record key, but written
     162             :  * status is merely a record attribute.
     163             :  */
     164             : static inline __be64 ondisk_rec_offset_to_key(const union xfs_btree_rec *rec)
     165             : {
     166 >25368*10^7 :         return rec->rmap.rm_offset & ~cpu_to_be64(XFS_RMAP_OFF_UNWRITTEN);
     167             : }
     168             : 
     169             : STATIC void
     170 >12126*10^7 : xfs_rmapbt_init_key_from_rec(
     171             :         union xfs_btree_key             *key,
     172             :         const union xfs_btree_rec       *rec)
     173             : {
     174 >12126*10^7 :         key->rmap.rm_startblock = rec->rmap.rm_startblock;
     175 >12126*10^7 :         key->rmap.rm_owner = rec->rmap.rm_owner;
     176 >12126*10^7 :         key->rmap.rm_offset = ondisk_rec_offset_to_key(rec);
     177 >12126*10^7 : }
     178             : 
     179             : /*
     180             :  * The high key for a reverse mapping record can be computed by shifting
     181             :  * the startblock and offset to the highest value that would still map
     182             :  * to that record.  In practice this means that we add blockcount-1 to
     183             :  * the startblock for all records, and if the record is for a data/attr
     184             :  * fork mapping, we add blockcount-1 to the offset too.
     185             :  */
     186             : STATIC void
     187 >13242*10^7 : xfs_rmapbt_init_high_key_from_rec(
     188             :         union xfs_btree_key             *key,
     189             :         const union xfs_btree_rec       *rec)
     190             : {
     191 >13242*10^7 :         uint64_t                        off;
     192 >13242*10^7 :         int                             adj;
     193             : 
     194 >13242*10^7 :         adj = be32_to_cpu(rec->rmap.rm_blockcount) - 1;
     195             : 
     196 >13242*10^7 :         key->rmap.rm_startblock = rec->rmap.rm_startblock;
     197 >13242*10^7 :         be32_add_cpu(&key->rmap.rm_startblock, adj);
     198 >13242*10^7 :         key->rmap.rm_owner = rec->rmap.rm_owner;
     199 >13242*10^7 :         key->rmap.rm_offset = ondisk_rec_offset_to_key(rec);
     200 >13242*10^7 :         if (XFS_RMAP_NON_INODE_OWNER(be64_to_cpu(rec->rmap.rm_owner)) ||
     201 >12491*10^7 :             XFS_RMAP_IS_BMBT_BLOCK(be64_to_cpu(rec->rmap.rm_offset)))
     202             :                 return;
     203 >12419*10^7 :         off = be64_to_cpu(key->rmap.rm_offset);
     204 >12419*10^7 :         off = (XFS_RMAP_OFF(off) + adj) | (off & ~XFS_RMAP_OFF_MASK);
     205 >12419*10^7 :         key->rmap.rm_offset = cpu_to_be64(off);
     206             : }
     207             : 
     208             : STATIC void
     209  2739235881 : xfs_rmapbt_init_rec_from_cur(
     210             :         struct xfs_btree_cur    *cur,
     211             :         union xfs_btree_rec     *rec)
     212             : {
     213  2739235881 :         rec->rmap.rm_startblock = cpu_to_be32(cur->bc_rec.r.rm_startblock);
     214  2739235881 :         rec->rmap.rm_blockcount = cpu_to_be32(cur->bc_rec.r.rm_blockcount);
     215  2739235881 :         rec->rmap.rm_owner = cpu_to_be64(cur->bc_rec.r.rm_owner);
     216  2739235881 :         rec->rmap.rm_offset = cpu_to_be64(
     217             :                         xfs_rmap_irec_offset_pack(&cur->bc_rec.r));
     218  2739235881 : }
     219             : 
     220             : STATIC void
     221  2006839219 : xfs_rmapbt_init_ptr_from_cur(
     222             :         struct xfs_btree_cur    *cur,
     223             :         union xfs_btree_ptr     *ptr)
     224             : {
     225  2006839219 :         struct xfs_agf          *agf = cur->bc_ag.agbp->b_addr;
     226             : 
     227  2006839219 :         ASSERT(cur->bc_ag.pag->pag_agno == be32_to_cpu(agf->agf_seqno));
     228             : 
     229  2006839219 :         ptr->s = agf->agf_roots[cur->bc_btnum];
     230  2006900916 : }
     231             : 
     232             : /*
     233             :  * Mask the appropriate parts of the ondisk key field for a key comparison.
     234             :  * Fork and bmbt are significant parts of the rmap record key, but written
     235             :  * status is merely a record attribute.
     236             :  */
     237             : static inline uint64_t offset_keymask(uint64_t offset)
     238             : {
     239 11729192846 :         return offset & ~XFS_RMAP_OFF_UNWRITTEN;
     240             : }
     241             : 
     242             : STATIC int64_t
     243 15094757692 : xfs_rmapbt_key_diff(
     244             :         struct xfs_btree_cur            *cur,
     245             :         const union xfs_btree_key       *key)
     246             : {
     247 15094757692 :         struct xfs_rmap_irec            *rec = &cur->bc_rec.r;
     248 15094757692 :         const struct xfs_rmap_key       *kp = &key->rmap;
     249 15094757692 :         __u64                           x, y;
     250 15094757692 :         int64_t                         d;
     251             : 
     252 15094757692 :         d = (int64_t)be32_to_cpu(kp->rm_startblock) - rec->rm_startblock;
     253 15094757692 :         if (d)
     254             :                 return d;
     255             : 
     256  2254542934 :         x = be64_to_cpu(kp->rm_owner);
     257  2254542934 :         y = rec->rm_owner;
     258  2254542934 :         if (x > y)
     259             :                 return 1;
     260  2143944612 :         else if (y > x)
     261             :                 return -1;
     262             : 
     263  1815070548 :         x = offset_keymask(be64_to_cpu(kp->rm_offset));
     264  1815070548 :         y = offset_keymask(xfs_rmap_irec_offset_pack(rec));
     265  1815070548 :         if (x > y)
     266             :                 return 1;
     267  1552371424 :         else if (y > x)
     268   977716299 :                 return -1;
     269             :         return 0;
     270             : }
     271             : 
     272             : STATIC int64_t
     273 >30862*10^7 : xfs_rmapbt_diff_two_keys(
     274             :         struct xfs_btree_cur            *cur,
     275             :         const union xfs_btree_key       *k1,
     276             :         const union xfs_btree_key       *k2,
     277             :         const union xfs_btree_key       *mask)
     278             : {
     279 >30862*10^7 :         const struct xfs_rmap_key       *kp1 = &k1->rmap;
     280 >30862*10^7 :         const struct xfs_rmap_key       *kp2 = &k2->rmap;
     281 >30862*10^7 :         int64_t                         d;
     282 >30862*10^7 :         __u64                           x, y;
     283             : 
     284             :         /* Doesn't make sense to mask off the physical space part */
     285 >30862*10^7 :         ASSERT(!mask || mask->rmap.rm_startblock);
     286             : 
     287 >30862*10^7 :         d = (int64_t)be32_to_cpu(kp1->rm_startblock) -
     288 >30862*10^7 :                      be32_to_cpu(kp2->rm_startblock);
     289 >30862*10^7 :         if (d)
     290             :                 return d;
     291             : 
     292 18291352774 :         if (!mask || mask->rmap.rm_owner) {
     293 18291339211 :                 x = be64_to_cpu(kp1->rm_owner);
     294 18291339211 :                 y = be64_to_cpu(kp2->rm_owner);
     295 18291339211 :                 if (x > y)
     296             :                         return 1;
     297 10642248665 :                 else if (y > x)
     298             :                         return -1;
     299             :         }
     300             : 
     301  9870661775 :         if (!mask || mask->rmap.rm_offset) {
     302             :                 /* Doesn't make sense to allow offset but not owner */
     303  9870661342 :                 ASSERT(!mask || mask->rmap.rm_owner);
     304             : 
     305  9870661342 :                 x = offset_keymask(be64_to_cpu(kp1->rm_offset));
     306  9870661342 :                 y = offset_keymask(be64_to_cpu(kp2->rm_offset));
     307  9870661342 :                 if (x > y)
     308             :                         return 1;
     309  1254581092 :                 else if (y > x)
     310    72120893 :                         return -1;
     311             :         }
     312             : 
     313             :         return 0;
     314             : }
     315             : 
     316             : static xfs_failaddr_t
     317    26420582 : xfs_rmapbt_verify(
     318             :         struct xfs_buf          *bp)
     319             : {
     320    26420582 :         struct xfs_mount        *mp = bp->b_mount;
     321    26420582 :         struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
     322    26420582 :         struct xfs_perag        *pag = bp->b_pag;
     323    26420582 :         xfs_failaddr_t          fa;
     324    26420582 :         unsigned int            level;
     325             : 
     326             :         /*
     327             :          * magic number and level verification
     328             :          *
     329             :          * During growfs operations, we can't verify the exact level or owner as
     330             :          * the perag is not fully initialised and hence not attached to the
     331             :          * buffer.  In this case, check against the maximum tree depth.
     332             :          *
     333             :          * Similarly, during log recovery we will have a perag structure
     334             :          * attached, but the agf information will not yet have been initialised
     335             :          * from the on disk AGF. Again, we can only check against maximum limits
     336             :          * in this case.
     337             :          */
     338    26420582 :         if (!xfs_verify_magic(bp, block->bb_magic))
     339           0 :                 return __this_address;
     340             : 
     341    26420488 :         if (!xfs_has_rmapbt(mp))
     342           0 :                 return __this_address;
     343    26420488 :         fa = xfs_btree_sblock_v5hdr_verify(bp);
     344    26420821 :         if (fa)
     345             :                 return fa;
     346             : 
     347    26420893 :         level = be16_to_cpu(block->bb_level);
     348    52823924 :         if (pag && xfs_perag_initialised_agf(pag)) {
     349    19972734 :                 if (level >= pag->pagf_levels[XFS_BTNUM_RMAPi])
     350           0 :                         return __this_address;
     351     6448159 :         } else if (level >= mp->m_rmap_maxlevels)
     352           0 :                 return __this_address;
     353             : 
     354    26420893 :         return xfs_btree_sblock_verify(bp, mp->m_rmap_mxr[level != 0]);
     355             : }
     356             : 
     357             : static void
     358     1558987 : xfs_rmapbt_read_verify(
     359             :         struct xfs_buf  *bp)
     360             : {
     361     1558987 :         xfs_failaddr_t  fa;
     362             : 
     363     1558987 :         if (!xfs_btree_sblock_verify_crc(bp))
     364          12 :                 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
     365             :         else {
     366     1558975 :                 fa = xfs_rmapbt_verify(bp);
     367     1558975 :                 if (fa)
     368           0 :                         xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     369             :         }
     370             : 
     371     1558987 :         if (bp->b_error)
     372          12 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     373     1558987 : }
     374             : 
     375             : static void
     376    11836512 : xfs_rmapbt_write_verify(
     377             :         struct xfs_buf  *bp)
     378             : {
     379    11836512 :         xfs_failaddr_t  fa;
     380             : 
     381    11836512 :         fa = xfs_rmapbt_verify(bp);
     382    11836512 :         if (fa) {
     383           0 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     384           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     385           0 :                 return;
     386             :         }
     387    11836512 :         xfs_btree_sblock_calc_crc(bp);
     388             : 
     389             : }
     390             : 
     391             : const struct xfs_buf_ops xfs_rmapbt_buf_ops = {
     392             :         .name                   = "xfs_rmapbt",
     393             :         .magic                  = { 0, cpu_to_be32(XFS_RMAP_CRC_MAGIC) },
     394             :         .verify_read            = xfs_rmapbt_read_verify,
     395             :         .verify_write           = xfs_rmapbt_write_verify,
     396             :         .verify_struct          = xfs_rmapbt_verify,
     397             : };
     398             : 
     399             : STATIC int
     400     5194527 : xfs_rmapbt_keys_inorder(
     401             :         struct xfs_btree_cur            *cur,
     402             :         const union xfs_btree_key       *k1,
     403             :         const union xfs_btree_key       *k2)
     404             : {
     405     5194527 :         uint32_t                x;
     406     5194527 :         uint32_t                y;
     407     5194527 :         uint64_t                a;
     408     5194527 :         uint64_t                b;
     409             : 
     410     5194527 :         x = be32_to_cpu(k1->rmap.rm_startblock);
     411     5194527 :         y = be32_to_cpu(k2->rmap.rm_startblock);
     412     5194527 :         if (x < y)
     413             :                 return 1;
     414      305003 :         else if (x > y)
     415             :                 return 0;
     416      305003 :         a = be64_to_cpu(k1->rmap.rm_owner);
     417      305003 :         b = be64_to_cpu(k2->rmap.rm_owner);
     418      305003 :         if (a < b)
     419             :                 return 1;
     420      253775 :         else if (a > b)
     421             :                 return 0;
     422      253775 :         a = offset_keymask(be64_to_cpu(k1->rmap.rm_offset));
     423      253775 :         b = offset_keymask(be64_to_cpu(k2->rmap.rm_offset));
     424      253775 :         if (a <= b)
     425      253775 :                 return 1;
     426             :         return 0;
     427             : }
     428             : 
     429             : STATIC int
     430  1004787412 : xfs_rmapbt_recs_inorder(
     431             :         struct xfs_btree_cur            *cur,
     432             :         const union xfs_btree_rec       *r1,
     433             :         const union xfs_btree_rec       *r2)
     434             : {
     435  1004787412 :         uint32_t                x;
     436  1004787412 :         uint32_t                y;
     437  1004787412 :         uint64_t                a;
     438  1004787412 :         uint64_t                b;
     439             : 
     440  1004787412 :         x = be32_to_cpu(r1->rmap.rm_startblock);
     441  1004787412 :         y = be32_to_cpu(r2->rmap.rm_startblock);
     442  1004787412 :         if (x < y)
     443             :                 return 1;
     444   121503379 :         else if (x > y)
     445             :                 return 0;
     446   121503379 :         a = be64_to_cpu(r1->rmap.rm_owner);
     447   121503379 :         b = be64_to_cpu(r2->rmap.rm_owner);
     448   121503379 :         if (a < b)
     449             :                 return 1;
     450    43207181 :         else if (a > b)
     451             :                 return 0;
     452    43207181 :         a = offset_keymask(be64_to_cpu(r1->rmap.rm_offset));
     453    43207181 :         b = offset_keymask(be64_to_cpu(r2->rmap.rm_offset));
     454    43207181 :         if (a <= b)
     455    43207186 :                 return 1;
     456             :         return 0;
     457             : }
     458             : 
     459             : STATIC enum xbtree_key_contig
     460           0 : xfs_rmapbt_keys_contiguous(
     461             :         struct xfs_btree_cur            *cur,
     462             :         const union xfs_btree_key       *key1,
     463             :         const union xfs_btree_key       *key2,
     464             :         const union xfs_btree_key       *mask)
     465             : {
     466           0 :         ASSERT(!mask || mask->rmap.rm_startblock);
     467             : 
     468             :         /*
     469             :          * We only support checking contiguity of the physical space component.
     470             :          * If any callers ever need more specificity than that, they'll have to
     471             :          * implement it here.
     472             :          */
     473           0 :         ASSERT(!mask || (!mask->rmap.rm_owner && !mask->rmap.rm_offset));
     474             : 
     475           0 :         return xbtree_key_contig(be32_to_cpu(key1->rmap.rm_startblock),
     476           0 :                                  be32_to_cpu(key2->rmap.rm_startblock));
     477             : }
     478             : 
     479             : static const struct xfs_btree_ops xfs_rmapbt_ops = {
     480             :         .rec_len                = sizeof(struct xfs_rmap_rec),
     481             :         .key_len                = 2 * sizeof(struct xfs_rmap_key),
     482             : 
     483             :         .dup_cursor             = xfs_rmapbt_dup_cursor,
     484             :         .set_root               = xfs_rmapbt_set_root,
     485             :         .alloc_block            = xfs_rmapbt_alloc_block,
     486             :         .free_block             = xfs_rmapbt_free_block,
     487             :         .get_minrecs            = xfs_rmapbt_get_minrecs,
     488             :         .get_maxrecs            = xfs_rmapbt_get_maxrecs,
     489             :         .init_key_from_rec      = xfs_rmapbt_init_key_from_rec,
     490             :         .init_high_key_from_rec = xfs_rmapbt_init_high_key_from_rec,
     491             :         .init_rec_from_cur      = xfs_rmapbt_init_rec_from_cur,
     492             :         .init_ptr_from_cur      = xfs_rmapbt_init_ptr_from_cur,
     493             :         .key_diff               = xfs_rmapbt_key_diff,
     494             :         .buf_ops                = &xfs_rmapbt_buf_ops,
     495             :         .diff_two_keys          = xfs_rmapbt_diff_two_keys,
     496             :         .keys_inorder           = xfs_rmapbt_keys_inorder,
     497             :         .recs_inorder           = xfs_rmapbt_recs_inorder,
     498             :         .keys_contiguous        = xfs_rmapbt_keys_contiguous,
     499             : };
     500             : 
     501             : static struct xfs_btree_cur *
     502   840225516 : xfs_rmapbt_init_common(
     503             :         struct xfs_mount        *mp,
     504             :         struct xfs_trans        *tp,
     505             :         struct xfs_perag        *pag)
     506             : {
     507   840225516 :         struct xfs_btree_cur    *cur;
     508             : 
     509             :         /* Overlapping btree; 2 keys per pointer. */
     510   840225516 :         cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_RMAP,
     511   840225516 :                         mp->m_rmap_maxlevels, xfs_rmapbt_cur_cache);
     512   840410027 :         cur->bc_flags = XFS_BTREE_CRC_BLOCKS | XFS_BTREE_OVERLAPPING;
     513   840410027 :         cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_rmap_2);
     514   840410027 :         cur->bc_ops = &xfs_rmapbt_ops;
     515             : 
     516   840410027 :         cur->bc_ag.pag = xfs_perag_hold(pag);
     517   840547364 :         return cur;
     518             : }
     519             : 
     520             : /* Create a new reverse mapping btree cursor. */
     521             : struct xfs_btree_cur *
     522   840328647 : xfs_rmapbt_init_cursor(
     523             :         struct xfs_mount        *mp,
     524             :         struct xfs_trans        *tp,
     525             :         struct xfs_buf          *agbp,
     526             :         struct xfs_perag        *pag)
     527             : {
     528   840328647 :         struct xfs_agf          *agf = agbp->b_addr;
     529   840328647 :         struct xfs_btree_cur    *cur;
     530             : 
     531   840328647 :         cur = xfs_rmapbt_init_common(mp, tp, pag);
     532   840548218 :         cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
     533   840548218 :         cur->bc_ag.agbp = agbp;
     534   840548218 :         return cur;
     535             : }
     536             : 
     537             : /* Create a new reverse mapping btree cursor with a fake root for staging. */
     538             : struct xfs_btree_cur *
     539           0 : xfs_rmapbt_stage_cursor(
     540             :         struct xfs_mount        *mp,
     541             :         struct xbtree_afakeroot *afake,
     542             :         struct xfs_perag        *pag)
     543             : {
     544           0 :         struct xfs_btree_cur    *cur;
     545             : 
     546           0 :         cur = xfs_rmapbt_init_common(mp, NULL, pag);
     547           0 :         xfs_btree_stage_afakeroot(cur, afake);
     548           0 :         return cur;
     549             : }
     550             : 
     551             : /*
     552             :  * Install a new reverse mapping btree root.  Caller is responsible for
     553             :  * invalidating and freeing the old btree blocks.
     554             :  */
     555             : void
     556           0 : xfs_rmapbt_commit_staged_btree(
     557             :         struct xfs_btree_cur    *cur,
     558             :         struct xfs_trans        *tp,
     559             :         struct xfs_buf          *agbp)
     560             : {
     561           0 :         struct xfs_agf          *agf = agbp->b_addr;
     562           0 :         struct xbtree_afakeroot *afake = cur->bc_ag.afake;
     563             : 
     564           0 :         ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
     565             : 
     566           0 :         agf->agf_roots[cur->bc_btnum] = cpu_to_be32(afake->af_root);
     567           0 :         agf->agf_levels[cur->bc_btnum] = cpu_to_be32(afake->af_levels);
     568           0 :         agf->agf_rmap_blocks = cpu_to_be32(afake->af_blocks);
     569           0 :         xfs_alloc_log_agf(tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS |
     570             :                                     XFS_AGF_RMAP_BLOCKS);
     571           0 :         xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_rmapbt_ops);
     572           0 : }
     573             : 
     574             : /* Calculate number of records in a reverse mapping btree block. */
     575             : static inline unsigned int
     576             : xfs_rmapbt_block_maxrecs(
     577             :         unsigned int            blocklen,
     578             :         bool                    leaf)
     579             : {
     580      118830 :         if (leaf)
     581       59415 :                 return blocklen / sizeof(struct xfs_rmap_rec);
     582       59415 :         return blocklen /
     583             :                 (2 * sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t));
     584             : }
     585             : 
     586             : /*
     587             :  * Calculate number of records in an rmap btree block.
     588             :  */
     589             : int
     590      118830 : xfs_rmapbt_maxrecs(
     591             :         int                     blocklen,
     592             :         int                     leaf)
     593             : {
     594      118830 :         blocklen -= XFS_RMAP_BLOCK_LEN;
     595      118830 :         return xfs_rmapbt_block_maxrecs(blocklen, leaf);
     596             : }
     597             : 
     598             : /* Compute the max possible height for reverse mapping btrees. */
     599             : unsigned int
     600       42809 : xfs_rmapbt_maxlevels_ondisk(void)
     601             : {
     602       42809 :         unsigned int            minrecs[2];
     603       42809 :         unsigned int            blocklen;
     604             : 
     605       42809 :         blocklen = XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN;
     606             : 
     607       42809 :         minrecs[0] = xfs_rmapbt_block_maxrecs(blocklen, true) / 2;
     608       42809 :         minrecs[1] = xfs_rmapbt_block_maxrecs(blocklen, false) / 2;
     609             : 
     610             :         /*
     611             :          * Compute the asymptotic maxlevels for an rmapbt on any reflink fs.
     612             :          *
     613             :          * On a reflink filesystem, each AG block can have up to 2^32 (per the
     614             :          * refcount record format) owners, which means that theoretically we
     615             :          * could face up to 2^64 rmap records.  However, we're likely to run
     616             :          * out of blocks in the AG long before that happens, which means that
     617             :          * we must compute the max height based on what the btree will look
     618             :          * like if it consumes almost all the blocks in the AG due to maximal
     619             :          * sharing factor.
     620             :          */
     621       42809 :         return xfs_btree_space_to_height(minrecs, XFS_MAX_CRC_AG_BLOCKS);
     622             : }
     623             : 
     624             : /* Compute the maximum height of an rmap btree. */
     625             : void
     626       59405 : xfs_rmapbt_compute_maxlevels(
     627             :         struct xfs_mount                *mp)
     628             : {
     629       59405 :         if (!xfs_has_rmapbt(mp)) {
     630       16646 :                 mp->m_rmap_maxlevels = 0;
     631       16646 :                 return;
     632             :         }
     633             : 
     634       42759 :         if (xfs_has_reflink(mp)) {
     635             :                 /*
     636             :                  * Compute the asymptotic maxlevels for an rmap btree on a
     637             :                  * filesystem that supports reflink.
     638             :                  *
     639             :                  * On a reflink filesystem, each AG block can have up to 2^32
     640             :                  * (per the refcount record format) owners, which means that
     641             :                  * theoretically we could face up to 2^64 rmap records.
     642             :                  * However, we're likely to run out of blocks in the AG long
     643             :                  * before that happens, which means that we must compute the
     644             :                  * max height based on what the btree will look like if it
     645             :                  * consumes almost all the blocks in the AG due to maximal
     646             :                  * sharing factor.
     647             :                  */
     648       42759 :                 mp->m_rmap_maxlevels = xfs_btree_space_to_height(mp->m_rmap_mnr,
     649       42759 :                                 mp->m_sb.sb_agblocks);
     650             :         } else {
     651             :                 /*
     652             :                  * If there's no block sharing, compute the maximum rmapbt
     653             :                  * height assuming one rmap record per AG block.
     654             :                  */
     655           0 :                 mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(
     656           0 :                                 mp->m_rmap_mnr, mp->m_sb.sb_agblocks);
     657             :         }
     658       42759 :         ASSERT(mp->m_rmap_maxlevels <= xfs_rmapbt_maxlevels_ondisk());
     659             : }
     660             : 
     661             : /* Calculate the refcount btree size for some records. */
     662             : xfs_extlen_t
     663     2679623 : xfs_rmapbt_calc_size(
     664             :         struct xfs_mount        *mp,
     665             :         unsigned long long      len)
     666             : {
     667     3369567 :         return xfs_btree_calc_size(mp->m_rmap_mnr, len);
     668             : }
     669             : 
     670             : /*
     671             :  * Calculate the maximum refcount btree size.
     672             :  */
     673             : xfs_extlen_t
     674           0 : xfs_rmapbt_max_size(
     675             :         struct xfs_mount        *mp,
     676             :         xfs_agblock_t           agblocks)
     677             : {
     678             :         /* Bail out if we're uninitialized, which can happen in mkfs. */
     679           0 :         if (mp->m_rmap_mxr[0] == 0)
     680             :                 return 0;
     681             : 
     682      689944 :         return xfs_rmapbt_calc_size(mp, agblocks);
     683             : }
     684             : 
     685             : /*
     686             :  * Figure out how many blocks to reserve and how many are used by this btree.
     687             :  */
     688             : int
     689      850362 : xfs_rmapbt_calc_reserves(
     690             :         struct xfs_mount        *mp,
     691             :         struct xfs_trans        *tp,
     692             :         struct xfs_perag        *pag,
     693             :         xfs_extlen_t            *ask,
     694             :         xfs_extlen_t            *used)
     695             : {
     696      850362 :         struct xfs_buf          *agbp;
     697      850362 :         struct xfs_agf          *agf;
     698      850362 :         xfs_agblock_t           agblocks;
     699      850362 :         xfs_extlen_t            tree_len;
     700      850362 :         int                     error;
     701             : 
     702      850362 :         if (!xfs_has_rmapbt(mp))
     703             :                 return 0;
     704             : 
     705      689944 :         error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
     706      689944 :         if (error)
     707             :                 return error;
     708             : 
     709      689944 :         agf = agbp->b_addr;
     710      689944 :         agblocks = be32_to_cpu(agf->agf_length);
     711      689944 :         tree_len = be32_to_cpu(agf->agf_rmap_blocks);
     712      689944 :         xfs_trans_brelse(tp, agbp);
     713             : 
     714             :         /*
     715             :          * The log is permanently allocated, so the space it occupies will
     716             :          * never be available for the kinds of things that would require btree
     717             :          * expansion.  We therefore can pretend the space isn't there.
     718             :          */
     719      689944 :         if (xfs_ag_contains_log(mp, pag->pag_agno))
     720       73796 :                 agblocks -= mp->m_sb.sb_logblocks;
     721             : 
     722             :         /* Reserve 1% of the AG or enough for 1 block per record. */
     723      689944 :         *ask += max(agblocks / 100, xfs_rmapbt_max_size(mp, agblocks));
     724      689944 :         *used += tree_len;
     725             : 
     726      689944 :         return error;
     727             : }
     728             : 
     729             : int __init
     730          50 : xfs_rmapbt_init_cur_cache(void)
     731             : {
     732          50 :         xfs_rmapbt_cur_cache = kmem_cache_create("xfs_rmapbt_cur",
     733          50 :                         xfs_btree_cur_sizeof(xfs_rmapbt_maxlevels_ondisk()),
     734             :                         0, 0, NULL);
     735             : 
     736          50 :         if (!xfs_rmapbt_cur_cache)
     737           0 :                 return -ENOMEM;
     738             :         return 0;
     739             : }
     740             : 
     741             : void
     742          49 : xfs_rmapbt_destroy_cur_cache(void)
     743             : {
     744          49 :         kmem_cache_destroy(xfs_rmapbt_cur_cache);
     745          49 :         xfs_rmapbt_cur_cache = NULL;
     746          49 : }

Generated by: LCOV version 1.14