LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_bmap_btree.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 274 306 89.5 %
Date: 2023-07-31 20:08:07 Functions: 34 36 94.4 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (c) 2000-2003,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_bit.h"
      13             : #include "xfs_mount.h"
      14             : #include "xfs_inode.h"
      15             : #include "xfs_trans.h"
      16             : #include "xfs_alloc.h"
      17             : #include "xfs_btree.h"
      18             : #include "xfs_btree_staging.h"
      19             : #include "xfs_bmap_btree.h"
      20             : #include "xfs_bmap.h"
      21             : #include "xfs_error.h"
      22             : #include "xfs_quota.h"
      23             : #include "xfs_trace.h"
      24             : #include "xfs_rmap.h"
      25             : #include "xfs_ag.h"
      26             : 
      27             : static struct kmem_cache        *xfs_bmbt_cur_cache;
      28             : 
      29             : /*
      30             :  * Convert on-disk form of btree root to in-memory form.
      31             :  */
      32             : void
      33    11005976 : xfs_bmdr_to_bmbt(
      34             :         struct xfs_inode        *ip,
      35             :         xfs_bmdr_block_t        *dblock,
      36             :         int                     dblocklen,
      37             :         struct xfs_btree_block  *rblock,
      38             :         int                     rblocklen)
      39             : {
      40    11005976 :         struct xfs_mount        *mp = ip->i_mount;
      41    11005976 :         int                     dmxr;
      42    11005976 :         xfs_bmbt_key_t          *fkp;
      43    11005976 :         __be64                  *fpp;
      44    11005976 :         xfs_bmbt_key_t          *tkp;
      45    11005976 :         __be64                  *tpp;
      46             : 
      47    11005976 :         xfs_btree_init_block(mp, rblock, &xfs_bmbt_ops, 0, 0, ip->i_ino);
      48    11005991 :         rblock->bb_level = dblock->bb_level;
      49    11005991 :         ASSERT(be16_to_cpu(rblock->bb_level) > 0);
      50    11005991 :         rblock->bb_numrecs = dblock->bb_numrecs;
      51    11005991 :         dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
      52    11005991 :         fkp = XFS_BMDR_KEY_ADDR(dblock, 1);
      53    22011982 :         tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
      54    11005991 :         fpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr);
      55    11005991 :         tpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen);
      56    11005991 :         dmxr = be16_to_cpu(dblock->bb_numrecs);
      57    22011982 :         memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
      58    22011982 :         memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
      59    11005991 : }
      60             : 
      61             : void
      62  1529244165 : xfs_bmbt_disk_get_all(
      63             :         const struct xfs_bmbt_rec *rec,
      64             :         struct xfs_bmbt_irec    *irec)
      65             : {
      66  1529244165 :         uint64_t                l0 = get_unaligned_be64(&rec->l0);
      67             :         uint64_t                l1 = get_unaligned_be64(&rec->l1);
      68             : 
      69  1529244165 :         irec->br_startoff = (l0 & xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
      70  1529244165 :         irec->br_startblock = ((l0 & xfs_mask64lo(9)) << 43) | (l1 >> 21);
      71  1529244165 :         irec->br_blockcount = l1 & xfs_mask64lo(21);
      72  1529244165 :         if (l0 >> (64 - BMBT_EXNTFLAG_BITLEN))
      73   112846944 :                 irec->br_state = XFS_EXT_UNWRITTEN;
      74             :         else
      75  1416397221 :                 irec->br_state = XFS_EXT_NORM;
      76  1529244165 : }
      77             : 
      78             : /*
      79             :  * Extract the blockcount field from an on disk bmap extent record.
      80             :  */
      81             : xfs_filblks_t
      82 >10368*10^7 : xfs_bmbt_disk_get_blockcount(
      83             :         const struct xfs_bmbt_rec       *r)
      84             : {
      85 >10368*10^7 :         return (xfs_filblks_t)(be64_to_cpu(r->l1) & xfs_mask64lo(21));
      86             : }
      87             : 
      88             : /*
      89             :  * Extract the startoff field from a disk format bmap extent record.
      90             :  */
      91             : xfs_fileoff_t
      92 >20854*10^7 : xfs_bmbt_disk_get_startoff(
      93             :         const struct xfs_bmbt_rec       *r)
      94             : {
      95 >20854*10^7 :         return ((xfs_fileoff_t)be64_to_cpu(r->l0) &
      96 >20854*10^7 :                  xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
      97             : }
      98             : 
      99             : /*
     100             :  * Set all the fields in a bmap extent record from the uncompressed form.
     101             :  */
     102             : void
     103  1042173546 : xfs_bmbt_disk_set_all(
     104             :         struct xfs_bmbt_rec     *r,
     105             :         struct xfs_bmbt_irec    *s)
     106             : {
     107  1042173546 :         int                     extent_flag = (s->br_state != XFS_EXT_NORM);
     108             : 
     109  1042173546 :         ASSERT(s->br_state == XFS_EXT_NORM || s->br_state == XFS_EXT_UNWRITTEN);
     110  1042173546 :         ASSERT(!(s->br_startoff & xfs_mask64hi(64-BMBT_STARTOFF_BITLEN)));
     111  1042173546 :         ASSERT(!(s->br_blockcount & xfs_mask64hi(64-BMBT_BLOCKCOUNT_BITLEN)));
     112  1042173546 :         ASSERT(!(s->br_startblock & xfs_mask64hi(64-BMBT_STARTBLOCK_BITLEN)));
     113             : 
     114  1042173546 :         put_unaligned_be64(
     115  1042173546 :                 ((xfs_bmbt_rec_base_t)extent_flag << 63) |
     116  1042173546 :                  ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
     117  1042173546 :                  ((xfs_bmbt_rec_base_t)s->br_startblock >> 43), &r->l0);
     118  1042177817 :         put_unaligned_be64(
     119  1042177817 :                 ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
     120  1042177817 :                  ((xfs_bmbt_rec_base_t)s->br_blockcount &
     121  1042177817 :                   (xfs_bmbt_rec_base_t)xfs_mask64lo(21)), &r->l1);
     122  1042184446 : }
     123             : 
     124             : /*
     125             :  * Convert in-memory form of btree root to on-disk form.
     126             :  */
     127             : void
     128     1157765 : xfs_bmbt_to_bmdr(
     129             :         struct xfs_mount        *mp,
     130             :         struct xfs_btree_block  *rblock,
     131             :         int                     rblocklen,
     132             :         xfs_bmdr_block_t        *dblock,
     133             :         int                     dblocklen)
     134             : {
     135     1157765 :         int                     dmxr;
     136     1157765 :         xfs_bmbt_key_t          *fkp;
     137     1157765 :         __be64                  *fpp;
     138     1157765 :         xfs_bmbt_key_t          *tkp;
     139     1157765 :         __be64                  *tpp;
     140             : 
     141     1157765 :         if (xfs_has_crc(mp)) {
     142     1157765 :                 ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC));
     143     1157765 :                 ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid,
     144             :                        &mp->m_sb.sb_meta_uuid));
     145     1157765 :                 ASSERT(rblock->bb_u.l.bb_blkno ==
     146             :                        cpu_to_be64(XFS_BUF_DADDR_NULL));
     147             :         } else
     148           0 :                 ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_MAGIC));
     149     1157765 :         ASSERT(rblock->bb_u.l.bb_leftsib == cpu_to_be64(NULLFSBLOCK));
     150     1157765 :         ASSERT(rblock->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK));
     151     1157765 :         ASSERT(rblock->bb_level != 0);
     152     1157765 :         dblock->bb_level = rblock->bb_level;
     153     1157765 :         dblock->bb_numrecs = rblock->bb_numrecs;
     154     1157765 :         dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
     155     2315530 :         fkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
     156     1157765 :         tkp = XFS_BMDR_KEY_ADDR(dblock, 1);
     157     1157765 :         fpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen);
     158     1157765 :         tpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr);
     159     1157765 :         dmxr = be16_to_cpu(dblock->bb_numrecs);
     160     2315530 :         memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
     161     2315530 :         memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
     162     1157765 : }
     163             : 
     164             : STATIC struct xfs_btree_cur *
     165    43717121 : xfs_bmbt_dup_cursor(
     166             :         struct xfs_btree_cur    *cur)
     167             : {
     168    43717121 :         struct xfs_btree_cur    *new;
     169             : 
     170    43717121 :         new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp,
     171    43717121 :                         cur->bc_ino.ip, cur->bc_ino.whichfork);
     172             : 
     173             :         /*
     174             :          * Copy the firstblock, dfops, and flags values,
     175             :          * since init cursor doesn't get them.
     176             :          */
     177    43717089 :         new->bc_ino.flags = cur->bc_ino.flags;
     178             : 
     179    43717089 :         return new;
     180             : }
     181             : 
     182             : STATIC void
     183      215957 : xfs_bmbt_update_cursor(
     184             :         struct xfs_btree_cur    *src,
     185             :         struct xfs_btree_cur    *dst)
     186             : {
     187      215957 :         ASSERT((dst->bc_tp->t_highest_agno != NULLAGNUMBER) ||
     188             :                (dst->bc_ino.ip->i_diflags & XFS_DIFLAG_REALTIME));
     189             : 
     190      215957 :         dst->bc_ino.allocated += src->bc_ino.allocated;
     191      215957 :         dst->bc_tp->t_highest_agno = src->bc_tp->t_highest_agno;
     192             : 
     193      215957 :         src->bc_ino.allocated = 0;
     194      215957 : }
     195             : 
     196             : STATIC int
     197      218411 : xfs_bmbt_alloc_block(
     198             :         struct xfs_btree_cur            *cur,
     199             :         const union xfs_btree_ptr       *start,
     200             :         union xfs_btree_ptr             *new,
     201             :         int                             *stat)
     202             : {
     203      218411 :         struct xfs_alloc_arg    args;
     204      218411 :         int                     error;
     205             : 
     206      218411 :         memset(&args, 0, sizeof(args));
     207      218411 :         args.tp = cur->bc_tp;
     208      218411 :         args.mp = cur->bc_mp;
     209      218411 :         xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_ino.ip->i_ino,
     210      218411 :                         cur->bc_ino.whichfork);
     211      218411 :         args.minlen = args.maxlen = args.prod = 1;
     212      218411 :         args.wasdel = cur->bc_ino.flags & XFS_BTCUR_BMBT_WASDEL;
     213      218411 :         if (!args.wasdel && args.tp->t_blk_res == 0)
     214             :                 return -ENOSPC;
     215             : 
     216             :         /*
     217             :          * If we are coming here from something like unwritten extent
     218             :          * conversion, there has been no data extent allocation already done, so
     219             :          * we have to ensure that we attempt to locate the entire set of bmbt
     220             :          * allocations in the same AG, as xfs_bmapi_write() would have reserved.
     221             :          */
     222      218411 :         if (cur->bc_tp->t_highest_agno == NULLAGNUMBER)
     223      203529 :                 args.minleft = xfs_bmapi_minleft(cur->bc_tp, cur->bc_ino.ip,
     224             :                                         cur->bc_ino.whichfork);
     225             : 
     226      218411 :         error = xfs_alloc_vextent_start_ag(&args, be64_to_cpu(start->l));
     227      218411 :         if (error)
     228             :                 return error;
     229             : 
     230      218411 :         if (args.fsbno == NULLFSBLOCK && args.minleft) {
     231             :                 /*
     232             :                  * Could not find an AG with enough free space to satisfy
     233             :                  * a full btree split.  Try again and if
     234             :                  * successful activate the lowspace algorithm.
     235             :                  */
     236           0 :                 args.minleft = 0;
     237           0 :                 error = xfs_alloc_vextent_start_ag(&args, 0);
     238           0 :                 if (error)
     239             :                         return error;
     240           0 :                 cur->bc_tp->t_flags |= XFS_TRANS_LOWMODE;
     241             :         }
     242      218411 :         if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
     243           0 :                 *stat = 0;
     244           0 :                 return 0;
     245             :         }
     246             : 
     247      218411 :         ASSERT(args.len == 1);
     248      218411 :         cur->bc_ino.allocated++;
     249      218411 :         cur->bc_ino.ip->i_nblocks++;
     250      218411 :         xfs_trans_log_inode(args.tp, cur->bc_ino.ip, XFS_ILOG_CORE);
     251      218411 :         xfs_trans_mod_dquot_byino(args.tp, cur->bc_ino.ip,
     252             :                         XFS_TRANS_DQ_BCOUNT, 1L);
     253             : 
     254      218411 :         new->l = cpu_to_be64(args.fsbno);
     255             : 
     256      218411 :         *stat = 1;
     257      218411 :         return 0;
     258             : }
     259             : 
     260             : STATIC int
     261      155675 : xfs_bmbt_free_block(
     262             :         struct xfs_btree_cur    *cur,
     263             :         struct xfs_buf          *bp)
     264             : {
     265      155675 :         struct xfs_mount        *mp = cur->bc_mp;
     266      155675 :         struct xfs_inode        *ip = cur->bc_ino.ip;
     267      155675 :         struct xfs_trans        *tp = cur->bc_tp;
     268      155675 :         xfs_fsblock_t           fsbno = XFS_DADDR_TO_FSB(mp, xfs_buf_daddr(bp));
     269      155675 :         struct xfs_owner_info   oinfo;
     270      155675 :         int                     error;
     271             : 
     272      155675 :         xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_ino.whichfork);
     273      155675 :         error = xfs_free_extent_later(cur->bc_tp, fsbno, 1, &oinfo,
     274             :                         XFS_AG_RESV_NONE);
     275      155675 :         if (error)
     276             :                 return error;
     277             : 
     278      155675 :         ip->i_nblocks--;
     279      155675 :         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
     280      155675 :         xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
     281      155675 :         return 0;
     282             : }
     283             : 
     284             : STATIC int
     285    85709318 : xfs_bmbt_get_minrecs(
     286             :         struct xfs_btree_cur    *cur,
     287             :         int                     level)
     288             : {
     289    85709318 :         if (level == cur->bc_nlevels - 1) {
     290     1524593 :                 struct xfs_ifork        *ifp = xfs_btree_ifork_ptr(cur);
     291             : 
     292     1524593 :                 return xfs_bmbt_maxrecs(cur->bc_mp,
     293     3049186 :                                         ifp->if_broot_bytes, level == 0) / 2;
     294             :         }
     295             : 
     296    84184725 :         return cur->bc_mp->m_bmap_dmnr[level != 0];
     297             : }
     298             : 
     299             : int
     300   875425574 : xfs_bmbt_get_maxrecs(
     301             :         struct xfs_btree_cur    *cur,
     302             :         int                     level)
     303             : {
     304   875425574 :         if (level == cur->bc_nlevels - 1) {
     305   161547654 :                 struct xfs_ifork        *ifp = xfs_btree_ifork_ptr(cur);
     306             : 
     307   161547732 :                 return xfs_bmbt_maxrecs(cur->bc_mp,
     308   161547732 :                                         ifp->if_broot_bytes, level == 0);
     309             :         }
     310             : 
     311   713877920 :         return cur->bc_mp->m_bmap_dmxr[level != 0];
     312             : 
     313             : }
     314             : 
     315             : /*
     316             :  * Get the maximum records we could store in the on-disk format.
     317             :  *
     318             :  * For non-root nodes this is equivalent to xfs_bmbt_get_maxrecs, but
     319             :  * for the root node this checks the available space in the dinode fork
     320             :  * so that we can resize the in-memory buffer to match it.  After a
     321             :  * resize to the maximum size this function returns the same value
     322             :  * as xfs_bmbt_get_maxrecs for the root node, too.
     323             :  */
     324             : STATIC int
     325     1698049 : xfs_bmbt_get_dmaxrecs(
     326             :         struct xfs_btree_cur    *cur,
     327             :         int                     level)
     328             : {
     329     1698049 :         if (level != cur->bc_nlevels - 1)
     330       10330 :                 return cur->bc_mp->m_bmap_dmxr[level != 0];
     331     1687719 :         return xfs_bmdr_maxrecs(cur->bc_ino.forksize, level == 0);
     332             : }
     333             : 
     334             : STATIC void
     335  1262709003 : xfs_bmbt_init_key_from_rec(
     336             :         union xfs_btree_key             *key,
     337             :         const union xfs_btree_rec       *rec)
     338             : {
     339  1262709003 :         key->bmbt.br_startoff =
     340  1262709003 :                 cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt));
     341  1262709003 : }
     342             : 
     343             : STATIC void
     344       37458 : xfs_bmbt_init_high_key_from_rec(
     345             :         union xfs_btree_key             *key,
     346             :         const union xfs_btree_rec       *rec)
     347             : {
     348       37458 :         key->bmbt.br_startoff = cpu_to_be64(
     349             :                         xfs_bmbt_disk_get_startoff(&rec->bmbt) +
     350             :                         xfs_bmbt_disk_get_blockcount(&rec->bmbt) - 1);
     351       37458 : }
     352             : 
     353             : STATIC void
     354    65473705 : xfs_bmbt_init_rec_from_cur(
     355             :         struct xfs_btree_cur    *cur,
     356             :         union xfs_btree_rec     *rec)
     357             : {
     358    65473705 :         xfs_bmbt_disk_set_all(&rec->bmbt, &cur->bc_rec.b);
     359    65473732 : }
     360             : 
     361             : STATIC void
     362   139707948 : xfs_bmbt_init_ptr_from_cur(
     363             :         struct xfs_btree_cur    *cur,
     364             :         union xfs_btree_ptr     *ptr)
     365             : {
     366   139707948 :         ptr->l = 0;
     367   139707948 : }
     368             : 
     369             : STATIC int64_t
     370  1767930940 : xfs_bmbt_key_diff(
     371             :         struct xfs_btree_cur            *cur,
     372             :         const union xfs_btree_key       *key)
     373             : {
     374  1767930940 :         return (int64_t)be64_to_cpu(key->bmbt.br_startoff) -
     375  1767930940 :                                       cur->bc_rec.b.br_startoff;
     376             : }
     377             : 
     378             : STATIC int64_t
     379   171651551 : xfs_bmbt_diff_two_keys(
     380             :         struct xfs_btree_cur            *cur,
     381             :         const union xfs_btree_key       *k1,
     382             :         const union xfs_btree_key       *k2,
     383             :         const union xfs_btree_key       *mask)
     384             : {
     385   171651551 :         uint64_t                        a = be64_to_cpu(k1->bmbt.br_startoff);
     386   171651551 :         uint64_t                        b = be64_to_cpu(k2->bmbt.br_startoff);
     387             : 
     388   171651551 :         ASSERT(!mask || mask->bmbt.br_startoff);
     389             : 
     390             :         /*
     391             :          * Note: This routine previously casted a and b to int64 and subtracted
     392             :          * them to generate a result.  This lead to problems if b was the
     393             :          * "maximum" key value (all ones) being signed incorrectly, hence this
     394             :          * somewhat less efficient version.
     395             :          */
     396   171651551 :         if (a > b)
     397             :                 return 1;
     398     7073151 :         if (b > a)
     399      724716 :                 return -1;
     400             :         return 0;
     401             : }
     402             : 
     403             : static xfs_failaddr_t
     404    14823299 : xfs_bmbt_verify(
     405             :         struct xfs_buf          *bp)
     406             : {
     407    14823299 :         struct xfs_mount        *mp = bp->b_mount;
     408    14823299 :         struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
     409    14823299 :         xfs_failaddr_t          fa;
     410    14823299 :         unsigned int            level;
     411             : 
     412    14823299 :         if (!xfs_verify_magic(bp, block->bb_magic))
     413           0 :                 return __this_address;
     414             : 
     415    14823307 :         if (xfs_has_crc(mp)) {
     416             :                 /*
     417             :                  * XXX: need a better way of verifying the owner here. Right now
     418             :                  * just make sure there has been one set.
     419             :                  */
     420    14823306 :                 fa = xfs_btree_lblock_v5hdr_verify(bp, XFS_RMAP_OWN_UNKNOWN);
     421    14823306 :                 if (fa)
     422             :                         return fa;
     423             :         }
     424             : 
     425             :         /*
     426             :          * numrecs and level verification.
     427             :          *
     428             :          * We don't know what fork we belong to, so just verify that the level
     429             :          * is less than the maximum of the two. Later checks will be more
     430             :          * precise.
     431             :          */
     432    14823308 :         level = be16_to_cpu(block->bb_level);
     433    14823308 :         if (level > max(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1]))
     434           0 :                 return __this_address;
     435             : 
     436    14823310 :         return xfs_btree_lblock_verify(bp, mp->m_bmap_dmxr[level != 0]);
     437             : }
     438             : 
     439             : static void
     440     6631688 : xfs_bmbt_read_verify(
     441             :         struct xfs_buf  *bp)
     442             : {
     443     6631688 :         xfs_failaddr_t  fa;
     444             : 
     445     6631688 :         if (!xfs_btree_lblock_verify_crc(bp))
     446           4 :                 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
     447             :         else {
     448     6631684 :                 fa = xfs_bmbt_verify(bp);
     449     6631684 :                 if (fa)
     450           0 :                         xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     451             :         }
     452             : 
     453     6631688 :         if (bp->b_error)
     454           4 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     455     6631688 : }
     456             : 
     457             : static void
     458     5033163 : xfs_bmbt_write_verify(
     459             :         struct xfs_buf  *bp)
     460             : {
     461     5033163 :         xfs_failaddr_t  fa;
     462             : 
     463     5033163 :         fa = xfs_bmbt_verify(bp);
     464     5033163 :         if (fa) {
     465           0 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     466           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     467           0 :                 return;
     468             :         }
     469     5033163 :         xfs_btree_lblock_calc_crc(bp);
     470             : }
     471             : 
     472             : const struct xfs_buf_ops xfs_bmbt_buf_ops = {
     473             :         .name = "xfs_bmbt",
     474             :         .magic = { cpu_to_be32(XFS_BMAP_MAGIC),
     475             :                    cpu_to_be32(XFS_BMAP_CRC_MAGIC) },
     476             :         .verify_read = xfs_bmbt_read_verify,
     477             :         .verify_write = xfs_bmbt_write_verify,
     478             :         .verify_struct = xfs_bmbt_verify,
     479             : };
     480             : 
     481             : 
     482             : STATIC int
     483      625246 : xfs_bmbt_keys_inorder(
     484             :         struct xfs_btree_cur            *cur,
     485             :         const union xfs_btree_key       *k1,
     486             :         const union xfs_btree_key       *k2)
     487             : {
     488      625246 :         return be64_to_cpu(k1->bmbt.br_startoff) <
     489      625246 :                 be64_to_cpu(k2->bmbt.br_startoff);
     490             : }
     491             : 
     492             : STATIC int
     493   218842869 : xfs_bmbt_recs_inorder(
     494             :         struct xfs_btree_cur            *cur,
     495             :         const union xfs_btree_rec       *r1,
     496             :         const union xfs_btree_rec       *r2)
     497             : {
     498   218842869 :         return xfs_bmbt_disk_get_startoff(&r1->bmbt) +
     499   218842869 :                 xfs_bmbt_disk_get_blockcount(&r1->bmbt) <=
     500   218842869 :                 xfs_bmbt_disk_get_startoff(&r2->bmbt);
     501             : }
     502             : 
     503             : STATIC enum xbtree_key_contig
     504           0 : xfs_bmbt_keys_contiguous(
     505             :         struct xfs_btree_cur            *cur,
     506             :         const union xfs_btree_key       *key1,
     507             :         const union xfs_btree_key       *key2,
     508             :         const union xfs_btree_key       *mask)
     509             : {
     510           0 :         ASSERT(!mask || mask->bmbt.br_startoff);
     511             : 
     512           0 :         return xbtree_key_contig(be64_to_cpu(key1->bmbt.br_startoff),
     513           0 :                                  be64_to_cpu(key2->bmbt.br_startoff));
     514             : }
     515             : 
     516             : const struct xfs_btree_ops xfs_bmbt_ops = {
     517             :         .rec_len                = sizeof(xfs_bmbt_rec_t),
     518             :         .key_len                = sizeof(xfs_bmbt_key_t),
     519             :         .lru_refs               = XFS_BMAP_BTREE_REF,
     520             :         .geom_flags             = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE,
     521             : 
     522             :         .dup_cursor             = xfs_bmbt_dup_cursor,
     523             :         .update_cursor          = xfs_bmbt_update_cursor,
     524             :         .alloc_block            = xfs_bmbt_alloc_block,
     525             :         .free_block             = xfs_bmbt_free_block,
     526             :         .get_maxrecs            = xfs_bmbt_get_maxrecs,
     527             :         .get_minrecs            = xfs_bmbt_get_minrecs,
     528             :         .get_dmaxrecs           = xfs_bmbt_get_dmaxrecs,
     529             :         .init_key_from_rec      = xfs_bmbt_init_key_from_rec,
     530             :         .init_high_key_from_rec = xfs_bmbt_init_high_key_from_rec,
     531             :         .init_rec_from_cur      = xfs_bmbt_init_rec_from_cur,
     532             :         .init_ptr_from_cur      = xfs_bmbt_init_ptr_from_cur,
     533             :         .key_diff               = xfs_bmbt_key_diff,
     534             :         .diff_two_keys          = xfs_bmbt_diff_two_keys,
     535             :         .buf_ops                = &xfs_bmbt_buf_ops,
     536             :         .keys_inorder           = xfs_bmbt_keys_inorder,
     537             :         .recs_inorder           = xfs_bmbt_recs_inorder,
     538             :         .keys_contiguous        = xfs_bmbt_keys_contiguous,
     539             : };
     540             : 
     541             : /*
     542             :  * Allocate a new bmap btree cursor.
     543             :  */
     544             : static struct xfs_btree_cur *                   /* new bmap btree cursor */
     545   163848785 : xfs_bmbt_init_common(
     546             :         struct xfs_mount        *mp,            /* file system mount point */
     547             :         struct xfs_trans        *tp,            /* transaction pointer */
     548             :         struct xfs_inode        *ip,            /* inode owning the btree */
     549             :         int                     whichfork)
     550             : {
     551   163848785 :         struct xfs_btree_cur    *cur;
     552             : 
     553   163848785 :         ASSERT(whichfork != XFS_COW_FORK);
     554             : 
     555   163848785 :         cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_BMAP, &xfs_bmbt_ops,
     556   163848785 :                         mp->m_bm_maxlevels[whichfork], xfs_bmbt_cur_cache);
     557   163849016 :         cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_bmbt_2);
     558             : 
     559   163849016 :         cur->bc_ino.ip = ip;
     560   163849016 :         cur->bc_ino.allocated = 0;
     561   163849016 :         cur->bc_ino.flags = 0;
     562             : 
     563   163849016 :         return cur;
     564             : }
     565             : 
     566             : /*
     567             :  * Allocate a new bmap btree cursor.
     568             :  */
     569             : struct xfs_btree_cur *                          /* new bmap btree cursor */
     570   163787985 : xfs_bmbt_init_cursor(
     571             :         struct xfs_mount        *mp,            /* file system mount point */
     572             :         struct xfs_trans        *tp,            /* transaction pointer */
     573             :         struct xfs_inode        *ip,            /* inode owning the btree */
     574             :         int                     whichfork)      /* data or attr fork */
     575             : {
     576   163787985 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     577   163788379 :         struct xfs_btree_cur    *cur;
     578             : 
     579   163788379 :         cur = xfs_bmbt_init_common(mp, tp, ip, whichfork);
     580             : 
     581   163787277 :         cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
     582   163787277 :         cur->bc_ino.forksize = xfs_inode_fork_size(ip, whichfork);
     583   163787277 :         cur->bc_ino.whichfork = whichfork;
     584             : 
     585   163787277 :         return cur;
     586             : }
     587             : 
     588             : /* Calculate number of records in a block mapping btree block. */
     589             : static inline unsigned int
     590             : xfs_bmbt_block_maxrecs(
     591             :         unsigned int            blocklen,
     592             :         bool                    leaf)
     593             : {
     594   447626626 :         if (leaf)
     595       24125 :                 return blocklen / sizeof(xfs_bmbt_rec_t);
     596   435438745 :         return blocklen / (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t));
     597             : }
     598             : 
     599             : /*
     600             :  * Allocate a new bmap btree cursor for reloading an inode block mapping data
     601             :  * structure.  Note that callers can use the staged cursor to reload extents
     602             :  * format inode forks if they rebuild the iext tree and commit the staged
     603             :  * cursor immediately.
     604             :  */
     605             : struct xfs_btree_cur *
     606       60814 : xfs_bmbt_stage_cursor(
     607             :         struct xfs_mount        *mp,
     608             :         struct xfs_inode        *ip,
     609             :         struct xbtree_ifakeroot *ifake)
     610             : {
     611       60814 :         struct xfs_btree_cur    *cur;
     612       60814 :         struct xfs_btree_ops    *ops;
     613             : 
     614       60814 :         cur = xfs_bmbt_init_common(mp, NULL, ip, ifake->if_whichfork);
     615       60814 :         cur->bc_nlevels = ifake->if_levels;
     616       60814 :         cur->bc_ino.forksize = ifake->if_fork_size;
     617             :         /* Don't let anyone think we're attached to the real fork yet. */
     618       60814 :         cur->bc_ino.whichfork = -1;
     619       60814 :         xfs_btree_stage_ifakeroot(cur, ifake, &ops);
     620       60814 :         ops->update_cursor = NULL;
     621       60814 :         return cur;
     622             : }
     623             : 
     624             : /*
     625             :  * Swap in the new inode fork root.  Once we pass this point the newly rebuilt
     626             :  * mappings are in place and we have to kill off any old btree blocks.
     627             :  */
     628             : void
     629       60814 : xfs_bmbt_commit_staged_btree(
     630             :         struct xfs_btree_cur    *cur,
     631             :         struct xfs_trans        *tp,
     632             :         int                     whichfork)
     633             : {
     634       60814 :         struct xbtree_ifakeroot *ifake = cur->bc_ino.ifake;
     635       60814 :         struct xfs_ifork        *ifp;
     636       60814 :         static const short      brootflag[2] =
     637             :                 { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
     638       60814 :         static const short      extflag[2] =
     639             :                 { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
     640       60814 :         int                     flags = XFS_ILOG_CORE;
     641             : 
     642       60814 :         ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
     643       60814 :         ASSERT(whichfork != XFS_COW_FORK);
     644             : 
     645             :         /*
     646             :          * Free any resources hanging off the real fork, then shallow-copy the
     647             :          * staging fork's contents into the real fork to transfer everything
     648             :          * we just built.
     649             :          */
     650       60814 :         ifp = xfs_ifork_ptr(cur->bc_ino.ip, whichfork);
     651       60814 :         xfs_idestroy_fork(ifp);
     652      121628 :         memcpy(ifp, ifake->if_fork, sizeof(struct xfs_ifork));
     653             : 
     654       60814 :         switch (ifp->if_format) {
     655       55651 :         case XFS_DINODE_FMT_EXTENTS:
     656       55651 :                 flags |= extflag[whichfork];
     657       55651 :                 break;
     658        5163 :         case XFS_DINODE_FMT_BTREE:
     659        5163 :                 flags |= brootflag[whichfork];
     660        5163 :                 break;
     661           0 :         default:
     662           0 :                 ASSERT(0);
     663           0 :                 break;
     664             :         }
     665       60814 :         xfs_trans_log_inode(tp, cur->bc_ino.ip, flags);
     666       60814 :         xfs_btree_commit_ifakeroot(cur, tp, whichfork, &xfs_bmbt_ops);
     667       60814 : }
     668             : 
     669             : /*
     670             :  * Calculate number of records in a bmap btree block.
     671             :  */
     672             : int
     673   272390545 : xfs_bmbt_maxrecs(
     674             :         struct xfs_mount        *mp,
     675             :         int                     blocklen,
     676             :         int                     leaf)
     677             : {
     678   435462870 :         blocklen -= XFS_BMBT_BLOCK_LEN(mp);
     679   610698951 :         return xfs_bmbt_block_maxrecs(blocklen, leaf);
     680             : }
     681             : 
     682             : /*
     683             :  * Calculate the maximum possible height of the btree that the on-disk format
     684             :  * supports. This is used for sizing structures large enough to support every
     685             :  * possible configuration of a filesystem that might get mounted.
     686             :  */
     687             : unsigned int
     688       48250 : xfs_bmbt_maxlevels_ondisk(void)
     689             : {
     690       48250 :         unsigned int            minrecs[2];
     691       48250 :         unsigned int            blocklen;
     692             : 
     693       48250 :         blocklen = min(XFS_MIN_BLOCKSIZE - XFS_BTREE_SBLOCK_LEN,
     694             :                        XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN);
     695             : 
     696       48250 :         minrecs[0] = xfs_bmbt_block_maxrecs(blocklen, true) / 2;
     697       48250 :         minrecs[1] = xfs_bmbt_block_maxrecs(blocklen, false) / 2;
     698             : 
     699             :         /* One extra level for the inode root. */
     700       48250 :         return xfs_btree_compute_maxlevels(minrecs,
     701       48250 :                         XFS_MAX_EXTCNT_DATA_FORK_LARGE) + 1;
     702             : }
     703             : 
     704             : /*
     705             :  * Calculate number of records in a bmap btree inode root.
     706             :  */
     707             : int
     708       48238 : xfs_bmdr_maxrecs(
     709             :         int                     blocklen,
     710             :         int                     leaf)
     711             : {
     712    13899713 :         blocklen -= sizeof(xfs_bmdr_block_t);
     713             : 
     714     1735957 :         if (leaf)
     715       10326 :                 return blocklen / sizeof(xfs_bmdr_rec_t);
     716    13889387 :         return blocklen / (sizeof(xfs_bmdr_key_t) + sizeof(xfs_bmdr_ptr_t));
     717             : }
     718             : 
     719             : /*
     720             :  * Change the owner of a btree format fork fo the inode passed in. Change it to
     721             :  * the owner of that is passed in so that we can change owners before or after
     722             :  * we switch forks between inodes. The operation that the caller is doing will
     723             :  * determine whether is needs to change owner before or after the switch.
     724             :  *
     725             :  * For demand paged transactional modification, the fork switch should be done
     726             :  * after reading in all the blocks, modifying them and pinning them in the
     727             :  * transaction. For modification when the buffers are already pinned in memory,
     728             :  * the fork switch can be done before changing the owner as we won't need to
     729             :  * validate the owner until the btree buffers are unpinned and writes can occur
     730             :  * again.
     731             :  *
     732             :  * For recovery based ownership change, there is no transactional context and
     733             :  * so a buffer list must be supplied so that we can record the buffers that we
     734             :  * modified for the caller to issue IO on.
     735             :  */
     736             : int
     737           0 : xfs_bmbt_change_owner(
     738             :         struct xfs_trans        *tp,
     739             :         struct xfs_inode        *ip,
     740             :         int                     whichfork,
     741             :         xfs_ino_t               new_owner,
     742             :         struct list_head        *buffer_list)
     743             : {
     744           0 :         struct xfs_btree_cur    *cur;
     745           0 :         int                     error;
     746             : 
     747           0 :         ASSERT(tp || buffer_list);
     748           0 :         ASSERT(!(tp && buffer_list));
     749           0 :         ASSERT(xfs_ifork_ptr(ip, whichfork)->if_format == XFS_DINODE_FMT_BTREE);
     750             : 
     751           0 :         cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
     752           0 :         cur->bc_ino.flags |= XFS_BTCUR_BMBT_INVALID_OWNER;
     753             : 
     754           0 :         error = xfs_btree_change_owner(cur, new_owner, buffer_list);
     755           0 :         xfs_btree_del_cursor(cur, error);
     756           0 :         return error;
     757             : }
     758             : 
     759             : /* Calculate the bmap btree size for some records. */
     760             : unsigned long long
     761      997867 : xfs_bmbt_calc_size(
     762             :         struct xfs_mount        *mp,
     763             :         unsigned long long      len)
     764             : {
     765      997867 :         return xfs_btree_calc_size(mp->m_bmap_dmnr, len);
     766             : }
     767             : 
     768             : int __init
     769          12 : xfs_bmbt_init_cur_cache(void)
     770             : {
     771          12 :         xfs_bmbt_cur_cache = kmem_cache_create("xfs_bmbt_cur",
     772          12 :                         xfs_btree_cur_sizeof(xfs_bmbt_maxlevels_ondisk()),
     773             :                         0, 0, NULL);
     774             : 
     775          12 :         if (!xfs_bmbt_cur_cache)
     776           0 :                 return -ENOMEM;
     777             :         return 0;
     778             : }
     779             : 
     780             : void
     781          12 : xfs_bmbt_destroy_cur_cache(void)
     782             : {
     783          12 :         kmem_cache_destroy(xfs_bmbt_cur_cache);
     784          12 :         xfs_bmbt_cur_cache = NULL;
     785          12 : }

Generated by: LCOV version 1.14