]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/phase3.c
Update copyright dates
[thirdparty/xfsprogs-dev.git] / repair / phase3.c
1 /*
2 * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include <libxfs.h>
34 #include "avl.h"
35 #include "globals.h"
36 #include "agheader.h"
37 #include "incore.h"
38 #include "protos.h"
39 #include "err_protos.h"
40 #include "dinode.h"
41
42 /*
43 * walks an unlinked list, returns 1 on an error (bogus pointer) or
44 * I/O error
45 */
46 int
47 walk_unlinked_list(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agino_t start_ino)
48 {
49 xfs_buf_t *bp;
50 xfs_dinode_t *dip;
51 xfs_agino_t current_ino = start_ino;
52 xfs_agblock_t agbno;
53 int state;
54
55 while (current_ino != NULLAGINO) {
56 if (verify_aginum(mp, agno, current_ino))
57 return(1);
58 if ((bp = get_agino_buf(mp, agno, current_ino, &dip)) == NULL)
59 return(1);
60 /*
61 * if this looks like a decent inode, then continue
62 * following the unlinked pointers. If not, bail.
63 */
64 if (verify_dinode(mp, dip, agno, current_ino) == 0) {
65 /*
66 * check if the unlinked list points to an unknown
67 * inode. if so, put it on the uncertain inode list
68 * and set block map appropriately.
69 */
70 if (find_inode_rec(agno, current_ino) == NULL) {
71 add_aginode_uncertain(agno, current_ino, 1);
72 agbno = XFS_AGINO_TO_AGBNO(mp, current_ino);
73
74 switch (state = get_agbno_state(mp,
75 agno, agbno)) {
76 case XR_E_UNKNOWN:
77 case XR_E_FREE:
78 case XR_E_FREE1:
79 set_agbno_state(mp, agno, agbno,
80 XR_E_INO);
81 break;
82 case XR_E_BAD_STATE:
83 do_error(
84 "bad state in block map %d\n",
85 state);
86 abort();
87 break;
88 default:
89 /*
90 * the block looks like inodes
91 * so be conservative and try
92 * to scavenge what's in there.
93 * if what's there is completely
94 * bogus, it'll show up later
95 * and the inode will be trashed
96 * anyway, hopefully without
97 * losing too much other data
98 */
99 set_agbno_state(mp, agno, agbno,
100 XR_E_INO);
101 break;
102 }
103 }
104 current_ino = dip->di_next_unlinked;
105 } else {
106 current_ino = NULLAGINO;;
107 }
108 libxfs_putbuf(bp);
109 }
110
111 return(0);
112 }
113
114 void
115 process_agi_unlinked(xfs_mount_t *mp, xfs_agnumber_t agno)
116 {
117 xfs_agnumber_t i;
118 xfs_buf_t *bp;
119 xfs_agi_t *agip;
120 int err = 0;
121 int agi_dirty = 0;
122
123 bp = libxfs_readbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR),
124 mp->m_sb.sb_sectsize/BBSIZE, 0);
125 if (!bp) {
126 do_error("cannot read agi block %lld for ag %u\n",
127 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR), agno);
128 exit(1);
129 }
130
131 agip = XFS_BUF_TO_AGI(bp);
132
133 ASSERT(no_modify || INT_GET(agip->agi_seqno, ARCH_CONVERT) == agno);
134
135 for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
136 if (INT_GET(agip->agi_unlinked[i], ARCH_CONVERT) != NULLAGINO) {
137 err += walk_unlinked_list(mp, agno,
138 INT_GET(agip->agi_unlinked[i], ARCH_CONVERT));
139 /*
140 * clear the list
141 */
142 if (!no_modify) {
143 INT_SET(agip->agi_unlinked[i], ARCH_CONVERT, NULLAGINO);
144 agi_dirty = 1;
145 }
146 }
147 }
148
149 if (err)
150 do_warn("error following ag %d unlinked list\n", agno);
151
152 ASSERT(agi_dirty == 0 || (agi_dirty && !no_modify));
153
154 if (agi_dirty && !no_modify)
155 libxfs_writebuf(bp, 0);
156 else
157 libxfs_putbuf(bp);
158 }
159
160 void
161 phase3(xfs_mount_t *mp)
162 {
163 int i, j;
164
165 printf("Phase 3 - for each AG...\n");
166 if (!no_modify)
167 printf(" - scan and clear agi unlinked lists...\n");
168 else
169 printf(" - scan (but don't clear) agi unlinked lists...\n");
170
171 /*
172 * first, let's look at the possibly bogus inodes
173 */
174 for (i = 0; i < mp->m_sb.sb_agcount; i++) {
175 /*
176 * walk unlinked list to add more potential inodes to list
177 */
178 process_agi_unlinked(mp, i);
179 check_uncertain_aginodes(mp, i);
180 }
181
182 /* ok, now that the tree's ok, let's take a good look */
183
184 printf(
185 " - process known inodes and perform inode discovery...\n");
186
187 for (i = 0; i < mp->m_sb.sb_agcount; i++) {
188 do_log(" - agno = %d\n", i);
189 /*
190 * turn on directory processing (inode discovery) and
191 * attribute processing (extra_attr_check)
192 */
193 process_aginodes(mp, i, 1, 0, 1);
194 }
195
196 /*
197 * process newly discovered inode chunks
198 */
199 printf(" - process newly discovered inodes...\n");
200 do {
201 /*
202 * have to loop until no ag has any uncertain
203 * inodes
204 */
205 j = 0;
206 for (i = 0; i < mp->m_sb.sb_agcount; i++) {
207 j += process_uncertain_aginodes(mp, i);
208 #ifdef XR_INODE_TRACE
209 fprintf(stderr,
210 "\t\t phase 3 - process_uncertain_inodes returns %d\n", j);
211 #endif
212 }
213 } while (j != 0);
214 }
215