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

Generated by: LCOV version 1.14