LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_rtrefcount_btree.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 295 317 93.1 %
Date: 2023-07-31 20:08:34 Functions: 32 35 91.4 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Copyright (C) 2021-2023 Oracle.  All Rights Reserved.
       4             :  * Author: Darrick J. Wong <djwong@kernel.org>
       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_sb.h"
      14             : #include "xfs_mount.h"
      15             : #include "xfs_defer.h"
      16             : #include "xfs_inode.h"
      17             : #include "xfs_trans.h"
      18             : #include "xfs_alloc.h"
      19             : #include "xfs_btree.h"
      20             : #include "xfs_btree_staging.h"
      21             : #include "xfs_rtrefcount_btree.h"
      22             : #include "xfs_refcount.h"
      23             : #include "xfs_trace.h"
      24             : #include "xfs_cksum.h"
      25             : #include "xfs_error.h"
      26             : #include "xfs_extent_busy.h"
      27             : #include "xfs_rtgroup.h"
      28             : #include "xfs_rtbitmap.h"
      29             : #include "xfs_imeta.h"
      30             : #include "xfs_health.h"
      31             : 
      32             : static struct kmem_cache        *xfs_rtrefcountbt_cur_cache;
      33             : 
      34             : /*
      35             :  * Realtime Reference Count btree.
      36             :  *
      37             :  * This is a btree used to track the owner(s) of a given extent in the realtime
      38             :  * device.  See the comments in xfs_refcount_btree.c for more information.
      39             :  *
      40             :  * This tree is basically the same as the regular refcount btree except that
      41             :  * it's rooted in an inode.
      42             :  */
      43             : 
      44             : static struct xfs_btree_cur *
      45     2789444 : xfs_rtrefcountbt_dup_cursor(
      46             :         struct xfs_btree_cur    *cur)
      47             : {
      48     2789444 :         struct xfs_btree_cur    *new;
      49             : 
      50     2789444 :         new = xfs_rtrefcountbt_init_cursor(cur->bc_mp, cur->bc_tp,
      51             :                         cur->bc_ino.rtg, cur->bc_ino.ip);
      52             : 
      53             :         /* Copy the flags values since init cursor doesn't get them. */
      54     2789460 :         new->bc_ino.flags = cur->bc_ino.flags;
      55             : 
      56     2789460 :         return new;
      57             : }
      58             : 
      59             : STATIC int
      60    21593988 : xfs_rtrefcountbt_get_minrecs(
      61             :         struct xfs_btree_cur    *cur,
      62             :         int                     level)
      63             : {
      64    21593988 :         if (level == cur->bc_nlevels - 1) {
      65      168037 :                 struct xfs_ifork        *ifp = xfs_btree_ifork_ptr(cur);
      66             : 
      67      168040 :                 return xfs_rtrefcountbt_maxrecs(cur->bc_mp, ifp->if_broot_bytes,
      68      168040 :                                 level == 0) / 2;
      69             :         }
      70             : 
      71    21425951 :         return cur->bc_mp->m_rtrefc_mnr[level != 0];
      72             : }
      73             : 
      74             : STATIC int
      75  4874221069 : xfs_rtrefcountbt_get_maxrecs(
      76             :         struct xfs_btree_cur    *cur,
      77             :         int                     level)
      78             : {
      79  4874221069 :         if (level == cur->bc_nlevels - 1) {
      80  1413932833 :                 struct xfs_ifork        *ifp = xfs_btree_ifork_ptr(cur);
      81             : 
      82  1413556515 :                 return xfs_rtrefcountbt_maxrecs(cur->bc_mp, ifp->if_broot_bytes,
      83             :                                 level == 0);
      84             :         }
      85             : 
      86  3460288236 :         return cur->bc_mp->m_rtrefc_mxr[level != 0];
      87             : }
      88             : 
      89             : /*
      90             :  * Calculate number of records in a realtime refcount btree inode root.
      91             :  */
      92             : unsigned int
      93           0 : xfs_rtrefcountbt_droot_maxrecs(
      94             :         unsigned int            blocklen,
      95             :         bool                    leaf)
      96             : {
      97     4012368 :         blocklen -= sizeof(struct xfs_rtrefcount_root);
      98             : 
      99           0 :         if (leaf)
     100     3308993 :                 return blocklen / sizeof(struct xfs_refcount_rec);
     101      678482 :         return blocklen / (2 * sizeof(struct xfs_refcount_key) +
     102             :                         sizeof(xfs_rtrefcount_ptr_t));
     103             : }
     104             : 
     105             : /*
     106             :  * Get the maximum records we could store in the on-disk format.
     107             :  *
     108             :  * For non-root nodes this is equivalent to xfs_rtrefcountbt_get_maxrecs, but
     109             :  * for the root node this checks the available space in the dinode fork so that
     110             :  * we can resize the in-memory buffer to match it.  After a resize to the
     111             :  * maximum size this function returns the same value as
     112             :  * xfs_rtrefcountbt_get_maxrecs for the root node, too.
     113             :  */
     114             : STATIC int
     115     4010553 : xfs_rtrefcountbt_get_dmaxrecs(
     116             :         struct xfs_btree_cur    *cur,
     117             :         int                     level)
     118             : {
     119     4010553 :         if (level != cur->bc_nlevels - 1)
     120       23078 :                 return cur->bc_mp->m_rtrefc_mxr[level != 0];
     121     7974950 :         return xfs_rtrefcountbt_droot_maxrecs(cur->bc_ino.forksize, level == 0);
     122             : }
     123             : 
     124             : STATIC void
     125 12382583719 : xfs_rtrefcountbt_init_key_from_rec(
     126             :         union xfs_btree_key             *key,
     127             :         const union xfs_btree_rec       *rec)
     128             : {
     129 12382583719 :         key->refc.rc_startblock = rec->refc.rc_startblock;
     130 12382583719 : }
     131             : 
     132             : STATIC void
     133   205769858 : xfs_rtrefcountbt_init_high_key_from_rec(
     134             :         union xfs_btree_key             *key,
     135             :         const union xfs_btree_rec       *rec)
     136             : {
     137   205769858 :         __u32                           x;
     138             : 
     139   205769858 :         x = be32_to_cpu(rec->refc.rc_startblock);
     140   205769858 :         x += be32_to_cpu(rec->refc.rc_blockcount) - 1;
     141   205769858 :         key->refc.rc_startblock = cpu_to_be32(x);
     142   205769858 : }
     143             : 
     144             : STATIC void
     145  1107243141 : xfs_rtrefcountbt_init_rec_from_cur(
     146             :         struct xfs_btree_cur    *cur,
     147             :         union xfs_btree_rec     *rec)
     148             : {
     149  1107243141 :         const struct xfs_refcount_irec *irec = &cur->bc_rec.rc;
     150  1107243141 :         uint32_t                start;
     151             : 
     152  1107243141 :         start = xfs_refcount_encode_startblock(irec->rc_startblock,
     153  1107243141 :                         irec->rc_domain);
     154  1107243141 :         rec->refc.rc_startblock = cpu_to_be32(start);
     155  1107243141 :         rec->refc.rc_blockcount = cpu_to_be32(cur->bc_rec.rc.rc_blockcount);
     156  1107243141 :         rec->refc.rc_refcount = cpu_to_be32(cur->bc_rec.rc.rc_refcount);
     157  1107243141 : }
     158             : 
     159             : STATIC void
     160  1780113068 : xfs_rtrefcountbt_init_ptr_from_cur(
     161             :         struct xfs_btree_cur    *cur,
     162             :         union xfs_btree_ptr     *ptr)
     163             : {
     164  1780113068 :         ptr->l = 0;
     165  1780113068 : }
     166             : 
     167             : STATIC int64_t
     168 15823309800 : xfs_rtrefcountbt_key_diff(
     169             :         struct xfs_btree_cur            *cur,
     170             :         const union xfs_btree_key       *key)
     171             : {
     172 15823309800 :         const struct xfs_refcount_key   *kp = &key->refc;
     173 15823309800 :         const struct xfs_refcount_irec  *irec = &cur->bc_rec.rc;
     174 15823309800 :         uint32_t                        start;
     175             : 
     176 15823309800 :         start = xfs_refcount_encode_startblock(irec->rc_startblock,
     177 15823309800 :                         irec->rc_domain);
     178 15823309800 :         return (int64_t)be32_to_cpu(kp->rc_startblock) - start;
     179             : }
     180             : 
     181             : STATIC int64_t
     182   592641212 : xfs_rtrefcountbt_diff_two_keys(
     183             :         struct xfs_btree_cur            *cur,
     184             :         const union xfs_btree_key       *k1,
     185             :         const union xfs_btree_key       *k2,
     186             :         const union xfs_btree_key       *mask)
     187             : {
     188   592641212 :         ASSERT(!mask || mask->refc.rc_startblock);
     189             : 
     190   592641212 :         return (int64_t)be32_to_cpu(k1->refc.rc_startblock) -
     191   592641212 :                         be32_to_cpu(k2->refc.rc_startblock);
     192             : }
     193             : 
     194             : static xfs_failaddr_t
     195      633098 : xfs_rtrefcountbt_verify(
     196             :         struct xfs_buf          *bp)
     197             : {
     198      633098 :         struct xfs_mount        *mp = bp->b_target->bt_mount;
     199      633098 :         struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
     200      633098 :         xfs_failaddr_t          fa;
     201      633098 :         int                     level;
     202             : 
     203      633098 :         if (!xfs_verify_magic(bp, block->bb_magic))
     204           0 :                 return __this_address;
     205             : 
     206      633098 :         if (!xfs_has_reflink(mp))
     207           0 :                 return __this_address;
     208      633098 :         fa = xfs_btree_lblock_v5hdr_verify(bp, XFS_RMAP_OWN_UNKNOWN);
     209      633098 :         if (fa)
     210             :                 return fa;
     211      633098 :         level = be16_to_cpu(block->bb_level);
     212      633098 :         if (level > mp->m_rtrefc_maxlevels)
     213           0 :                 return __this_address;
     214             : 
     215      633098 :         return xfs_btree_lblock_verify(bp, mp->m_rtrefc_mxr[level != 0]);
     216             : }
     217             : 
     218             : static void
     219       12041 : xfs_rtrefcountbt_read_verify(
     220             :         struct xfs_buf  *bp)
     221             : {
     222       12041 :         xfs_failaddr_t  fa;
     223             : 
     224       12041 :         if (!xfs_btree_lblock_verify_crc(bp))
     225           0 :                 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
     226             :         else {
     227       12041 :                 fa = xfs_rtrefcountbt_verify(bp);
     228       12041 :                 if (fa)
     229           0 :                         xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     230             :         }
     231             : 
     232       12041 :         if (bp->b_error)
     233           0 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     234       12041 : }
     235             : 
     236             : static void
     237      261969 : xfs_rtrefcountbt_write_verify(
     238             :         struct xfs_buf  *bp)
     239             : {
     240      261969 :         xfs_failaddr_t  fa;
     241             : 
     242      261969 :         fa = xfs_rtrefcountbt_verify(bp);
     243      261969 :         if (fa) {
     244           0 :                 trace_xfs_btree_corrupt(bp, _RET_IP_);
     245           0 :                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
     246           0 :                 return;
     247             :         }
     248      261969 :         xfs_btree_lblock_calc_crc(bp);
     249             : 
     250             : }
     251             : 
     252             : const struct xfs_buf_ops xfs_rtrefcountbt_buf_ops = {
     253             :         .name                   = "xfs_rtrefcountbt",
     254             :         .magic                  = { 0, cpu_to_be32(XFS_RTREFC_CRC_MAGIC) },
     255             :         .verify_read            = xfs_rtrefcountbt_read_verify,
     256             :         .verify_write           = xfs_rtrefcountbt_write_verify,
     257             :         .verify_struct          = xfs_rtrefcountbt_verify,
     258             : };
     259             : 
     260             : STATIC int
     261      198647 : xfs_rtrefcountbt_keys_inorder(
     262             :         struct xfs_btree_cur            *cur,
     263             :         const union xfs_btree_key       *k1,
     264             :         const union xfs_btree_key       *k2)
     265             : {
     266      198647 :         return be32_to_cpu(k1->refc.rc_startblock) <
     267      198647 :                be32_to_cpu(k2->refc.rc_startblock);
     268             : }
     269             : 
     270             : STATIC int
     271   108957450 : xfs_rtrefcountbt_recs_inorder(
     272             :         struct xfs_btree_cur            *cur,
     273             :         const union xfs_btree_rec       *r1,
     274             :         const union xfs_btree_rec       *r2)
     275             : {
     276   108957450 :         return  be32_to_cpu(r1->refc.rc_startblock) +
     277   108957450 :                 be32_to_cpu(r1->refc.rc_blockcount) <=
     278   108957450 :                 be32_to_cpu(r2->refc.rc_startblock);
     279             : }
     280             : 
     281             : STATIC enum xbtree_key_contig
     282           0 : xfs_rtrefcountbt_keys_contiguous(
     283             :         struct xfs_btree_cur            *cur,
     284             :         const union xfs_btree_key       *key1,
     285             :         const union xfs_btree_key       *key2,
     286             :         const union xfs_btree_key       *mask)
     287             : {
     288           0 :         ASSERT(!mask || mask->refc.rc_startblock);
     289             : 
     290           0 :         return xbtree_key_contig(be32_to_cpu(key1->refc.rc_startblock),
     291           0 :                                  be32_to_cpu(key2->refc.rc_startblock));
     292             : }
     293             : 
     294             : /* Move the rt refcount btree root from one incore buffer to another. */
     295             : static void
     296     6370422 : xfs_rtrefcountbt_broot_move(
     297             :         struct xfs_inode        *ip,
     298             :         int                     whichfork,
     299             :         struct xfs_btree_block  *dst_broot,
     300             :         size_t                  dst_bytes,
     301             :         struct xfs_btree_block  *src_broot,
     302             :         size_t                  src_bytes,
     303             :         unsigned int            level,
     304             :         unsigned int            numrecs)
     305             : {
     306     6370422 :         struct xfs_mount        *mp = ip->i_mount;
     307     6370422 :         void                    *dptr;
     308     6370422 :         void                    *sptr;
     309             : 
     310    12740844 :         ASSERT(xfs_rtrefcount_droot_space(src_broot) <=
     311             :                         xfs_inode_fork_size(ip, whichfork));
     312             : 
     313             :         /*
     314             :          * We always have to move the pointers because they are not butted
     315             :          * against the btree block header.
     316             :          */
     317     6370422 :         if (numrecs && level > 0) {
     318        4648 :                 sptr = xfs_rtrefcount_broot_ptr_addr(mp, src_broot, 1,
     319             :                                 src_bytes);
     320        4648 :                 dptr = xfs_rtrefcount_broot_ptr_addr(mp, dst_broot, 1,
     321             :                                 dst_bytes);
     322        9296 :                 memmove(dptr, sptr, numrecs * sizeof(xfs_fsblock_t));
     323             :         }
     324             : 
     325     6370422 :         if (src_broot == dst_broot)
     326             :                 return;
     327             : 
     328             :         /*
     329             :          * If the root is being totally relocated, we have to migrate the block
     330             :          * header and the keys/records that come after it.
     331             :          */
     332     6316252 :         memcpy(dst_broot, src_broot, XFS_RTREFCOUNT_BLOCK_LEN);
     333             : 
     334     3158126 :         if (!numrecs)
     335             :                 return;
     336             : 
     337     3005729 :         if (level == 0) {
     338     3004148 :                 sptr = xfs_rtrefcount_rec_addr(src_broot, 1);
     339     3004148 :                 dptr = xfs_rtrefcount_rec_addr(dst_broot, 1);
     340     6008296 :                 memcpy(dptr, sptr,
     341             :                                 numrecs * sizeof(struct xfs_refcount_rec));
     342             :         } else {
     343        1581 :                 sptr = xfs_rtrefcount_key_addr(src_broot, 1);
     344        1581 :                 dptr = xfs_rtrefcount_key_addr(dst_broot, 1);
     345        3162 :                 memcpy(dptr, sptr,
     346             :                                 numrecs * sizeof(struct xfs_refcount_key));
     347             :         }
     348             : }
     349             : 
     350             : static const struct xfs_ifork_broot_ops xfs_rtrefcountbt_iroot_ops = {
     351             :         .maxrecs                = xfs_rtrefcountbt_maxrecs,
     352             :         .size                   = xfs_rtrefcount_broot_space_calc,
     353             :         .move                   = xfs_rtrefcountbt_broot_move,
     354             : };
     355             : 
     356             : const struct xfs_btree_ops xfs_rtrefcountbt_ops = {
     357             :         .rec_len                = sizeof(struct xfs_refcount_rec),
     358             :         .key_len                = sizeof(struct xfs_refcount_key),
     359             :         .lru_refs               = XFS_REFC_BTREE_REF,
     360             :         .geom_flags             = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE |
     361             :                                   XFS_BTREE_CRC_BLOCKS | XFS_BTREE_IROOT_RECORDS,
     362             : 
     363             :         .dup_cursor             = xfs_rtrefcountbt_dup_cursor,
     364             :         .alloc_block            = xfs_btree_alloc_imeta_block,
     365             :         .free_block             = xfs_btree_free_imeta_block,
     366             :         .get_minrecs            = xfs_rtrefcountbt_get_minrecs,
     367             :         .get_maxrecs            = xfs_rtrefcountbt_get_maxrecs,
     368             :         .get_dmaxrecs           = xfs_rtrefcountbt_get_dmaxrecs,
     369             :         .init_key_from_rec      = xfs_rtrefcountbt_init_key_from_rec,
     370             :         .init_high_key_from_rec = xfs_rtrefcountbt_init_high_key_from_rec,
     371             :         .init_rec_from_cur      = xfs_rtrefcountbt_init_rec_from_cur,
     372             :         .init_ptr_from_cur      = xfs_rtrefcountbt_init_ptr_from_cur,
     373             :         .key_diff               = xfs_rtrefcountbt_key_diff,
     374             :         .buf_ops                = &xfs_rtrefcountbt_buf_ops,
     375             :         .diff_two_keys          = xfs_rtrefcountbt_diff_two_keys,
     376             :         .keys_inorder           = xfs_rtrefcountbt_keys_inorder,
     377             :         .recs_inorder           = xfs_rtrefcountbt_recs_inorder,
     378             :         .keys_contiguous        = xfs_rtrefcountbt_keys_contiguous,
     379             :         .iroot_ops              = &xfs_rtrefcountbt_iroot_ops,
     380             : };
     381             : 
     382             : /* Initialize a new rt refcount btree cursor. */
     383             : static struct xfs_btree_cur *
     384   491855395 : xfs_rtrefcountbt_init_common(
     385             :         struct xfs_mount        *mp,
     386             :         struct xfs_trans        *tp,
     387             :         struct xfs_rtgroup      *rtg,
     388             :         struct xfs_inode        *ip)
     389             : {
     390   491855395 :         struct xfs_btree_cur    *cur;
     391             : 
     392   491855395 :         ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
     393             : 
     394   487273109 :         cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_RTREFC,
     395   487273109 :                         &xfs_rtrefcountbt_ops, mp->m_rtrefc_maxlevels,
     396             :                         xfs_rtrefcountbt_cur_cache);
     397   492458642 :         cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_refcbt_2);
     398             : 
     399   492458642 :         cur->bc_ino.ip = ip;
     400   492458642 :         cur->bc_ino.allocated = 0;
     401   492458642 :         cur->bc_ino.flags = 0;
     402   492458642 :         cur->bc_ino.refc.nr_ops = 0;
     403   492458642 :         cur->bc_ino.refc.shape_changes = 0;
     404             : 
     405   492458642 :         cur->bc_ino.rtg = xfs_rtgroup_hold(rtg);
     406   493800313 :         return cur;
     407             : }
     408             : 
     409             : /* Allocate a new rt refcount btree cursor. */
     410             : struct xfs_btree_cur *
     411   492425599 : xfs_rtrefcountbt_init_cursor(
     412             :         struct xfs_mount        *mp,
     413             :         struct xfs_trans        *tp,
     414             :         struct xfs_rtgroup      *rtg,
     415             :         struct xfs_inode        *ip)
     416             : {
     417   492425599 :         struct xfs_btree_cur    *cur;
     418   492425599 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
     419             : 
     420   492425599 :         cur = xfs_rtrefcountbt_init_common(mp, tp, rtg, ip);
     421   494639166 :         cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
     422   494639166 :         cur->bc_ino.forksize = xfs_inode_fork_size(ip, XFS_DATA_FORK);
     423   494639166 :         cur->bc_ino.whichfork = XFS_DATA_FORK;
     424   494639166 :         return cur;
     425             : }
     426             : 
     427             : /* Create a new rt reverse mapping btree cursor with a fake root for staging. */
     428             : struct xfs_btree_cur *
     429       28374 : xfs_rtrefcountbt_stage_cursor(
     430             :         struct xfs_mount        *mp,
     431             :         struct xfs_rtgroup      *rtg,
     432             :         struct xfs_inode        *ip,
     433             :         struct xbtree_ifakeroot *ifake)
     434             : {
     435       28374 :         struct xfs_btree_cur    *cur;
     436             : 
     437       28374 :         cur = xfs_rtrefcountbt_init_common(mp, NULL, rtg, ip);
     438       28377 :         cur->bc_nlevels = ifake->if_levels;
     439       28377 :         cur->bc_ino.forksize = ifake->if_fork_size;
     440       28377 :         cur->bc_ino.whichfork = -1;
     441       28377 :         xfs_btree_stage_ifakeroot(cur, ifake, NULL);
     442       28357 :         return cur;
     443             : }
     444             : 
     445             : /*
     446             :  * Install a new rt reverse mapping btree root.  Caller is responsible for
     447             :  * invalidating and freeing the old btree blocks.
     448             :  */
     449             : void
     450       28340 : xfs_rtrefcountbt_commit_staged_btree(
     451             :         struct xfs_btree_cur    *cur,
     452             :         struct xfs_trans        *tp)
     453             : {
     454       28340 :         struct xbtree_ifakeroot *ifake = cur->bc_ino.ifake;
     455       28340 :         struct xfs_ifork        *ifp;
     456       28340 :         int                     flags = XFS_ILOG_CORE | XFS_ILOG_DBROOT;
     457             : 
     458       28340 :         ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
     459       28340 :         ASSERT(ifake->if_fork->if_format == XFS_DINODE_FMT_REFCOUNT);
     460             : 
     461             :         /*
     462             :          * Free any resources hanging off the real fork, then shallow-copy the
     463             :          * staging fork's contents into the real fork to transfer everything
     464             :          * we just built.
     465             :          */
     466       28340 :         ifp = xfs_ifork_ptr(cur->bc_ino.ip, XFS_DATA_FORK);
     467       28340 :         xfs_idestroy_fork(ifp);
     468       56726 :         memcpy(ifp, ifake->if_fork, sizeof(struct xfs_ifork));
     469             : 
     470       28363 :         xfs_trans_log_inode(tp, cur->bc_ino.ip, flags);
     471       28372 :         xfs_btree_commit_ifakeroot(cur, tp, XFS_DATA_FORK,
     472             :                         &xfs_rtrefcountbt_ops);
     473       28365 : }
     474             : 
     475             : /* Calculate number of records in a realtime refcount btree block. */
     476             : static inline unsigned int
     477             : xfs_rtrefcountbt_block_maxrecs(
     478             :         unsigned int            blocklen,
     479             :         bool                    leaf)
     480             : {
     481             : 
     482  1420258482 :         if (leaf)
     483     9838420 :                 return blocklen / sizeof(struct xfs_refcount_rec);
     484  1410390521 :         return blocklen / (sizeof(struct xfs_refcount_key) +
     485             :                            sizeof(xfs_rtrefcount_ptr_t));
     486             : }
     487             : 
     488             : /*
     489             :  * Calculate number of records in an refcount btree block.
     490             :  */
     491             : unsigned int
     492     6504386 : xfs_rtrefcountbt_maxrecs(
     493             :         struct xfs_mount        *mp,
     494             :         unsigned int            blocklen,
     495             :         bool                    leaf)
     496             : {
     497  1420258482 :         blocklen -= XFS_RTREFCOUNT_BLOCK_LEN;
     498  1420258482 :         return xfs_rtrefcountbt_block_maxrecs(blocklen, leaf);
     499             : }
     500             : 
     501             : /* Compute the max possible height for realtime refcount btrees. */
     502             : unsigned int
     503          59 : xfs_rtrefcountbt_maxlevels_ondisk(void)
     504             : {
     505          59 :         unsigned int            minrecs[2];
     506          59 :         unsigned int            blocklen;
     507             : 
     508          59 :         blocklen = XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_LBLOCK_CRC_LEN;
     509             : 
     510          59 :         minrecs[0] = xfs_rtrefcountbt_block_maxrecs(blocklen, true) / 2;
     511          59 :         minrecs[1] = xfs_rtrefcountbt_block_maxrecs(blocklen, false) / 2;
     512             : 
     513             :         /* We need at most one record for every block in an rt group. */
     514          59 :         return xfs_btree_compute_maxlevels(minrecs, XFS_MAX_RGBLOCKS);
     515             : }
     516             : 
     517             : int __init
     518          59 : xfs_rtrefcountbt_init_cur_cache(void)
     519             : {
     520          59 :         xfs_rtrefcountbt_cur_cache = kmem_cache_create("xfs_rtrefcountbt_cur",
     521          59 :                         xfs_btree_cur_sizeof(
     522             :                                         xfs_rtrefcountbt_maxlevels_ondisk()),
     523             :                         0, 0, NULL);
     524             : 
     525          59 :         if (!xfs_rtrefcountbt_cur_cache)
     526           0 :                 return -ENOMEM;
     527             :         return 0;
     528             : }
     529             : 
     530             : void
     531          58 : xfs_rtrefcountbt_destroy_cur_cache(void)
     532             : {
     533          58 :         kmem_cache_destroy(xfs_rtrefcountbt_cur_cache);
     534          58 :         xfs_rtrefcountbt_cur_cache = NULL;
     535          58 : }
     536             : 
     537             : /* Compute the maximum height of a realtime refcount btree. */
     538             : void
     539       70799 : xfs_rtrefcountbt_compute_maxlevels(
     540             :         struct xfs_mount        *mp)
     541             : {
     542       70799 :         unsigned int            d_maxlevels, r_maxlevels;
     543             : 
     544       70799 :         if (!xfs_has_rtreflink(mp)) {
     545       50044 :                 mp->m_rtrefc_maxlevels = 0;
     546       50044 :                 return;
     547             :         }
     548             : 
     549             :         /*
     550             :          * The realtime refcountbt lives on the data device, which means that
     551             :          * its maximum height is constrained by the size of the data device and
     552             :          * the height required to store one refcount record for each rtextent
     553             :          * in an rt group.
     554             :          */
     555       20755 :         d_maxlevels = xfs_btree_space_to_height(mp->m_rtrefc_mnr,
     556             :                                 mp->m_sb.sb_dblocks);
     557       20755 :         r_maxlevels = xfs_btree_compute_maxlevels(mp->m_rtrefc_mnr,
     558       20755 :                                 xfs_rtb_to_rtxt(mp, mp->m_sb.sb_rgblocks));
     559             : 
     560             :         /* Add one level to handle the inode root level. */
     561       20755 :         mp->m_rtrefc_maxlevels = min(d_maxlevels, r_maxlevels) + 1;
     562             : }
     563             : 
     564             : #define XFS_RTREFC_NAMELEN              21
     565             : 
     566             : /* Create the metadata directory path for an rtrefcount btree inode. */
     567             : int
     568      100384 : xfs_rtrefcountbt_create_path(
     569             :         struct xfs_mount        *mp,
     570             :         xfs_rgnumber_t          rgno,
     571             :         struct xfs_imeta_path   **pathp)
     572             : {
     573      100384 :         struct xfs_imeta_path   *path;
     574      100384 :         unsigned char           *fname;
     575      100384 :         int                     error;
     576             : 
     577      100384 :         error = xfs_imeta_create_file_path(mp, 2, &path);
     578      100384 :         if (error)
     579             :                 return error;
     580             : 
     581      100384 :         fname = kmalloc(XFS_RTREFC_NAMELEN, GFP_KERNEL);
     582      100384 :         if (!fname) {
     583           0 :                 xfs_imeta_free_path(path);
     584           0 :                 return -ENOMEM;
     585             :         }
     586             : 
     587      100384 :         snprintf(fname, XFS_RTREFC_NAMELEN, "%u.refcount", rgno);
     588      100384 :         path->im_path[0] = "realtime";
     589      100384 :         path->im_path[1] = fname;
     590      100384 :         path->im_dynamicmask = 0x2;
     591      100384 :         *pathp = path;
     592      100384 :         return 0;
     593             : }
     594             : 
     595             : /* Calculate the rtrefcount btree size for some records. */
     596             : unsigned long long
     597           0 : xfs_rtrefcountbt_calc_size(
     598             :         struct xfs_mount        *mp,
     599             :         unsigned long long      len)
     600             : {
     601           0 :         return xfs_btree_calc_size(mp->m_rtrefc_mnr, len);
     602             : }
     603             : 
     604             : /*
     605             :  * Calculate the maximum refcount btree size.
     606             :  */
     607             : static unsigned long long
     608             : xfs_rtrefcountbt_max_size(
     609             :         struct xfs_mount        *mp,
     610             :         xfs_rtblock_t           rtblocks)
     611             : {
     612             :         /* Bail out if we're uninitialized, which can happen in mkfs. */
     613      198055 :         if (mp->m_rtrefc_mxr[0] == 0)
     614             :                 return 0;
     615             : 
     616      198055 :         return xfs_rtrefcountbt_calc_size(mp, rtblocks);
     617             : }
     618             : 
     619             : /*
     620             :  * Figure out how many blocks to reserve and how many are used by this btree.
     621             :  * We need enough space to hold one record for every rt extent in the rtgroup.
     622             :  */
     623             : xfs_filblks_t
     624      198325 : xfs_rtrefcountbt_calc_reserves(
     625             :         struct xfs_mount        *mp)
     626             : {
     627      198325 :         if (!xfs_has_rtreflink(mp))
     628             :                 return 0;
     629             : 
     630      198055 :         return xfs_rtrefcountbt_max_size(mp,
     631      198055 :                         xfs_rtb_to_rtxt(mp, mp->m_sb.sb_rgblocks));
     632             : }
     633             : 
     634             : /*
     635             :  * Convert on-disk form of btree root to in-memory form.
     636             :  */
     637             : STATIC void
     638       97301 : xfs_rtrefcountbt_from_disk(
     639             :         struct xfs_inode                *ip,
     640             :         struct xfs_rtrefcount_root      *dblock,
     641             :         int                             dblocklen,
     642             :         struct xfs_btree_block          *rblock)
     643             : {
     644       97301 :         struct xfs_mount                *mp = ip->i_mount;
     645       97301 :         struct xfs_refcount_key *fkp;
     646       97301 :         __be64                          *fpp;
     647       97301 :         struct xfs_refcount_key *tkp;
     648       97301 :         __be64                          *tpp;
     649       97301 :         struct xfs_refcount_rec *frp;
     650       97301 :         struct xfs_refcount_rec *trp;
     651       97301 :         unsigned int                    numrecs;
     652       97301 :         unsigned int                    maxrecs;
     653       97301 :         unsigned int                    rblocklen;
     654             : 
     655       97301 :         rblocklen = xfs_rtrefcount_broot_space(mp, dblock);
     656             : 
     657       97301 :         xfs_btree_init_block(mp, rblock, &xfs_rtrefcountbt_ops, 0, 0,
     658             :                         ip->i_ino);
     659             : 
     660       97301 :         rblock->bb_level = dblock->bb_level;
     661       97301 :         rblock->bb_numrecs = dblock->bb_numrecs;
     662             : 
     663       97301 :         if (be16_to_cpu(rblock->bb_level) > 0) {
     664        1601 :                 maxrecs = xfs_rtrefcountbt_droot_maxrecs(dblocklen, false);
     665        1601 :                 fkp = xfs_rtrefcount_droot_key_addr(dblock, 1);
     666        1601 :                 tkp = xfs_rtrefcount_key_addr(rblock, 1);
     667        1601 :                 fpp = xfs_rtrefcount_droot_ptr_addr(dblock, 1, maxrecs);
     668        1601 :                 tpp = xfs_rtrefcount_broot_ptr_addr(mp, rblock, 1, rblocklen);
     669        1601 :                 numrecs = be16_to_cpu(dblock->bb_numrecs);
     670        3202 :                 memcpy(tkp, fkp, 2 * sizeof(*fkp) * numrecs);
     671        3202 :                 memcpy(tpp, fpp, sizeof(*fpp) * numrecs);
     672             :         } else {
     673       95700 :                 frp = xfs_rtrefcount_droot_rec_addr(dblock, 1);
     674       95700 :                 trp = xfs_rtrefcount_rec_addr(rblock, 1);
     675       95700 :                 numrecs = be16_to_cpu(dblock->bb_numrecs);
     676      191400 :                 memcpy(trp, frp, sizeof(*frp) * numrecs);
     677             :         }
     678       97301 : }
     679             : 
     680             : /* Load a realtime reference count btree root in from disk. */
     681             : int
     682       97301 : xfs_iformat_rtrefcount(
     683             :         struct xfs_inode        *ip,
     684             :         struct xfs_dinode       *dip)
     685             : {
     686       97301 :         struct xfs_mount        *mp = ip->i_mount;
     687       97301 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
     688       97301 :         struct xfs_rtrefcount_root *dfp = XFS_DFORK_PTR(dip, XFS_DATA_FORK);
     689       97301 :         unsigned int            numrecs;
     690       97301 :         unsigned int            level;
     691       97301 :         int                     dsize;
     692             : 
     693       97301 :         dsize = XFS_DFORK_SIZE(dip, mp, XFS_DATA_FORK);
     694       97301 :         numrecs = be16_to_cpu(dfp->bb_numrecs);
     695       97301 :         level = be16_to_cpu(dfp->bb_level);
     696             : 
     697       97301 :         if (level > mp->m_rtrefc_maxlevels ||
     698       97301 :             xfs_rtrefcount_droot_space_calc(level, numrecs) > dsize) {
     699           0 :                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
     700           0 :                 return -EFSCORRUPTED;
     701             :         }
     702             : 
     703      194602 :         xfs_iroot_alloc(ip, XFS_DATA_FORK,
     704             :                         xfs_rtrefcount_broot_space_calc(mp, level, numrecs));
     705       97301 :         xfs_rtrefcountbt_from_disk(ip, dfp, dsize, ifp->if_broot);
     706       97301 :         return 0;
     707             : }
     708             : 
     709             : /*
     710             :  * Convert in-memory form of btree root to on-disk form.
     711             :  */
     712             : void
     713       45237 : xfs_rtrefcountbt_to_disk(
     714             :         struct xfs_mount                *mp,
     715             :         struct xfs_btree_block          *rblock,
     716             :         int                             rblocklen,
     717             :         struct xfs_rtrefcount_root      *dblock,
     718             :         int                             dblocklen)
     719             : {
     720       45237 :         struct xfs_refcount_key *fkp;
     721       45237 :         __be64                          *fpp;
     722       45237 :         struct xfs_refcount_key *tkp;
     723       45237 :         __be64                          *tpp;
     724       45237 :         struct xfs_refcount_rec *frp;
     725       45237 :         struct xfs_refcount_rec *trp;
     726       45237 :         unsigned int                    maxrecs;
     727       45237 :         unsigned int                    numrecs;
     728             : 
     729       45237 :         ASSERT(rblock->bb_magic == cpu_to_be32(XFS_RTREFC_CRC_MAGIC));
     730       45237 :         ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid));
     731       45237 :         ASSERT(rblock->bb_u.l.bb_blkno == cpu_to_be64(XFS_BUF_DADDR_NULL));
     732       45237 :         ASSERT(rblock->bb_u.l.bb_leftsib == cpu_to_be64(NULLFSBLOCK));
     733       45237 :         ASSERT(rblock->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK));
     734             : 
     735       45237 :         dblock->bb_level = rblock->bb_level;
     736       45237 :         dblock->bb_numrecs = rblock->bb_numrecs;
     737             : 
     738       45237 :         if (be16_to_cpu(rblock->bb_level) > 0) {
     739       23292 :                 maxrecs = xfs_rtrefcountbt_droot_maxrecs(dblocklen, false);
     740       23292 :                 fkp = xfs_rtrefcount_key_addr(rblock, 1);
     741       23292 :                 tkp = xfs_rtrefcount_droot_key_addr(dblock, 1);
     742       23292 :                 fpp = xfs_rtrefcount_broot_ptr_addr(mp, rblock, 1, rblocklen);
     743       23292 :                 tpp = xfs_rtrefcount_droot_ptr_addr(dblock, 1, maxrecs);
     744       23292 :                 numrecs = be16_to_cpu(rblock->bb_numrecs);
     745       46584 :                 memcpy(tkp, fkp, 2 * sizeof(*fkp) * numrecs);
     746       46584 :                 memcpy(tpp, fpp, sizeof(*fpp) * numrecs);
     747             :         } else {
     748       21945 :                 frp = xfs_rtrefcount_rec_addr(rblock, 1);
     749       21945 :                 trp = xfs_rtrefcount_droot_rec_addr(dblock, 1);
     750       21945 :                 numrecs = be16_to_cpu(rblock->bb_numrecs);
     751       43890 :                 memcpy(trp, frp, sizeof(*frp) * numrecs);
     752             :         }
     753       45237 : }
     754             : 
     755             : /* Flush a realtime reference count btree root out to disk. */
     756             : void
     757       44743 : xfs_iflush_rtrefcount(
     758             :         struct xfs_inode        *ip,
     759             :         struct xfs_dinode       *dip)
     760             : {
     761       44743 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
     762       44743 :         struct xfs_rtrefcount_root *dfp = XFS_DFORK_PTR(dip, XFS_DATA_FORK);
     763             : 
     764       44743 :         ASSERT(ifp->if_broot != NULL);
     765       44743 :         ASSERT(ifp->if_broot_bytes > 0);
     766       89486 :         ASSERT(xfs_rtrefcount_droot_space(ifp->if_broot) <=
     767             :                         xfs_inode_fork_size(ip, XFS_DATA_FORK));
     768      134229 :         xfs_rtrefcountbt_to_disk(ip->i_mount, ifp->if_broot,
     769       44743 :                         ifp->if_broot_bytes, dfp,
     770       44743 :                         XFS_DFORK_SIZE(dip, ip->i_mount, XFS_DATA_FORK));
     771       44743 : }
     772             : 
     773             : /*
     774             :  * Create a realtime refcount btree inode.
     775             :  *
     776             :  * Regardless of the return value, the caller must clean up @upd.  If a new
     777             :  * inode is returned through *ipp, the caller must finish setting up the incore
     778             :  * inode and release it.
     779             :  */
     780             : int
     781        3083 : xfs_rtrefcountbt_create(
     782             :         struct xfs_imeta_update *upd,
     783             :         struct xfs_inode        **ipp)
     784             : {
     785        3083 :         struct xfs_mount        *mp = upd->mp;
     786        3083 :         struct xfs_ifork        *ifp;
     787        3083 :         int                     error;
     788             : 
     789        3083 :         error = xfs_imeta_create(upd, S_IFREG, ipp);
     790        3083 :         if (error)
     791             :                 return error;
     792             : 
     793        3083 :         ifp = xfs_ifork_ptr(upd->ip, XFS_DATA_FORK);
     794        3083 :         ifp->if_format = XFS_DINODE_FMT_REFCOUNT;
     795        3083 :         ASSERT(ifp->if_broot_bytes == 0);
     796        3083 :         ASSERT(ifp->if_bytes == 0);
     797             : 
     798             :         /* Initialize the empty incore btree root. */
     799        3083 :         xfs_iroot_alloc(upd->ip, XFS_DATA_FORK,
     800             :                         xfs_rtrefcount_broot_space_calc(mp, 0, 0));
     801        3083 :         xfs_btree_init_block(mp, ifp->if_broot, &xfs_rtrefcountbt_ops,
     802        3083 :                         0, 0, upd->ip->i_ino);
     803        3083 :         xfs_trans_log_inode(upd->tp, upd->ip, XFS_ILOG_CORE | XFS_ILOG_DBROOT);
     804        3083 :         return 0;
     805             : }

Generated by: LCOV version 1.14