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