]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/trans.c
Flush out my xfsprogs backlog - bunch of I18N and sector size related
[thirdparty/xfsprogs-dev.git] / libxfs / trans.c
CommitLineData
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
39xfs_trans_t *
ad10fb70
NS
40libxfs_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
61xfs_trans_t *
ad10fb70
NS
62libxfs_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
74int
ad10fb70
NS
75libxfs_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
98void
ad10fb70
NS
99libxfs_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
116int
ad10fb70
NS
117libxfs_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
148void
ad10fb70
NS
149libxfs_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
175void
ad10fb70
NS
176libxfs_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
198void
ad10fb70
NS
199libxfs_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
212void
ad10fb70
NS
213libxfs_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 */
234void
235xfs_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 */
274void
ad10fb70
NS
275libxfs_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
301void
ad10fb70
NS
302libxfs_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
338void
ad10fb70
NS
339libxfs_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
362void
ad10fb70
NS
363libxfs_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
380void
ad10fb70
NS
381libxfs_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
397xfs_buf_t *
ad10fb70
NS
398libxfs_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
441int
ad10fb70
NS
442libxfs_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 */
506void
ad10fb70
NS
507libxfs_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
540STATIC void
ad10fb70
NS
541inode_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
600ili_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
608STATIC void
ad10fb70
NS
609buf_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 */
641static void
ad10fb70
NS
642trans_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 */
669static void
ad10fb70
NS
670trans_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 */
704int
705xfs_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 */
767int
ad10fb70
NS
768libxfs_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}