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