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_trans_resv.h"
11#include "xfs_mount.h"
12#include "xfs_btree.h"
13#include "xfs_log_format.h"
14#include "xfs_trans.h"
15#include "xfs_sb.h"
16#include "xfs_inode.h"
17#include "xfs_alloc.h"
18#include "xfs_alloc_btree.h"
19#include "xfs_ialloc.h"
20#include "xfs_ialloc_btree.h"
21#include "xfs_rmap.h"
22#include "xfs_rmap_btree.h"
23#include "xfs_refcount_btree.h"
24#include "xfs_extent_busy.h"
25#include "xfs_ag_resv.h"
26#include "xfs_quota.h"
27#include "scrub/scrub.h"
28#include "scrub/common.h"
29#include "scrub/trace.h"
30#include "scrub/repair.h"
31#include "scrub/bitmap.h"
32
33
34
35
36
37
38int
39xrep_attempt(
40 struct xfs_inode *ip,
41 struct xfs_scrub *sc)
42{
43 int error = 0;
44
45 trace_xrep_attempt(ip, sc->sm, error);
46
47 xchk_ag_btcur_free(&sc->sa);
48
49
50 ASSERT(sc->ops->repair);
51 error = sc->ops->repair(sc);
52 trace_xrep_done(ip, sc->sm, error);
53 switch (error) {
54 case 0:
55
56
57
58
59 sc->sm->sm_flags &= ~XFS_SCRUB_FLAGS_OUT;
60 sc->flags |= XREP_ALREADY_FIXED;
61 return -EAGAIN;
62 case -EDEADLOCK:
63 case -EAGAIN:
64
65 if (!(sc->flags & XCHK_TRY_HARDER)) {
66 sc->flags |= XCHK_TRY_HARDER;
67 return -EAGAIN;
68 }
69
70
71
72
73
74 return -EFSCORRUPTED;
75 default:
76 return error;
77 }
78}
79
80
81
82
83
84
85
86
87
88
89void
90xrep_failure(
91 struct xfs_mount *mp)
92{
93 xfs_alert_ratelimited(mp,
94"Corruption not fixed during online repair. Unmount and run xfs_repair.");
95}
96
97
98
99
100
101int
102xrep_probe(
103 struct xfs_scrub *sc)
104{
105 int error = 0;
106
107 if (xchk_should_terminate(sc, &error))
108 return error;
109
110 return 0;
111}
112
113
114
115
116
117int
118xrep_roll_ag_trans(
119 struct xfs_scrub *sc)
120{
121 int error;
122
123
124 if (sc->sa.agi_bp)
125 xfs_trans_bhold(sc->tp, sc->sa.agi_bp);
126 if (sc->sa.agf_bp)
127 xfs_trans_bhold(sc->tp, sc->sa.agf_bp);
128 if (sc->sa.agfl_bp)
129 xfs_trans_bhold(sc->tp, sc->sa.agfl_bp);
130
131
132
133
134
135
136
137
138 error = xfs_trans_roll(&sc->tp);
139 if (error)
140 return error;
141
142
143 if (sc->sa.agi_bp)
144 xfs_trans_bjoin(sc->tp, sc->sa.agi_bp);
145 if (sc->sa.agf_bp)
146 xfs_trans_bjoin(sc->tp, sc->sa.agf_bp);
147 if (sc->sa.agfl_bp)
148 xfs_trans_bjoin(sc->tp, sc->sa.agfl_bp);
149
150 return 0;
151}
152
153
154
155
156
157
158bool
159xrep_ag_has_space(
160 struct xfs_perag *pag,
161 xfs_extlen_t nr_blocks,
162 enum xfs_ag_resv_type type)
163{
164 return !xfs_ag_resv_critical(pag, XFS_AG_RESV_RMAPBT) &&
165 !xfs_ag_resv_critical(pag, XFS_AG_RESV_METADATA) &&
166 pag->pagf_freeblks > xfs_ag_resv_needed(pag, type) + nr_blocks;
167}
168
169
170
171
172
173
174xfs_extlen_t
175xrep_calc_ag_resblks(
176 struct xfs_scrub *sc)
177{
178 struct xfs_mount *mp = sc->mp;
179 struct xfs_scrub_metadata *sm = sc->sm;
180 struct xfs_perag *pag;
181 struct xfs_buf *bp;
182 xfs_agino_t icount = NULLAGINO;
183 xfs_extlen_t aglen = NULLAGBLOCK;
184 xfs_extlen_t usedlen;
185 xfs_extlen_t freelen;
186 xfs_extlen_t bnobt_sz;
187 xfs_extlen_t inobt_sz;
188 xfs_extlen_t rmapbt_sz;
189 xfs_extlen_t refcbt_sz;
190 int error;
191
192 if (!(sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR))
193 return 0;
194
195 pag = xfs_perag_get(mp, sm->sm_agno);
196 if (pag->pagi_init) {
197
198 icount = pag->pagi_count;
199 } else {
200
201 error = xfs_ialloc_read_agi(mp, NULL, sm->sm_agno, &bp);
202 if (!error) {
203 icount = pag->pagi_count;
204 xfs_buf_relse(bp);
205 }
206 }
207
208
209 error = xfs_alloc_read_agf(mp, NULL, sm->sm_agno, 0, &bp);
210 if (!error) {
211 struct xfs_agf *agf = bp->b_addr;
212
213 aglen = be32_to_cpu(agf->agf_length);
214 freelen = be32_to_cpu(agf->agf_freeblks);
215 usedlen = aglen - freelen;
216 xfs_buf_relse(bp);
217 }
218 xfs_perag_put(pag);
219
220
221 if (icount == NULLAGINO ||
222 !xfs_verify_agino(mp, sm->sm_agno, icount)) {
223 xfs_agino_t first, last;
224
225 xfs_agino_range(mp, sm->sm_agno, &first, &last);
226 icount = last - first + 1;
227 }
228
229
230 if (aglen == NULLAGBLOCK ||
231 aglen != xfs_ag_block_count(mp, sm->sm_agno) ||
232 freelen >= aglen) {
233 aglen = xfs_ag_block_count(mp, sm->sm_agno);
234 freelen = aglen;
235 usedlen = aglen;
236 }
237
238 trace_xrep_calc_ag_resblks(mp, sm->sm_agno, icount, aglen,
239 freelen, usedlen);
240
241
242
243
244
245
246 bnobt_sz = 2 * xfs_allocbt_calc_size(mp, freelen);
247 if (xfs_sb_version_hassparseinodes(&mp->m_sb))
248 inobt_sz = xfs_iallocbt_calc_size(mp, icount /
249 XFS_INODES_PER_HOLEMASK_BIT);
250 else
251 inobt_sz = xfs_iallocbt_calc_size(mp, icount /
252 XFS_INODES_PER_CHUNK);
253 if (xfs_sb_version_hasfinobt(&mp->m_sb))
254 inobt_sz *= 2;
255 if (xfs_sb_version_hasreflink(&mp->m_sb))
256 refcbt_sz = xfs_refcountbt_calc_size(mp, usedlen);
257 else
258 refcbt_sz = 0;
259 if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
260
261
262
263
264
265
266
267
268 if (xfs_sb_version_hasreflink(&mp->m_sb))
269 rmapbt_sz = xfs_rmapbt_calc_size(mp,
270 (unsigned long long)aglen * 2);
271 else
272 rmapbt_sz = xfs_rmapbt_calc_size(mp, usedlen);
273 } else {
274 rmapbt_sz = 0;
275 }
276
277 trace_xrep_calc_ag_resblks_btsize(mp, sm->sm_agno, bnobt_sz,
278 inobt_sz, rmapbt_sz, refcbt_sz);
279
280 return max(max(bnobt_sz, inobt_sz), max(rmapbt_sz, refcbt_sz));
281}
282
283
284int
285xrep_alloc_ag_block(
286 struct xfs_scrub *sc,
287 const struct xfs_owner_info *oinfo,
288 xfs_fsblock_t *fsbno,
289 enum xfs_ag_resv_type resv)
290{
291 struct xfs_alloc_arg args = {0};
292 xfs_agblock_t bno;
293 int error;
294
295 switch (resv) {
296 case XFS_AG_RESV_AGFL:
297 case XFS_AG_RESV_RMAPBT:
298 error = xfs_alloc_get_freelist(sc->tp, sc->sa.agf_bp, &bno, 1);
299 if (error)
300 return error;
301 if (bno == NULLAGBLOCK)
302 return -ENOSPC;
303 xfs_extent_busy_reuse(sc->mp, sc->sa.agno, bno,
304 1, false);
305 *fsbno = XFS_AGB_TO_FSB(sc->mp, sc->sa.agno, bno);
306 if (resv == XFS_AG_RESV_RMAPBT)
307 xfs_ag_resv_rmapbt_alloc(sc->mp, sc->sa.agno);
308 return 0;
309 default:
310 break;
311 }
312
313 args.tp = sc->tp;
314 args.mp = sc->mp;
315 args.oinfo = *oinfo;
316 args.fsbno = XFS_AGB_TO_FSB(args.mp, sc->sa.agno, 0);
317 args.minlen = 1;
318 args.maxlen = 1;
319 args.prod = 1;
320 args.type = XFS_ALLOCTYPE_THIS_AG;
321 args.resv = resv;
322
323 error = xfs_alloc_vextent(&args);
324 if (error)
325 return error;
326 if (args.fsbno == NULLFSBLOCK)
327 return -ENOSPC;
328 ASSERT(args.len == 1);
329 *fsbno = args.fsbno;
330
331 return 0;
332}
333
334
335int
336xrep_init_btblock(
337 struct xfs_scrub *sc,
338 xfs_fsblock_t fsb,
339 struct xfs_buf **bpp,
340 xfs_btnum_t btnum,
341 const struct xfs_buf_ops *ops)
342{
343 struct xfs_trans *tp = sc->tp;
344 struct xfs_mount *mp = sc->mp;
345 struct xfs_buf *bp;
346 int error;
347
348 trace_xrep_init_btblock(mp, XFS_FSB_TO_AGNO(mp, fsb),
349 XFS_FSB_TO_AGBNO(mp, fsb), btnum);
350
351 ASSERT(XFS_FSB_TO_AGNO(mp, fsb) == sc->sa.agno);
352 error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
353 XFS_FSB_TO_DADDR(mp, fsb), XFS_FSB_TO_BB(mp, 1), 0,
354 &bp);
355 if (error)
356 return error;
357 xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
358 xfs_btree_init_block(mp, bp, btnum, 0, 0, sc->sa.agno);
359 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_BTREE_BUF);
360 xfs_trans_log_buf(tp, bp, 0, BBTOB(bp->b_length) - 1);
361 bp->b_ops = ops;
362 *bpp = bp;
363
364 return 0;
365}
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436int
437xrep_invalidate_blocks(
438 struct xfs_scrub *sc,
439 struct xbitmap *bitmap)
440{
441 struct xbitmap_range *bmr;
442 struct xbitmap_range *n;
443 struct xfs_buf *bp;
444 xfs_fsblock_t fsbno;
445
446
447
448
449
450
451
452
453
454 for_each_xbitmap_block(fsbno, bmr, n, bitmap) {
455
456 if (!xfs_verify_fsbno(sc->mp, fsbno))
457 continue;
458 bp = xfs_buf_incore(sc->mp->m_ddev_targp,
459 XFS_FSB_TO_DADDR(sc->mp, fsbno),
460 XFS_FSB_TO_BB(sc->mp, 1), XBF_TRYLOCK);
461 if (bp) {
462 xfs_trans_bjoin(sc->tp, bp);
463 xfs_trans_binval(sc->tp, bp);
464 }
465 }
466
467 return 0;
468}
469
470
471int
472xrep_fix_freelist(
473 struct xfs_scrub *sc,
474 bool can_shrink)
475{
476 struct xfs_alloc_arg args = {0};
477
478 args.mp = sc->mp;
479 args.tp = sc->tp;
480 args.agno = sc->sa.agno;
481 args.alignment = 1;
482 args.pag = sc->sa.pag;
483
484 return xfs_alloc_fix_freelist(&args,
485 can_shrink ? 0 : XFS_ALLOC_FLAG_NOSHRINK);
486}
487
488
489
490
491STATIC int
492xrep_put_freelist(
493 struct xfs_scrub *sc,
494 xfs_agblock_t agbno)
495{
496 int error;
497
498
499 error = xrep_fix_freelist(sc, true);
500 if (error)
501 return error;
502
503
504
505
506
507
508 error = xfs_rmap_alloc(sc->tp, sc->sa.agf_bp, sc->sa.agno, agbno, 1,
509 &XFS_RMAP_OINFO_AG);
510 if (error)
511 return error;
512
513
514 error = xfs_alloc_put_freelist(sc->tp, sc->sa.agf_bp, sc->sa.agfl_bp,
515 agbno, 0);
516 if (error)
517 return error;
518 xfs_extent_busy_insert(sc->tp, sc->sa.agno, agbno, 1,
519 XFS_EXTENT_BUSY_SKIP_DISCARD);
520
521 return 0;
522}
523
524
525STATIC int
526xrep_reap_block(
527 struct xfs_scrub *sc,
528 xfs_fsblock_t fsbno,
529 const struct xfs_owner_info *oinfo,
530 enum xfs_ag_resv_type resv)
531{
532 struct xfs_btree_cur *cur;
533 struct xfs_buf *agf_bp = NULL;
534 xfs_agnumber_t agno;
535 xfs_agblock_t agbno;
536 bool has_other_rmap;
537 int error;
538
539 agno = XFS_FSB_TO_AGNO(sc->mp, fsbno);
540 agbno = XFS_FSB_TO_AGBNO(sc->mp, fsbno);
541
542
543
544
545
546
547 if (sc->ip) {
548 error = xfs_alloc_read_agf(sc->mp, sc->tp, agno, 0, &agf_bp);
549 if (error)
550 return error;
551 } else {
552 agf_bp = sc->sa.agf_bp;
553 }
554 cur = xfs_rmapbt_init_cursor(sc->mp, sc->tp, agf_bp, agno);
555
556
557 error = xfs_rmap_has_other_keys(cur, agbno, 1, oinfo, &has_other_rmap);
558 xfs_btree_del_cursor(cur, error);
559 if (error)
560 goto out_free;
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575 if (has_other_rmap)
576 error = xfs_rmap_free(sc->tp, agf_bp, agno, agbno, 1, oinfo);
577 else if (resv == XFS_AG_RESV_AGFL)
578 error = xrep_put_freelist(sc, agbno);
579 else
580 error = xfs_free_extent(sc->tp, fsbno, 1, oinfo, resv);
581 if (agf_bp != sc->sa.agf_bp)
582 xfs_trans_brelse(sc->tp, agf_bp);
583 if (error)
584 return error;
585
586 if (sc->ip)
587 return xfs_trans_roll_inode(&sc->tp, sc->ip);
588 return xrep_roll_ag_trans(sc);
589
590out_free:
591 if (agf_bp != sc->sa.agf_bp)
592 xfs_trans_brelse(sc->tp, agf_bp);
593 return error;
594}
595
596
597int
598xrep_reap_extents(
599 struct xfs_scrub *sc,
600 struct xbitmap *bitmap,
601 const struct xfs_owner_info *oinfo,
602 enum xfs_ag_resv_type type)
603{
604 struct xbitmap_range *bmr;
605 struct xbitmap_range *n;
606 xfs_fsblock_t fsbno;
607 int error = 0;
608
609 ASSERT(xfs_sb_version_hasrmapbt(&sc->mp->m_sb));
610
611 for_each_xbitmap_block(fsbno, bmr, n, bitmap) {
612 ASSERT(sc->ip != NULL ||
613 XFS_FSB_TO_AGNO(sc->mp, fsbno) == sc->sa.agno);
614 trace_xrep_dispose_btree_extent(sc->mp,
615 XFS_FSB_TO_AGNO(sc->mp, fsbno),
616 XFS_FSB_TO_AGBNO(sc->mp, fsbno), 1);
617
618 error = xrep_reap_block(sc, fsbno, oinfo, type);
619 if (error)
620 break;
621 }
622
623 return error;
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
653struct xrep_findroot {
654 struct xfs_scrub *sc;
655 struct xfs_buf *agfl_bp;
656 struct xfs_agf *agf;
657 struct xrep_find_ag_btree *btree_info;
658};
659
660
661STATIC int
662xrep_findroot_agfl_walk(
663 struct xfs_mount *mp,
664 xfs_agblock_t bno,
665 void *priv)
666{
667 xfs_agblock_t *agbno = priv;
668
669 return (*agbno == bno) ? -ECANCELED : 0;
670}
671
672
673STATIC int
674xrep_findroot_block(
675 struct xrep_findroot *ri,
676 struct xrep_find_ag_btree *fab,
677 uint64_t owner,
678 xfs_agblock_t agbno,
679 bool *done_with_block)
680{
681 struct xfs_mount *mp = ri->sc->mp;
682 struct xfs_buf *bp;
683 struct xfs_btree_block *btblock;
684 xfs_daddr_t daddr;
685 int block_level;
686 int error = 0;
687
688 daddr = XFS_AGB_TO_DADDR(mp, ri->sc->sa.agno, agbno);
689
690
691
692
693
694
695
696 if (owner == XFS_RMAP_OWN_AG) {
697 error = xfs_agfl_walk(mp, ri->agf, ri->agfl_bp,
698 xrep_findroot_agfl_walk, &agbno);
699 if (error == -ECANCELED)
700 return 0;
701 if (error)
702 return error;
703 }
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723 error = xfs_trans_read_buf(mp, ri->sc->tp, mp->m_ddev_targp, daddr,
724 mp->m_bsize, 0, &bp, NULL);
725 if (error)
726 return error;
727
728
729 btblock = XFS_BUF_TO_BLOCK(bp);
730 ASSERT(fab->buf_ops->magic[1] != 0);
731 if (btblock->bb_magic != fab->buf_ops->magic[1])
732 goto out;
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748 if (bp->b_ops) {
749 if (bp->b_ops != fab->buf_ops)
750 goto out;
751 } else {
752 ASSERT(!xfs_trans_buf_is_dirty(bp));
753 if (!uuid_equal(&btblock->bb_u.s.bb_uuid,
754 &mp->m_sb.sb_meta_uuid))
755 goto out;
756
757
758
759
760
761 bp->b_ops = fab->buf_ops;
762 fab->buf_ops->verify_read(bp);
763 if (bp->b_error) {
764 bp->b_ops = NULL;
765 bp->b_error = 0;
766 goto out;
767 }
768
769
770
771
772
773 }
774
775
776
777
778
779 *done_with_block = true;
780
781
782
783
784
785
786
787
788
789
790
791 block_level = xfs_btree_get_level(btblock);
792 if (block_level + 1 == fab->height) {
793 fab->root = NULLAGBLOCK;
794 goto out;
795 } else if (block_level < fab->height) {
796 goto out;
797 }
798
799
800
801
802
803
804 fab->height = block_level + 1;
805
806
807
808
809
810
811 if (btblock->bb_u.s.bb_leftsib == cpu_to_be32(NULLAGBLOCK) &&
812 btblock->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK))
813 fab->root = agbno;
814 else
815 fab->root = NULLAGBLOCK;
816
817 trace_xrep_findroot_block(mp, ri->sc->sa.agno, agbno,
818 be32_to_cpu(btblock->bb_magic), fab->height - 1);
819out:
820 xfs_trans_brelse(ri->sc->tp, bp);
821 return error;
822}
823
824
825
826
827
828STATIC int
829xrep_findroot_rmap(
830 struct xfs_btree_cur *cur,
831 struct xfs_rmap_irec *rec,
832 void *priv)
833{
834 struct xrep_findroot *ri = priv;
835 struct xrep_find_ag_btree *fab;
836 xfs_agblock_t b;
837 bool done;
838 int error = 0;
839
840
841 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner))
842 return 0;
843
844
845 for (b = 0; b < rec->rm_blockcount; b++) {
846 done = false;
847 for (fab = ri->btree_info; fab->buf_ops; fab++) {
848 if (rec->rm_owner != fab->rmap_owner)
849 continue;
850 error = xrep_findroot_block(ri, fab,
851 rec->rm_owner, rec->rm_startblock + b,
852 &done);
853 if (error)
854 return error;
855 if (done)
856 break;
857 }
858 }
859
860 return 0;
861}
862
863
864int
865xrep_find_ag_btree_roots(
866 struct xfs_scrub *sc,
867 struct xfs_buf *agf_bp,
868 struct xrep_find_ag_btree *btree_info,
869 struct xfs_buf *agfl_bp)
870{
871 struct xfs_mount *mp = sc->mp;
872 struct xrep_findroot ri;
873 struct xrep_find_ag_btree *fab;
874 struct xfs_btree_cur *cur;
875 int error;
876
877 ASSERT(xfs_buf_islocked(agf_bp));
878 ASSERT(agfl_bp == NULL || xfs_buf_islocked(agfl_bp));
879
880 ri.sc = sc;
881 ri.btree_info = btree_info;
882 ri.agf = agf_bp->b_addr;
883 ri.agfl_bp = agfl_bp;
884 for (fab = btree_info; fab->buf_ops; fab++) {
885 ASSERT(agfl_bp || fab->rmap_owner != XFS_RMAP_OWN_AG);
886 ASSERT(XFS_RMAP_NON_INODE_OWNER(fab->rmap_owner));
887 fab->root = NULLAGBLOCK;
888 fab->height = 0;
889 }
890
891 cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.agno);
892 error = xfs_rmap_query_all(cur, xrep_findroot_rmap, &ri);
893 xfs_btree_del_cursor(cur, error);
894
895 return error;
896}
897
898
899void
900xrep_force_quotacheck(
901 struct xfs_scrub *sc,
902 xfs_dqtype_t type)
903{
904 uint flag;
905
906 flag = xfs_quota_chkd_flag(type);
907 if (!(flag & sc->mp->m_qflags))
908 return;
909
910 sc->mp->m_qflags &= ~flag;
911 spin_lock(&sc->mp->m_sb_lock);
912 sc->mp->m_sb.sb_qflags &= ~flag;
913 spin_unlock(&sc->mp->m_sb_lock);
914 xfs_log_sb(sc->tp);
915}
916
917
918
919
920
921
922
923
924
925
926
927int
928xrep_ino_dqattach(
929 struct xfs_scrub *sc)
930{
931 int error;
932
933 error = xfs_qm_dqattach_locked(sc->ip, false);
934 switch (error) {
935 case -EFSBADCRC:
936 case -EFSCORRUPTED:
937 case -ENOENT:
938 xfs_err_ratelimited(sc->mp,
939"inode %llu repair encountered quota error %d, quotacheck forced.",
940 (unsigned long long)sc->ip->i_ino, error);
941 if (XFS_IS_UQUOTA_ON(sc->mp) && !sc->ip->i_udquot)
942 xrep_force_quotacheck(sc, XFS_DQTYPE_USER);
943 if (XFS_IS_GQUOTA_ON(sc->mp) && !sc->ip->i_gdquot)
944 xrep_force_quotacheck(sc, XFS_DQTYPE_GROUP);
945 if (XFS_IS_PQUOTA_ON(sc->mp) && !sc->ip->i_pdquot)
946 xrep_force_quotacheck(sc, XFS_DQTYPE_PROJ);
947
948 case -ESRCH:
949 error = 0;
950 break;
951 default:
952 break;
953 }
954
955 return error;
956}
957