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-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 283 304 93.1 %
Date: 2023-07-31 20:08:12 Functions: 35 36 97.2 %

          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    14100517 : 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    14100517 :         struct xfs_mount        *mp = ip->i_mount;
      41    14100517 :         int                     dmxr;
      42    14100517 :         xfs_bmbt_key_t          *fkp;
      43    14100517 :         __be64                  *fpp;
      44    14100517 :         xfs_bmbt_key_t          *tkp;
      45    14100517 :         __be64                  *tpp;
      46             : 
      47    14100517 :         xfs_btree_init_block(mp, rblock, &xfs_bmbt_ops, 0, 0, ip->i_ino);
      48    14100505 :         rblock->bb_level = dblock->bb_level;
      49    14100505 :         ASSERT(be16_to_cpu(rblock->bb_level) > 0);
      50    14100505 :         rblock->bb_numrecs = dblock->bb_numrecs;
      51    14100505 :         dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
      52    14100505 :         fkp = XFS_BMDR_KEY_ADDR(dblock, 1);
      53    28201010 :         tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
      54    14100505 :         fpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr);
      55    14100505 :         tpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen);
      56    14100505 :         dmxr = be16_to_cpu(dblock->bb_numrecs);
      57    14100505 :         memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
      58    28201010 :         memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
      59    14100505 : }
      60             : 
      61             : void
      62  1775382157 : xfs_bmbt_disk_get_all(
      63             :         const struct xfs_bmbt_rec *rec,
      64             :         struct xfs_bmbt_irec    *irec)
      65             : {
      66  1775382157 :         uint64_t                l0 = get_unaligned_be64(&rec->l0);
      67             :         uint64_t                l1 = get_unaligned_be64(&rec->l1);
      68             : 
      69  1775382157 :         irec->br_startoff = (l0 & xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
      70  1775382157 :         irec->br_startblock = ((l0 & xfs_mask64lo(9)) << 43) | (l1 >> 21);
      71  1775382157 :         irec->br_blockcount = l1 & xfs_mask64lo(21);
      72  1775382157 :         if (l0 >> (64 - BMBT_EXNTFLAG_BITLEN))
      73   133745057 :                 irec->br_state = XFS_EXT_UNWRITTEN;
      74             :         else
      75  1641637100 :                 irec->br_state = XFS_EXT_NORM;
      76  1775382157 : }
      77             : 
      78             : /*
      79             :  * Extract the blockcount field from an on disk bmap extent record.
      80             :  */
      81             : xfs_filblks_t
      82 >11647*10^7 : xfs_bmbt_disk_get_blockcount(
      83             :         const struct xfs_bmbt_rec       *r)
      84             : {
      85 >11690*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 >23326*10^7 : xfs_bmbt_disk_get_startoff(
      93             :         const struct xfs_bmbt_rec       *r)
      94             : {
      95 >23658*10^7 :         return ((xfs_fileoff_t)be64_to_cpu(r->l0) &
      96 >23658*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  2681922893 : xfs_bmbt_disk_set_all(
     104             :         struct xfs_bmbt_rec     *r,
     105             :         struct xfs_bmbt_irec    *s)
     106             : {
     107  2681922893 :         int                     extent_flag = (s->br_state != XFS_EXT_NORM);
     108             : 
     109  2681922893 :         ASSERT(s->br_state == XFS_EXT_NORM || s->br_state == XFS_EXT_UNWRITTEN);
     110  2681922893 :         ASSERT(!(s->br_startoff & xfs_mask64hi(64-BMBT_STARTOFF_BITLEN)));
     111  2681922893 :         ASSERT(!(s->br_blockcount & xfs_mask64hi(64-BMBT_BLOCKCOUNT_BITLEN)));
     112  2681922893 :         ASSERT(!(s->br_startblock & xfs_mask64hi(64-BMBT_STARTBLOCK_BITLEN)));
     113             : 
     114  2681922893 :         put_unaligned_be64(
     115  2681922893 :                 ((xfs_bmbt_rec_base_t)extent_flag << 63) |
     116  2681922893 :                  ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
     117  2681922893 :                  ((xfs_bmbt_rec_base_t)s->br_startblock >> 43), &r->l0);
     118  2681922893 :         put_unaligned_be64(
     119  2681922893 :                 ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
     120  2681922893 :                  ((xfs_bmbt_rec_base_t)s->br_blockcount &
     121             :                   (xfs_bmbt_rec_base_t)xfs_mask64lo(21)), &r->l1);
     122  2681922893 : }
     123             : 
     124             : /*
     125             :  * Convert in-memory form of btree root to on-disk form.
     126             :  */
     127             : void
     128     2320692 : 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     2320692 :         int                     dmxr;
     136     2320692 :         xfs_bmbt_key_t          *fkp;
     137     2320692 :         __be64                  *fpp;
     138     2320692 :         xfs_bmbt_key_t          *tkp;
     139     2320692 :         __be64                  *tpp;
     140             : 
     141     2320692 :         if (xfs_has_crc(mp)) {
     142     2320692 :                 ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC));
     143     2320692 :                 ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid,
     144             :                        &mp->m_sb.sb_meta_uuid));
     145     2320692 :                 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     2320692 :         ASSERT(rblock->bb_u.l.bb_leftsib == cpu_to_be64(NULLFSBLOCK));
     150     2320692 :         ASSERT(rblock->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK));
     151     2320692 :         ASSERT(rblock->bb_level != 0);
     152     2320692 :         dblock->bb_level = rblock->bb_level;
     153     2320692 :         dblock->bb_numrecs = rblock->bb_numrecs;
     154     2320692 :         dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
     155     4641384 :         fkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
     156     2320692 :         tkp = XFS_BMDR_KEY_ADDR(dblock, 1);
     157     2320692 :         fpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen);
     158     2320692 :         tpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr);
     159     2320692 :         dmxr = be16_to_cpu(dblock->bb_numrecs);
     160     2320692 :         memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
     161     4641384 :         memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
     162     2320692 : }
     163             : 
     164             : STATIC struct xfs_btree_cur *
     165    55259352 : xfs_bmbt_dup_cursor(
     166             :         struct xfs_btree_cur    *cur)
     167             : {
     168    55259352 :         struct xfs_btree_cur    *new;
     169             : 
     170    55259352 :         new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp,
     171    55259352 :                         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    55260000 :         new->bc_ino.flags = cur->bc_ino.flags;
     178             : 
     179    55260000 :         return new;
     180             : }
     181             : 
     182             : STATIC void
     183      481093 : xfs_bmbt_update_cursor(
     184             :         struct xfs_btree_cur    *src,
     185             :         struct xfs_btree_cur    *dst)
     186             : {
     187      481093 :         ASSERT((dst->bc_tp->t_highest_agno != NULLAGNUMBER) ||
     188             :                (dst->bc_ino.ip->i_diflags & XFS_DIFLAG_REALTIME));
     189             : 
     190      481093 :         dst->bc_ino.allocated += src->bc_ino.allocated;
     191      481093 :         dst->bc_tp->t_highest_agno = src->bc_tp->t_highest_agno;
     192             : 
     193      481093 :         src->bc_ino.allocated = 0;
     194      481093 : }
     195             : 
     196             : STATIC int
     197      483974 : 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      483974 :         struct xfs_alloc_arg    args;
     204      483974 :         int                     error;
     205             : 
     206      483974 :         memset(&args, 0, sizeof(args));
     207      483974 :         args.tp = cur->bc_tp;
     208      483974 :         args.mp = cur->bc_mp;
     209      483974 :         xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_ino.ip->i_ino,
     210      483974 :                         cur->bc_ino.whichfork);
     211      483974 :         args.minlen = args.maxlen = args.prod = 1;
     212      483974 :         args.wasdel = cur->bc_ino.flags & XFS_BTCUR_BMBT_WASDEL;
     213      483974 :         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      483974 :         if (cur->bc_tp->t_highest_agno == NULLAGNUMBER)
     223      445407 :                 args.minleft = xfs_bmapi_minleft(cur->bc_tp, cur->bc_ino.ip,
     224             :                                         cur->bc_ino.whichfork);
     225             : 
     226      483976 :         error = xfs_alloc_vextent_start_ag(&args, be64_to_cpu(start->l));
     227      483975 :         if (error)
     228             :                 return error;
     229             : 
     230      483972 :         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      483972 :         if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
     243           0 :                 *stat = 0;
     244           0 :                 return 0;
     245             :         }
     246             : 
     247      483972 :         ASSERT(args.len == 1);
     248      483972 :         cur->bc_ino.allocated++;
     249      483972 :         cur->bc_ino.ip->i_nblocks++;
     250      483972 :         xfs_trans_log_inode(args.tp, cur->bc_ino.ip, XFS_ILOG_CORE);
     251      483972 :         xfs_trans_mod_dquot_byino(args.tp, cur->bc_ino.ip,
     252             :                         XFS_TRANS_DQ_BCOUNT, 1L);
     253             : 
     254      483972 :         new->l = cpu_to_be64(args.fsbno);
     255             : 
     256      483972 :         *stat = 1;
     257      483972 :         return 0;
     258             : }
     259             : 
     260             : STATIC int
     261      188676 : xfs_bmbt_free_block(
     262             :         struct xfs_btree_cur    *cur,
     263             :         struct xfs_buf          *bp)
     264             : {
     265      188676 :         struct xfs_mount        *mp = cur->bc_mp;
     266      188676 :         struct xfs_inode        *ip = cur->bc_ino.ip;
     267      188676 :         struct xfs_trans        *tp = cur->bc_tp;
     268      188676 :         xfs_fsblock_t           fsbno = XFS_DADDR_TO_FSB(mp, xfs_buf_daddr(bp));
     269      188676 :         struct xfs_owner_info   oinfo;
     270      188676 :         int                     error;
     271             : 
     272      188676 :         xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_ino.whichfork);
     273      188676 :         error = xfs_free_extent_later(cur->bc_tp, fsbno, 1, &oinfo,
     274             :                         XFS_AG_RESV_NONE);
     275      188676 :         if (error)
     276             :                 return error;
     277             : 
     278      188676 :         ip->i_nblocks--;
     279      188676 :         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
     280      188676 :         xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
     281      188676 :         return 0;
     282             : }
     283             : 
     284             : STATIC int
     285   121464498 : xfs_bmbt_get_minrecs(
     286             :         struct xfs_btree_cur    *cur,
     287             :         int                     level)
     288             : {
     289   121464498 :         if (level == cur->bc_nlevels - 1) {
     290     2331362 :                 struct xfs_ifork        *ifp = xfs_btree_ifork_ptr(cur);
     291             : 
     292     2331098 :                 return xfs_bmbt_maxrecs(cur->bc_mp,
     293     4662196 :                                         ifp->if_broot_bytes, level == 0) / 2;
     294             :         }
     295             : 
     296   119133136 :         return cur->bc_mp->m_bmap_dmnr[level != 0];
     297             : }
     298             : 
     299             : int
     300  1926761137 : xfs_bmbt_get_maxrecs(
     301             :         struct xfs_btree_cur    *cur,
     302             :         int                     level)
     303             : {
     304  1926761137 :         if (level == cur->bc_nlevels - 1) {
     305   402437072 :                 struct xfs_ifork        *ifp = xfs_btree_ifork_ptr(cur);
     306             : 
     307   402431702 :                 return xfs_bmbt_maxrecs(cur->bc_mp,
     308   402431702 :                                         ifp->if_broot_bytes, level == 0);
     309             :         }
     310             : 
     311  1524324065 :         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     2661452 : xfs_bmbt_get_dmaxrecs(
     326             :         struct xfs_btree_cur    *cur,
     327             :         int                     level)
     328             : {
     329     2661452 :         if (level != cur->bc_nlevels - 1)
     330       47696 :                 return cur->bc_mp->m_bmap_dmxr[level != 0];
     331     2613756 :         return xfs_bmdr_maxrecs(cur->bc_ino.forksize, level == 0);
     332             : }
     333             : 
     334             : STATIC void
     335  2889758210 : xfs_bmbt_init_key_from_rec(
     336             :         union xfs_btree_key             *key,
     337             :         const union xfs_btree_rec       *rec)
     338             : {
     339  2889758210 :         key->bmbt.br_startoff =
     340  2889758210 :                 cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt));
     341  2889758210 : }
     342             : 
     343             : STATIC void
     344           8 : xfs_bmbt_init_high_key_from_rec(
     345             :         union xfs_btree_key             *key,
     346             :         const union xfs_btree_rec       *rec)
     347             : {
     348           8 :         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           8 : }
     352             : 
     353             : STATIC void
     354   157898970 : xfs_bmbt_init_rec_from_cur(
     355             :         struct xfs_btree_cur    *cur,
     356             :         union xfs_btree_rec     *rec)
     357             : {
     358   157898970 :         xfs_bmbt_disk_set_all(&rec->bmbt, &cur->bc_rec.b);
     359   157899427 : }
     360             : 
     361             : STATIC void
     362   371551388 : xfs_bmbt_init_ptr_from_cur(
     363             :         struct xfs_btree_cur    *cur,
     364             :         union xfs_btree_ptr     *ptr)
     365             : {
     366   371551388 :         ptr->l = 0;
     367   371551388 : }
     368             : 
     369             : STATIC int64_t
     370  4543735708 : xfs_bmbt_key_diff(
     371             :         struct xfs_btree_cur            *cur,
     372             :         const union xfs_btree_key       *key)
     373             : {
     374  4543735708 :         return (int64_t)be64_to_cpu(key->bmbt.br_startoff) -
     375  4543735708 :                                       cur->bc_rec.b.br_startoff;
     376             : }
     377             : 
     378             : STATIC int64_t
     379   259746238 : 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   259746238 :         uint64_t                        a = be64_to_cpu(k1->bmbt.br_startoff);
     386   259746238 :         uint64_t                        b = be64_to_cpu(k2->bmbt.br_startoff);
     387             : 
     388   259746238 :         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   259746238 :         if (a > b)
     397             :                 return 1;
     398     9665600 :         if (b > a)
     399         128 :                 return -1;
     400             :         return 0;
     401             : }
     402             : 
     403             : static xfs_failaddr_t
     404    19492573 : xfs_bmbt_verify(
     405             :         struct xfs_buf          *bp)
     406             : {
     407    19492573 :         struct xfs_mount        *mp = bp->b_mount;
     408    19492573 :         struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
     409    19492573 :         xfs_failaddr_t          fa;
     410    19492573 :         unsigned int            level;
     411             : 
     412    19492573 :         if (!xfs_verify_magic(bp, block->bb_magic))
     413           0 :                 return __this_address;
     414             : 
     415    19492143 :         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    19492264 :                 fa = xfs_btree_lblock_v5hdr_verify(bp, XFS_RMAP_OWN_UNKNOWN);
     421    19492566 :                 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    19492479 :         level = be16_to_cpu(block->bb_level);
     433    19492479 :         if (level > max(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1]))
     434           0 :                 return __this_address;
     435             : 
     436    19492479 :         return xfs_btree_lblock_verify(bp, mp->m_bmap_dmxr[level != 0]);
     437             : }
     438             : 
     439             : static void
     440     5467933 : xfs_bmbt_read_verify(
     441             :         struct xfs_buf  *bp)
     442             : {
     443     5467933 :         xfs_failaddr_t  fa;
     444             : 
     445     5467933 :         if (!xfs_btree_lblock_verify_crc(bp))
     446          20 :                 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
     447             :         else {
     448     5467913 :                 fa = xfs_bmbt_verify(bp);
     449     5467913 :                 if (fa)
     450           0 :                         xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     451             :         }
     452             : 
     453     5467933 :         if (bp->b_error)
     454          20 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     455     5467933 : }
     456             : 
     457             : static void
     458     9286042 : xfs_bmbt_write_verify(
     459             :         struct xfs_buf  *bp)
     460             : {
     461     9286042 :         xfs_failaddr_t  fa;
     462             : 
     463     9286042 :         fa = xfs_bmbt_verify(bp);
     464     9286042 :         if (fa) {
     465           0 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     466           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     467           0 :                 return;
     468             :         }
     469     9286042 :         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     1091330 : 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     1091330 :         return be64_to_cpu(k1->bmbt.br_startoff) <
     489     1091330 :                 be64_to_cpu(k2->bmbt.br_startoff);
     490             : }
     491             : 
     492             : STATIC int
     493   429091080 : 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   429091080 :         return xfs_bmbt_disk_get_startoff(&r1->bmbt) +
     499   429091080 :                 xfs_bmbt_disk_get_blockcount(&r1->bmbt) <=
     500             :                 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   401211007 : 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   401211007 :         struct xfs_btree_cur    *cur;
     552             : 
     553   401211007 :         ASSERT(whichfork != XFS_COW_FORK);
     554             : 
     555   802423724 :         cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_BMAP, &xfs_bmbt_ops,
     556   401211007 :                         mp->m_bm_maxlevels[whichfork], xfs_bmbt_cur_cache);
     557   401220800 :         cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_bmbt_2);
     558             : 
     559   401220800 :         cur->bc_ino.ip = ip;
     560   401220800 :         cur->bc_ino.allocated = 0;
     561   401220800 :         cur->bc_ino.flags = 0;
     562             : 
     563   401220800 :         return cur;
     564             : }
     565             : 
     566             : /*
     567             :  * Allocate a new bmap btree cursor.
     568             :  */
     569             : struct xfs_btree_cur *                          /* new bmap btree cursor */
     570   398646845 : 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   398646845 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     577   398642597 :         struct xfs_btree_cur    *cur;
     578             : 
     579   398642597 :         cur = xfs_bmbt_init_common(mp, tp, ip, whichfork);
     580             : 
     581   398652100 :         cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
     582   398652100 :         cur->bc_ino.forksize = xfs_inode_fork_size(ip, whichfork);
     583   398652100 :         cur->bc_ino.whichfork = whichfork;
     584             : 
     585   398652100 :         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   842142337 :         if (leaf)
     595       60890 :                 return blocklen / sizeof(xfs_bmbt_rec_t);
     596   825660250 :         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     2568677 : xfs_bmbt_stage_cursor(
     607             :         struct xfs_mount        *mp,
     608             :         struct xfs_inode        *ip,
     609             :         struct xbtree_ifakeroot *ifake)
     610             : {
     611     2568677 :         struct xfs_btree_cur    *cur;
     612     2568677 :         struct xfs_btree_ops    *ops;
     613             : 
     614     2568677 :         cur = xfs_bmbt_init_common(mp, NULL, ip, ifake->if_whichfork);
     615     2568677 :         cur->bc_nlevels = ifake->if_levels;
     616     2568677 :         cur->bc_ino.forksize = ifake->if_fork_size;
     617             :         /* Don't let anyone think we're attached to the real fork yet. */
     618     2568677 :         cur->bc_ino.whichfork = -1;
     619     2568677 :         xfs_btree_stage_ifakeroot(cur, ifake, &ops);
     620     2568677 :         ops->update_cursor = NULL;
     621     2568677 :         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     2568665 : xfs_bmbt_commit_staged_btree(
     630             :         struct xfs_btree_cur    *cur,
     631             :         struct xfs_trans        *tp,
     632             :         int                     whichfork)
     633             : {
     634     2568665 :         struct xbtree_ifakeroot *ifake = cur->bc_ino.ifake;
     635     2568665 :         struct xfs_ifork        *ifp;
     636     2568665 :         static const short      brootflag[2] =
     637             :                 { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
     638     2568665 :         static const short      extflag[2] =
     639             :                 { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
     640     2568665 :         int                     flags = XFS_ILOG_CORE;
     641             : 
     642     2568665 :         ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
     643     2568665 :         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     2568665 :         ifp = xfs_ifork_ptr(cur->bc_ino.ip, whichfork);
     651     2568665 :         xfs_idestroy_fork(ifp);
     652     5137330 :         memcpy(ifp, ifake->if_fork, sizeof(struct xfs_ifork));
     653             : 
     654     2568665 :         switch (ifp->if_format) {
     655     2544908 :         case XFS_DINODE_FMT_EXTENTS:
     656     2544908 :                 flags |= extflag[whichfork];
     657     2544908 :                 break;
     658       23757 :         case XFS_DINODE_FMT_BTREE:
     659       23757 :                 flags |= brootflag[whichfork];
     660       23757 :                 break;
     661           0 :         default:
     662           0 :                 ASSERT(0);
     663           0 :                 break;
     664             :         }
     665     2568665 :         xfs_trans_log_inode(tp, cur->bc_ino.ip, flags);
     666     2568665 :         xfs_btree_commit_ifakeroot(cur, tp, whichfork, &xfs_bmbt_ops);
     667     2568665 : }
     668             : 
     669             : /*
     670             :  * Calculate number of records in a bmap btree block.
     671             :  */
     672             : int
     673   420958340 : xfs_bmbt_maxrecs(
     674             :         struct xfs_mount        *mp,
     675             :         int                     blocklen,
     676             :         int                     leaf)
     677             : {
     678   825721140 :         blocklen -= XFS_BMBT_BLOCK_LEN(mp);
     679  1246905137 :         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      121810 : xfs_bmbt_maxlevels_ondisk(void)
     689             : {
     690      121810 :         unsigned int            minrecs[2];
     691      121810 :         unsigned int            blocklen;
     692             : 
     693      121810 :         blocklen = min(XFS_MIN_BLOCKSIZE - XFS_BTREE_SBLOCK_LEN,
     694             :                        XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN);
     695             : 
     696      121810 :         minrecs[0] = xfs_bmbt_block_maxrecs(blocklen, true) / 2;
     697      121810 :         minrecs[1] = xfs_bmbt_block_maxrecs(blocklen, false) / 2;
     698             : 
     699             :         /* One extra level for the inode root. */
     700      121810 :         return xfs_btree_compute_maxlevels(minrecs,
     701      121810 :                         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      121760 : xfs_bmdr_maxrecs(
     709             :         int                     blocklen,
     710             :         int                     leaf)
     711             : {
     712    19156713 :         blocklen -= sizeof(xfs_bmdr_block_t);
     713             : 
     714     2735516 :         if (leaf)
     715       47538 :                 return blocklen / sizeof(xfs_bmdr_rec_t);
     716    19109175 :         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       13654 : 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       13654 :         struct xfs_btree_cur    *cur;
     745       13654 :         int                     error;
     746             : 
     747       13654 :         ASSERT(tp || buffer_list);
     748       13654 :         ASSERT(!(tp && buffer_list));
     749       13654 :         ASSERT(xfs_ifork_ptr(ip, whichfork)->if_format == XFS_DINODE_FMT_BTREE);
     750             : 
     751       13654 :         cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
     752       13654 :         cur->bc_ino.flags |= XFS_BTCUR_BMBT_INVALID_OWNER;
     753             : 
     754       13654 :         error = xfs_btree_change_owner(cur, new_owner, buffer_list);
     755       13654 :         xfs_btree_del_cursor(cur, error);
     756       13654 :         return error;
     757             : }
     758             : 
     759             : /* Calculate the bmap btree size for some records. */
     760             : unsigned long long
     761     1421121 : xfs_bmbt_calc_size(
     762             :         struct xfs_mount        *mp,
     763             :         unsigned long long      len)
     764             : {
     765     1421121 :         return xfs_btree_calc_size(mp->m_bmap_dmnr, len);
     766             : }
     767             : 
     768             : int __init
     769          50 : xfs_bmbt_init_cur_cache(void)
     770             : {
     771          50 :         xfs_bmbt_cur_cache = kmem_cache_create("xfs_bmbt_cur",
     772          50 :                         xfs_btree_cur_sizeof(xfs_bmbt_maxlevels_ondisk()),
     773             :                         0, 0, NULL);
     774             : 
     775          50 :         if (!xfs_bmbt_cur_cache)
     776           0 :                 return -ENOMEM;
     777             :         return 0;
     778             : }
     779             : 
     780             : void
     781          49 : xfs_bmbt_destroy_cur_cache(void)
     782             : {
     783          49 :         kmem_cache_destroy(xfs_bmbt_cur_cache);
     784          49 :         xfs_bmbt_cur_cache = NULL;
     785          49 : }

Generated by: LCOV version 1.14