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