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