Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
0004  * Copyright (C) 2010 Red Hat, Inc.
0005  * All Rights Reserved.
0006  */
0007 #include "xfs.h"
0008 #include "xfs_fs.h"
0009 #include "xfs_shared.h"
0010 #include "xfs_format.h"
0011 #include "xfs_log_format.h"
0012 #include "xfs_trans_resv.h"
0013 #include "xfs_mount.h"
0014 #include "xfs_da_format.h"
0015 #include "xfs_da_btree.h"
0016 #include "xfs_inode.h"
0017 #include "xfs_bmap_btree.h"
0018 #include "xfs_quota.h"
0019 #include "xfs_trans.h"
0020 #include "xfs_qm.h"
0021 #include "xfs_trans_space.h"
0022 
0023 #define _ALLOC  true
0024 #define _FREE   false
0025 
0026 /*
0027  * A buffer has a format structure overhead in the log in addition
0028  * to the data, so we need to take this into account when reserving
0029  * space in a transaction for a buffer.  Round the space required up
0030  * to a multiple of 128 bytes so that we don't change the historical
0031  * reservation that has been used for this overhead.
0032  */
0033 STATIC uint
0034 xfs_buf_log_overhead(void)
0035 {
0036     return round_up(sizeof(struct xlog_op_header) +
0037             sizeof(struct xfs_buf_log_format), 128);
0038 }
0039 
0040 /*
0041  * Calculate out transaction log reservation per item in bytes.
0042  *
0043  * The nbufs argument is used to indicate the number of items that
0044  * will be changed in a transaction.  size is used to tell how many
0045  * bytes should be reserved per item.
0046  */
0047 STATIC uint
0048 xfs_calc_buf_res(
0049     uint        nbufs,
0050     uint        size)
0051 {
0052     return nbufs * (size + xfs_buf_log_overhead());
0053 }
0054 
0055 /*
0056  * Per-extent log reservation for the btree changes involved in freeing or
0057  * allocating an extent.  In classic XFS there were two trees that will be
0058  * modified (bnobt + cntbt).  With rmap enabled, there are three trees
0059  * (rmapbt).  The number of blocks reserved is based on the formula:
0060  *
0061  * num trees * ((2 blocks/level * max depth) - 1)
0062  *
0063  * Keep in mind that max depth is calculated separately for each type of tree.
0064  */
0065 uint
0066 xfs_allocfree_block_count(
0067     struct xfs_mount *mp,
0068     uint        num_ops)
0069 {
0070     uint        blocks;
0071 
0072     blocks = num_ops * 2 * (2 * mp->m_alloc_maxlevels - 1);
0073     if (xfs_has_rmapbt(mp))
0074         blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1);
0075 
0076     return blocks;
0077 }
0078 
0079 /*
0080  * Per-extent log reservation for refcount btree changes.  These are never done
0081  * in the same transaction as an allocation or a free, so we compute them
0082  * separately.
0083  */
0084 static unsigned int
0085 xfs_refcountbt_block_count(
0086     struct xfs_mount    *mp,
0087     unsigned int        num_ops)
0088 {
0089     return num_ops * (2 * mp->m_refc_maxlevels - 1);
0090 }
0091 
0092 /*
0093  * Logging inodes is really tricksy. They are logged in memory format,
0094  * which means that what we write into the log doesn't directly translate into
0095  * the amount of space they use on disk.
0096  *
0097  * Case in point - btree format forks in memory format use more space than the
0098  * on-disk format. In memory, the buffer contains a normal btree block header so
0099  * the btree code can treat it as though it is just another generic buffer.
0100  * However, when we write it to the inode fork, we don't write all of this
0101  * header as it isn't needed. e.g. the root is only ever in the inode, so
0102  * there's no need for sibling pointers which would waste 16 bytes of space.
0103  *
0104  * Hence when we have an inode with a maximally sized btree format fork, then
0105  * amount of information we actually log is greater than the size of the inode
0106  * on disk. Hence we need an inode reservation function that calculates all this
0107  * correctly. So, we log:
0108  *
0109  * - 4 log op headers for object
0110  *  - for the ilf, the inode core and 2 forks
0111  * - inode log format object
0112  * - the inode core
0113  * - two inode forks containing bmap btree root blocks.
0114  *  - the btree data contained by both forks will fit into the inode size,
0115  *    hence when combined with the inode core above, we have a total of the
0116  *    actual inode size.
0117  *  - the BMBT headers need to be accounted separately, as they are
0118  *    additional to the records and pointers that fit inside the inode
0119  *    forks.
0120  */
0121 STATIC uint
0122 xfs_calc_inode_res(
0123     struct xfs_mount    *mp,
0124     uint            ninodes)
0125 {
0126     return ninodes *
0127         (4 * sizeof(struct xlog_op_header) +
0128          sizeof(struct xfs_inode_log_format) +
0129          mp->m_sb.sb_inodesize +
0130          2 * XFS_BMBT_BLOCK_LEN(mp));
0131 }
0132 
0133 /*
0134  * Inode btree record insertion/removal modifies the inode btree and free space
0135  * btrees (since the inobt does not use the agfl). This requires the following
0136  * reservation:
0137  *
0138  * the inode btree: max depth * blocksize
0139  * the allocation btrees: 2 trees * (max depth - 1) * block size
0140  *
0141  * The caller must account for SB and AG header modifications, etc.
0142  */
0143 STATIC uint
0144 xfs_calc_inobt_res(
0145     struct xfs_mount    *mp)
0146 {
0147     return xfs_calc_buf_res(M_IGEO(mp)->inobt_maxlevels,
0148             XFS_FSB_TO_B(mp, 1)) +
0149                 xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
0150             XFS_FSB_TO_B(mp, 1));
0151 }
0152 
0153 /*
0154  * The free inode btree is a conditional feature. The behavior differs slightly
0155  * from that of the traditional inode btree in that the finobt tracks records
0156  * for inode chunks with at least one free inode. A record can be removed from
0157  * the tree during individual inode allocation. Therefore the finobt
0158  * reservation is unconditional for both the inode chunk allocation and
0159  * individual inode allocation (modify) cases.
0160  *
0161  * Behavior aside, the reservation for finobt modification is equivalent to the
0162  * traditional inobt: cover a full finobt shape change plus block allocation.
0163  */
0164 STATIC uint
0165 xfs_calc_finobt_res(
0166     struct xfs_mount    *mp)
0167 {
0168     if (!xfs_has_finobt(mp))
0169         return 0;
0170 
0171     return xfs_calc_inobt_res(mp);
0172 }
0173 
0174 /*
0175  * Calculate the reservation required to allocate or free an inode chunk. This
0176  * includes:
0177  *
0178  * the allocation btrees: 2 trees * (max depth - 1) * block size
0179  * the inode chunk: m_ino_geo.ialloc_blks * N
0180  *
0181  * The size N of the inode chunk reservation depends on whether it is for
0182  * allocation or free and which type of create transaction is in use. An inode
0183  * chunk free always invalidates the buffers and only requires reservation for
0184  * headers (N == 0). An inode chunk allocation requires a chunk sized
0185  * reservation on v4 and older superblocks to initialize the chunk. No chunk
0186  * reservation is required for allocation on v5 supers, which use ordered
0187  * buffers to initialize.
0188  */
0189 STATIC uint
0190 xfs_calc_inode_chunk_res(
0191     struct xfs_mount    *mp,
0192     bool            alloc)
0193 {
0194     uint            res, size = 0;
0195 
0196     res = xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
0197                    XFS_FSB_TO_B(mp, 1));
0198     if (alloc) {
0199         /* icreate tx uses ordered buffers */
0200         if (xfs_has_v3inodes(mp))
0201             return res;
0202         size = XFS_FSB_TO_B(mp, 1);
0203     }
0204 
0205     res += xfs_calc_buf_res(M_IGEO(mp)->ialloc_blks, size);
0206     return res;
0207 }
0208 
0209 /*
0210  * Per-extent log reservation for the btree changes involved in freeing or
0211  * allocating a realtime extent.  We have to be able to log as many rtbitmap
0212  * blocks as needed to mark inuse XFS_BMBT_MAX_EXTLEN blocks' worth of realtime
0213  * extents, as well as the realtime summary block.
0214  */
0215 static unsigned int
0216 xfs_rtalloc_block_count(
0217     struct xfs_mount    *mp,
0218     unsigned int        num_ops)
0219 {
0220     unsigned int        blksz = XFS_FSB_TO_B(mp, 1);
0221     unsigned int        rtbmp_bytes;
0222 
0223     rtbmp_bytes = (XFS_MAX_BMBT_EXTLEN / mp->m_sb.sb_rextsize) / NBBY;
0224     return (howmany(rtbmp_bytes, blksz) + 1) * num_ops;
0225 }
0226 
0227 /*
0228  * Various log reservation values.
0229  *
0230  * These are based on the size of the file system block because that is what
0231  * most transactions manipulate.  Each adds in an additional 128 bytes per
0232  * item logged to try to account for the overhead of the transaction mechanism.
0233  *
0234  * Note:  Most of the reservations underestimate the number of allocation
0235  * groups into which they could free extents in the xfs_defer_finish() call.
0236  * This is because the number in the worst case is quite high and quite
0237  * unusual.  In order to fix this we need to change xfs_defer_finish() to free
0238  * extents in only a single AG at a time.  This will require changes to the
0239  * EFI code as well, however, so that the EFI for the extents not freed is
0240  * logged again in each transaction.  See SGI PV #261917.
0241  *
0242  * Reservation functions here avoid a huge stack in xfs_trans_init due to
0243  * register overflow from temporaries in the calculations.
0244  */
0245 
0246 /*
0247  * Compute the log reservation required to handle the refcount update
0248  * transaction.  Refcount updates are always done via deferred log items.
0249  *
0250  * This is calculated as:
0251  * Data device refcount updates (t1):
0252  *    the agfs of the ags containing the blocks: nr_ops * sector size
0253  *    the refcount btrees: nr_ops * 1 trees * (2 * max depth - 1) * block size
0254  */
0255 static unsigned int
0256 xfs_calc_refcountbt_reservation(
0257     struct xfs_mount    *mp,
0258     unsigned int        nr_ops)
0259 {
0260     unsigned int        blksz = XFS_FSB_TO_B(mp, 1);
0261 
0262     if (!xfs_has_reflink(mp))
0263         return 0;
0264 
0265     return xfs_calc_buf_res(nr_ops, mp->m_sb.sb_sectsize) +
0266            xfs_calc_buf_res(xfs_refcountbt_block_count(mp, nr_ops), blksz);
0267 }
0268 
0269 /*
0270  * In a write transaction we can allocate a maximum of 2
0271  * extents.  This gives (t1):
0272  *    the inode getting the new extents: inode size
0273  *    the inode's bmap btree: max depth * block size
0274  *    the agfs of the ags from which the extents are allocated: 2 * sector
0275  *    the superblock free block counter: sector size
0276  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
0277  * Or, if we're writing to a realtime file (t2):
0278  *    the inode getting the new extents: inode size
0279  *    the inode's bmap btree: max depth * block size
0280  *    the agfs of the ags from which the extents are allocated: 2 * sector
0281  *    the superblock free block counter: sector size
0282  *    the realtime bitmap: ((XFS_BMBT_MAX_EXTLEN / rtextsize) / NBBY) bytes
0283  *    the realtime summary: 1 block
0284  *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
0285  * And the bmap_finish transaction can free bmap blocks in a join (t3):
0286  *    the agfs of the ags containing the blocks: 2 * sector size
0287  *    the agfls of the ags containing the blocks: 2 * sector size
0288  *    the super block free block counter: sector size
0289  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
0290  * And any refcount updates that happen in a separate transaction (t4).
0291  */
0292 STATIC uint
0293 xfs_calc_write_reservation(
0294     struct xfs_mount    *mp,
0295     bool            for_minlogsize)
0296 {
0297     unsigned int        t1, t2, t3, t4;
0298     unsigned int        blksz = XFS_FSB_TO_B(mp, 1);
0299 
0300     t1 = xfs_calc_inode_res(mp, 1) +
0301          xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), blksz) +
0302          xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
0303          xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
0304 
0305     if (xfs_has_realtime(mp)) {
0306         t2 = xfs_calc_inode_res(mp, 1) +
0307              xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
0308                      blksz) +
0309              xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
0310              xfs_calc_buf_res(xfs_rtalloc_block_count(mp, 1), blksz) +
0311              xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1), blksz);
0312     } else {
0313         t2 = 0;
0314     }
0315 
0316     t3 = xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
0317          xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
0318 
0319     /*
0320      * In the early days of reflink, we included enough reservation to log
0321      * two refcountbt splits for each transaction.  The codebase runs
0322      * refcountbt updates in separate transactions now, so to compute the
0323      * minimum log size, add the refcountbtree splits back to t1 and t3 and
0324      * do not account them separately as t4.  Reflink did not support
0325      * realtime when the reservations were established, so no adjustment to
0326      * t2 is needed.
0327      */
0328     if (for_minlogsize) {
0329         unsigned int    adj = 0;
0330 
0331         if (xfs_has_reflink(mp))
0332             adj = xfs_calc_buf_res(
0333                     xfs_refcountbt_block_count(mp, 2),
0334                     blksz);
0335         t1 += adj;
0336         t3 += adj;
0337         return XFS_DQUOT_LOGRES(mp) + max3(t1, t2, t3);
0338     }
0339 
0340     t4 = xfs_calc_refcountbt_reservation(mp, 1);
0341     return XFS_DQUOT_LOGRES(mp) + max(t4, max3(t1, t2, t3));
0342 }
0343 
0344 unsigned int
0345 xfs_calc_write_reservation_minlogsize(
0346     struct xfs_mount    *mp)
0347 {
0348     return xfs_calc_write_reservation(mp, true);
0349 }
0350 
0351 /*
0352  * In truncating a file we free up to two extents at once.  We can modify (t1):
0353  *    the inode being truncated: inode size
0354  *    the inode's bmap btree: (max depth + 1) * block size
0355  * And the bmap_finish transaction can free the blocks and bmap blocks (t2):
0356  *    the agf for each of the ags: 4 * sector size
0357  *    the agfl for each of the ags: 4 * sector size
0358  *    the super block to reflect the freed blocks: sector size
0359  *    worst case split in allocation btrees per extent assuming 4 extents:
0360  *      4 exts * 2 trees * (2 * max depth - 1) * block size
0361  * Or, if it's a realtime file (t3):
0362  *    the agf for each of the ags: 2 * sector size
0363  *    the agfl for each of the ags: 2 * sector size
0364  *    the super block to reflect the freed blocks: sector size
0365  *    the realtime bitmap:
0366  *      2 exts * ((XFS_BMBT_MAX_EXTLEN / rtextsize) / NBBY) bytes
0367  *    the realtime summary: 2 exts * 1 block
0368  *    worst case split in allocation btrees per extent assuming 2 extents:
0369  *      2 exts * 2 trees * (2 * max depth - 1) * block size
0370  * And any refcount updates that happen in a separate transaction (t4).
0371  */
0372 STATIC uint
0373 xfs_calc_itruncate_reservation(
0374     struct xfs_mount    *mp,
0375     bool            for_minlogsize)
0376 {
0377     unsigned int        t1, t2, t3, t4;
0378     unsigned int        blksz = XFS_FSB_TO_B(mp, 1);
0379 
0380     t1 = xfs_calc_inode_res(mp, 1) +
0381          xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, blksz);
0382 
0383     t2 = xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
0384          xfs_calc_buf_res(xfs_allocfree_block_count(mp, 4), blksz);
0385 
0386     if (xfs_has_realtime(mp)) {
0387         t3 = xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
0388              xfs_calc_buf_res(xfs_rtalloc_block_count(mp, 2), blksz) +
0389              xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
0390     } else {
0391         t3 = 0;
0392     }
0393 
0394     /*
0395      * In the early days of reflink, we included enough reservation to log
0396      * four refcountbt splits in the same transaction as bnobt/cntbt
0397      * updates.  The codebase runs refcountbt updates in separate
0398      * transactions now, so to compute the minimum log size, add the
0399      * refcount btree splits back here and do not compute them separately
0400      * as t4.  Reflink did not support realtime when the reservations were
0401      * established, so do not adjust t3.
0402      */
0403     if (for_minlogsize) {
0404         if (xfs_has_reflink(mp))
0405             t2 += xfs_calc_buf_res(
0406                     xfs_refcountbt_block_count(mp, 4),
0407                     blksz);
0408 
0409         return XFS_DQUOT_LOGRES(mp) + max3(t1, t2, t3);
0410     }
0411 
0412     t4 = xfs_calc_refcountbt_reservation(mp, 2);
0413     return XFS_DQUOT_LOGRES(mp) + max(t4, max3(t1, t2, t3));
0414 }
0415 
0416 unsigned int
0417 xfs_calc_itruncate_reservation_minlogsize(
0418     struct xfs_mount    *mp)
0419 {
0420     return xfs_calc_itruncate_reservation(mp, true);
0421 }
0422 
0423 /*
0424  * In renaming a files we can modify:
0425  *    the four inodes involved: 4 * inode size
0426  *    the two directory btrees: 2 * (max depth + v2) * dir block size
0427  *    the two directory bmap btrees: 2 * max depth * block size
0428  * And the bmap_finish transaction can free dir and bmap blocks (two sets
0429  *  of bmap blocks) giving:
0430  *    the agf for the ags in which the blocks live: 3 * sector size
0431  *    the agfl for the ags in which the blocks live: 3 * sector size
0432  *    the superblock for the free block count: sector size
0433  *    the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
0434  */
0435 STATIC uint
0436 xfs_calc_rename_reservation(
0437     struct xfs_mount    *mp)
0438 {
0439     return XFS_DQUOT_LOGRES(mp) +
0440         max((xfs_calc_inode_res(mp, 4) +
0441              xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp),
0442                       XFS_FSB_TO_B(mp, 1))),
0443             (xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) +
0444              xfs_calc_buf_res(xfs_allocfree_block_count(mp, 3),
0445                       XFS_FSB_TO_B(mp, 1))));
0446 }
0447 
0448 /*
0449  * For removing an inode from unlinked list at first, we can modify:
0450  *    the agi hash list and counters: sector size
0451  *    the on disk inode before ours in the agi hash list: inode cluster size
0452  *    the on disk inode in the agi hash list: inode cluster size
0453  */
0454 STATIC uint
0455 xfs_calc_iunlink_remove_reservation(
0456     struct xfs_mount        *mp)
0457 {
0458     return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
0459            2 * M_IGEO(mp)->inode_cluster_size;
0460 }
0461 
0462 /*
0463  * For creating a link to an inode:
0464  *    the parent directory inode: inode size
0465  *    the linked inode: inode size
0466  *    the directory btree could split: (max depth + v2) * dir block size
0467  *    the directory bmap btree could join or split: (max depth + v2) * blocksize
0468  * And the bmap_finish transaction can free some bmap blocks giving:
0469  *    the agf for the ag in which the blocks live: sector size
0470  *    the agfl for the ag in which the blocks live: sector size
0471  *    the superblock for the free block count: sector size
0472  *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
0473  */
0474 STATIC uint
0475 xfs_calc_link_reservation(
0476     struct xfs_mount    *mp)
0477 {
0478     return XFS_DQUOT_LOGRES(mp) +
0479         xfs_calc_iunlink_remove_reservation(mp) +
0480         max((xfs_calc_inode_res(mp, 2) +
0481              xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
0482                       XFS_FSB_TO_B(mp, 1))),
0483             (xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
0484              xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
0485                       XFS_FSB_TO_B(mp, 1))));
0486 }
0487 
0488 /*
0489  * For adding an inode to unlinked list we can modify:
0490  *    the agi hash list: sector size
0491  *    the on disk inode: inode cluster size
0492  */
0493 STATIC uint
0494 xfs_calc_iunlink_add_reservation(xfs_mount_t *mp)
0495 {
0496     return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
0497             M_IGEO(mp)->inode_cluster_size;
0498 }
0499 
0500 /*
0501  * For removing a directory entry we can modify:
0502  *    the parent directory inode: inode size
0503  *    the removed inode: inode size
0504  *    the directory btree could join: (max depth + v2) * dir block size
0505  *    the directory bmap btree could join or split: (max depth + v2) * blocksize
0506  * And the bmap_finish transaction can free the dir and bmap blocks giving:
0507  *    the agf for the ag in which the blocks live: 2 * sector size
0508  *    the agfl for the ag in which the blocks live: 2 * sector size
0509  *    the superblock for the free block count: sector size
0510  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
0511  */
0512 STATIC uint
0513 xfs_calc_remove_reservation(
0514     struct xfs_mount    *mp)
0515 {
0516     return XFS_DQUOT_LOGRES(mp) +
0517         xfs_calc_iunlink_add_reservation(mp) +
0518         max((xfs_calc_inode_res(mp, 2) +
0519              xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
0520                       XFS_FSB_TO_B(mp, 1))),
0521             (xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) +
0522              xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2),
0523                       XFS_FSB_TO_B(mp, 1))));
0524 }
0525 
0526 /*
0527  * For create, break it in to the two cases that the transaction
0528  * covers. We start with the modify case - allocation done by modification
0529  * of the state of existing inodes - and the allocation case.
0530  */
0531 
0532 /*
0533  * For create we can modify:
0534  *    the parent directory inode: inode size
0535  *    the new inode: inode size
0536  *    the inode btree entry: block size
0537  *    the superblock for the nlink flag: sector size
0538  *    the directory btree: (max depth + v2) * dir block size
0539  *    the directory inode's bmap btree: (max depth + v2) * block size
0540  *    the finobt (record modification and allocation btrees)
0541  */
0542 STATIC uint
0543 xfs_calc_create_resv_modify(
0544     struct xfs_mount    *mp)
0545 {
0546     return xfs_calc_inode_res(mp, 2) +
0547         xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
0548         (uint)XFS_FSB_TO_B(mp, 1) +
0549         xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)) +
0550         xfs_calc_finobt_res(mp);
0551 }
0552 
0553 /*
0554  * For icreate we can allocate some inodes giving:
0555  *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
0556  *    the superblock for the nlink flag: sector size
0557  *    the inode chunk (allocation, optional init)
0558  *    the inobt (record insertion)
0559  *    the finobt (optional, record insertion)
0560  */
0561 STATIC uint
0562 xfs_calc_icreate_resv_alloc(
0563     struct xfs_mount    *mp)
0564 {
0565     return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
0566         mp->m_sb.sb_sectsize +
0567         xfs_calc_inode_chunk_res(mp, _ALLOC) +
0568         xfs_calc_inobt_res(mp) +
0569         xfs_calc_finobt_res(mp);
0570 }
0571 
0572 STATIC uint
0573 xfs_calc_icreate_reservation(xfs_mount_t *mp)
0574 {
0575     return XFS_DQUOT_LOGRES(mp) +
0576         max(xfs_calc_icreate_resv_alloc(mp),
0577             xfs_calc_create_resv_modify(mp));
0578 }
0579 
0580 STATIC uint
0581 xfs_calc_create_tmpfile_reservation(
0582     struct xfs_mount        *mp)
0583 {
0584     uint    res = XFS_DQUOT_LOGRES(mp);
0585 
0586     res += xfs_calc_icreate_resv_alloc(mp);
0587     return res + xfs_calc_iunlink_add_reservation(mp);
0588 }
0589 
0590 /*
0591  * Making a new directory is the same as creating a new file.
0592  */
0593 STATIC uint
0594 xfs_calc_mkdir_reservation(
0595     struct xfs_mount    *mp)
0596 {
0597     return xfs_calc_icreate_reservation(mp);
0598 }
0599 
0600 
0601 /*
0602  * Making a new symplink is the same as creating a new file, but
0603  * with the added blocks for remote symlink data which can be up to 1kB in
0604  * length (XFS_SYMLINK_MAXLEN).
0605  */
0606 STATIC uint
0607 xfs_calc_symlink_reservation(
0608     struct xfs_mount    *mp)
0609 {
0610     return xfs_calc_icreate_reservation(mp) +
0611            xfs_calc_buf_res(1, XFS_SYMLINK_MAXLEN);
0612 }
0613 
0614 /*
0615  * In freeing an inode we can modify:
0616  *    the inode being freed: inode size
0617  *    the super block free inode counter, AGF and AGFL: sector size
0618  *    the on disk inode (agi unlinked list removal)
0619  *    the inode chunk (invalidated, headers only)
0620  *    the inode btree
0621  *    the finobt (record insertion, removal or modification)
0622  *
0623  * Note that the inode chunk res. includes an allocfree res. for freeing of the
0624  * inode chunk. This is technically extraneous because the inode chunk free is
0625  * deferred (it occurs after a transaction roll). Include the extra reservation
0626  * anyways since we've had reports of ifree transaction overruns due to too many
0627  * agfl fixups during inode chunk frees.
0628  */
0629 STATIC uint
0630 xfs_calc_ifree_reservation(
0631     struct xfs_mount    *mp)
0632 {
0633     return XFS_DQUOT_LOGRES(mp) +
0634         xfs_calc_inode_res(mp, 1) +
0635         xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
0636         xfs_calc_iunlink_remove_reservation(mp) +
0637         xfs_calc_inode_chunk_res(mp, _FREE) +
0638         xfs_calc_inobt_res(mp) +
0639         xfs_calc_finobt_res(mp);
0640 }
0641 
0642 /*
0643  * When only changing the inode we log the inode and possibly the superblock
0644  * We also add a bit of slop for the transaction stuff.
0645  */
0646 STATIC uint
0647 xfs_calc_ichange_reservation(
0648     struct xfs_mount    *mp)
0649 {
0650     return XFS_DQUOT_LOGRES(mp) +
0651         xfs_calc_inode_res(mp, 1) +
0652         xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
0653 
0654 }
0655 
0656 /*
0657  * Growing the data section of the filesystem.
0658  *  superblock
0659  *  agi and agf
0660  *  allocation btrees
0661  */
0662 STATIC uint
0663 xfs_calc_growdata_reservation(
0664     struct xfs_mount    *mp)
0665 {
0666     return xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
0667         xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
0668                  XFS_FSB_TO_B(mp, 1));
0669 }
0670 
0671 /*
0672  * Growing the rt section of the filesystem.
0673  * In the first set of transactions (ALLOC) we allocate space to the
0674  * bitmap or summary files.
0675  *  superblock: sector size
0676  *  agf of the ag from which the extent is allocated: sector size
0677  *  bmap btree for bitmap/summary inode: max depth * blocksize
0678  *  bitmap/summary inode: inode size
0679  *  allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
0680  */
0681 STATIC uint
0682 xfs_calc_growrtalloc_reservation(
0683     struct xfs_mount    *mp)
0684 {
0685     return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
0686         xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
0687                  XFS_FSB_TO_B(mp, 1)) +
0688         xfs_calc_inode_res(mp, 1) +
0689         xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
0690                  XFS_FSB_TO_B(mp, 1));
0691 }
0692 
0693 /*
0694  * Growing the rt section of the filesystem.
0695  * In the second set of transactions (ZERO) we zero the new metadata blocks.
0696  *  one bitmap/summary block: blocksize
0697  */
0698 STATIC uint
0699 xfs_calc_growrtzero_reservation(
0700     struct xfs_mount    *mp)
0701 {
0702     return xfs_calc_buf_res(1, mp->m_sb.sb_blocksize);
0703 }
0704 
0705 /*
0706  * Growing the rt section of the filesystem.
0707  * In the third set of transactions (FREE) we update metadata without
0708  * allocating any new blocks.
0709  *  superblock: sector size
0710  *  bitmap inode: inode size
0711  *  summary inode: inode size
0712  *  one bitmap block: blocksize
0713  *  summary blocks: new summary size
0714  */
0715 STATIC uint
0716 xfs_calc_growrtfree_reservation(
0717     struct xfs_mount    *mp)
0718 {
0719     return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
0720         xfs_calc_inode_res(mp, 2) +
0721         xfs_calc_buf_res(1, mp->m_sb.sb_blocksize) +
0722         xfs_calc_buf_res(1, mp->m_rsumsize);
0723 }
0724 
0725 /*
0726  * Logging the inode modification timestamp on a synchronous write.
0727  *  inode
0728  */
0729 STATIC uint
0730 xfs_calc_swrite_reservation(
0731     struct xfs_mount    *mp)
0732 {
0733     return xfs_calc_inode_res(mp, 1);
0734 }
0735 
0736 /*
0737  * Logging the inode mode bits when writing a setuid/setgid file
0738  *  inode
0739  */
0740 STATIC uint
0741 xfs_calc_writeid_reservation(
0742     struct xfs_mount    *mp)
0743 {
0744     return xfs_calc_inode_res(mp, 1);
0745 }
0746 
0747 /*
0748  * Converting the inode from non-attributed to attributed.
0749  *  the inode being converted: inode size
0750  *  agf block and superblock (for block allocation)
0751  *  the new block (directory sized)
0752  *  bmap blocks for the new directory block
0753  *  allocation btrees
0754  */
0755 STATIC uint
0756 xfs_calc_addafork_reservation(
0757     struct xfs_mount    *mp)
0758 {
0759     return XFS_DQUOT_LOGRES(mp) +
0760         xfs_calc_inode_res(mp, 1) +
0761         xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
0762         xfs_calc_buf_res(1, mp->m_dir_geo->blksize) +
0763         xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1,
0764                  XFS_FSB_TO_B(mp, 1)) +
0765         xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
0766                  XFS_FSB_TO_B(mp, 1));
0767 }
0768 
0769 /*
0770  * Removing the attribute fork of a file
0771  *    the inode being truncated: inode size
0772  *    the inode's bmap btree: max depth * block size
0773  * And the bmap_finish transaction can free the blocks and bmap blocks:
0774  *    the agf for each of the ags: 4 * sector size
0775  *    the agfl for each of the ags: 4 * sector size
0776  *    the super block to reflect the freed blocks: sector size
0777  *    worst case split in allocation btrees per extent assuming 4 extents:
0778  *      4 exts * 2 trees * (2 * max depth - 1) * block size
0779  */
0780 STATIC uint
0781 xfs_calc_attrinval_reservation(
0782     struct xfs_mount    *mp)
0783 {
0784     return max((xfs_calc_inode_res(mp, 1) +
0785             xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
0786                      XFS_FSB_TO_B(mp, 1))),
0787            (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
0788             xfs_calc_buf_res(xfs_allocfree_block_count(mp, 4),
0789                      XFS_FSB_TO_B(mp, 1))));
0790 }
0791 
0792 /*
0793  * Setting an attribute at mount time.
0794  *  the inode getting the attribute
0795  *  the superblock for allocations
0796  *  the agfs extents are allocated from
0797  *  the attribute btree * max depth
0798  *  the inode allocation btree
0799  * Since attribute transaction space is dependent on the size of the attribute,
0800  * the calculation is done partially at mount time and partially at runtime(see
0801  * below).
0802  */
0803 STATIC uint
0804 xfs_calc_attrsetm_reservation(
0805     struct xfs_mount    *mp)
0806 {
0807     return XFS_DQUOT_LOGRES(mp) +
0808         xfs_calc_inode_res(mp, 1) +
0809         xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
0810         xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, XFS_FSB_TO_B(mp, 1));
0811 }
0812 
0813 /*
0814  * Setting an attribute at runtime, transaction space unit per block.
0815  *  the superblock for allocations: sector size
0816  *  the inode bmap btree could join or split: max depth * block size
0817  * Since the runtime attribute transaction space is dependent on the total
0818  * blocks needed for the 1st bmap, here we calculate out the space unit for
0819  * one block so that the caller could figure out the total space according
0820  * to the attibute extent length in blocks by:
0821  *  ext * M_RES(mp)->tr_attrsetrt.tr_logres
0822  */
0823 STATIC uint
0824 xfs_calc_attrsetrt_reservation(
0825     struct xfs_mount    *mp)
0826 {
0827     return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
0828         xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
0829                  XFS_FSB_TO_B(mp, 1));
0830 }
0831 
0832 /*
0833  * Removing an attribute.
0834  *    the inode: inode size
0835  *    the attribute btree could join: max depth * block size
0836  *    the inode bmap btree could join or split: max depth * block size
0837  * And the bmap_finish transaction can free the attr blocks freed giving:
0838  *    the agf for the ag in which the blocks live: 2 * sector size
0839  *    the agfl for the ag in which the blocks live: 2 * sector size
0840  *    the superblock for the free block count: sector size
0841  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
0842  */
0843 STATIC uint
0844 xfs_calc_attrrm_reservation(
0845     struct xfs_mount    *mp)
0846 {
0847     return XFS_DQUOT_LOGRES(mp) +
0848         max((xfs_calc_inode_res(mp, 1) +
0849              xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH,
0850                       XFS_FSB_TO_B(mp, 1)) +
0851              (uint)XFS_FSB_TO_B(mp,
0852                     XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
0853              xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)),
0854             (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
0855              xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2),
0856                       XFS_FSB_TO_B(mp, 1))));
0857 }
0858 
0859 /*
0860  * Clearing a bad agino number in an agi hash bucket.
0861  */
0862 STATIC uint
0863 xfs_calc_clear_agi_bucket_reservation(
0864     struct xfs_mount    *mp)
0865 {
0866     return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
0867 }
0868 
0869 /*
0870  * Adjusting quota limits.
0871  *    the disk quota buffer: sizeof(struct xfs_disk_dquot)
0872  */
0873 STATIC uint
0874 xfs_calc_qm_setqlim_reservation(void)
0875 {
0876     return xfs_calc_buf_res(1, sizeof(struct xfs_disk_dquot));
0877 }
0878 
0879 /*
0880  * Allocating quota on disk if needed.
0881  *  the write transaction log space for quota file extent allocation
0882  *  the unit of quota allocation: one system block size
0883  */
0884 STATIC uint
0885 xfs_calc_qm_dqalloc_reservation(
0886     struct xfs_mount    *mp,
0887     bool            for_minlogsize)
0888 {
0889     return xfs_calc_write_reservation(mp, for_minlogsize) +
0890         xfs_calc_buf_res(1,
0891             XFS_FSB_TO_B(mp, XFS_DQUOT_CLUSTER_SIZE_FSB) - 1);
0892 }
0893 
0894 unsigned int
0895 xfs_calc_qm_dqalloc_reservation_minlogsize(
0896     struct xfs_mount    *mp)
0897 {
0898     return xfs_calc_qm_dqalloc_reservation(mp, true);
0899 }
0900 
0901 /*
0902  * Syncing the incore super block changes to disk.
0903  *     the super block to reflect the changes: sector size
0904  */
0905 STATIC uint
0906 xfs_calc_sb_reservation(
0907     struct xfs_mount    *mp)
0908 {
0909     return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
0910 }
0911 
0912 void
0913 xfs_trans_resv_calc(
0914     struct xfs_mount    *mp,
0915     struct xfs_trans_resv   *resp)
0916 {
0917     int         logcount_adj = 0;
0918 
0919     /*
0920      * The following transactions are logged in physical format and
0921      * require a permanent reservation on space.
0922      */
0923     resp->tr_write.tr_logres = xfs_calc_write_reservation(mp, false);
0924     resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
0925     resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0926 
0927     resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp, false);
0928     resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
0929     resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0930 
0931     resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp);
0932     resp->tr_rename.tr_logcount = XFS_RENAME_LOG_COUNT;
0933     resp->tr_rename.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0934 
0935     resp->tr_link.tr_logres = xfs_calc_link_reservation(mp);
0936     resp->tr_link.tr_logcount = XFS_LINK_LOG_COUNT;
0937     resp->tr_link.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0938 
0939     resp->tr_remove.tr_logres = xfs_calc_remove_reservation(mp);
0940     resp->tr_remove.tr_logcount = XFS_REMOVE_LOG_COUNT;
0941     resp->tr_remove.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0942 
0943     resp->tr_symlink.tr_logres = xfs_calc_symlink_reservation(mp);
0944     resp->tr_symlink.tr_logcount = XFS_SYMLINK_LOG_COUNT;
0945     resp->tr_symlink.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0946 
0947     resp->tr_create.tr_logres = xfs_calc_icreate_reservation(mp);
0948     resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT;
0949     resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0950 
0951     resp->tr_create_tmpfile.tr_logres =
0952             xfs_calc_create_tmpfile_reservation(mp);
0953     resp->tr_create_tmpfile.tr_logcount = XFS_CREATE_TMPFILE_LOG_COUNT;
0954     resp->tr_create_tmpfile.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0955 
0956     resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
0957     resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT;
0958     resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0959 
0960     resp->tr_ifree.tr_logres = xfs_calc_ifree_reservation(mp);
0961     resp->tr_ifree.tr_logcount = XFS_INACTIVE_LOG_COUNT;
0962     resp->tr_ifree.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0963 
0964     resp->tr_addafork.tr_logres = xfs_calc_addafork_reservation(mp);
0965     resp->tr_addafork.tr_logcount = XFS_ADDAFORK_LOG_COUNT;
0966     resp->tr_addafork.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0967 
0968     resp->tr_attrinval.tr_logres = xfs_calc_attrinval_reservation(mp);
0969     resp->tr_attrinval.tr_logcount = XFS_ATTRINVAL_LOG_COUNT;
0970     resp->tr_attrinval.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0971 
0972     resp->tr_attrsetm.tr_logres = xfs_calc_attrsetm_reservation(mp);
0973     resp->tr_attrsetm.tr_logcount = XFS_ATTRSET_LOG_COUNT;
0974     resp->tr_attrsetm.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0975 
0976     resp->tr_attrrm.tr_logres = xfs_calc_attrrm_reservation(mp);
0977     resp->tr_attrrm.tr_logcount = XFS_ATTRRM_LOG_COUNT;
0978     resp->tr_attrrm.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0979 
0980     resp->tr_growrtalloc.tr_logres = xfs_calc_growrtalloc_reservation(mp);
0981     resp->tr_growrtalloc.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT;
0982     resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0983 
0984     resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp,
0985             false);
0986     resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
0987     resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
0988 
0989     /*
0990      * The following transactions are logged in logical format with
0991      * a default log count.
0992      */
0993     resp->tr_qm_setqlim.tr_logres = xfs_calc_qm_setqlim_reservation();
0994     resp->tr_qm_setqlim.tr_logcount = XFS_DEFAULT_LOG_COUNT;
0995 
0996     resp->tr_sb.tr_logres = xfs_calc_sb_reservation(mp);
0997     resp->tr_sb.tr_logcount = XFS_DEFAULT_LOG_COUNT;
0998 
0999     /* growdata requires permanent res; it can free space to the last AG */
1000     resp->tr_growdata.tr_logres = xfs_calc_growdata_reservation(mp);
1001     resp->tr_growdata.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT;
1002     resp->tr_growdata.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1003 
1004     /* The following transaction are logged in logical format */
1005     resp->tr_ichange.tr_logres = xfs_calc_ichange_reservation(mp);
1006     resp->tr_fsyncts.tr_logres = xfs_calc_swrite_reservation(mp);
1007     resp->tr_writeid.tr_logres = xfs_calc_writeid_reservation(mp);
1008     resp->tr_attrsetrt.tr_logres = xfs_calc_attrsetrt_reservation(mp);
1009     resp->tr_clearagi.tr_logres = xfs_calc_clear_agi_bucket_reservation(mp);
1010     resp->tr_growrtzero.tr_logres = xfs_calc_growrtzero_reservation(mp);
1011     resp->tr_growrtfree.tr_logres = xfs_calc_growrtfree_reservation(mp);
1012 
1013     /*
1014      * Add one logcount for BUI items that appear with rmap or reflink,
1015      * one logcount for refcount intent items, and one logcount for rmap
1016      * intent items.
1017      */
1018     if (xfs_has_reflink(mp) || xfs_has_rmapbt(mp))
1019         logcount_adj++;
1020     if (xfs_has_reflink(mp))
1021         logcount_adj++;
1022     if (xfs_has_rmapbt(mp))
1023         logcount_adj++;
1024 
1025     resp->tr_itruncate.tr_logcount += logcount_adj;
1026     resp->tr_write.tr_logcount += logcount_adj;
1027     resp->tr_qm_dqalloc.tr_logcount += logcount_adj;
1028 }