]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/trans.c
xfs: bmap code cleanup
[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)
81f8132a 246 return libxfs_iget(mp, tp, ino, lock_flags, ipp);
2bd0ea18 247
81f8132a 248 error = libxfs_iget(mp, tp, ino, lock_flags, &ip);
2bd0ea18
NS
249 if (error)
250 return error;
251 ASSERT(ip != NULL);
252
253 if (ip->i_itemp == NULL)
254 xfs_inode_item_init(ip, mp);
255 iip = ip->i_itemp;
256 xfs_trans_add_item(tp, (xfs_log_item_t *)(iip));
257
258 /* initialize i_transp so we can find it incore */
259 ip->i_transp = tp;
260
261 *ipp = ip;
262 return 0;
263}
264
2bd0ea18 265void
ad10fb70
NS
266libxfs_trans_ijoin(
267 xfs_trans_t *tp,
268 xfs_inode_t *ip,
269 uint lock_flags)
2bd0ea18
NS
270{
271 xfs_inode_log_item_t *iip;
272
273 ASSERT(ip->i_transp == NULL);
274 if (ip->i_itemp == NULL)
275 xfs_inode_item_init(ip, ip->i_mount);
276 iip = ip->i_itemp;
277 ASSERT(iip->ili_flags == 0);
278 ASSERT(iip->ili_inode != NULL);
279
280 xfs_trans_add_item(tp, (xfs_log_item_t *)(iip));
281
282 ip->i_transp = tp;
283#ifdef XACT_DEBUG
284 fprintf(stderr, "ijoin'd inode %llu, transaction %p\n", ip->i_ino, tp);
285#endif
286}
287
c40bdaa2
DC
288void
289libxfs_trans_ijoin_ref(
290 xfs_trans_t *tp,
291 xfs_inode_t *ip,
292 int lock_flags)
293{
294 ASSERT(ip->i_transp == tp);
295 ASSERT(ip->i_itemp != NULL);
296
297 xfs_trans_ijoin(tp, ip, lock_flags);
c40bdaa2
DC
298
299#ifdef XACT_DEBUG
300 fprintf(stderr, "ijoin_ref'd inode %llu, transaction %p\n", ip->i_ino, tp);
301#endif
302}
303
2bd0ea18 304void
ad10fb70
NS
305libxfs_trans_inode_alloc_buf(
306 xfs_trans_t *tp,
307 xfs_buf_t *bp)
2bd0ea18 308{
37d086ca 309 xfs_buf_log_item_t *bip = bp->b_log_item;
2bd0ea18 310
cfc06b60 311 ASSERT(bp->bp_transp == tp);
38d096b6 312 ASSERT(bip != NULL);
2bd0ea18 313 bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF;
bdc16ee5 314 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF);
2bd0ea18
NS
315}
316
317/*
318 * This is called to mark the fields indicated in fieldmask as needing
319 * to be logged when the transaction is committed. The inode must
320 * already be associated with the given transaction.
321 *
2d4bfb91 322 * The values for fieldmask are defined in xfs_log_format.h. We always
2bd0ea18
NS
323 * log all of the core inode if any of it has changed, and we always log
324 * all of the inline data/extents/b-tree root if any of them has changed.
325 */
326void
327xfs_trans_log_inode(
ad10fb70
NS
328 xfs_trans_t *tp,
329 xfs_inode_t *ip,
330 uint flags)
2bd0ea18 331{
2bd0ea18
NS
332 ASSERT(ip->i_transp == tp);
333 ASSERT(ip->i_itemp != NULL);
334#ifdef XACT_DEBUG
335 fprintf(stderr, "dirtied inode %llu, transaction %p\n", ip->i_ino, tp);
336#endif
337
2bd0ea18 338 tp->t_flags |= XFS_TRANS_DIRTY;
c40bdaa2 339 ip->i_itemp->ili_item.li_desc->lid_flags |= XFS_LID_DIRTY;
2bd0ea18
NS
340
341 /*
342 * Always OR in the bits from the ili_last_fields field.
343 * This is to coordinate with the xfs_iflush() and xfs_iflush_done()
344 * routines in the eventual clearing of the ilf_fields bits.
345 * See the big comment in xfs_iflush() for an explanation of
346 * this coordination mechanism.
347 */
348 flags |= ip->i_itemp->ili_last_fields;
a2ceac1f 349 ip->i_itemp->ili_fields |= flags;
2bd0ea18
NS
350}
351
d67406c9
CH
352int
353libxfs_trans_roll_inode(
354 struct xfs_trans **tpp,
355 struct xfs_inode *ip)
356{
357 int error;
358
359 xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
360 error = xfs_trans_roll(tpp);
361 if (!error)
362 xfs_trans_ijoin(*tpp, ip, 0);
363 return error;
364}
365
366
59630067
BF
367/*
368 * Mark a buffer dirty in the transaction.
369 */
370void
371libxfs_trans_dirty_buf(
372 struct xfs_trans *tp,
373 struct xfs_buf *bp)
374{
37d086ca 375 struct xfs_buf_log_item *bip = bp->b_log_item;
59630067 376
cfc06b60 377 ASSERT(bp->bp_transp == tp);
38d096b6 378 ASSERT(bip != NULL);
59630067 379
59630067
BF
380#ifdef XACT_DEBUG
381 fprintf(stderr, "dirtied buffer %p, transaction %p\n", bp, tp);
382#endif
383 tp->t_flags |= XFS_TRANS_DIRTY;
384 bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY;
385}
386
2bd0ea18
NS
387/*
388 * This is called to mark bytes first through last inclusive of the given
389 * buffer as needing to be logged when the transaction is committed.
390 * The buffer must already be associated with the given transaction.
5000d01d 391 *
2bd0ea18
NS
392 * First and last are numbers relative to the beginning of this buffer,
393 * so the first byte in the buffer is numbered 0 regardless of the
394 * value of b_blkno.
395 */
396void
ad10fb70 397libxfs_trans_log_buf(
59630067
BF
398 struct xfs_trans *tp,
399 struct xfs_buf *bp,
ad10fb70
NS
400 uint first,
401 uint last)
2bd0ea18 402{
37d086ca 403 struct xfs_buf_log_item *bip = bp->b_log_item;
2bd0ea18 404
2bd0ea18 405 ASSERT((first <= last) && (last < XFS_BUF_COUNT(bp)));
2bd0ea18 406
59630067 407 xfs_trans_dirty_buf(tp, bp);
2bd0ea18
NS
408 xfs_buf_item_log(bip, first, last);
409}
410
38fa71a7
BF
411/*
412 * For userspace, ordered buffers just need to be marked dirty so
413 * the transaction commit will write them and mark them up-to-date.
414 * In essence, they are just like any other logged buffer in userspace.
415 *
416 * If the buffer is already dirty, trigger the "already logged" return condition.
417 */
418bool
419libxfs_trans_ordered_buf(
420 struct xfs_trans *tp,
421 struct xfs_buf *bp)
422{
37d086ca 423 struct xfs_buf_log_item *bip = bp->b_log_item;
38fa71a7
BF
424 bool ret;
425
426 ret = (bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY);
427 libxfs_trans_log_buf(tp, bp, 0, bp->b_bcount);
428 return ret;
429}
430
2bd0ea18 431void
ad10fb70
NS
432libxfs_trans_brelse(
433 xfs_trans_t *tp,
434 xfs_buf_t *bp)
2bd0ea18
NS
435{
436 xfs_buf_log_item_t *bip;
2bd0ea18
NS
437#ifdef XACT_DEBUG
438 fprintf(stderr, "released buffer %p, transaction %p\n", bp, tp);
439#endif
440
441 if (tp == NULL) {
cfc06b60 442 ASSERT(bp->bp_transp == NULL);
2bd0ea18
NS
443 libxfs_putbuf(bp);
444 return;
445 }
cfc06b60 446 ASSERT(bp->bp_transp == tp);
37d086ca 447 bip = bp->b_log_item;
2bd0ea18 448 ASSERT(bip->bli_item.li_type == XFS_LI_BUF);
2bd0ea18
NS
449 if (bip->bli_recur > 0) {
450 bip->bli_recur--;
451 return;
452 }
f1b058f9
NS
453 /* If dirty/stale, can't release till transaction committed */
454 if (bip->bli_flags & XFS_BLI_STALE)
455 return;
c40bdaa2 456 if (bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY)
2bd0ea18 457 return;
c40bdaa2 458 xfs_trans_del_item(&bip->bli_item);
f1b058f9 459 if (bip->bli_flags & XFS_BLI_HOLD)
2bd0ea18 460 bip->bli_flags &= ~XFS_BLI_HOLD;
cfc06b60 461 bp->b_transp = NULL;
2bd0ea18
NS
462 libxfs_putbuf(bp);
463}
464
465void
ad10fb70
NS
466libxfs_trans_binval(
467 xfs_trans_t *tp,
468 xfs_buf_t *bp)
2bd0ea18 469{
37d086ca 470 xfs_buf_log_item_t *bip = bp->b_log_item;
2bd0ea18
NS
471#ifdef XACT_DEBUG
472 fprintf(stderr, "binval'd buffer %p, transaction %p\n", bp, tp);
473#endif
474
cfc06b60 475 ASSERT(bp->bp_transp == tp);
38d096b6 476 ASSERT(bip != NULL);
2bd0ea18 477
f1b058f9
NS
478 if (bip->bli_flags & XFS_BLI_STALE)
479 return;
480 XFS_BUF_UNDELAYWRITE(bp);
a2ceac1f 481 xfs_buf_stale(bp);
f1b058f9
NS
482 bip->bli_flags |= XFS_BLI_STALE;
483 bip->bli_flags &= ~XFS_BLI_DIRTY;
c40bdaa2
DC
484 bip->bli_format.blf_flags &= ~XFS_BLF_INODE_BUF;
485 bip->bli_format.blf_flags |= XFS_BLF_CANCEL;
486 bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY;
2bd0ea18
NS
487 tp->t_flags |= XFS_TRANS_DIRTY;
488}
489
490void
ad10fb70
NS
491libxfs_trans_bjoin(
492 xfs_trans_t *tp,
493 xfs_buf_t *bp)
2bd0ea18
NS
494{
495 xfs_buf_log_item_t *bip;
496
cfc06b60 497 ASSERT(bp->bp_transp == NULL);
2bd0ea18
NS
498#ifdef XACT_DEBUG
499 fprintf(stderr, "bjoin'd buffer %p, transaction %p\n", bp, tp);
500#endif
501
502 xfs_buf_item_init(bp, tp->t_mountp);
37d086ca 503 bip = bp->b_log_item;
2bd0ea18 504 xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
cfc06b60 505 bp->b_transp = tp;
2bd0ea18
NS
506}
507
508void
ad10fb70
NS
509libxfs_trans_bhold(
510 xfs_trans_t *tp,
511 xfs_buf_t *bp)
2bd0ea18 512{
37d086ca 513 xfs_buf_log_item_t *bip = bp->b_log_item;
2bd0ea18 514
cfc06b60 515 ASSERT(bp->bp_transp == tp);
37d086ca 516 ASSERT(bip != NULL);
2bd0ea18
NS
517#ifdef XACT_DEBUG
518 fprintf(stderr, "bhold'd buffer %p, transaction %p\n", bp, tp);
519#endif
520
2bd0ea18
NS
521 bip->bli_flags |= XFS_BLI_HOLD;
522}
523
524xfs_buf_t *
a2ceac1f 525libxfs_trans_get_buf_map(
ad10fb70 526 xfs_trans_t *tp,
75c8b434 527 struct xfs_buftarg *btp,
a2ceac1f
DC
528 struct xfs_buf_map *map,
529 int nmaps,
ad10fb70 530 uint f)
2bd0ea18
NS
531{
532 xfs_buf_t *bp;
533 xfs_buf_log_item_t *bip;
2bd0ea18
NS
534
535 if (tp == NULL)
7e3ab890 536 return libxfs_getbuf_map(btp, map, nmaps, 0);
2bd0ea18 537
75c8b434 538 bp = xfs_trans_buf_item_match(tp, btp, map, nmaps);
2bd0ea18 539 if (bp != NULL) {
cfc06b60 540 ASSERT(bp->bp_transp == tp);
37d086ca 541 bip = bp->b_log_item;
2bd0ea18
NS
542 ASSERT(bip != NULL);
543 bip->bli_recur++;
544 return bp;
545 }
546
7e3ab890 547 bp = libxfs_getbuf_map(btp, map, nmaps, 0);
2bd0ea18
NS
548 if (bp == NULL)
549 return NULL;
550#ifdef XACT_DEBUG
551 fprintf(stderr, "trans_get_buf buffer %p, transaction %p\n", bp, tp);
552#endif
553
554 xfs_buf_item_init(bp, tp->t_mountp);
37d086ca 555 bip = bp->b_log_item;
2bd0ea18
NS
556 bip->bli_recur = 0;
557 xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
558
cfc06b60
CH
559 /* initialize b_transp so we can find it incore */
560 bp->b_transp = tp;
2bd0ea18
NS
561 return bp;
562}
563
f1b058f9
NS
564xfs_buf_t *
565libxfs_trans_getsb(
566 xfs_trans_t *tp,
567 xfs_mount_t *mp,
568 int flags)
569{
570 xfs_buf_t *bp;
571 xfs_buf_log_item_t *bip;
a2ceac1f
DC
572 int len = XFS_FSS_TO_BB(mp, 1);
573 DEFINE_SINGLE_BUF_MAP(map, XFS_SB_DADDR, len);
f1b058f9
NS
574
575 if (tp == NULL)
576 return libxfs_getsb(mp, flags);
577
a2ceac1f 578 bp = xfs_trans_buf_item_match(tp, mp->m_dev, &map, 1);
f1b058f9 579 if (bp != NULL) {
cfc06b60 580 ASSERT(bp->bp_transp == tp);
37d086ca 581 bip = bp->b_log_item;
f1b058f9
NS
582 ASSERT(bip != NULL);
583 bip->bli_recur++;
584 return bp;
585 }
586
587 bp = libxfs_getsb(mp, flags);
588#ifdef XACT_DEBUG
589 fprintf(stderr, "trans_get_sb buffer %p, transaction %p\n", bp, tp);
590#endif
591
592 xfs_buf_item_init(bp, mp);
37d086ca 593 bip = bp->b_log_item;
f1b058f9
NS
594 bip->bli_recur = 0;
595 xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
596
cfc06b60
CH
597 /* initialize b_transp so we can find it incore */
598 bp->b_transp = tp;
f1b058f9
NS
599 return bp;
600}
601
2bd0ea18 602int
a2ceac1f 603libxfs_trans_read_buf_map(
ad10fb70
NS
604 xfs_mount_t *mp,
605 xfs_trans_t *tp,
75c8b434 606 struct xfs_buftarg *btp,
a2ceac1f
DC
607 struct xfs_buf_map *map,
608 int nmaps,
f1b058f9 609 uint flags,
a2ceac1f
DC
610 xfs_buf_t **bpp,
611 const struct xfs_buf_ops *ops)
2bd0ea18
NS
612{
613 xfs_buf_t *bp;
614 xfs_buf_log_item_t *bip;
a6a7776a 615 int error;
2bd0ea18 616
00aea09f
CH
617 *bpp = NULL;
618
2bd0ea18 619 if (tp == NULL) {
75c8b434 620 bp = libxfs_readbuf_map(btp, map, nmaps, flags, ops);
00aea09f 621 if (!bp) {
12b53197 622 return (flags & XBF_TRYLOCK) ? -EAGAIN : -ENOMEM;
00aea09f 623 }
a6a7776a
CH
624 if (bp->b_error)
625 goto out_relse;
00aea09f 626 goto done;
2bd0ea18
NS
627 }
628
75c8b434 629 bp = xfs_trans_buf_item_match(tp, btp, map, nmaps);
2bd0ea18 630 if (bp != NULL) {
cfc06b60 631 ASSERT(bp->bp_transp == tp);
37d086ca
CM
632 ASSERT(bp->b_log_item != NULL);
633 bip = bp->b_log_item;
2bd0ea18 634 bip->bli_recur++;
00aea09f 635 goto done;
2bd0ea18
NS
636 }
637
75c8b434 638 bp = libxfs_readbuf_map(btp, map, nmaps, flags, ops);
00aea09f 639 if (!bp) {
12b53197 640 return (flags & XBF_TRYLOCK) ? -EAGAIN : -ENOMEM;
00aea09f 641 }
a6a7776a
CH
642 if (bp->b_error)
643 goto out_relse;
00aea09f 644
2bd0ea18
NS
645#ifdef XACT_DEBUG
646 fprintf(stderr, "trans_read_buf buffer %p, transaction %p\n", bp, tp);
647#endif
648
649 xfs_buf_item_init(bp, tp->t_mountp);
37d086ca 650 bip = bp->b_log_item;
2bd0ea18
NS
651 bip->bli_recur = 0;
652 xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
653
cfc06b60
CH
654 /* initialise b_transp so we can find it incore */
655 bp->b_transp = tp;
00aea09f 656done:
2bd0ea18
NS
657 *bpp = bp;
658 return 0;
a6a7776a
CH
659out_relse:
660 error = bp->b_error;
661 xfs_buf_relse(bp);
662 return error;
2bd0ea18
NS
663}
664
665/*
666 * Record the indicated change to the given field for application
667 * to the file system's superblock when the transaction commits.
668 * For now, just store the change in the transaction structure.
669 * Mark the transaction structure to indicate that the superblock
5000d01d 670 * needs to be updated before committing.
2bd0ea18
NS
671 *
672 * Originally derived from xfs_trans_mod_sb().
673 */
674void
ad10fb70
NS
675libxfs_trans_mod_sb(
676 xfs_trans_t *tp,
677 uint field,
678 long delta)
2bd0ea18
NS
679{
680 switch (field) {
681 case XFS_TRANS_SB_RES_FDBLOCKS:
682 return;
683 case XFS_TRANS_SB_FDBLOCKS:
684 tp->t_fdblocks_delta += delta;
685 break;
686 case XFS_TRANS_SB_ICOUNT:
687 ASSERT(delta > 0);
688 tp->t_icount_delta += delta;
689 break;
690 case XFS_TRANS_SB_IFREE:
691 tp->t_ifree_delta += delta;
692 break;
693 case XFS_TRANS_SB_FREXTENTS:
694 tp->t_frextents_delta += delta;
695 break;
696 default:
697 ASSERT(0);
698 return;
699 }
700 tp->t_flags |= (XFS_TRANS_SB_DIRTY | XFS_TRANS_DIRTY);
701}
702
703
704/*
705 * Transaction commital code follows (i.e. write to disk in libxfs)
706 */
707
5e656dbb 708static void
ad10fb70
NS
709inode_item_done(
710 xfs_inode_log_item_t *iip)
2bd0ea18 711{
ad10fb70
NS
712 xfs_dinode_t *dip;
713 xfs_inode_t *ip;
714 xfs_mount_t *mp;
715 xfs_buf_t *bp;
ad10fb70 716 int error;
2bd0ea18
NS
717
718 ip = iip->ili_inode;
719 mp = iip->ili_item.li_mountp;
2bd0ea18
NS
720 ASSERT(ip != NULL);
721
a2ceac1f 722 if (!(iip->ili_fields & XFS_ILOG_ALL)) {
2bd0ea18
NS
723 ip->i_transp = NULL; /* disassociate from transaction */
724 iip->ili_flags = 0; /* reset all flags */
260c85e8 725 return;
2bd0ea18
NS
726 }
727
728 /*
729 * Get the buffer containing the on-disk inode.
730 */
a2ceac1f 731 error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, 0, 0);
2bd0ea18 732 if (error) {
a2ceac1f 733 fprintf(stderr, _("%s: warning - imap_to_bp failed (%d)\n"),
2bd0ea18 734 progname, error);
260c85e8 735 return;
2bd0ea18
NS
736 }
737
37d086ca 738 bp->b_log_item = iip;
2bd0ea18
NS
739 error = libxfs_iflush_int(ip, bp);
740 if (error) {
9440d84d 741 fprintf(stderr, _("%s: warning - iflush_int failed (%d)\n"),
2bd0ea18 742 progname, error);
260c85e8 743 return;
2bd0ea18
NS
744 }
745
746 ip->i_transp = NULL; /* disassociate from transaction */
37d086ca 747 bp->b_log_item = NULL; /* remove log item */
cfc06b60 748 bp->b_transp = NULL; /* remove xact ptr */
f1b058f9 749 libxfs_writebuf(bp, 0);
2bd0ea18 750#ifdef XACT_DEBUG
260c85e8
MT
751 fprintf(stderr, "flushing dirty inode %llu, buffer %p\n",
752 ip->i_ino, bp);
2bd0ea18 753#endif
2bd0ea18
NS
754}
755
5e656dbb 756static void
ad10fb70
NS
757buf_item_done(
758 xfs_buf_log_item_t *bip)
2bd0ea18 759{
ad10fb70
NS
760 xfs_buf_t *bp;
761 int hold;
5e656dbb 762 extern kmem_zone_t *xfs_buf_item_zone;
2bd0ea18
NS
763
764 bp = bip->bli_buf;
765 ASSERT(bp != NULL);
37d086ca 766 bp->b_log_item = NULL; /* remove log item */
cfc06b60 767 bp->b_transp = NULL; /* remove xact ptr */
2bd0ea18
NS
768
769 hold = (bip->bli_flags & XFS_BLI_HOLD);
2556c98b 770 if (bip->bli_flags & XFS_BLI_DIRTY) {
2bd0ea18 771#ifdef XACT_DEBUG
f1b058f9 772 fprintf(stderr, "flushing/staling buffer %p (hold=%d)\n",
2bd0ea18
NS
773 bp, hold);
774#endif
2556c98b 775 libxfs_writebuf_int(bp, 0);
2bd0ea18 776 }
2556c98b
BN
777 if (hold)
778 bip->bli_flags &= ~XFS_BLI_HOLD;
779 else
780 libxfs_putbuf(bp);
2bd0ea18
NS
781 /* release the buf item */
782 kmem_zone_free(xfs_buf_item_zone, bip);
783}
784
2bd0ea18 785static void
c40bdaa2
DC
786trans_committed(
787 xfs_trans_t *tp)
2bd0ea18 788{
c40bdaa2
DC
789 struct xfs_log_item_desc *lidp, *next;
790
791 list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
792 struct xfs_log_item *lip = lidp->lid_item;
793
68f7f684 794 xfs_trans_del_item(lip);
a2ceac1f 795
2bd0ea18 796 if (lip->li_type == XFS_LI_BUF)
c40bdaa2 797 buf_item_done((xfs_buf_log_item_t *)lip);
2bd0ea18 798 else if (lip->li_type == XFS_LI_INODE)
c40bdaa2 799 inode_item_done((xfs_inode_log_item_t *)lip);
2bd0ea18 800 else {
9440d84d 801 fprintf(stderr, _("%s: unrecognised log item type\n"),
2bd0ea18
NS
802 progname);
803 ASSERT(0);
804 }
c40bdaa2 805 }
2bd0ea18
NS
806}
807
5e656dbb 808static void
1bab604b
NS
809buf_item_unlock(
810 xfs_buf_log_item_t *bip)
811{
812 xfs_buf_t *bp = bip->bli_buf;
813 uint hold;
814
815 /* Clear the buffer's association with this transaction. */
cfc06b60 816 bip->bli_buf->b_transp = NULL;
1bab604b
NS
817
818 hold = bip->bli_flags & XFS_BLI_HOLD;
c40bdaa2 819 bip->bli_flags &= ~XFS_BLI_HOLD;
1bab604b
NS
820 if (!hold)
821 libxfs_putbuf(bp);
1bab604b
NS
822}
823
5e656dbb 824static void
1bab604b
NS
825inode_item_unlock(
826 xfs_inode_log_item_t *iip)
827{
828 xfs_inode_t *ip = iip->ili_inode;
1bab604b
NS
829
830 /* Clear the transaction pointer in the inode. */
831 ip->i_transp = NULL;
832
1bab604b
NS
833 iip->ili_flags = 0;
834}
835
2bd0ea18 836/*
c40bdaa2
DC
837 * Unlock all of the items of a transaction and free all the descriptors
838 * of that transaction.
2bd0ea18 839 */
7bcb8403 840static void
c40bdaa2 841xfs_trans_free_items(
7bcb8403 842 struct xfs_trans *tp)
2bd0ea18 843{
c40bdaa2 844 struct xfs_log_item_desc *lidp, *next;
2bd0ea18 845
c40bdaa2
DC
846 list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
847 struct xfs_log_item *lip = lidp->lid_item;
848
849 xfs_trans_del_item(lip);
1bab604b 850 if (lip->li_type == XFS_LI_BUF)
c40bdaa2 851 buf_item_unlock((xfs_buf_log_item_t *)lip);
1bab604b 852 else if (lip->li_type == XFS_LI_INODE)
c40bdaa2 853 inode_item_unlock((xfs_inode_log_item_t *)lip);
2bd0ea18 854 else {
9440d84d 855 fprintf(stderr, _("%s: unrecognised log item type\n"),
2bd0ea18
NS
856 progname);
857 ASSERT(0);
858 }
2bd0ea18 859 }
2bd0ea18
NS
860}
861
2bd0ea18
NS
862/*
863 * Commit the changes represented by this transaction
864 */
865int
ad10fb70 866libxfs_trans_commit(
de5a3f46 867 xfs_trans_t *tp)
2bd0ea18
NS
868{
869 xfs_sb_t *sbp;
2bd0ea18
NS
870
871 if (tp == NULL)
872 return 0;
873
874 if (!(tp->t_flags & XFS_TRANS_DIRTY)) {
875#ifdef XACT_DEBUG
876 fprintf(stderr, "committed clean transaction %p\n", tp);
877#endif
7bcb8403 878 xfs_trans_free_items(tp);
67d72279 879 xfs_trans_free(tp);
2bd0ea18
NS
880 return 0;
881 }
882
883 if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
884 sbp = &(tp->t_mountp->m_sb);
885 if (tp->t_icount_delta)
886 sbp->sb_icount += tp->t_icount_delta;
887 if (tp->t_ifree_delta)
888 sbp->sb_ifree += tp->t_ifree_delta;
889 if (tp->t_fdblocks_delta)
890 sbp->sb_fdblocks += tp->t_fdblocks_delta;
891 if (tp->t_frextents_delta)
892 sbp->sb_frextents += tp->t_frextents_delta;
19ebedcf 893 xfs_log_sb(tp);
2bd0ea18
NS
894 }
895
896#ifdef XACT_DEBUG
897 fprintf(stderr, "committing dirty transaction %p\n", tp);
898#endif
899 trans_committed(tp);
900
901 /* That's it for the transaction structure. Free it. */
67d72279 902 xfs_trans_free(tp);
2bd0ea18
NS
903 return 0;
904}