0001
0002
0003
0004
0005
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_trans.h"
0014 #include "xfs_buf_item.h"
0015 #include "xfs_trans_priv.h"
0016 #include "xfs_trace.h"
0017
0018
0019
0020
0021
0022 STATIC struct xfs_buf *
0023 xfs_trans_buf_item_match(
0024 struct xfs_trans *tp,
0025 struct xfs_buftarg *target,
0026 struct xfs_buf_map *map,
0027 int nmaps)
0028 {
0029 struct xfs_log_item *lip;
0030 struct xfs_buf_log_item *blip;
0031 int len = 0;
0032 int i;
0033
0034 for (i = 0; i < nmaps; i++)
0035 len += map[i].bm_len;
0036
0037 list_for_each_entry(lip, &tp->t_items, li_trans) {
0038 blip = (struct xfs_buf_log_item *)lip;
0039 if (blip->bli_item.li_type == XFS_LI_BUF &&
0040 blip->bli_buf->b_target == target &&
0041 xfs_buf_daddr(blip->bli_buf) == map[0].bm_bn &&
0042 blip->bli_buf->b_length == len) {
0043 ASSERT(blip->bli_buf->b_map_count == nmaps);
0044 return blip->bli_buf;
0045 }
0046 }
0047
0048 return NULL;
0049 }
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 STATIC void
0061 _xfs_trans_bjoin(
0062 struct xfs_trans *tp,
0063 struct xfs_buf *bp,
0064 int reset_recur)
0065 {
0066 struct xfs_buf_log_item *bip;
0067
0068 ASSERT(bp->b_transp == NULL);
0069
0070
0071
0072
0073
0074
0075 xfs_buf_item_init(bp, tp->t_mountp);
0076 bip = bp->b_log_item;
0077 ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
0078 ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
0079 ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
0080 if (reset_recur)
0081 bip->bli_recur = 0;
0082
0083
0084
0085
0086 atomic_inc(&bip->bli_refcount);
0087
0088
0089
0090
0091
0092 xfs_trans_add_item(tp, &bip->bli_item);
0093 bp->b_transp = tp;
0094
0095 }
0096
0097 void
0098 xfs_trans_bjoin(
0099 struct xfs_trans *tp,
0100 struct xfs_buf *bp)
0101 {
0102 _xfs_trans_bjoin(tp, bp, 0);
0103 trace_xfs_trans_bjoin(bp->b_log_item);
0104 }
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 int
0116 xfs_trans_get_buf_map(
0117 struct xfs_trans *tp,
0118 struct xfs_buftarg *target,
0119 struct xfs_buf_map *map,
0120 int nmaps,
0121 xfs_buf_flags_t flags,
0122 struct xfs_buf **bpp)
0123 {
0124 struct xfs_buf *bp;
0125 struct xfs_buf_log_item *bip;
0126 int error;
0127
0128 *bpp = NULL;
0129 if (!tp)
0130 return xfs_buf_get_map(target, map, nmaps, flags, bpp);
0131
0132
0133
0134
0135
0136
0137
0138 bp = xfs_trans_buf_item_match(tp, target, map, nmaps);
0139 if (bp != NULL) {
0140 ASSERT(xfs_buf_islocked(bp));
0141 if (xfs_is_shutdown(tp->t_mountp)) {
0142 xfs_buf_stale(bp);
0143 bp->b_flags |= XBF_DONE;
0144 }
0145
0146 ASSERT(bp->b_transp == tp);
0147 bip = bp->b_log_item;
0148 ASSERT(bip != NULL);
0149 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0150 bip->bli_recur++;
0151 trace_xfs_trans_get_buf_recur(bip);
0152 *bpp = bp;
0153 return 0;
0154 }
0155
0156 error = xfs_buf_get_map(target, map, nmaps, flags, &bp);
0157 if (error)
0158 return error;
0159
0160 ASSERT(!bp->b_error);
0161
0162 _xfs_trans_bjoin(tp, bp, 1);
0163 trace_xfs_trans_get_buf(bp->b_log_item);
0164 *bpp = bp;
0165 return 0;
0166 }
0167
0168
0169
0170
0171 struct xfs_buf *
0172 xfs_trans_getsb(
0173 struct xfs_trans *tp)
0174 {
0175 struct xfs_buf *bp = tp->t_mountp->m_sb_bp;
0176
0177
0178
0179
0180
0181 if (bp->b_transp == tp) {
0182 struct xfs_buf_log_item *bip = bp->b_log_item;
0183
0184 ASSERT(bip != NULL);
0185 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0186 bip->bli_recur++;
0187
0188 trace_xfs_trans_getsb_recur(bip);
0189 } else {
0190 xfs_buf_lock(bp);
0191 xfs_buf_hold(bp);
0192 _xfs_trans_bjoin(tp, bp, 1);
0193
0194 trace_xfs_trans_getsb(bp->b_log_item);
0195 }
0196
0197 return bp;
0198 }
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 int
0211 xfs_trans_read_buf_map(
0212 struct xfs_mount *mp,
0213 struct xfs_trans *tp,
0214 struct xfs_buftarg *target,
0215 struct xfs_buf_map *map,
0216 int nmaps,
0217 xfs_buf_flags_t flags,
0218 struct xfs_buf **bpp,
0219 const struct xfs_buf_ops *ops)
0220 {
0221 struct xfs_buf *bp = NULL;
0222 struct xfs_buf_log_item *bip;
0223 int error;
0224
0225 *bpp = NULL;
0226
0227
0228
0229
0230
0231
0232
0233
0234 if (tp)
0235 bp = xfs_trans_buf_item_match(tp, target, map, nmaps);
0236 if (bp) {
0237 ASSERT(xfs_buf_islocked(bp));
0238 ASSERT(bp->b_transp == tp);
0239 ASSERT(bp->b_log_item != NULL);
0240 ASSERT(!bp->b_error);
0241 ASSERT(bp->b_flags & XBF_DONE);
0242
0243
0244
0245
0246
0247 if (xfs_is_shutdown(mp)) {
0248 trace_xfs_trans_read_buf_shut(bp, _RET_IP_);
0249 return -EIO;
0250 }
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264 ASSERT(bp->b_ops != NULL);
0265 error = xfs_buf_reverify(bp, ops);
0266 if (error) {
0267 xfs_buf_ioerror_alert(bp, __return_address);
0268
0269 if (tp->t_flags & XFS_TRANS_DIRTY)
0270 xfs_force_shutdown(tp->t_mountp,
0271 SHUTDOWN_META_IO_ERROR);
0272
0273
0274 if (error == -EFSBADCRC)
0275 error = -EFSCORRUPTED;
0276 return error;
0277 }
0278
0279 bip = bp->b_log_item;
0280 bip->bli_recur++;
0281
0282 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0283 trace_xfs_trans_read_buf_recur(bip);
0284 ASSERT(bp->b_ops != NULL || ops == NULL);
0285 *bpp = bp;
0286 return 0;
0287 }
0288
0289 error = xfs_buf_read_map(target, map, nmaps, flags, &bp, ops,
0290 __return_address);
0291 switch (error) {
0292 case 0:
0293 break;
0294 default:
0295 if (tp && (tp->t_flags & XFS_TRANS_DIRTY))
0296 xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR);
0297 fallthrough;
0298 case -ENOMEM:
0299 case -EAGAIN:
0300 return error;
0301 }
0302
0303 if (xfs_is_shutdown(mp)) {
0304 xfs_buf_relse(bp);
0305 trace_xfs_trans_read_buf_shut(bp, _RET_IP_);
0306 return -EIO;
0307 }
0308
0309 if (tp) {
0310 _xfs_trans_bjoin(tp, bp, 1);
0311 trace_xfs_trans_read_buf(bp->b_log_item);
0312 }
0313 ASSERT(bp->b_ops != NULL || ops == NULL);
0314 *bpp = bp;
0315 return 0;
0316
0317 }
0318
0319
0320 bool
0321 xfs_trans_buf_is_dirty(
0322 struct xfs_buf *bp)
0323 {
0324 struct xfs_buf_log_item *bip = bp->b_log_item;
0325
0326 if (!bip)
0327 return false;
0328 ASSERT(bip->bli_item.li_type == XFS_LI_BUF);
0329 return test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags);
0330 }
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344 void
0345 xfs_trans_brelse(
0346 struct xfs_trans *tp,
0347 struct xfs_buf *bp)
0348 {
0349 struct xfs_buf_log_item *bip = bp->b_log_item;
0350
0351 ASSERT(bp->b_transp == tp);
0352
0353 if (!tp) {
0354 xfs_buf_relse(bp);
0355 return;
0356 }
0357
0358 trace_xfs_trans_brelse(bip);
0359 ASSERT(bip->bli_item.li_type == XFS_LI_BUF);
0360 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0361
0362
0363
0364
0365
0366 if (bip->bli_recur > 0) {
0367 bip->bli_recur--;
0368 return;
0369 }
0370
0371
0372
0373
0374
0375 if (test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags))
0376 return;
0377 if (bip->bli_flags & XFS_BLI_STALE)
0378 return;
0379
0380
0381
0382
0383
0384 ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
0385 xfs_trans_del_item(&bip->bli_item);
0386 bip->bli_flags &= ~XFS_BLI_HOLD;
0387
0388
0389 xfs_buf_item_put(bip);
0390
0391 bp->b_transp = NULL;
0392 xfs_buf_relse(bp);
0393 }
0394
0395
0396
0397
0398
0399
0400
0401 void
0402 xfs_trans_bhold(
0403 xfs_trans_t *tp,
0404 struct xfs_buf *bp)
0405 {
0406 struct xfs_buf_log_item *bip = bp->b_log_item;
0407
0408 ASSERT(bp->b_transp == tp);
0409 ASSERT(bip != NULL);
0410 ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
0411 ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
0412 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0413
0414 bip->bli_flags |= XFS_BLI_HOLD;
0415 trace_xfs_trans_bhold(bip);
0416 }
0417
0418
0419
0420
0421
0422 void
0423 xfs_trans_bhold_release(
0424 xfs_trans_t *tp,
0425 struct xfs_buf *bp)
0426 {
0427 struct xfs_buf_log_item *bip = bp->b_log_item;
0428
0429 ASSERT(bp->b_transp == tp);
0430 ASSERT(bip != NULL);
0431 ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
0432 ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
0433 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0434 ASSERT(bip->bli_flags & XFS_BLI_HOLD);
0435
0436 bip->bli_flags &= ~XFS_BLI_HOLD;
0437 trace_xfs_trans_bhold_release(bip);
0438 }
0439
0440
0441
0442
0443 void
0444 xfs_trans_dirty_buf(
0445 struct xfs_trans *tp,
0446 struct xfs_buf *bp)
0447 {
0448 struct xfs_buf_log_item *bip = bp->b_log_item;
0449
0450 ASSERT(bp->b_transp == tp);
0451 ASSERT(bip != NULL);
0452
0453
0454
0455
0456
0457
0458
0459 bp->b_flags |= XBF_DONE;
0460
0461 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0462
0463
0464
0465
0466
0467
0468
0469 if (bip->bli_flags & XFS_BLI_STALE) {
0470 bip->bli_flags &= ~XFS_BLI_STALE;
0471 ASSERT(bp->b_flags & XBF_STALE);
0472 bp->b_flags &= ~XBF_STALE;
0473 bip->__bli_format.blf_flags &= ~XFS_BLF_CANCEL;
0474 }
0475 bip->bli_flags |= XFS_BLI_DIRTY | XFS_BLI_LOGGED;
0476
0477 tp->t_flags |= XFS_TRANS_DIRTY;
0478 set_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags);
0479 }
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490 void
0491 xfs_trans_log_buf(
0492 struct xfs_trans *tp,
0493 struct xfs_buf *bp,
0494 uint first,
0495 uint last)
0496 {
0497 struct xfs_buf_log_item *bip = bp->b_log_item;
0498
0499 ASSERT(first <= last && last < BBTOB(bp->b_length));
0500 ASSERT(!(bip->bli_flags & XFS_BLI_ORDERED));
0501
0502 xfs_trans_dirty_buf(tp, bp);
0503
0504 trace_xfs_trans_log_buf(bip);
0505 xfs_buf_item_log(bip, first, last);
0506 }
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538 void
0539 xfs_trans_binval(
0540 xfs_trans_t *tp,
0541 struct xfs_buf *bp)
0542 {
0543 struct xfs_buf_log_item *bip = bp->b_log_item;
0544 int i;
0545
0546 ASSERT(bp->b_transp == tp);
0547 ASSERT(bip != NULL);
0548 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0549
0550 trace_xfs_trans_binval(bip);
0551
0552 if (bip->bli_flags & XFS_BLI_STALE) {
0553
0554
0555
0556
0557 ASSERT(bp->b_flags & XBF_STALE);
0558 ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY)));
0559 ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_INODE_BUF));
0560 ASSERT(!(bip->__bli_format.blf_flags & XFS_BLFT_MASK));
0561 ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL);
0562 ASSERT(test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags));
0563 ASSERT(tp->t_flags & XFS_TRANS_DIRTY);
0564 return;
0565 }
0566
0567 xfs_buf_stale(bp);
0568
0569 bip->bli_flags |= XFS_BLI_STALE;
0570 bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY);
0571 bip->__bli_format.blf_flags &= ~XFS_BLF_INODE_BUF;
0572 bip->__bli_format.blf_flags |= XFS_BLF_CANCEL;
0573 bip->__bli_format.blf_flags &= ~XFS_BLFT_MASK;
0574 for (i = 0; i < bip->bli_format_count; i++) {
0575 memset(bip->bli_formats[i].blf_data_map, 0,
0576 (bip->bli_formats[i].blf_map_size * sizeof(uint)));
0577 }
0578 set_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags);
0579 tp->t_flags |= XFS_TRANS_DIRTY;
0580 }
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593 void
0594 xfs_trans_inode_buf(
0595 xfs_trans_t *tp,
0596 struct xfs_buf *bp)
0597 {
0598 struct xfs_buf_log_item *bip = bp->b_log_item;
0599
0600 ASSERT(bp->b_transp == tp);
0601 ASSERT(bip != NULL);
0602 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0603
0604 bip->bli_flags |= XFS_BLI_INODE_BUF;
0605 bp->b_flags |= _XBF_INODES;
0606 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF);
0607 }
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618 void
0619 xfs_trans_stale_inode_buf(
0620 xfs_trans_t *tp,
0621 struct xfs_buf *bp)
0622 {
0623 struct xfs_buf_log_item *bip = bp->b_log_item;
0624
0625 ASSERT(bp->b_transp == tp);
0626 ASSERT(bip != NULL);
0627 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0628
0629 bip->bli_flags |= XFS_BLI_STALE_INODE;
0630 bp->b_flags |= _XBF_INODES;
0631 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF);
0632 }
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643 void
0644 xfs_trans_inode_alloc_buf(
0645 xfs_trans_t *tp,
0646 struct xfs_buf *bp)
0647 {
0648 struct xfs_buf_log_item *bip = bp->b_log_item;
0649
0650 ASSERT(bp->b_transp == tp);
0651 ASSERT(bip != NULL);
0652 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0653
0654 bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF;
0655 bp->b_flags |= _XBF_INODES;
0656 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF);
0657 }
0658
0659
0660
0661
0662
0663
0664
0665
0666 bool
0667 xfs_trans_ordered_buf(
0668 struct xfs_trans *tp,
0669 struct xfs_buf *bp)
0670 {
0671 struct xfs_buf_log_item *bip = bp->b_log_item;
0672
0673 ASSERT(bp->b_transp == tp);
0674 ASSERT(bip != NULL);
0675 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0676
0677 if (xfs_buf_item_dirty_format(bip))
0678 return false;
0679
0680 bip->bli_flags |= XFS_BLI_ORDERED;
0681 trace_xfs_buf_item_ordered(bip);
0682
0683
0684
0685
0686
0687 xfs_trans_dirty_buf(tp, bp);
0688 return true;
0689 }
0690
0691
0692
0693
0694
0695 void
0696 xfs_trans_buf_set_type(
0697 struct xfs_trans *tp,
0698 struct xfs_buf *bp,
0699 enum xfs_blft type)
0700 {
0701 struct xfs_buf_log_item *bip = bp->b_log_item;
0702
0703 if (!tp)
0704 return;
0705
0706 ASSERT(bp->b_transp == tp);
0707 ASSERT(bip != NULL);
0708 ASSERT(atomic_read(&bip->bli_refcount) > 0);
0709
0710 xfs_blft_to_flags(&bip->__bli_format, type);
0711 }
0712
0713 void
0714 xfs_trans_buf_copy_type(
0715 struct xfs_buf *dst_bp,
0716 struct xfs_buf *src_bp)
0717 {
0718 struct xfs_buf_log_item *sbip = src_bp->b_log_item;
0719 struct xfs_buf_log_item *dbip = dst_bp->b_log_item;
0720 enum xfs_blft type;
0721
0722 type = xfs_blft_from_flags(&sbip->__bli_format);
0723 xfs_blft_to_flags(&dbip->__bli_format, type);
0724 }
0725
0726
0727
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737 void
0738 xfs_trans_dquot_buf(
0739 xfs_trans_t *tp,
0740 struct xfs_buf *bp,
0741 uint type)
0742 {
0743 struct xfs_buf_log_item *bip = bp->b_log_item;
0744
0745 ASSERT(type == XFS_BLF_UDQUOT_BUF ||
0746 type == XFS_BLF_PDQUOT_BUF ||
0747 type == XFS_BLF_GDQUOT_BUF);
0748
0749 bip->__bli_format.blf_flags |= type;
0750
0751 switch (type) {
0752 case XFS_BLF_UDQUOT_BUF:
0753 type = XFS_BLFT_UDQUOT_BUF;
0754 break;
0755 case XFS_BLF_PDQUOT_BUF:
0756 type = XFS_BLFT_PDQUOT_BUF;
0757 break;
0758 case XFS_BLF_GDQUOT_BUF:
0759 type = XFS_BLFT_GDQUOT_BUF;
0760 break;
0761 default:
0762 type = XFS_BLFT_UNKNOWN_BUF;
0763 break;
0764 }
0765
0766 bp->b_flags |= _XBF_DQUOTS;
0767 xfs_trans_buf_set_type(tp, bp, type);
0768 }