1
2
3
4
5
6#include "xfs.h"
7#include "xfs_fs.h"
8#include "xfs_shared.h"
9#include "xfs_format.h"
10#include "xfs_log_format.h"
11#include "xfs_trans_resv.h"
12#include "xfs_mount.h"
13#include "xfs_inode.h"
14#include "xfs_trans.h"
15#include "xfs_buf_item.h"
16#include "xfs_trans_priv.h"
17#include "xfs_error.h"
18#include "xfs_trace.h"
19
20
21
22
23
24STATIC struct xfs_buf *
25xfs_trans_buf_item_match(
26 struct xfs_trans *tp,
27 struct xfs_buftarg *target,
28 struct xfs_buf_map *map,
29 int nmaps)
30{
31 struct xfs_log_item *lip;
32 struct xfs_buf_log_item *blip;
33 int len = 0;
34 int i;
35
36 for (i = 0; i < nmaps; i++)
37 len += map[i].bm_len;
38
39 list_for_each_entry(lip, &tp->t_items, li_trans) {
40 blip = (struct xfs_buf_log_item *)lip;
41 if (blip->bli_item.li_type == XFS_LI_BUF &&
42 blip->bli_buf->b_target == target &&
43 XFS_BUF_ADDR(blip->bli_buf) == map[0].bm_bn &&
44 blip->bli_buf->b_length == len) {
45 ASSERT(blip->bli_buf->b_map_count == nmaps);
46 return blip->bli_buf;
47 }
48 }
49
50 return NULL;
51}
52
53
54
55
56
57
58
59
60
61
62STATIC void
63_xfs_trans_bjoin(
64 struct xfs_trans *tp,
65 struct xfs_buf *bp,
66 int reset_recur)
67{
68 struct xfs_buf_log_item *bip;
69
70 ASSERT(bp->b_transp == NULL);
71
72
73
74
75
76
77 xfs_buf_item_init(bp, tp->t_mountp);
78 bip = bp->b_log_item;
79 ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
80 ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
81 ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
82 if (reset_recur)
83 bip->bli_recur = 0;
84
85
86
87
88 atomic_inc(&bip->bli_refcount);
89
90
91
92
93
94 xfs_trans_add_item(tp, &bip->bli_item);
95 bp->b_transp = tp;
96
97}
98
99void
100xfs_trans_bjoin(
101 struct xfs_trans *tp,
102 struct xfs_buf *bp)
103{
104 _xfs_trans_bjoin(tp, bp, 0);
105 trace_xfs_trans_bjoin(bp->b_log_item);
106}
107
108
109
110
111
112
113
114
115
116
117struct xfs_buf *
118xfs_trans_get_buf_map(
119 struct xfs_trans *tp,
120 struct xfs_buftarg *target,
121 struct xfs_buf_map *map,
122 int nmaps,
123 xfs_buf_flags_t flags)
124{
125 xfs_buf_t *bp;
126 struct xfs_buf_log_item *bip;
127
128 if (!tp)
129 return xfs_buf_get_map(target, map, nmaps, flags);
130
131
132
133
134
135
136
137 bp = xfs_trans_buf_item_match(tp, target, map, nmaps);
138 if (bp != NULL) {
139 ASSERT(xfs_buf_islocked(bp));
140 if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) {
141 xfs_buf_stale(bp);
142 bp->b_flags |= XBF_DONE;
143 }
144
145 ASSERT(bp->b_transp == tp);
146 bip = bp->b_log_item;
147 ASSERT(bip != NULL);
148 ASSERT(atomic_read(&bip->bli_refcount) > 0);
149 bip->bli_recur++;
150 trace_xfs_trans_get_buf_recur(bip);
151 return bp;
152 }
153
154 bp = xfs_buf_get_map(target, map, nmaps, flags);
155 if (bp == NULL) {
156 return NULL;
157 }
158
159 ASSERT(!bp->b_error);
160
161 _xfs_trans_bjoin(tp, bp, 1);
162 trace_xfs_trans_get_buf(bp->b_log_item);
163 return bp;
164}
165
166
167
168
169
170
171
172
173
174xfs_buf_t *
175xfs_trans_getsb(
176 xfs_trans_t *tp,
177 struct xfs_mount *mp,
178 int flags)
179{
180 xfs_buf_t *bp;
181 struct xfs_buf_log_item *bip;
182
183
184
185
186
187 if (tp == NULL)
188 return xfs_getsb(mp, flags);
189
190
191
192
193
194
195
196 bp = mp->m_sb_bp;
197 if (bp->b_transp == tp) {
198 bip = bp->b_log_item;
199 ASSERT(bip != NULL);
200 ASSERT(atomic_read(&bip->bli_refcount) > 0);
201 bip->bli_recur++;
202 trace_xfs_trans_getsb_recur(bip);
203 return bp;
204 }
205
206 bp = xfs_getsb(mp, flags);
207 if (bp == NULL)
208 return NULL;
209
210 _xfs_trans_bjoin(tp, bp, 1);
211 trace_xfs_trans_getsb(bp->b_log_item);
212 return bp;
213}
214
215
216
217
218
219
220
221
222
223
224
225int
226xfs_trans_read_buf_map(
227 struct xfs_mount *mp,
228 struct xfs_trans *tp,
229 struct xfs_buftarg *target,
230 struct xfs_buf_map *map,
231 int nmaps,
232 xfs_buf_flags_t flags,
233 struct xfs_buf **bpp,
234 const struct xfs_buf_ops *ops)
235{
236 struct xfs_buf *bp = NULL;
237 struct xfs_buf_log_item *bip;
238 int error;
239
240 *bpp = NULL;
241
242
243
244
245
246
247
248
249 if (tp)
250 bp = xfs_trans_buf_item_match(tp, target, map, nmaps);
251 if (bp) {
252 ASSERT(xfs_buf_islocked(bp));
253 ASSERT(bp->b_transp == tp);
254 ASSERT(bp->b_log_item != NULL);
255 ASSERT(!bp->b_error);
256 ASSERT(bp->b_flags & XBF_DONE);
257
258
259
260
261
262 if (XFS_FORCED_SHUTDOWN(mp)) {
263 trace_xfs_trans_read_buf_shut(bp, _RET_IP_);
264 return -EIO;
265 }
266
267
268
269
270
271
272
273
274
275
276
277
278
279 ASSERT(bp->b_ops != NULL);
280 error = xfs_buf_ensure_ops(bp, ops);
281 if (error) {
282 xfs_buf_ioerror_alert(bp, __func__);
283
284 if (tp->t_flags & XFS_TRANS_DIRTY)
285 xfs_force_shutdown(tp->t_mountp,
286 SHUTDOWN_META_IO_ERROR);
287
288
289 if (error == -EFSBADCRC)
290 error = -EFSCORRUPTED;
291 return error;
292 }
293
294 bip = bp->b_log_item;
295 bip->bli_recur++;
296
297 ASSERT(atomic_read(&bip->bli_refcount) > 0);
298 trace_xfs_trans_read_buf_recur(bip);
299 ASSERT(bp->b_ops != NULL || ops == NULL);
300 *bpp = bp;
301 return 0;
302 }
303
304 bp = xfs_buf_read_map(target, map, nmaps, flags, ops);
305 if (!bp) {
306 if (!(flags & XBF_TRYLOCK))
307 return -ENOMEM;
308 return tp ? 0 : -EAGAIN;
309 }
310
311
312
313
314
315
316
317
318
319
320 if (bp->b_error) {
321 error = bp->b_error;
322 if (!XFS_FORCED_SHUTDOWN(mp))
323 xfs_buf_ioerror_alert(bp, __func__);
324 bp->b_flags &= ~XBF_DONE;
325 xfs_buf_stale(bp);
326
327 if (tp && (tp->t_flags & XFS_TRANS_DIRTY))
328 xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR);
329 xfs_buf_relse(bp);
330
331
332 if (error == -EFSBADCRC)
333 error = -EFSCORRUPTED;
334 return error;
335 }
336
337 if (XFS_FORCED_SHUTDOWN(mp)) {
338 xfs_buf_relse(bp);
339 trace_xfs_trans_read_buf_shut(bp, _RET_IP_);
340 return -EIO;
341 }
342
343 if (tp) {
344 _xfs_trans_bjoin(tp, bp, 1);
345 trace_xfs_trans_read_buf(bp->b_log_item);
346 }
347 ASSERT(bp->b_ops != NULL || ops == NULL);
348 *bpp = bp;
349 return 0;
350
351}
352
353
354bool
355xfs_trans_buf_is_dirty(
356 struct xfs_buf *bp)
357{
358 struct xfs_buf_log_item *bip = bp->b_log_item;
359
360 if (!bip)
361 return false;
362 ASSERT(bip->bli_item.li_type == XFS_LI_BUF);
363 return test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags);
364}
365
366
367
368
369
370
371
372
373
374
375
376
377
378void
379xfs_trans_brelse(
380 struct xfs_trans *tp,
381 struct xfs_buf *bp)
382{
383 struct xfs_buf_log_item *bip = bp->b_log_item;
384
385 ASSERT(bp->b_transp == tp);
386
387 if (!tp) {
388 xfs_buf_relse(bp);
389 return;
390 }
391
392 trace_xfs_trans_brelse(bip);
393 ASSERT(bip->bli_item.li_type == XFS_LI_BUF);
394 ASSERT(atomic_read(&bip->bli_refcount) > 0);
395
396
397
398
399
400 if (bip->bli_recur > 0) {
401 bip->bli_recur--;
402 return;
403 }
404
405
406
407
408
409 if (test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags))
410 return;
411 if (bip->bli_flags & XFS_BLI_STALE)
412 return;
413
414
415
416
417
418 ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
419 xfs_trans_del_item(&bip->bli_item);
420 bip->bli_flags &= ~XFS_BLI_HOLD;
421
422
423 xfs_buf_item_put(bip);
424
425 bp->b_transp = NULL;
426 xfs_buf_relse(bp);
427}
428
429
430
431
432
433
434
435void
436xfs_trans_bhold(
437 xfs_trans_t *tp,
438 xfs_buf_t *bp)
439{
440 struct xfs_buf_log_item *bip = bp->b_log_item;
441
442 ASSERT(bp->b_transp == tp);
443 ASSERT(bip != NULL);
444 ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
445 ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
446 ASSERT(atomic_read(&bip->bli_refcount) > 0);
447
448 bip->bli_flags |= XFS_BLI_HOLD;
449 trace_xfs_trans_bhold(bip);
450}
451
452
453
454
455
456void
457xfs_trans_bhold_release(
458 xfs_trans_t *tp,
459 xfs_buf_t *bp)
460{
461 struct xfs_buf_log_item *bip = bp->b_log_item;
462
463 ASSERT(bp->b_transp == tp);
464 ASSERT(bip != NULL);
465 ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
466 ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
467 ASSERT(atomic_read(&bip->bli_refcount) > 0);
468 ASSERT(bip->bli_flags & XFS_BLI_HOLD);
469
470 bip->bli_flags &= ~XFS_BLI_HOLD;
471 trace_xfs_trans_bhold_release(bip);
472}
473
474
475
476
477void
478xfs_trans_dirty_buf(
479 struct xfs_trans *tp,
480 struct xfs_buf *bp)
481{
482 struct xfs_buf_log_item *bip = bp->b_log_item;
483
484 ASSERT(bp->b_transp == tp);
485 ASSERT(bip != NULL);
486 ASSERT(bp->b_iodone == NULL ||
487 bp->b_iodone == xfs_buf_iodone_callbacks);
488
489
490
491
492
493
494
495
496
497
498
499 bp->b_flags |= XBF_DONE;
500
501 ASSERT(atomic_read(&bip->bli_refcount) > 0);
502 bp->b_iodone = xfs_buf_iodone_callbacks;
503 bip->bli_item.li_cb = xfs_buf_iodone;
504
505
506
507
508
509
510
511 if (bip->bli_flags & XFS_BLI_STALE) {
512 bip->bli_flags &= ~XFS_BLI_STALE;
513 ASSERT(bp->b_flags & XBF_STALE);
514 bp->b_flags &= ~XBF_STALE;
515 bip->__bli_format.blf_flags &= ~XFS_BLF_CANCEL;
516 }
517 bip->bli_flags |= XFS_BLI_DIRTY | XFS_BLI_LOGGED;
518
519 tp->t_flags |= XFS_TRANS_DIRTY;
520 set_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags);
521}
522
523
524
525
526
527
528
529
530
531
532void
533xfs_trans_log_buf(
534 struct xfs_trans *tp,
535 struct xfs_buf *bp,
536 uint first,
537 uint last)
538{
539 struct xfs_buf_log_item *bip = bp->b_log_item;
540
541 ASSERT(first <= last && last < BBTOB(bp->b_length));
542 ASSERT(!(bip->bli_flags & XFS_BLI_ORDERED));
543
544 xfs_trans_dirty_buf(tp, bp);
545
546 trace_xfs_trans_log_buf(bip);
547 xfs_buf_item_log(bip, first, last);
548}
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580void
581xfs_trans_binval(
582 xfs_trans_t *tp,
583 xfs_buf_t *bp)
584{
585 struct xfs_buf_log_item *bip = bp->b_log_item;
586 int i;
587
588 ASSERT(bp->b_transp == tp);
589 ASSERT(bip != NULL);
590 ASSERT(atomic_read(&bip->bli_refcount) > 0);
591
592 trace_xfs_trans_binval(bip);
593
594 if (bip->bli_flags & XFS_BLI_STALE) {
595
596
597
598
599 ASSERT(bp->b_flags & XBF_STALE);
600 ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY)));
601 ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_INODE_BUF));
602 ASSERT(!(bip->__bli_format.blf_flags & XFS_BLFT_MASK));
603 ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL);
604 ASSERT(test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags));
605 ASSERT(tp->t_flags & XFS_TRANS_DIRTY);
606 return;
607 }
608
609 xfs_buf_stale(bp);
610
611 bip->bli_flags |= XFS_BLI_STALE;
612 bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY);
613 bip->__bli_format.blf_flags &= ~XFS_BLF_INODE_BUF;
614 bip->__bli_format.blf_flags |= XFS_BLF_CANCEL;
615 bip->__bli_format.blf_flags &= ~XFS_BLFT_MASK;
616 for (i = 0; i < bip->bli_format_count; i++) {
617 memset(bip->bli_formats[i].blf_data_map, 0,
618 (bip->bli_formats[i].blf_map_size * sizeof(uint)));
619 }
620 set_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags);
621 tp->t_flags |= XFS_TRANS_DIRTY;
622}
623
624
625
626
627
628
629
630
631
632
633
634
635void
636xfs_trans_inode_buf(
637 xfs_trans_t *tp,
638 xfs_buf_t *bp)
639{
640 struct xfs_buf_log_item *bip = bp->b_log_item;
641
642 ASSERT(bp->b_transp == tp);
643 ASSERT(bip != NULL);
644 ASSERT(atomic_read(&bip->bli_refcount) > 0);
645
646 bip->bli_flags |= XFS_BLI_INODE_BUF;
647 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF);
648}
649
650
651
652
653
654
655
656
657
658
659void
660xfs_trans_stale_inode_buf(
661 xfs_trans_t *tp,
662 xfs_buf_t *bp)
663{
664 struct xfs_buf_log_item *bip = bp->b_log_item;
665
666 ASSERT(bp->b_transp == tp);
667 ASSERT(bip != NULL);
668 ASSERT(atomic_read(&bip->bli_refcount) > 0);
669
670 bip->bli_flags |= XFS_BLI_STALE_INODE;
671 bip->bli_item.li_cb = xfs_buf_iodone;
672 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF);
673}
674
675
676
677
678
679
680
681
682
683
684void
685xfs_trans_inode_alloc_buf(
686 xfs_trans_t *tp,
687 xfs_buf_t *bp)
688{
689 struct xfs_buf_log_item *bip = bp->b_log_item;
690
691 ASSERT(bp->b_transp == tp);
692 ASSERT(bip != NULL);
693 ASSERT(atomic_read(&bip->bli_refcount) > 0);
694
695 bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF;
696 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF);
697}
698
699
700
701
702
703
704
705
706bool
707xfs_trans_ordered_buf(
708 struct xfs_trans *tp,
709 struct xfs_buf *bp)
710{
711 struct xfs_buf_log_item *bip = bp->b_log_item;
712
713 ASSERT(bp->b_transp == tp);
714 ASSERT(bip != NULL);
715 ASSERT(atomic_read(&bip->bli_refcount) > 0);
716
717 if (xfs_buf_item_dirty_format(bip))
718 return false;
719
720 bip->bli_flags |= XFS_BLI_ORDERED;
721 trace_xfs_buf_item_ordered(bip);
722
723
724
725
726
727 xfs_trans_dirty_buf(tp, bp);
728 return true;
729}
730
731
732
733
734
735void
736xfs_trans_buf_set_type(
737 struct xfs_trans *tp,
738 struct xfs_buf *bp,
739 enum xfs_blft type)
740{
741 struct xfs_buf_log_item *bip = bp->b_log_item;
742
743 if (!tp)
744 return;
745
746 ASSERT(bp->b_transp == tp);
747 ASSERT(bip != NULL);
748 ASSERT(atomic_read(&bip->bli_refcount) > 0);
749
750 xfs_blft_to_flags(&bip->__bli_format, type);
751}
752
753void
754xfs_trans_buf_copy_type(
755 struct xfs_buf *dst_bp,
756 struct xfs_buf *src_bp)
757{
758 struct xfs_buf_log_item *sbip = src_bp->b_log_item;
759 struct xfs_buf_log_item *dbip = dst_bp->b_log_item;
760 enum xfs_blft type;
761
762 type = xfs_blft_from_flags(&sbip->__bli_format);
763 xfs_blft_to_flags(&dbip->__bli_format, type);
764}
765
766
767
768
769
770
771
772
773
774
775
776
777void
778xfs_trans_dquot_buf(
779 xfs_trans_t *tp,
780 xfs_buf_t *bp,
781 uint type)
782{
783 struct xfs_buf_log_item *bip = bp->b_log_item;
784
785 ASSERT(type == XFS_BLF_UDQUOT_BUF ||
786 type == XFS_BLF_PDQUOT_BUF ||
787 type == XFS_BLF_GDQUOT_BUF);
788
789 bip->__bli_format.blf_flags |= type;
790
791 switch (type) {
792 case XFS_BLF_UDQUOT_BUF:
793 type = XFS_BLFT_UDQUOT_BUF;
794 break;
795 case XFS_BLF_PDQUOT_BUF:
796 type = XFS_BLFT_PDQUOT_BUF;
797 break;
798 case XFS_BLF_GDQUOT_BUF:
799 type = XFS_BLFT_GDQUOT_BUF;
800 break;
801 default:
802 type = XFS_BLFT_UNKNOWN_BUF;
803 break;
804 }
805
806 xfs_trans_buf_set_type(tp, bp, type);
807}
808