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-xfsa @ Mon Jul 31 20:08:27 PDT 2023 Lines: 296 327 90.5 %
Date: 2023-07-31 20:08:27 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    12629455 : 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    12629455 :         struct xfs_mount        *mp = ip->i_mount;
      41    12629455 :         int                     dmxr;
      42    12629455 :         xfs_bmbt_key_t          *fkp;
      43    12629455 :         __be64                  *fpp;
      44    12629455 :         xfs_bmbt_key_t          *tkp;
      45    12629455 :         __be64                  *tpp;
      46             : 
      47    12629455 :         xfs_btree_init_block(mp, rblock, &xfs_bmbt_ops, 0, 0, ip->i_ino);
      48    12629483 :         rblock->bb_level = dblock->bb_level;
      49    12629483 :         ASSERT(be16_to_cpu(rblock->bb_level) > 0);
      50    12629483 :         rblock->bb_numrecs = dblock->bb_numrecs;
      51    12629483 :         dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
      52    12629483 :         fkp = xfs_bmdr_key_addr(dblock, 1);
      53    12629483 :         tkp = xfs_bmbt_key_addr(mp, rblock, 1);
      54    12629483 :         fpp = xfs_bmdr_ptr_addr(dblock, 1, dmxr);
      55    12629483 :         tpp = xfs_bmap_broot_ptr_addr(mp, rblock, 1, rblocklen);
      56    12629483 :         dmxr = be16_to_cpu(dblock->bb_numrecs);
      57    25258966 :         memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
      58    25258966 :         memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
      59    12629483 : }
      60             : 
      61             : void
      62  2112938118 : xfs_bmbt_disk_get_all(
      63             :         const struct xfs_bmbt_rec *rec,
      64             :         struct xfs_bmbt_irec    *irec)
      65             : {
      66  2112938118 :         uint64_t                l0 = get_unaligned_be64(&rec->l0);
      67             :         uint64_t                l1 = get_unaligned_be64(&rec->l1);
      68             : 
      69  2112938118 :         irec->br_startoff = (l0 & xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
      70  2112938118 :         irec->br_startblock = ((l0 & xfs_mask64lo(9)) << 43) | (l1 >> 21);
      71  2112938118 :         irec->br_blockcount = l1 & xfs_mask64lo(21);
      72  2112938118 :         if (l0 >> (64 - BMBT_EXNTFLAG_BITLEN))
      73   125109191 :                 irec->br_state = XFS_EXT_UNWRITTEN;
      74             :         else
      75  1987828927 :                 irec->br_state = XFS_EXT_NORM;
      76  2112938118 : }
      77             : 
      78             : /*
      79             :  * Extract the blockcount field from an on disk bmap extent record.
      80             :  */
      81             : xfs_filblks_t
      82 >10895*10^7 : xfs_bmbt_disk_get_blockcount(
      83             :         const struct xfs_bmbt_rec       *r)
      84             : {
      85 >10895*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 >22130*10^7 : xfs_bmbt_disk_get_startoff(
      93             :         const struct xfs_bmbt_rec       *r)
      94             : {
      95 >22130*10^7 :         return ((xfs_fileoff_t)be64_to_cpu(r->l0) &
      96 >22130*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  1594234265 : xfs_bmbt_disk_set_all(
     104             :         struct xfs_bmbt_rec     *r,
     105             :         struct xfs_bmbt_irec    *s)
     106             : {
     107  1594234265 :         int                     extent_flag = (s->br_state != XFS_EXT_NORM);
     108             : 
     109  1594234265 :         ASSERT(s->br_state == XFS_EXT_NORM || s->br_state == XFS_EXT_UNWRITTEN);
     110  1594234265 :         ASSERT(!(s->br_startoff & xfs_mask64hi(64-BMBT_STARTOFF_BITLEN)));
     111  1594234265 :         ASSERT(!(s->br_blockcount & xfs_mask64hi(64-BMBT_BLOCKCOUNT_BITLEN)));
     112  1594234265 :         ASSERT(!(s->br_startblock & xfs_mask64hi(64-BMBT_STARTBLOCK_BITLEN)));
     113             : 
     114  1594234265 :         put_unaligned_be64(
     115  1594234265 :                 ((xfs_bmbt_rec_base_t)extent_flag << 63) |
     116  1594234265 :                  ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
     117  1594234265 :                  ((xfs_bmbt_rec_base_t)s->br_startblock >> 43), &r->l0);
     118  1594250407 :         put_unaligned_be64(
     119  1594250407 :                 ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
     120  1594250407 :                  ((xfs_bmbt_rec_base_t)s->br_blockcount &
     121  1594250407 :                   (xfs_bmbt_rec_base_t)xfs_mask64lo(21)), &r->l1);
     122  1594253063 : }
     123             : 
     124             : /*
     125             :  * Convert in-memory form of btree root to on-disk form.
     126             :  */
     127             : void
     128     2208432 : 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     2208432 :         int                     dmxr;
     136     2208432 :         xfs_bmbt_key_t          *fkp;
     137     2208432 :         __be64                  *fpp;
     138     2208432 :         xfs_bmbt_key_t          *tkp;
     139     2208432 :         __be64                  *tpp;
     140             : 
     141     2208432 :         if (xfs_has_crc(mp)) {
     142     2208432 :                 ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC));
     143     2208432 :                 ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid,
     144             :                        &mp->m_sb.sb_meta_uuid));
     145     2208432 :                 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     2208432 :         ASSERT(rblock->bb_u.l.bb_leftsib == cpu_to_be64(NULLFSBLOCK));
     150     2208432 :         ASSERT(rblock->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK));
     151     2208432 :         ASSERT(rblock->bb_level != 0);
     152     2208432 :         dblock->bb_level = rblock->bb_level;
     153     2208432 :         dblock->bb_numrecs = rblock->bb_numrecs;
     154     2208432 :         dmxr = xfs_bmdr_maxrecs(dblocklen, 0);
     155     2208432 :         fkp = xfs_bmbt_key_addr(mp, rblock, 1);
     156     2208432 :         tkp = xfs_bmdr_key_addr(dblock, 1);
     157     2208432 :         fpp = xfs_bmap_broot_ptr_addr(mp, rblock, 1, rblocklen);
     158     2208432 :         tpp = xfs_bmdr_ptr_addr(dblock, 1, dmxr);
     159     2208432 :         dmxr = be16_to_cpu(dblock->bb_numrecs);
     160     4416864 :         memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
     161     4416864 :         memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
     162     2208432 : }
     163             : 
     164             : STATIC struct xfs_btree_cur *
     165    51461595 : xfs_bmbt_dup_cursor(
     166             :         struct xfs_btree_cur    *cur)
     167             : {
     168    51461595 :         struct xfs_btree_cur    *new;
     169             : 
     170    51461595 :         new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp,
     171    51461595 :                         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    51461559 :         new->bc_ino.flags = cur->bc_ino.flags;
     178             : 
     179    51461559 :         return new;
     180             : }
     181             : 
     182             : STATIC void
     183      238860 : xfs_bmbt_update_cursor(
     184             :         struct xfs_btree_cur    *src,
     185             :         struct xfs_btree_cur    *dst)
     186             : {
     187      238860 :         ASSERT((dst->bc_tp->t_highest_agno != NULLAGNUMBER) ||
     188             :                (dst->bc_ino.ip->i_diflags & XFS_DIFLAG_REALTIME));
     189             : 
     190      238860 :         dst->bc_ino.allocated += src->bc_ino.allocated;
     191      238860 :         dst->bc_tp->t_highest_agno = src->bc_tp->t_highest_agno;
     192             : 
     193      238860 :         src->bc_ino.allocated = 0;
     194      238860 : }
     195             : 
     196             : STATIC int
     197      241371 : 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      241371 :         struct xfs_alloc_arg    args;
     204      241371 :         int                     error;
     205             : 
     206      241371 :         memset(&args, 0, sizeof(args));
     207      241371 :         args.tp = cur->bc_tp;
     208      241371 :         args.mp = cur->bc_mp;
     209      241371 :         xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_ino.ip->i_ino,
     210      241371 :                         cur->bc_ino.whichfork);
     211      241371 :         args.minlen = args.maxlen = args.prod = 1;
     212      241371 :         args.wasdel = cur->bc_ino.flags & XFS_BTCUR_BMBT_WASDEL;
     213      241371 :         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      241371 :         if (cur->bc_tp->t_highest_agno == NULLAGNUMBER)
     223      218576 :                 args.minleft = xfs_bmapi_minleft(cur->bc_tp, cur->bc_ino.ip,
     224             :                                         cur->bc_ino.whichfork);
     225             : 
     226      241371 :         error = xfs_alloc_vextent_start_ag(&args, be64_to_cpu(start->l));
     227      241371 :         if (error)
     228             :                 return error;
     229             : 
     230      241366 :         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      241366 :         if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
     243           0 :                 *stat = 0;
     244           0 :                 return 0;
     245             :         }
     246             : 
     247      241366 :         ASSERT(args.len == 1);
     248      241366 :         cur->bc_ino.allocated++;
     249      241366 :         cur->bc_ino.ip->i_nblocks++;
     250      241366 :         xfs_trans_log_inode(args.tp, cur->bc_ino.ip, XFS_ILOG_CORE);
     251      241366 :         xfs_trans_mod_dquot_byino(args.tp, cur->bc_ino.ip,
     252             :                         XFS_TRANS_DQ_BCOUNT, 1L);
     253             : 
     254      241366 :         new->l = cpu_to_be64(args.fsbno);
     255             : 
     256      241366 :         *stat = 1;
     257      241366 :         return 0;
     258             : }
     259             : 
     260             : STATIC int
     261      171844 : xfs_bmbt_free_block(
     262             :         struct xfs_btree_cur    *cur,
     263             :         struct xfs_buf          *bp)
     264             : {
     265      171844 :         struct xfs_mount        *mp = cur->bc_mp;
     266      171844 :         struct xfs_inode        *ip = cur->bc_ino.ip;
     267      171844 :         struct xfs_trans        *tp = cur->bc_tp;
     268      171844 :         xfs_fsblock_t           fsbno = XFS_DADDR_TO_FSB(mp, xfs_buf_daddr(bp));
     269      171844 :         struct xfs_owner_info   oinfo;
     270      171844 :         int                     error;
     271             : 
     272      171844 :         xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_ino.whichfork);
     273      171844 :         error = xfs_free_extent_later(cur->bc_tp, fsbno, 1, &oinfo,
     274             :                         XFS_AG_RESV_NONE, 0);
     275      171844 :         if (error)
     276             :                 return error;
     277             : 
     278      171844 :         ip->i_nblocks--;
     279      171844 :         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
     280      171844 :         xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
     281      171844 :         return 0;
     282             : }
     283             : 
     284             : STATIC int
     285   104197369 : xfs_bmbt_get_minrecs(
     286             :         struct xfs_btree_cur    *cur,
     287             :         int                     level)
     288             : {
     289   104197369 :         if (level == cur->bc_nlevels - 1) {
     290     1421318 :                 struct xfs_ifork        *ifp = xfs_btree_ifork_ptr(cur);
     291             : 
     292     1421320 :                 return xfs_bmbt_maxrecs(cur->bc_mp,
     293     1421320 :                                         ifp->if_broot_bytes, level == 0) / 2;
     294             :         }
     295             : 
     296   102776051 :         return cur->bc_mp->m_bmap_dmnr[level != 0];
     297             : }
     298             : 
     299             : int
     300  1073111671 : xfs_bmbt_get_maxrecs(
     301             :         struct xfs_btree_cur    *cur,
     302             :         int                     level)
     303             : {
     304  1073111671 :         if (level == cur->bc_nlevels - 1) {
     305   205724757 :                 struct xfs_ifork        *ifp = xfs_btree_ifork_ptr(cur);
     306             : 
     307   205726361 :                 return xfs_bmbt_maxrecs(cur->bc_mp,
     308   205726361 :                                         ifp->if_broot_bytes, level == 0);
     309             :         }
     310             : 
     311   867386914 :         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     1806457 : xfs_bmbt_get_dmaxrecs(
     326             :         struct xfs_btree_cur    *cur,
     327             :         int                     level)
     328             : {
     329     1806457 :         if (level != cur->bc_nlevels - 1)
     330       84590 :                 return cur->bc_mp->m_bmap_dmxr[level != 0];
     331     1721867 :         return xfs_bmdr_maxrecs(cur->bc_ino.forksize, level == 0);
     332             : }
     333             : 
     334             : STATIC void
     335  1879191531 : xfs_bmbt_init_key_from_rec(
     336             :         union xfs_btree_key             *key,
     337             :         const union xfs_btree_rec       *rec)
     338             : {
     339  1879191531 :         key->bmbt.br_startoff =
     340  1879191531 :                 cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt));
     341  1879191531 : }
     342             : 
     343             : STATIC void
     344      104421 : xfs_bmbt_init_high_key_from_rec(
     345             :         union xfs_btree_key             *key,
     346             :         const union xfs_btree_rec       *rec)
     347             : {
     348      104421 :         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      104421 : }
     352             : 
     353             : STATIC void
     354   150001434 : xfs_bmbt_init_rec_from_cur(
     355             :         struct xfs_btree_cur    *cur,
     356             :         union xfs_btree_rec     *rec)
     357             : {
     358   150001434 :         xfs_bmbt_disk_set_all(&rec->bmbt, &cur->bc_rec.b);
     359   150001581 : }
     360             : 
     361             : STATIC void
     362   196264398 : xfs_bmbt_init_ptr_from_cur(
     363             :         struct xfs_btree_cur    *cur,
     364             :         union xfs_btree_ptr     *ptr)
     365             : {
     366   196264398 :         ptr->l = 0;
     367   196264398 : }
     368             : 
     369             : STATIC int64_t
     370  2139717078 : xfs_bmbt_key_diff(
     371             :         struct xfs_btree_cur            *cur,
     372             :         const union xfs_btree_key       *key)
     373             : {
     374  2139717078 :         return (int64_t)be64_to_cpu(key->bmbt.br_startoff) -
     375  2139717078 :                                       cur->bc_rec.b.br_startoff;
     376             : }
     377             : 
     378             : STATIC int64_t
     379   505301770 : 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   505301770 :         uint64_t                        a = be64_to_cpu(k1->bmbt.br_startoff);
     386   505301770 :         uint64_t                        b = be64_to_cpu(k2->bmbt.br_startoff);
     387             : 
     388   505301770 :         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   505301770 :         if (a > b)
     397             :                 return 1;
     398    13237485 :         if (b > a)
     399     2349097 :                 return -1;
     400             :         return 0;
     401             : }
     402             : 
     403             : static xfs_failaddr_t
     404    29340887 : xfs_bmbt_verify(
     405             :         struct xfs_buf          *bp)
     406             : {
     407    29340887 :         struct xfs_mount        *mp = bp->b_mount;
     408    29340887 :         struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
     409    29340887 :         xfs_failaddr_t          fa;
     410    29340887 :         unsigned int            level;
     411             : 
     412    29340887 :         if (!xfs_verify_magic(bp, block->bb_magic))
     413           0 :                 return __this_address;
     414             : 
     415    29340958 :         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    29340960 :                 fa = xfs_btree_lblock_v5hdr_verify(bp, XFS_RMAP_OWN_UNKNOWN);
     421    29340970 :                 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    29340970 :         level = be16_to_cpu(block->bb_level);
     433    29340970 :         if (level > max(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1]))
     434           6 :                 return __this_address;
     435             : 
     436    29340966 :         return xfs_btree_lblock_verify(bp, mp->m_bmap_dmxr[level != 0]);
     437             : }
     438             : 
     439             : static void
     440     7732602 : xfs_bmbt_read_verify(
     441             :         struct xfs_buf  *bp)
     442             : {
     443     7732602 :         xfs_failaddr_t  fa;
     444             : 
     445     7732602 :         if (!xfs_btree_lblock_verify_crc(bp))
     446           4 :                 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
     447             :         else {
     448     7732598 :                 fa = xfs_bmbt_verify(bp);
     449     7732598 :                 if (fa)
     450           0 :                         xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     451             :         }
     452             : 
     453     7732602 :         if (bp->b_error)
     454           4 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     455     7732602 : }
     456             : 
     457             : static void
     458    13972582 : xfs_bmbt_write_verify(
     459             :         struct xfs_buf  *bp)
     460             : {
     461    13972582 :         xfs_failaddr_t  fa;
     462             : 
     463    13972582 :         fa = xfs_bmbt_verify(bp);
     464    13972581 :         if (fa) {
     465           0 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     466           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     467           0 :                 return;
     468             :         }
     469    13972581 :         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     2215488 : 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     2215488 :         return be64_to_cpu(k1->bmbt.br_startoff) <
     489     2215488 :                 be64_to_cpu(k2->bmbt.br_startoff);
     490             : }
     491             : 
     492             : STATIC int
     493   576018997 : 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   576018997 :         return xfs_bmbt_disk_get_startoff(&r1->bmbt) +
     499   576018997 :                 xfs_bmbt_disk_get_blockcount(&r1->bmbt) <=
     500   576018997 :                 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       56642 : 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       56642 :         struct xfs_mount        *mp = ip->i_mount;
     529       56642 :         void                    *dptr;
     530       56642 :         void                    *sptr;
     531             : 
     532       56642 :         ASSERT(xfs_bmap_bmdr_space(src_broot) <= xfs_inode_fork_size(ip, whichfork));
     533       56642 :         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       56642 :         if (numrecs) {
     540       56642 :                 sptr = xfs_bmap_broot_ptr_addr(mp, src_broot, 1, src_bytes);
     541       56642 :                 dptr = xfs_bmap_broot_ptr_addr(mp, dst_broot, 1, dst_bytes);
     542      113284 :                 memmove(dptr, sptr, numrecs * sizeof(xfs_fsblock_t));
     543             :         }
     544             : 
     545       56642 :         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       50490 :         memcpy(dst_broot, src_broot, xfs_bmbt_block_len(mp));
     553             : 
     554             :         /* Now copy the keys, which come right after the header. */
     555       25245 :         if (numrecs) {
     556       25245 :                 sptr = xfs_bmbt_key_addr(mp, src_broot, 1);
     557       25245 :                 dptr = xfs_bmbt_key_addr(mp, dst_broot, 1);
     558       50490 :                 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   225128936 : 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   225128936 :         struct xfs_btree_cur    *cur;
     605             : 
     606   225128936 :         ASSERT(whichfork != XFS_COW_FORK);
     607             : 
     608   225128936 :         cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_BMAP, &xfs_bmbt_ops,
     609   225128936 :                         mp->m_bm_maxlevels[whichfork], xfs_bmbt_cur_cache);
     610   225155564 :         cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_bmbt_2);
     611             : 
     612   225155564 :         cur->bc_ino.ip = ip;
     613   225155564 :         cur->bc_ino.allocated = 0;
     614   225155564 :         cur->bc_ino.flags = 0;
     615             : 
     616   225155564 :         return cur;
     617             : }
     618             : 
     619             : /*
     620             :  * Allocate a new bmap btree cursor.
     621             :  */
     622             : struct xfs_btree_cur *                          /* new bmap btree cursor */
     623   224996372 : 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   224996372 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     630   224996245 :         struct xfs_btree_cur    *cur;
     631             : 
     632   224996245 :         cur = xfs_bmbt_init_common(mp, tp, ip, whichfork);
     633             : 
     634   225018422 :         cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
     635   225018422 :         cur->bc_ino.forksize = xfs_inode_fork_size(ip, whichfork);
     636   225018422 :         cur->bc_ino.whichfork = whichfork;
     637             : 
     638   225018422 :         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   524745397 :         if (leaf)
     648       24343 :                 return blocklen / sizeof(xfs_bmbt_rec_t);
     649   509826497 :         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      133368 : xfs_bmbt_stage_cursor(
     660             :         struct xfs_mount        *mp,
     661             :         struct xfs_inode        *ip,
     662             :         struct xbtree_ifakeroot *ifake)
     663             : {
     664      133368 :         struct xfs_btree_cur    *cur;
     665      133368 :         struct xfs_btree_ops    *ops;
     666             : 
     667      133368 :         cur = xfs_bmbt_init_common(mp, NULL, ip, ifake->if_whichfork);
     668      133368 :         cur->bc_nlevels = ifake->if_levels;
     669      133368 :         cur->bc_ino.forksize = ifake->if_fork_size;
     670             :         /* Don't let anyone think we're attached to the real fork yet. */
     671      133368 :         cur->bc_ino.whichfork = -1;
     672      133368 :         xfs_btree_stage_ifakeroot(cur, ifake, &ops);
     673      133368 :         ops->update_cursor = NULL;
     674      133368 :         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      133368 : xfs_bmbt_commit_staged_btree(
     683             :         struct xfs_btree_cur    *cur,
     684             :         struct xfs_trans        *tp,
     685             :         int                     whichfork)
     686             : {
     687      133368 :         struct xbtree_ifakeroot *ifake = cur->bc_ino.ifake;
     688      133368 :         struct xfs_ifork        *ifp;
     689      133368 :         static const short      brootflag[2] =
     690             :                 { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
     691      133368 :         static const short      extflag[2] =
     692             :                 { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
     693      133368 :         int                     flags = XFS_ILOG_CORE;
     694             : 
     695      133368 :         ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
     696      133368 :         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      133368 :         ifp = xfs_ifork_ptr(cur->bc_ino.ip, whichfork);
     704      133368 :         xfs_idestroy_fork(ifp);
     705      266736 :         memcpy(ifp, ifake->if_fork, sizeof(struct xfs_ifork));
     706             : 
     707      133368 :         switch (ifp->if_format) {
     708       98314 :         case XFS_DINODE_FMT_EXTENTS:
     709       98314 :                 flags |= extflag[whichfork];
     710       98314 :                 break;
     711       35054 :         case XFS_DINODE_FMT_BTREE:
     712       35054 :                 flags |= brootflag[whichfork];
     713       35054 :                 break;
     714           0 :         default:
     715           0 :                 ASSERT(0);
     716           0 :                 break;
     717             :         }
     718      133368 :         xfs_trans_log_inode(tp, cur->bc_ino.ip, flags);
     719      133368 :         xfs_btree_commit_ifakeroot(cur, tp, whichfork, &xfs_bmbt_ops);
     720      133368 : }
     721             : 
     722             : /*
     723             :  * Calculate number of records in a bmap btree block.
     724             :  */
     725             : unsigned int
     726   302703159 : xfs_bmbt_maxrecs(
     727             :         struct xfs_mount        *mp,
     728             :         unsigned int            blocklen,
     729             :         bool                    leaf)
     730             : {
     731   509907482 :         blocklen -= xfs_bmbt_block_len(mp);
     732   524745397 :         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       48686 : xfs_bmbt_maxlevels_ondisk(void)
     742             : {
     743       48686 :         unsigned int            minrecs[2];
     744       48686 :         unsigned int            blocklen;
     745             : 
     746       48686 :         blocklen = min(XFS_MIN_BLOCKSIZE - XFS_BTREE_SBLOCK_LEN,
     747             :                        XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN);
     748             : 
     749       48686 :         minrecs[0] = xfs_bmbt_block_maxrecs(blocklen, true) / 2;
     750       48686 :         minrecs[1] = xfs_bmbt_block_maxrecs(blocklen, false) / 2;
     751             : 
     752             :         /* One extra level for the inode root. */
     753       48686 :         return xfs_btree_compute_maxlevels(minrecs,
     754       48686 :                         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       48674 : xfs_bmdr_maxrecs(
     762             :         int                     blocklen,
     763             :         int                     leaf)
     764             : {
     765    16608456 :         blocklen -= sizeof(xfs_bmdr_block_t);
     766             : 
     767     1770541 :         if (leaf)
     768       70108 :                 return blocklen / sizeof(xfs_bmdr_rec_t);
     769    16538348 :         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           0 : 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           0 :         struct xfs_btree_cur    *cur;
     798           0 :         int                     error;
     799             : 
     800           0 :         ASSERT(tp || buffer_list);
     801           0 :         ASSERT(!(tp && buffer_list));
     802           0 :         ASSERT(xfs_ifork_ptr(ip, whichfork)->if_format == XFS_DINODE_FMT_BTREE);
     803             : 
     804           0 :         cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
     805           0 :         cur->bc_ino.flags |= XFS_BTCUR_BMBT_INVALID_OWNER;
     806             : 
     807           0 :         error = xfs_btree_change_owner(cur, new_owner, buffer_list);
     808           0 :         xfs_btree_del_cursor(cur, error);
     809           0 :         return error;
     810             : }
     811             : 
     812             : /* Calculate the bmap btree size for some records. */
     813             : unsigned long long
     814       72876 : xfs_bmbt_calc_size(
     815             :         struct xfs_mount        *mp,
     816             :         unsigned long long      len)
     817             : {
     818       72876 :         return xfs_btree_calc_size(mp->m_bmap_dmnr, len);
     819             : }
     820             : 
     821             : int __init
     822          12 : xfs_bmbt_init_cur_cache(void)
     823             : {
     824          12 :         xfs_bmbt_cur_cache = kmem_cache_create("xfs_bmbt_cur",
     825          12 :                         xfs_btree_cur_sizeof(xfs_bmbt_maxlevels_ondisk()),
     826             :                         0, 0, NULL);
     827             : 
     828          12 :         if (!xfs_bmbt_cur_cache)
     829           0 :                 return -ENOMEM;
     830             :         return 0;
     831             : }
     832             : 
     833             : void
     834          12 : xfs_bmbt_destroy_cur_cache(void)
     835             : {
     836          12 :         kmem_cache_destroy(xfs_bmbt_cur_cache);
     837          12 :         xfs_bmbt_cur_cache = NULL;
     838          12 : }
     839             : 
     840             : /* Create an incore bmbt btree root block. */
     841             : void
     842     1566493 : xfs_bmbt_iroot_alloc(
     843             :         struct xfs_inode        *ip,
     844             :         int                     whichfork)
     845             : {
     846     1566493 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
     847             : 
     848     1566493 :         xfs_iroot_alloc(ip, whichfork,
     849             :                         xfs_bmap_broot_space_calc(ip->i_mount, 1, 1));
     850             : 
     851             :         /* Fill in the root. */
     852     1566493 :         xfs_btree_init_block(ip->i_mount, ifp->if_broot, &xfs_bmbt_ops, 1, 1,
     853             :                         ip->i_ino);
     854     1566493 : }

Generated by: LCOV version 1.14