]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/xfs/xfs_trans_resv.c
xfs: create xfs_bmap_util.[ch]
[karo-tx-linux.git] / fs / xfs / xfs_trans_resv.c
1 /*
2  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3  * Copyright (C) 2010 Red Hat, Inc.
4  * All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it would be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write the Free Software Foundation,
17  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 #include "xfs.h"
20 #include "xfs_fs.h"
21 #include "xfs_format.h"
22 #include "xfs_log.h"
23 #include "xfs_trans_resv.h"
24 #include "xfs_trans.h"
25 #include "xfs_sb.h"
26 #include "xfs_ag.h"
27 #include "xfs_mount.h"
28 #include "xfs_error.h"
29 #include "xfs_da_btree.h"
30 #include "xfs_bmap_btree.h"
31 #include "xfs_alloc_btree.h"
32 #include "xfs_ialloc_btree.h"
33 #include "xfs_dinode.h"
34 #include "xfs_inode.h"
35 #include "xfs_btree.h"
36 #include "xfs_ialloc.h"
37 #include "xfs_alloc.h"
38 #include "xfs_extent_busy.h"
39 #include "xfs_bmap.h"
40 #include "xfs_bmap_util.h"
41 #include "xfs_quota.h"
42 #include "xfs_qm.h"
43 #include "xfs_trans_space.h"
44 #include "xfs_trace.h"
45
46 /*
47  * A buffer has a format structure overhead in the log in addition
48  * to the data, so we need to take this into account when reserving
49  * space in a transaction for a buffer.  Round the space required up
50  * to a multiple of 128 bytes so that we don't change the historical
51  * reservation that has been used for this overhead.
52  */
53 STATIC uint
54 xfs_buf_log_overhead(void)
55 {
56         return round_up(sizeof(struct xlog_op_header) +
57                         sizeof(struct xfs_buf_log_format), 128);
58 }
59
60 /*
61  * Calculate out transaction log reservation per item in bytes.
62  *
63  * The nbufs argument is used to indicate the number of items that
64  * will be changed in a transaction.  size is used to tell how many
65  * bytes should be reserved per item.
66  */
67 STATIC uint
68 xfs_calc_buf_res(
69         uint            nbufs,
70         uint            size)
71 {
72         return nbufs * (size + xfs_buf_log_overhead());
73 }
74
75 /*
76  * Various log reservation values.
77  *
78  * These are based on the size of the file system block because that is what
79  * most transactions manipulate.  Each adds in an additional 128 bytes per
80  * item logged to try to account for the overhead of the transaction mechanism.
81  *
82  * Note:  Most of the reservations underestimate the number of allocation
83  * groups into which they could free extents in the xfs_bmap_finish() call.
84  * This is because the number in the worst case is quite high and quite
85  * unusual.  In order to fix this we need to change xfs_bmap_finish() to free
86  * extents in only a single AG at a time.  This will require changes to the
87  * EFI code as well, however, so that the EFI for the extents not freed is
88  * logged again in each transaction.  See SGI PV #261917.
89  *
90  * Reservation functions here avoid a huge stack in xfs_trans_init due to
91  * register overflow from temporaries in the calculations.
92  */
93
94
95 /*
96  * In a write transaction we can allocate a maximum of 2
97  * extents.  This gives:
98  *    the inode getting the new extents: inode size
99  *    the inode's bmap btree: max depth * block size
100  *    the agfs of the ags from which the extents are allocated: 2 * sector
101  *    the superblock free block counter: sector size
102  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
103  * And the bmap_finish transaction can free bmap blocks in a join:
104  *    the agfs of the ags containing the blocks: 2 * sector size
105  *    the agfls of the ags containing the blocks: 2 * sector size
106  *    the super block free block counter: sector size
107  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
108  */
109 STATIC uint
110 xfs_calc_write_reservation(
111         struct xfs_mount        *mp)
112 {
113         return XFS_DQUOT_LOGRES(mp) +
114                 MAX((xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) +
115                      xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
116                                       XFS_FSB_TO_B(mp, 1)) +
117                      xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
118                      xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
119                                       XFS_FSB_TO_B(mp, 1))),
120                     (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
121                      xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
122                                       XFS_FSB_TO_B(mp, 1))));
123 }
124
125 /*
126  * In truncating a file we free up to two extents at once.  We can modify:
127  *    the inode being truncated: inode size
128  *    the inode's bmap btree: (max depth + 1) * block size
129  * And the bmap_finish transaction can free the blocks and bmap blocks:
130  *    the agf for each of the ags: 4 * sector size
131  *    the agfl for each of the ags: 4 * sector size
132  *    the super block to reflect the freed blocks: sector size
133  *    worst case split in allocation btrees per extent assuming 4 extents:
134  *              4 exts * 2 trees * (2 * max depth - 1) * block size
135  *    the inode btree: max depth * blocksize
136  *    the allocation btrees: 2 trees * (max depth - 1) * block size
137  */
138 STATIC uint
139 xfs_calc_itruncate_reservation(
140         struct xfs_mount        *mp)
141 {
142         return XFS_DQUOT_LOGRES(mp) +
143                 MAX((xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) +
144                      xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1,
145                                       XFS_FSB_TO_B(mp, 1))),
146                     (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
147                      xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4),
148                                       XFS_FSB_TO_B(mp, 1)) +
149                     xfs_calc_buf_res(5, 0) +
150                     xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
151                                      XFS_FSB_TO_B(mp, 1)) +
152                     xfs_calc_buf_res(2 + XFS_IALLOC_BLOCKS(mp) +
153                                      mp->m_in_maxlevels, 0)));
154 }
155
156 /*
157  * In renaming a files we can modify:
158  *    the four inodes involved: 4 * inode size
159  *    the two directory btrees: 2 * (max depth + v2) * dir block size
160  *    the two directory bmap btrees: 2 * max depth * block size
161  * And the bmap_finish transaction can free dir and bmap blocks (two sets
162  *      of bmap blocks) giving:
163  *    the agf for the ags in which the blocks live: 3 * sector size
164  *    the agfl for the ags in which the blocks live: 3 * sector size
165  *    the superblock for the free block count: sector size
166  *    the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
167  */
168 STATIC uint
169 xfs_calc_rename_reservation(
170         struct xfs_mount        *mp)
171 {
172         return XFS_DQUOT_LOGRES(mp) +
173                 MAX((xfs_calc_buf_res(4, mp->m_sb.sb_inodesize) +
174                      xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp),
175                                       XFS_FSB_TO_B(mp, 1))),
176                     (xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) +
177                      xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 3),
178                                       XFS_FSB_TO_B(mp, 1))));
179 }
180
181 /*
182  * For creating a link to an inode:
183  *    the parent directory inode: inode size
184  *    the linked inode: inode size
185  *    the directory btree could split: (max depth + v2) * dir block size
186  *    the directory bmap btree could join or split: (max depth + v2) * blocksize
187  * And the bmap_finish transaction can free some bmap blocks giving:
188  *    the agf for the ag in which the blocks live: sector size
189  *    the agfl for the ag in which the blocks live: sector size
190  *    the superblock for the free block count: sector size
191  *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
192  */
193 STATIC uint
194 xfs_calc_link_reservation(
195         struct xfs_mount        *mp)
196 {
197         return XFS_DQUOT_LOGRES(mp) +
198                 MAX((xfs_calc_buf_res(2, mp->m_sb.sb_inodesize) +
199                      xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
200                                       XFS_FSB_TO_B(mp, 1))),
201                     (xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
202                      xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
203                                       XFS_FSB_TO_B(mp, 1))));
204 }
205
206 /*
207  * For removing a directory entry we can modify:
208  *    the parent directory inode: inode size
209  *    the removed inode: inode size
210  *    the directory btree could join: (max depth + v2) * dir block size
211  *    the directory bmap btree could join or split: (max depth + v2) * blocksize
212  * And the bmap_finish transaction can free the dir and bmap blocks giving:
213  *    the agf for the ag in which the blocks live: 2 * sector size
214  *    the agfl for the ag in which the blocks live: 2 * sector size
215  *    the superblock for the free block count: sector size
216  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
217  */
218 STATIC uint
219 xfs_calc_remove_reservation(
220         struct xfs_mount        *mp)
221 {
222         return XFS_DQUOT_LOGRES(mp) +
223                 MAX((xfs_calc_buf_res(2, mp->m_sb.sb_inodesize) +
224                      xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
225                                       XFS_FSB_TO_B(mp, 1))),
226                     (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
227                      xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
228                                       XFS_FSB_TO_B(mp, 1))));
229 }
230
231 /*
232  * For create, break it in to the two cases that the transaction
233  * covers. We start with the modify case - allocation done by modification
234  * of the state of existing inodes - and the allocation case.
235  */
236
237 /*
238  * For create we can modify:
239  *    the parent directory inode: inode size
240  *    the new inode: inode size
241  *    the inode btree entry: block size
242  *    the superblock for the nlink flag: sector size
243  *    the directory btree: (max depth + v2) * dir block size
244  *    the directory inode's bmap btree: (max depth + v2) * block size
245  */
246 STATIC uint
247 xfs_calc_create_resv_modify(
248         struct xfs_mount        *mp)
249 {
250         return xfs_calc_buf_res(2, mp->m_sb.sb_inodesize) +
251                 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
252                 (uint)XFS_FSB_TO_B(mp, 1) +
253                 xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1));
254 }
255
256 /*
257  * For create we can allocate some inodes giving:
258  *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
259  *    the superblock for the nlink flag: sector size
260  *    the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
261  *    the inode btree: max depth * blocksize
262  *    the allocation btrees: 2 trees * (max depth - 1) * block size
263  */
264 STATIC uint
265 xfs_calc_create_resv_alloc(
266         struct xfs_mount        *mp)
267 {
268         return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
269                 mp->m_sb.sb_sectsize +
270                 xfs_calc_buf_res(XFS_IALLOC_BLOCKS(mp), XFS_FSB_TO_B(mp, 1)) +
271                 xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) +
272                 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
273                                  XFS_FSB_TO_B(mp, 1));
274 }
275
276 STATIC uint
277 __xfs_calc_create_reservation(
278         struct xfs_mount        *mp)
279 {
280         return XFS_DQUOT_LOGRES(mp) +
281                 MAX(xfs_calc_create_resv_alloc(mp),
282                     xfs_calc_create_resv_modify(mp));
283 }
284
285 /*
286  * For icreate we can allocate some inodes giving:
287  *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
288  *    the superblock for the nlink flag: sector size
289  *    the inode btree: max depth * blocksize
290  *    the allocation btrees: 2 trees * (max depth - 1) * block size
291  */
292 STATIC uint
293 xfs_calc_icreate_resv_alloc(
294         struct xfs_mount        *mp)
295 {
296         return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
297                 mp->m_sb.sb_sectsize +
298                 xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) +
299                 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
300                                  XFS_FSB_TO_B(mp, 1));
301 }
302
303 STATIC uint
304 xfs_calc_icreate_reservation(xfs_mount_t *mp)
305 {
306         return XFS_DQUOT_LOGRES(mp) +
307                 MAX(xfs_calc_icreate_resv_alloc(mp),
308                     xfs_calc_create_resv_modify(mp));
309 }
310
311 STATIC uint
312 xfs_calc_create_reservation(
313         struct xfs_mount        *mp)
314 {
315         if (xfs_sb_version_hascrc(&mp->m_sb))
316                 return xfs_calc_icreate_reservation(mp);
317         return __xfs_calc_create_reservation(mp);
318
319 }
320
321 /*
322  * Making a new directory is the same as creating a new file.
323  */
324 STATIC uint
325 xfs_calc_mkdir_reservation(
326         struct xfs_mount        *mp)
327 {
328         return xfs_calc_create_reservation(mp);
329 }
330
331
332 /*
333  * Making a new symplink is the same as creating a new file, but
334  * with the added blocks for remote symlink data which can be up to 1kB in
335  * length (MAXPATHLEN).
336  */
337 STATIC uint
338 xfs_calc_symlink_reservation(
339         struct xfs_mount        *mp)
340 {
341         return xfs_calc_create_reservation(mp) +
342                xfs_calc_buf_res(1, MAXPATHLEN);
343 }
344
345 /*
346  * In freeing an inode we can modify:
347  *    the inode being freed: inode size
348  *    the super block free inode counter: sector size
349  *    the agi hash list and counters: sector size
350  *    the inode btree entry: block size
351  *    the on disk inode before ours in the agi hash list: inode cluster size
352  *    the inode btree: max depth * blocksize
353  *    the allocation btrees: 2 trees * (max depth - 1) * block size
354  */
355 STATIC uint
356 xfs_calc_ifree_reservation(
357         struct xfs_mount        *mp)
358 {
359         return XFS_DQUOT_LOGRES(mp) +
360                 xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) +
361                 xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
362                 xfs_calc_buf_res(1, XFS_FSB_TO_B(mp, 1)) +
363                 MAX((__uint16_t)XFS_FSB_TO_B(mp, 1),
364                     XFS_INODE_CLUSTER_SIZE(mp)) +
365                 xfs_calc_buf_res(1, 0) +
366                 xfs_calc_buf_res(2 + XFS_IALLOC_BLOCKS(mp) +
367                                  mp->m_in_maxlevels, 0) +
368                 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
369                                  XFS_FSB_TO_B(mp, 1));
370 }
371
372 /*
373  * When only changing the inode we log the inode and possibly the superblock
374  * We also add a bit of slop for the transaction stuff.
375  */
376 STATIC uint
377 xfs_calc_ichange_reservation(
378         struct xfs_mount        *mp)
379 {
380         return XFS_DQUOT_LOGRES(mp) +
381                 mp->m_sb.sb_inodesize +
382                 mp->m_sb.sb_sectsize +
383                 512;
384
385 }
386
387 /*
388  * Growing the data section of the filesystem.
389  *      superblock
390  *      agi and agf
391  *      allocation btrees
392  */
393 STATIC uint
394 xfs_calc_growdata_reservation(
395         struct xfs_mount        *mp)
396 {
397         return xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
398                 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
399                                  XFS_FSB_TO_B(mp, 1));
400 }
401
402 /*
403  * Growing the rt section of the filesystem.
404  * In the first set of transactions (ALLOC) we allocate space to the
405  * bitmap or summary files.
406  *      superblock: sector size
407  *      agf of the ag from which the extent is allocated: sector size
408  *      bmap btree for bitmap/summary inode: max depth * blocksize
409  *      bitmap/summary inode: inode size
410  *      allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
411  */
412 STATIC uint
413 xfs_calc_growrtalloc_reservation(
414         struct xfs_mount        *mp)
415 {
416         return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
417                 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
418                                  XFS_FSB_TO_B(mp, 1)) +
419                 xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) +
420                 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
421                                  XFS_FSB_TO_B(mp, 1));
422 }
423
424 /*
425  * Growing the rt section of the filesystem.
426  * In the second set of transactions (ZERO) we zero the new metadata blocks.
427  *      one bitmap/summary block: blocksize
428  */
429 STATIC uint
430 xfs_calc_growrtzero_reservation(
431         struct xfs_mount        *mp)
432 {
433         return xfs_calc_buf_res(1, mp->m_sb.sb_blocksize);
434 }
435
436 /*
437  * Growing the rt section of the filesystem.
438  * In the third set of transactions (FREE) we update metadata without
439  * allocating any new blocks.
440  *      superblock: sector size
441  *      bitmap inode: inode size
442  *      summary inode: inode size
443  *      one bitmap block: blocksize
444  *      summary blocks: new summary size
445  */
446 STATIC uint
447 xfs_calc_growrtfree_reservation(
448         struct xfs_mount        *mp)
449 {
450         return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
451                 xfs_calc_buf_res(2, mp->m_sb.sb_inodesize) +
452                 xfs_calc_buf_res(1, mp->m_sb.sb_blocksize) +
453                 xfs_calc_buf_res(1, mp->m_rsumsize);
454 }
455
456 /*
457  * Logging the inode modification timestamp on a synchronous write.
458  *      inode
459  */
460 STATIC uint
461 xfs_calc_swrite_reservation(
462         struct xfs_mount        *mp)
463 {
464         return xfs_calc_buf_res(1, mp->m_sb.sb_inodesize);
465 }
466
467 /*
468  * Logging the inode mode bits when writing a setuid/setgid file
469  *      inode
470  */
471 STATIC uint
472 xfs_calc_writeid_reservation(xfs_mount_t *mp)
473 {
474         return xfs_calc_buf_res(1, mp->m_sb.sb_inodesize);
475 }
476
477 /*
478  * Converting the inode from non-attributed to attributed.
479  *      the inode being converted: inode size
480  *      agf block and superblock (for block allocation)
481  *      the new block (directory sized)
482  *      bmap blocks for the new directory block
483  *      allocation btrees
484  */
485 STATIC uint
486 xfs_calc_addafork_reservation(
487         struct xfs_mount        *mp)
488 {
489         return XFS_DQUOT_LOGRES(mp) +
490                 xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) +
491                 xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
492                 xfs_calc_buf_res(1, mp->m_dirblksize) +
493                 xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1,
494                                  XFS_FSB_TO_B(mp, 1)) +
495                 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
496                                  XFS_FSB_TO_B(mp, 1));
497 }
498
499 /*
500  * Removing the attribute fork of a file
501  *    the inode being truncated: inode size
502  *    the inode's bmap btree: max depth * block size
503  * And the bmap_finish transaction can free the blocks and bmap blocks:
504  *    the agf for each of the ags: 4 * sector size
505  *    the agfl for each of the ags: 4 * sector size
506  *    the super block to reflect the freed blocks: sector size
507  *    worst case split in allocation btrees per extent assuming 4 extents:
508  *              4 exts * 2 trees * (2 * max depth - 1) * block size
509  */
510 STATIC uint
511 xfs_calc_attrinval_reservation(
512         struct xfs_mount        *mp)
513 {
514         return MAX((xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) +
515                     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
516                                      XFS_FSB_TO_B(mp, 1))),
517                    (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
518                     xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4),
519                                      XFS_FSB_TO_B(mp, 1))));
520 }
521
522 /*
523  * Setting an attribute at mount time.
524  *      the inode getting the attribute
525  *      the superblock for allocations
526  *      the agfs extents are allocated from
527  *      the attribute btree * max depth
528  *      the inode allocation btree
529  * Since attribute transaction space is dependent on the size of the attribute,
530  * the calculation is done partially at mount time and partially at runtime(see
531  * below).
532  */
533 STATIC uint
534 xfs_calc_attrsetm_reservation(
535         struct xfs_mount        *mp)
536 {
537         return XFS_DQUOT_LOGRES(mp) +
538                 xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) +
539                 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
540                 xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, XFS_FSB_TO_B(mp, 1));
541 }
542
543 /*
544  * Setting an attribute at runtime, transaction space unit per block.
545  *      the superblock for allocations: sector size
546  *      the inode bmap btree could join or split: max depth * block size
547  * Since the runtime attribute transaction space is dependent on the total
548  * blocks needed for the 1st bmap, here we calculate out the space unit for
549  * one block so that the caller could figure out the total space according
550  * to the attibute extent length in blocks by: ext * XFS_ATTRSETRT_LOG_RES(mp).
551  */
552 STATIC uint
553 xfs_calc_attrsetrt_reservation(
554         struct xfs_mount        *mp)
555 {
556         return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
557                 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
558                                  XFS_FSB_TO_B(mp, 1));
559 }
560
561 /*
562  * Removing an attribute.
563  *    the inode: inode size
564  *    the attribute btree could join: max depth * block size
565  *    the inode bmap btree could join or split: max depth * block size
566  * And the bmap_finish transaction can free the attr blocks freed giving:
567  *    the agf for the ag in which the blocks live: 2 * sector size
568  *    the agfl for the ag in which the blocks live: 2 * sector size
569  *    the superblock for the free block count: sector size
570  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
571  */
572 STATIC uint
573 xfs_calc_attrrm_reservation(
574         struct xfs_mount        *mp)
575 {
576         return XFS_DQUOT_LOGRES(mp) +
577                 MAX((xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) +
578                      xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH,
579                                       XFS_FSB_TO_B(mp, 1)) +
580                      (uint)XFS_FSB_TO_B(mp,
581                                         XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
582                      xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)),
583                     (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
584                      xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
585                                       XFS_FSB_TO_B(mp, 1))));
586 }
587
588 /*
589  * Clearing a bad agino number in an agi hash bucket.
590  */
591 STATIC uint
592 xfs_calc_clear_agi_bucket_reservation(
593         struct xfs_mount        *mp)
594 {
595         return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
596 }
597
598 /*
599  * Clearing the quotaflags in the superblock.
600  *      the super block for changing quota flags: sector size
601  */
602 STATIC uint
603 xfs_calc_qm_sbchange_reservation(
604         struct xfs_mount        *mp)
605 {
606         return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
607 }
608
609 /*
610  * Adjusting quota limits.
611  *    the xfs_disk_dquot_t: sizeof(struct xfs_disk_dquot)
612  */
613 STATIC uint
614 xfs_calc_qm_setqlim_reservation(
615         struct xfs_mount        *mp)
616 {
617         return xfs_calc_buf_res(1, sizeof(struct xfs_disk_dquot));
618 }
619
620 /*
621  * Allocating quota on disk if needed.
622  *      the write transaction log space: XFS_WRITE_LOG_RES(mp)
623  *      the unit of quota allocation: one system block size
624  */
625 STATIC uint
626 xfs_calc_qm_dqalloc_reservation(
627         struct xfs_mount        *mp)
628 {
629         return XFS_WRITE_LOG_RES(mp) +
630                 xfs_calc_buf_res(1,
631                         XFS_FSB_TO_B(mp, XFS_DQUOT_CLUSTER_SIZE_FSB) - 1);
632 }
633
634 /*
635  * Turning off quotas.
636  *    the xfs_qoff_logitem_t: sizeof(struct xfs_qoff_logitem) * 2
637  *    the superblock for the quota flags: sector size
638  */
639 STATIC uint
640 xfs_calc_qm_quotaoff_reservation(
641         struct xfs_mount        *mp)
642 {
643         return sizeof(struct xfs_qoff_logitem) * 2 +
644                 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
645 }
646
647 /*
648  * End of turning off quotas.
649  *    the xfs_qoff_logitem_t: sizeof(struct xfs_qoff_logitem) * 2
650  */
651 STATIC uint
652 xfs_calc_qm_quotaoff_end_reservation(
653         struct xfs_mount        *mp)
654 {
655         return sizeof(struct xfs_qoff_logitem) * 2;
656 }
657
658 /*
659  * Syncing the incore super block changes to disk.
660  *     the super block to reflect the changes: sector size
661  */
662 STATIC uint
663 xfs_calc_sb_reservation(
664         struct xfs_mount        *mp)
665 {
666         return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
667 }
668
669 void
670 xfs_trans_resv_calc(
671         struct xfs_mount        *mp,
672         struct xfs_trans_resv   *resp)
673 {
674         resp->tr_write = xfs_calc_write_reservation(mp);
675         resp->tr_itruncate = xfs_calc_itruncate_reservation(mp);
676         resp->tr_rename = xfs_calc_rename_reservation(mp);
677         resp->tr_link = xfs_calc_link_reservation(mp);
678         resp->tr_remove = xfs_calc_remove_reservation(mp);
679         resp->tr_symlink = xfs_calc_symlink_reservation(mp);
680         resp->tr_create = xfs_calc_create_reservation(mp);
681         resp->tr_mkdir = xfs_calc_mkdir_reservation(mp);
682         resp->tr_ifree = xfs_calc_ifree_reservation(mp);
683         resp->tr_ichange = xfs_calc_ichange_reservation(mp);
684         resp->tr_growdata = xfs_calc_growdata_reservation(mp);
685         resp->tr_swrite = xfs_calc_swrite_reservation(mp);
686         resp->tr_writeid = xfs_calc_writeid_reservation(mp);
687         resp->tr_addafork = xfs_calc_addafork_reservation(mp);
688         resp->tr_attrinval = xfs_calc_attrinval_reservation(mp);
689         resp->tr_attrsetm = xfs_calc_attrsetm_reservation(mp);
690         resp->tr_attrsetrt = xfs_calc_attrsetrt_reservation(mp);
691         resp->tr_attrrm = xfs_calc_attrrm_reservation(mp);
692         resp->tr_clearagi = xfs_calc_clear_agi_bucket_reservation(mp);
693         resp->tr_growrtalloc = xfs_calc_growrtalloc_reservation(mp);
694         resp->tr_growrtzero = xfs_calc_growrtzero_reservation(mp);
695         resp->tr_growrtfree = xfs_calc_growrtfree_reservation(mp);
696         resp->tr_qm_sbchange = xfs_calc_qm_sbchange_reservation(mp);
697         resp->tr_qm_setqlim = xfs_calc_qm_setqlim_reservation(mp);
698         resp->tr_qm_dqalloc = xfs_calc_qm_dqalloc_reservation(mp);
699         resp->tr_qm_quotaoff = xfs_calc_qm_quotaoff_reservation(mp);
700         resp->tr_qm_equotaoff = xfs_calc_qm_quotaoff_end_reservation(mp);
701         resp->tr_sb = xfs_calc_sb_reservation(mp);
702 }