]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxfs/trans.c
xfs: use ->t_dfops for attr set/remove operations
[thirdparty/xfsprogs-dev.git] / libxfs / trans.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2000-2001,2005-2006 Silicon Graphics, Inc.
4 * Copyright (C) 2010 Red Hat, Inc.
5 * All Rights Reserved.
6 */
7
8 #include "libxfs_priv.h"
9 #include "xfs_fs.h"
10 #include "xfs_shared.h"
11 #include "xfs_format.h"
12 #include "xfs_log_format.h"
13 #include "xfs_trans_resv.h"
14 #include "xfs_mount.h"
15 #include "xfs_inode_buf.h"
16 #include "xfs_inode_fork.h"
17 #include "xfs_inode.h"
18 #include "xfs_trans.h"
19 #include "xfs_sb.h"
20
21 static void xfs_trans_free_items(struct xfs_trans *tp);
22 STATIC struct xfs_trans *xfs_trans_dup(struct xfs_trans *tp);
23 static int xfs_trans_reserve(struct xfs_trans *tp, struct xfs_trans_res *resp,
24 uint blocks, uint rtextents);
25 static int __xfs_trans_commit(struct xfs_trans *tp, bool regrant);
26
27 /*
28 * Simple transaction interface
29 */
30
31 kmem_zone_t *xfs_trans_zone;
32
33 /*
34 * Initialize the precomputed transaction reservation values
35 * in the mount structure.
36 */
37 void
38 libxfs_trans_init(
39 struct xfs_mount *mp)
40 {
41 xfs_trans_resv_calc(mp, &mp->m_resv);
42 }
43
44 /*
45 * Add the given log item to the transaction's list of log items.
46 */
47 void
48 libxfs_trans_add_item(
49 struct xfs_trans *tp,
50 struct xfs_log_item *lip)
51 {
52 ASSERT(lip->li_mountp == tp->t_mountp);
53 ASSERT(lip->li_ailp == tp->t_mountp->m_ail);
54 ASSERT(list_empty(&lip->li_trans));
55 ASSERT(!test_bit(XFS_LI_DIRTY, &lip->li_flags));
56
57 list_add_tail(&lip->li_trans, &tp->t_items);
58 }
59
60 /*
61 * Unlink and free the given descriptor.
62 */
63 void
64 libxfs_trans_del_item(
65 struct xfs_log_item *lip)
66 {
67 clear_bit(XFS_LI_DIRTY, &lip->li_flags);
68 list_del_init(&lip->li_trans);
69 }
70
71 /*
72 * Roll from one trans in the sequence of PERMANENT transactions to
73 * the next: permanent transactions are only flushed out when
74 * committed with XFS_TRANS_RELEASE_LOG_RES, but we still want as soon
75 * as possible to let chunks of it go to the log. So we commit the
76 * chunk we've been working on and get a new transaction to continue.
77 */
78 int
79 libxfs_trans_roll(
80 struct xfs_trans **tpp)
81 {
82 struct xfs_trans *trans = *tpp;
83 struct xfs_trans_res tres;
84 int error;
85
86 /*
87 * Copy the critical parameters from one trans to the next.
88 */
89 tres.tr_logres = trans->t_log_res;
90 tres.tr_logcount = trans->t_log_count;
91
92 *tpp = xfs_trans_dup(trans);
93
94 /*
95 * Commit the current transaction.
96 * If this commit failed, then it'd just unlock those items that
97 * are marked to be released. That also means that a filesystem shutdown
98 * is in progress. The caller takes the responsibility to cancel
99 * the duplicate transaction that gets returned.
100 */
101 error = __xfs_trans_commit(trans, true);
102 if (error)
103 return error;
104
105 /*
106 * Reserve space in the log for the next transaction.
107 * This also pushes items in the "AIL", the list of logged items,
108 * out to disk if they are taking up space at the tail of the log
109 * that we want to use. This requires that either nothing be locked
110 * across this call, or that anything that is locked be logged in
111 * the prior and the next transactions.
112 */
113 tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
114 return xfs_trans_reserve(*tpp, &tres, 0, 0);
115 }
116
117 /*
118 * Free the transaction structure. If there is more clean up
119 * to do when the structure is freed, add it here.
120 */
121 static void
122 xfs_trans_free(
123 struct xfs_trans *tp)
124 {
125 kmem_zone_free(xfs_trans_zone, tp);
126 }
127
128 /*
129 * This is called to create a new transaction which will share the
130 * permanent log reservation of the given transaction. The remaining
131 * unused block and rt extent reservations are also inherited. This
132 * implies that the original transaction is no longer allowed to allocate
133 * blocks. Locks and log items, however, are no inherited. They must
134 * be added to the new transaction explicitly.
135 */
136 STATIC struct xfs_trans *
137 xfs_trans_dup(
138 struct xfs_trans *tp)
139 {
140 struct xfs_trans *ntp;
141
142 ntp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
143
144 /*
145 * Initialize the new transaction structure.
146 */
147 ntp->t_mountp = tp->t_mountp;
148 INIT_LIST_HEAD(&ntp->t_items);
149
150 ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
151
152 ntp->t_flags = XFS_TRANS_PERM_LOG_RES |
153 (tp->t_flags & XFS_TRANS_RESERVE) |
154 (tp->t_flags & XFS_TRANS_NO_WRITECOUNT);
155 /* We gave our writer reference to the new transaction */
156 tp->t_flags |= XFS_TRANS_NO_WRITECOUNT;
157
158 ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used;
159 tp->t_blk_res = tp->t_blk_res_used;
160
161 ntp->t_dfops = tp->t_dfops;
162
163 return ntp;
164 }
165
166 /*
167 * This is called to reserve free disk blocks and log space for the
168 * given transaction. This must be done before allocating any resources
169 * within the transaction.
170 *
171 * This will return ENOSPC if there are not enough blocks available.
172 * It will sleep waiting for available log space.
173 * The only valid value for the flags parameter is XFS_RES_LOG_PERM, which
174 * is used by long running transactions. If any one of the reservations
175 * fails then they will all be backed out.
176 *
177 * This does not do quota reservations. That typically is done by the
178 * caller afterwards.
179 */
180 static int
181 xfs_trans_reserve(
182 struct xfs_trans *tp,
183 struct xfs_trans_res *resp,
184 uint blocks,
185 uint rtextents)
186 {
187 int error = 0;
188
189 /*
190 * Attempt to reserve the needed disk blocks by decrementing
191 * the number needed from the number available. This will
192 * fail if the count would go below zero.
193 */
194 if (blocks > 0) {
195 if (tp->t_mountp->m_sb.sb_fdblocks < blocks)
196 return -ENOSPC;
197 tp->t_blk_res += blocks;
198 }
199
200 /*
201 * Reserve the log space needed for this transaction.
202 */
203 if (resp->tr_logres > 0) {
204 ASSERT(tp->t_log_res == 0 ||
205 tp->t_log_res == resp->tr_logres);
206 ASSERT(tp->t_log_count == 0 ||
207 tp->t_log_count == resp->tr_logcount);
208
209 if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES)
210 tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
211 else
212 ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
213
214 tp->t_log_res = resp->tr_logres;
215 tp->t_log_count = resp->tr_logcount;
216 }
217
218 /*
219 * Attempt to reserve the needed realtime extents by decrementing
220 * the number needed from the number available. This will
221 * fail if the count would go below zero.
222 */
223 if (rtextents > 0) {
224 if (tp->t_mountp->m_sb.sb_rextents < rtextents) {
225 error = -ENOSPC;
226 goto undo_blocks;
227 }
228 }
229
230 return 0;
231
232 /*
233 * Error cases jump to one of these labels to undo any
234 * reservations which have already been performed.
235 */
236 undo_blocks:
237 if (blocks > 0)
238 tp->t_blk_res = 0;
239
240 return error;
241 }
242
243 int
244 libxfs_trans_alloc(
245 struct xfs_mount *mp,
246 struct xfs_trans_res *resp,
247 unsigned int blocks,
248 unsigned int rtextents,
249 unsigned int flags,
250 struct xfs_trans **tpp)
251
252 {
253 struct xfs_trans *tp;
254 int error;
255
256 tp = kmem_zone_zalloc(xfs_trans_zone,
257 (flags & XFS_TRANS_NOFS) ? KM_NOFS : KM_SLEEP);
258 tp->t_mountp = mp;
259 INIT_LIST_HEAD(&tp->t_items);
260
261 error = xfs_trans_reserve(tp, resp, blocks, rtextents);
262 if (error) {
263 xfs_trans_cancel(tp);
264 return error;
265 }
266 #ifdef XACT_DEBUG
267 fprintf(stderr, "allocated new transaction %p\n", tp);
268 #endif
269 *tpp = tp;
270 return 0;
271 }
272
273 /*
274 * Create an empty transaction with no reservation. This is a defensive
275 * mechanism for routines that query metadata without actually modifying
276 * them -- if the metadata being queried is somehow cross-linked (think a
277 * btree block pointer that points higher in the tree), we risk deadlock.
278 * However, blocks grabbed as part of a transaction can be re-grabbed.
279 * The verifiers will notice the corrupt block and the operation will fail
280 * back to userspace without deadlocking.
281 *
282 * Note the zero-length reservation; this transaction MUST be cancelled
283 * without any dirty data.
284 */
285 int
286 libxfs_trans_alloc_empty(
287 struct xfs_mount *mp,
288 struct xfs_trans **tpp)
289 {
290 struct xfs_trans_res resv = {0};
291
292 return xfs_trans_alloc(mp, &resv, 0, 0, XFS_TRANS_NO_WRITECOUNT, tpp);
293 }
294
295 /*
296 * Allocate a transaction that can be rolled. Since userspace doesn't have
297 * a need for log reservations, we really only tr_itruncate to get the
298 * permanent log reservation flag to avoid blowing asserts.
299 */
300 int
301 libxfs_trans_alloc_rollable(
302 struct xfs_mount *mp,
303 unsigned int blocks,
304 struct xfs_trans **tpp)
305 {
306 return libxfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, blocks,
307 0, 0, tpp);
308 }
309
310 void
311 libxfs_trans_cancel(
312 struct xfs_trans *tp)
313 {
314 #ifdef XACT_DEBUG
315 struct xfs_trans *otp = tp;
316 #endif
317 if (tp == NULL)
318 goto out;
319
320 xfs_trans_free_items(tp);
321 xfs_trans_free(tp);
322
323 out:
324 #ifdef XACT_DEBUG
325 fprintf(stderr, "## cancelled transaction %p\n", otp);
326 #endif
327 return;
328 }
329
330 int
331 libxfs_trans_iget(
332 xfs_mount_t *mp,
333 xfs_trans_t *tp,
334 xfs_ino_t ino,
335 uint flags,
336 uint lock_flags,
337 xfs_inode_t **ipp)
338 {
339 int error;
340 xfs_inode_t *ip;
341 xfs_inode_log_item_t *iip;
342
343 if (tp == NULL)
344 return libxfs_iget(mp, tp, ino, lock_flags, ipp,
345 &xfs_default_ifork_ops);
346
347 error = libxfs_iget(mp, tp, ino, lock_flags, &ip,
348 &xfs_default_ifork_ops);
349 if (error)
350 return error;
351 ASSERT(ip != NULL);
352
353 if (ip->i_itemp == NULL)
354 xfs_inode_item_init(ip, mp);
355 iip = ip->i_itemp;
356 xfs_trans_add_item(tp, (xfs_log_item_t *)(iip));
357
358 /* initialize i_transp so we can find it incore */
359 ip->i_transp = tp;
360
361 *ipp = ip;
362 return 0;
363 }
364
365 void
366 libxfs_trans_ijoin(
367 xfs_trans_t *tp,
368 xfs_inode_t *ip,
369 uint lock_flags)
370 {
371 xfs_inode_log_item_t *iip;
372
373 ASSERT(ip->i_transp == NULL);
374 if (ip->i_itemp == NULL)
375 xfs_inode_item_init(ip, ip->i_mount);
376 iip = ip->i_itemp;
377 ASSERT(iip->ili_flags == 0);
378 ASSERT(iip->ili_inode != NULL);
379
380 xfs_trans_add_item(tp, (xfs_log_item_t *)(iip));
381
382 ip->i_transp = tp;
383 #ifdef XACT_DEBUG
384 fprintf(stderr, "ijoin'd inode %llu, transaction %p\n", ip->i_ino, tp);
385 #endif
386 }
387
388 void
389 libxfs_trans_ijoin_ref(
390 xfs_trans_t *tp,
391 xfs_inode_t *ip,
392 int lock_flags)
393 {
394 ASSERT(ip->i_transp == tp);
395 ASSERT(ip->i_itemp != NULL);
396
397 xfs_trans_ijoin(tp, ip, lock_flags);
398
399 #ifdef XACT_DEBUG
400 fprintf(stderr, "ijoin_ref'd inode %llu, transaction %p\n", ip->i_ino, tp);
401 #endif
402 }
403
404 void
405 libxfs_trans_inode_alloc_buf(
406 xfs_trans_t *tp,
407 xfs_buf_t *bp)
408 {
409 xfs_buf_log_item_t *bip = bp->b_log_item;
410
411 ASSERT(bp->bp_transp == tp);
412 ASSERT(bip != NULL);
413 bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF;
414 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF);
415 }
416
417 /*
418 * This is called to mark the fields indicated in fieldmask as needing
419 * to be logged when the transaction is committed. The inode must
420 * already be associated with the given transaction.
421 *
422 * The values for fieldmask are defined in xfs_log_format.h. We always
423 * log all of the core inode if any of it has changed, and we always log
424 * all of the inline data/extents/b-tree root if any of them has changed.
425 */
426 void
427 xfs_trans_log_inode(
428 xfs_trans_t *tp,
429 xfs_inode_t *ip,
430 uint flags)
431 {
432 ASSERT(ip->i_transp == tp);
433 ASSERT(ip->i_itemp != NULL);
434 #ifdef XACT_DEBUG
435 fprintf(stderr, "dirtied inode %llu, transaction %p\n", ip->i_ino, tp);
436 #endif
437
438 tp->t_flags |= XFS_TRANS_DIRTY;
439 set_bit(XFS_LI_DIRTY, &ip->i_itemp->ili_item.li_flags);
440
441 /*
442 * Always OR in the bits from the ili_last_fields field.
443 * This is to coordinate with the xfs_iflush() and xfs_iflush_done()
444 * routines in the eventual clearing of the ilf_fields bits.
445 * See the big comment in xfs_iflush() for an explanation of
446 * this coordination mechanism.
447 */
448 flags |= ip->i_itemp->ili_last_fields;
449 ip->i_itemp->ili_fields |= flags;
450 }
451
452 int
453 libxfs_trans_roll_inode(
454 struct xfs_trans **tpp,
455 struct xfs_inode *ip)
456 {
457 int error;
458
459 xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
460 error = xfs_trans_roll(tpp);
461 if (!error)
462 xfs_trans_ijoin(*tpp, ip, 0);
463 return error;
464 }
465
466
467 /*
468 * Mark a buffer dirty in the transaction.
469 */
470 void
471 libxfs_trans_dirty_buf(
472 struct xfs_trans *tp,
473 struct xfs_buf *bp)
474 {
475 struct xfs_buf_log_item *bip = bp->b_log_item;
476
477 ASSERT(bp->bp_transp == tp);
478 ASSERT(bip != NULL);
479
480 #ifdef XACT_DEBUG
481 fprintf(stderr, "dirtied buffer %p, transaction %p\n", bp, tp);
482 #endif
483 tp->t_flags |= XFS_TRANS_DIRTY;
484 set_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags);
485 }
486
487 /*
488 * This is called to mark bytes first through last inclusive of the given
489 * buffer as needing to be logged when the transaction is committed.
490 * The buffer must already be associated with the given transaction.
491 *
492 * First and last are numbers relative to the beginning of this buffer,
493 * so the first byte in the buffer is numbered 0 regardless of the
494 * value of b_blkno.
495 */
496 void
497 libxfs_trans_log_buf(
498 struct xfs_trans *tp,
499 struct xfs_buf *bp,
500 uint first,
501 uint last)
502 {
503 struct xfs_buf_log_item *bip = bp->b_log_item;
504
505 ASSERT((first <= last) && (last < bp->b_bcount));
506
507 xfs_trans_dirty_buf(tp, bp);
508 xfs_buf_item_log(bip, first, last);
509 }
510
511 /*
512 * For userspace, ordered buffers just need to be marked dirty so
513 * the transaction commit will write them and mark them up-to-date.
514 * In essence, they are just like any other logged buffer in userspace.
515 *
516 * If the buffer is already dirty, trigger the "already logged" return condition.
517 */
518 bool
519 libxfs_trans_ordered_buf(
520 struct xfs_trans *tp,
521 struct xfs_buf *bp)
522 {
523 struct xfs_buf_log_item *bip = bp->b_log_item;
524 bool ret;
525
526 ret = test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags);
527 libxfs_trans_log_buf(tp, bp, 0, bp->b_bcount);
528 return ret;
529 }
530
531 void
532 libxfs_trans_brelse(
533 xfs_trans_t *tp,
534 xfs_buf_t *bp)
535 {
536 xfs_buf_log_item_t *bip;
537 #ifdef XACT_DEBUG
538 fprintf(stderr, "released buffer %p, transaction %p\n", bp, tp);
539 #endif
540
541 if (tp == NULL) {
542 ASSERT(bp->bp_transp == NULL);
543 libxfs_putbuf(bp);
544 return;
545 }
546 ASSERT(bp->bp_transp == tp);
547 bip = bp->b_log_item;
548 ASSERT(bip->bli_item.li_type == XFS_LI_BUF);
549 if (bip->bli_recur > 0) {
550 bip->bli_recur--;
551 return;
552 }
553 /* If dirty/stale, can't release till transaction committed */
554 if (bip->bli_flags & XFS_BLI_STALE)
555 return;
556 if (test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags))
557 return;
558 xfs_trans_del_item(&bip->bli_item);
559 if (bip->bli_flags & XFS_BLI_HOLD)
560 bip->bli_flags &= ~XFS_BLI_HOLD;
561 bp->b_transp = NULL;
562 libxfs_putbuf(bp);
563 }
564
565 void
566 libxfs_trans_binval(
567 xfs_trans_t *tp,
568 xfs_buf_t *bp)
569 {
570 xfs_buf_log_item_t *bip = bp->b_log_item;
571 #ifdef XACT_DEBUG
572 fprintf(stderr, "binval'd buffer %p, transaction %p\n", bp, tp);
573 #endif
574
575 ASSERT(bp->bp_transp == tp);
576 ASSERT(bip != NULL);
577
578 if (bip->bli_flags & XFS_BLI_STALE)
579 return;
580 XFS_BUF_UNDELAYWRITE(bp);
581 xfs_buf_stale(bp);
582 bip->bli_flags |= XFS_BLI_STALE;
583 bip->bli_flags &= ~XFS_BLI_DIRTY;
584 bip->bli_format.blf_flags &= ~XFS_BLF_INODE_BUF;
585 bip->bli_format.blf_flags |= XFS_BLF_CANCEL;
586 set_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags);
587 tp->t_flags |= XFS_TRANS_DIRTY;
588 }
589
590 void
591 libxfs_trans_bjoin(
592 xfs_trans_t *tp,
593 xfs_buf_t *bp)
594 {
595 xfs_buf_log_item_t *bip;
596
597 ASSERT(bp->bp_transp == NULL);
598 #ifdef XACT_DEBUG
599 fprintf(stderr, "bjoin'd buffer %p, transaction %p\n", bp, tp);
600 #endif
601
602 xfs_buf_item_init(bp, tp->t_mountp);
603 bip = bp->b_log_item;
604 xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
605 bp->b_transp = tp;
606 }
607
608 void
609 libxfs_trans_bhold(
610 xfs_trans_t *tp,
611 xfs_buf_t *bp)
612 {
613 xfs_buf_log_item_t *bip = bp->b_log_item;
614
615 ASSERT(bp->bp_transp == tp);
616 ASSERT(bip != NULL);
617 #ifdef XACT_DEBUG
618 fprintf(stderr, "bhold'd buffer %p, transaction %p\n", bp, tp);
619 #endif
620
621 bip->bli_flags |= XFS_BLI_HOLD;
622 }
623
624 xfs_buf_t *
625 libxfs_trans_get_buf_map(
626 xfs_trans_t *tp,
627 struct xfs_buftarg *btp,
628 struct xfs_buf_map *map,
629 int nmaps,
630 uint f)
631 {
632 xfs_buf_t *bp;
633 xfs_buf_log_item_t *bip;
634
635 if (tp == NULL)
636 return libxfs_getbuf_map(btp, map, nmaps, 0);
637
638 bp = xfs_trans_buf_item_match(tp, btp, map, nmaps);
639 if (bp != NULL) {
640 ASSERT(bp->bp_transp == tp);
641 bip = bp->b_log_item;
642 ASSERT(bip != NULL);
643 bip->bli_recur++;
644 return bp;
645 }
646
647 bp = libxfs_getbuf_map(btp, map, nmaps, 0);
648 if (bp == NULL)
649 return NULL;
650 #ifdef XACT_DEBUG
651 fprintf(stderr, "trans_get_buf buffer %p, transaction %p\n", bp, tp);
652 #endif
653
654 xfs_buf_item_init(bp, tp->t_mountp);
655 bip = bp->b_log_item;
656 bip->bli_recur = 0;
657 xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
658
659 /* initialize b_transp so we can find it incore */
660 bp->b_transp = tp;
661 return bp;
662 }
663
664 xfs_buf_t *
665 libxfs_trans_getsb(
666 xfs_trans_t *tp,
667 xfs_mount_t *mp,
668 int flags)
669 {
670 xfs_buf_t *bp;
671 xfs_buf_log_item_t *bip;
672 int len = XFS_FSS_TO_BB(mp, 1);
673 DEFINE_SINGLE_BUF_MAP(map, XFS_SB_DADDR, len);
674
675 if (tp == NULL)
676 return libxfs_getsb(mp, flags);
677
678 bp = xfs_trans_buf_item_match(tp, mp->m_dev, &map, 1);
679 if (bp != NULL) {
680 ASSERT(bp->bp_transp == tp);
681 bip = bp->b_log_item;
682 ASSERT(bip != NULL);
683 bip->bli_recur++;
684 return bp;
685 }
686
687 bp = libxfs_getsb(mp, flags);
688 #ifdef XACT_DEBUG
689 fprintf(stderr, "trans_get_sb buffer %p, transaction %p\n", bp, tp);
690 #endif
691
692 xfs_buf_item_init(bp, mp);
693 bip = bp->b_log_item;
694 bip->bli_recur = 0;
695 xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
696
697 /* initialize b_transp so we can find it incore */
698 bp->b_transp = tp;
699 return bp;
700 }
701
702 int
703 libxfs_trans_read_buf_map(
704 xfs_mount_t *mp,
705 xfs_trans_t *tp,
706 struct xfs_buftarg *btp,
707 struct xfs_buf_map *map,
708 int nmaps,
709 uint flags,
710 xfs_buf_t **bpp,
711 const struct xfs_buf_ops *ops)
712 {
713 xfs_buf_t *bp;
714 xfs_buf_log_item_t *bip;
715 int error;
716
717 *bpp = NULL;
718
719 if (tp == NULL) {
720 bp = libxfs_readbuf_map(btp, map, nmaps, flags, ops);
721 if (!bp) {
722 return (flags & XBF_TRYLOCK) ? -EAGAIN : -ENOMEM;
723 }
724 if (bp->b_error)
725 goto out_relse;
726 goto done;
727 }
728
729 bp = xfs_trans_buf_item_match(tp, btp, map, nmaps);
730 if (bp != NULL) {
731 ASSERT(bp->bp_transp == tp);
732 ASSERT(bp->b_log_item != NULL);
733 bip = bp->b_log_item;
734 bip->bli_recur++;
735 goto done;
736 }
737
738 bp = libxfs_readbuf_map(btp, map, nmaps, flags, ops);
739 if (!bp) {
740 return (flags & XBF_TRYLOCK) ? -EAGAIN : -ENOMEM;
741 }
742 if (bp->b_error)
743 goto out_relse;
744
745 #ifdef XACT_DEBUG
746 fprintf(stderr, "trans_read_buf buffer %p, transaction %p\n", bp, tp);
747 #endif
748
749 xfs_buf_item_init(bp, tp->t_mountp);
750 bip = bp->b_log_item;
751 bip->bli_recur = 0;
752 xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
753
754 /* initialise b_transp so we can find it incore */
755 bp->b_transp = tp;
756 done:
757 *bpp = bp;
758 return 0;
759 out_relse:
760 error = bp->b_error;
761 xfs_buf_relse(bp);
762 return error;
763 }
764
765 /*
766 * Record the indicated change to the given field for application
767 * to the file system's superblock when the transaction commits.
768 * For now, just store the change in the transaction structure.
769 * Mark the transaction structure to indicate that the superblock
770 * needs to be updated before committing.
771 *
772 * Originally derived from xfs_trans_mod_sb().
773 */
774 void
775 libxfs_trans_mod_sb(
776 xfs_trans_t *tp,
777 uint field,
778 long delta)
779 {
780 switch (field) {
781 case XFS_TRANS_SB_RES_FDBLOCKS:
782 return;
783 case XFS_TRANS_SB_FDBLOCKS:
784 if (delta < 0) {
785 tp->t_blk_res_used += (uint)-delta;
786 if (tp->t_blk_res_used > tp->t_blk_res) {
787 fprintf(stderr,
788 _("Transaction block reservation exceeded! %u > %u\n"),
789 tp->t_blk_res_used, tp->t_blk_res);
790 ASSERT(0);
791 }
792 }
793 tp->t_fdblocks_delta += delta;
794 break;
795 case XFS_TRANS_SB_ICOUNT:
796 ASSERT(delta > 0);
797 tp->t_icount_delta += delta;
798 break;
799 case XFS_TRANS_SB_IFREE:
800 tp->t_ifree_delta += delta;
801 break;
802 case XFS_TRANS_SB_FREXTENTS:
803 tp->t_frextents_delta += delta;
804 break;
805 default:
806 ASSERT(0);
807 return;
808 }
809 tp->t_flags |= (XFS_TRANS_SB_DIRTY | XFS_TRANS_DIRTY);
810 }
811
812
813 /*
814 * Transaction commital code follows (i.e. write to disk in libxfs)
815 */
816
817 static void
818 inode_item_done(
819 xfs_inode_log_item_t *iip)
820 {
821 xfs_dinode_t *dip;
822 xfs_inode_t *ip;
823 xfs_mount_t *mp;
824 xfs_buf_t *bp;
825 int error;
826
827 ip = iip->ili_inode;
828 mp = iip->ili_item.li_mountp;
829 ASSERT(ip != NULL);
830
831 if (!(iip->ili_fields & XFS_ILOG_ALL)) {
832 ip->i_transp = NULL; /* disassociate from transaction */
833 iip->ili_flags = 0; /* reset all flags */
834 return;
835 }
836
837 /*
838 * Get the buffer containing the on-disk inode.
839 */
840 error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, 0, 0);
841 if (error) {
842 fprintf(stderr, _("%s: warning - imap_to_bp failed (%d)\n"),
843 progname, error);
844 return;
845 }
846
847 bp->b_log_item = iip;
848 error = libxfs_iflush_int(ip, bp);
849 if (error) {
850 fprintf(stderr, _("%s: warning - iflush_int failed (%d)\n"),
851 progname, error);
852 return;
853 }
854
855 ip->i_transp = NULL; /* disassociate from transaction */
856 bp->b_log_item = NULL; /* remove log item */
857 bp->b_transp = NULL; /* remove xact ptr */
858 libxfs_writebuf(bp, 0);
859 #ifdef XACT_DEBUG
860 fprintf(stderr, "flushing dirty inode %llu, buffer %p\n",
861 ip->i_ino, bp);
862 #endif
863 }
864
865 static void
866 buf_item_done(
867 xfs_buf_log_item_t *bip)
868 {
869 xfs_buf_t *bp;
870 int hold;
871 extern kmem_zone_t *xfs_buf_item_zone;
872
873 bp = bip->bli_buf;
874 ASSERT(bp != NULL);
875 bp->b_log_item = NULL; /* remove log item */
876 bp->b_transp = NULL; /* remove xact ptr */
877
878 hold = (bip->bli_flags & XFS_BLI_HOLD);
879 if (bip->bli_flags & XFS_BLI_DIRTY) {
880 #ifdef XACT_DEBUG
881 fprintf(stderr, "flushing/staling buffer %p (hold=%d)\n",
882 bp, hold);
883 #endif
884 libxfs_writebuf_int(bp, 0);
885 }
886 if (hold)
887 bip->bli_flags &= ~XFS_BLI_HOLD;
888 else
889 libxfs_putbuf(bp);
890 /* release the buf item */
891 kmem_zone_free(xfs_buf_item_zone, bip);
892 }
893
894 static void
895 trans_committed(
896 xfs_trans_t *tp)
897 {
898 struct xfs_log_item *lip, *next;
899
900 list_for_each_entry_safe(lip, next, &tp->t_items, li_trans) {
901 xfs_trans_del_item(lip);
902
903 if (lip->li_type == XFS_LI_BUF)
904 buf_item_done((xfs_buf_log_item_t *)lip);
905 else if (lip->li_type == XFS_LI_INODE)
906 inode_item_done((xfs_inode_log_item_t *)lip);
907 else {
908 fprintf(stderr, _("%s: unrecognised log item type\n"),
909 progname);
910 ASSERT(0);
911 }
912 }
913 }
914
915 static void
916 buf_item_unlock(
917 xfs_buf_log_item_t *bip)
918 {
919 xfs_buf_t *bp = bip->bli_buf;
920 uint hold;
921
922 /* Clear the buffer's association with this transaction. */
923 bip->bli_buf->b_transp = NULL;
924
925 hold = bip->bli_flags & XFS_BLI_HOLD;
926 bip->bli_flags &= ~XFS_BLI_HOLD;
927 if (!hold)
928 libxfs_putbuf(bp);
929 }
930
931 static void
932 inode_item_unlock(
933 xfs_inode_log_item_t *iip)
934 {
935 xfs_inode_t *ip = iip->ili_inode;
936
937 /* Clear the transaction pointer in the inode. */
938 ip->i_transp = NULL;
939
940 iip->ili_flags = 0;
941 }
942
943 /* Detach and unlock all of the items in a transaction */
944 static void
945 xfs_trans_free_items(
946 struct xfs_trans *tp)
947 {
948 struct xfs_log_item *lip, *next;
949
950 list_for_each_entry_safe(lip, next, &tp->t_items, li_trans) {
951 xfs_trans_del_item(lip);
952 if (lip->li_type == XFS_LI_BUF)
953 buf_item_unlock((xfs_buf_log_item_t *)lip);
954 else if (lip->li_type == XFS_LI_INODE)
955 inode_item_unlock((xfs_inode_log_item_t *)lip);
956 else {
957 fprintf(stderr, _("%s: unrecognised log item type\n"),
958 progname);
959 ASSERT(0);
960 }
961 }
962 }
963
964 /*
965 * Commit the changes represented by this transaction
966 */
967 static int
968 __xfs_trans_commit(
969 struct xfs_trans *tp,
970 bool regrant)
971 {
972 struct xfs_sb *sbp;
973 int error = 0;
974
975 if (tp == NULL)
976 return 0;
977
978 ASSERT(!tp->t_dfops ||
979 !xfs_defer_has_unfinished_work(tp->t_dfops) || regrant);
980
981 if (!(tp->t_flags & XFS_TRANS_DIRTY)) {
982 #ifdef XACT_DEBUG
983 fprintf(stderr, "committed clean transaction %p\n", tp);
984 #endif
985 goto out_unreserve;
986 }
987
988 if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
989 sbp = &(tp->t_mountp->m_sb);
990 if (tp->t_icount_delta)
991 sbp->sb_icount += tp->t_icount_delta;
992 if (tp->t_ifree_delta)
993 sbp->sb_ifree += tp->t_ifree_delta;
994 if (tp->t_fdblocks_delta)
995 sbp->sb_fdblocks += tp->t_fdblocks_delta;
996 if (tp->t_frextents_delta)
997 sbp->sb_frextents += tp->t_frextents_delta;
998 xfs_log_sb(tp);
999 }
1000
1001 #ifdef XACT_DEBUG
1002 fprintf(stderr, "committing dirty transaction %p\n", tp);
1003 #endif
1004 trans_committed(tp);
1005
1006 /* That's it for the transaction structure. Free it. */
1007 xfs_trans_free(tp);
1008 return 0;
1009
1010 out_unreserve:
1011 xfs_trans_free_items(tp);
1012 xfs_trans_free(tp);
1013 return error;
1014 }
1015
1016 int
1017 libxfs_trans_commit(
1018 struct xfs_trans *tp)
1019 {
1020 return __xfs_trans_commit(tp, false);
1021 }