LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_alloc_btree.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwx @ Mon Jul 31 20:08:22 PDT 2023 Lines: 199 240 82.9 %
Date: 2023-07-31 20:08:22 Functions: 29 33 87.9 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (c) 2000-2001,2005 Silicon Graphics, 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_btree.h"
      14             : #include "xfs_btree_staging.h"
      15             : #include "xfs_alloc_btree.h"
      16             : #include "xfs_alloc.h"
      17             : #include "xfs_extent_busy.h"
      18             : #include "xfs_error.h"
      19             : #include "xfs_trace.h"
      20             : #include "xfs_trans.h"
      21             : #include "xfs_ag.h"
      22             : 
      23             : static struct kmem_cache        *xfs_allocbt_cur_cache;
      24             : 
      25             : STATIC struct xfs_btree_cur *
      26     7007563 : xfs_allocbt_dup_cursor(
      27             :         struct xfs_btree_cur    *cur)
      28             : {
      29     7007563 :         return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp,
      30             :                         cur->bc_ag.agbp, cur->bc_ag.pag, cur->bc_btnum);
      31             : }
      32             : 
      33             : STATIC void
      34       15248 : xfs_allocbt_set_root(
      35             :         struct xfs_btree_cur            *cur,
      36             :         const union xfs_btree_ptr       *ptr,
      37             :         int                             inc)
      38             : {
      39       15248 :         struct xfs_buf          *agbp = cur->bc_ag.agbp;
      40       15248 :         struct xfs_agf          *agf = agbp->b_addr;
      41       15248 :         int                     btnum = cur->bc_btnum;
      42             : 
      43       15248 :         ASSERT(ptr->s != 0);
      44             : 
      45       15248 :         agf->agf_roots[btnum] = ptr->s;
      46       15248 :         be32_add_cpu(&agf->agf_levels[btnum], inc);
      47       15248 :         cur->bc_ag.pag->pagf_levels[btnum] += inc;
      48             : 
      49       15248 :         xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
      50       15248 : }
      51             : 
      52             : STATIC int
      53      116765 : xfs_allocbt_alloc_block(
      54             :         struct xfs_btree_cur            *cur,
      55             :         const union xfs_btree_ptr       *start,
      56             :         union xfs_btree_ptr             *new,
      57             :         int                             *stat)
      58             : {
      59      116765 :         int                     error;
      60      116765 :         xfs_agblock_t           bno;
      61             : 
      62             :         /* Allocate the new block from the freelist. If we can't, give up.  */
      63      116765 :         error = xfs_alloc_get_freelist(cur->bc_ag.pag, cur->bc_tp,
      64             :                         cur->bc_ag.agbp, &bno, 1);
      65      116765 :         if (error)
      66             :                 return error;
      67             : 
      68      116765 :         if (bno == NULLAGBLOCK) {
      69           0 :                 *stat = 0;
      70           0 :                 return 0;
      71             :         }
      72             : 
      73      116765 :         atomic64_inc(&cur->bc_mp->m_allocbt_blks);
      74      116765 :         xfs_extent_busy_reuse(cur->bc_mp, cur->bc_ag.pag, bno, 1, false);
      75             : 
      76      116765 :         new->s = cpu_to_be32(bno);
      77             : 
      78      116765 :         *stat = 1;
      79      116765 :         return 0;
      80             : }
      81             : 
      82             : STATIC int
      83       29720 : xfs_allocbt_free_block(
      84             :         struct xfs_btree_cur    *cur,
      85             :         struct xfs_buf          *bp)
      86             : {
      87       29720 :         struct xfs_buf          *agbp = cur->bc_ag.agbp;
      88       29720 :         xfs_agblock_t           bno;
      89       29720 :         int                     error;
      90             : 
      91       29720 :         bno = xfs_daddr_to_agbno(cur->bc_mp, xfs_buf_daddr(bp));
      92       29720 :         error = xfs_alloc_put_freelist(cur->bc_ag.pag, cur->bc_tp, agbp, NULL,
      93             :                         bno, 1);
      94       29720 :         if (error)
      95             :                 return error;
      96             : 
      97       29720 :         atomic64_dec(&cur->bc_mp->m_allocbt_blks);
      98       29720 :         xfs_extent_busy_insert(cur->bc_tp, agbp->b_pag, bno, 1,
      99             :                               XFS_EXTENT_BUSY_SKIP_DISCARD);
     100       29720 :         return 0;
     101             : }
     102             : 
     103             : /*
     104             :  * Update the longest extent in the AGF
     105             :  */
     106             : STATIC void
     107   201955006 : xfs_allocbt_update_lastrec(
     108             :         struct xfs_btree_cur            *cur,
     109             :         const struct xfs_btree_block    *block,
     110             :         const union xfs_btree_rec       *rec,
     111             :         int                             ptr,
     112             :         int                             reason)
     113             : {
     114   201955006 :         struct xfs_agf          *agf = cur->bc_ag.agbp->b_addr;
     115   201955006 :         struct xfs_perag        *pag;
     116   201955006 :         __be32                  len;
     117   201955006 :         int                     numrecs;
     118             : 
     119   201955006 :         ASSERT(cur->bc_btnum == XFS_BTNUM_CNT);
     120             : 
     121   201955006 :         switch (reason) {
     122             :         case LASTREC_UPDATE:
     123             :                 /*
     124             :                  * If this is the last leaf block and it's the last record,
     125             :                  * then update the size of the longest extent in the AG.
     126             :                  */
     127           0 :                 if (ptr != xfs_btree_get_numrecs(block))
     128             :                         return;
     129           0 :                 len = rec->alloc.ar_blockcount;
     130           0 :                 break;
     131   108273671 :         case LASTREC_INSREC:
     132   108273671 :                 if (be32_to_cpu(rec->alloc.ar_blockcount) <=
     133   108273671 :                     be32_to_cpu(agf->agf_longest))
     134             :                         return;
     135             :                 len = rec->alloc.ar_blockcount;
     136             :                 break;
     137             :         case LASTREC_DELREC:
     138    93681335 :                 numrecs = xfs_btree_get_numrecs(block);
     139    93681335 :                 if (ptr <= numrecs)
     140             :                         return;
     141    20562697 :                 ASSERT(ptr == numrecs + 1);
     142             : 
     143    20562697 :                 if (numrecs) {
     144    11608721 :                         xfs_alloc_rec_t *rrp;
     145             : 
     146    11608721 :                         rrp = XFS_ALLOC_REC_ADDR(cur->bc_mp, block, numrecs);
     147    11608721 :                         len = rrp->ar_blockcount;
     148             :                 } else {
     149             :                         len = 0;
     150             :                 }
     151             : 
     152             :                 break;
     153           0 :         default:
     154           0 :                 ASSERT(0);
     155           0 :                 return;
     156             :         }
     157             : 
     158    41138509 :         agf->agf_longest = len;
     159    41138509 :         pag = cur->bc_ag.agbp->b_pag;
     160    41138509 :         pag->pagf_longest = be32_to_cpu(len);
     161    41138509 :         xfs_alloc_log_agf(cur->bc_tp, cur->bc_ag.agbp, XFS_AGF_LONGEST);
     162             : }
     163             : 
     164             : STATIC int
     165    61348866 : xfs_allocbt_get_minrecs(
     166             :         struct xfs_btree_cur    *cur,
     167             :         int                     level)
     168             : {
     169    61348866 :         return cur->bc_mp->m_alloc_mnr[level != 0];
     170             : }
     171             : 
     172             : STATIC int
     173 19761470021 : xfs_allocbt_get_maxrecs(
     174             :         struct xfs_btree_cur    *cur,
     175             :         int                     level)
     176             : {
     177 19761470021 :         return cur->bc_mp->m_alloc_mxr[level != 0];
     178             : }
     179             : 
     180             : STATIC void
     181 26714517774 : xfs_allocbt_init_key_from_rec(
     182             :         union xfs_btree_key             *key,
     183             :         const union xfs_btree_rec       *rec)
     184             : {
     185 26714517774 :         key->alloc.ar_startblock = rec->alloc.ar_startblock;
     186 26714517774 :         key->alloc.ar_blockcount = rec->alloc.ar_blockcount;
     187 26714517774 : }
     188             : 
     189             : STATIC void
     190  1482115804 : xfs_bnobt_init_high_key_from_rec(
     191             :         union xfs_btree_key             *key,
     192             :         const union xfs_btree_rec       *rec)
     193             : {
     194  1482115804 :         __u32                           x;
     195             : 
     196  1482115804 :         x = be32_to_cpu(rec->alloc.ar_startblock);
     197  1482115804 :         x += be32_to_cpu(rec->alloc.ar_blockcount) - 1;
     198  1482115804 :         key->alloc.ar_startblock = cpu_to_be32(x);
     199  1482115804 :         key->alloc.ar_blockcount = 0;
     200  1482115804 : }
     201             : 
     202             : STATIC void
     203           0 : xfs_cntbt_init_high_key_from_rec(
     204             :         union xfs_btree_key             *key,
     205             :         const union xfs_btree_rec       *rec)
     206             : {
     207           0 :         key->alloc.ar_blockcount = rec->alloc.ar_blockcount;
     208           0 :         key->alloc.ar_startblock = 0;
     209           0 : }
     210             : 
     211             : STATIC void
     212  6093540374 : xfs_allocbt_init_rec_from_cur(
     213             :         struct xfs_btree_cur    *cur,
     214             :         union xfs_btree_rec     *rec)
     215             : {
     216  6093540374 :         rec->alloc.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock);
     217  6093540374 :         rec->alloc.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount);
     218  6093540374 : }
     219             : 
     220             : STATIC void
     221  2481299162 : xfs_allocbt_init_ptr_from_cur(
     222             :         struct xfs_btree_cur    *cur,
     223             :         union xfs_btree_ptr     *ptr)
     224             : {
     225  2481299162 :         struct xfs_agf          *agf = cur->bc_ag.agbp->b_addr;
     226             : 
     227  2481299162 :         ASSERT(cur->bc_ag.pag->pag_agno == be32_to_cpu(agf->agf_seqno));
     228             : 
     229  2481299162 :         ptr->s = agf->agf_roots[cur->bc_btnum];
     230  2482625733 : }
     231             : 
     232             : STATIC int64_t
     233 17139378236 : xfs_bnobt_key_diff(
     234             :         struct xfs_btree_cur            *cur,
     235             :         const union xfs_btree_key       *key)
     236             : {
     237 17139378236 :         struct xfs_alloc_rec_incore     *rec = &cur->bc_rec.a;
     238 17139378236 :         const struct xfs_alloc_rec      *kp = &key->alloc;
     239             : 
     240 17139378236 :         return (int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock;
     241             : }
     242             : 
     243             : STATIC int64_t
     244  5617809228 : xfs_cntbt_key_diff(
     245             :         struct xfs_btree_cur            *cur,
     246             :         const union xfs_btree_key       *key)
     247             : {
     248  5617809228 :         struct xfs_alloc_rec_incore     *rec = &cur->bc_rec.a;
     249  5617809228 :         const struct xfs_alloc_rec      *kp = &key->alloc;
     250  5617809228 :         int64_t                         diff;
     251             : 
     252  5617809228 :         diff = (int64_t)be32_to_cpu(kp->ar_blockcount) - rec->ar_blockcount;
     253  5617809228 :         if (diff)
     254             :                 return diff;
     255             : 
     256  3110104037 :         return (int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock;
     257             : }
     258             : 
     259             : STATIC int64_t
     260  6787445855 : xfs_bnobt_diff_two_keys(
     261             :         struct xfs_btree_cur            *cur,
     262             :         const union xfs_btree_key       *k1,
     263             :         const union xfs_btree_key       *k2,
     264             :         const union xfs_btree_key       *mask)
     265             : {
     266  6787445855 :         ASSERT(!mask || mask->alloc.ar_startblock);
     267             : 
     268  6787445855 :         return (int64_t)be32_to_cpu(k1->alloc.ar_startblock) -
     269  6787445855 :                         be32_to_cpu(k2->alloc.ar_startblock);
     270             : }
     271             : 
     272             : STATIC int64_t
     273   155777495 : xfs_cntbt_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   155777495 :         int64_t                         diff;
     280             : 
     281   155777495 :         ASSERT(!mask || (mask->alloc.ar_blockcount &&
     282             :                          mask->alloc.ar_startblock));
     283             : 
     284   155777495 :         diff =  be32_to_cpu(k1->alloc.ar_blockcount) -
     285   155777495 :                 be32_to_cpu(k2->alloc.ar_blockcount);
     286   155777495 :         if (diff)
     287             :                 return diff;
     288             : 
     289   108255496 :         return  be32_to_cpu(k1->alloc.ar_startblock) -
     290   108255496 :                 be32_to_cpu(k2->alloc.ar_startblock);
     291             : }
     292             : 
     293             : static xfs_failaddr_t
     294    10520950 : xfs_allocbt_verify(
     295             :         struct xfs_buf          *bp)
     296             : {
     297    10520950 :         struct xfs_mount        *mp = bp->b_mount;
     298    10520950 :         struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
     299    10520950 :         struct xfs_perag        *pag = bp->b_pag;
     300    10520950 :         xfs_failaddr_t          fa;
     301    10520950 :         unsigned int            level;
     302    10520950 :         xfs_btnum_t             btnum = XFS_BTNUM_BNOi;
     303             : 
     304    10520950 :         if (!xfs_verify_magic(bp, block->bb_magic))
     305           0 :                 return __this_address;
     306             : 
     307    10519518 :         if (xfs_has_crc(mp)) {
     308    10492696 :                 fa = xfs_btree_sblock_v5hdr_verify(bp);
     309    10493749 :                 if (fa)
     310             :                         return fa;
     311             :         }
     312             : 
     313             :         /*
     314             :          * The perag may not be attached during grow operations or fully
     315             :          * initialized from the AGF during log recovery. Therefore we can only
     316             :          * check against maximum tree depth from those contexts.
     317             :          *
     318             :          * Otherwise check against the per-tree limit. Peek at one of the
     319             :          * verifier magic values to determine the type of tree we're verifying
     320             :          * against.
     321             :          */
     322    10520679 :         level = be16_to_cpu(block->bb_level);
     323    10520679 :         if (bp->b_ops->magic[0] == cpu_to_be32(XFS_ABTC_MAGIC))
     324     5765436 :                 btnum = XFS_BTNUM_CNTi;
     325    20978148 :         if (pag && xfs_perag_initialised_agf(pag)) {
     326     6235689 :                 if (level >= pag->pagf_levels[btnum])
     327           0 :                         return __this_address;
     328     4284993 :         } else if (level >= mp->m_alloc_maxlevels)
     329           0 :                 return __this_address;
     330             : 
     331    10520635 :         return xfs_btree_sblock_verify(bp, mp->m_alloc_mxr[level != 0]);
     332             : }
     333             : 
     334             : static void
     335      797724 : xfs_allocbt_read_verify(
     336             :         struct xfs_buf  *bp)
     337             : {
     338      797724 :         xfs_failaddr_t  fa;
     339             : 
     340      797724 :         if (!xfs_btree_sblock_verify_crc(bp))
     341        1280 :                 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
     342             :         else {
     343      796444 :                 fa = xfs_allocbt_verify(bp);
     344      796444 :                 if (fa)
     345           0 :                         xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     346             :         }
     347             : 
     348      797724 :         if (bp->b_error)
     349        1280 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     350      797724 : }
     351             : 
     352             : static void
     353     5760312 : xfs_allocbt_write_verify(
     354             :         struct xfs_buf  *bp)
     355             : {
     356     5760312 :         xfs_failaddr_t  fa;
     357             : 
     358     5760312 :         fa = xfs_allocbt_verify(bp);
     359     5760312 :         if (fa) {
     360           0 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     361           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     362           0 :                 return;
     363             :         }
     364     5760312 :         xfs_btree_sblock_calc_crc(bp);
     365             : 
     366             : }
     367             : 
     368             : const struct xfs_buf_ops xfs_bnobt_buf_ops = {
     369             :         .name = "xfs_bnobt",
     370             :         .magic = { cpu_to_be32(XFS_ABTB_MAGIC),
     371             :                    cpu_to_be32(XFS_ABTB_CRC_MAGIC) },
     372             :         .verify_read = xfs_allocbt_read_verify,
     373             :         .verify_write = xfs_allocbt_write_verify,
     374             :         .verify_struct = xfs_allocbt_verify,
     375             : };
     376             : 
     377             : const struct xfs_buf_ops xfs_cntbt_buf_ops = {
     378             :         .name = "xfs_cntbt",
     379             :         .magic = { cpu_to_be32(XFS_ABTC_MAGIC),
     380             :                    cpu_to_be32(XFS_ABTC_CRC_MAGIC) },
     381             :         .verify_read = xfs_allocbt_read_verify,
     382             :         .verify_write = xfs_allocbt_write_verify,
     383             :         .verify_struct = xfs_allocbt_verify,
     384             : };
     385             : 
     386             : STATIC int
     387      383044 : xfs_bnobt_keys_inorder(
     388             :         struct xfs_btree_cur            *cur,
     389             :         const union xfs_btree_key       *k1,
     390             :         const union xfs_btree_key       *k2)
     391             : {
     392      383044 :         return be32_to_cpu(k1->alloc.ar_startblock) <
     393      383044 :                be32_to_cpu(k2->alloc.ar_startblock);
     394             : }
     395             : 
     396             : STATIC int
     397   266652741 : xfs_bnobt_recs_inorder(
     398             :         struct xfs_btree_cur            *cur,
     399             :         const union xfs_btree_rec       *r1,
     400             :         const union xfs_btree_rec       *r2)
     401             : {
     402   266652741 :         return be32_to_cpu(r1->alloc.ar_startblock) +
     403   266652741 :                 be32_to_cpu(r1->alloc.ar_blockcount) <=
     404   266652741 :                 be32_to_cpu(r2->alloc.ar_startblock);
     405             : }
     406             : 
     407             : STATIC int
     408      396126 : xfs_cntbt_keys_inorder(
     409             :         struct xfs_btree_cur            *cur,
     410             :         const union xfs_btree_key       *k1,
     411             :         const union xfs_btree_key       *k2)
     412             : {
     413      396126 :         return be32_to_cpu(k1->alloc.ar_blockcount) <
     414      396126 :                 be32_to_cpu(k2->alloc.ar_blockcount) ||
     415      218333 :                 (k1->alloc.ar_blockcount == k2->alloc.ar_blockcount &&
     416      218333 :                  be32_to_cpu(k1->alloc.ar_startblock) <
     417      218333 :                  be32_to_cpu(k2->alloc.ar_startblock));
     418             : }
     419             : 
     420             : STATIC int
     421   390431483 : xfs_cntbt_recs_inorder(
     422             :         struct xfs_btree_cur            *cur,
     423             :         const union xfs_btree_rec       *r1,
     424             :         const union xfs_btree_rec       *r2)
     425             : {
     426   390431483 :         return be32_to_cpu(r1->alloc.ar_blockcount) <
     427   390431483 :                 be32_to_cpu(r2->alloc.ar_blockcount) ||
     428   291120797 :                 (r1->alloc.ar_blockcount == r2->alloc.ar_blockcount &&
     429   291120797 :                  be32_to_cpu(r1->alloc.ar_startblock) <
     430   291120797 :                  be32_to_cpu(r2->alloc.ar_startblock));
     431             : }
     432             : 
     433             : STATIC enum xbtree_key_contig
     434           0 : xfs_allocbt_keys_contiguous(
     435             :         struct xfs_btree_cur            *cur,
     436             :         const union xfs_btree_key       *key1,
     437             :         const union xfs_btree_key       *key2,
     438             :         const union xfs_btree_key       *mask)
     439             : {
     440           0 :         ASSERT(!mask || mask->alloc.ar_startblock);
     441             : 
     442           0 :         return xbtree_key_contig(be32_to_cpu(key1->alloc.ar_startblock),
     443           0 :                                  be32_to_cpu(key2->alloc.ar_startblock));
     444             : }
     445             : 
     446             : static const struct xfs_btree_ops xfs_bnobt_ops = {
     447             :         .rec_len                = sizeof(xfs_alloc_rec_t),
     448             :         .key_len                = sizeof(xfs_alloc_key_t),
     449             : 
     450             :         .dup_cursor             = xfs_allocbt_dup_cursor,
     451             :         .set_root               = xfs_allocbt_set_root,
     452             :         .alloc_block            = xfs_allocbt_alloc_block,
     453             :         .free_block             = xfs_allocbt_free_block,
     454             :         .update_lastrec         = xfs_allocbt_update_lastrec,
     455             :         .get_minrecs            = xfs_allocbt_get_minrecs,
     456             :         .get_maxrecs            = xfs_allocbt_get_maxrecs,
     457             :         .init_key_from_rec      = xfs_allocbt_init_key_from_rec,
     458             :         .init_high_key_from_rec = xfs_bnobt_init_high_key_from_rec,
     459             :         .init_rec_from_cur      = xfs_allocbt_init_rec_from_cur,
     460             :         .init_ptr_from_cur      = xfs_allocbt_init_ptr_from_cur,
     461             :         .key_diff               = xfs_bnobt_key_diff,
     462             :         .buf_ops                = &xfs_bnobt_buf_ops,
     463             :         .diff_two_keys          = xfs_bnobt_diff_two_keys,
     464             :         .keys_inorder           = xfs_bnobt_keys_inorder,
     465             :         .recs_inorder           = xfs_bnobt_recs_inorder,
     466             :         .keys_contiguous        = xfs_allocbt_keys_contiguous,
     467             : };
     468             : 
     469             : static const struct xfs_btree_ops xfs_cntbt_ops = {
     470             :         .rec_len                = sizeof(xfs_alloc_rec_t),
     471             :         .key_len                = sizeof(xfs_alloc_key_t),
     472             : 
     473             :         .dup_cursor             = xfs_allocbt_dup_cursor,
     474             :         .set_root               = xfs_allocbt_set_root,
     475             :         .alloc_block            = xfs_allocbt_alloc_block,
     476             :         .free_block             = xfs_allocbt_free_block,
     477             :         .update_lastrec         = xfs_allocbt_update_lastrec,
     478             :         .get_minrecs            = xfs_allocbt_get_minrecs,
     479             :         .get_maxrecs            = xfs_allocbt_get_maxrecs,
     480             :         .init_key_from_rec      = xfs_allocbt_init_key_from_rec,
     481             :         .init_high_key_from_rec = xfs_cntbt_init_high_key_from_rec,
     482             :         .init_rec_from_cur      = xfs_allocbt_init_rec_from_cur,
     483             :         .init_ptr_from_cur      = xfs_allocbt_init_ptr_from_cur,
     484             :         .key_diff               = xfs_cntbt_key_diff,
     485             :         .buf_ops                = &xfs_cntbt_buf_ops,
     486             :         .diff_two_keys          = xfs_cntbt_diff_two_keys,
     487             :         .keys_inorder           = xfs_cntbt_keys_inorder,
     488             :         .recs_inorder           = xfs_cntbt_recs_inorder,
     489             :         .keys_contiguous        = NULL, /* not needed right now */
     490             : };
     491             : 
     492             : /* Allocate most of a new allocation btree cursor. */
     493             : STATIC struct xfs_btree_cur *
     494  1712727727 : xfs_allocbt_init_common(
     495             :         struct xfs_mount        *mp,
     496             :         struct xfs_trans        *tp,
     497             :         struct xfs_perag        *pag,
     498             :         xfs_btnum_t             btnum)
     499             : {
     500  1712727727 :         struct xfs_btree_cur    *cur;
     501             : 
     502  1712727727 :         ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT);
     503             : 
     504  1712727727 :         cur = xfs_btree_alloc_cursor(mp, tp, btnum, mp->m_alloc_maxlevels,
     505             :                         xfs_allocbt_cur_cache);
     506  1713369211 :         cur->bc_ag.abt.active = false;
     507             : 
     508  1713369211 :         if (btnum == XFS_BTNUM_CNT) {
     509   827708170 :                 cur->bc_ops = &xfs_cntbt_ops;
     510   827708170 :                 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_abtc_2);
     511   827708170 :                 cur->bc_flags = XFS_BTREE_LASTREC_UPDATE;
     512             :         } else {
     513   885661041 :                 cur->bc_ops = &xfs_bnobt_ops;
     514   885661041 :                 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_abtb_2);
     515             :         }
     516             : 
     517  1713369211 :         cur->bc_ag.pag = xfs_perag_hold(pag);
     518             : 
     519  1713550167 :         if (xfs_has_crc(mp))
     520  1713619478 :                 cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
     521             : 
     522  1713550167 :         return cur;
     523             : }
     524             : 
     525             : /*
     526             :  * Allocate a new allocation btree cursor.
     527             :  */
     528             : struct xfs_btree_cur *                  /* new alloc btree cursor */
     529  1713049215 : xfs_allocbt_init_cursor(
     530             :         struct xfs_mount        *mp,            /* file system mount point */
     531             :         struct xfs_trans        *tp,            /* transaction pointer */
     532             :         struct xfs_buf          *agbp,          /* buffer for agf structure */
     533             :         struct xfs_perag        *pag,
     534             :         xfs_btnum_t             btnum)          /* btree identifier */
     535             : {
     536  1713049215 :         struct xfs_agf          *agf = agbp->b_addr;
     537  1713049215 :         struct xfs_btree_cur    *cur;
     538             : 
     539  1713049215 :         cur = xfs_allocbt_init_common(mp, tp, pag, btnum);
     540  1713631439 :         if (btnum == XFS_BTNUM_CNT)
     541   827961317 :                 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]);
     542             :         else
     543   885670122 :                 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]);
     544             : 
     545  1713631439 :         cur->bc_ag.agbp = agbp;
     546             : 
     547  1713631439 :         return cur;
     548             : }
     549             : 
     550             : /* Create a free space btree cursor with a fake root for staging. */
     551             : struct xfs_btree_cur *
     552           0 : xfs_allocbt_stage_cursor(
     553             :         struct xfs_mount        *mp,
     554             :         struct xbtree_afakeroot *afake,
     555             :         struct xfs_perag        *pag,
     556             :         xfs_btnum_t             btnum)
     557             : {
     558           0 :         struct xfs_btree_cur    *cur;
     559             : 
     560           0 :         cur = xfs_allocbt_init_common(mp, NULL, pag, btnum);
     561           0 :         xfs_btree_stage_afakeroot(cur, afake);
     562           0 :         return cur;
     563             : }
     564             : 
     565             : /*
     566             :  * Install a new free space btree root.  Caller is responsible for invalidating
     567             :  * and freeing the old btree blocks.
     568             :  */
     569             : void
     570           0 : xfs_allocbt_commit_staged_btree(
     571             :         struct xfs_btree_cur    *cur,
     572             :         struct xfs_trans        *tp,
     573             :         struct xfs_buf          *agbp)
     574             : {
     575           0 :         struct xfs_agf          *agf = agbp->b_addr;
     576           0 :         struct xbtree_afakeroot *afake = cur->bc_ag.afake;
     577             : 
     578           0 :         ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
     579             : 
     580           0 :         agf->agf_roots[cur->bc_btnum] = cpu_to_be32(afake->af_root);
     581           0 :         agf->agf_levels[cur->bc_btnum] = cpu_to_be32(afake->af_levels);
     582           0 :         xfs_alloc_log_agf(tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
     583             : 
     584           0 :         if (cur->bc_btnum == XFS_BTNUM_BNO) {
     585           0 :                 xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_bnobt_ops);
     586             :         } else {
     587           0 :                 cur->bc_flags |= XFS_BTREE_LASTREC_UPDATE;
     588           0 :                 xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_cntbt_ops);
     589             :         }
     590           0 : }
     591             : 
     592             : /* Calculate number of records in an alloc btree block. */
     593             : static inline unsigned int
     594             : xfs_allocbt_block_maxrecs(
     595             :         unsigned int            blocklen,
     596             :         bool                    leaf)
     597             : {
     598      118830 :         if (leaf)
     599       59415 :                 return blocklen / sizeof(xfs_alloc_rec_t);
     600       59415 :         return blocklen / (sizeof(xfs_alloc_key_t) + sizeof(xfs_alloc_ptr_t));
     601             : }
     602             : 
     603             : /*
     604             :  * Calculate number of records in an alloc btree block.
     605             :  */
     606             : int
     607      118830 : xfs_allocbt_maxrecs(
     608             :         struct xfs_mount        *mp,
     609             :         int                     blocklen,
     610             :         int                     leaf)
     611             : {
     612      118830 :         blocklen -= XFS_ALLOC_BLOCK_LEN(mp);
     613      118830 :         return xfs_allocbt_block_maxrecs(blocklen, leaf);
     614             : }
     615             : 
     616             : /* Free space btrees are at their largest when every other block is free. */
     617             : #define XFS_MAX_FREESP_RECORDS  ((XFS_MAX_AG_BLOCKS + 1) / 2)
     618             : 
     619             : /* Compute the max possible height for free space btrees. */
     620             : unsigned int
     621       59455 : xfs_allocbt_maxlevels_ondisk(void)
     622             : {
     623       59455 :         unsigned int            minrecs[2];
     624       59455 :         unsigned int            blocklen;
     625             : 
     626       59455 :         blocklen = min(XFS_MIN_BLOCKSIZE - XFS_BTREE_SBLOCK_LEN,
     627             :                        XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN);
     628             : 
     629       59455 :         minrecs[0] = xfs_allocbt_block_maxrecs(blocklen, true) / 2;
     630       59455 :         minrecs[1] = xfs_allocbt_block_maxrecs(blocklen, false) / 2;
     631             : 
     632       59455 :         return xfs_btree_compute_maxlevels(minrecs, XFS_MAX_FREESP_RECORDS);
     633             : }
     634             : 
     635             : /* Calculate the freespace btree size for some records. */
     636             : xfs_extlen_t
     637     3558790 : xfs_allocbt_calc_size(
     638             :         struct xfs_mount        *mp,
     639             :         unsigned long long      len)
     640             : {
     641     3558790 :         return xfs_btree_calc_size(mp->m_alloc_mnr, len);
     642             : }
     643             : 
     644             : int __init
     645          50 : xfs_allocbt_init_cur_cache(void)
     646             : {
     647          50 :         xfs_allocbt_cur_cache = kmem_cache_create("xfs_bnobt_cur",
     648          50 :                         xfs_btree_cur_sizeof(xfs_allocbt_maxlevels_ondisk()),
     649             :                         0, 0, NULL);
     650             : 
     651          50 :         if (!xfs_allocbt_cur_cache)
     652           0 :                 return -ENOMEM;
     653             :         return 0;
     654             : }
     655             : 
     656             : void
     657          49 : xfs_allocbt_destroy_cur_cache(void)
     658             : {
     659          49 :         kmem_cache_destroy(xfs_allocbt_cur_cache);
     660          49 :         xfs_allocbt_cur_cache = NULL;
     661          49 : }

Generated by: LCOV version 1.14