]>
Commit | Line | Data |
---|---|---|
2bd0ea18 | 1 | /* |
0d3e0b37 | 2 | * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. |
2bd0ea18 NS |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms of version 2 of the GNU General Public License as | |
6 | * published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it would be useful, but | |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
11 | * | |
12 | * Further, this software is distributed without any warranty that it is | |
13 | * free of the rightful claim of any third person regarding infringement | |
5000d01d | 14 | * or the like. Any license provided herein, whether implied or |
2bd0ea18 NS |
15 | * otherwise, applies only to this software file. Patent licenses, if |
16 | * any, provided herein do not apply to combinations of this program with | |
17 | * other software, or any other product whatsoever. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License along | |
20 | * with this program; if not, write the Free Software Foundation, Inc., 59 | |
21 | * Temple Place - Suite 330, Boston MA 02111-1307, USA. | |
22 | * | |
23 | * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, | |
24 | * Mountain View, CA 94043, or: | |
25 | * | |
26 | * http://www.sgi.com | |
27 | * | |
28 | * For further information regarding this notice, see: | |
29 | * | |
30 | * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ | |
31 | */ | |
32 | ||
33 | #include <xfs.h> | |
34 | ||
35 | /* | |
36 | * Simple transaction interface | |
37 | */ | |
38 | ||
39 | xfs_trans_t * | |
ad10fb70 NS |
40 | libxfs_trans_alloc( |
41 | xfs_mount_t *mp, | |
42 | int type) | |
2bd0ea18 NS |
43 | { |
44 | xfs_trans_t *ptr; | |
45 | ||
46 | if ((ptr = calloc(sizeof(xfs_trans_t), 1)) == NULL) { | |
9440d84d | 47 | fprintf(stderr, _("%s: xact calloc failed (%d bytes): %s\n"), |
5b64e00a | 48 | progname, (int)sizeof(xfs_trans_t), strerror(errno)); |
2bd0ea18 NS |
49 | exit(1); |
50 | } | |
51 | ptr->t_mountp = mp; | |
52 | ptr->t_type = type; | |
53 | ptr->t_items_free = XFS_LIC_NUM_SLOTS; | |
54 | XFS_LIC_INIT(&(ptr->t_items)); | |
55 | #ifdef XACT_DEBUG | |
56 | fprintf(stderr, "allocated new transaction %p\n", ptr); | |
57 | #endif | |
58 | return ptr; | |
59 | } | |
60 | ||
61 | xfs_trans_t * | |
ad10fb70 NS |
62 | libxfs_trans_dup( |
63 | xfs_trans_t *tp) | |
2bd0ea18 | 64 | { |
ad10fb70 | 65 | xfs_trans_t *ptr; |
2bd0ea18 NS |
66 | |
67 | ptr = libxfs_trans_alloc(tp->t_mountp, tp->t_type); | |
68 | #ifdef XACT_DEBUG | |
69 | fprintf(stderr, "duplicated transaction %p (new=%p)\n", tp, ptr); | |
70 | #endif | |
71 | return ptr; | |
72 | } | |
73 | ||
74 | int | |
ad10fb70 NS |
75 | libxfs_trans_reserve( |
76 | xfs_trans_t *tp, | |
77 | uint blocks, | |
78 | uint logspace, | |
79 | uint rtextents, | |
80 | uint flags, | |
81 | uint logcount) | |
2bd0ea18 NS |
82 | { |
83 | xfs_sb_t *mpsb = &tp->t_mountp->m_sb; | |
84 | ||
85 | /* | |
86 | * Attempt to reserve the needed disk blocks by decrementing | |
5000d01d | 87 | * the number needed from the number available. This will |
2bd0ea18 NS |
88 | * fail if the count would go below zero. |
89 | */ | |
90 | if (blocks > 0) { | |
91 | if (mpsb->sb_fdblocks < blocks) | |
92 | return ENOSPC; | |
93 | } | |
94 | /* user space, don't need log/RT stuff (preserve the API though) */ | |
95 | return 0; | |
96 | } | |
97 | ||
98 | void | |
ad10fb70 NS |
99 | libxfs_trans_cancel( |
100 | xfs_trans_t *tp, | |
101 | int flags) | |
2bd0ea18 NS |
102 | { |
103 | #ifdef XACT_DEBUG | |
ad10fb70 | 104 | xfs_trans_t *otp = tp; |
2bd0ea18 NS |
105 | #endif |
106 | if (tp != NULL) { | |
107 | xfs_trans_free_items(tp, flags); | |
108 | free(tp); | |
109 | tp = NULL; | |
110 | } | |
111 | #ifdef XACT_DEBUG | |
112 | fprintf(stderr, "## cancelled transaction %p\n", otp); | |
113 | #endif | |
114 | } | |
115 | ||
116 | int | |
ad10fb70 NS |
117 | libxfs_trans_iget( |
118 | xfs_mount_t *mp, | |
119 | xfs_trans_t *tp, | |
120 | xfs_ino_t ino, | |
121 | uint lock_flags, | |
122 | xfs_inode_t **ipp) | |
2bd0ea18 NS |
123 | { |
124 | int error; | |
125 | xfs_inode_t *ip; | |
126 | xfs_inode_log_item_t *iip; | |
127 | ||
128 | if (tp == NULL) | |
129 | return libxfs_iread(mp, tp, ino, ipp, 0); | |
130 | ||
131 | error = libxfs_iread(mp, tp, ino, &ip, 0); | |
132 | if (error) | |
133 | return error; | |
134 | ASSERT(ip != NULL); | |
135 | ||
136 | if (ip->i_itemp == NULL) | |
137 | xfs_inode_item_init(ip, mp); | |
138 | iip = ip->i_itemp; | |
139 | xfs_trans_add_item(tp, (xfs_log_item_t *)(iip)); | |
140 | ||
141 | /* initialize i_transp so we can find it incore */ | |
142 | ip->i_transp = tp; | |
143 | ||
144 | *ipp = ip; | |
145 | return 0; | |
146 | } | |
147 | ||
148 | void | |
ad10fb70 NS |
149 | libxfs_trans_iput( |
150 | xfs_trans_t *tp, | |
151 | xfs_inode_t *ip, | |
152 | uint lock_flags) | |
2bd0ea18 NS |
153 | { |
154 | xfs_inode_log_item_t *iip; | |
155 | xfs_log_item_desc_t *lidp; | |
156 | ||
157 | if (tp == NULL) { | |
158 | libxfs_iput(ip, lock_flags); | |
159 | return; | |
160 | } | |
161 | ||
162 | ASSERT(ip->i_transp == tp); | |
163 | iip = ip->i_itemp; | |
164 | ASSERT(iip != NULL); | |
165 | ||
166 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t *)iip); | |
167 | ASSERT(lidp != NULL); | |
168 | ASSERT(lidp->lid_item == (xfs_log_item_t *)iip); | |
169 | ASSERT(!(lidp->lid_flags & XFS_LID_DIRTY)); | |
170 | xfs_trans_free_item(tp, lidp); | |
171 | ||
172 | libxfs_iput(ip, lock_flags); | |
173 | } | |
174 | ||
175 | void | |
ad10fb70 NS |
176 | libxfs_trans_ijoin( |
177 | xfs_trans_t *tp, | |
178 | xfs_inode_t *ip, | |
179 | uint lock_flags) | |
2bd0ea18 NS |
180 | { |
181 | xfs_inode_log_item_t *iip; | |
182 | ||
183 | ASSERT(ip->i_transp == NULL); | |
184 | if (ip->i_itemp == NULL) | |
185 | xfs_inode_item_init(ip, ip->i_mount); | |
186 | iip = ip->i_itemp; | |
187 | ASSERT(iip->ili_flags == 0); | |
188 | ASSERT(iip->ili_inode != NULL); | |
189 | ||
190 | xfs_trans_add_item(tp, (xfs_log_item_t *)(iip)); | |
191 | ||
192 | ip->i_transp = tp; | |
193 | #ifdef XACT_DEBUG | |
194 | fprintf(stderr, "ijoin'd inode %llu, transaction %p\n", ip->i_ino, tp); | |
195 | #endif | |
196 | } | |
197 | ||
198 | void | |
ad10fb70 NS |
199 | libxfs_trans_ihold( |
200 | xfs_trans_t *tp, | |
201 | xfs_inode_t *ip) | |
2bd0ea18 NS |
202 | { |
203 | ASSERT(ip->i_transp == tp); | |
204 | ASSERT(ip->i_itemp != NULL); | |
205 | ||
206 | ip->i_itemp->ili_flags |= XFS_ILI_HOLD; | |
207 | #ifdef XACT_DEBUG | |
208 | fprintf(stderr, "ihold'd inode %llu, transaction %p\n", ip->i_ino, tp); | |
209 | #endif | |
210 | } | |
211 | ||
212 | void | |
ad10fb70 NS |
213 | libxfs_trans_inode_alloc_buf( |
214 | xfs_trans_t *tp, | |
215 | xfs_buf_t *bp) | |
2bd0ea18 NS |
216 | { |
217 | xfs_buf_log_item_t *bip; | |
218 | ||
219 | ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); | |
220 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); | |
221 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); | |
222 | bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; | |
223 | } | |
224 | ||
225 | /* | |
226 | * This is called to mark the fields indicated in fieldmask as needing | |
227 | * to be logged when the transaction is committed. The inode must | |
228 | * already be associated with the given transaction. | |
229 | * | |
230 | * The values for fieldmask are defined in xfs_inode_item.h. We always | |
231 | * log all of the core inode if any of it has changed, and we always log | |
232 | * all of the inline data/extents/b-tree root if any of them has changed. | |
233 | */ | |
234 | void | |
235 | xfs_trans_log_inode( | |
ad10fb70 NS |
236 | xfs_trans_t *tp, |
237 | xfs_inode_t *ip, | |
238 | uint flags) | |
2bd0ea18 NS |
239 | { |
240 | xfs_log_item_desc_t *lidp; | |
241 | ||
242 | ASSERT(ip->i_transp == tp); | |
243 | ASSERT(ip->i_itemp != NULL); | |
244 | #ifdef XACT_DEBUG | |
245 | fprintf(stderr, "dirtied inode %llu, transaction %p\n", ip->i_ino, tp); | |
246 | #endif | |
247 | ||
248 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)(ip->i_itemp)); | |
249 | ASSERT(lidp != NULL); | |
250 | ||
251 | tp->t_flags |= XFS_TRANS_DIRTY; | |
252 | lidp->lid_flags |= XFS_LID_DIRTY; | |
253 | ||
254 | /* | |
255 | * Always OR in the bits from the ili_last_fields field. | |
256 | * This is to coordinate with the xfs_iflush() and xfs_iflush_done() | |
257 | * routines in the eventual clearing of the ilf_fields bits. | |
258 | * See the big comment in xfs_iflush() for an explanation of | |
259 | * this coordination mechanism. | |
260 | */ | |
261 | flags |= ip->i_itemp->ili_last_fields; | |
262 | ip->i_itemp->ili_format.ilf_fields |= flags; | |
263 | } | |
264 | ||
265 | /* | |
266 | * This is called to mark bytes first through last inclusive of the given | |
267 | * buffer as needing to be logged when the transaction is committed. | |
268 | * The buffer must already be associated with the given transaction. | |
5000d01d | 269 | * |
2bd0ea18 NS |
270 | * First and last are numbers relative to the beginning of this buffer, |
271 | * so the first byte in the buffer is numbered 0 regardless of the | |
272 | * value of b_blkno. | |
273 | */ | |
274 | void | |
ad10fb70 NS |
275 | libxfs_trans_log_buf( |
276 | xfs_trans_t *tp, | |
277 | xfs_buf_t *bp, | |
278 | uint first, | |
279 | uint last) | |
2bd0ea18 NS |
280 | { |
281 | xfs_buf_log_item_t *bip; | |
282 | xfs_log_item_desc_t *lidp; | |
283 | ||
284 | ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); | |
285 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); | |
286 | ASSERT((first <= last) && (last < XFS_BUF_COUNT(bp))); | |
287 | #ifdef XACT_DEBUG | |
288 | fprintf(stderr, "dirtied buffer %p, transaction %p\n", bp, tp); | |
289 | #endif | |
290 | ||
291 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); | |
292 | ||
293 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t *)bip); | |
294 | ASSERT(lidp != NULL); | |
295 | ||
296 | tp->t_flags |= XFS_TRANS_DIRTY; | |
297 | lidp->lid_flags |= XFS_LID_DIRTY; | |
298 | xfs_buf_item_log(bip, first, last); | |
299 | } | |
300 | ||
301 | void | |
ad10fb70 NS |
302 | libxfs_trans_brelse( |
303 | xfs_trans_t *tp, | |
304 | xfs_buf_t *bp) | |
2bd0ea18 NS |
305 | { |
306 | xfs_buf_log_item_t *bip; | |
307 | xfs_log_item_desc_t *lidp; | |
308 | #ifdef XACT_DEBUG | |
309 | fprintf(stderr, "released buffer %p, transaction %p\n", bp, tp); | |
310 | #endif | |
311 | ||
312 | if (tp == NULL) { | |
313 | ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL); | |
314 | libxfs_putbuf(bp); | |
315 | return; | |
316 | } | |
317 | ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); | |
318 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); | |
319 | ASSERT(bip->bli_item.li_type == XFS_LI_BUF); | |
320 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip); | |
321 | ASSERT(lidp != NULL); | |
322 | if (bip->bli_recur > 0) { | |
323 | bip->bli_recur--; | |
324 | return; | |
325 | } | |
326 | /* If dirty, can't release till transaction committed */ | |
327 | if (lidp->lid_flags & XFS_LID_DIRTY) { | |
328 | return; | |
329 | } | |
330 | xfs_trans_free_item(tp, lidp); | |
331 | if (bip->bli_flags & XFS_BLI_HOLD) { | |
332 | bip->bli_flags &= ~XFS_BLI_HOLD; | |
333 | } | |
334 | XFS_BUF_SET_FSPRIVATE2(bp, NULL); | |
335 | libxfs_putbuf(bp); | |
336 | } | |
337 | ||
338 | void | |
ad10fb70 NS |
339 | libxfs_trans_binval( |
340 | xfs_trans_t *tp, | |
341 | xfs_buf_t *bp) | |
2bd0ea18 NS |
342 | { |
343 | xfs_log_item_desc_t *lidp; | |
344 | xfs_buf_log_item_t *bip; | |
345 | #ifdef XACT_DEBUG | |
346 | fprintf(stderr, "binval'd buffer %p, transaction %p\n", bp, tp); | |
347 | #endif | |
348 | ||
349 | ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); | |
350 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); | |
351 | ||
352 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); | |
353 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip); | |
354 | ASSERT(lidp != NULL); | |
355 | bip->bli_flags &= ~(XFS_BLI_DIRTY); | |
356 | bip->bli_format.blf_flags &= ~XFS_BLI_INODE_BUF; | |
357 | bip->bli_format.blf_flags |= XFS_BLI_CANCEL; | |
358 | lidp->lid_flags |= XFS_LID_DIRTY; | |
359 | tp->t_flags |= XFS_TRANS_DIRTY; | |
360 | } | |
361 | ||
362 | void | |
ad10fb70 NS |
363 | libxfs_trans_bjoin( |
364 | xfs_trans_t *tp, | |
365 | xfs_buf_t *bp) | |
2bd0ea18 NS |
366 | { |
367 | xfs_buf_log_item_t *bip; | |
368 | ||
369 | ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL); | |
370 | #ifdef XACT_DEBUG | |
371 | fprintf(stderr, "bjoin'd buffer %p, transaction %p\n", bp, tp); | |
372 | #endif | |
373 | ||
374 | xfs_buf_item_init(bp, tp->t_mountp); | |
375 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); | |
376 | xfs_trans_add_item(tp, (xfs_log_item_t *)bip); | |
377 | XFS_BUF_SET_FSPRIVATE2(bp, tp); | |
378 | } | |
379 | ||
380 | void | |
ad10fb70 NS |
381 | libxfs_trans_bhold( |
382 | xfs_trans_t *tp, | |
383 | xfs_buf_t *bp) | |
2bd0ea18 NS |
384 | { |
385 | xfs_buf_log_item_t *bip; | |
386 | ||
387 | ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); | |
388 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); | |
389 | #ifdef XACT_DEBUG | |
390 | fprintf(stderr, "bhold'd buffer %p, transaction %p\n", bp, tp); | |
391 | #endif | |
392 | ||
393 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); | |
394 | bip->bli_flags |= XFS_BLI_HOLD; | |
395 | } | |
396 | ||
397 | xfs_buf_t * | |
ad10fb70 NS |
398 | libxfs_trans_get_buf( |
399 | xfs_trans_t *tp, | |
400 | dev_t dev, | |
401 | xfs_daddr_t d, | |
402 | int len, | |
403 | uint f) | |
2bd0ea18 NS |
404 | { |
405 | xfs_buf_t *bp; | |
406 | xfs_buf_log_item_t *bip; | |
b391b7cd | 407 | xfs_buftarg_t bdev = { dev }; |
2bd0ea18 NS |
408 | |
409 | if (tp == NULL) | |
410 | return libxfs_getbuf(dev, d, len); | |
411 | ||
412 | if (tp->t_items.lic_next == NULL) | |
413 | bp = xfs_trans_buf_item_match(tp, &bdev, d, len); | |
414 | else | |
415 | bp = xfs_trans_buf_item_match_all(tp, &bdev, d, len); | |
416 | if (bp != NULL) { | |
417 | ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); | |
418 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); | |
419 | ASSERT(bip != NULL); | |
420 | bip->bli_recur++; | |
421 | return bp; | |
422 | } | |
423 | ||
424 | bp = libxfs_getbuf(dev, d, len); | |
425 | if (bp == NULL) | |
426 | return NULL; | |
427 | #ifdef XACT_DEBUG | |
428 | fprintf(stderr, "trans_get_buf buffer %p, transaction %p\n", bp, tp); | |
429 | #endif | |
430 | ||
431 | xfs_buf_item_init(bp, tp->t_mountp); | |
432 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); | |
433 | bip->bli_recur = 0; | |
434 | xfs_trans_add_item(tp, (xfs_log_item_t *)bip); | |
435 | ||
436 | /* initialize b_fsprivate2 so we can find it incore */ | |
437 | XFS_BUF_SET_FSPRIVATE2(bp, tp); | |
438 | return bp; | |
439 | } | |
440 | ||
441 | int | |
ad10fb70 NS |
442 | libxfs_trans_read_buf( |
443 | xfs_mount_t *mp, | |
444 | xfs_trans_t *tp, | |
445 | dev_t dev, | |
446 | xfs_daddr_t blkno, | |
447 | int len, | |
448 | uint f, | |
449 | xfs_buf_t **bpp) | |
2bd0ea18 NS |
450 | { |
451 | xfs_buf_t *bp; | |
452 | xfs_buf_log_item_t *bip; | |
453 | int error; | |
b391b7cd | 454 | xfs_buftarg_t bdev = { dev }; |
2bd0ea18 NS |
455 | |
456 | if (tp == NULL) { | |
457 | bp = libxfs_getbuf(mp->m_dev, blkno, len); | |
458 | error = libxfs_readbufr(dev, blkno, bp, len, 0); | |
459 | *bpp = bp; | |
460 | return error; | |
461 | } | |
462 | ||
463 | if (tp->t_items.lic_next == NULL) | |
464 | bp = xfs_trans_buf_item_match(tp, &bdev, blkno, len); | |
465 | else | |
466 | bp = xfs_trans_buf_item_match_all(tp, &bdev, blkno, len); | |
467 | if (bp != NULL) { | |
468 | ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); | |
469 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); | |
470 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); | |
471 | bip->bli_recur++; | |
472 | *bpp = bp; | |
473 | return 0; | |
474 | } | |
475 | ||
476 | bp = libxfs_getbuf(mp->m_dev, blkno, len); | |
477 | error = libxfs_readbufr(dev, blkno, bp, len, 0); | |
478 | if (error) { | |
479 | *bpp = NULL; | |
480 | return error; | |
481 | } | |
482 | #ifdef XACT_DEBUG | |
483 | fprintf(stderr, "trans_read_buf buffer %p, transaction %p\n", bp, tp); | |
484 | #endif | |
485 | ||
486 | xfs_buf_item_init(bp, tp->t_mountp); | |
487 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); | |
488 | bip->bli_recur = 0; | |
489 | xfs_trans_add_item(tp, (xfs_log_item_t *)bip); | |
490 | ||
491 | /* initialise b_fsprivate2 so we can find it incore */ | |
492 | XFS_BUF_SET_FSPRIVATE2(bp, tp); | |
493 | *bpp = bp; | |
494 | return 0; | |
495 | } | |
496 | ||
497 | /* | |
498 | * Record the indicated change to the given field for application | |
499 | * to the file system's superblock when the transaction commits. | |
500 | * For now, just store the change in the transaction structure. | |
501 | * Mark the transaction structure to indicate that the superblock | |
5000d01d | 502 | * needs to be updated before committing. |
2bd0ea18 NS |
503 | * |
504 | * Originally derived from xfs_trans_mod_sb(). | |
505 | */ | |
506 | void | |
ad10fb70 NS |
507 | libxfs_trans_mod_sb( |
508 | xfs_trans_t *tp, | |
509 | uint field, | |
510 | long delta) | |
2bd0ea18 NS |
511 | { |
512 | switch (field) { | |
513 | case XFS_TRANS_SB_RES_FDBLOCKS: | |
514 | return; | |
515 | case XFS_TRANS_SB_FDBLOCKS: | |
516 | tp->t_fdblocks_delta += delta; | |
517 | break; | |
518 | case XFS_TRANS_SB_ICOUNT: | |
519 | ASSERT(delta > 0); | |
520 | tp->t_icount_delta += delta; | |
521 | break; | |
522 | case XFS_TRANS_SB_IFREE: | |
523 | tp->t_ifree_delta += delta; | |
524 | break; | |
525 | case XFS_TRANS_SB_FREXTENTS: | |
526 | tp->t_frextents_delta += delta; | |
527 | break; | |
528 | default: | |
529 | ASSERT(0); | |
530 | return; | |
531 | } | |
532 | tp->t_flags |= (XFS_TRANS_SB_DIRTY | XFS_TRANS_DIRTY); | |
533 | } | |
534 | ||
535 | ||
536 | /* | |
537 | * Transaction commital code follows (i.e. write to disk in libxfs) | |
538 | */ | |
539 | ||
540 | STATIC void | |
ad10fb70 NS |
541 | inode_item_done( |
542 | xfs_inode_log_item_t *iip) | |
2bd0ea18 | 543 | { |
ad10fb70 NS |
544 | xfs_dinode_t *dip; |
545 | xfs_inode_t *ip; | |
546 | xfs_mount_t *mp; | |
547 | xfs_buf_t *bp; | |
548 | int hold; | |
549 | int error; | |
550 | extern xfs_zone_t *xfs_ili_zone; | |
2bd0ea18 NS |
551 | |
552 | ip = iip->ili_inode; | |
553 | mp = iip->ili_item.li_mountp; | |
554 | hold = iip->ili_flags & XFS_ILI_HOLD; | |
555 | ASSERT(ip != NULL); | |
556 | ||
557 | if (!(iip->ili_format.ilf_fields & XFS_ILOG_ALL)) { | |
558 | ip->i_transp = NULL; /* disassociate from transaction */ | |
559 | iip->ili_flags = 0; /* reset all flags */ | |
560 | if (!hold) | |
561 | goto ili_done; | |
562 | return; | |
563 | } | |
564 | ||
565 | /* | |
566 | * Get the buffer containing the on-disk inode. | |
567 | */ | |
568 | error = libxfs_itobp(mp, NULL, ip, &dip, &bp, 0); | |
569 | if (error) { | |
9440d84d | 570 | fprintf(stderr, _("%s: warning - itobp failed (%d)\n"), |
2bd0ea18 NS |
571 | progname, error); |
572 | goto ili_done; | |
573 | } | |
574 | ||
575 | XFS_BUF_SET_FSPRIVATE(bp, iip); | |
576 | error = libxfs_iflush_int(ip, bp); | |
577 | if (error) { | |
9440d84d | 578 | fprintf(stderr, _("%s: warning - iflush_int failed (%d)\n"), |
2bd0ea18 NS |
579 | progname, error); |
580 | goto ili_done; | |
581 | } | |
582 | ||
583 | ip->i_transp = NULL; /* disassociate from transaction */ | |
584 | XFS_BUF_SET_FSPRIVATE(bp, NULL); /* remove log item */ | |
585 | XFS_BUF_SET_FSPRIVATE2(bp, NULL); /* remove xact ptr */ | |
586 | libxfs_writebuf_int(bp, 0); | |
587 | #ifdef XACT_DEBUG | |
588 | fprintf(stderr, "flushing dirty inode %llu, buffer %p (hold=%u)\n", | |
589 | ip->i_ino, bp, hold); | |
590 | #endif | |
591 | if (hold) { | |
592 | iip->ili_flags &= ~XFS_ILI_HOLD; | |
593 | return; | |
594 | } | |
595 | else { | |
596 | /*libxfs_iput(iip->ili_inode, 0); - nathans TODO? */ | |
597 | libxfs_putbuf(bp); | |
598 | } | |
599 | ||
600 | ili_done: | |
601 | if (ip->i_itemp) | |
602 | kmem_zone_free(xfs_ili_zone, ip->i_itemp); | |
603 | else | |
604 | ASSERT(0); | |
605 | ip->i_itemp = NULL; | |
606 | } | |
607 | ||
608 | STATIC void | |
ad10fb70 NS |
609 | buf_item_done( |
610 | xfs_buf_log_item_t *bip) | |
2bd0ea18 | 611 | { |
ad10fb70 NS |
612 | xfs_buf_t *bp; |
613 | int hold; | |
614 | extern xfs_zone_t *xfs_buf_item_zone; | |
2bd0ea18 NS |
615 | |
616 | bp = bip->bli_buf; | |
617 | ASSERT(bp != NULL); | |
618 | XFS_BUF_SET_FSPRIVATE(bp, NULL); /* remove log item */ | |
619 | XFS_BUF_SET_FSPRIVATE2(bp, NULL); /* remove xact ptr */ | |
620 | ||
621 | hold = (bip->bli_flags & XFS_BLI_HOLD); | |
622 | if (bip->bli_flags & XFS_BLI_DIRTY) { | |
623 | #ifdef XACT_DEBUG | |
624 | fprintf(stderr, "flushing dirty buffer %p (hold=%d)\n", | |
625 | bp, hold); | |
626 | #endif | |
627 | libxfs_writebuf_int(bp, 0); | |
628 | if (hold) | |
629 | bip->bli_flags &= ~XFS_BLI_HOLD; | |
630 | else | |
631 | libxfs_putbuf(bp); | |
632 | } | |
633 | /* release the buf item */ | |
634 | kmem_zone_free(xfs_buf_item_zone, bip); | |
635 | } | |
636 | ||
637 | /* | |
638 | * This is called to perform the commit processing for each | |
639 | * item described by the given chunk. | |
640 | */ | |
641 | static void | |
ad10fb70 NS |
642 | trans_chunk_committed( |
643 | xfs_log_item_chunk_t *licp) | |
2bd0ea18 NS |
644 | { |
645 | xfs_log_item_desc_t *lidp; | |
646 | xfs_log_item_t *lip; | |
647 | int i; | |
648 | ||
649 | lidp = licp->lic_descs; | |
650 | for (i = 0; i < licp->lic_unused; i++, lidp++) { | |
651 | if (XFS_LIC_ISFREE(licp, i)) | |
652 | continue; | |
653 | lip = lidp->lid_item; | |
654 | if (lip->li_type == XFS_LI_BUF) | |
655 | buf_item_done((xfs_buf_log_item_t *)lidp->lid_item); | |
656 | else if (lip->li_type == XFS_LI_INODE) | |
657 | inode_item_done((xfs_inode_log_item_t *)lidp->lid_item); | |
658 | else { | |
9440d84d | 659 | fprintf(stderr, _("%s: unrecognised log item type\n"), |
2bd0ea18 NS |
660 | progname); |
661 | ASSERT(0); | |
662 | } | |
663 | } | |
664 | } | |
665 | ||
666 | /* | |
667 | * Calls trans_chunk_committed() to process the items in each chunk. | |
668 | */ | |
669 | static void | |
ad10fb70 NS |
670 | trans_committed( |
671 | xfs_trans_t *tp) | |
2bd0ea18 NS |
672 | { |
673 | xfs_log_item_chunk_t *licp; | |
674 | xfs_log_item_chunk_t *next_licp; | |
675 | ||
676 | /* | |
677 | * Special case the chunk embedded in the transaction. | |
678 | */ | |
679 | licp = &(tp->t_items); | |
680 | if (!(XFS_LIC_ARE_ALL_FREE(licp))) { | |
681 | trans_chunk_committed(licp); | |
682 | } | |
683 | ||
684 | /* | |
685 | * Process the items in each chunk in turn. | |
686 | */ | |
687 | licp = licp->lic_next; | |
688 | while (licp != NULL) { | |
689 | trans_chunk_committed(licp); | |
690 | next_licp = licp->lic_next; | |
691 | kmem_free(licp, sizeof(xfs_log_item_chunk_t)); | |
692 | licp = next_licp; | |
693 | } | |
694 | } | |
695 | ||
696 | /* | |
697 | * Unlock each item pointed to by a descriptor in the given chunk. | |
698 | * Free descriptors pointing to items which are not dirty if freeing_chunk | |
699 | * is zero. If freeing_chunk is non-zero, then we need to unlock all | |
5000d01d | 700 | * items in the chunk. Return the number of descriptors freed. |
2bd0ea18 NS |
701 | * Originally based on xfs_trans_unlock_chunk() - adapted for libxfs |
702 | * transactions though. | |
703 | */ | |
704 | int | |
705 | xfs_trans_unlock_chunk( | |
5000d01d | 706 | xfs_log_item_chunk_t *licp, |
2bd0ea18 NS |
707 | int freeing_chunk, |
708 | int abort, | |
709 | xfs_lsn_t commit_lsn) /* nb: unused */ | |
710 | { | |
711 | xfs_log_item_desc_t *lidp; | |
712 | xfs_log_item_t *lip; | |
713 | int i; | |
714 | int freed; | |
715 | ||
716 | freed = 0; | |
717 | lidp = licp->lic_descs; | |
718 | for (i = 0; i < licp->lic_unused; i++, lidp++) { | |
719 | if (XFS_LIC_ISFREE(licp, i)) { | |
720 | continue; | |
721 | } | |
722 | lip = lidp->lid_item; | |
723 | lip->li_desc = NULL; | |
724 | ||
725 | /* | |
726 | * Disassociate the logged item from this transaction | |
727 | */ | |
728 | if (lip->li_type == XFS_LI_BUF) { | |
729 | xfs_buf_log_item_t *bip; | |
730 | ||
731 | bip = (xfs_buf_log_item_t *)lidp->lid_item; | |
732 | XFS_BUF_SET_FSPRIVATE2(bip->bli_buf, NULL); | |
733 | bip->bli_flags &= ~XFS_BLI_HOLD; | |
734 | } | |
735 | else if (lip->li_type == XFS_LI_INODE) { | |
736 | xfs_inode_log_item_t *iip; | |
737 | ||
738 | iip = (xfs_inode_log_item_t*)lidp->lid_item; | |
739 | iip->ili_inode->i_transp = NULL; | |
740 | iip->ili_flags &= ~XFS_ILI_HOLD; | |
741 | } | |
742 | else { | |
9440d84d | 743 | fprintf(stderr, _("%s: unrecognised log item type\n"), |
2bd0ea18 NS |
744 | progname); |
745 | ASSERT(0); | |
746 | } | |
747 | ||
748 | /* | |
749 | * Free the descriptor if the item is not dirty | |
750 | * within this transaction and the caller is not | |
751 | * going to just free the entire thing regardless. | |
752 | */ | |
753 | if (!(freeing_chunk) && | |
754 | (!(lidp->lid_flags & XFS_LID_DIRTY) || abort)) { | |
755 | XFS_LIC_RELSE(licp, i); | |
756 | freed++; | |
757 | } | |
758 | } | |
759 | ||
760 | return (freed); | |
761 | } | |
762 | ||
763 | ||
764 | /* | |
765 | * Commit the changes represented by this transaction | |
766 | */ | |
767 | int | |
ad10fb70 NS |
768 | libxfs_trans_commit( |
769 | xfs_trans_t *tp, | |
770 | uint flags, | |
771 | xfs_lsn_t *commit_lsn_p) | |
2bd0ea18 NS |
772 | { |
773 | xfs_sb_t *sbp; | |
2bd0ea18 NS |
774 | |
775 | if (tp == NULL) | |
776 | return 0; | |
777 | ||
778 | if (!(tp->t_flags & XFS_TRANS_DIRTY)) { | |
779 | #ifdef XACT_DEBUG | |
780 | fprintf(stderr, "committed clean transaction %p\n", tp); | |
781 | #endif | |
782 | xfs_trans_free_items(tp, flags); | |
783 | free(tp); | |
784 | tp = NULL; | |
785 | return 0; | |
786 | } | |
787 | ||
788 | if (tp->t_flags & XFS_TRANS_SB_DIRTY) { | |
789 | sbp = &(tp->t_mountp->m_sb); | |
790 | if (tp->t_icount_delta) | |
791 | sbp->sb_icount += tp->t_icount_delta; | |
792 | if (tp->t_ifree_delta) | |
793 | sbp->sb_ifree += tp->t_ifree_delta; | |
794 | if (tp->t_fdblocks_delta) | |
795 | sbp->sb_fdblocks += tp->t_fdblocks_delta; | |
796 | if (tp->t_frextents_delta) | |
797 | sbp->sb_frextents += tp->t_frextents_delta; | |
798 | libxfs_mod_sb(tp, XFS_SB_ALL_BITS); | |
799 | } | |
800 | ||
801 | #ifdef XACT_DEBUG | |
802 | fprintf(stderr, "committing dirty transaction %p\n", tp); | |
803 | #endif | |
804 | trans_committed(tp); | |
805 | ||
806 | /* That's it for the transaction structure. Free it. */ | |
807 | free(tp); | |
808 | tp = NULL; | |
809 | return 0; | |
810 | } |