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