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