xref: /linux/fs/xfs/xfs_trans.c (revision d9457dc056249913a7abe8b71dc09e427e590e35)
11da177e4SLinus Torvalds /*
27b718769SNathan Scott  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3e98c414fSChristoph Hellwig  * Copyright (C) 2010 Red Hat, Inc.
47b718769SNathan Scott  * All Rights Reserved.
51da177e4SLinus Torvalds  *
67b718769SNathan Scott  * This program is free software; you can redistribute it and/or
77b718769SNathan Scott  * modify it under the terms of the GNU General Public License as
81da177e4SLinus Torvalds  * published by the Free Software Foundation.
91da177e4SLinus Torvalds  *
107b718769SNathan Scott  * This program is distributed in the hope that it would be useful,
117b718769SNathan Scott  * but WITHOUT ANY WARRANTY; without even the implied warranty of
127b718769SNathan Scott  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
137b718769SNathan Scott  * GNU General Public License for more details.
141da177e4SLinus Torvalds  *
157b718769SNathan Scott  * You should have received a copy of the GNU General Public License
167b718769SNathan Scott  * along with this program; if not, write the Free Software Foundation,
177b718769SNathan Scott  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
181da177e4SLinus Torvalds  */
191da177e4SLinus Torvalds #include "xfs.h"
20a844f451SNathan Scott #include "xfs_fs.h"
211da177e4SLinus Torvalds #include "xfs_types.h"
221da177e4SLinus Torvalds #include "xfs_log.h"
231da177e4SLinus Torvalds #include "xfs_trans.h"
241da177e4SLinus Torvalds #include "xfs_sb.h"
251da177e4SLinus Torvalds #include "xfs_ag.h"
261da177e4SLinus Torvalds #include "xfs_mount.h"
271da177e4SLinus Torvalds #include "xfs_error.h"
28a844f451SNathan Scott #include "xfs_da_btree.h"
291da177e4SLinus Torvalds #include "xfs_bmap_btree.h"
30a844f451SNathan Scott #include "xfs_alloc_btree.h"
311da177e4SLinus Torvalds #include "xfs_ialloc_btree.h"
32a844f451SNathan Scott #include "xfs_dinode.h"
33a844f451SNathan Scott #include "xfs_inode.h"
341da177e4SLinus Torvalds #include "xfs_btree.h"
351da177e4SLinus Torvalds #include "xfs_ialloc.h"
361da177e4SLinus Torvalds #include "xfs_alloc.h"
37efc27b52SDave Chinner #include "xfs_extent_busy.h"
381da177e4SLinus Torvalds #include "xfs_bmap.h"
391da177e4SLinus Torvalds #include "xfs_quota.h"
40a844f451SNathan Scott #include "xfs_trans_priv.h"
411da177e4SLinus Torvalds #include "xfs_trans_space.h"
42322ff6b8SNiv Sardi #include "xfs_inode_item.h"
43ed3b4d6cSDave Chinner #include "xfs_trace.h"
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds kmem_zone_t	*xfs_trans_zone;
46e98c414fSChristoph Hellwig kmem_zone_t	*xfs_log_item_desc_zone;
471da177e4SLinus Torvalds 
48025101dcSChristoph Hellwig 
491da177e4SLinus Torvalds /*
50025101dcSChristoph Hellwig  * Various log reservation values.
51025101dcSChristoph Hellwig  *
52025101dcSChristoph Hellwig  * These are based on the size of the file system block because that is what
53025101dcSChristoph Hellwig  * most transactions manipulate.  Each adds in an additional 128 bytes per
54025101dcSChristoph Hellwig  * item logged to try to account for the overhead of the transaction mechanism.
55025101dcSChristoph Hellwig  *
56025101dcSChristoph Hellwig  * Note:  Most of the reservations underestimate the number of allocation
57025101dcSChristoph Hellwig  * groups into which they could free extents in the xfs_bmap_finish() call.
58025101dcSChristoph Hellwig  * This is because the number in the worst case is quite high and quite
59025101dcSChristoph Hellwig  * unusual.  In order to fix this we need to change xfs_bmap_finish() to free
60025101dcSChristoph Hellwig  * extents in only a single AG at a time.  This will require changes to the
61025101dcSChristoph Hellwig  * EFI code as well, however, so that the EFI for the extents not freed is
62025101dcSChristoph Hellwig  * logged again in each transaction.  See SGI PV #261917.
63025101dcSChristoph Hellwig  *
64025101dcSChristoph Hellwig  * Reservation functions here avoid a huge stack in xfs_trans_init due to
65025101dcSChristoph Hellwig  * register overflow from temporaries in the calculations.
66025101dcSChristoph Hellwig  */
67025101dcSChristoph Hellwig 
68025101dcSChristoph Hellwig 
69025101dcSChristoph Hellwig /*
70025101dcSChristoph Hellwig  * In a write transaction we can allocate a maximum of 2
71025101dcSChristoph Hellwig  * extents.  This gives:
72025101dcSChristoph Hellwig  *    the inode getting the new extents: inode size
73025101dcSChristoph Hellwig  *    the inode's bmap btree: max depth * block size
74025101dcSChristoph Hellwig  *    the agfs of the ags from which the extents are allocated: 2 * sector
75025101dcSChristoph Hellwig  *    the superblock free block counter: sector size
76025101dcSChristoph Hellwig  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
77025101dcSChristoph Hellwig  * And the bmap_finish transaction can free bmap blocks in a join:
78025101dcSChristoph Hellwig  *    the agfs of the ags containing the blocks: 2 * sector size
79025101dcSChristoph Hellwig  *    the agfls of the ags containing the blocks: 2 * sector size
80025101dcSChristoph Hellwig  *    the super block free block counter: sector size
81025101dcSChristoph Hellwig  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
828f794055SNathan Scott  */
838f794055SNathan Scott STATIC uint
84025101dcSChristoph Hellwig xfs_calc_write_reservation(
85025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
868f794055SNathan Scott {
87025101dcSChristoph Hellwig 	return XFS_DQUOT_LOGRES(mp) +
88025101dcSChristoph Hellwig 		MAX((mp->m_sb.sb_inodesize +
89025101dcSChristoph Hellwig 		     XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) +
90025101dcSChristoph Hellwig 		     2 * mp->m_sb.sb_sectsize +
91025101dcSChristoph Hellwig 		     mp->m_sb.sb_sectsize +
92025101dcSChristoph Hellwig 		     XFS_ALLOCFREE_LOG_RES(mp, 2) +
93025101dcSChristoph Hellwig 		     128 * (4 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) +
94025101dcSChristoph Hellwig 			    XFS_ALLOCFREE_LOG_COUNT(mp, 2))),
95025101dcSChristoph Hellwig 		    (2 * mp->m_sb.sb_sectsize +
96025101dcSChristoph Hellwig 		     2 * mp->m_sb.sb_sectsize +
97025101dcSChristoph Hellwig 		     mp->m_sb.sb_sectsize +
98025101dcSChristoph Hellwig 		     XFS_ALLOCFREE_LOG_RES(mp, 2) +
99025101dcSChristoph Hellwig 		     128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
1008f794055SNathan Scott }
1018f794055SNathan Scott 
102025101dcSChristoph Hellwig /*
103025101dcSChristoph Hellwig  * In truncating a file we free up to two extents at once.  We can modify:
104025101dcSChristoph Hellwig  *    the inode being truncated: inode size
105025101dcSChristoph Hellwig  *    the inode's bmap btree: (max depth + 1) * block size
106025101dcSChristoph Hellwig  * And the bmap_finish transaction can free the blocks and bmap blocks:
107025101dcSChristoph Hellwig  *    the agf for each of the ags: 4 * sector size
108025101dcSChristoph Hellwig  *    the agfl for each of the ags: 4 * sector size
109025101dcSChristoph Hellwig  *    the super block to reflect the freed blocks: sector size
110025101dcSChristoph Hellwig  *    worst case split in allocation btrees per extent assuming 4 extents:
111025101dcSChristoph Hellwig  *		4 exts * 2 trees * (2 * max depth - 1) * block size
112025101dcSChristoph Hellwig  *    the inode btree: max depth * blocksize
113025101dcSChristoph Hellwig  *    the allocation btrees: 2 trees * (max depth - 1) * block size
114025101dcSChristoph Hellwig  */
1158f794055SNathan Scott STATIC uint
116025101dcSChristoph Hellwig xfs_calc_itruncate_reservation(
117025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
1188f794055SNathan Scott {
119025101dcSChristoph Hellwig 	return XFS_DQUOT_LOGRES(mp) +
120025101dcSChristoph Hellwig 		MAX((mp->m_sb.sb_inodesize +
121025101dcSChristoph Hellwig 		     XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1) +
122025101dcSChristoph Hellwig 		     128 * (2 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))),
123025101dcSChristoph Hellwig 		    (4 * mp->m_sb.sb_sectsize +
124025101dcSChristoph Hellwig 		     4 * mp->m_sb.sb_sectsize +
125025101dcSChristoph Hellwig 		     mp->m_sb.sb_sectsize +
126025101dcSChristoph Hellwig 		     XFS_ALLOCFREE_LOG_RES(mp, 4) +
127025101dcSChristoph Hellwig 		     128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4)) +
128025101dcSChristoph Hellwig 		     128 * 5 +
129025101dcSChristoph Hellwig 		     XFS_ALLOCFREE_LOG_RES(mp, 1) +
130025101dcSChristoph Hellwig 		     128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
131025101dcSChristoph Hellwig 			    XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
1328f794055SNathan Scott }
1338f794055SNathan Scott 
134025101dcSChristoph Hellwig /*
135025101dcSChristoph Hellwig  * In renaming a files we can modify:
136025101dcSChristoph Hellwig  *    the four inodes involved: 4 * inode size
137025101dcSChristoph Hellwig  *    the two directory btrees: 2 * (max depth + v2) * dir block size
138025101dcSChristoph Hellwig  *    the two directory bmap btrees: 2 * max depth * block size
139025101dcSChristoph Hellwig  * And the bmap_finish transaction can free dir and bmap blocks (two sets
140025101dcSChristoph Hellwig  *	of bmap blocks) giving:
141025101dcSChristoph Hellwig  *    the agf for the ags in which the blocks live: 3 * sector size
142025101dcSChristoph Hellwig  *    the agfl for the ags in which the blocks live: 3 * sector size
143025101dcSChristoph Hellwig  *    the superblock for the free block count: sector size
144025101dcSChristoph Hellwig  *    the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
145025101dcSChristoph Hellwig  */
1468f794055SNathan Scott STATIC uint
147025101dcSChristoph Hellwig xfs_calc_rename_reservation(
148025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
1498f794055SNathan Scott {
150025101dcSChristoph Hellwig 	return XFS_DQUOT_LOGRES(mp) +
151025101dcSChristoph Hellwig 		MAX((4 * mp->m_sb.sb_inodesize +
152025101dcSChristoph Hellwig 		     2 * XFS_DIROP_LOG_RES(mp) +
153025101dcSChristoph Hellwig 		     128 * (4 + 2 * XFS_DIROP_LOG_COUNT(mp))),
154025101dcSChristoph Hellwig 		    (3 * mp->m_sb.sb_sectsize +
155025101dcSChristoph Hellwig 		     3 * mp->m_sb.sb_sectsize +
156025101dcSChristoph Hellwig 		     mp->m_sb.sb_sectsize +
157025101dcSChristoph Hellwig 		     XFS_ALLOCFREE_LOG_RES(mp, 3) +
158025101dcSChristoph Hellwig 		     128 * (7 + XFS_ALLOCFREE_LOG_COUNT(mp, 3))));
1598f794055SNathan Scott }
1608f794055SNathan Scott 
161025101dcSChristoph Hellwig /*
162025101dcSChristoph Hellwig  * For creating a link to an inode:
163025101dcSChristoph Hellwig  *    the parent directory inode: inode size
164025101dcSChristoph Hellwig  *    the linked inode: inode size
165025101dcSChristoph Hellwig  *    the directory btree could split: (max depth + v2) * dir block size
166025101dcSChristoph Hellwig  *    the directory bmap btree could join or split: (max depth + v2) * blocksize
167025101dcSChristoph Hellwig  * And the bmap_finish transaction can free some bmap blocks giving:
168025101dcSChristoph Hellwig  *    the agf for the ag in which the blocks live: sector size
169025101dcSChristoph Hellwig  *    the agfl for the ag in which the blocks live: sector size
170025101dcSChristoph Hellwig  *    the superblock for the free block count: sector size
171025101dcSChristoph Hellwig  *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
172025101dcSChristoph Hellwig  */
1738f794055SNathan Scott STATIC uint
174025101dcSChristoph Hellwig xfs_calc_link_reservation(
175025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
1768f794055SNathan Scott {
177025101dcSChristoph Hellwig 	return XFS_DQUOT_LOGRES(mp) +
178025101dcSChristoph Hellwig 		MAX((mp->m_sb.sb_inodesize +
179025101dcSChristoph Hellwig 		     mp->m_sb.sb_inodesize +
180025101dcSChristoph Hellwig 		     XFS_DIROP_LOG_RES(mp) +
181025101dcSChristoph Hellwig 		     128 * (2 + XFS_DIROP_LOG_COUNT(mp))),
182025101dcSChristoph Hellwig 		    (mp->m_sb.sb_sectsize +
183025101dcSChristoph Hellwig 		     mp->m_sb.sb_sectsize +
184025101dcSChristoph Hellwig 		     mp->m_sb.sb_sectsize +
185025101dcSChristoph Hellwig 		     XFS_ALLOCFREE_LOG_RES(mp, 1) +
186025101dcSChristoph Hellwig 		     128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
1878f794055SNathan Scott }
1888f794055SNathan Scott 
189025101dcSChristoph Hellwig /*
190025101dcSChristoph Hellwig  * For removing a directory entry we can modify:
191025101dcSChristoph Hellwig  *    the parent directory inode: inode size
192025101dcSChristoph Hellwig  *    the removed inode: inode size
193025101dcSChristoph Hellwig  *    the directory btree could join: (max depth + v2) * dir block size
194025101dcSChristoph Hellwig  *    the directory bmap btree could join or split: (max depth + v2) * blocksize
195025101dcSChristoph Hellwig  * And the bmap_finish transaction can free the dir and bmap blocks giving:
196025101dcSChristoph Hellwig  *    the agf for the ag in which the blocks live: 2 * sector size
197025101dcSChristoph Hellwig  *    the agfl for the ag in which the blocks live: 2 * sector size
198025101dcSChristoph Hellwig  *    the superblock for the free block count: sector size
199025101dcSChristoph Hellwig  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
200025101dcSChristoph Hellwig  */
2018f794055SNathan Scott STATIC uint
202025101dcSChristoph Hellwig xfs_calc_remove_reservation(
203025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
2048f794055SNathan Scott {
205025101dcSChristoph Hellwig 	return XFS_DQUOT_LOGRES(mp) +
206025101dcSChristoph Hellwig 		MAX((mp->m_sb.sb_inodesize +
207025101dcSChristoph Hellwig 		     mp->m_sb.sb_inodesize +
208025101dcSChristoph Hellwig 		     XFS_DIROP_LOG_RES(mp) +
209025101dcSChristoph Hellwig 		     128 * (2 + XFS_DIROP_LOG_COUNT(mp))),
210025101dcSChristoph Hellwig 		    (2 * mp->m_sb.sb_sectsize +
211025101dcSChristoph Hellwig 		     2 * mp->m_sb.sb_sectsize +
212025101dcSChristoph Hellwig 		     mp->m_sb.sb_sectsize +
213025101dcSChristoph Hellwig 		     XFS_ALLOCFREE_LOG_RES(mp, 2) +
214025101dcSChristoph Hellwig 		     128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
2158f794055SNathan Scott }
2168f794055SNathan Scott 
217025101dcSChristoph Hellwig /*
218025101dcSChristoph Hellwig  * For symlink we can modify:
219025101dcSChristoph Hellwig  *    the parent directory inode: inode size
220025101dcSChristoph Hellwig  *    the new inode: inode size
221025101dcSChristoph Hellwig  *    the inode btree entry: 1 block
222025101dcSChristoph Hellwig  *    the directory btree: (max depth + v2) * dir block size
223025101dcSChristoph Hellwig  *    the directory inode's bmap btree: (max depth + v2) * block size
224025101dcSChristoph Hellwig  *    the blocks for the symlink: 1 kB
225025101dcSChristoph Hellwig  * Or in the first xact we allocate some inodes giving:
226025101dcSChristoph Hellwig  *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
227025101dcSChristoph Hellwig  *    the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
228025101dcSChristoph Hellwig  *    the inode btree: max depth * blocksize
229025101dcSChristoph Hellwig  *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
230025101dcSChristoph Hellwig  */
2318f794055SNathan Scott STATIC uint
232025101dcSChristoph Hellwig xfs_calc_symlink_reservation(
233025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
2348f794055SNathan Scott {
235025101dcSChristoph Hellwig 	return XFS_DQUOT_LOGRES(mp) +
236025101dcSChristoph Hellwig 		MAX((mp->m_sb.sb_inodesize +
237025101dcSChristoph Hellwig 		     mp->m_sb.sb_inodesize +
238025101dcSChristoph Hellwig 		     XFS_FSB_TO_B(mp, 1) +
239025101dcSChristoph Hellwig 		     XFS_DIROP_LOG_RES(mp) +
240025101dcSChristoph Hellwig 		     1024 +
241025101dcSChristoph Hellwig 		     128 * (4 + XFS_DIROP_LOG_COUNT(mp))),
242025101dcSChristoph Hellwig 		    (2 * mp->m_sb.sb_sectsize +
243025101dcSChristoph Hellwig 		     XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) +
244025101dcSChristoph Hellwig 		     XFS_FSB_TO_B(mp, mp->m_in_maxlevels) +
245025101dcSChristoph Hellwig 		     XFS_ALLOCFREE_LOG_RES(mp, 1) +
246025101dcSChristoph Hellwig 		     128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
247025101dcSChristoph Hellwig 			    XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
2488f794055SNathan Scott }
2498f794055SNathan Scott 
250025101dcSChristoph Hellwig /*
251025101dcSChristoph Hellwig  * For create we can modify:
252025101dcSChristoph Hellwig  *    the parent directory inode: inode size
253025101dcSChristoph Hellwig  *    the new inode: inode size
254025101dcSChristoph Hellwig  *    the inode btree entry: block size
255025101dcSChristoph Hellwig  *    the superblock for the nlink flag: sector size
256025101dcSChristoph Hellwig  *    the directory btree: (max depth + v2) * dir block size
257025101dcSChristoph Hellwig  *    the directory inode's bmap btree: (max depth + v2) * block size
258025101dcSChristoph Hellwig  * Or in the first xact we allocate some inodes giving:
259025101dcSChristoph Hellwig  *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
260025101dcSChristoph Hellwig  *    the superblock for the nlink flag: sector size
261025101dcSChristoph Hellwig  *    the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
262025101dcSChristoph Hellwig  *    the inode btree: max depth * blocksize
263025101dcSChristoph Hellwig  *    the allocation btrees: 2 trees * (max depth - 1) * block size
264025101dcSChristoph Hellwig  */
2658f794055SNathan Scott STATIC uint
266025101dcSChristoph Hellwig xfs_calc_create_reservation(
267025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
2688f794055SNathan Scott {
269025101dcSChristoph Hellwig 	return XFS_DQUOT_LOGRES(mp) +
270025101dcSChristoph Hellwig 		MAX((mp->m_sb.sb_inodesize +
271025101dcSChristoph Hellwig 		     mp->m_sb.sb_inodesize +
272025101dcSChristoph Hellwig 		     mp->m_sb.sb_sectsize +
273025101dcSChristoph Hellwig 		     XFS_FSB_TO_B(mp, 1) +
274025101dcSChristoph Hellwig 		     XFS_DIROP_LOG_RES(mp) +
275025101dcSChristoph Hellwig 		     128 * (3 + XFS_DIROP_LOG_COUNT(mp))),
276025101dcSChristoph Hellwig 		    (3 * mp->m_sb.sb_sectsize +
277025101dcSChristoph Hellwig 		     XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) +
278025101dcSChristoph Hellwig 		     XFS_FSB_TO_B(mp, mp->m_in_maxlevels) +
279025101dcSChristoph Hellwig 		     XFS_ALLOCFREE_LOG_RES(mp, 1) +
280025101dcSChristoph Hellwig 		     128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
281025101dcSChristoph Hellwig 			    XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
2828f794055SNathan Scott }
2838f794055SNathan Scott 
284025101dcSChristoph Hellwig /*
285025101dcSChristoph Hellwig  * Making a new directory is the same as creating a new file.
286025101dcSChristoph Hellwig  */
2878f794055SNathan Scott STATIC uint
288025101dcSChristoph Hellwig xfs_calc_mkdir_reservation(
289025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
2908f794055SNathan Scott {
291025101dcSChristoph Hellwig 	return xfs_calc_create_reservation(mp);
2928f794055SNathan Scott }
2938f794055SNathan Scott 
294025101dcSChristoph Hellwig /*
295025101dcSChristoph Hellwig  * In freeing an inode we can modify:
296025101dcSChristoph Hellwig  *    the inode being freed: inode size
297025101dcSChristoph Hellwig  *    the super block free inode counter: sector size
298025101dcSChristoph Hellwig  *    the agi hash list and counters: sector size
299025101dcSChristoph Hellwig  *    the inode btree entry: block size
300025101dcSChristoph Hellwig  *    the on disk inode before ours in the agi hash list: inode cluster size
301025101dcSChristoph Hellwig  *    the inode btree: max depth * blocksize
302025101dcSChristoph Hellwig  *    the allocation btrees: 2 trees * (max depth - 1) * block size
303025101dcSChristoph Hellwig  */
3048f794055SNathan Scott STATIC uint
305025101dcSChristoph Hellwig xfs_calc_ifree_reservation(
306025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
3078f794055SNathan Scott {
308025101dcSChristoph Hellwig 	return XFS_DQUOT_LOGRES(mp) +
309025101dcSChristoph Hellwig 		mp->m_sb.sb_inodesize +
310025101dcSChristoph Hellwig 		mp->m_sb.sb_sectsize +
311025101dcSChristoph Hellwig 		mp->m_sb.sb_sectsize +
312025101dcSChristoph Hellwig 		XFS_FSB_TO_B(mp, 1) +
313025101dcSChristoph Hellwig 		MAX((__uint16_t)XFS_FSB_TO_B(mp, 1),
314025101dcSChristoph Hellwig 		    XFS_INODE_CLUSTER_SIZE(mp)) +
315025101dcSChristoph Hellwig 		128 * 5 +
316025101dcSChristoph Hellwig 		XFS_ALLOCFREE_LOG_RES(mp, 1) +
317025101dcSChristoph Hellwig 		128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
318025101dcSChristoph Hellwig 		       XFS_ALLOCFREE_LOG_COUNT(mp, 1));
3198f794055SNathan Scott }
3208f794055SNathan Scott 
321025101dcSChristoph Hellwig /*
322025101dcSChristoph Hellwig  * When only changing the inode we log the inode and possibly the superblock
323025101dcSChristoph Hellwig  * We also add a bit of slop for the transaction stuff.
324025101dcSChristoph Hellwig  */
3258f794055SNathan Scott STATIC uint
326025101dcSChristoph Hellwig xfs_calc_ichange_reservation(
327025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
3288f794055SNathan Scott {
329025101dcSChristoph Hellwig 	return XFS_DQUOT_LOGRES(mp) +
330025101dcSChristoph Hellwig 		mp->m_sb.sb_inodesize +
331025101dcSChristoph Hellwig 		mp->m_sb.sb_sectsize +
332025101dcSChristoph Hellwig 		512;
333025101dcSChristoph Hellwig 
3348f794055SNathan Scott }
3358f794055SNathan Scott 
336025101dcSChristoph Hellwig /*
337025101dcSChristoph Hellwig  * Growing the data section of the filesystem.
338025101dcSChristoph Hellwig  *	superblock
339025101dcSChristoph Hellwig  *	agi and agf
340025101dcSChristoph Hellwig  *	allocation btrees
341025101dcSChristoph Hellwig  */
3428f794055SNathan Scott STATIC uint
343025101dcSChristoph Hellwig xfs_calc_growdata_reservation(
344025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
3458f794055SNathan Scott {
346025101dcSChristoph Hellwig 	return mp->m_sb.sb_sectsize * 3 +
347025101dcSChristoph Hellwig 		XFS_ALLOCFREE_LOG_RES(mp, 1) +
348025101dcSChristoph Hellwig 		128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1));
3498f794055SNathan Scott }
3508f794055SNathan Scott 
351025101dcSChristoph Hellwig /*
352025101dcSChristoph Hellwig  * Growing the rt section of the filesystem.
353025101dcSChristoph Hellwig  * In the first set of transactions (ALLOC) we allocate space to the
354025101dcSChristoph Hellwig  * bitmap or summary files.
355025101dcSChristoph Hellwig  *	superblock: sector size
356025101dcSChristoph Hellwig  *	agf of the ag from which the extent is allocated: sector size
357025101dcSChristoph Hellwig  *	bmap btree for bitmap/summary inode: max depth * blocksize
358025101dcSChristoph Hellwig  *	bitmap/summary inode: inode size
359025101dcSChristoph Hellwig  *	allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
360025101dcSChristoph Hellwig  */
3618f794055SNathan Scott STATIC uint
362025101dcSChristoph Hellwig xfs_calc_growrtalloc_reservation(
363025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
3648f794055SNathan Scott {
365025101dcSChristoph Hellwig 	return 2 * mp->m_sb.sb_sectsize +
366025101dcSChristoph Hellwig 		XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) +
367025101dcSChristoph Hellwig 		mp->m_sb.sb_inodesize +
368025101dcSChristoph Hellwig 		XFS_ALLOCFREE_LOG_RES(mp, 1) +
369025101dcSChristoph Hellwig 		128 * (3 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) +
370025101dcSChristoph Hellwig 		       XFS_ALLOCFREE_LOG_COUNT(mp, 1));
3718f794055SNathan Scott }
3728f794055SNathan Scott 
373025101dcSChristoph Hellwig /*
374025101dcSChristoph Hellwig  * Growing the rt section of the filesystem.
375025101dcSChristoph Hellwig  * In the second set of transactions (ZERO) we zero the new metadata blocks.
376025101dcSChristoph Hellwig  *	one bitmap/summary block: blocksize
377025101dcSChristoph Hellwig  */
3788f794055SNathan Scott STATIC uint
379025101dcSChristoph Hellwig xfs_calc_growrtzero_reservation(
380025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
3818f794055SNathan Scott {
382025101dcSChristoph Hellwig 	return mp->m_sb.sb_blocksize + 128;
3838f794055SNathan Scott }
3848f794055SNathan Scott 
385025101dcSChristoph Hellwig /*
386025101dcSChristoph Hellwig  * Growing the rt section of the filesystem.
387025101dcSChristoph Hellwig  * In the third set of transactions (FREE) we update metadata without
388025101dcSChristoph Hellwig  * allocating any new blocks.
389025101dcSChristoph Hellwig  *	superblock: sector size
390025101dcSChristoph Hellwig  *	bitmap inode: inode size
391025101dcSChristoph Hellwig  *	summary inode: inode size
392025101dcSChristoph Hellwig  *	one bitmap block: blocksize
393025101dcSChristoph Hellwig  *	summary blocks: new summary size
394025101dcSChristoph Hellwig  */
3958f794055SNathan Scott STATIC uint
396025101dcSChristoph Hellwig xfs_calc_growrtfree_reservation(
397025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
3988f794055SNathan Scott {
399025101dcSChristoph Hellwig 	return mp->m_sb.sb_sectsize +
400025101dcSChristoph Hellwig 		2 * mp->m_sb.sb_inodesize +
401025101dcSChristoph Hellwig 		mp->m_sb.sb_blocksize +
402025101dcSChristoph Hellwig 		mp->m_rsumsize +
403025101dcSChristoph Hellwig 		128 * 5;
4048f794055SNathan Scott }
4058f794055SNathan Scott 
406025101dcSChristoph Hellwig /*
407025101dcSChristoph Hellwig  * Logging the inode modification timestamp on a synchronous write.
408025101dcSChristoph Hellwig  *	inode
409025101dcSChristoph Hellwig  */
4108f794055SNathan Scott STATIC uint
411025101dcSChristoph Hellwig xfs_calc_swrite_reservation(
412025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
4138f794055SNathan Scott {
414025101dcSChristoph Hellwig 	return mp->m_sb.sb_inodesize + 128;
4158f794055SNathan Scott }
4168f794055SNathan Scott 
417025101dcSChristoph Hellwig /*
418025101dcSChristoph Hellwig  * Logging the inode mode bits when writing a setuid/setgid file
419025101dcSChristoph Hellwig  *	inode
420025101dcSChristoph Hellwig  */
4218f794055SNathan Scott STATIC uint
4228f794055SNathan Scott xfs_calc_writeid_reservation(xfs_mount_t *mp)
4238f794055SNathan Scott {
424025101dcSChristoph Hellwig 	return mp->m_sb.sb_inodesize + 128;
4258f794055SNathan Scott }
4268f794055SNathan Scott 
427025101dcSChristoph Hellwig /*
428025101dcSChristoph Hellwig  * Converting the inode from non-attributed to attributed.
429025101dcSChristoph Hellwig  *	the inode being converted: inode size
430025101dcSChristoph Hellwig  *	agf block and superblock (for block allocation)
431025101dcSChristoph Hellwig  *	the new block (directory sized)
432025101dcSChristoph Hellwig  *	bmap blocks for the new directory block
433025101dcSChristoph Hellwig  *	allocation btrees
434025101dcSChristoph Hellwig  */
4358f794055SNathan Scott STATIC uint
436025101dcSChristoph Hellwig xfs_calc_addafork_reservation(
437025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
4388f794055SNathan Scott {
439025101dcSChristoph Hellwig 	return XFS_DQUOT_LOGRES(mp) +
440025101dcSChristoph Hellwig 		mp->m_sb.sb_inodesize +
441025101dcSChristoph Hellwig 		mp->m_sb.sb_sectsize * 2 +
442025101dcSChristoph Hellwig 		mp->m_dirblksize +
443025101dcSChristoph Hellwig 		XFS_FSB_TO_B(mp, XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) +
444025101dcSChristoph Hellwig 		XFS_ALLOCFREE_LOG_RES(mp, 1) +
445025101dcSChristoph Hellwig 		128 * (4 + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1 +
446025101dcSChristoph Hellwig 		       XFS_ALLOCFREE_LOG_COUNT(mp, 1));
4478f794055SNathan Scott }
4488f794055SNathan Scott 
449025101dcSChristoph Hellwig /*
450025101dcSChristoph Hellwig  * Removing the attribute fork of a file
451025101dcSChristoph Hellwig  *    the inode being truncated: inode size
452025101dcSChristoph Hellwig  *    the inode's bmap btree: max depth * block size
453025101dcSChristoph Hellwig  * And the bmap_finish transaction can free the blocks and bmap blocks:
454025101dcSChristoph Hellwig  *    the agf for each of the ags: 4 * sector size
455025101dcSChristoph Hellwig  *    the agfl for each of the ags: 4 * sector size
456025101dcSChristoph Hellwig  *    the super block to reflect the freed blocks: sector size
457025101dcSChristoph Hellwig  *    worst case split in allocation btrees per extent assuming 4 extents:
458025101dcSChristoph Hellwig  *		4 exts * 2 trees * (2 * max depth - 1) * block size
459025101dcSChristoph Hellwig  */
4608f794055SNathan Scott STATIC uint
461025101dcSChristoph Hellwig xfs_calc_attrinval_reservation(
462025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
4638f794055SNathan Scott {
464025101dcSChristoph Hellwig 	return MAX((mp->m_sb.sb_inodesize +
465025101dcSChristoph Hellwig 		    XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
466025101dcSChristoph Hellwig 		    128 * (1 + XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK))),
467025101dcSChristoph Hellwig 		   (4 * mp->m_sb.sb_sectsize +
468025101dcSChristoph Hellwig 		    4 * mp->m_sb.sb_sectsize +
469025101dcSChristoph Hellwig 		    mp->m_sb.sb_sectsize +
470025101dcSChristoph Hellwig 		    XFS_ALLOCFREE_LOG_RES(mp, 4) +
471025101dcSChristoph Hellwig 		    128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))));
4728f794055SNathan Scott }
4738f794055SNathan Scott 
474025101dcSChristoph Hellwig /*
475025101dcSChristoph Hellwig  * Setting an attribute.
476025101dcSChristoph Hellwig  *	the inode getting the attribute
477025101dcSChristoph Hellwig  *	the superblock for allocations
478025101dcSChristoph Hellwig  *	the agfs extents are allocated from
479025101dcSChristoph Hellwig  *	the attribute btree * max depth
480025101dcSChristoph Hellwig  *	the inode allocation btree
481025101dcSChristoph Hellwig  * Since attribute transaction space is dependent on the size of the attribute,
482025101dcSChristoph Hellwig  * the calculation is done partially at mount time and partially at runtime.
483025101dcSChristoph Hellwig  */
4848f794055SNathan Scott STATIC uint
485025101dcSChristoph Hellwig xfs_calc_attrset_reservation(
486025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
4878f794055SNathan Scott {
488025101dcSChristoph Hellwig 	return XFS_DQUOT_LOGRES(mp) +
489025101dcSChristoph Hellwig 		mp->m_sb.sb_inodesize +
490025101dcSChristoph Hellwig 		mp->m_sb.sb_sectsize +
491025101dcSChristoph Hellwig 		XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) +
492025101dcSChristoph Hellwig 		128 * (2 + XFS_DA_NODE_MAXDEPTH);
4938f794055SNathan Scott }
4948f794055SNathan Scott 
495025101dcSChristoph Hellwig /*
496025101dcSChristoph Hellwig  * Removing an attribute.
497025101dcSChristoph Hellwig  *    the inode: inode size
498025101dcSChristoph Hellwig  *    the attribute btree could join: max depth * block size
499025101dcSChristoph Hellwig  *    the inode bmap btree could join or split: max depth * block size
500025101dcSChristoph Hellwig  * And the bmap_finish transaction can free the attr blocks freed giving:
501025101dcSChristoph Hellwig  *    the agf for the ag in which the blocks live: 2 * sector size
502025101dcSChristoph Hellwig  *    the agfl for the ag in which the blocks live: 2 * sector size
503025101dcSChristoph Hellwig  *    the superblock for the free block count: sector size
504025101dcSChristoph Hellwig  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
505025101dcSChristoph Hellwig  */
5068f794055SNathan Scott STATIC uint
507025101dcSChristoph Hellwig xfs_calc_attrrm_reservation(
508025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
5098f794055SNathan Scott {
510025101dcSChristoph Hellwig 	return XFS_DQUOT_LOGRES(mp) +
511025101dcSChristoph Hellwig 		MAX((mp->m_sb.sb_inodesize +
512025101dcSChristoph Hellwig 		     XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) +
513025101dcSChristoph Hellwig 		     XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
514025101dcSChristoph Hellwig 		     128 * (1 + XFS_DA_NODE_MAXDEPTH +
515025101dcSChristoph Hellwig 			    XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))),
516025101dcSChristoph Hellwig 		    (2 * mp->m_sb.sb_sectsize +
517025101dcSChristoph Hellwig 		     2 * mp->m_sb.sb_sectsize +
518025101dcSChristoph Hellwig 		     mp->m_sb.sb_sectsize +
519025101dcSChristoph Hellwig 		     XFS_ALLOCFREE_LOG_RES(mp, 2) +
520025101dcSChristoph Hellwig 		     128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
5218f794055SNathan Scott }
5228f794055SNathan Scott 
523025101dcSChristoph Hellwig /*
524025101dcSChristoph Hellwig  * Clearing a bad agino number in an agi hash bucket.
525025101dcSChristoph Hellwig  */
5268f794055SNathan Scott STATIC uint
527025101dcSChristoph Hellwig xfs_calc_clear_agi_bucket_reservation(
528025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
5298f794055SNathan Scott {
530025101dcSChristoph Hellwig 	return mp->m_sb.sb_sectsize + 128;
5318f794055SNathan Scott }
5328f794055SNathan Scott 
5338f794055SNathan Scott /*
5341da177e4SLinus Torvalds  * Initialize the precomputed transaction reservation values
5351da177e4SLinus Torvalds  * in the mount structure.
5361da177e4SLinus Torvalds  */
5371da177e4SLinus Torvalds void
5381da177e4SLinus Torvalds xfs_trans_init(
539025101dcSChristoph Hellwig 	struct xfs_mount	*mp)
5401da177e4SLinus Torvalds {
541025101dcSChristoph Hellwig 	struct xfs_trans_reservations *resp = &mp->m_reservations;
5421da177e4SLinus Torvalds 
5438f794055SNathan Scott 	resp->tr_write = xfs_calc_write_reservation(mp);
5448f794055SNathan Scott 	resp->tr_itruncate = xfs_calc_itruncate_reservation(mp);
5458f794055SNathan Scott 	resp->tr_rename = xfs_calc_rename_reservation(mp);
5468f794055SNathan Scott 	resp->tr_link = xfs_calc_link_reservation(mp);
5478f794055SNathan Scott 	resp->tr_remove = xfs_calc_remove_reservation(mp);
5488f794055SNathan Scott 	resp->tr_symlink = xfs_calc_symlink_reservation(mp);
5498f794055SNathan Scott 	resp->tr_create = xfs_calc_create_reservation(mp);
5508f794055SNathan Scott 	resp->tr_mkdir = xfs_calc_mkdir_reservation(mp);
5518f794055SNathan Scott 	resp->tr_ifree = xfs_calc_ifree_reservation(mp);
5528f794055SNathan Scott 	resp->tr_ichange = xfs_calc_ichange_reservation(mp);
5538f794055SNathan Scott 	resp->tr_growdata = xfs_calc_growdata_reservation(mp);
5548f794055SNathan Scott 	resp->tr_swrite = xfs_calc_swrite_reservation(mp);
5558f794055SNathan Scott 	resp->tr_writeid = xfs_calc_writeid_reservation(mp);
5568f794055SNathan Scott 	resp->tr_addafork = xfs_calc_addafork_reservation(mp);
5578f794055SNathan Scott 	resp->tr_attrinval = xfs_calc_attrinval_reservation(mp);
5588f794055SNathan Scott 	resp->tr_attrset = xfs_calc_attrset_reservation(mp);
5598f794055SNathan Scott 	resp->tr_attrrm = xfs_calc_attrrm_reservation(mp);
5608f794055SNathan Scott 	resp->tr_clearagi = xfs_calc_clear_agi_bucket_reservation(mp);
5618f794055SNathan Scott 	resp->tr_growrtalloc = xfs_calc_growrtalloc_reservation(mp);
5628f794055SNathan Scott 	resp->tr_growrtzero = xfs_calc_growrtzero_reservation(mp);
5638f794055SNathan Scott 	resp->tr_growrtfree = xfs_calc_growrtfree_reservation(mp);
5641da177e4SLinus Torvalds }
5651da177e4SLinus Torvalds 
5661da177e4SLinus Torvalds /*
5671da177e4SLinus Torvalds  * This routine is called to allocate a transaction structure.
5681da177e4SLinus Torvalds  * The type parameter indicates the type of the transaction.  These
5691da177e4SLinus Torvalds  * are enumerated in xfs_trans.h.
570b2ce3974SAlex Elder  *
571b2ce3974SAlex Elder  * Dynamically allocate the transaction structure from the transaction
572b2ce3974SAlex Elder  * zone, initialize it, and return it to the caller.
5731da177e4SLinus Torvalds  */
574b2ce3974SAlex Elder xfs_trans_t *
575b2ce3974SAlex Elder xfs_trans_alloc(
576b2ce3974SAlex Elder 	xfs_mount_t	*mp,
577b2ce3974SAlex Elder 	uint		type)
5781da177e4SLinus Torvalds {
579*d9457dc0SJan Kara 	xfs_trans_t     *tp;
580*d9457dc0SJan Kara 
581*d9457dc0SJan Kara 	sb_start_intwrite(mp->m_super);
582*d9457dc0SJan Kara 	tp = _xfs_trans_alloc(mp, type, KM_SLEEP);
583*d9457dc0SJan Kara 	tp->t_flags |= XFS_TRANS_FREEZE_PROT;
584*d9457dc0SJan Kara 	return tp;
585b2ce3974SAlex Elder }
586b2ce3974SAlex Elder 
587b2ce3974SAlex Elder xfs_trans_t *
588b2ce3974SAlex Elder _xfs_trans_alloc(
589b2ce3974SAlex Elder 	xfs_mount_t	*mp,
590b2ce3974SAlex Elder 	uint		type,
59177ba7877SAl Viro 	xfs_km_flags_t	memflags)
592b2ce3974SAlex Elder {
593b2ce3974SAlex Elder 	xfs_trans_t	*tp;
5941da177e4SLinus Torvalds 
595*d9457dc0SJan Kara 	WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE);
59634327e13SNathan Scott 	atomic_inc(&mp->m_active_trans);
5971da177e4SLinus Torvalds 
59880641dc6SChristoph Hellwig 	tp = kmem_zone_zalloc(xfs_trans_zone, memflags);
5991da177e4SLinus Torvalds 	tp->t_magic = XFS_TRANS_MAGIC;
6001da177e4SLinus Torvalds 	tp->t_type = type;
6011da177e4SLinus Torvalds 	tp->t_mountp = mp;
602e98c414fSChristoph Hellwig 	INIT_LIST_HEAD(&tp->t_items);
603ed3b4d6cSDave Chinner 	INIT_LIST_HEAD(&tp->t_busy);
60434327e13SNathan Scott 	return tp;
6051da177e4SLinus Torvalds }
6061da177e4SLinus Torvalds 
6071da177e4SLinus Torvalds /*
608b1c1b5b6SDave Chinner  * Free the transaction structure.  If there is more clean up
609b1c1b5b6SDave Chinner  * to do when the structure is freed, add it here.
610b1c1b5b6SDave Chinner  */
611b1c1b5b6SDave Chinner STATIC void
612b1c1b5b6SDave Chinner xfs_trans_free(
613ed3b4d6cSDave Chinner 	struct xfs_trans	*tp)
614b1c1b5b6SDave Chinner {
6154ecbfe63SDave Chinner 	xfs_extent_busy_sort(&tp->t_busy);
6164ecbfe63SDave Chinner 	xfs_extent_busy_clear(tp->t_mountp, &tp->t_busy, false);
617ed3b4d6cSDave Chinner 
618b1c1b5b6SDave Chinner 	atomic_dec(&tp->t_mountp->m_active_trans);
619*d9457dc0SJan Kara 	if (tp->t_flags & XFS_TRANS_FREEZE_PROT)
620*d9457dc0SJan Kara 		sb_end_intwrite(tp->t_mountp->m_super);
621b1c1b5b6SDave Chinner 	xfs_trans_free_dqinfo(tp);
622b1c1b5b6SDave Chinner 	kmem_zone_free(xfs_trans_zone, tp);
623b1c1b5b6SDave Chinner }
624b1c1b5b6SDave Chinner 
625b1c1b5b6SDave Chinner /*
6261da177e4SLinus Torvalds  * This is called to create a new transaction which will share the
6271da177e4SLinus Torvalds  * permanent log reservation of the given transaction.  The remaining
6281da177e4SLinus Torvalds  * unused block and rt extent reservations are also inherited.  This
6291da177e4SLinus Torvalds  * implies that the original transaction is no longer allowed to allocate
6301da177e4SLinus Torvalds  * blocks.  Locks and log items, however, are no inherited.  They must
6311da177e4SLinus Torvalds  * be added to the new transaction explicitly.
6321da177e4SLinus Torvalds  */
6331da177e4SLinus Torvalds xfs_trans_t *
6341da177e4SLinus Torvalds xfs_trans_dup(
6351da177e4SLinus Torvalds 	xfs_trans_t	*tp)
6361da177e4SLinus Torvalds {
6371da177e4SLinus Torvalds 	xfs_trans_t	*ntp;
6381da177e4SLinus Torvalds 
6391da177e4SLinus Torvalds 	ntp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
6401da177e4SLinus Torvalds 
6411da177e4SLinus Torvalds 	/*
6421da177e4SLinus Torvalds 	 * Initialize the new transaction structure.
6431da177e4SLinus Torvalds 	 */
6441da177e4SLinus Torvalds 	ntp->t_magic = XFS_TRANS_MAGIC;
6451da177e4SLinus Torvalds 	ntp->t_type = tp->t_type;
6461da177e4SLinus Torvalds 	ntp->t_mountp = tp->t_mountp;
647e98c414fSChristoph Hellwig 	INIT_LIST_HEAD(&ntp->t_items);
648ed3b4d6cSDave Chinner 	INIT_LIST_HEAD(&ntp->t_busy);
6491da177e4SLinus Torvalds 
6501da177e4SLinus Torvalds 	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
6511da177e4SLinus Torvalds 	ASSERT(tp->t_ticket != NULL);
652cfcbbbd0SNathan Scott 
653*d9457dc0SJan Kara 	ntp->t_flags = XFS_TRANS_PERM_LOG_RES |
654*d9457dc0SJan Kara 		       (tp->t_flags & XFS_TRANS_RESERVE) |
655*d9457dc0SJan Kara 		       (tp->t_flags & XFS_TRANS_FREEZE_PROT);
656*d9457dc0SJan Kara 	/* We gave our writer reference to the new transaction */
657*d9457dc0SJan Kara 	tp->t_flags &= ~XFS_TRANS_FREEZE_PROT;
658cc09c0dcSDave Chinner 	ntp->t_ticket = xfs_log_ticket_get(tp->t_ticket);
6591da177e4SLinus Torvalds 	ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used;
6601da177e4SLinus Torvalds 	tp->t_blk_res = tp->t_blk_res_used;
6611da177e4SLinus Torvalds 	ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used;
6621da177e4SLinus Torvalds 	tp->t_rtx_res = tp->t_rtx_res_used;
66359c1b082SNathan Scott 	ntp->t_pflags = tp->t_pflags;
6641da177e4SLinus Torvalds 
6657d095257SChristoph Hellwig 	xfs_trans_dup_dqinfo(tp, ntp);
6661da177e4SLinus Torvalds 
6671da177e4SLinus Torvalds 	atomic_inc(&tp->t_mountp->m_active_trans);
6681da177e4SLinus Torvalds 	return ntp;
6691da177e4SLinus Torvalds }
6701da177e4SLinus Torvalds 
6711da177e4SLinus Torvalds /*
6721da177e4SLinus Torvalds  * This is called to reserve free disk blocks and log space for the
6731da177e4SLinus Torvalds  * given transaction.  This must be done before allocating any resources
6741da177e4SLinus Torvalds  * within the transaction.
6751da177e4SLinus Torvalds  *
6761da177e4SLinus Torvalds  * This will return ENOSPC if there are not enough blocks available.
6771da177e4SLinus Torvalds  * It will sleep waiting for available log space.
6781da177e4SLinus Torvalds  * The only valid value for the flags parameter is XFS_RES_LOG_PERM, which
6791da177e4SLinus Torvalds  * is used by long running transactions.  If any one of the reservations
6801da177e4SLinus Torvalds  * fails then they will all be backed out.
6811da177e4SLinus Torvalds  *
6821da177e4SLinus Torvalds  * This does not do quota reservations. That typically is done by the
6831da177e4SLinus Torvalds  * caller afterwards.
6841da177e4SLinus Torvalds  */
6851da177e4SLinus Torvalds int
6861da177e4SLinus Torvalds xfs_trans_reserve(
6871da177e4SLinus Torvalds 	xfs_trans_t	*tp,
6881da177e4SLinus Torvalds 	uint		blocks,
6891da177e4SLinus Torvalds 	uint		logspace,
6901da177e4SLinus Torvalds 	uint		rtextents,
6911da177e4SLinus Torvalds 	uint		flags,
6921da177e4SLinus Torvalds 	uint		logcount)
6931da177e4SLinus Torvalds {
69459c1b082SNathan Scott 	int		error = 0;
69559c1b082SNathan Scott 	int		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
6961da177e4SLinus Torvalds 
6971da177e4SLinus Torvalds 	/* Mark this thread as being in a transaction */
69859c1b082SNathan Scott 	current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
6991da177e4SLinus Torvalds 
7001da177e4SLinus Torvalds 	/*
7011da177e4SLinus Torvalds 	 * Attempt to reserve the needed disk blocks by decrementing
7021da177e4SLinus Torvalds 	 * the number needed from the number available.  This will
7031da177e4SLinus Torvalds 	 * fail if the count would go below zero.
7041da177e4SLinus Torvalds 	 */
7051da177e4SLinus Torvalds 	if (blocks > 0) {
70696540c78SChristoph Hellwig 		error = xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
70720f4ebf2SDavid Chinner 					  -((int64_t)blocks), rsvd);
7081da177e4SLinus Torvalds 		if (error != 0) {
70959c1b082SNathan Scott 			current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
7101da177e4SLinus Torvalds 			return (XFS_ERROR(ENOSPC));
7111da177e4SLinus Torvalds 		}
7121da177e4SLinus Torvalds 		tp->t_blk_res += blocks;
7131da177e4SLinus Torvalds 	}
7141da177e4SLinus Torvalds 
7151da177e4SLinus Torvalds 	/*
7161da177e4SLinus Torvalds 	 * Reserve the log space needed for this transaction.
7171da177e4SLinus Torvalds 	 */
7181da177e4SLinus Torvalds 	if (logspace > 0) {
7199006fb91SChristoph Hellwig 		bool	permanent = false;
7209006fb91SChristoph Hellwig 
7219006fb91SChristoph Hellwig 		ASSERT(tp->t_log_res == 0 || tp->t_log_res == logspace);
7229006fb91SChristoph Hellwig 		ASSERT(tp->t_log_count == 0 || tp->t_log_count == logcount);
7239006fb91SChristoph Hellwig 
7241da177e4SLinus Torvalds 		if (flags & XFS_TRANS_PERM_LOG_RES) {
7251da177e4SLinus Torvalds 			tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
7269006fb91SChristoph Hellwig 			permanent = true;
7271da177e4SLinus Torvalds 		} else {
7281da177e4SLinus Torvalds 			ASSERT(tp->t_ticket == NULL);
7291da177e4SLinus Torvalds 			ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
7301da177e4SLinus Torvalds 		}
7311da177e4SLinus Torvalds 
7329006fb91SChristoph Hellwig 		if (tp->t_ticket != NULL) {
7339006fb91SChristoph Hellwig 			ASSERT(flags & XFS_TRANS_PERM_LOG_RES);
7349006fb91SChristoph Hellwig 			error = xfs_log_regrant(tp->t_mountp, tp->t_ticket);
7359006fb91SChristoph Hellwig 		} else {
7369006fb91SChristoph Hellwig 			error = xfs_log_reserve(tp->t_mountp, logspace,
7379006fb91SChristoph Hellwig 						logcount, &tp->t_ticket,
7389006fb91SChristoph Hellwig 						XFS_TRANSACTION, permanent,
7399006fb91SChristoph Hellwig 						tp->t_type);
7401da177e4SLinus Torvalds 		}
7419006fb91SChristoph Hellwig 
7429006fb91SChristoph Hellwig 		if (error)
7439006fb91SChristoph Hellwig 			goto undo_blocks;
7449006fb91SChristoph Hellwig 
7451da177e4SLinus Torvalds 		tp->t_log_res = logspace;
7461da177e4SLinus Torvalds 		tp->t_log_count = logcount;
7471da177e4SLinus Torvalds 	}
7481da177e4SLinus Torvalds 
7491da177e4SLinus Torvalds 	/*
7501da177e4SLinus Torvalds 	 * Attempt to reserve the needed realtime extents by decrementing
7511da177e4SLinus Torvalds 	 * the number needed from the number available.  This will
7521da177e4SLinus Torvalds 	 * fail if the count would go below zero.
7531da177e4SLinus Torvalds 	 */
7541da177e4SLinus Torvalds 	if (rtextents > 0) {
7551da177e4SLinus Torvalds 		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS,
75620f4ebf2SDavid Chinner 					  -((int64_t)rtextents), rsvd);
7571da177e4SLinus Torvalds 		if (error) {
7581da177e4SLinus Torvalds 			error = XFS_ERROR(ENOSPC);
7591da177e4SLinus Torvalds 			goto undo_log;
7601da177e4SLinus Torvalds 		}
7611da177e4SLinus Torvalds 		tp->t_rtx_res += rtextents;
7621da177e4SLinus Torvalds 	}
7631da177e4SLinus Torvalds 
7641da177e4SLinus Torvalds 	return 0;
7651da177e4SLinus Torvalds 
7661da177e4SLinus Torvalds 	/*
7671da177e4SLinus Torvalds 	 * Error cases jump to one of these labels to undo any
7681da177e4SLinus Torvalds 	 * reservations which have already been performed.
7691da177e4SLinus Torvalds 	 */
7701da177e4SLinus Torvalds undo_log:
7711da177e4SLinus Torvalds 	if (logspace > 0) {
7729006fb91SChristoph Hellwig 		int		log_flags;
7739006fb91SChristoph Hellwig 
7741da177e4SLinus Torvalds 		if (flags & XFS_TRANS_PERM_LOG_RES) {
7751da177e4SLinus Torvalds 			log_flags = XFS_LOG_REL_PERM_RESERV;
7761da177e4SLinus Torvalds 		} else {
7771da177e4SLinus Torvalds 			log_flags = 0;
7781da177e4SLinus Torvalds 		}
7791da177e4SLinus Torvalds 		xfs_log_done(tp->t_mountp, tp->t_ticket, NULL, log_flags);
7801da177e4SLinus Torvalds 		tp->t_ticket = NULL;
7811da177e4SLinus Torvalds 		tp->t_log_res = 0;
7821da177e4SLinus Torvalds 		tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
7831da177e4SLinus Torvalds 	}
7841da177e4SLinus Torvalds 
7851da177e4SLinus Torvalds undo_blocks:
7861da177e4SLinus Torvalds 	if (blocks > 0) {
78796540c78SChristoph Hellwig 		xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
78820f4ebf2SDavid Chinner 					 (int64_t)blocks, rsvd);
7891da177e4SLinus Torvalds 		tp->t_blk_res = 0;
7901da177e4SLinus Torvalds 	}
7911da177e4SLinus Torvalds 
79259c1b082SNathan Scott 	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
7931da177e4SLinus Torvalds 
79459c1b082SNathan Scott 	return error;
7951da177e4SLinus Torvalds }
7961da177e4SLinus Torvalds 
7971da177e4SLinus Torvalds /*
7981da177e4SLinus Torvalds  * Record the indicated change to the given field for application
7991da177e4SLinus Torvalds  * to the file system's superblock when the transaction commits.
8001da177e4SLinus Torvalds  * For now, just store the change in the transaction structure.
8011da177e4SLinus Torvalds  *
8021da177e4SLinus Torvalds  * Mark the transaction structure to indicate that the superblock
8031da177e4SLinus Torvalds  * needs to be updated before committing.
80492821e2bSDavid Chinner  *
80592821e2bSDavid Chinner  * Because we may not be keeping track of allocated/free inodes and
80692821e2bSDavid Chinner  * used filesystem blocks in the superblock, we do not mark the
80792821e2bSDavid Chinner  * superblock dirty in this transaction if we modify these fields.
80892821e2bSDavid Chinner  * We still need to update the transaction deltas so that they get
80992821e2bSDavid Chinner  * applied to the incore superblock, but we don't want them to
81092821e2bSDavid Chinner  * cause the superblock to get locked and logged if these are the
81192821e2bSDavid Chinner  * only fields in the superblock that the transaction modifies.
8121da177e4SLinus Torvalds  */
8131da177e4SLinus Torvalds void
8141da177e4SLinus Torvalds xfs_trans_mod_sb(
8151da177e4SLinus Torvalds 	xfs_trans_t	*tp,
8161da177e4SLinus Torvalds 	uint		field,
81720f4ebf2SDavid Chinner 	int64_t		delta)
8181da177e4SLinus Torvalds {
81992821e2bSDavid Chinner 	uint32_t	flags = (XFS_TRANS_DIRTY|XFS_TRANS_SB_DIRTY);
82092821e2bSDavid Chinner 	xfs_mount_t	*mp = tp->t_mountp;
8211da177e4SLinus Torvalds 
8221da177e4SLinus Torvalds 	switch (field) {
8231da177e4SLinus Torvalds 	case XFS_TRANS_SB_ICOUNT:
8241da177e4SLinus Torvalds 		tp->t_icount_delta += delta;
82592821e2bSDavid Chinner 		if (xfs_sb_version_haslazysbcount(&mp->m_sb))
82692821e2bSDavid Chinner 			flags &= ~XFS_TRANS_SB_DIRTY;
8271da177e4SLinus Torvalds 		break;
8281da177e4SLinus Torvalds 	case XFS_TRANS_SB_IFREE:
8291da177e4SLinus Torvalds 		tp->t_ifree_delta += delta;
83092821e2bSDavid Chinner 		if (xfs_sb_version_haslazysbcount(&mp->m_sb))
83192821e2bSDavid Chinner 			flags &= ~XFS_TRANS_SB_DIRTY;
8321da177e4SLinus Torvalds 		break;
8331da177e4SLinus Torvalds 	case XFS_TRANS_SB_FDBLOCKS:
8341da177e4SLinus Torvalds 		/*
8351da177e4SLinus Torvalds 		 * Track the number of blocks allocated in the
8361da177e4SLinus Torvalds 		 * transaction.  Make sure it does not exceed the
8371da177e4SLinus Torvalds 		 * number reserved.
8381da177e4SLinus Torvalds 		 */
8391da177e4SLinus Torvalds 		if (delta < 0) {
8401da177e4SLinus Torvalds 			tp->t_blk_res_used += (uint)-delta;
8411da177e4SLinus Torvalds 			ASSERT(tp->t_blk_res_used <= tp->t_blk_res);
8421da177e4SLinus Torvalds 		}
8431da177e4SLinus Torvalds 		tp->t_fdblocks_delta += delta;
84492821e2bSDavid Chinner 		if (xfs_sb_version_haslazysbcount(&mp->m_sb))
84592821e2bSDavid Chinner 			flags &= ~XFS_TRANS_SB_DIRTY;
8461da177e4SLinus Torvalds 		break;
8471da177e4SLinus Torvalds 	case XFS_TRANS_SB_RES_FDBLOCKS:
8481da177e4SLinus Torvalds 		/*
8491da177e4SLinus Torvalds 		 * The allocation has already been applied to the
8501da177e4SLinus Torvalds 		 * in-core superblock's counter.  This should only
8511da177e4SLinus Torvalds 		 * be applied to the on-disk superblock.
8521da177e4SLinus Torvalds 		 */
8531da177e4SLinus Torvalds 		ASSERT(delta < 0);
8541da177e4SLinus Torvalds 		tp->t_res_fdblocks_delta += delta;
85592821e2bSDavid Chinner 		if (xfs_sb_version_haslazysbcount(&mp->m_sb))
85692821e2bSDavid Chinner 			flags &= ~XFS_TRANS_SB_DIRTY;
8571da177e4SLinus Torvalds 		break;
8581da177e4SLinus Torvalds 	case XFS_TRANS_SB_FREXTENTS:
8591da177e4SLinus Torvalds 		/*
8601da177e4SLinus Torvalds 		 * Track the number of blocks allocated in the
8611da177e4SLinus Torvalds 		 * transaction.  Make sure it does not exceed the
8621da177e4SLinus Torvalds 		 * number reserved.
8631da177e4SLinus Torvalds 		 */
8641da177e4SLinus Torvalds 		if (delta < 0) {
8651da177e4SLinus Torvalds 			tp->t_rtx_res_used += (uint)-delta;
8661da177e4SLinus Torvalds 			ASSERT(tp->t_rtx_res_used <= tp->t_rtx_res);
8671da177e4SLinus Torvalds 		}
8681da177e4SLinus Torvalds 		tp->t_frextents_delta += delta;
8691da177e4SLinus Torvalds 		break;
8701da177e4SLinus Torvalds 	case XFS_TRANS_SB_RES_FREXTENTS:
8711da177e4SLinus Torvalds 		/*
8721da177e4SLinus Torvalds 		 * The allocation has already been applied to the
873c41564b5SNathan Scott 		 * in-core superblock's counter.  This should only
8741da177e4SLinus Torvalds 		 * be applied to the on-disk superblock.
8751da177e4SLinus Torvalds 		 */
8761da177e4SLinus Torvalds 		ASSERT(delta < 0);
8771da177e4SLinus Torvalds 		tp->t_res_frextents_delta += delta;
8781da177e4SLinus Torvalds 		break;
8791da177e4SLinus Torvalds 	case XFS_TRANS_SB_DBLOCKS:
8801da177e4SLinus Torvalds 		ASSERT(delta > 0);
8811da177e4SLinus Torvalds 		tp->t_dblocks_delta += delta;
8821da177e4SLinus Torvalds 		break;
8831da177e4SLinus Torvalds 	case XFS_TRANS_SB_AGCOUNT:
8841da177e4SLinus Torvalds 		ASSERT(delta > 0);
8851da177e4SLinus Torvalds 		tp->t_agcount_delta += delta;
8861da177e4SLinus Torvalds 		break;
8871da177e4SLinus Torvalds 	case XFS_TRANS_SB_IMAXPCT:
8881da177e4SLinus Torvalds 		tp->t_imaxpct_delta += delta;
8891da177e4SLinus Torvalds 		break;
8901da177e4SLinus Torvalds 	case XFS_TRANS_SB_REXTSIZE:
8911da177e4SLinus Torvalds 		tp->t_rextsize_delta += delta;
8921da177e4SLinus Torvalds 		break;
8931da177e4SLinus Torvalds 	case XFS_TRANS_SB_RBMBLOCKS:
8941da177e4SLinus Torvalds 		tp->t_rbmblocks_delta += delta;
8951da177e4SLinus Torvalds 		break;
8961da177e4SLinus Torvalds 	case XFS_TRANS_SB_RBLOCKS:
8971da177e4SLinus Torvalds 		tp->t_rblocks_delta += delta;
8981da177e4SLinus Torvalds 		break;
8991da177e4SLinus Torvalds 	case XFS_TRANS_SB_REXTENTS:
9001da177e4SLinus Torvalds 		tp->t_rextents_delta += delta;
9011da177e4SLinus Torvalds 		break;
9021da177e4SLinus Torvalds 	case XFS_TRANS_SB_REXTSLOG:
9031da177e4SLinus Torvalds 		tp->t_rextslog_delta += delta;
9041da177e4SLinus Torvalds 		break;
9051da177e4SLinus Torvalds 	default:
9061da177e4SLinus Torvalds 		ASSERT(0);
9071da177e4SLinus Torvalds 		return;
9081da177e4SLinus Torvalds 	}
9091da177e4SLinus Torvalds 
910210c6f1cSDavid Chinner 	tp->t_flags |= flags;
9111da177e4SLinus Torvalds }
9121da177e4SLinus Torvalds 
9131da177e4SLinus Torvalds /*
9141da177e4SLinus Torvalds  * xfs_trans_apply_sb_deltas() is called from the commit code
9151da177e4SLinus Torvalds  * to bring the superblock buffer into the current transaction
9161da177e4SLinus Torvalds  * and modify it as requested by earlier calls to xfs_trans_mod_sb().
9171da177e4SLinus Torvalds  *
9181da177e4SLinus Torvalds  * For now we just look at each field allowed to change and change
9191da177e4SLinus Torvalds  * it if necessary.
9201da177e4SLinus Torvalds  */
9211da177e4SLinus Torvalds STATIC void
9221da177e4SLinus Torvalds xfs_trans_apply_sb_deltas(
9231da177e4SLinus Torvalds 	xfs_trans_t	*tp)
9241da177e4SLinus Torvalds {
9252bdf7cd0SChristoph Hellwig 	xfs_dsb_t	*sbp;
9261da177e4SLinus Torvalds 	xfs_buf_t	*bp;
9271da177e4SLinus Torvalds 	int		whole = 0;
9281da177e4SLinus Torvalds 
9291da177e4SLinus Torvalds 	bp = xfs_trans_getsb(tp, tp->t_mountp, 0);
9301da177e4SLinus Torvalds 	sbp = XFS_BUF_TO_SBP(bp);
9311da177e4SLinus Torvalds 
9321da177e4SLinus Torvalds 	/*
9331da177e4SLinus Torvalds 	 * Check that superblock mods match the mods made to AGF counters.
9341da177e4SLinus Torvalds 	 */
9351da177e4SLinus Torvalds 	ASSERT((tp->t_fdblocks_delta + tp->t_res_fdblocks_delta) ==
9361da177e4SLinus Torvalds 	       (tp->t_ag_freeblks_delta + tp->t_ag_flist_delta +
9371da177e4SLinus Torvalds 		tp->t_ag_btree_delta));
9381da177e4SLinus Torvalds 
93992821e2bSDavid Chinner 	/*
94092821e2bSDavid Chinner 	 * Only update the superblock counters if we are logging them
94192821e2bSDavid Chinner 	 */
94292821e2bSDavid Chinner 	if (!xfs_sb_version_haslazysbcount(&(tp->t_mountp->m_sb))) {
9432bdf7cd0SChristoph Hellwig 		if (tp->t_icount_delta)
944413d57c9SMarcin Slusarz 			be64_add_cpu(&sbp->sb_icount, tp->t_icount_delta);
9452bdf7cd0SChristoph Hellwig 		if (tp->t_ifree_delta)
946413d57c9SMarcin Slusarz 			be64_add_cpu(&sbp->sb_ifree, tp->t_ifree_delta);
9472bdf7cd0SChristoph Hellwig 		if (tp->t_fdblocks_delta)
948413d57c9SMarcin Slusarz 			be64_add_cpu(&sbp->sb_fdblocks, tp->t_fdblocks_delta);
9492bdf7cd0SChristoph Hellwig 		if (tp->t_res_fdblocks_delta)
950413d57c9SMarcin Slusarz 			be64_add_cpu(&sbp->sb_fdblocks, tp->t_res_fdblocks_delta);
9511da177e4SLinus Torvalds 	}
9521da177e4SLinus Torvalds 
9532bdf7cd0SChristoph Hellwig 	if (tp->t_frextents_delta)
954413d57c9SMarcin Slusarz 		be64_add_cpu(&sbp->sb_frextents, tp->t_frextents_delta);
9552bdf7cd0SChristoph Hellwig 	if (tp->t_res_frextents_delta)
956413d57c9SMarcin Slusarz 		be64_add_cpu(&sbp->sb_frextents, tp->t_res_frextents_delta);
9571da177e4SLinus Torvalds 
9582bdf7cd0SChristoph Hellwig 	if (tp->t_dblocks_delta) {
959413d57c9SMarcin Slusarz 		be64_add_cpu(&sbp->sb_dblocks, tp->t_dblocks_delta);
9601da177e4SLinus Torvalds 		whole = 1;
9611da177e4SLinus Torvalds 	}
9622bdf7cd0SChristoph Hellwig 	if (tp->t_agcount_delta) {
963413d57c9SMarcin Slusarz 		be32_add_cpu(&sbp->sb_agcount, tp->t_agcount_delta);
9641da177e4SLinus Torvalds 		whole = 1;
9651da177e4SLinus Torvalds 	}
9662bdf7cd0SChristoph Hellwig 	if (tp->t_imaxpct_delta) {
9672bdf7cd0SChristoph Hellwig 		sbp->sb_imax_pct += tp->t_imaxpct_delta;
9681da177e4SLinus Torvalds 		whole = 1;
9691da177e4SLinus Torvalds 	}
9702bdf7cd0SChristoph Hellwig 	if (tp->t_rextsize_delta) {
971413d57c9SMarcin Slusarz 		be32_add_cpu(&sbp->sb_rextsize, tp->t_rextsize_delta);
9721da177e4SLinus Torvalds 		whole = 1;
9731da177e4SLinus Torvalds 	}
9742bdf7cd0SChristoph Hellwig 	if (tp->t_rbmblocks_delta) {
975413d57c9SMarcin Slusarz 		be32_add_cpu(&sbp->sb_rbmblocks, tp->t_rbmblocks_delta);
9761da177e4SLinus Torvalds 		whole = 1;
9771da177e4SLinus Torvalds 	}
9782bdf7cd0SChristoph Hellwig 	if (tp->t_rblocks_delta) {
979413d57c9SMarcin Slusarz 		be64_add_cpu(&sbp->sb_rblocks, tp->t_rblocks_delta);
9801da177e4SLinus Torvalds 		whole = 1;
9811da177e4SLinus Torvalds 	}
9822bdf7cd0SChristoph Hellwig 	if (tp->t_rextents_delta) {
983413d57c9SMarcin Slusarz 		be64_add_cpu(&sbp->sb_rextents, tp->t_rextents_delta);
9841da177e4SLinus Torvalds 		whole = 1;
9851da177e4SLinus Torvalds 	}
9862bdf7cd0SChristoph Hellwig 	if (tp->t_rextslog_delta) {
9872bdf7cd0SChristoph Hellwig 		sbp->sb_rextslog += tp->t_rextslog_delta;
9881da177e4SLinus Torvalds 		whole = 1;
9891da177e4SLinus Torvalds 	}
9901da177e4SLinus Torvalds 
9911da177e4SLinus Torvalds 	if (whole)
9921da177e4SLinus Torvalds 		/*
993c41564b5SNathan Scott 		 * Log the whole thing, the fields are noncontiguous.
9941da177e4SLinus Torvalds 		 */
9952bdf7cd0SChristoph Hellwig 		xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_dsb_t) - 1);
9961da177e4SLinus Torvalds 	else
9971da177e4SLinus Torvalds 		/*
9981da177e4SLinus Torvalds 		 * Since all the modifiable fields are contiguous, we
9991da177e4SLinus Torvalds 		 * can get away with this.
10001da177e4SLinus Torvalds 		 */
10012bdf7cd0SChristoph Hellwig 		xfs_trans_log_buf(tp, bp, offsetof(xfs_dsb_t, sb_icount),
10022bdf7cd0SChristoph Hellwig 				  offsetof(xfs_dsb_t, sb_frextents) +
10031da177e4SLinus Torvalds 				  sizeof(sbp->sb_frextents) - 1);
10041da177e4SLinus Torvalds }
10051da177e4SLinus Torvalds 
10061da177e4SLinus Torvalds /*
100745c34141SDavid Chinner  * xfs_trans_unreserve_and_mod_sb() is called to release unused reservations
100845c34141SDavid Chinner  * and apply superblock counter changes to the in-core superblock.  The
100945c34141SDavid Chinner  * t_res_fdblocks_delta and t_res_frextents_delta fields are explicitly NOT
101045c34141SDavid Chinner  * applied to the in-core superblock.  The idea is that that has already been
101145c34141SDavid Chinner  * done.
10121da177e4SLinus Torvalds  *
10131da177e4SLinus Torvalds  * This is done efficiently with a single call to xfs_mod_incore_sb_batch().
101445c34141SDavid Chinner  * However, we have to ensure that we only modify each superblock field only
101545c34141SDavid Chinner  * once because the application of the delta values may not be atomic. That can
101645c34141SDavid Chinner  * lead to ENOSPC races occurring if we have two separate modifcations of the
101745c34141SDavid Chinner  * free space counter to put back the entire reservation and then take away
101845c34141SDavid Chinner  * what we used.
101945c34141SDavid Chinner  *
102045c34141SDavid Chinner  * If we are not logging superblock counters, then the inode allocated/free and
102145c34141SDavid Chinner  * used block counts are not updated in the on disk superblock. In this case,
102245c34141SDavid Chinner  * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we
102345c34141SDavid Chinner  * still need to update the incore superblock with the changes.
10241da177e4SLinus Torvalds  */
102571e330b5SDave Chinner void
10261da177e4SLinus Torvalds xfs_trans_unreserve_and_mod_sb(
10271da177e4SLinus Torvalds 	xfs_trans_t	*tp)
10281da177e4SLinus Torvalds {
10291b040712SChristoph Hellwig 	xfs_mod_sb_t	msb[9];	/* If you add cases, add entries */
10301da177e4SLinus Torvalds 	xfs_mod_sb_t	*msbp;
103192821e2bSDavid Chinner 	xfs_mount_t	*mp = tp->t_mountp;
10321da177e4SLinus Torvalds 	/* REFERENCED */
10331da177e4SLinus Torvalds 	int		error;
10341da177e4SLinus Torvalds 	int		rsvd;
103545c34141SDavid Chinner 	int64_t		blkdelta = 0;
103645c34141SDavid Chinner 	int64_t		rtxdelta = 0;
10371b040712SChristoph Hellwig 	int64_t		idelta = 0;
10381b040712SChristoph Hellwig 	int64_t		ifreedelta = 0;
10391da177e4SLinus Torvalds 
10401da177e4SLinus Torvalds 	msbp = msb;
10411da177e4SLinus Torvalds 	rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
10421da177e4SLinus Torvalds 
10431b040712SChristoph Hellwig 	/* calculate deltas */
104445c34141SDavid Chinner 	if (tp->t_blk_res > 0)
104545c34141SDavid Chinner 		blkdelta = tp->t_blk_res;
104645c34141SDavid Chinner 	if ((tp->t_fdblocks_delta != 0) &&
104745c34141SDavid Chinner 	    (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
104845c34141SDavid Chinner 	     (tp->t_flags & XFS_TRANS_SB_DIRTY)))
104945c34141SDavid Chinner 	        blkdelta += tp->t_fdblocks_delta;
105045c34141SDavid Chinner 
105145c34141SDavid Chinner 	if (tp->t_rtx_res > 0)
105245c34141SDavid Chinner 		rtxdelta = tp->t_rtx_res;
105345c34141SDavid Chinner 	if ((tp->t_frextents_delta != 0) &&
105445c34141SDavid Chinner 	    (tp->t_flags & XFS_TRANS_SB_DIRTY))
105545c34141SDavid Chinner 		rtxdelta += tp->t_frextents_delta;
105645c34141SDavid Chinner 
10571b040712SChristoph Hellwig 	if (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
10581b040712SChristoph Hellwig 	     (tp->t_flags & XFS_TRANS_SB_DIRTY)) {
10591b040712SChristoph Hellwig 		idelta = tp->t_icount_delta;
10601b040712SChristoph Hellwig 		ifreedelta = tp->t_ifree_delta;
10611b040712SChristoph Hellwig 	}
10621b040712SChristoph Hellwig 
10631b040712SChristoph Hellwig 	/* apply the per-cpu counters */
10641b040712SChristoph Hellwig 	if (blkdelta) {
10651b040712SChristoph Hellwig 		error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
10661b040712SChristoph Hellwig 						 blkdelta, rsvd);
10671b040712SChristoph Hellwig 		if (error)
10681b040712SChristoph Hellwig 			goto out;
10691b040712SChristoph Hellwig 	}
10701b040712SChristoph Hellwig 
10711b040712SChristoph Hellwig 	if (idelta) {
10721b040712SChristoph Hellwig 		error = xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT,
10731b040712SChristoph Hellwig 						 idelta, rsvd);
10741b040712SChristoph Hellwig 		if (error)
10751b040712SChristoph Hellwig 			goto out_undo_fdblocks;
10761b040712SChristoph Hellwig 	}
10771b040712SChristoph Hellwig 
10781b040712SChristoph Hellwig 	if (ifreedelta) {
10791b040712SChristoph Hellwig 		error = xfs_icsb_modify_counters(mp, XFS_SBS_IFREE,
10801b040712SChristoph Hellwig 						 ifreedelta, rsvd);
10811b040712SChristoph Hellwig 		if (error)
10821b040712SChristoph Hellwig 			goto out_undo_icount;
10831b040712SChristoph Hellwig 	}
10841b040712SChristoph Hellwig 
10851b040712SChristoph Hellwig 	/* apply remaining deltas */
108645c34141SDavid Chinner 	if (rtxdelta != 0) {
10871da177e4SLinus Torvalds 		msbp->msb_field = XFS_SBS_FREXTENTS;
108845c34141SDavid Chinner 		msbp->msb_delta = rtxdelta;
10891da177e4SLinus Torvalds 		msbp++;
10901da177e4SLinus Torvalds 	}
10911da177e4SLinus Torvalds 
109292821e2bSDavid Chinner 	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
10931da177e4SLinus Torvalds 		if (tp->t_dblocks_delta != 0) {
10941da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_DBLOCKS;
109520f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_dblocks_delta;
10961da177e4SLinus Torvalds 			msbp++;
10971da177e4SLinus Torvalds 		}
10981da177e4SLinus Torvalds 		if (tp->t_agcount_delta != 0) {
10991da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_AGCOUNT;
110020f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_agcount_delta;
11011da177e4SLinus Torvalds 			msbp++;
11021da177e4SLinus Torvalds 		}
11031da177e4SLinus Torvalds 		if (tp->t_imaxpct_delta != 0) {
11041da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_IMAX_PCT;
110520f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_imaxpct_delta;
11061da177e4SLinus Torvalds 			msbp++;
11071da177e4SLinus Torvalds 		}
11081da177e4SLinus Torvalds 		if (tp->t_rextsize_delta != 0) {
11091da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_REXTSIZE;
111020f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_rextsize_delta;
11111da177e4SLinus Torvalds 			msbp++;
11121da177e4SLinus Torvalds 		}
11131da177e4SLinus Torvalds 		if (tp->t_rbmblocks_delta != 0) {
11141da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_RBMBLOCKS;
111520f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_rbmblocks_delta;
11161da177e4SLinus Torvalds 			msbp++;
11171da177e4SLinus Torvalds 		}
11181da177e4SLinus Torvalds 		if (tp->t_rblocks_delta != 0) {
11191da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_RBLOCKS;
112020f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_rblocks_delta;
11211da177e4SLinus Torvalds 			msbp++;
11221da177e4SLinus Torvalds 		}
11231da177e4SLinus Torvalds 		if (tp->t_rextents_delta != 0) {
11241da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_REXTENTS;
112520f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_rextents_delta;
11261da177e4SLinus Torvalds 			msbp++;
11271da177e4SLinus Torvalds 		}
11281da177e4SLinus Torvalds 		if (tp->t_rextslog_delta != 0) {
11291da177e4SLinus Torvalds 			msbp->msb_field = XFS_SBS_REXTSLOG;
113020f4ebf2SDavid Chinner 			msbp->msb_delta = tp->t_rextslog_delta;
11311da177e4SLinus Torvalds 			msbp++;
11321da177e4SLinus Torvalds 		}
11331da177e4SLinus Torvalds 	}
11341da177e4SLinus Torvalds 
11351da177e4SLinus Torvalds 	/*
11361da177e4SLinus Torvalds 	 * If we need to change anything, do it.
11371da177e4SLinus Torvalds 	 */
11381da177e4SLinus Torvalds 	if (msbp > msb) {
11391da177e4SLinus Torvalds 		error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
11401da177e4SLinus Torvalds 			(uint)(msbp - msb), rsvd);
11411b040712SChristoph Hellwig 		if (error)
11421b040712SChristoph Hellwig 			goto out_undo_ifreecount;
11431da177e4SLinus Torvalds 	}
11441b040712SChristoph Hellwig 
11451b040712SChristoph Hellwig 	return;
11461b040712SChristoph Hellwig 
11471b040712SChristoph Hellwig out_undo_ifreecount:
11481b040712SChristoph Hellwig 	if (ifreedelta)
11491b040712SChristoph Hellwig 		xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd);
11501b040712SChristoph Hellwig out_undo_icount:
11511b040712SChristoph Hellwig 	if (idelta)
11521b040712SChristoph Hellwig 		xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, -idelta, rsvd);
11531b040712SChristoph Hellwig out_undo_fdblocks:
11541b040712SChristoph Hellwig 	if (blkdelta)
11551b040712SChristoph Hellwig 		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd);
11561b040712SChristoph Hellwig out:
11571884bd83SJesper Juhl 	ASSERT(error == 0);
11581b040712SChristoph Hellwig 	return;
11591da177e4SLinus Torvalds }
11601da177e4SLinus Torvalds 
11611da177e4SLinus Torvalds /*
1162e98c414fSChristoph Hellwig  * Add the given log item to the transaction's list of log items.
1163e98c414fSChristoph Hellwig  *
1164e98c414fSChristoph Hellwig  * The log item will now point to its new descriptor with its li_desc field.
1165e98c414fSChristoph Hellwig  */
1166e98c414fSChristoph Hellwig void
1167e98c414fSChristoph Hellwig xfs_trans_add_item(
1168e98c414fSChristoph Hellwig 	struct xfs_trans	*tp,
1169e98c414fSChristoph Hellwig 	struct xfs_log_item	*lip)
1170e98c414fSChristoph Hellwig {
1171e98c414fSChristoph Hellwig 	struct xfs_log_item_desc *lidp;
1172e98c414fSChristoph Hellwig 
1173f65020a8SJesper Juhl 	ASSERT(lip->li_mountp == tp->t_mountp);
1174f65020a8SJesper Juhl 	ASSERT(lip->li_ailp == tp->t_mountp->m_ail);
1175e98c414fSChristoph Hellwig 
117643869706SDave Chinner 	lidp = kmem_zone_zalloc(xfs_log_item_desc_zone, KM_SLEEP | KM_NOFS);
1177e98c414fSChristoph Hellwig 
1178e98c414fSChristoph Hellwig 	lidp->lid_item = lip;
1179e98c414fSChristoph Hellwig 	lidp->lid_flags = 0;
1180e98c414fSChristoph Hellwig 	list_add_tail(&lidp->lid_trans, &tp->t_items);
1181e98c414fSChristoph Hellwig 
1182e98c414fSChristoph Hellwig 	lip->li_desc = lidp;
1183e98c414fSChristoph Hellwig }
1184e98c414fSChristoph Hellwig 
1185e98c414fSChristoph Hellwig STATIC void
1186e98c414fSChristoph Hellwig xfs_trans_free_item_desc(
1187e98c414fSChristoph Hellwig 	struct xfs_log_item_desc *lidp)
1188e98c414fSChristoph Hellwig {
1189e98c414fSChristoph Hellwig 	list_del_init(&lidp->lid_trans);
1190e98c414fSChristoph Hellwig 	kmem_zone_free(xfs_log_item_desc_zone, lidp);
1191e98c414fSChristoph Hellwig }
1192e98c414fSChristoph Hellwig 
1193e98c414fSChristoph Hellwig /*
1194e98c414fSChristoph Hellwig  * Unlink and free the given descriptor.
1195e98c414fSChristoph Hellwig  */
1196e98c414fSChristoph Hellwig void
1197e98c414fSChristoph Hellwig xfs_trans_del_item(
1198e98c414fSChristoph Hellwig 	struct xfs_log_item	*lip)
1199e98c414fSChristoph Hellwig {
1200e98c414fSChristoph Hellwig 	xfs_trans_free_item_desc(lip->li_desc);
1201e98c414fSChristoph Hellwig 	lip->li_desc = NULL;
1202e98c414fSChristoph Hellwig }
1203e98c414fSChristoph Hellwig 
1204e98c414fSChristoph Hellwig /*
1205e98c414fSChristoph Hellwig  * Unlock all of the items of a transaction and free all the descriptors
1206e98c414fSChristoph Hellwig  * of that transaction.
1207e98c414fSChristoph Hellwig  */
1208d17c701cSDave Chinner void
1209e98c414fSChristoph Hellwig xfs_trans_free_items(
1210e98c414fSChristoph Hellwig 	struct xfs_trans	*tp,
1211e98c414fSChristoph Hellwig 	xfs_lsn_t		commit_lsn,
1212e98c414fSChristoph Hellwig 	int			flags)
1213e98c414fSChristoph Hellwig {
1214e98c414fSChristoph Hellwig 	struct xfs_log_item_desc *lidp, *next;
1215e98c414fSChristoph Hellwig 
1216e98c414fSChristoph Hellwig 	list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
1217e98c414fSChristoph Hellwig 		struct xfs_log_item	*lip = lidp->lid_item;
1218e98c414fSChristoph Hellwig 
1219e98c414fSChristoph Hellwig 		lip->li_desc = NULL;
1220e98c414fSChristoph Hellwig 
1221e98c414fSChristoph Hellwig 		if (commit_lsn != NULLCOMMITLSN)
1222e98c414fSChristoph Hellwig 			IOP_COMMITTING(lip, commit_lsn);
1223e98c414fSChristoph Hellwig 		if (flags & XFS_TRANS_ABORT)
1224e98c414fSChristoph Hellwig 			lip->li_flags |= XFS_LI_ABORTED;
1225e98c414fSChristoph Hellwig 		IOP_UNLOCK(lip);
1226e98c414fSChristoph Hellwig 
1227e98c414fSChristoph Hellwig 		xfs_trans_free_item_desc(lidp);
1228e98c414fSChristoph Hellwig 	}
1229e98c414fSChristoph Hellwig }
1230e98c414fSChristoph Hellwig 
12310e57f6a3SDave Chinner static inline void
12320e57f6a3SDave Chinner xfs_log_item_batch_insert(
12330e57f6a3SDave Chinner 	struct xfs_ail		*ailp,
12341d8c95a3SDave Chinner 	struct xfs_ail_cursor	*cur,
12350e57f6a3SDave Chinner 	struct xfs_log_item	**log_items,
12360e57f6a3SDave Chinner 	int			nr_items,
12370e57f6a3SDave Chinner 	xfs_lsn_t		commit_lsn)
12380e57f6a3SDave Chinner {
12390e57f6a3SDave Chinner 	int	i;
12400e57f6a3SDave Chinner 
12410e57f6a3SDave Chinner 	spin_lock(&ailp->xa_lock);
12420e57f6a3SDave Chinner 	/* xfs_trans_ail_update_bulk drops ailp->xa_lock */
12431d8c95a3SDave Chinner 	xfs_trans_ail_update_bulk(ailp, cur, log_items, nr_items, commit_lsn);
12440e57f6a3SDave Chinner 
12450e57f6a3SDave Chinner 	for (i = 0; i < nr_items; i++)
12460e57f6a3SDave Chinner 		IOP_UNPIN(log_items[i], 0);
12470e57f6a3SDave Chinner }
12480e57f6a3SDave Chinner 
12490e57f6a3SDave Chinner /*
12500e57f6a3SDave Chinner  * Bulk operation version of xfs_trans_committed that takes a log vector of
12510e57f6a3SDave Chinner  * items to insert into the AIL. This uses bulk AIL insertion techniques to
12520e57f6a3SDave Chinner  * minimise lock traffic.
1253e34a314cSDave Chinner  *
1254e34a314cSDave Chinner  * If we are called with the aborted flag set, it is because a log write during
1255e34a314cSDave Chinner  * a CIL checkpoint commit has failed. In this case, all the items in the
1256e34a314cSDave Chinner  * checkpoint have already gone through IOP_COMMITED and IOP_UNLOCK, which
1257e34a314cSDave Chinner  * means that checkpoint commit abort handling is treated exactly the same
1258e34a314cSDave Chinner  * as an iclog write error even though we haven't started any IO yet. Hence in
1259e34a314cSDave Chinner  * this case all we need to do is IOP_COMMITTED processing, followed by an
1260e34a314cSDave Chinner  * IOP_UNPIN(aborted) call.
12611d8c95a3SDave Chinner  *
12621d8c95a3SDave Chinner  * The AIL cursor is used to optimise the insert process. If commit_lsn is not
12631d8c95a3SDave Chinner  * at the end of the AIL, the insert cursor avoids the need to walk
12641d8c95a3SDave Chinner  * the AIL to find the insertion point on every xfs_log_item_batch_insert()
12651d8c95a3SDave Chinner  * call. This saves a lot of needless list walking and is a net win, even
12661d8c95a3SDave Chinner  * though it slightly increases that amount of AIL lock traffic to set it up
12671d8c95a3SDave Chinner  * and tear it down.
12680e57f6a3SDave Chinner  */
12690e57f6a3SDave Chinner void
12700e57f6a3SDave Chinner xfs_trans_committed_bulk(
12710e57f6a3SDave Chinner 	struct xfs_ail		*ailp,
12720e57f6a3SDave Chinner 	struct xfs_log_vec	*log_vector,
12730e57f6a3SDave Chinner 	xfs_lsn_t		commit_lsn,
12740e57f6a3SDave Chinner 	int			aborted)
12750e57f6a3SDave Chinner {
12760e57f6a3SDave Chinner #define LOG_ITEM_BATCH_SIZE	32
12770e57f6a3SDave Chinner 	struct xfs_log_item	*log_items[LOG_ITEM_BATCH_SIZE];
12780e57f6a3SDave Chinner 	struct xfs_log_vec	*lv;
12791d8c95a3SDave Chinner 	struct xfs_ail_cursor	cur;
12800e57f6a3SDave Chinner 	int			i = 0;
12810e57f6a3SDave Chinner 
12821d8c95a3SDave Chinner 	spin_lock(&ailp->xa_lock);
12831d8c95a3SDave Chinner 	xfs_trans_ail_cursor_last(ailp, &cur, commit_lsn);
12841d8c95a3SDave Chinner 	spin_unlock(&ailp->xa_lock);
12851d8c95a3SDave Chinner 
12860e57f6a3SDave Chinner 	/* unpin all the log items */
12870e57f6a3SDave Chinner 	for (lv = log_vector; lv; lv = lv->lv_next ) {
12880e57f6a3SDave Chinner 		struct xfs_log_item	*lip = lv->lv_item;
12890e57f6a3SDave Chinner 		xfs_lsn_t		item_lsn;
12900e57f6a3SDave Chinner 
12910e57f6a3SDave Chinner 		if (aborted)
12920e57f6a3SDave Chinner 			lip->li_flags |= XFS_LI_ABORTED;
12930e57f6a3SDave Chinner 		item_lsn = IOP_COMMITTED(lip, commit_lsn);
12940e57f6a3SDave Chinner 
12951316d4daSDave Chinner 		/* item_lsn of -1 means the item needs no further processing */
12960e57f6a3SDave Chinner 		if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0)
12970e57f6a3SDave Chinner 			continue;
12980e57f6a3SDave Chinner 
1299e34a314cSDave Chinner 		/*
1300e34a314cSDave Chinner 		 * if we are aborting the operation, no point in inserting the
1301e34a314cSDave Chinner 		 * object into the AIL as we are in a shutdown situation.
1302e34a314cSDave Chinner 		 */
1303e34a314cSDave Chinner 		if (aborted) {
1304e34a314cSDave Chinner 			ASSERT(XFS_FORCED_SHUTDOWN(ailp->xa_mount));
1305e34a314cSDave Chinner 			IOP_UNPIN(lip, 1);
1306e34a314cSDave Chinner 			continue;
1307e34a314cSDave Chinner 		}
1308e34a314cSDave Chinner 
13090e57f6a3SDave Chinner 		if (item_lsn != commit_lsn) {
13100e57f6a3SDave Chinner 
13110e57f6a3SDave Chinner 			/*
13120e57f6a3SDave Chinner 			 * Not a bulk update option due to unusual item_lsn.
13130e57f6a3SDave Chinner 			 * Push into AIL immediately, rechecking the lsn once
13141d8c95a3SDave Chinner 			 * we have the ail lock. Then unpin the item. This does
13151d8c95a3SDave Chinner 			 * not affect the AIL cursor the bulk insert path is
13161d8c95a3SDave Chinner 			 * using.
13170e57f6a3SDave Chinner 			 */
13180e57f6a3SDave Chinner 			spin_lock(&ailp->xa_lock);
13190e57f6a3SDave Chinner 			if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0)
13200e57f6a3SDave Chinner 				xfs_trans_ail_update(ailp, lip, item_lsn);
13210e57f6a3SDave Chinner 			else
13220e57f6a3SDave Chinner 				spin_unlock(&ailp->xa_lock);
13230e57f6a3SDave Chinner 			IOP_UNPIN(lip, 0);
13240e57f6a3SDave Chinner 			continue;
13250e57f6a3SDave Chinner 		}
13260e57f6a3SDave Chinner 
13270e57f6a3SDave Chinner 		/* Item is a candidate for bulk AIL insert.  */
13280e57f6a3SDave Chinner 		log_items[i++] = lv->lv_item;
13290e57f6a3SDave Chinner 		if (i >= LOG_ITEM_BATCH_SIZE) {
13301d8c95a3SDave Chinner 			xfs_log_item_batch_insert(ailp, &cur, log_items,
13310e57f6a3SDave Chinner 					LOG_ITEM_BATCH_SIZE, commit_lsn);
13320e57f6a3SDave Chinner 			i = 0;
13330e57f6a3SDave Chinner 		}
13340e57f6a3SDave Chinner 	}
13350e57f6a3SDave Chinner 
13360e57f6a3SDave Chinner 	/* make sure we insert the remainder! */
13370e57f6a3SDave Chinner 	if (i)
13381d8c95a3SDave Chinner 		xfs_log_item_batch_insert(ailp, &cur, log_items, i, commit_lsn);
13391d8c95a3SDave Chinner 
13401d8c95a3SDave Chinner 	spin_lock(&ailp->xa_lock);
13411d8c95a3SDave Chinner 	xfs_trans_ail_cursor_done(ailp, &cur);
13421d8c95a3SDave Chinner 	spin_unlock(&ailp->xa_lock);
13430e57f6a3SDave Chinner }
13440e57f6a3SDave Chinner 
1345b1c1b5b6SDave Chinner /*
1346b1037058SChristoph Hellwig  * Commit the given transaction to the log.
13470924378aSDave Chinner  *
13480924378aSDave Chinner  * XFS disk error handling mechanism is not based on a typical
13490924378aSDave Chinner  * transaction abort mechanism. Logically after the filesystem
13500924378aSDave Chinner  * gets marked 'SHUTDOWN', we can't let any new transactions
13510924378aSDave Chinner  * be durable - ie. committed to disk - because some metadata might
13520924378aSDave Chinner  * be inconsistent. In such cases, this returns an error, and the
13530924378aSDave Chinner  * caller may assume that all locked objects joined to the transaction
13540924378aSDave Chinner  * have already been unlocked as if the commit had succeeded.
13550924378aSDave Chinner  * Do not reference the transaction structure after this call.
13560924378aSDave Chinner  */
13570924378aSDave Chinner int
1358b1037058SChristoph Hellwig xfs_trans_commit(
1359a3ccd2caSChristoph Hellwig 	struct xfs_trans	*tp,
1360b1037058SChristoph Hellwig 	uint			flags)
13610924378aSDave Chinner {
1362a3ccd2caSChristoph Hellwig 	struct xfs_mount	*mp = tp->t_mountp;
13630924378aSDave Chinner 	xfs_lsn_t		commit_lsn = -1;
1364a3ccd2caSChristoph Hellwig 	int			error = 0;
13650924378aSDave Chinner 	int			log_flags = 0;
13660924378aSDave Chinner 	int			sync = tp->t_flags & XFS_TRANS_SYNC;
13670924378aSDave Chinner 
13680924378aSDave Chinner 	/*
13690924378aSDave Chinner 	 * Determine whether this commit is releasing a permanent
13700924378aSDave Chinner 	 * log reservation or not.
13710924378aSDave Chinner 	 */
13720924378aSDave Chinner 	if (flags & XFS_TRANS_RELEASE_LOG_RES) {
13730924378aSDave Chinner 		ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
13740924378aSDave Chinner 		log_flags = XFS_LOG_REL_PERM_RESERV;
13750924378aSDave Chinner 	}
13760924378aSDave Chinner 
13770924378aSDave Chinner 	/*
13780924378aSDave Chinner 	 * If there is nothing to be logged by the transaction,
13790924378aSDave Chinner 	 * then unlock all of the items associated with the
13800924378aSDave Chinner 	 * transaction and free the transaction structure.
13810924378aSDave Chinner 	 * Also make sure to return any reserved blocks to
13820924378aSDave Chinner 	 * the free pool.
13830924378aSDave Chinner 	 */
1384a3ccd2caSChristoph Hellwig 	if (!(tp->t_flags & XFS_TRANS_DIRTY))
1385a3ccd2caSChristoph Hellwig 		goto out_unreserve;
1386a3ccd2caSChristoph Hellwig 
1387a3ccd2caSChristoph Hellwig 	if (XFS_FORCED_SHUTDOWN(mp)) {
1388a3ccd2caSChristoph Hellwig 		error = XFS_ERROR(EIO);
1389a3ccd2caSChristoph Hellwig 		goto out_unreserve;
13900924378aSDave Chinner 	}
1391a3ccd2caSChristoph Hellwig 
13920924378aSDave Chinner 	ASSERT(tp->t_ticket != NULL);
13930924378aSDave Chinner 
13940924378aSDave Chinner 	/*
13950924378aSDave Chinner 	 * If we need to update the superblock, then do it now.
13960924378aSDave Chinner 	 */
13970924378aSDave Chinner 	if (tp->t_flags & XFS_TRANS_SB_DIRTY)
13980924378aSDave Chinner 		xfs_trans_apply_sb_deltas(tp);
13990924378aSDave Chinner 	xfs_trans_apply_dquot_deltas(tp);
14000924378aSDave Chinner 
14010244b960SChristoph Hellwig 	error = xfs_log_commit_cil(mp, tp, &commit_lsn, flags);
14020924378aSDave Chinner 	if (error == ENOMEM) {
14030924378aSDave Chinner 		xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
1404a3ccd2caSChristoph Hellwig 		error = XFS_ERROR(EIO);
1405a3ccd2caSChristoph Hellwig 		goto out_unreserve;
14060924378aSDave Chinner 	}
14071da177e4SLinus Torvalds 
14080244b960SChristoph Hellwig 	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
14090244b960SChristoph Hellwig 	xfs_trans_free(tp);
14100244b960SChristoph Hellwig 
14111da177e4SLinus Torvalds 	/*
14121da177e4SLinus Torvalds 	 * If the transaction needs to be synchronous, then force the
14131da177e4SLinus Torvalds 	 * log out now and wait for it.
14141da177e4SLinus Torvalds 	 */
14151da177e4SLinus Torvalds 	if (sync) {
1416f538d4daSChristoph Hellwig 		if (!error) {
1417a14a348bSChristoph Hellwig 			error = _xfs_log_force_lsn(mp, commit_lsn,
1418b1037058SChristoph Hellwig 				      XFS_LOG_SYNC, NULL);
1419f538d4daSChristoph Hellwig 		}
14201da177e4SLinus Torvalds 		XFS_STATS_INC(xs_trans_sync);
14211da177e4SLinus Torvalds 	} else {
14221da177e4SLinus Torvalds 		XFS_STATS_INC(xs_trans_async);
14231da177e4SLinus Torvalds 	}
14241da177e4SLinus Torvalds 
1425a3ccd2caSChristoph Hellwig 	return error;
1426a3ccd2caSChristoph Hellwig 
1427a3ccd2caSChristoph Hellwig out_unreserve:
1428a3ccd2caSChristoph Hellwig 	xfs_trans_unreserve_and_mod_sb(tp);
1429a3ccd2caSChristoph Hellwig 
1430a3ccd2caSChristoph Hellwig 	/*
1431a3ccd2caSChristoph Hellwig 	 * It is indeed possible for the transaction to be not dirty but
1432a3ccd2caSChristoph Hellwig 	 * the dqinfo portion to be.  All that means is that we have some
1433a3ccd2caSChristoph Hellwig 	 * (non-persistent) quota reservations that need to be unreserved.
1434a3ccd2caSChristoph Hellwig 	 */
1435a3ccd2caSChristoph Hellwig 	xfs_trans_unreserve_and_mod_dquots(tp);
1436a3ccd2caSChristoph Hellwig 	if (tp->t_ticket) {
1437a3ccd2caSChristoph Hellwig 		commit_lsn = xfs_log_done(mp, tp->t_ticket, NULL, log_flags);
1438a3ccd2caSChristoph Hellwig 		if (commit_lsn == -1 && !error)
1439a3ccd2caSChristoph Hellwig 			error = XFS_ERROR(EIO);
1440a3ccd2caSChristoph Hellwig 	}
1441a3ccd2caSChristoph Hellwig 	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
144271e330b5SDave Chinner 	xfs_trans_free_items(tp, NULLCOMMITLSN, error ? XFS_TRANS_ABORT : 0);
1443a3ccd2caSChristoph Hellwig 	xfs_trans_free(tp);
1444a3ccd2caSChristoph Hellwig 
1445a3ccd2caSChristoph Hellwig 	XFS_STATS_INC(xs_trans_empty);
1446a3ccd2caSChristoph Hellwig 	return error;
14471da177e4SLinus Torvalds }
14481da177e4SLinus Torvalds 
14491da177e4SLinus Torvalds /*
14501da177e4SLinus Torvalds  * Unlock all of the transaction's items and free the transaction.
14511da177e4SLinus Torvalds  * The transaction must not have modified any of its items, because
14521da177e4SLinus Torvalds  * there is no way to restore them to their previous state.
14531da177e4SLinus Torvalds  *
14541da177e4SLinus Torvalds  * If the transaction has made a log reservation, make sure to release
14551da177e4SLinus Torvalds  * it as well.
14561da177e4SLinus Torvalds  */
14571da177e4SLinus Torvalds void
14581da177e4SLinus Torvalds xfs_trans_cancel(
14591da177e4SLinus Torvalds 	xfs_trans_t		*tp,
14601da177e4SLinus Torvalds 	int			flags)
14611da177e4SLinus Torvalds {
14621da177e4SLinus Torvalds 	int			log_flags;
14630733af21SRyan Hankins 	xfs_mount_t		*mp = tp->t_mountp;
14641da177e4SLinus Torvalds 
14651da177e4SLinus Torvalds 	/*
14661da177e4SLinus Torvalds 	 * See if the caller is being too lazy to figure out if
14671da177e4SLinus Torvalds 	 * the transaction really needs an abort.
14681da177e4SLinus Torvalds 	 */
14691da177e4SLinus Torvalds 	if ((flags & XFS_TRANS_ABORT) && !(tp->t_flags & XFS_TRANS_DIRTY))
14701da177e4SLinus Torvalds 		flags &= ~XFS_TRANS_ABORT;
14711da177e4SLinus Torvalds 	/*
14721da177e4SLinus Torvalds 	 * See if the caller is relying on us to shut down the
14731da177e4SLinus Torvalds 	 * filesystem.  This happens in paths where we detect
14741da177e4SLinus Torvalds 	 * corruption and decide to give up.
14751da177e4SLinus Torvalds 	 */
147660a204f0SNathan Scott 	if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) {
14770733af21SRyan Hankins 		XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp);
14787d04a335SNathan Scott 		xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
147960a204f0SNathan Scott 	}
14801da177e4SLinus Torvalds #ifdef DEBUG
1481e98c414fSChristoph Hellwig 	if (!(flags & XFS_TRANS_ABORT) && !XFS_FORCED_SHUTDOWN(mp)) {
1482e98c414fSChristoph Hellwig 		struct xfs_log_item_desc *lidp;
14831da177e4SLinus Torvalds 
1484e98c414fSChristoph Hellwig 		list_for_each_entry(lidp, &tp->t_items, lid_trans)
1485e98c414fSChristoph Hellwig 			ASSERT(!(lidp->lid_item->li_type == XFS_LI_EFD));
14861da177e4SLinus Torvalds 	}
14871da177e4SLinus Torvalds #endif
14881da177e4SLinus Torvalds 	xfs_trans_unreserve_and_mod_sb(tp);
14897d095257SChristoph Hellwig 	xfs_trans_unreserve_and_mod_dquots(tp);
14901da177e4SLinus Torvalds 
14911da177e4SLinus Torvalds 	if (tp->t_ticket) {
14921da177e4SLinus Torvalds 		if (flags & XFS_TRANS_RELEASE_LOG_RES) {
14931da177e4SLinus Torvalds 			ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
14941da177e4SLinus Torvalds 			log_flags = XFS_LOG_REL_PERM_RESERV;
14951da177e4SLinus Torvalds 		} else {
14961da177e4SLinus Torvalds 			log_flags = 0;
14971da177e4SLinus Torvalds 		}
14980733af21SRyan Hankins 		xfs_log_done(mp, tp->t_ticket, NULL, log_flags);
14991da177e4SLinus Torvalds 	}
15001da177e4SLinus Torvalds 
15011da177e4SLinus Torvalds 	/* mark this thread as no longer being in a transaction */
150259c1b082SNathan Scott 	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
15031da177e4SLinus Torvalds 
150471e330b5SDave Chinner 	xfs_trans_free_items(tp, NULLCOMMITLSN, flags);
15051da177e4SLinus Torvalds 	xfs_trans_free(tp);
15061da177e4SLinus Torvalds }
15071da177e4SLinus Torvalds 
1508322ff6b8SNiv Sardi /*
1509322ff6b8SNiv Sardi  * Roll from one trans in the sequence of PERMANENT transactions to
1510322ff6b8SNiv Sardi  * the next: permanent transactions are only flushed out when
1511322ff6b8SNiv Sardi  * committed with XFS_TRANS_RELEASE_LOG_RES, but we still want as soon
1512322ff6b8SNiv Sardi  * as possible to let chunks of it go to the log. So we commit the
1513322ff6b8SNiv Sardi  * chunk we've been working on and get a new transaction to continue.
1514322ff6b8SNiv Sardi  */
1515322ff6b8SNiv Sardi int
1516322ff6b8SNiv Sardi xfs_trans_roll(
1517322ff6b8SNiv Sardi 	struct xfs_trans	**tpp,
1518322ff6b8SNiv Sardi 	struct xfs_inode	*dp)
1519322ff6b8SNiv Sardi {
1520322ff6b8SNiv Sardi 	struct xfs_trans	*trans;
1521322ff6b8SNiv Sardi 	unsigned int		logres, count;
1522322ff6b8SNiv Sardi 	int			error;
1523322ff6b8SNiv Sardi 
1524322ff6b8SNiv Sardi 	/*
1525322ff6b8SNiv Sardi 	 * Ensure that the inode is always logged.
1526322ff6b8SNiv Sardi 	 */
1527322ff6b8SNiv Sardi 	trans = *tpp;
1528322ff6b8SNiv Sardi 	xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE);
1529322ff6b8SNiv Sardi 
1530322ff6b8SNiv Sardi 	/*
1531322ff6b8SNiv Sardi 	 * Copy the critical parameters from one trans to the next.
1532322ff6b8SNiv Sardi 	 */
1533322ff6b8SNiv Sardi 	logres = trans->t_log_res;
1534322ff6b8SNiv Sardi 	count = trans->t_log_count;
1535322ff6b8SNiv Sardi 	*tpp = xfs_trans_dup(trans);
1536322ff6b8SNiv Sardi 
1537322ff6b8SNiv Sardi 	/*
1538322ff6b8SNiv Sardi 	 * Commit the current transaction.
1539322ff6b8SNiv Sardi 	 * If this commit failed, then it'd just unlock those items that
1540322ff6b8SNiv Sardi 	 * are not marked ihold. That also means that a filesystem shutdown
1541322ff6b8SNiv Sardi 	 * is in progress. The caller takes the responsibility to cancel
1542322ff6b8SNiv Sardi 	 * the duplicate transaction that gets returned.
1543322ff6b8SNiv Sardi 	 */
1544322ff6b8SNiv Sardi 	error = xfs_trans_commit(trans, 0);
1545322ff6b8SNiv Sardi 	if (error)
1546322ff6b8SNiv Sardi 		return (error);
1547322ff6b8SNiv Sardi 
1548322ff6b8SNiv Sardi 	trans = *tpp;
1549322ff6b8SNiv Sardi 
1550322ff6b8SNiv Sardi 	/*
1551cc09c0dcSDave Chinner 	 * transaction commit worked ok so we can drop the extra ticket
1552cc09c0dcSDave Chinner 	 * reference that we gained in xfs_trans_dup()
1553cc09c0dcSDave Chinner 	 */
1554cc09c0dcSDave Chinner 	xfs_log_ticket_put(trans->t_ticket);
1555cc09c0dcSDave Chinner 
1556cc09c0dcSDave Chinner 
1557cc09c0dcSDave Chinner 	/*
1558322ff6b8SNiv Sardi 	 * Reserve space in the log for th next transaction.
1559322ff6b8SNiv Sardi 	 * This also pushes items in the "AIL", the list of logged items,
1560322ff6b8SNiv Sardi 	 * out to disk if they are taking up space at the tail of the log
1561322ff6b8SNiv Sardi 	 * that we want to use.  This requires that either nothing be locked
1562322ff6b8SNiv Sardi 	 * across this call, or that anything that is locked be logged in
1563322ff6b8SNiv Sardi 	 * the prior and the next transactions.
1564322ff6b8SNiv Sardi 	 */
1565322ff6b8SNiv Sardi 	error = xfs_trans_reserve(trans, 0, logres, 0,
1566322ff6b8SNiv Sardi 				  XFS_TRANS_PERM_LOG_RES, count);
1567322ff6b8SNiv Sardi 	/*
1568322ff6b8SNiv Sardi 	 *  Ensure that the inode is in the new transaction and locked.
1569322ff6b8SNiv Sardi 	 */
1570322ff6b8SNiv Sardi 	if (error)
1571322ff6b8SNiv Sardi 		return error;
1572322ff6b8SNiv Sardi 
1573ddc3415aSChristoph Hellwig 	xfs_trans_ijoin(trans, dp, 0);
1574322ff6b8SNiv Sardi 	return 0;
1575322ff6b8SNiv Sardi }
1576