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