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