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-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 300 325 92.3 %
Date: 2023-07-31 20:08:34 Functions: 36 38 94.7 %

          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    12989722 : 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    12989722 :         struct xfs_mount        *mp = ip->i_mount;
      41    12989722 :         int                     dmxr;
      42    12989722 :         xfs_bmbt_key_t          *fkp;
      43    12989722 :         __be64                  *fpp;
      44    12989722 :         xfs_bmbt_key_t          *tkp;
      45    12989722 :         __be64                  *tpp;
      46             : 
      47    12989722 :         xfs_btree_init_block(mp, rblock, &xfs_bmbt_ops, 0, 0, ip->i_ino);
      48    12989714 :         rblock->bb_level = dblock->bb_level;
      49    12989714 :         ASSERT(be16_to_cpu(rblock->bb_level) > 0);
      50    12989714 :         rblock->bb_numrecs = dblock->bb_numrecs;
      51    12989714 :         dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
      52    12989714 :         fkp = xfs_bmdr_key_addr(dblock, 1);
      53    12989714 :         tkp = xfs_bmbt_key_addr(mp, rblock, 1);
      54    12989714 :         fpp = xfs_bmdr_ptr_addr(dblock, 1, dmxr);
      55    12989714 :         tpp = xfs_bmap_broot_ptr_addr(mp, rblock, 1, rblocklen);
      56    12989714 :         dmxr = be16_to_cpu(dblock->bb_numrecs);
      57    25979428 :         memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
      58    25979428 :         memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
      59    12989714 : }
      60             : 
      61             : void
      62  2332369594 : xfs_bmbt_disk_get_all(
      63             :         const struct xfs_bmbt_rec *rec,
      64             :         struct xfs_bmbt_irec    *irec)
      65             : {
      66  2332369594 :         uint64_t                l0 = get_unaligned_be64(&rec->l0);
      67             :         uint64_t                l1 = get_unaligned_be64(&rec->l1);
      68             : 
      69  2332369594 :         irec->br_startoff = (l0 & xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
      70  2332369594 :         irec->br_startblock = ((l0 & xfs_mask64lo(9)) << 43) | (l1 >> 21);
      71  2332369594 :         irec->br_blockcount = l1 & xfs_mask64lo(21);
      72  2332369594 :         if (l0 >> (64 - BMBT_EXNTFLAG_BITLEN))
      73   126578491 :                 irec->br_state = XFS_EXT_UNWRITTEN;
      74             :         else
      75  2205791103 :                 irec->br_state = XFS_EXT_NORM;
      76  2332369594 : }
      77             : 
      78             : /*
      79             :  * Extract the blockcount field from an on disk bmap extent record.
      80             :  */
      81             : xfs_filblks_t
      82 >15011*10^7 : xfs_bmbt_disk_get_blockcount(
      83             :         const struct xfs_bmbt_rec       *r)
      84             : {
      85 >15106*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 >30254*10^7 : xfs_bmbt_disk_get_startoff(
      93             :         const struct xfs_bmbt_rec       *r)
      94             : {
      95 >30763*10^7 :         return ((xfs_fileoff_t)be64_to_cpu(r->l0) &
      96 >30763*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  3687568823 : xfs_bmbt_disk_set_all(
     104             :         struct xfs_bmbt_rec     *r,
     105             :         struct xfs_bmbt_irec    *s)
     106             : {
     107  3687568823 :         int                     extent_flag = (s->br_state != XFS_EXT_NORM);
     108             : 
     109  3687568823 :         ASSERT(s->br_state == XFS_EXT_NORM || s->br_state == XFS_EXT_UNWRITTEN);
     110  3687568823 :         ASSERT(!(s->br_startoff & xfs_mask64hi(64-BMBT_STARTOFF_BITLEN)));
     111  3687568823 :         ASSERT(!(s->br_blockcount & xfs_mask64hi(64-BMBT_BLOCKCOUNT_BITLEN)));
     112  3687568823 :         ASSERT(!(s->br_startblock & xfs_mask64hi(64-BMBT_STARTBLOCK_BITLEN)));
     113             : 
     114  3687568823 :         put_unaligned_be64(
     115  3687568823 :                 ((xfs_bmbt_rec_base_t)extent_flag << 63) |
     116  3687568823 :                  ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
     117  3687568823 :                  ((xfs_bmbt_rec_base_t)s->br_startblock >> 43), &r->l0);
     118  3687568823 :         put_unaligned_be64(
     119  3687568823 :                 ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
     120  3687568823 :                  ((xfs_bmbt_rec_base_t)s->br_blockcount &
     121             :                   (xfs_bmbt_rec_base_t)xfs_mask64lo(21)), &r->l1);
     122  3687568823 : }
     123             : 
     124             : /*
     125             :  * Convert in-memory form of btree root to on-disk form.
     126             :  */
     127             : void
     128     3791502 : 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     3791502 :         int                     dmxr;
     136     3791502 :         xfs_bmbt_key_t          *fkp;
     137     3791502 :         __be64                  *fpp;
     138     3791502 :         xfs_bmbt_key_t          *tkp;
     139     3791502 :         __be64                  *tpp;
     140             : 
     141     3791502 :         if (xfs_has_crc(mp)) {
     142     3791502 :                 ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC));
     143     3791502 :                 ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid,
     144             :                        &mp->m_sb.sb_meta_uuid));
     145     3791502 :                 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     3791502 :         ASSERT(rblock->bb_u.l.bb_leftsib == cpu_to_be64(NULLFSBLOCK));
     150     3791502 :         ASSERT(rblock->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK));
     151     3791502 :         ASSERT(rblock->bb_level != 0);
     152     3791502 :         dblock->bb_level = rblock->bb_level;
     153     3791502 :         dblock->bb_numrecs = rblock->bb_numrecs;
     154     3791502 :         dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
     155     3791502 :         fkp = xfs_bmbt_key_addr(mp, rblock, 1);
     156     3791502 :         tkp = xfs_bmdr_key_addr(dblock, 1);
     157     3791502 :         fpp = xfs_bmap_broot_ptr_addr(mp, rblock, 1, rblocklen);
     158     3791502 :         tpp = xfs_bmdr_ptr_addr(dblock, 1, dmxr);
     159     3791502 :         dmxr = be16_to_cpu(dblock->bb_numrecs);
     160     7583004 :         memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
     161     7583004 :         memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
     162     3791502 : }
     163             : 
     164             : STATIC struct xfs_btree_cur *
     165    59043696 : xfs_bmbt_dup_cursor(
     166             :         struct xfs_btree_cur    *cur)
     167             : {
     168    59043696 :         struct xfs_btree_cur    *new;
     169             : 
     170    59043696 :         new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp,
     171    59043696 :                         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    59044008 :         new->bc_ino.flags = cur->bc_ino.flags;
     178             : 
     179    59044008 :         return new;
     180             : }
     181             : 
     182             : STATIC void
     183      665184 : xfs_bmbt_update_cursor(
     184             :         struct xfs_btree_cur    *src,
     185             :         struct xfs_btree_cur    *dst)
     186             : {
     187      665184 :         ASSERT((dst->bc_tp->t_highest_agno != NULLAGNUMBER) ||
     188             :                (dst->bc_ino.ip->i_diflags & XFS_DIFLAG_REALTIME));
     189             : 
     190      665184 :         dst->bc_ino.allocated += src->bc_ino.allocated;
     191      665184 :         dst->bc_tp->t_highest_agno = src->bc_tp->t_highest_agno;
     192             : 
     193      665184 :         src->bc_ino.allocated = 0;
     194      665184 : }
     195             : 
     196             : STATIC int
     197      668541 : 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      668541 :         struct xfs_alloc_arg    args;
     204      668541 :         int                     error;
     205             : 
     206      668541 :         memset(&args, 0, sizeof(args));
     207      668541 :         args.tp = cur->bc_tp;
     208      668541 :         args.mp = cur->bc_mp;
     209      668541 :         xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_ino.ip->i_ino,
     210      668541 :                         cur->bc_ino.whichfork);
     211      668541 :         args.minlen = args.maxlen = args.prod = 1;
     212      668541 :         args.wasdel = cur->bc_ino.flags & XFS_BTCUR_BMBT_WASDEL;
     213      668541 :         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      668541 :         if (cur->bc_tp->t_highest_agno == NULLAGNUMBER)
     223      611118 :                 args.minleft = xfs_bmapi_minleft(cur->bc_tp, cur->bc_ino.ip,
     224             :                                         cur->bc_ino.whichfork);
     225             : 
     226      668541 :         error = xfs_alloc_vextent_start_ag(&args, be64_to_cpu(start->l));
     227      668542 :         if (error)
     228             :                 return error;
     229             : 
     230      668538 :         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      668538 :         if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
     243           0 :                 *stat = 0;
     244           0 :                 return 0;
     245             :         }
     246             : 
     247      668538 :         ASSERT(args.len == 1);
     248      668538 :         cur->bc_ino.allocated++;
     249      668538 :         cur->bc_ino.ip->i_nblocks++;
     250      668538 :         xfs_trans_log_inode(args.tp, cur->bc_ino.ip, XFS_ILOG_CORE);
     251      668538 :         xfs_trans_mod_dquot_byino(args.tp, cur->bc_ino.ip,
     252             :                         XFS_TRANS_DQ_BCOUNT, 1L);
     253             : 
     254      668538 :         new->l = cpu_to_be64(args.fsbno);
     255             : 
     256      668538 :         *stat = 1;
     257      668538 :         return 0;
     258             : }
     259             : 
     260             : STATIC int
     261      183902 : xfs_bmbt_free_block(
     262             :         struct xfs_btree_cur    *cur,
     263             :         struct xfs_buf          *bp)
     264             : {
     265      183902 :         struct xfs_mount        *mp = cur->bc_mp;
     266      183902 :         struct xfs_inode        *ip = cur->bc_ino.ip;
     267      183902 :         struct xfs_trans        *tp = cur->bc_tp;
     268      183902 :         xfs_fsblock_t           fsbno = XFS_DADDR_TO_FSB(mp, xfs_buf_daddr(bp));
     269      183902 :         struct xfs_owner_info   oinfo;
     270      183902 :         int                     error;
     271             : 
     272      183902 :         xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_ino.whichfork);
     273      183902 :         error = xfs_free_extent_later(cur->bc_tp, fsbno, 1, &oinfo,
     274             :                         XFS_AG_RESV_NONE, 0);
     275      183902 :         if (error)
     276             :                 return error;
     277             : 
     278      183902 :         ip->i_nblocks--;
     279      183902 :         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
     280      183902 :         xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
     281      183902 :         return 0;
     282             : }
     283             : 
     284             : STATIC int
     285   138074245 : xfs_bmbt_get_minrecs(
     286             :         struct xfs_btree_cur    *cur,
     287             :         int                     level)
     288             : {
     289   138074245 :         if (level == cur->bc_nlevels - 1) {
     290     2508496 :                 struct xfs_ifork        *ifp = xfs_btree_ifork_ptr(cur);
     291             : 
     292     2508425 :                 return xfs_bmbt_maxrecs(cur->bc_mp,
     293     2508425 :                                         ifp->if_broot_bytes, level == 0) / 2;
     294             :         }
     295             : 
     296   135565749 :         return cur->bc_mp->m_bmap_dmnr[level != 0];
     297             : }
     298             : 
     299             : int
     300  2388850835 : xfs_bmbt_get_maxrecs(
     301             :         struct xfs_btree_cur    *cur,
     302             :         int                     level)
     303             : {
     304  2388850835 :         if (level == cur->bc_nlevels - 1) {
     305   525807960 :                 struct xfs_ifork        *ifp = xfs_btree_ifork_ptr(cur);
     306             : 
     307   525806311 :                 return xfs_bmbt_maxrecs(cur->bc_mp,
     308   525806311 :                                         ifp->if_broot_bytes, level == 0);
     309             :         }
     310             : 
     311  1863042875 :         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     3353544 : xfs_bmbt_get_dmaxrecs(
     326             :         struct xfs_btree_cur    *cur,
     327             :         int                     level)
     328             : {
     329     3353544 :         if (level != cur->bc_nlevels - 1)
     330      211242 :                 return cur->bc_mp->m_bmap_dmxr[level != 0];
     331     3142302 :         return xfs_bmdr_maxrecs(cur->bc_ino.forksize, level == 0);
     332             : }
     333             : 
     334             : STATIC void
     335  4144397854 : xfs_bmbt_init_key_from_rec(
     336             :         union xfs_btree_key             *key,
     337             :         const union xfs_btree_rec       *rec)
     338             : {
     339  4144397854 :         key->bmbt.br_startoff =
     340  4144397854 :                 cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt));
     341  4144397854 : }
     342             : 
     343             : STATIC void
     344           0 : xfs_bmbt_init_high_key_from_rec(
     345             :         union xfs_btree_key             *key,
     346             :         const union xfs_btree_rec       *rec)
     347             : {
     348           0 :         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           0 : }
     352             : 
     353             : STATIC void
     354   307496939 : xfs_bmbt_init_rec_from_cur(
     355             :         struct xfs_btree_cur    *cur,
     356             :         union xfs_btree_rec     *rec)
     357             : {
     358   307496939 :         xfs_bmbt_disk_set_all(&rec->bmbt, &cur->bc_rec.b);
     359   307496171 : }
     360             : 
     361             : STATIC void
     362   509117797 : xfs_bmbt_init_ptr_from_cur(
     363             :         struct xfs_btree_cur    *cur,
     364             :         union xfs_btree_ptr     *ptr)
     365             : {
     366   509117797 :         ptr->l = 0;
     367   509117797 : }
     368             : 
     369             : STATIC int64_t
     370  5491437452 : xfs_bmbt_key_diff(
     371             :         struct xfs_btree_cur            *cur,
     372             :         const union xfs_btree_key       *key)
     373             : {
     374  5491437452 :         return (int64_t)be64_to_cpu(key->bmbt.br_startoff) -
     375  5491437452 :                                       cur->bc_rec.b.br_startoff;
     376             : }
     377             : 
     378             : STATIC int64_t
     379   717165527 : 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   717165527 :         uint64_t                        a = be64_to_cpu(k1->bmbt.br_startoff);
     386   717165527 :         uint64_t                        b = be64_to_cpu(k2->bmbt.br_startoff);
     387             : 
     388   717165527 :         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   717165527 :         if (a > b)
     397             :                 return 1;
     398    16276697 :         if (b > a)
     399           0 :                 return -1;
     400             :         return 0;
     401             : }
     402             : 
     403             : static xfs_failaddr_t
     404    34971909 : xfs_bmbt_verify(
     405             :         struct xfs_buf          *bp)
     406             : {
     407    34971909 :         struct xfs_mount        *mp = bp->b_mount;
     408    34971909 :         struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
     409    34971909 :         xfs_failaddr_t          fa;
     410    34971909 :         unsigned int            level;
     411             : 
     412    34971909 :         if (!xfs_verify_magic(bp, block->bb_magic))
     413           0 :                 return __this_address;
     414             : 
     415    34971740 :         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    34971708 :                 fa = xfs_btree_lblock_v5hdr_verify(bp, XFS_RMAP_OWN_UNKNOWN);
     421    34971802 :                 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    34971852 :         level = be16_to_cpu(block->bb_level);
     433    34971852 :         if (level > max(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1]))
     434           0 :                 return __this_address;
     435             : 
     436    34971852 :         return xfs_btree_lblock_verify(bp, mp->m_bmap_dmxr[level != 0]);
     437             : }
     438             : 
     439             : static void
     440     5166785 : xfs_bmbt_read_verify(
     441             :         struct xfs_buf  *bp)
     442             : {
     443     5166785 :         xfs_failaddr_t  fa;
     444             : 
     445     5166785 :         if (!xfs_btree_lblock_verify_crc(bp))
     446          20 :                 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
     447             :         else {
     448     5166765 :                 fa = xfs_bmbt_verify(bp);
     449     5166765 :                 if (fa)
     450           0 :                         xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     451             :         }
     452             : 
     453     5166785 :         if (bp->b_error)
     454          20 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     455     5166785 : }
     456             : 
     457             : static void
     458    19774776 : xfs_bmbt_write_verify(
     459             :         struct xfs_buf  *bp)
     460             : {
     461    19774776 :         xfs_failaddr_t  fa;
     462             : 
     463    19774776 :         fa = xfs_bmbt_verify(bp);
     464    19774774 :         if (fa) {
     465           0 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     466           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     467           0 :                 return;
     468             :         }
     469    19774774 :         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     3123793 : 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     3123793 :         return be64_to_cpu(k1->bmbt.br_startoff) <
     489     3123793 :                 be64_to_cpu(k2->bmbt.br_startoff);
     490             : }
     491             : 
     492             : STATIC int
     493   944720602 : 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   944720602 :         return xfs_bmbt_disk_get_startoff(&r1->bmbt) +
     499   944720602 :                 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             : /* Move the bmap btree root from one incore buffer to another. */
     517             : static void
     518      233496 : xfs_bmbt_broot_move(
     519             :         struct xfs_inode        *ip,
     520             :         int                     whichfork,
     521             :         struct xfs_btree_block  *dst_broot,
     522             :         size_t                  dst_bytes,
     523             :         struct xfs_btree_block  *src_broot,
     524             :         size_t                  src_bytes,
     525             :         unsigned int            level,
     526             :         unsigned int            numrecs)
     527             : {
     528      233496 :         struct xfs_mount        *mp = ip->i_mount;
     529      233496 :         void                    *dptr;
     530      233496 :         void                    *sptr;
     531             : 
     532      233496 :         ASSERT(xfs_bmap_bmdr_space(src_broot) <= xfs_inode_fork_size(ip, whichfork));
     533      233496 :         ASSERT(level > 0);
     534             : 
     535             :         /*
     536             :          * We always have to move the pointers because they are not butted
     537             :          * against the btree block header.
     538             :          */
     539      233496 :         if (numrecs) {
     540      233496 :                 sptr = xfs_bmap_broot_ptr_addr(mp, src_broot, 1, src_bytes);
     541      233496 :                 dptr = xfs_bmap_broot_ptr_addr(mp, dst_broot, 1, dst_bytes);
     542      466992 :                 memmove(dptr, sptr, numrecs * sizeof(xfs_fsblock_t));
     543             :         }
     544             : 
     545      233496 :         if (src_broot == dst_broot)
     546             :                 return;
     547             : 
     548             :         /*
     549             :          * If the root is being totally relocated, we have to migrate the block
     550             :          * header and the keys that come after it.
     551             :          */
     552       75636 :         memcpy(dst_broot, src_broot, xfs_bmbt_block_len(mp));
     553             : 
     554             :         /* Now copy the keys, which come right after the header. */
     555       37818 :         if (numrecs) {
     556       37818 :                 sptr = xfs_bmbt_key_addr(mp, src_broot, 1);
     557       37818 :                 dptr = xfs_bmbt_key_addr(mp, dst_broot, 1);
     558       75636 :                 memcpy(dptr, sptr, numrecs * sizeof(struct xfs_bmbt_key));
     559             :         }
     560             : }
     561             : 
     562             : static const struct xfs_ifork_broot_ops xfs_bmbt_iroot_ops = {
     563             :         .maxrecs                = xfs_bmbt_maxrecs,
     564             :         .size                   = xfs_bmap_broot_space_calc,
     565             :         .move                   = xfs_bmbt_broot_move,
     566             : };
     567             : 
     568             : const struct xfs_btree_ops xfs_bmbt_ops = {
     569             :         .rec_len                = sizeof(xfs_bmbt_rec_t),
     570             :         .key_len                = sizeof(xfs_bmbt_key_t),
     571             :         .lru_refs               = XFS_BMAP_BTREE_REF,
     572             :         .geom_flags             = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE,
     573             : 
     574             :         .dup_cursor             = xfs_bmbt_dup_cursor,
     575             :         .update_cursor          = xfs_bmbt_update_cursor,
     576             :         .alloc_block            = xfs_bmbt_alloc_block,
     577             :         .free_block             = xfs_bmbt_free_block,
     578             :         .get_maxrecs            = xfs_bmbt_get_maxrecs,
     579             :         .get_minrecs            = xfs_bmbt_get_minrecs,
     580             :         .get_dmaxrecs           = xfs_bmbt_get_dmaxrecs,
     581             :         .init_key_from_rec      = xfs_bmbt_init_key_from_rec,
     582             :         .init_high_key_from_rec = xfs_bmbt_init_high_key_from_rec,
     583             :         .init_rec_from_cur      = xfs_bmbt_init_rec_from_cur,
     584             :         .init_ptr_from_cur      = xfs_bmbt_init_ptr_from_cur,
     585             :         .key_diff               = xfs_bmbt_key_diff,
     586             :         .diff_two_keys          = xfs_bmbt_diff_two_keys,
     587             :         .buf_ops                = &xfs_bmbt_buf_ops,
     588             :         .keys_inorder           = xfs_bmbt_keys_inorder,
     589             :         .recs_inorder           = xfs_bmbt_recs_inorder,
     590             :         .keys_contiguous        = xfs_bmbt_keys_contiguous,
     591             :         .iroot_ops              = &xfs_bmbt_iroot_ops,
     592             : };
     593             : 
     594             : /*
     595             :  * Allocate a new bmap btree cursor.
     596             :  */
     597             : static struct xfs_btree_cur *                   /* new bmap btree cursor */
     598   541636988 : xfs_bmbt_init_common(
     599             :         struct xfs_mount        *mp,            /* file system mount point */
     600             :         struct xfs_trans        *tp,            /* transaction pointer */
     601             :         struct xfs_inode        *ip,            /* inode owning the btree */
     602             :         int                     whichfork)
     603             : {
     604   541636988 :         struct xfs_btree_cur    *cur;
     605             : 
     606   541636988 :         ASSERT(whichfork != XFS_COW_FORK);
     607             : 
     608  1083276305 :         cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_BMAP, &xfs_bmbt_ops,
     609   541636988 :                         mp->m_bm_maxlevels[whichfork], xfs_bmbt_cur_cache);
     610   541646672 :         cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_bmbt_2);
     611             : 
     612   541646672 :         cur->bc_ino.ip = ip;
     613   541646672 :         cur->bc_ino.allocated = 0;
     614   541646672 :         cur->bc_ino.flags = 0;
     615             : 
     616   541646672 :         return cur;
     617             : }
     618             : 
     619             : /*
     620             :  * Allocate a new bmap btree cursor.
     621             :  */
     622             : struct xfs_btree_cur *                          /* new bmap btree cursor */
     623   538304488 : xfs_bmbt_init_cursor(
     624             :         struct xfs_mount        *mp,            /* file system mount point */
     625             :         struct xfs_trans        *tp,            /* transaction pointer */
     626             :         struct xfs_inode        *ip,            /* inode owning the btree */
     627             :         int                     whichfork)      /* data or attr fork */
     628             : {
     629   538304488 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     630   538297019 :         struct xfs_btree_cur    *cur;
     631             : 
     632   538297019 :         cur = xfs_bmbt_init_common(mp, tp, ip, whichfork);
     633             : 
     634   538306715 :         cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
     635   538306715 :         cur->bc_ino.forksize = xfs_inode_fork_size(ip, whichfork);
     636   538306715 :         cur->bc_ino.whichfork = whichfork;
     637             : 
     638   538306715 :         return cur;
     639             : }
     640             : 
     641             : /* Calculate number of records in a block mapping btree block. */
     642             : static inline unsigned int
     643             : xfs_bmbt_block_maxrecs(
     644             :         unsigned int            blocklen,
     645             :         bool                    leaf)
     646             : {
     647  1335910728 :         if (leaf)
     648       66982 :                 return blocklen / sizeof(xfs_bmbt_rec_t);
     649  1318829034 :         return blocklen / (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t));
     650             : }
     651             : 
     652             : /*
     653             :  * Allocate a new bmap btree cursor for reloading an inode block mapping data
     654             :  * structure.  Note that callers can use the staged cursor to reload extents
     655             :  * format inode forks if they rebuild the iext tree and commit the staged
     656             :  * cursor immediately.
     657             :  */
     658             : struct xfs_btree_cur *
     659     3340419 : xfs_bmbt_stage_cursor(
     660             :         struct xfs_mount        *mp,
     661             :         struct xfs_inode        *ip,
     662             :         struct xbtree_ifakeroot *ifake)
     663             : {
     664     3340419 :         struct xfs_btree_cur    *cur;
     665     3340419 :         struct xfs_btree_ops    *ops;
     666             : 
     667     3340419 :         cur = xfs_bmbt_init_common(mp, NULL, ip, ifake->if_whichfork);
     668     3340419 :         cur->bc_nlevels = ifake->if_levels;
     669     3340419 :         cur->bc_ino.forksize = ifake->if_fork_size;
     670             :         /* Don't let anyone think we're attached to the real fork yet. */
     671     3340419 :         cur->bc_ino.whichfork = -1;
     672     3340419 :         xfs_btree_stage_ifakeroot(cur, ifake, &ops);
     673     3340419 :         ops->update_cursor = NULL;
     674     3340419 :         return cur;
     675             : }
     676             : 
     677             : /*
     678             :  * Swap in the new inode fork root.  Once we pass this point the newly rebuilt
     679             :  * mappings are in place and we have to kill off any old btree blocks.
     680             :  */
     681             : void
     682     3340405 : xfs_bmbt_commit_staged_btree(
     683             :         struct xfs_btree_cur    *cur,
     684             :         struct xfs_trans        *tp,
     685             :         int                     whichfork)
     686             : {
     687     3340405 :         struct xbtree_ifakeroot *ifake = cur->bc_ino.ifake;
     688     3340405 :         struct xfs_ifork        *ifp;
     689     3340405 :         static const short      brootflag[2] =
     690             :                 { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
     691     3340405 :         static const short      extflag[2] =
     692             :                 { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
     693     3340405 :         int                     flags = XFS_ILOG_CORE;
     694             : 
     695     3340405 :         ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
     696     3340405 :         ASSERT(whichfork != XFS_COW_FORK);
     697             : 
     698             :         /*
     699             :          * Free any resources hanging off the real fork, then shallow-copy the
     700             :          * staging fork's contents into the real fork to transfer everything
     701             :          * we just built.
     702             :          */
     703     3340405 :         ifp = xfs_ifork_ptr(cur->bc_ino.ip, whichfork);
     704     3340405 :         xfs_idestroy_fork(ifp);
     705     6680806 :         memcpy(ifp, ifake->if_fork, sizeof(struct xfs_ifork));
     706             : 
     707     3340403 :         switch (ifp->if_format) {
     708     3241364 :         case XFS_DINODE_FMT_EXTENTS:
     709     3241364 :                 flags |= extflag[whichfork];
     710     3241364 :                 break;
     711       99039 :         case XFS_DINODE_FMT_BTREE:
     712       99039 :                 flags |= brootflag[whichfork];
     713       99040 :                 break;
     714           0 :         default:
     715           0 :                 ASSERT(0);
     716           0 :                 break;
     717             :         }
     718     3340404 :         xfs_trans_log_inode(tp, cur->bc_ino.ip, flags);
     719     3340404 :         xfs_btree_commit_ifakeroot(cur, tp, whichfork, &xfs_bmbt_ops);
     720     3340404 : }
     721             : 
     722             : /*
     723             :  * Calculate number of records in a bmap btree block.
     724             :  */
     725             : unsigned int
     726   790581280 : xfs_bmbt_maxrecs(
     727             :         struct xfs_mount        *mp,
     728             :         unsigned int            blocklen,
     729             :         bool                    leaf)
     730             : {
     731  1319129512 :         blocklen -= xfs_bmbt_block_len(mp);
     732  1335910728 :         return xfs_bmbt_block_maxrecs(blocklen, leaf);
     733             : }
     734             : 
     735             : /*
     736             :  * Calculate the maximum possible height of the btree that the on-disk format
     737             :  * supports. This is used for sizing structures large enough to support every
     738             :  * possible configuration of a filesystem that might get mounted.
     739             :  */
     740             : unsigned int
     741      134003 : xfs_bmbt_maxlevels_ondisk(void)
     742             : {
     743      134003 :         unsigned int            minrecs[2];
     744      134003 :         unsigned int            blocklen;
     745             : 
     746      134003 :         blocklen = min(XFS_MIN_BLOCKSIZE - XFS_BTREE_SBLOCK_LEN,
     747             :                        XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN);
     748             : 
     749      134003 :         minrecs[0] = xfs_bmbt_block_maxrecs(blocklen, true) / 2;
     750      134003 :         minrecs[1] = xfs_bmbt_block_maxrecs(blocklen, false) / 2;
     751             : 
     752             :         /* One extra level for the inode root. */
     753      134003 :         return xfs_btree_compute_maxlevels(minrecs,
     754      134003 :                         XFS_MAX_EXTCNT_DATA_FORK_LARGE) + 1;
     755             : }
     756             : 
     757             : /*
     758             :  * Calculate number of records in a bmap btree inode root.
     759             :  */
     760             : int
     761      133944 : xfs_bmdr_maxrecs(
     762             :         int                     blocklen,
     763             :         int                     leaf)
     764             : {
     765    20057462 :         blocklen -= sizeof(xfs_bmdr_block_t);
     766             : 
     767     3276246 :         if (leaf)
     768      198110 :                 return blocklen / sizeof(xfs_bmdr_rec_t);
     769    19859352 :         return blocklen / (sizeof(xfs_bmdr_key_t) + sizeof(xfs_bmdr_ptr_t));
     770             : }
     771             : 
     772             : /*
     773             :  * Change the owner of a btree format fork fo the inode passed in. Change it to
     774             :  * the owner of that is passed in so that we can change owners before or after
     775             :  * we switch forks between inodes. The operation that the caller is doing will
     776             :  * determine whether is needs to change owner before or after the switch.
     777             :  *
     778             :  * For demand paged transactional modification, the fork switch should be done
     779             :  * after reading in all the blocks, modifying them and pinning them in the
     780             :  * transaction. For modification when the buffers are already pinned in memory,
     781             :  * the fork switch can be done before changing the owner as we won't need to
     782             :  * validate the owner until the btree buffers are unpinned and writes can occur
     783             :  * again.
     784             :  *
     785             :  * For recovery based ownership change, there is no transactional context and
     786             :  * so a buffer list must be supplied so that we can record the buffers that we
     787             :  * modified for the caller to issue IO on.
     788             :  */
     789             : int
     790        2707 : xfs_bmbt_change_owner(
     791             :         struct xfs_trans        *tp,
     792             :         struct xfs_inode        *ip,
     793             :         int                     whichfork,
     794             :         xfs_ino_t               new_owner,
     795             :         struct list_head        *buffer_list)
     796             : {
     797        2707 :         struct xfs_btree_cur    *cur;
     798        2707 :         int                     error;
     799             : 
     800        2707 :         ASSERT(tp || buffer_list);
     801        2707 :         ASSERT(!(tp && buffer_list));
     802        2707 :         ASSERT(xfs_ifork_ptr(ip, whichfork)->if_format == XFS_DINODE_FMT_BTREE);
     803             : 
     804        2707 :         cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
     805        2707 :         cur->bc_ino.flags |= XFS_BTCUR_BMBT_INVALID_OWNER;
     806             : 
     807        2707 :         error = xfs_btree_change_owner(cur, new_owner, buffer_list);
     808        2707 :         xfs_btree_del_cursor(cur, error);
     809        2707 :         return error;
     810             : }
     811             : 
     812             : /* Calculate the bmap btree size for some records. */
     813             : unsigned long long
     814      242690 : xfs_bmbt_calc_size(
     815             :         struct xfs_mount        *mp,
     816             :         unsigned long long      len)
     817             : {
     818      242690 :         return xfs_btree_calc_size(mp->m_bmap_dmnr, len);
     819             : }
     820             : 
     821             : int __init
     822          59 : xfs_bmbt_init_cur_cache(void)
     823             : {
     824          59 :         xfs_bmbt_cur_cache = kmem_cache_create("xfs_bmbt_cur",
     825          59 :                         xfs_btree_cur_sizeof(xfs_bmbt_maxlevels_ondisk()),
     826             :                         0, 0, NULL);
     827             : 
     828          59 :         if (!xfs_bmbt_cur_cache)
     829           0 :                 return -ENOMEM;
     830             :         return 0;
     831             : }
     832             : 
     833             : void
     834          58 : xfs_bmbt_destroy_cur_cache(void)
     835             : {
     836          58 :         kmem_cache_destroy(xfs_bmbt_cur_cache);
     837          58 :         xfs_bmbt_cur_cache = NULL;
     838          58 : }
     839             : 
     840             : /* Create an incore bmbt btree root block. */
     841             : void
     842     3746201 : xfs_bmbt_iroot_alloc(
     843             :         struct xfs_inode        *ip,
     844             :         int                     whichfork)
     845             : {
     846     3746201 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     847             : 
     848     3746196 :         xfs_iroot_alloc(ip, whichfork,
     849             :                         xfs_bmap_broot_space_calc(ip->i_mount, 1, 1));
     850             : 
     851             :         /* Fill in the root. */
     852     3746204 :         xfs_btree_init_block(ip->i_mount, ifp->if_broot, &xfs_bmbt_ops, 1, 1,
     853             :                         ip->i_ino);
     854     3746196 : }

Generated by: LCOV version 1.14