]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/phase3.c
Merge branch 'libxfs-4.13-sync' into for-next
[thirdparty/xfsprogs-dev.git] / repair / phase3.c
1 /*
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "libxfs.h"
20 #include "threads.h"
21 #include "prefetch.h"
22 #include "avl.h"
23 #include "globals.h"
24 #include "agheader.h"
25 #include "incore.h"
26 #include "protos.h"
27 #include "err_protos.h"
28 #include "dinode.h"
29 #include "progress.h"
30 #include "bmap.h"
31 #include "threads.h"
32
33 static void
34 process_agi_unlinked(
35 struct xfs_mount *mp,
36 xfs_agnumber_t agno)
37 {
38 struct xfs_buf *bp;
39 struct xfs_agi *agip;
40 xfs_agnumber_t i;
41 int agi_dirty = 0;
42
43 bp = libxfs_readbuf(mp->m_dev,
44 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
45 mp->m_sb.sb_sectsize/BBSIZE, 0, &xfs_agi_buf_ops);
46 if (!bp)
47 do_error(_("cannot read agi block %" PRId64 " for ag %u\n"),
48 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), agno);
49
50 agip = XFS_BUF_TO_AGI(bp);
51
52 ASSERT(be32_to_cpu(agip->agi_seqno) == agno);
53
54 for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
55 if (agip->agi_unlinked[i] != cpu_to_be32(NULLAGINO)) {
56 agip->agi_unlinked[i] = cpu_to_be32(NULLAGINO);
57 agi_dirty = 1;
58 }
59 }
60
61 if (agi_dirty)
62 libxfs_writebuf(bp, 0);
63 else
64 libxfs_putbuf(bp);
65 }
66
67 static void
68 process_ag_func(
69 work_queue_t *wq,
70 xfs_agnumber_t agno,
71 void *arg)
72 {
73 /*
74 * turn on directory processing (inode discovery) and
75 * attribute processing (extra_attr_check)
76 */
77 wait_for_inode_prefetch(arg);
78 do_log(_(" - agno = %d\n"), agno);
79 process_aginodes(wq->mp, arg, agno, 1, 0, 1);
80 blkmap_free_final();
81 cleanup_inode_prefetch(arg);
82 }
83
84 static void
85 process_ags(
86 xfs_mount_t *mp)
87 {
88 do_inode_prefetch(mp, ag_stride, process_ag_func, false, false);
89 }
90
91 static void
92 do_uncertain_aginodes(
93 work_queue_t *wq,
94 xfs_agnumber_t agno,
95 void *arg)
96 {
97 int *count = arg;
98
99 *count = process_uncertain_aginodes(wq->mp, agno);
100
101 #ifdef XR_INODE_TRACE
102 fprintf(stderr,
103 "\t\t phase 3 - ag %d process_uncertain_inodes returns %d\n",
104 *count, j);
105 #endif
106
107 PROG_RPT_INC(prog_rpt_done[agno], 1);
108 }
109
110 void
111 phase3(
112 struct xfs_mount *mp,
113 int scan_threads)
114 {
115 int i, j;
116 int *counts;
117 work_queue_t wq;
118
119 do_log(_("Phase 3 - for each AG...\n"));
120 if (!no_modify)
121 do_log(_(" - scan and clear agi unlinked lists...\n"));
122 else
123 do_log(_(" - scan (but don't clear) agi unlinked lists...\n"));
124
125 set_progress_msg(PROG_FMT_AGI_UNLINKED, (uint64_t) glob_agcount);
126
127 /* first clear the agi unlinked AGI list */
128 if (!no_modify) {
129 for (i = 0; i < mp->m_sb.sb_agcount; i++)
130 process_agi_unlinked(mp, i);
131 }
132
133 /* now look at possibly bogus inodes */
134 for (i = 0; i < mp->m_sb.sb_agcount; i++) {
135 check_uncertain_aginodes(mp, i);
136 PROG_RPT_INC(prog_rpt_done[i], 1);
137 }
138 print_final_rpt();
139
140 /* ok, now that the tree's ok, let's take a good look */
141
142 do_log(_(
143 " - process known inodes and perform inode discovery...\n"));
144
145 set_progress_msg(PROG_FMT_PROCESS_INO, (uint64_t) mp->m_sb.sb_icount);
146
147 process_ags(mp);
148
149 print_final_rpt();
150
151 /*
152 * process newly discovered inode chunks
153 */
154 do_log(_(" - process newly discovered inodes...\n"));
155 set_progress_msg(PROG_FMT_NEW_INODES, (uint64_t) glob_agcount);
156
157 counts = calloc(sizeof(*counts), mp->m_sb.sb_agcount);
158 if (!counts) {
159 do_abort(_("no memory for uncertain inode counts\n"));
160 return;
161 }
162
163 do {
164 /*
165 * have to loop until no ag has any uncertain
166 * inodes
167 */
168 j = 0;
169 memset(counts, 0, mp->m_sb.sb_agcount * sizeof(*counts));
170
171 create_work_queue(&wq, mp, scan_threads);
172
173 for (i = 0; i < mp->m_sb.sb_agcount; i++)
174 queue_work(&wq, do_uncertain_aginodes, i, &counts[i]);
175
176 destroy_work_queue(&wq);
177
178 /* tally up the counts */
179 for (i = 0; i < mp->m_sb.sb_agcount; i++)
180 j += counts[i];
181
182 } while (j != 0);
183
184 free(counts);
185
186 print_final_rpt();
187 }