diff options
Diffstat (limited to 'fs/xfs/xfs_trans.c')
-rw-r--r-- | fs/xfs/xfs_trans.c | 590 |
1 files changed, 508 insertions, 82 deletions
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index be578ecb4af2..28547dfce037 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -44,137 +44,493 @@ | |||
44 | #include "xfs_trans_priv.h" | 44 | #include "xfs_trans_priv.h" |
45 | #include "xfs_trans_space.h" | 45 | #include "xfs_trans_space.h" |
46 | #include "xfs_inode_item.h" | 46 | #include "xfs_inode_item.h" |
47 | #include "xfs_trace.h" | ||
47 | 48 | ||
48 | kmem_zone_t *xfs_trans_zone; | 49 | kmem_zone_t *xfs_trans_zone; |
49 | 50 | ||
51 | |||
52 | /* | ||
53 | * Various log reservation values. | ||
54 | * | ||
55 | * These are based on the size of the file system block because that is what | ||
56 | * most transactions manipulate. Each adds in an additional 128 bytes per | ||
57 | * item logged to try to account for the overhead of the transaction mechanism. | ||
58 | * | ||
59 | * Note: Most of the reservations underestimate the number of allocation | ||
60 | * groups into which they could free extents in the xfs_bmap_finish() call. | ||
61 | * This is because the number in the worst case is quite high and quite | ||
62 | * unusual. In order to fix this we need to change xfs_bmap_finish() to free | ||
63 | * extents in only a single AG at a time. This will require changes to the | ||
64 | * EFI code as well, however, so that the EFI for the extents not freed is | ||
65 | * logged again in each transaction. See SGI PV #261917. | ||
66 | * | ||
67 | * Reservation functions here avoid a huge stack in xfs_trans_init due to | ||
68 | * register overflow from temporaries in the calculations. | ||
69 | */ | ||
70 | |||
71 | |||
50 | /* | 72 | /* |
51 | * Reservation functions here avoid a huge stack in xfs_trans_init | 73 | * In a write transaction we can allocate a maximum of 2 |
52 | * due to register overflow from temporaries in the calculations. | 74 | * extents. This gives: |
75 | * the inode getting the new extents: inode size | ||
76 | * the inode's bmap btree: max depth * block size | ||
77 | * the agfs of the ags from which the extents are allocated: 2 * sector | ||
78 | * the superblock free block counter: sector size | ||
79 | * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size | ||
80 | * And the bmap_finish transaction can free bmap blocks in a join: | ||
81 | * the agfs of the ags containing the blocks: 2 * sector size | ||
82 | * the agfls of the ags containing the blocks: 2 * sector size | ||
83 | * the super block free block counter: sector size | ||
84 | * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size | ||
53 | */ | 85 | */ |
54 | STATIC uint | 86 | STATIC uint |
55 | xfs_calc_write_reservation(xfs_mount_t *mp) | 87 | xfs_calc_write_reservation( |
88 | struct xfs_mount *mp) | ||
56 | { | 89 | { |
57 | return XFS_CALC_WRITE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 90 | return XFS_DQUOT_LOGRES(mp) + |
91 | MAX((mp->m_sb.sb_inodesize + | ||
92 | XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) + | ||
93 | 2 * mp->m_sb.sb_sectsize + | ||
94 | mp->m_sb.sb_sectsize + | ||
95 | XFS_ALLOCFREE_LOG_RES(mp, 2) + | ||
96 | 128 * (4 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + | ||
97 | XFS_ALLOCFREE_LOG_COUNT(mp, 2))), | ||
98 | (2 * mp->m_sb.sb_sectsize + | ||
99 | 2 * mp->m_sb.sb_sectsize + | ||
100 | mp->m_sb.sb_sectsize + | ||
101 | XFS_ALLOCFREE_LOG_RES(mp, 2) + | ||
102 | 128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2)))); | ||
58 | } | 103 | } |
59 | 104 | ||
105 | /* | ||
106 | * In truncating a file we free up to two extents at once. We can modify: | ||
107 | * the inode being truncated: inode size | ||
108 | * the inode's bmap btree: (max depth + 1) * block size | ||
109 | * And the bmap_finish transaction can free the blocks and bmap blocks: | ||
110 | * the agf for each of the ags: 4 * sector size | ||
111 | * the agfl for each of the ags: 4 * sector size | ||
112 | * the super block to reflect the freed blocks: sector size | ||
113 | * worst case split in allocation btrees per extent assuming 4 extents: | ||
114 | * 4 exts * 2 trees * (2 * max depth - 1) * block size | ||
115 | * the inode btree: max depth * blocksize | ||
116 | * the allocation btrees: 2 trees * (max depth - 1) * block size | ||
117 | */ | ||
60 | STATIC uint | 118 | STATIC uint |
61 | xfs_calc_itruncate_reservation(xfs_mount_t *mp) | 119 | xfs_calc_itruncate_reservation( |
120 | struct xfs_mount *mp) | ||
62 | { | 121 | { |
63 | return XFS_CALC_ITRUNCATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 122 | return XFS_DQUOT_LOGRES(mp) + |
123 | MAX((mp->m_sb.sb_inodesize + | ||
124 | XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1) + | ||
125 | 128 * (2 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))), | ||
126 | (4 * mp->m_sb.sb_sectsize + | ||
127 | 4 * mp->m_sb.sb_sectsize + | ||
128 | mp->m_sb.sb_sectsize + | ||
129 | XFS_ALLOCFREE_LOG_RES(mp, 4) + | ||
130 | 128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4)) + | ||
131 | 128 * 5 + | ||
132 | XFS_ALLOCFREE_LOG_RES(mp, 1) + | ||
133 | 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels + | ||
134 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))); | ||
64 | } | 135 | } |
65 | 136 | ||
137 | /* | ||
138 | * In renaming a files we can modify: | ||
139 | * the four inodes involved: 4 * inode size | ||
140 | * the two directory btrees: 2 * (max depth + v2) * dir block size | ||
141 | * the two directory bmap btrees: 2 * max depth * block size | ||
142 | * And the bmap_finish transaction can free dir and bmap blocks (two sets | ||
143 | * of bmap blocks) giving: | ||
144 | * the agf for the ags in which the blocks live: 3 * sector size | ||
145 | * the agfl for the ags in which the blocks live: 3 * sector size | ||
146 | * the superblock for the free block count: sector size | ||
147 | * the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size | ||
148 | */ | ||
66 | STATIC uint | 149 | STATIC uint |
67 | xfs_calc_rename_reservation(xfs_mount_t *mp) | 150 | xfs_calc_rename_reservation( |
151 | struct xfs_mount *mp) | ||
68 | { | 152 | { |
69 | return XFS_CALC_RENAME_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 153 | return XFS_DQUOT_LOGRES(mp) + |
154 | MAX((4 * mp->m_sb.sb_inodesize + | ||
155 | 2 * XFS_DIROP_LOG_RES(mp) + | ||
156 | 128 * (4 + 2 * XFS_DIROP_LOG_COUNT(mp))), | ||
157 | (3 * mp->m_sb.sb_sectsize + | ||
158 | 3 * mp->m_sb.sb_sectsize + | ||
159 | mp->m_sb.sb_sectsize + | ||
160 | XFS_ALLOCFREE_LOG_RES(mp, 3) + | ||
161 | 128 * (7 + XFS_ALLOCFREE_LOG_COUNT(mp, 3)))); | ||
70 | } | 162 | } |
71 | 163 | ||
164 | /* | ||
165 | * For creating a link to an inode: | ||
166 | * the parent directory inode: inode size | ||
167 | * the linked inode: inode size | ||
168 | * the directory btree could split: (max depth + v2) * dir block size | ||
169 | * the directory bmap btree could join or split: (max depth + v2) * blocksize | ||
170 | * And the bmap_finish transaction can free some bmap blocks giving: | ||
171 | * the agf for the ag in which the blocks live: sector size | ||
172 | * the agfl for the ag in which the blocks live: sector size | ||
173 | * the superblock for the free block count: sector size | ||
174 | * the allocation btrees: 2 trees * (2 * max depth - 1) * block size | ||
175 | */ | ||
72 | STATIC uint | 176 | STATIC uint |
73 | xfs_calc_link_reservation(xfs_mount_t *mp) | 177 | xfs_calc_link_reservation( |
178 | struct xfs_mount *mp) | ||
74 | { | 179 | { |
75 | return XFS_CALC_LINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 180 | return XFS_DQUOT_LOGRES(mp) + |
181 | MAX((mp->m_sb.sb_inodesize + | ||
182 | mp->m_sb.sb_inodesize + | ||
183 | XFS_DIROP_LOG_RES(mp) + | ||
184 | 128 * (2 + XFS_DIROP_LOG_COUNT(mp))), | ||
185 | (mp->m_sb.sb_sectsize + | ||
186 | mp->m_sb.sb_sectsize + | ||
187 | mp->m_sb.sb_sectsize + | ||
188 | XFS_ALLOCFREE_LOG_RES(mp, 1) + | ||
189 | 128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1)))); | ||
76 | } | 190 | } |
77 | 191 | ||
192 | /* | ||
193 | * For removing a directory entry we can modify: | ||
194 | * the parent directory inode: inode size | ||
195 | * the removed inode: inode size | ||
196 | * the directory btree could join: (max depth + v2) * dir block size | ||
197 | * the directory bmap btree could join or split: (max depth + v2) * blocksize | ||
198 | * And the bmap_finish transaction can free the dir and bmap blocks giving: | ||
199 | * the agf for the ag in which the blocks live: 2 * sector size | ||
200 | * the agfl for the ag in which the blocks live: 2 * sector size | ||
201 | * the superblock for the free block count: sector size | ||
202 | * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size | ||
203 | */ | ||
78 | STATIC uint | 204 | STATIC uint |
79 | xfs_calc_remove_reservation(xfs_mount_t *mp) | 205 | xfs_calc_remove_reservation( |
206 | struct xfs_mount *mp) | ||
80 | { | 207 | { |
81 | return XFS_CALC_REMOVE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 208 | return XFS_DQUOT_LOGRES(mp) + |
209 | MAX((mp->m_sb.sb_inodesize + | ||
210 | mp->m_sb.sb_inodesize + | ||
211 | XFS_DIROP_LOG_RES(mp) + | ||
212 | 128 * (2 + XFS_DIROP_LOG_COUNT(mp))), | ||
213 | (2 * mp->m_sb.sb_sectsize + | ||
214 | 2 * mp->m_sb.sb_sectsize + | ||
215 | mp->m_sb.sb_sectsize + | ||
216 | XFS_ALLOCFREE_LOG_RES(mp, 2) + | ||
217 | 128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2)))); | ||
82 | } | 218 | } |
83 | 219 | ||
220 | /* | ||
221 | * For symlink we can modify: | ||
222 | * the parent directory inode: inode size | ||
223 | * the new inode: inode size | ||
224 | * the inode btree entry: 1 block | ||
225 | * the directory btree: (max depth + v2) * dir block size | ||
226 | * the directory inode's bmap btree: (max depth + v2) * block size | ||
227 | * the blocks for the symlink: 1 kB | ||
228 | * Or in the first xact we allocate some inodes giving: | ||
229 | * the agi and agf of the ag getting the new inodes: 2 * sectorsize | ||
230 | * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize | ||
231 | * the inode btree: max depth * blocksize | ||
232 | * the allocation btrees: 2 trees * (2 * max depth - 1) * block size | ||
233 | */ | ||
84 | STATIC uint | 234 | STATIC uint |
85 | xfs_calc_symlink_reservation(xfs_mount_t *mp) | 235 | xfs_calc_symlink_reservation( |
236 | struct xfs_mount *mp) | ||
86 | { | 237 | { |
87 | return XFS_CALC_SYMLINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 238 | return XFS_DQUOT_LOGRES(mp) + |
239 | MAX((mp->m_sb.sb_inodesize + | ||
240 | mp->m_sb.sb_inodesize + | ||
241 | XFS_FSB_TO_B(mp, 1) + | ||
242 | XFS_DIROP_LOG_RES(mp) + | ||
243 | 1024 + | ||
244 | 128 * (4 + XFS_DIROP_LOG_COUNT(mp))), | ||
245 | (2 * mp->m_sb.sb_sectsize + | ||
246 | XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) + | ||
247 | XFS_FSB_TO_B(mp, mp->m_in_maxlevels) + | ||
248 | XFS_ALLOCFREE_LOG_RES(mp, 1) + | ||
249 | 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels + | ||
250 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))); | ||
88 | } | 251 | } |
89 | 252 | ||
253 | /* | ||
254 | * For create we can modify: | ||
255 | * the parent directory inode: inode size | ||
256 | * the new inode: inode size | ||
257 | * the inode btree entry: block size | ||
258 | * the superblock for the nlink flag: sector size | ||
259 | * the directory btree: (max depth + v2) * dir block size | ||
260 | * the directory inode's bmap btree: (max depth + v2) * block size | ||
261 | * Or in the first xact we allocate some inodes giving: | ||
262 | * the agi and agf of the ag getting the new inodes: 2 * sectorsize | ||
263 | * the superblock for the nlink flag: sector size | ||
264 | * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize | ||
265 | * the inode btree: max depth * blocksize | ||
266 | * the allocation btrees: 2 trees * (max depth - 1) * block size | ||
267 | */ | ||
90 | STATIC uint | 268 | STATIC uint |
91 | xfs_calc_create_reservation(xfs_mount_t *mp) | 269 | xfs_calc_create_reservation( |
270 | struct xfs_mount *mp) | ||
92 | { | 271 | { |
93 | return XFS_CALC_CREATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 272 | return XFS_DQUOT_LOGRES(mp) + |
273 | MAX((mp->m_sb.sb_inodesize + | ||
274 | mp->m_sb.sb_inodesize + | ||
275 | mp->m_sb.sb_sectsize + | ||
276 | XFS_FSB_TO_B(mp, 1) + | ||
277 | XFS_DIROP_LOG_RES(mp) + | ||
278 | 128 * (3 + XFS_DIROP_LOG_COUNT(mp))), | ||
279 | (3 * mp->m_sb.sb_sectsize + | ||
280 | XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) + | ||
281 | XFS_FSB_TO_B(mp, mp->m_in_maxlevels) + | ||
282 | XFS_ALLOCFREE_LOG_RES(mp, 1) + | ||
283 | 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels + | ||
284 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))); | ||
94 | } | 285 | } |
95 | 286 | ||
287 | /* | ||
288 | * Making a new directory is the same as creating a new file. | ||
289 | */ | ||
96 | STATIC uint | 290 | STATIC uint |
97 | xfs_calc_mkdir_reservation(xfs_mount_t *mp) | 291 | xfs_calc_mkdir_reservation( |
292 | struct xfs_mount *mp) | ||
98 | { | 293 | { |
99 | return XFS_CALC_MKDIR_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 294 | return xfs_calc_create_reservation(mp); |
100 | } | 295 | } |
101 | 296 | ||
297 | /* | ||
298 | * In freeing an inode we can modify: | ||
299 | * the inode being freed: inode size | ||
300 | * the super block free inode counter: sector size | ||
301 | * the agi hash list and counters: sector size | ||
302 | * the inode btree entry: block size | ||
303 | * the on disk inode before ours in the agi hash list: inode cluster size | ||
304 | * the inode btree: max depth * blocksize | ||
305 | * the allocation btrees: 2 trees * (max depth - 1) * block size | ||
306 | */ | ||
102 | STATIC uint | 307 | STATIC uint |
103 | xfs_calc_ifree_reservation(xfs_mount_t *mp) | 308 | xfs_calc_ifree_reservation( |
309 | struct xfs_mount *mp) | ||
104 | { | 310 | { |
105 | return XFS_CALC_IFREE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 311 | return XFS_DQUOT_LOGRES(mp) + |
312 | mp->m_sb.sb_inodesize + | ||
313 | mp->m_sb.sb_sectsize + | ||
314 | mp->m_sb.sb_sectsize + | ||
315 | XFS_FSB_TO_B(mp, 1) + | ||
316 | MAX((__uint16_t)XFS_FSB_TO_B(mp, 1), | ||
317 | XFS_INODE_CLUSTER_SIZE(mp)) + | ||
318 | 128 * 5 + | ||
319 | XFS_ALLOCFREE_LOG_RES(mp, 1) + | ||
320 | 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels + | ||
321 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)); | ||
106 | } | 322 | } |
107 | 323 | ||
324 | /* | ||
325 | * When only changing the inode we log the inode and possibly the superblock | ||
326 | * We also add a bit of slop for the transaction stuff. | ||
327 | */ | ||
108 | STATIC uint | 328 | STATIC uint |
109 | xfs_calc_ichange_reservation(xfs_mount_t *mp) | 329 | xfs_calc_ichange_reservation( |
330 | struct xfs_mount *mp) | ||
110 | { | 331 | { |
111 | return XFS_CALC_ICHANGE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 332 | return XFS_DQUOT_LOGRES(mp) + |
333 | mp->m_sb.sb_inodesize + | ||
334 | mp->m_sb.sb_sectsize + | ||
335 | 512; | ||
336 | |||
112 | } | 337 | } |
113 | 338 | ||
339 | /* | ||
340 | * Growing the data section of the filesystem. | ||
341 | * superblock | ||
342 | * agi and agf | ||
343 | * allocation btrees | ||
344 | */ | ||
114 | STATIC uint | 345 | STATIC uint |
115 | xfs_calc_growdata_reservation(xfs_mount_t *mp) | 346 | xfs_calc_growdata_reservation( |
347 | struct xfs_mount *mp) | ||
116 | { | 348 | { |
117 | return XFS_CALC_GROWDATA_LOG_RES(mp); | 349 | return mp->m_sb.sb_sectsize * 3 + |
350 | XFS_ALLOCFREE_LOG_RES(mp, 1) + | ||
351 | 128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1)); | ||
118 | } | 352 | } |
119 | 353 | ||
354 | /* | ||
355 | * Growing the rt section of the filesystem. | ||
356 | * In the first set of transactions (ALLOC) we allocate space to the | ||
357 | * bitmap or summary files. | ||
358 | * superblock: sector size | ||
359 | * agf of the ag from which the extent is allocated: sector size | ||
360 | * bmap btree for bitmap/summary inode: max depth * blocksize | ||
361 | * bitmap/summary inode: inode size | ||
362 | * allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize | ||
363 | */ | ||
120 | STATIC uint | 364 | STATIC uint |
121 | xfs_calc_growrtalloc_reservation(xfs_mount_t *mp) | 365 | xfs_calc_growrtalloc_reservation( |
366 | struct xfs_mount *mp) | ||
122 | { | 367 | { |
123 | return XFS_CALC_GROWRTALLOC_LOG_RES(mp); | 368 | return 2 * mp->m_sb.sb_sectsize + |
369 | XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) + | ||
370 | mp->m_sb.sb_inodesize + | ||
371 | XFS_ALLOCFREE_LOG_RES(mp, 1) + | ||
372 | 128 * (3 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + | ||
373 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)); | ||
124 | } | 374 | } |
125 | 375 | ||
376 | /* | ||
377 | * Growing the rt section of the filesystem. | ||
378 | * In the second set of transactions (ZERO) we zero the new metadata blocks. | ||
379 | * one bitmap/summary block: blocksize | ||
380 | */ | ||
126 | STATIC uint | 381 | STATIC uint |
127 | xfs_calc_growrtzero_reservation(xfs_mount_t *mp) | 382 | xfs_calc_growrtzero_reservation( |
383 | struct xfs_mount *mp) | ||
128 | { | 384 | { |
129 | return XFS_CALC_GROWRTZERO_LOG_RES(mp); | 385 | return mp->m_sb.sb_blocksize + 128; |
130 | } | 386 | } |
131 | 387 | ||
388 | /* | ||
389 | * Growing the rt section of the filesystem. | ||
390 | * In the third set of transactions (FREE) we update metadata without | ||
391 | * allocating any new blocks. | ||
392 | * superblock: sector size | ||
393 | * bitmap inode: inode size | ||
394 | * summary inode: inode size | ||
395 | * one bitmap block: blocksize | ||
396 | * summary blocks: new summary size | ||
397 | */ | ||
132 | STATIC uint | 398 | STATIC uint |
133 | xfs_calc_growrtfree_reservation(xfs_mount_t *mp) | 399 | xfs_calc_growrtfree_reservation( |
400 | struct xfs_mount *mp) | ||
134 | { | 401 | { |
135 | return XFS_CALC_GROWRTFREE_LOG_RES(mp); | 402 | return mp->m_sb.sb_sectsize + |
403 | 2 * mp->m_sb.sb_inodesize + | ||
404 | mp->m_sb.sb_blocksize + | ||
405 | mp->m_rsumsize + | ||
406 | 128 * 5; | ||
136 | } | 407 | } |
137 | 408 | ||
409 | /* | ||
410 | * Logging the inode modification timestamp on a synchronous write. | ||
411 | * inode | ||
412 | */ | ||
138 | STATIC uint | 413 | STATIC uint |
139 | xfs_calc_swrite_reservation(xfs_mount_t *mp) | 414 | xfs_calc_swrite_reservation( |
415 | struct xfs_mount *mp) | ||
140 | { | 416 | { |
141 | return XFS_CALC_SWRITE_LOG_RES(mp); | 417 | return mp->m_sb.sb_inodesize + 128; |
142 | } | 418 | } |
143 | 419 | ||
420 | /* | ||
421 | * Logging the inode mode bits when writing a setuid/setgid file | ||
422 | * inode | ||
423 | */ | ||
144 | STATIC uint | 424 | STATIC uint |
145 | xfs_calc_writeid_reservation(xfs_mount_t *mp) | 425 | xfs_calc_writeid_reservation(xfs_mount_t *mp) |
146 | { | 426 | { |
147 | return XFS_CALC_WRITEID_LOG_RES(mp); | 427 | return mp->m_sb.sb_inodesize + 128; |
148 | } | 428 | } |
149 | 429 | ||
430 | /* | ||
431 | * Converting the inode from non-attributed to attributed. | ||
432 | * the inode being converted: inode size | ||
433 | * agf block and superblock (for block allocation) | ||
434 | * the new block (directory sized) | ||
435 | * bmap blocks for the new directory block | ||
436 | * allocation btrees | ||
437 | */ | ||
150 | STATIC uint | 438 | STATIC uint |
151 | xfs_calc_addafork_reservation(xfs_mount_t *mp) | 439 | xfs_calc_addafork_reservation( |
440 | struct xfs_mount *mp) | ||
152 | { | 441 | { |
153 | return XFS_CALC_ADDAFORK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 442 | return XFS_DQUOT_LOGRES(mp) + |
443 | mp->m_sb.sb_inodesize + | ||
444 | mp->m_sb.sb_sectsize * 2 + | ||
445 | mp->m_dirblksize + | ||
446 | XFS_FSB_TO_B(mp, XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + | ||
447 | XFS_ALLOCFREE_LOG_RES(mp, 1) + | ||
448 | 128 * (4 + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1 + | ||
449 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)); | ||
154 | } | 450 | } |
155 | 451 | ||
452 | /* | ||
453 | * Removing the attribute fork of a file | ||
454 | * the inode being truncated: inode size | ||
455 | * the inode's bmap btree: max depth * block size | ||
456 | * And the bmap_finish transaction can free the blocks and bmap blocks: | ||
457 | * the agf for each of the ags: 4 * sector size | ||
458 | * the agfl for each of the ags: 4 * sector size | ||
459 | * the super block to reflect the freed blocks: sector size | ||
460 | * worst case split in allocation btrees per extent assuming 4 extents: | ||
461 | * 4 exts * 2 trees * (2 * max depth - 1) * block size | ||
462 | */ | ||
156 | STATIC uint | 463 | STATIC uint |
157 | xfs_calc_attrinval_reservation(xfs_mount_t *mp) | 464 | xfs_calc_attrinval_reservation( |
465 | struct xfs_mount *mp) | ||
158 | { | 466 | { |
159 | return XFS_CALC_ATTRINVAL_LOG_RES(mp); | 467 | return MAX((mp->m_sb.sb_inodesize + |
468 | XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + | ||
469 | 128 * (1 + XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK))), | ||
470 | (4 * mp->m_sb.sb_sectsize + | ||
471 | 4 * mp->m_sb.sb_sectsize + | ||
472 | mp->m_sb.sb_sectsize + | ||
473 | XFS_ALLOCFREE_LOG_RES(mp, 4) + | ||
474 | 128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4)))); | ||
160 | } | 475 | } |
161 | 476 | ||
477 | /* | ||
478 | * Setting an attribute. | ||
479 | * the inode getting the attribute | ||
480 | * the superblock for allocations | ||
481 | * the agfs extents are allocated from | ||
482 | * the attribute btree * max depth | ||
483 | * the inode allocation btree | ||
484 | * Since attribute transaction space is dependent on the size of the attribute, | ||
485 | * the calculation is done partially at mount time and partially at runtime. | ||
486 | */ | ||
162 | STATIC uint | 487 | STATIC uint |
163 | xfs_calc_attrset_reservation(xfs_mount_t *mp) | 488 | xfs_calc_attrset_reservation( |
489 | struct xfs_mount *mp) | ||
164 | { | 490 | { |
165 | return XFS_CALC_ATTRSET_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 491 | return XFS_DQUOT_LOGRES(mp) + |
492 | mp->m_sb.sb_inodesize + | ||
493 | mp->m_sb.sb_sectsize + | ||
494 | XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) + | ||
495 | 128 * (2 + XFS_DA_NODE_MAXDEPTH); | ||
166 | } | 496 | } |
167 | 497 | ||
498 | /* | ||
499 | * Removing an attribute. | ||
500 | * the inode: inode size | ||
501 | * the attribute btree could join: max depth * block size | ||
502 | * the inode bmap btree could join or split: max depth * block size | ||
503 | * And the bmap_finish transaction can free the attr blocks freed giving: | ||
504 | * the agf for the ag in which the blocks live: 2 * sector size | ||
505 | * the agfl for the ag in which the blocks live: 2 * sector size | ||
506 | * the superblock for the free block count: sector size | ||
507 | * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size | ||
508 | */ | ||
168 | STATIC uint | 509 | STATIC uint |
169 | xfs_calc_attrrm_reservation(xfs_mount_t *mp) | 510 | xfs_calc_attrrm_reservation( |
511 | struct xfs_mount *mp) | ||
170 | { | 512 | { |
171 | return XFS_CALC_ATTRRM_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp); | 513 | return XFS_DQUOT_LOGRES(mp) + |
514 | MAX((mp->m_sb.sb_inodesize + | ||
515 | XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) + | ||
516 | XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + | ||
517 | 128 * (1 + XFS_DA_NODE_MAXDEPTH + | ||
518 | XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))), | ||
519 | (2 * mp->m_sb.sb_sectsize + | ||
520 | 2 * mp->m_sb.sb_sectsize + | ||
521 | mp->m_sb.sb_sectsize + | ||
522 | XFS_ALLOCFREE_LOG_RES(mp, 2) + | ||
523 | 128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2)))); | ||
172 | } | 524 | } |
173 | 525 | ||
526 | /* | ||
527 | * Clearing a bad agino number in an agi hash bucket. | ||
528 | */ | ||
174 | STATIC uint | 529 | STATIC uint |
175 | xfs_calc_clear_agi_bucket_reservation(xfs_mount_t *mp) | 530 | xfs_calc_clear_agi_bucket_reservation( |
531 | struct xfs_mount *mp) | ||
176 | { | 532 | { |
177 | return XFS_CALC_CLEAR_AGI_BUCKET_LOG_RES(mp); | 533 | return mp->m_sb.sb_sectsize + 128; |
178 | } | 534 | } |
179 | 535 | ||
180 | /* | 536 | /* |
@@ -183,11 +539,10 @@ xfs_calc_clear_agi_bucket_reservation(xfs_mount_t *mp) | |||
183 | */ | 539 | */ |
184 | void | 540 | void |
185 | xfs_trans_init( | 541 | xfs_trans_init( |
186 | xfs_mount_t *mp) | 542 | struct xfs_mount *mp) |
187 | { | 543 | { |
188 | xfs_trans_reservations_t *resp; | 544 | struct xfs_trans_reservations *resp = &mp->m_reservations; |
189 | 545 | ||
190 | resp = &(mp->m_reservations); | ||
191 | resp->tr_write = xfs_calc_write_reservation(mp); | 546 | resp->tr_write = xfs_calc_write_reservation(mp); |
192 | resp->tr_itruncate = xfs_calc_itruncate_reservation(mp); | 547 | resp->tr_itruncate = xfs_calc_itruncate_reservation(mp); |
193 | resp->tr_rename = xfs_calc_rename_reservation(mp); | 548 | resp->tr_rename = xfs_calc_rename_reservation(mp); |
@@ -243,9 +598,8 @@ _xfs_trans_alloc( | |||
243 | tp->t_type = type; | 598 | tp->t_type = type; |
244 | tp->t_mountp = mp; | 599 | tp->t_mountp = mp; |
245 | tp->t_items_free = XFS_LIC_NUM_SLOTS; | 600 | tp->t_items_free = XFS_LIC_NUM_SLOTS; |
246 | tp->t_busy_free = XFS_LBC_NUM_SLOTS; | ||
247 | xfs_lic_init(&(tp->t_items)); | 601 | xfs_lic_init(&(tp->t_items)); |
248 | XFS_LBC_INIT(&(tp->t_busy)); | 602 | INIT_LIST_HEAD(&tp->t_busy); |
249 | return tp; | 603 | return tp; |
250 | } | 604 | } |
251 | 605 | ||
@@ -255,8 +609,13 @@ _xfs_trans_alloc( | |||
255 | */ | 609 | */ |
256 | STATIC void | 610 | STATIC void |
257 | xfs_trans_free( | 611 | xfs_trans_free( |
258 | xfs_trans_t *tp) | 612 | struct xfs_trans *tp) |
259 | { | 613 | { |
614 | struct xfs_busy_extent *busyp, *n; | ||
615 | |||
616 | list_for_each_entry_safe(busyp, n, &tp->t_busy, list) | ||
617 | xfs_alloc_busy_clear(tp->t_mountp, busyp); | ||
618 | |||
260 | atomic_dec(&tp->t_mountp->m_active_trans); | 619 | atomic_dec(&tp->t_mountp->m_active_trans); |
261 | xfs_trans_free_dqinfo(tp); | 620 | xfs_trans_free_dqinfo(tp); |
262 | kmem_zone_free(xfs_trans_zone, tp); | 621 | kmem_zone_free(xfs_trans_zone, tp); |
@@ -285,9 +644,8 @@ xfs_trans_dup( | |||
285 | ntp->t_type = tp->t_type; | 644 | ntp->t_type = tp->t_type; |
286 | ntp->t_mountp = tp->t_mountp; | 645 | ntp->t_mountp = tp->t_mountp; |
287 | ntp->t_items_free = XFS_LIC_NUM_SLOTS; | 646 | ntp->t_items_free = XFS_LIC_NUM_SLOTS; |
288 | ntp->t_busy_free = XFS_LBC_NUM_SLOTS; | ||
289 | xfs_lic_init(&(ntp->t_items)); | 647 | xfs_lic_init(&(ntp->t_items)); |
290 | XFS_LBC_INIT(&(ntp->t_busy)); | 648 | INIT_LIST_HEAD(&ntp->t_busy); |
291 | 649 | ||
292 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); | 650 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); |
293 | ASSERT(tp->t_ticket != NULL); | 651 | ASSERT(tp->t_ticket != NULL); |
@@ -423,7 +781,6 @@ undo_blocks: | |||
423 | return error; | 781 | return error; |
424 | } | 782 | } |
425 | 783 | ||
426 | |||
427 | /* | 784 | /* |
428 | * Record the indicated change to the given field for application | 785 | * Record the indicated change to the given field for application |
429 | * to the file system's superblock when the transaction commits. | 786 | * to the file system's superblock when the transaction commits. |
@@ -652,7 +1009,7 @@ xfs_trans_apply_sb_deltas( | |||
652 | * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we | 1009 | * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we |
653 | * still need to update the incore superblock with the changes. | 1010 | * still need to update the incore superblock with the changes. |
654 | */ | 1011 | */ |
655 | STATIC void | 1012 | void |
656 | xfs_trans_unreserve_and_mod_sb( | 1013 | xfs_trans_unreserve_and_mod_sb( |
657 | xfs_trans_t *tp) | 1014 | xfs_trans_t *tp) |
658 | { | 1015 | { |
@@ -880,7 +1237,7 @@ xfs_trans_fill_vecs( | |||
880 | * they could be immediately flushed and we'd have to race with the flusher | 1237 | * they could be immediately flushed and we'd have to race with the flusher |
881 | * trying to pull the item from the AIL as we add it. | 1238 | * trying to pull the item from the AIL as we add it. |
882 | */ | 1239 | */ |
883 | static void | 1240 | void |
884 | xfs_trans_item_committed( | 1241 | xfs_trans_item_committed( |
885 | struct xfs_log_item *lip, | 1242 | struct xfs_log_item *lip, |
886 | xfs_lsn_t commit_lsn, | 1243 | xfs_lsn_t commit_lsn, |
@@ -930,26 +1287,6 @@ xfs_trans_item_committed( | |||
930 | IOP_UNPIN(lip); | 1287 | IOP_UNPIN(lip); |
931 | } | 1288 | } |
932 | 1289 | ||
933 | /* Clear all the per-AG busy list items listed in this transaction */ | ||
934 | static void | ||
935 | xfs_trans_clear_busy_extents( | ||
936 | struct xfs_trans *tp) | ||
937 | { | ||
938 | xfs_log_busy_chunk_t *lbcp; | ||
939 | xfs_log_busy_slot_t *lbsp; | ||
940 | int i; | ||
941 | |||
942 | for (lbcp = &tp->t_busy; lbcp != NULL; lbcp = lbcp->lbc_next) { | ||
943 | i = 0; | ||
944 | for (lbsp = lbcp->lbc_busy; i < lbcp->lbc_unused; i++, lbsp++) { | ||
945 | if (XFS_LBC_ISFREE(lbcp, i)) | ||
946 | continue; | ||
947 | xfs_alloc_clear_busy(tp, lbsp->lbc_ag, lbsp->lbc_idx); | ||
948 | } | ||
949 | } | ||
950 | xfs_trans_free_busy(tp); | ||
951 | } | ||
952 | |||
953 | /* | 1290 | /* |
954 | * This is typically called by the LM when a transaction has been fully | 1291 | * This is typically called by the LM when a transaction has been fully |
955 | * committed to disk. It needs to unpin the items which have | 1292 | * committed to disk. It needs to unpin the items which have |
@@ -984,7 +1321,6 @@ xfs_trans_committed( | |||
984 | kmem_free(licp); | 1321 | kmem_free(licp); |
985 | } | 1322 | } |
986 | 1323 | ||
987 | xfs_trans_clear_busy_extents(tp); | ||
988 | xfs_trans_free(tp); | 1324 | xfs_trans_free(tp); |
989 | } | 1325 | } |
990 | 1326 | ||
@@ -1012,8 +1348,7 @@ xfs_trans_uncommit( | |||
1012 | xfs_trans_unreserve_and_mod_sb(tp); | 1348 | xfs_trans_unreserve_and_mod_sb(tp); |
1013 | xfs_trans_unreserve_and_mod_dquots(tp); | 1349 | xfs_trans_unreserve_and_mod_dquots(tp); |
1014 | 1350 | ||
1015 | xfs_trans_free_items(tp, flags); | 1351 | xfs_trans_free_items(tp, NULLCOMMITLSN, flags); |
1016 | xfs_trans_free_busy(tp); | ||
1017 | xfs_trans_free(tp); | 1352 | xfs_trans_free(tp); |
1018 | } | 1353 | } |
1019 | 1354 | ||
@@ -1075,6 +1410,8 @@ xfs_trans_commit_iclog( | |||
1075 | *commit_lsn = xfs_log_done(mp, tp->t_ticket, &commit_iclog, log_flags); | 1410 | *commit_lsn = xfs_log_done(mp, tp->t_ticket, &commit_iclog, log_flags); |
1076 | 1411 | ||
1077 | tp->t_commit_lsn = *commit_lsn; | 1412 | tp->t_commit_lsn = *commit_lsn; |
1413 | trace_xfs_trans_commit_lsn(tp); | ||
1414 | |||
1078 | if (nvec > XFS_TRANS_LOGVEC_COUNT) | 1415 | if (nvec > XFS_TRANS_LOGVEC_COUNT) |
1079 | kmem_free(log_vector); | 1416 | kmem_free(log_vector); |
1080 | 1417 | ||
@@ -1161,6 +1498,93 @@ xfs_trans_commit_iclog( | |||
1161 | return xfs_log_release_iclog(mp, commit_iclog); | 1498 | return xfs_log_release_iclog(mp, commit_iclog); |
1162 | } | 1499 | } |
1163 | 1500 | ||
1501 | /* | ||
1502 | * Walk the log items and allocate log vector structures for | ||
1503 | * each item large enough to fit all the vectors they require. | ||
1504 | * Note that this format differs from the old log vector format in | ||
1505 | * that there is no transaction header in these log vectors. | ||
1506 | */ | ||
1507 | STATIC struct xfs_log_vec * | ||
1508 | xfs_trans_alloc_log_vecs( | ||
1509 | xfs_trans_t *tp) | ||
1510 | { | ||
1511 | xfs_log_item_desc_t *lidp; | ||
1512 | struct xfs_log_vec *lv = NULL; | ||
1513 | struct xfs_log_vec *ret_lv = NULL; | ||
1514 | |||
1515 | lidp = xfs_trans_first_item(tp); | ||
1516 | |||
1517 | /* Bail out if we didn't find a log item. */ | ||
1518 | if (!lidp) { | ||
1519 | ASSERT(0); | ||
1520 | return NULL; | ||
1521 | } | ||
1522 | |||
1523 | while (lidp != NULL) { | ||
1524 | struct xfs_log_vec *new_lv; | ||
1525 | |||
1526 | /* Skip items which aren't dirty in this transaction. */ | ||
1527 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) { | ||
1528 | lidp = xfs_trans_next_item(tp, lidp); | ||
1529 | continue; | ||
1530 | } | ||
1531 | |||
1532 | /* Skip items that do not have any vectors for writing */ | ||
1533 | lidp->lid_size = IOP_SIZE(lidp->lid_item); | ||
1534 | if (!lidp->lid_size) { | ||
1535 | lidp = xfs_trans_next_item(tp, lidp); | ||
1536 | continue; | ||
1537 | } | ||
1538 | |||
1539 | new_lv = kmem_zalloc(sizeof(*new_lv) + | ||
1540 | lidp->lid_size * sizeof(struct xfs_log_iovec), | ||
1541 | KM_SLEEP); | ||
1542 | |||
1543 | /* The allocated iovec region lies beyond the log vector. */ | ||
1544 | new_lv->lv_iovecp = (struct xfs_log_iovec *)&new_lv[1]; | ||
1545 | new_lv->lv_niovecs = lidp->lid_size; | ||
1546 | new_lv->lv_item = lidp->lid_item; | ||
1547 | if (!ret_lv) | ||
1548 | ret_lv = new_lv; | ||
1549 | else | ||
1550 | lv->lv_next = new_lv; | ||
1551 | lv = new_lv; | ||
1552 | lidp = xfs_trans_next_item(tp, lidp); | ||
1553 | } | ||
1554 | |||
1555 | return ret_lv; | ||
1556 | } | ||
1557 | |||
1558 | static int | ||
1559 | xfs_trans_commit_cil( | ||
1560 | struct xfs_mount *mp, | ||
1561 | struct xfs_trans *tp, | ||
1562 | xfs_lsn_t *commit_lsn, | ||
1563 | int flags) | ||
1564 | { | ||
1565 | struct xfs_log_vec *log_vector; | ||
1566 | int error; | ||
1567 | |||
1568 | /* | ||
1569 | * Get each log item to allocate a vector structure for | ||
1570 | * the log item to to pass to the log write code. The | ||
1571 | * CIL commit code will format the vector and save it away. | ||
1572 | */ | ||
1573 | log_vector = xfs_trans_alloc_log_vecs(tp); | ||
1574 | if (!log_vector) | ||
1575 | return ENOMEM; | ||
1576 | |||
1577 | error = xfs_log_commit_cil(mp, tp, log_vector, commit_lsn, flags); | ||
1578 | if (error) | ||
1579 | return error; | ||
1580 | |||
1581 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); | ||
1582 | |||
1583 | /* xfs_trans_free_items() unlocks them first */ | ||
1584 | xfs_trans_free_items(tp, *commit_lsn, 0); | ||
1585 | xfs_trans_free(tp); | ||
1586 | return 0; | ||
1587 | } | ||
1164 | 1588 | ||
1165 | /* | 1589 | /* |
1166 | * xfs_trans_commit | 1590 | * xfs_trans_commit |
@@ -1221,7 +1645,11 @@ _xfs_trans_commit( | |||
1221 | xfs_trans_apply_sb_deltas(tp); | 1645 | xfs_trans_apply_sb_deltas(tp); |
1222 | xfs_trans_apply_dquot_deltas(tp); | 1646 | xfs_trans_apply_dquot_deltas(tp); |
1223 | 1647 | ||
1224 | error = xfs_trans_commit_iclog(mp, tp, &commit_lsn, flags); | 1648 | if (mp->m_flags & XFS_MOUNT_DELAYLOG) |
1649 | error = xfs_trans_commit_cil(mp, tp, &commit_lsn, flags); | ||
1650 | else | ||
1651 | error = xfs_trans_commit_iclog(mp, tp, &commit_lsn, flags); | ||
1652 | |||
1225 | if (error == ENOMEM) { | 1653 | if (error == ENOMEM) { |
1226 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); | 1654 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); |
1227 | error = XFS_ERROR(EIO); | 1655 | error = XFS_ERROR(EIO); |
@@ -1259,8 +1687,7 @@ out_unreserve: | |||
1259 | error = XFS_ERROR(EIO); | 1687 | error = XFS_ERROR(EIO); |
1260 | } | 1688 | } |
1261 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); | 1689 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
1262 | xfs_trans_free_items(tp, error ? XFS_TRANS_ABORT : 0); | 1690 | xfs_trans_free_items(tp, NULLCOMMITLSN, error ? XFS_TRANS_ABORT : 0); |
1263 | xfs_trans_free_busy(tp); | ||
1264 | xfs_trans_free(tp); | 1691 | xfs_trans_free(tp); |
1265 | 1692 | ||
1266 | XFS_STATS_INC(xs_trans_empty); | 1693 | XFS_STATS_INC(xs_trans_empty); |
@@ -1338,8 +1765,7 @@ xfs_trans_cancel( | |||
1338 | /* mark this thread as no longer being in a transaction */ | 1765 | /* mark this thread as no longer being in a transaction */ |
1339 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); | 1766 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
1340 | 1767 | ||
1341 | xfs_trans_free_items(tp, flags); | 1768 | xfs_trans_free_items(tp, NULLCOMMITLSN, flags); |
1342 | xfs_trans_free_busy(tp); | ||
1343 | xfs_trans_free(tp); | 1769 | xfs_trans_free(tp); |
1344 | } | 1770 | } |
1345 | 1771 | ||