LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_trans_resv.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 330 330 100.0 %
Date: 2023-07-31 20:08:07 Functions: 43 43 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
       4             :  * Copyright (C) 2010 Red Hat, Inc.
       5             :  * All Rights Reserved.
       6             :  */
       7             : #include "xfs.h"
       8             : #include "xfs_fs.h"
       9             : #include "xfs_shared.h"
      10             : #include "xfs_format.h"
      11             : #include "xfs_log_format.h"
      12             : #include "xfs_trans_resv.h"
      13             : #include "xfs_mount.h"
      14             : #include "xfs_da_format.h"
      15             : #include "xfs_da_btree.h"
      16             : #include "xfs_inode.h"
      17             : #include "xfs_bmap_btree.h"
      18             : #include "xfs_quota.h"
      19             : #include "xfs_trans.h"
      20             : #include "xfs_qm.h"
      21             : #include "xfs_trans_space.h"
      22             : #include "xfs_attr_item.h"
      23             : #include "xfs_log.h"
      24             : #include "xfs_da_format.h"
      25             : 
      26             : #define _ALLOC  true
      27             : #define _FREE   false
      28             : 
      29             : /*
      30             :  * A buffer has a format structure overhead in the log in addition
      31             :  * to the data, so we need to take this into account when reserving
      32             :  * space in a transaction for a buffer.  Round the space required up
      33             :  * to a multiple of 128 bytes so that we don't change the historical
      34             :  * reservation that has been used for this overhead.
      35             :  */
      36             : STATIC uint
      37     4974052 : xfs_buf_log_overhead(void)
      38             : {
      39     4974052 :         return round_up(sizeof(struct xlog_op_header) +
      40             :                         sizeof(struct xfs_buf_log_format), 128);
      41             : }
      42             : 
      43             : /*
      44             :  * Calculate out transaction log reservation per item in bytes.
      45             :  *
      46             :  * The nbufs argument is used to indicate the number of items that
      47             :  * will be changed in a transaction.  size is used to tell how many
      48             :  * bytes should be reserved per item.
      49             :  */
      50             : STATIC uint
      51     4974052 : xfs_calc_buf_res(
      52             :         uint            nbufs,
      53             :         uint            size)
      54             : {
      55     4974052 :         return nbufs * (size + xfs_buf_log_overhead());
      56             : }
      57             : 
      58             : /*
      59             :  * Per-extent log reservation for the btree changes involved in freeing or
      60             :  * allocating an extent.  In classic XFS there were two trees that will be
      61             :  * modified (bnobt + cntbt).  With rmap enabled, there are three trees
      62             :  * (rmapbt).  The number of blocks reserved is based on the formula:
      63             :  *
      64             :  * num trees * ((2 blocks/level * max depth) - 1)
      65             :  *
      66             :  * Keep in mind that max depth is calculated separately for each type of tree.
      67             :  */
      68             : uint
      69   111979831 : xfs_allocfree_block_count(
      70             :         struct xfs_mount *mp,
      71             :         uint            num_ops)
      72             : {
      73   111979831 :         uint            blocks;
      74             : 
      75   111979831 :         blocks = num_ops * 2 * (2 * mp->m_alloc_maxlevels - 1);
      76   111979831 :         if (xfs_has_rmapbt(mp))
      77   111964730 :                 blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1);
      78             : 
      79   111979831 :         return blocks;
      80             : }
      81             : 
      82             : /*
      83             :  * Per-extent log reservation for refcount btree changes.  These are never done
      84             :  * in the same transaction as an allocation or a free, so we compute them
      85             :  * separately.
      86             :  */
      87             : static unsigned int
      88             : xfs_refcountbt_block_count(
      89             :         struct xfs_mount        *mp,
      90             :         unsigned int            num_ops)
      91             : {
      92      144630 :         return num_ops * (2 * mp->m_refc_maxlevels - 1);
      93             : }
      94             : 
      95             : /*
      96             :  * Logging inodes is really tricksy. They are logged in memory format,
      97             :  * which means that what we write into the log doesn't directly translate into
      98             :  * the amount of space they use on disk.
      99             :  *
     100             :  * Case in point - btree format forks in memory format use more space than the
     101             :  * on-disk format. In memory, the buffer contains a normal btree block header so
     102             :  * the btree code can treat it as though it is just another generic buffer.
     103             :  * However, when we write it to the inode fork, we don't write all of this
     104             :  * header as it isn't needed. e.g. the root is only ever in the inode, so
     105             :  * there's no need for sibling pointers which would waste 16 bytes of space.
     106             :  *
     107             :  * Hence when we have an inode with a maximally sized btree format fork, then
     108             :  * amount of information we actually log is greater than the size of the inode
     109             :  * on disk. Hence we need an inode reservation function that calculates all this
     110             :  * correctly. So, we log:
     111             :  *
     112             :  * - 4 log op headers for object
     113             :  *      - for the ilf, the inode core and 2 forks
     114             :  * - inode log format object
     115             :  * - the inode core
     116             :  * - two inode forks containing bmap btree root blocks.
     117             :  *      - the btree data contained by both forks will fit into the inode size,
     118             :  *        hence when combined with the inode core above, we have a total of the
     119             :  *        actual inode size.
     120             :  *      - the BMBT headers need to be accounted separately, as they are
     121             :  *        additional to the records and pointers that fit inside the inode
     122             :  *        forks.
     123             :  */
     124             : STATIC uint
     125      918026 : xfs_calc_inode_res(
     126             :         struct xfs_mount        *mp,
     127             :         uint                    ninodes)
     128             : {
     129     1836052 :         return ninodes *
     130             :                 (4 * sizeof(struct xlog_op_header) +
     131             :                  sizeof(struct xfs_inode_log_format) +
     132      918026 :                  mp->m_sb.sb_inodesize +
     133      918026 :                  2 * XFS_BMBT_BLOCK_LEN(mp));
     134             : }
     135             : 
     136             : /*
     137             :  * Inode btree record insertion/removal modifies the inode btree and free space
     138             :  * btrees (since the inobt does not use the agfl). This requires the following
     139             :  * reservation:
     140             :  *
     141             :  * the inode btree: max depth * blocksize
     142             :  * the allocation btrees: 2 trees * (max depth - 1) * block size
     143             :  *
     144             :  * The caller must account for SB and AG header modifications, etc.
     145             :  */
     146             : STATIC uint
     147      626222 : xfs_calc_inobt_res(
     148             :         struct xfs_mount        *mp)
     149             : {
     150      626222 :         return xfs_calc_buf_res(M_IGEO(mp)->inobt_maxlevels,
     151      626222 :                         XFS_FSB_TO_B(mp, 1)) +
     152      626222 :                                 xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
     153             :                         XFS_FSB_TO_B(mp, 1));
     154             : }
     155             : 
     156             : /*
     157             :  * The free inode btree is a conditional feature. The behavior differs slightly
     158             :  * from that of the traditional inode btree in that the finobt tracks records
     159             :  * for inode chunks with at least one free inode. A record can be removed from
     160             :  * the tree during individual inode allocation. Therefore the finobt
     161             :  * reservation is unconditional for both the inode chunk allocation and
     162             :  * individual inode allocation (modify) cases.
     163             :  *
     164             :  * Behavior aside, the reservation for finobt modification is equivalent to the
     165             :  * traditional inobt: cover a full finobt shape change plus block allocation.
     166             :  */
     167             : STATIC uint
     168      385840 : xfs_calc_finobt_res(
     169             :         struct xfs_mount        *mp)
     170             : {
     171      385840 :         if (!xfs_has_finobt(mp))
     172             :                 return 0;
     173             : 
     174      385072 :         return xfs_calc_inobt_res(mp);
     175             : }
     176             : 
     177             : /*
     178             :  * Calculate the reservation required to allocate or free an inode chunk. This
     179             :  * includes:
     180             :  *
     181             :  * the allocation btrees: 2 trees * (max depth - 1) * block size
     182             :  * the inode chunk: m_ino_geo.ialloc_blks * N
     183             :  *
     184             :  * The size N of the inode chunk reservation depends on whether it is for
     185             :  * allocation or free and which type of create transaction is in use. An inode
     186             :  * chunk free always invalidates the buffers and only requires reservation for
     187             :  * headers (N == 0). An inode chunk allocation requires a chunk sized
     188             :  * reservation on v4 and older superblocks to initialize the chunk. No chunk
     189             :  * reservation is required for allocation on v5 supers, which use ordered
     190             :  * buffers to initialize.
     191             :  */
     192             : STATIC uint
     193      241150 : xfs_calc_inode_chunk_res(
     194             :         struct xfs_mount        *mp,
     195             :         bool                    alloc)
     196             : {
     197      241150 :         uint                    res, size = 0;
     198             : 
     199      241150 :         res = xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
     200      241150 :                                XFS_FSB_TO_B(mp, 1));
     201      241150 :         if (alloc) {
     202             :                 /* icreate tx uses ordered buffers */
     203      192920 :                 if (xfs_has_v3inodes(mp))
     204             :                         return res;
     205             :                 size = XFS_FSB_TO_B(mp, 1);
     206             :         }
     207             : 
     208       48566 :         res += xfs_calc_buf_res(M_IGEO(mp)->ialloc_blks, size);
     209       48566 :         return res;
     210             : }
     211             : 
     212             : /*
     213             :  * Per-extent log reservation for the btree changes involved in freeing or
     214             :  * allocating a realtime extent.  We have to be able to log as many rtbitmap
     215             :  * blocks as needed to mark inuse XFS_BMBT_MAX_EXTLEN blocks' worth of realtime
     216             :  * extents, as well as the realtime summary block.
     217             :  */
     218             : static unsigned int
     219             : xfs_rtalloc_block_count(
     220             :         struct xfs_mount        *mp,
     221             :         unsigned int            num_ops)
     222             : {
     223        1086 :         unsigned int            blksz = XFS_FSB_TO_B(mp, 1);
     224        1086 :         unsigned int            rtbmp_bytes;
     225             : 
     226        1086 :         rtbmp_bytes = (XFS_MAX_BMBT_EXTLEN / mp->m_sb.sb_rextsize) / NBBY;
     227        1086 :         return (howmany(rtbmp_bytes, blksz) + 1) * num_ops;
     228             : }
     229             : 
     230             : /*
     231             :  * Various log reservation values.
     232             :  *
     233             :  * These are based on the size of the file system block because that is what
     234             :  * most transactions manipulate.  Each adds in an additional 128 bytes per
     235             :  * item logged to try to account for the overhead of the transaction mechanism.
     236             :  *
     237             :  * Note:  Most of the reservations underestimate the number of allocation
     238             :  * groups into which they could free extents in the xfs_defer_finish() call.
     239             :  * This is because the number in the worst case is quite high and quite
     240             :  * unusual.  In order to fix this we need to change xfs_defer_finish() to free
     241             :  * extents in only a single AG at a time.  This will require changes to the
     242             :  * EFI code as well, however, so that the EFI for the extents not freed is
     243             :  * logged again in each transaction.  See SGI PV #261917.
     244             :  *
     245             :  * Reservation functions here avoid a huge stack in xfs_trans_init due to
     246             :  * register overflow from temporaries in the calculations.
     247             :  */
     248             : 
     249             : /*
     250             :  * Compute the log reservation required to handle the refcount update
     251             :  * transaction.  Refcount updates are always done via deferred log items.
     252             :  *
     253             :  * This is calculated as:
     254             :  * Data device refcount updates (t1):
     255             :  *    the agfs of the ags containing the blocks: nr_ops * sector size
     256             :  *    the refcount btrees: nr_ops * 1 trees * (2 * max depth - 1) * block size
     257             :  */
     258             : static unsigned int
     259      144690 : xfs_calc_refcountbt_reservation(
     260             :         struct xfs_mount        *mp,
     261             :         unsigned int            nr_ops)
     262             : {
     263      144690 :         unsigned int            blksz = XFS_FSB_TO_B(mp, 1);
     264             : 
     265      144690 :         if (!xfs_has_reflink(mp))
     266             :                 return 0;
     267             : 
     268      143154 :         return xfs_calc_buf_res(nr_ops, mp->m_sb.sb_sectsize) +
     269      143154 :                xfs_calc_buf_res(xfs_refcountbt_block_count(mp, nr_ops), blksz);
     270             : }
     271             : 
     272             : /*
     273             :  * In a write transaction we can allocate a maximum of 2
     274             :  * extents.  This gives (t1):
     275             :  *    the inode getting the new extents: inode size
     276             :  *    the inode's bmap btree: max depth * block size
     277             :  *    the agfs of the ags from which the extents are allocated: 2 * sector
     278             :  *    the superblock free block counter: sector size
     279             :  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
     280             :  * Or, if we're writing to a realtime file (t2):
     281             :  *    the inode getting the new extents: inode size
     282             :  *    the inode's bmap btree: max depth * block size
     283             :  *    the agfs of the ags from which the extents are allocated: 2 * sector
     284             :  *    the superblock free block counter: sector size
     285             :  *    the realtime bitmap: ((XFS_BMBT_MAX_EXTLEN / rtextsize) / NBBY) bytes
     286             :  *    the realtime summary: 1 block
     287             :  *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
     288             :  * And the bmap_finish transaction can free bmap blocks in a join (t3):
     289             :  *    the agfs of the ags containing the blocks: 2 * sector size
     290             :  *    the agfls of the ags containing the blocks: 2 * sector size
     291             :  *    the super block free block counter: sector size
     292             :  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
     293             :  * And any refcount updates that happen in a separate transaction (t4).
     294             :  */
     295             : STATIC uint
     296       97564 : xfs_calc_write_reservation(
     297             :         struct xfs_mount        *mp,
     298             :         bool                    for_minlogsize)
     299             : {
     300       97564 :         unsigned int            t1, t2, t3, t4;
     301       97564 :         unsigned int            blksz = XFS_FSB_TO_B(mp, 1);
     302             : 
     303       97564 :         t1 = xfs_calc_inode_res(mp, 1) +
     304       97564 :              xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), blksz) +
     305       97564 :              xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
     306       97564 :              xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
     307             : 
     308       97564 :         if (xfs_has_realtime(mp)) {
     309         724 :                 t2 = xfs_calc_inode_res(mp, 1) +
     310             :                      xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
     311             :                                      blksz) +
     312         724 :                      xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
     313         724 :                      xfs_calc_buf_res(xfs_rtalloc_block_count(mp, 1), blksz) +
     314         724 :                      xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1), blksz);
     315             :         } else {
     316             :                 t2 = 0;
     317             :         }
     318             : 
     319       97564 :         t3 = xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
     320             :              xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
     321             : 
     322             :         /*
     323             :          * In the early days of reflink, we included enough reservation to log
     324             :          * two refcountbt splits for each transaction.  The codebase runs
     325             :          * refcountbt updates in separate transactions now, so to compute the
     326             :          * minimum log size, add the refcountbtree splits back to t1 and t3 and
     327             :          * do not account them separately as t4.  Reflink did not support
     328             :          * realtime when the reservations were established, so no adjustment to
     329             :          * t2 is needed.
     330             :          */
     331       97564 :         if (for_minlogsize) {
     332        1104 :                 unsigned int    adj = 0;
     333             : 
     334        1104 :                 if (xfs_has_reflink(mp))
     335         984 :                         adj = xfs_calc_buf_res(
     336             :                                         xfs_refcountbt_block_count(mp, 2),
     337             :                                         blksz);
     338        1104 :                 t1 += adj;
     339        1104 :                 t3 += adj;
     340        1104 :                 return XFS_DQUOT_LOGRES(mp) + max3(t1, t2, t3);
     341             :         }
     342             : 
     343       96460 :         t4 = xfs_calc_refcountbt_reservation(mp, 1);
     344       96460 :         return XFS_DQUOT_LOGRES(mp) + max(t4, max3(t1, t2, t3));
     345             : }
     346             : 
     347             : unsigned int
     348         552 : xfs_calc_write_reservation_minlogsize(
     349             :         struct xfs_mount        *mp)
     350             : {
     351         552 :         return xfs_calc_write_reservation(mp, true);
     352             : }
     353             : 
     354             : /*
     355             :  * In truncating a file we free up to two extents at once.  We can modify (t1):
     356             :  *    the inode being truncated: inode size
     357             :  *    the inode's bmap btree: (max depth + 1) * block size
     358             :  * And the bmap_finish transaction can free the blocks and bmap blocks (t2):
     359             :  *    the agf for each of the ags: 4 * sector size
     360             :  *    the agfl for each of the ags: 4 * sector size
     361             :  *    the super block to reflect the freed blocks: sector size
     362             :  *    worst case split in allocation btrees per extent assuming 4 extents:
     363             :  *              4 exts * 2 trees * (2 * max depth - 1) * block size
     364             :  * Or, if it's a realtime file (t3):
     365             :  *    the agf for each of the ags: 2 * sector size
     366             :  *    the agfl for each of the ags: 2 * sector size
     367             :  *    the super block to reflect the freed blocks: sector size
     368             :  *    the realtime bitmap:
     369             :  *              2 exts * ((XFS_BMBT_MAX_EXTLEN / rtextsize) / NBBY) bytes
     370             :  *    the realtime summary: 2 exts * 1 block
     371             :  *    worst case split in allocation btrees per extent assuming 2 extents:
     372             :  *              2 exts * 2 trees * (2 * max depth - 1) * block size
     373             :  * And any refcount updates that happen in a separate transaction (t4).
     374             :  */
     375             : STATIC uint
     376       48782 : xfs_calc_itruncate_reservation(
     377             :         struct xfs_mount        *mp,
     378             :         bool                    for_minlogsize)
     379             : {
     380       48782 :         unsigned int            t1, t2, t3, t4;
     381       48782 :         unsigned int            blksz = XFS_FSB_TO_B(mp, 1);
     382             : 
     383       48782 :         t1 = xfs_calc_inode_res(mp, 1) +
     384       48782 :              xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, blksz);
     385             : 
     386       48782 :         t2 = xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
     387       48782 :              xfs_calc_buf_res(xfs_allocfree_block_count(mp, 4), blksz);
     388             : 
     389       48782 :         if (xfs_has_realtime(mp)) {
     390         362 :                 t3 = xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
     391         362 :                      xfs_calc_buf_res(xfs_rtalloc_block_count(mp, 2), blksz) +
     392         362 :                      xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
     393             :         } else {
     394             :                 t3 = 0;
     395             :         }
     396             : 
     397             :         /*
     398             :          * In the early days of reflink, we included enough reservation to log
     399             :          * four refcountbt splits in the same transaction as bnobt/cntbt
     400             :          * updates.  The codebase runs refcountbt updates in separate
     401             :          * transactions now, so to compute the minimum log size, add the
     402             :          * refcount btree splits back here and do not compute them separately
     403             :          * as t4.  Reflink did not support realtime when the reservations were
     404             :          * established, so do not adjust t3.
     405             :          */
     406       48782 :         if (for_minlogsize) {
     407         552 :                 if (xfs_has_reflink(mp))
     408         492 :                         t2 += xfs_calc_buf_res(
     409             :                                         xfs_refcountbt_block_count(mp, 4),
     410             :                                         blksz);
     411             : 
     412         552 :                 return XFS_DQUOT_LOGRES(mp) + max3(t1, t2, t3);
     413             :         }
     414             : 
     415       48230 :         t4 = xfs_calc_refcountbt_reservation(mp, 2);
     416       48230 :         return XFS_DQUOT_LOGRES(mp) + max(t4, max3(t1, t2, t3));
     417             : }
     418             : 
     419             : unsigned int
     420         552 : xfs_calc_itruncate_reservation_minlogsize(
     421             :         struct xfs_mount        *mp)
     422             : {
     423         552 :         return xfs_calc_itruncate_reservation(mp, true);
     424             : }
     425             : 
     426             : static inline unsigned int xfs_calc_pptr_link_overhead(void)
     427             : {
     428             :         return sizeof(struct xfs_attri_log_format) +
     429             :                         xlog_calc_iovec_len(sizeof(struct xfs_parent_name_rec)) +
     430             :                         xlog_calc_iovec_len(XFS_PARENT_DIRENT_NAME_MAX_SIZE);
     431             : }
     432             : static inline unsigned int xfs_calc_pptr_unlink_overhead(void)
     433             : {
     434             :         return sizeof(struct xfs_attri_log_format) +
     435             :                         xlog_calc_iovec_len(sizeof(struct xfs_parent_name_rec)) +
     436             :                         xlog_calc_iovec_len(XFS_PARENT_DIRENT_NAME_MAX_SIZE);
     437             : }
     438             : static inline unsigned int xfs_calc_pptr_replace_overhead(void)
     439             : {
     440             :         return sizeof(struct xfs_attri_log_format) +
     441             :                         xlog_calc_iovec_len(sizeof(struct xfs_parent_name_rec)) +
     442             :                         xlog_calc_iovec_len(XFS_PARENT_DIRENT_NAME_MAX_SIZE) +
     443             :                         xlog_calc_iovec_len(sizeof(struct xfs_parent_name_rec)) +
     444             :                         xlog_calc_iovec_len(XFS_PARENT_DIRENT_NAME_MAX_SIZE);
     445             : }
     446             : 
     447             : /*
     448             :  * In renaming a files we can modify:
     449             :  *    the five inodes involved: 5 * inode size
     450             :  *    the two directory btrees: 2 * (max depth + v2) * dir block size
     451             :  *    the two directory bmap btrees: 2 * max depth * block size
     452             :  * And the bmap_finish transaction can free dir and bmap blocks (two sets
     453             :  *      of bmap blocks) giving (t2):
     454             :  *    the agf for the ags in which the blocks live: 3 * sector size
     455             :  *    the agfl for the ags in which the blocks live: 3 * sector size
     456             :  *    the superblock for the free block count: sector size
     457             :  *    the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
     458             :  * If parent pointers are enabled (t3), then each transaction in the chain
     459             :  *    must be capable of setting or removing the extended attribute
     460             :  *    containing the parent information.  It must also be able to handle
     461             :  *    the three xattr intent items that track the progress of the parent
     462             :  *    pointer update.
     463             :  */
     464             : STATIC uint
     465       48230 : xfs_calc_rename_reservation(
     466             :         struct xfs_mount        *mp)
     467             : {
     468       48230 :         unsigned int            overhead = XFS_DQUOT_LOGRES(mp);
     469       48230 :         struct xfs_trans_resv   *resp = M_RES(mp);
     470       48230 :         unsigned int            t1, t2, t3 = 0;
     471             : 
     472       48230 :         t1 = xfs_calc_inode_res(mp, 5) +
     473       48230 :              xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp),
     474       48230 :                         XFS_FSB_TO_B(mp, 1));
     475             : 
     476       48230 :         t2 = xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) +
     477       48230 :              xfs_calc_buf_res(xfs_allocfree_block_count(mp, 3),
     478             :                         XFS_FSB_TO_B(mp, 1));
     479             : 
     480       48230 :         if (xfs_has_parent(mp)) {
     481       47126 :                 unsigned int    rename_overhead, exchange_overhead;
     482             : 
     483       47126 :                 t3 = max(resp->tr_attrsetm.tr_logres,
     484             :                          resp->tr_attrrm.tr_logres);
     485             : 
     486             :                 /*
     487             :                  * For a standard rename, the three xattr intent log items
     488             :                  * are (1) replacing the pptr for the source file; (2)
     489             :                  * removing the pptr on the dest file; and (3) adding a
     490             :                  * pptr for the whiteout file in the src dir.
     491             :                  *
     492             :                  * For an RENAME_EXCHANGE, there are two xattr intent
     493             :                  * items to replace the pptr for both src and dest
     494             :                  * files.  Link counts don't change and there is no
     495             :                  * whiteout.
     496             :                  *
     497             :                  * In the worst case we can end up relogging all log
     498             :                  * intent items to allow the log tail to move ahead, so
     499             :                  * they become overhead added to each transaction in a
     500             :                  * processing chain.
     501             :                  */
     502       47126 :                 rename_overhead = xfs_calc_pptr_replace_overhead() +
     503             :                                   xfs_calc_pptr_unlink_overhead() +
     504             :                                   xfs_calc_pptr_link_overhead();
     505       47126 :                 exchange_overhead = 2 * xfs_calc_pptr_replace_overhead();
     506             : 
     507       47126 :                 overhead += max(rename_overhead, exchange_overhead);
     508             :         }
     509             : 
     510       48230 :         return overhead + max3(t1, t2, t3);
     511             : }
     512             : 
     513             : static inline unsigned int
     514             : xfs_rename_log_count(
     515             :         struct xfs_mount        *mp,
     516             :         struct xfs_trans_resv   *resp)
     517             : {
     518             :         /* One for the rename, one more for freeing blocks */
     519       48230 :         unsigned int            ret = XFS_RENAME_LOG_COUNT;
     520             : 
     521             :         /*
     522             :          * Pre-reserve enough log reservation to handle the transaction
     523             :          * rolling needed to remove or add one parent pointer.
     524             :          */
     525       48230 :         if (xfs_has_parent(mp))
     526       47126 :                 ret += max(resp->tr_attrsetm.tr_logcount,
     527             :                            resp->tr_attrrm.tr_logcount);
     528             : 
     529       48230 :         return ret;
     530             : }
     531             : 
     532             : /*
     533             :  * For removing an inode from unlinked list at first, we can modify:
     534             :  *    the agi hash list and counters: sector size
     535             :  *    the on disk inode before ours in the agi hash list: inode cluster size
     536             :  *    the on disk inode in the agi hash list: inode cluster size
     537             :  */
     538             : STATIC uint
     539       96460 : xfs_calc_iunlink_remove_reservation(
     540             :         struct xfs_mount        *mp)
     541             : {
     542       96460 :         return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
     543       96460 :                2 * M_IGEO(mp)->inode_cluster_size;
     544             : }
     545             : 
     546             : static inline unsigned int
     547             : xfs_link_log_count(
     548             :         struct xfs_mount        *mp,
     549             :         struct xfs_trans_resv   *resp)
     550             : {
     551       48230 :         unsigned int            ret = XFS_LINK_LOG_COUNT;
     552             : 
     553             :         /*
     554             :          * Pre-reserve enough log reservation to handle the transaction
     555             :          * rolling needed to add one parent pointer.
     556             :          */
     557       48230 :         if (xfs_has_parent(mp))
     558       47126 :                 ret += resp->tr_attrsetm.tr_logcount;
     559             : 
     560       48230 :         return ret;
     561             : }
     562             : 
     563             : /*
     564             :  * For creating a link to an inode:
     565             :  *    the parent directory inode: inode size
     566             :  *    the linked inode: inode size
     567             :  *    the directory btree could split: (max depth + v2) * dir block size
     568             :  *    the directory bmap btree could join or split: (max depth + v2) * blocksize
     569             :  * And the bmap_finish transaction can free some bmap blocks giving:
     570             :  *    the agf for the ag in which the blocks live: sector size
     571             :  *    the agfl for the ag in which the blocks live: sector size
     572             :  *    the superblock for the free block count: sector size
     573             :  *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
     574             :  */
     575             : STATIC uint
     576       48230 : xfs_calc_link_reservation(
     577             :         struct xfs_mount        *mp)
     578             : {
     579       48230 :         unsigned int            overhead = XFS_DQUOT_LOGRES(mp);
     580       48230 :         struct xfs_trans_resv   *resp = M_RES(mp);
     581       48230 :         unsigned int            t1, t2, t3 = 0;
     582             : 
     583       48230 :         overhead += xfs_calc_iunlink_remove_reservation(mp);
     584       48230 :         t1 = xfs_calc_inode_res(mp, 2) +
     585       48230 :              xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1));
     586       48230 :         t2 = xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
     587       48230 :              xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
     588             :                               XFS_FSB_TO_B(mp, 1));
     589             : 
     590       48230 :         if (xfs_has_parent(mp)) {
     591       47126 :                 t3 = resp->tr_attrsetm.tr_logres;
     592       47126 :                 overhead += xfs_calc_pptr_link_overhead();
     593             :         }
     594             : 
     595       48230 :         return overhead + max3(t1, t2, t3);
     596             : }
     597             : 
     598             : /*
     599             :  * For adding an inode to unlinked list we can modify:
     600             :  *    the agi hash list: sector size
     601             :  *    the on disk inode: inode cluster size
     602             :  */
     603             : STATIC uint
     604       96460 : xfs_calc_iunlink_add_reservation(xfs_mount_t *mp)
     605             : {
     606       96460 :         return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
     607       96460 :                         M_IGEO(mp)->inode_cluster_size;
     608             : }
     609             : 
     610             : static inline unsigned int
     611             : xfs_remove_log_count(
     612             :         struct xfs_mount        *mp,
     613             :         struct xfs_trans_resv   *resp)
     614             : {
     615       48230 :         unsigned int            ret = XFS_REMOVE_LOG_COUNT;
     616             : 
     617             :         /*
     618             :          * Pre-reserve enough log reservation to handle the transaction
     619             :          * rolling needed to add one parent pointer.
     620             :          */
     621       48230 :         if (xfs_has_parent(mp))
     622       47126 :                 ret += resp->tr_attrrm.tr_logcount;
     623             : 
     624       48230 :         return ret;
     625             : }
     626             : 
     627             : /*
     628             :  * For removing a directory entry we can modify:
     629             :  *    the parent directory inode: inode size
     630             :  *    the removed inode: inode size
     631             :  *    the directory btree could join: (max depth + v2) * dir block size
     632             :  *    the directory bmap btree could join or split: (max depth + v2) * blocksize
     633             :  * And the bmap_finish transaction can free the dir and bmap blocks giving:
     634             :  *    the agf for the ag in which the blocks live: 2 * sector size
     635             :  *    the agfl for the ag in which the blocks live: 2 * sector size
     636             :  *    the superblock for the free block count: sector size
     637             :  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
     638             :  */
     639             : STATIC uint
     640       48230 : xfs_calc_remove_reservation(
     641             :         struct xfs_mount        *mp)
     642             : {
     643       48230 :         unsigned int            overhead = XFS_DQUOT_LOGRES(mp);
     644       48230 :         struct xfs_trans_resv   *resp = M_RES(mp);
     645       48230 :         unsigned int            t1, t2, t3 = 0;
     646             : 
     647       48230 :         overhead += xfs_calc_iunlink_add_reservation(mp);
     648             : 
     649       48230 :         t1 = xfs_calc_inode_res(mp, 2) +
     650       48230 :              xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1));
     651       48230 :         t2 = xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) +
     652       48230 :              xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2),
     653             :                               XFS_FSB_TO_B(mp, 1));
     654             : 
     655       48230 :         if (xfs_has_parent(mp)) {
     656       47126 :                 t3 = resp->tr_attrrm.tr_logres;
     657       47126 :                 overhead += xfs_calc_pptr_unlink_overhead();
     658             :         }
     659             : 
     660       48230 :         return overhead + max3(t1, t2, t3);
     661             : }
     662             : 
     663             : /*
     664             :  * For create, break it in to the two cases that the transaction
     665             :  * covers. We start with the modify case - allocation done by modification
     666             :  * of the state of existing inodes - and the allocation case.
     667             :  */
     668             : 
     669             : /*
     670             :  * For create we can modify:
     671             :  *    the parent directory inode: inode size
     672             :  *    the new inode: inode size
     673             :  *    the inode btree entry: block size
     674             :  *    the superblock for the nlink flag: sector size
     675             :  *    the directory btree: (max depth + v2) * dir block size
     676             :  *    the directory inode's bmap btree: (max depth + v2) * block size
     677             :  *    the finobt (record modification and allocation btrees)
     678             :  */
     679             : STATIC uint
     680      144690 : xfs_calc_create_resv_modify(
     681             :         struct xfs_mount        *mp)
     682             : {
     683      144690 :         return xfs_calc_inode_res(mp, 2) +
     684      144690 :                 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
     685      144690 :                 (uint)XFS_FSB_TO_B(mp, 1) +
     686      144690 :                 xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)) +
     687      144690 :                 xfs_calc_finobt_res(mp);
     688             : }
     689             : 
     690             : /*
     691             :  * For icreate we can allocate some inodes giving:
     692             :  *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
     693             :  *    the superblock for the nlink flag: sector size
     694             :  *    the inode chunk (allocation, optional init)
     695             :  *    the inobt (record insertion)
     696             :  *    the finobt (optional, record insertion)
     697             :  */
     698             : STATIC uint
     699      192920 : xfs_calc_icreate_resv_alloc(
     700             :         struct xfs_mount        *mp)
     701             : {
     702      192920 :         return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
     703      192920 :                 mp->m_sb.sb_sectsize +
     704      192920 :                 xfs_calc_inode_chunk_res(mp, _ALLOC) +
     705      192920 :                 xfs_calc_inobt_res(mp) +
     706      192920 :                 xfs_calc_finobt_res(mp);
     707             : }
     708             : 
     709             : static inline unsigned int
     710             : xfs_icreate_log_count(
     711             :         struct xfs_mount        *mp,
     712             :         struct xfs_trans_resv   *resp)
     713             : {
     714       48230 :         unsigned int            ret = XFS_CREATE_LOG_COUNT;
     715             : 
     716             :         /*
     717             :          * Pre-reserve enough log reservation to handle the transaction
     718             :          * rolling needed to add one parent pointer.
     719             :          */
     720       48230 :         if (xfs_has_parent(mp))
     721       47126 :                 ret += resp->tr_attrsetm.tr_logcount;
     722             : 
     723       48230 :         return ret;
     724             : }
     725             : 
     726             : STATIC uint
     727      144690 : xfs_calc_icreate_reservation(
     728             :         struct xfs_mount        *mp)
     729             : {
     730      144690 :         struct xfs_trans_resv   *resp = M_RES(mp);
     731      144690 :         unsigned int            overhead = XFS_DQUOT_LOGRES(mp);
     732      144690 :         unsigned int            t1, t2, t3 = 0;
     733             : 
     734      144690 :         t1 = xfs_calc_icreate_resv_alloc(mp);
     735      144690 :         t2 = xfs_calc_create_resv_modify(mp);
     736             : 
     737      144690 :         if (xfs_has_parent(mp)) {
     738      141378 :                 t3 = resp->tr_attrsetm.tr_logres;
     739      141378 :                 overhead += xfs_calc_pptr_link_overhead();
     740             :         }
     741             : 
     742      144690 :         return overhead + max3(t1, t2, t3);
     743             : }
     744             : 
     745             : STATIC uint
     746       48230 : xfs_calc_create_tmpfile_reservation(
     747             :         struct xfs_mount        *mp)
     748             : {
     749       48230 :         uint    res = XFS_DQUOT_LOGRES(mp);
     750             : 
     751       48230 :         res += xfs_calc_icreate_resv_alloc(mp);
     752       48230 :         return res + xfs_calc_iunlink_add_reservation(mp);
     753             : }
     754             : 
     755             : static inline unsigned int
     756             : xfs_mkdir_log_count(
     757             :         struct xfs_mount        *mp,
     758             :         struct xfs_trans_resv   *resp)
     759             : {
     760       48230 :         unsigned int            ret = XFS_MKDIR_LOG_COUNT;
     761             : 
     762             :         /*
     763             :          * Pre-reserve enough log reservation to handle the transaction
     764             :          * rolling needed to add one parent pointer.
     765             :          */
     766       48230 :         if (xfs_has_parent(mp))
     767       47126 :                 ret += resp->tr_attrsetm.tr_logcount;
     768             : 
     769       48230 :         return ret;
     770             : }
     771             : 
     772             : /*
     773             :  * Making a new directory is the same as creating a new file.
     774             :  */
     775             : STATIC uint
     776       48230 : xfs_calc_mkdir_reservation(
     777             :         struct xfs_mount        *mp)
     778             : {
     779       48230 :         return xfs_calc_icreate_reservation(mp);
     780             : }
     781             : 
     782             : static inline unsigned int
     783             : xfs_symlink_log_count(
     784             :         struct xfs_mount        *mp,
     785             :         struct xfs_trans_resv   *resp)
     786             : {
     787       48230 :         unsigned int            ret = XFS_SYMLINK_LOG_COUNT;
     788             : 
     789             :         /*
     790             :          * Pre-reserve enough log reservation to handle the transaction
     791             :          * rolling needed to add one parent pointer.
     792             :          */
     793       48230 :         if (xfs_has_parent(mp))
     794       47126 :                 ret += resp->tr_attrsetm.tr_logcount;
     795             : 
     796       48230 :         return ret;
     797             : }
     798             : 
     799             : /*
     800             :  * Making a new symplink is the same as creating a new file, but
     801             :  * with the added blocks for remote symlink data which can be up to 1kB in
     802             :  * length (XFS_SYMLINK_MAXLEN).
     803             :  */
     804             : STATIC uint
     805       48230 : xfs_calc_symlink_reservation(
     806             :         struct xfs_mount        *mp)
     807             : {
     808       48230 :         return xfs_calc_icreate_reservation(mp) +
     809       48230 :                xfs_calc_buf_res(1, XFS_SYMLINK_MAXLEN);
     810             : }
     811             : 
     812             : /*
     813             :  * In freeing an inode we can modify:
     814             :  *    the inode being freed: inode size
     815             :  *    the super block free inode counter, AGF and AGFL: sector size
     816             :  *    the on disk inode (agi unlinked list removal)
     817             :  *    the inode chunk (invalidated, headers only)
     818             :  *    the inode btree
     819             :  *    the finobt (record insertion, removal or modification)
     820             :  *
     821             :  * Note that the inode chunk res. includes an allocfree res. for freeing of the
     822             :  * inode chunk. This is technically extraneous because the inode chunk free is
     823             :  * deferred (it occurs after a transaction roll). Include the extra reservation
     824             :  * anyways since we've had reports of ifree transaction overruns due to too many
     825             :  * agfl fixups during inode chunk frees.
     826             :  */
     827             : STATIC uint
     828       48230 : xfs_calc_ifree_reservation(
     829             :         struct xfs_mount        *mp)
     830             : {
     831       48230 :         return XFS_DQUOT_LOGRES(mp) +
     832       48230 :                 xfs_calc_inode_res(mp, 1) +
     833       48230 :                 xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
     834       48230 :                 xfs_calc_iunlink_remove_reservation(mp) +
     835       48230 :                 xfs_calc_inode_chunk_res(mp, _FREE) +
     836       48230 :                 xfs_calc_inobt_res(mp) +
     837       48230 :                 xfs_calc_finobt_res(mp);
     838             : }
     839             : 
     840             : /*
     841             :  * When only changing the inode we log the inode and possibly the superblock
     842             :  * We also add a bit of slop for the transaction stuff.
     843             :  */
     844             : STATIC uint
     845       48230 : xfs_calc_ichange_reservation(
     846             :         struct xfs_mount        *mp)
     847             : {
     848       48230 :         return XFS_DQUOT_LOGRES(mp) +
     849       48230 :                 xfs_calc_inode_res(mp, 1) +
     850       48230 :                 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
     851             : 
     852             : }
     853             : 
     854             : /*
     855             :  * Growing the data section of the filesystem.
     856             :  *      superblock
     857             :  *      agi and agf
     858             :  *      allocation btrees
     859             :  */
     860             : STATIC uint
     861       48230 : xfs_calc_growdata_reservation(
     862             :         struct xfs_mount        *mp)
     863             : {
     864       48230 :         return xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
     865       48230 :                 xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
     866       48230 :                                  XFS_FSB_TO_B(mp, 1));
     867             : }
     868             : 
     869             : /*
     870             :  * Growing the rt section of the filesystem.
     871             :  * In the first set of transactions (ALLOC) we allocate space to the
     872             :  * bitmap or summary files.
     873             :  *      superblock: sector size
     874             :  *      agf of the ag from which the extent is allocated: sector size
     875             :  *      bmap btree for bitmap/summary inode: max depth * blocksize
     876             :  *      bitmap/summary inode: inode size
     877             :  *      allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
     878             :  */
     879             : STATIC uint
     880       48230 : xfs_calc_growrtalloc_reservation(
     881             :         struct xfs_mount        *mp)
     882             : {
     883       48230 :         return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
     884       48230 :                 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
     885       48230 :                                  XFS_FSB_TO_B(mp, 1)) +
     886       48230 :                 xfs_calc_inode_res(mp, 1) +
     887       48230 :                 xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
     888             :                                  XFS_FSB_TO_B(mp, 1));
     889             : }
     890             : 
     891             : /*
     892             :  * Growing the rt section of the filesystem.
     893             :  * In the second set of transactions (ZERO) we zero the new metadata blocks.
     894             :  *      one bitmap/summary block: blocksize
     895             :  */
     896             : STATIC uint
     897       48230 : xfs_calc_growrtzero_reservation(
     898             :         struct xfs_mount        *mp)
     899             : {
     900       48230 :         return xfs_calc_buf_res(1, mp->m_sb.sb_blocksize);
     901             : }
     902             : 
     903             : /*
     904             :  * Growing the rt section of the filesystem.
     905             :  * In the third set of transactions (FREE) we update metadata without
     906             :  * allocating any new blocks.
     907             :  *      superblock: sector size
     908             :  *      bitmap inode: inode size
     909             :  *      summary inode: inode size
     910             :  *      one bitmap block: blocksize
     911             :  *      summary blocks: new summary size
     912             :  */
     913             : STATIC uint
     914       48230 : xfs_calc_growrtfree_reservation(
     915             :         struct xfs_mount        *mp)
     916             : {
     917       48230 :         return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
     918       48230 :                 xfs_calc_inode_res(mp, 2) +
     919       48230 :                 xfs_calc_buf_res(1, mp->m_sb.sb_blocksize) +
     920       48230 :                 xfs_calc_buf_res(1, mp->m_rsumsize);
     921             : }
     922             : 
     923             : /*
     924             :  * Logging the inode modification timestamp on a synchronous write.
     925             :  *      inode
     926             :  */
     927             : STATIC uint
     928       48230 : xfs_calc_swrite_reservation(
     929             :         struct xfs_mount        *mp)
     930             : {
     931       48230 :         return xfs_calc_inode_res(mp, 1);
     932             : }
     933             : 
     934             : /*
     935             :  * Logging the inode mode bits when writing a setuid/setgid file
     936             :  *      inode
     937             :  */
     938             : STATIC uint
     939       48230 : xfs_calc_writeid_reservation(
     940             :         struct xfs_mount        *mp)
     941             : {
     942       48230 :         return xfs_calc_inode_res(mp, 1);
     943             : }
     944             : 
     945             : /*
     946             :  * Converting the inode from non-attributed to attributed.
     947             :  *      the inode being converted: inode size
     948             :  *      agf block and superblock (for block allocation)
     949             :  *      the new block (directory sized)
     950             :  *      bmap blocks for the new directory block
     951             :  *      allocation btrees
     952             :  */
     953             : STATIC uint
     954       48230 : xfs_calc_addafork_reservation(
     955             :         struct xfs_mount        *mp)
     956             : {
     957       48230 :         return XFS_DQUOT_LOGRES(mp) +
     958       48230 :                 xfs_calc_inode_res(mp, 1) +
     959       48230 :                 xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
     960       48230 :                 xfs_calc_buf_res(1, mp->m_dir_geo->blksize) +
     961       48230 :                 xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1,
     962       48230 :                                  XFS_FSB_TO_B(mp, 1)) +
     963       48230 :                 xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
     964             :                                  XFS_FSB_TO_B(mp, 1));
     965             : }
     966             : 
     967             : /*
     968             :  * Removing the attribute fork of a file
     969             :  *    the inode being truncated: inode size
     970             :  *    the inode's bmap btree: max depth * block size
     971             :  * And the bmap_finish transaction can free the blocks and bmap blocks:
     972             :  *    the agf for each of the ags: 4 * sector size
     973             :  *    the agfl for each of the ags: 4 * sector size
     974             :  *    the super block to reflect the freed blocks: sector size
     975             :  *    worst case split in allocation btrees per extent assuming 4 extents:
     976             :  *              4 exts * 2 trees * (2 * max depth - 1) * block size
     977             :  */
     978             : STATIC uint
     979       48230 : xfs_calc_attrinval_reservation(
     980             :         struct xfs_mount        *mp)
     981             : {
     982       48230 :         return max((xfs_calc_inode_res(mp, 1) +
     983             :                     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
     984             :                                      XFS_FSB_TO_B(mp, 1))),
     985             :                    (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
     986             :                     xfs_calc_buf_res(xfs_allocfree_block_count(mp, 4),
     987             :                                      XFS_FSB_TO_B(mp, 1))));
     988             : }
     989             : 
     990             : /*
     991             :  * Setting an attribute at mount time.
     992             :  *      the inode getting the attribute
     993             :  *      the superblock for allocations
     994             :  *      the agfs extents are allocated from
     995             :  *      the attribute btree * max depth
     996             :  *      the inode allocation btree
     997             :  * Since attribute transaction space is dependent on the size of the attribute,
     998             :  * the calculation is done partially at mount time and partially at runtime(see
     999             :  * below).
    1000             :  */
    1001             : STATIC uint
    1002       48230 : xfs_calc_attrsetm_reservation(
    1003             :         struct xfs_mount        *mp)
    1004             : {
    1005       48230 :         return XFS_DQUOT_LOGRES(mp) +
    1006       48230 :                 xfs_calc_inode_res(mp, 1) +
    1007       48230 :                 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
    1008       48230 :                 xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, XFS_FSB_TO_B(mp, 1));
    1009             : }
    1010             : 
    1011             : /*
    1012             :  * Setting an attribute at runtime, transaction space unit per block.
    1013             :  *      the superblock for allocations: sector size
    1014             :  *      the inode bmap btree could join or split: max depth * block size
    1015             :  * Since the runtime attribute transaction space is dependent on the total
    1016             :  * blocks needed for the 1st bmap, here we calculate out the space unit for
    1017             :  * one block so that the caller could figure out the total space according
    1018             :  * to the attibute extent length in blocks by:
    1019             :  *      ext * M_RES(mp)->tr_attrsetrt.tr_logres
    1020             :  */
    1021             : STATIC uint
    1022       48230 : xfs_calc_attrsetrt_reservation(
    1023             :         struct xfs_mount        *mp)
    1024             : {
    1025       48230 :         return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
    1026       48230 :                 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
    1027       48230 :                                  XFS_FSB_TO_B(mp, 1));
    1028             : }
    1029             : 
    1030             : /*
    1031             :  * Removing an attribute.
    1032             :  *    the inode: inode size
    1033             :  *    the attribute btree could join: max depth * block size
    1034             :  *    the inode bmap btree could join or split: max depth * block size
    1035             :  * And the bmap_finish transaction can free the attr blocks freed giving:
    1036             :  *    the agf for the ag in which the blocks live: 2 * sector size
    1037             :  *    the agfl for the ag in which the blocks live: 2 * sector size
    1038             :  *    the superblock for the free block count: sector size
    1039             :  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
    1040             :  */
    1041             : STATIC uint
    1042       48230 : xfs_calc_attrrm_reservation(
    1043             :         struct xfs_mount        *mp)
    1044             : {
    1045       48230 :         return XFS_DQUOT_LOGRES(mp) +
    1046       48230 :                 max((xfs_calc_inode_res(mp, 1) +
    1047             :                      xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH,
    1048             :                                       XFS_FSB_TO_B(mp, 1)) +
    1049             :                      (uint)XFS_FSB_TO_B(mp,
    1050             :                                         XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
    1051             :                      xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)),
    1052             :                     (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
    1053             :                      xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2),
    1054             :                                       XFS_FSB_TO_B(mp, 1))));
    1055             : }
    1056             : 
    1057             : /*
    1058             :  * Clearing a bad agino number in an agi hash bucket.
    1059             :  */
    1060             : STATIC uint
    1061       48230 : xfs_calc_clear_agi_bucket_reservation(
    1062             :         struct xfs_mount        *mp)
    1063             : {
    1064       48230 :         return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
    1065             : }
    1066             : 
    1067             : /*
    1068             :  * Adjusting quota limits.
    1069             :  *    the disk quota buffer: sizeof(struct xfs_disk_dquot)
    1070             :  */
    1071             : STATIC uint
    1072       48230 : xfs_calc_qm_setqlim_reservation(void)
    1073             : {
    1074       48230 :         return xfs_calc_buf_res(1, sizeof(struct xfs_disk_dquot));
    1075             : }
    1076             : 
    1077             : /*
    1078             :  * Allocating quota on disk if needed.
    1079             :  *      the write transaction log space for quota file extent allocation
    1080             :  *      the unit of quota allocation: one system block size
    1081             :  */
    1082             : STATIC uint
    1083       48782 : xfs_calc_qm_dqalloc_reservation(
    1084             :         struct xfs_mount        *mp,
    1085             :         bool                    for_minlogsize)
    1086             : {
    1087       48782 :         return xfs_calc_write_reservation(mp, for_minlogsize) +
    1088       48782 :                 xfs_calc_buf_res(1,
    1089       48782 :                         XFS_FSB_TO_B(mp, XFS_DQUOT_CLUSTER_SIZE_FSB) - 1);
    1090             : }
    1091             : 
    1092             : unsigned int
    1093         552 : xfs_calc_qm_dqalloc_reservation_minlogsize(
    1094             :         struct xfs_mount        *mp)
    1095             : {
    1096         552 :         return xfs_calc_qm_dqalloc_reservation(mp, true);
    1097             : }
    1098             : 
    1099             : /*
    1100             :  * Syncing the incore super block changes to disk.
    1101             :  *     the super block to reflect the changes: sector size
    1102             :  */
    1103             : STATIC uint
    1104       48230 : xfs_calc_sb_reservation(
    1105             :         struct xfs_mount        *mp)
    1106             : {
    1107       48230 :         return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
    1108             : }
    1109             : 
    1110             : /*
    1111             :  * Namespace reservations.
    1112             :  *
    1113             :  * These get tricky when parent pointers are enabled as we have attribute
    1114             :  * modifications occurring from within these transactions. Rather than confuse
    1115             :  * each of these reservation calculations with the conditional attribute
    1116             :  * reservations, add them here in a clear and concise manner. This requires that
    1117             :  * the attribute reservations have already been calculated.
    1118             :  *
    1119             :  * Note that we only include the static attribute reservation here; the runtime
    1120             :  * reservation will have to be modified by the size of the attributes being
    1121             :  * added/removed/modified. See the comments on the attribute reservation
    1122             :  * calculations for more details.
    1123             :  */
    1124             : STATIC void
    1125       48230 : xfs_calc_namespace_reservations(
    1126             :         struct xfs_mount        *mp,
    1127             :         struct xfs_trans_resv   *resp)
    1128             : {
    1129       48230 :         ASSERT(resp->tr_attrsetm.tr_logres > 0);
    1130             : 
    1131       48230 :         resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp);
    1132       48230 :         resp->tr_rename.tr_logcount = xfs_rename_log_count(mp, resp);
    1133       48230 :         resp->tr_rename.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1134             : 
    1135       48230 :         resp->tr_link.tr_logres = xfs_calc_link_reservation(mp);
    1136       48230 :         resp->tr_link.tr_logcount = xfs_link_log_count(mp, resp);
    1137       48230 :         resp->tr_link.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1138             : 
    1139       48230 :         resp->tr_remove.tr_logres = xfs_calc_remove_reservation(mp);
    1140       48230 :         resp->tr_remove.tr_logcount = xfs_remove_log_count(mp, resp);
    1141       48230 :         resp->tr_remove.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1142             : 
    1143       48230 :         resp->tr_symlink.tr_logres = xfs_calc_symlink_reservation(mp);
    1144       48230 :         resp->tr_symlink.tr_logcount = xfs_symlink_log_count(mp, resp);
    1145       48230 :         resp->tr_symlink.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1146             : 
    1147       48230 :         resp->tr_create.tr_logres = xfs_calc_icreate_reservation(mp);
    1148       48230 :         resp->tr_create.tr_logcount = xfs_icreate_log_count(mp, resp);
    1149       48230 :         resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1150             : 
    1151       48230 :         resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
    1152       48230 :         resp->tr_mkdir.tr_logcount = xfs_mkdir_log_count(mp, resp);
    1153       48230 :         resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1154       48230 : }
    1155             : 
    1156             : void
    1157       48230 : xfs_trans_resv_calc(
    1158             :         struct xfs_mount        *mp,
    1159             :         struct xfs_trans_resv   *resp)
    1160             : {
    1161       48230 :         int                     logcount_adj = 0;
    1162             : 
    1163             :         /*
    1164             :          * The following transactions are logged in physical format and
    1165             :          * require a permanent reservation on space.
    1166             :          */
    1167       48230 :         resp->tr_write.tr_logres = xfs_calc_write_reservation(mp, false);
    1168       48230 :         resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
    1169       48230 :         resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1170             : 
    1171       48230 :         resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp, false);
    1172       48230 :         resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
    1173       48230 :         resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1174             : 
    1175       48230 :         resp->tr_create_tmpfile.tr_logres =
    1176       48230 :                         xfs_calc_create_tmpfile_reservation(mp);
    1177       48230 :         resp->tr_create_tmpfile.tr_logcount = XFS_CREATE_TMPFILE_LOG_COUNT;
    1178       48230 :         resp->tr_create_tmpfile.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1179             : 
    1180       48230 :         resp->tr_ifree.tr_logres = xfs_calc_ifree_reservation(mp);
    1181       48230 :         resp->tr_ifree.tr_logcount = XFS_INACTIVE_LOG_COUNT;
    1182       48230 :         resp->tr_ifree.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1183             : 
    1184       48230 :         resp->tr_addafork.tr_logres = xfs_calc_addafork_reservation(mp);
    1185       48230 :         resp->tr_addafork.tr_logcount = XFS_ADDAFORK_LOG_COUNT;
    1186       48230 :         resp->tr_addafork.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1187             : 
    1188       48230 :         resp->tr_attrinval.tr_logres = xfs_calc_attrinval_reservation(mp);
    1189       48230 :         resp->tr_attrinval.tr_logcount = XFS_ATTRINVAL_LOG_COUNT;
    1190       48230 :         resp->tr_attrinval.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1191             : 
    1192       48230 :         resp->tr_attrsetm.tr_logres = xfs_calc_attrsetm_reservation(mp);
    1193       48230 :         resp->tr_attrsetm.tr_logcount = XFS_ATTRSET_LOG_COUNT;
    1194       48230 :         resp->tr_attrsetm.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1195             : 
    1196       48230 :         resp->tr_attrrm.tr_logres = xfs_calc_attrrm_reservation(mp);
    1197       48230 :         resp->tr_attrrm.tr_logcount = XFS_ATTRRM_LOG_COUNT;
    1198       48230 :         resp->tr_attrrm.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1199             : 
    1200       48230 :         resp->tr_growrtalloc.tr_logres = xfs_calc_growrtalloc_reservation(mp);
    1201       48230 :         resp->tr_growrtalloc.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT;
    1202       48230 :         resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1203             : 
    1204       48230 :         resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp,
    1205             :                         false);
    1206       48230 :         resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
    1207       48230 :         resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1208             : 
    1209       48230 :         xfs_calc_namespace_reservations(mp, resp);
    1210             : 
    1211             :         /*
    1212             :          * The following transactions are logged in logical format with
    1213             :          * a default log count.
    1214             :          */
    1215       48230 :         resp->tr_qm_setqlim.tr_logres = xfs_calc_qm_setqlim_reservation();
    1216       48230 :         resp->tr_qm_setqlim.tr_logcount = XFS_DEFAULT_LOG_COUNT;
    1217             : 
    1218       48230 :         resp->tr_sb.tr_logres = xfs_calc_sb_reservation(mp);
    1219       48230 :         resp->tr_sb.tr_logcount = XFS_DEFAULT_LOG_COUNT;
    1220             : 
    1221             :         /* growdata requires permanent res; it can free space to the last AG */
    1222       48230 :         resp->tr_growdata.tr_logres = xfs_calc_growdata_reservation(mp);
    1223       48230 :         resp->tr_growdata.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT;
    1224       48230 :         resp->tr_growdata.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
    1225             : 
    1226             :         /* The following transaction are logged in logical format */
    1227       48230 :         resp->tr_ichange.tr_logres = xfs_calc_ichange_reservation(mp);
    1228       48230 :         resp->tr_fsyncts.tr_logres = xfs_calc_swrite_reservation(mp);
    1229       48230 :         resp->tr_writeid.tr_logres = xfs_calc_writeid_reservation(mp);
    1230       48230 :         resp->tr_attrsetrt.tr_logres = xfs_calc_attrsetrt_reservation(mp);
    1231       48230 :         resp->tr_clearagi.tr_logres = xfs_calc_clear_agi_bucket_reservation(mp);
    1232       48230 :         resp->tr_growrtzero.tr_logres = xfs_calc_growrtzero_reservation(mp);
    1233       48230 :         resp->tr_growrtfree.tr_logres = xfs_calc_growrtfree_reservation(mp);
    1234             : 
    1235             :         /*
    1236             :          * Add one logcount for BUI items that appear with rmap or reflink,
    1237             :          * one logcount for refcount intent items, and one logcount for rmap
    1238             :          * intent items.
    1239             :          */
    1240       48230 :         if (xfs_has_reflink(mp) || xfs_has_rmapbt(mp))
    1241             :                 logcount_adj++;
    1242       48230 :         if (xfs_has_reflink(mp))
    1243       47718 :                 logcount_adj++;
    1244       48230 :         if (xfs_has_rmapbt(mp))
    1245       47728 :                 logcount_adj++;
    1246             : 
    1247       48230 :         resp->tr_itruncate.tr_logcount += logcount_adj;
    1248       48230 :         resp->tr_write.tr_logcount += logcount_adj;
    1249       48230 :         resp->tr_qm_dqalloc.tr_logcount += logcount_adj;
    1250       48230 : }

Generated by: LCOV version 1.14