]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/phase3.c
xfs: create a helper to convert extlen to rtextlen
[thirdparty/xfsprogs-dev.git] / repair / phase3.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
2bd0ea18 2/*
da23017d
NS
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
2bd0ea18
NS
5 */
6
6b803e5a 7#include "libxfs.h"
1164bde5
DC
8#include "threads.h"
9#include "prefetch.h"
2bd0ea18
NS
10#include "avl.h"
11#include "globals.h"
12#include "agheader.h"
13#include "incore.h"
14#include "protos.h"
15#include "err_protos.h"
16#include "dinode.h"
06fbdda9 17#include "progress.h"
bd758142 18#include "bmap.h"
8100dd79 19#include "threads.h"
2bd0ea18 20
62b00e63
CH
21static void
22process_agi_unlinked(
23 struct xfs_mount *mp,
24 xfs_agnumber_t agno)
2bd0ea18 25{
62b00e63
CH
26 struct xfs_buf *bp;
27 struct xfs_agi *agip;
28 xfs_agnumber_t i;
29 int agi_dirty = 0;
31079e67 30 int error;
2bd0ea18 31
31079e67 32 error = -libxfs_buf_read(mp->m_dev,
9440d84d 33 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
31079e67
DW
34 mp->m_sb.sb_sectsize / BBSIZE, LIBXFS_READBUF_SALVAGE,
35 &bp, &xfs_agi_buf_ops);
36 if (error)
5d1b7f0f 37 do_error(_("cannot read agi block %" PRId64 " for ag %u\n"),
9440d84d 38 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), agno);
2bd0ea18 39
c99cea5c 40 agip = bp->b_addr;
2bd0ea18 41
62b00e63 42 ASSERT(be32_to_cpu(agip->agi_seqno) == agno);
2bd0ea18
NS
43
44 for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
62b00e63
CH
45 if (agip->agi_unlinked[i] != cpu_to_be32(NULLAGINO)) {
46 agip->agi_unlinked[i] = cpu_to_be32(NULLAGINO);
47 agi_dirty = 1;
2bd0ea18
NS
48 }
49 }
50
18b4f688 51 if (agi_dirty) {
f524ae04 52 libxfs_buf_mark_dirty(bp);
18b4f688
DW
53 libxfs_buf_relse(bp);
54 }
2bd0ea18 55 else
e02ba985 56 libxfs_buf_relse(bp);
2bd0ea18
NS
57}
58
2556c98b
BN
59static void
60process_ag_func(
62843f36 61 struct workqueue *wq,
2556c98b
BN
62 xfs_agnumber_t agno,
63 void *arg)
3b6ac903
MV
64{
65 /*
66 * turn on directory processing (inode discovery) and
67 * attribute processing (extra_attr_check)
68 */
2556c98b 69 wait_for_inode_prefetch(arg);
3b6ac903 70 do_log(_(" - agno = %d\n"), agno);
62843f36 71 process_aginodes(wq->wq_ctx, arg, agno, 1, 0, 1);
bd758142 72 blkmap_free_final();
2556c98b
BN
73 cleanup_inode_prefetch(arg);
74}
75
76static void
77process_ags(
78 xfs_mount_t *mp)
79{
1164bde5 80 do_inode_prefetch(mp, ag_stride, process_ag_func, false, false);
3b6ac903
MV
81}
82
8100dd79
DC
83static void
84do_uncertain_aginodes(
62843f36
DW
85 struct workqueue *wq,
86 xfs_agnumber_t agno,
87 void *arg)
8100dd79 88{
62843f36 89 int *count = arg;
8100dd79 90
62843f36 91 *count = process_uncertain_aginodes(wq->wq_ctx, agno);
8100dd79
DC
92
93#ifdef XR_INODE_TRACE
94 fprintf(stderr,
95 "\t\t phase 3 - ag %d process_uncertain_inodes returns %d\n",
96 *count, j);
97#endif
98
99 PROG_RPT_INC(prog_rpt_done[agno], 1);
100}
101
2bd0ea18 102void
8100dd79
DC
103phase3(
104 struct xfs_mount *mp,
105 int scan_threads)
2bd0ea18 106{
8100dd79
DC
107 int i, j;
108 int *counts;
62843f36 109 struct workqueue wq;
2bd0ea18 110
507f4e33 111 do_log(_("Phase 3 - for each AG...\n"));
2bd0ea18 112 if (!no_modify)
507f4e33 113 do_log(_(" - scan and clear agi unlinked lists...\n"));
2bd0ea18 114 else
507f4e33 115 do_log(_(" - scan (but don't clear) agi unlinked lists...\n"));
2bd0ea18 116
14f8b681 117 set_progress_msg(PROG_FMT_AGI_UNLINKED, (uint64_t) glob_agcount);
06fbdda9 118
62b00e63
CH
119 /* first clear the agi unlinked AGI list */
120 if (!no_modify) {
121 for (i = 0; i < mp->m_sb.sb_agcount; i++)
122 process_agi_unlinked(mp, i);
123 }
124
125 /* now look at possibly bogus inodes */
2bd0ea18 126 for (i = 0; i < mp->m_sb.sb_agcount; i++) {
2bd0ea18 127 check_uncertain_aginodes(mp, i);
06fbdda9 128 PROG_RPT_INC(prog_rpt_done[i], 1);
2bd0ea18 129 }
06fbdda9 130 print_final_rpt();
2bd0ea18
NS
131
132 /* ok, now that the tree's ok, let's take a good look */
133
507f4e33
NS
134 do_log(_(
135 " - process known inodes and perform inode discovery...\n"));
2bd0ea18 136
14f8b681 137 set_progress_msg(PROG_FMT_PROCESS_INO, (uint64_t) mp->m_sb.sb_icount);
2556c98b
BN
138
139 process_ags(mp);
140
06fbdda9 141 print_final_rpt();
2bd0ea18
NS
142
143 /*
144 * process newly discovered inode chunks
145 */
507f4e33 146 do_log(_(" - process newly discovered inodes...\n"));
14f8b681 147 set_progress_msg(PROG_FMT_NEW_INODES, (uint64_t) glob_agcount);
8100dd79
DC
148
149 counts = calloc(sizeof(*counts), mp->m_sb.sb_agcount);
150 if (!counts) {
151 do_abort(_("no memory for uncertain inode counts\n"));
152 return;
153 }
154
2bd0ea18
NS
155 do {
156 /*
157 * have to loop until no ag has any uncertain
158 * inodes
159 */
160 j = 0;
8100dd79
DC
161 memset(counts, 0, mp->m_sb.sb_agcount * sizeof(*counts));
162
163 create_work_queue(&wq, mp, scan_threads);
164
165 for (i = 0; i < mp->m_sb.sb_agcount; i++)
166 queue_work(&wq, do_uncertain_aginodes, i, &counts[i]);
167
168 destroy_work_queue(&wq);
169
170 /* tally up the counts */
171 for (i = 0; i < mp->m_sb.sb_agcount; i++)
172 j += counts[i];
173
2bd0ea18 174 } while (j != 0);
8100dd79
DC
175
176 free(counts);
177
06fbdda9 178 print_final_rpt();
2bd0ea18 179}