LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_bmap_btree.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 241 277 87.0 %
Date: 2023-07-31 20:08:17 Functions: 29 33 87.9 %

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

Generated by: LCOV version 1.14