8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / fs.d / ufs / fsck / pass3.c
blobf0a9a693e9b9b97ab73391302978b837122defa6
1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
9 /*
10 * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
11 * All rights reserved.
13 * Redistribution and use in source and binary forms are permitted
14 * provided that: (1) source distributions retain this entire copyright
15 * notice and comment, and (2) distributions including binaries display
16 * the following acknowledgement: ``This product includes software
17 * developed by the University of California, Berkeley and its contributors''
18 * in the documentation or other materials provided with the distribution
19 * and in all advertising materials mentioning features or use of this
20 * software. Neither the name of the University nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/mntent.h>
37 #include <sys/fs/ufs_fs.h>
38 #include <sys/vnode.h>
39 #include <sys/fs/ufs_inode.h>
40 #define _KERNEL
41 #include <sys/fs/ufs_fsdir.h>
42 #undef _KERNEL
43 #include "fsck.h"
45 static int pass3acheck(struct inodesc *);
46 static void setcurino(struct inodesc *, struct dinode *, struct inoinfo *);
48 void
49 pass3a(void)
51 caddr_t flow;
52 struct inoinfo **inpp, *inp;
53 fsck_ino_t orphan;
54 int loopcnt;
55 int state;
56 struct shadowclientinfo *sci, *sci_victim, *sci_prev, **sci_rootp;
57 struct inodesc curino;
58 struct dinode *dp;
59 struct inodesc idesc;
60 char namebuf[MAXNAMLEN + 1];
62 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) {
63 inp = *inpp;
64 state = statemap[inp->i_number];
65 if (inp->i_number == UFSROOTINO ||
66 (inp->i_parent != 0 && !S_IS_DUNFOUND(state)))
67 continue;
68 if (state == DCLEAR || state == USTATE || (state & INORPHAN))
69 continue;
71 * If we are running with logging and we come
72 * across unreferenced directories, we just leave
73 * them in DSTATE which will cause them to be pitched
74 * in pass 4.
76 if (preen && !iscorrupt && islog && S_IS_DUNFOUND(state)) {
77 if (inp->i_dotdot >= UFSROOTINO) {
78 LINK_RANGE(flow, lncntp[inp->i_dotdot], 1);
79 if (flow != NULL) {
80 dp = ginode(inp->i_dotdot);
81 LINK_CLEAR(flow, inp->i_dotdot,
82 dp->di_mode, &idesc);
83 if (statemap[inp->i_dotdot] == USTATE)
84 continue;
86 TRACK_LNCNTP(inp->i_dotdot,
87 lncntp[inp->i_dotdot]++);
89 continue;
92 for (loopcnt = 0; ; loopcnt++) {
93 orphan = inp->i_number;
95 * Skip out if we aren't connected to the name
96 * space, or our parent is connected, or we've
97 * looked at too many directories. Our parent
98 * being connected means that orphan is the
99 * first ancestor of *inpp with questionable
100 * antecedents.
102 if (inp->i_parent == 0 ||
103 !INO_IS_DUNFOUND(inp->i_parent) ||
104 loopcnt > numdirs)
105 break;
106 inp = getinoinfo(inp->i_parent);
108 * Can't happen, because a non-zero parent's already
109 * been seen and therefore cached.
111 if (inp == NULL)
112 errexit("pass3 could not find cached "
113 "inode I=%d\n",
114 inp->i_parent);
118 * Already did this one. Don't bother the user
119 * with redundant questions.
121 if (statemap[orphan] & INORPHAN)
122 continue;
125 * A link count of 0 with parent and .. inodes of 0
126 * indicates a partly deleted directory.
127 * Clear it.
129 dp = ginode(orphan);
130 if (dp->di_nlink == 0 && inp->i_dotdot == 0 &&
131 inp->i_parent == 0) {
133 * clri() just uses curino.id_number; in other
134 * words, it won't use the callback that setcurino()
135 * puts in.
137 setcurino(&curino, dp, inp);
138 clri(&curino, "UNREF", CLRI_VERBOSE, CLRI_NOP_OK);
141 * If we didn't clear it, at least mark it so
142 * we don't waste time on it again.
144 if (statemap[orphan] != USTATE) {
145 statemap[orphan] |= INORPHAN;
147 continue;
151 * We can call linkup() multiple times on the same directory
152 * inode, if we were told not to reconnect it the first time.
153 * This is because we find it as a disconnected parent of
154 * of its children (and mark it found), and then finally get
155 * to it in the inpsort array. This is better than in the
156 * past, where we'd call it every time we found it as a
157 * child's parent. Ideally, we'd suppress even the second
158 * query, but that confuses pass 4's interpretation of
159 * the state flags.
161 if (loopcnt <= countdirs) {
162 if (linkup(orphan, inp->i_dotdot, NULL)) {
164 * Bookkeeping for any sort of relinked
165 * directory.
167 inp->i_dotdot = lfdir;
168 inp->i_parent = inp->i_dotdot;
169 statemap[orphan] &= ~(INORPHAN);
170 } else {
171 statemap[orphan] |= INORPHAN;
173 propagate();
174 continue;
178 * We visited more directories than exist in the
179 * filesystem. The only way to do that is if there's
180 * a loop.
182 pfatal("ORPHANED DIRECTORY LOOP DETECTED I=%d\n", orphan);
185 * Can never get here with inp->i_parent zero, because
186 * of the interactions between the for() and the
187 * if (loopcnt <= countdirs) above.
189 init_inodesc(&idesc);
190 idesc.id_type = DATA;
191 idesc.id_number = inp->i_parent;
192 idesc.id_parent = orphan;
193 idesc.id_func = findname;
194 idesc.id_name = namebuf;
195 namebuf[0] = '\0';
198 * Theoretically, this lookup via ckinode can't fail
199 * (if orphan doesn't exist in i_parent, then i_parent
200 * would not have been filled in by pass2check()).
201 * However, if we're interactive, we want to at least
202 * attempt to continue. The worst case is that it
203 * gets reconnected as #nnn into lost+found instead of
204 * to its old parent with its old name.
206 if ((ckinode(ginode(inp->i_parent),
207 &idesc, CKI_TRAVERSE) & FOUND) == 0)
208 pfatal("COULD NOT FIND NAME IN PARENT DIRECTORY");
210 if (linkup(orphan, inp->i_parent, namebuf)) {
211 if (cleardirentry(inp->i_parent, orphan) & FOUND) {
212 LFDIR_LINK_RANGE_NORVAL(flow, lncntp[lfdir], 1,
213 &idesc);
214 TRACK_LNCNTP(orphan, lncntp[orphan]++);
216 inp->i_parent = inp->i_dotdot = lfdir;
217 LFDIR_LINK_RANGE_NORVAL(flow, lncntp[lfdir], -1,
218 &idesc);
219 TRACK_LNCNTP(lfdir, lncntp[lfdir]--);
220 statemap[orphan] = DFOUND;
221 } else {
223 * Represents a on-disk leak, not an inconsistency,
224 * so don't set iscorrupt. Such leaks are harmless
225 * in the context of discrepancies that the kernel
226 * will panic over.
228 * We don't care if tsearch() returns non-NULL
229 * != orphan, since there's no dynamic memory
230 * to free here.
232 if (tsearch((void *)orphan, &limbo_dirs,
233 ino_t_cmp) == NULL)
234 errexit("out of memory");
235 statemap[orphan] |= INORPHAN;
236 continue;
238 propagate();
242 * The essence of the inner loop is to update the inode of
243 * every shadow or attribute inode's lncntp[] by the number of
244 * links we've found to them in pass 2 and above. Logically,
245 * all that is needed is just the one line:
247 * lncntp[sci->shadow] -= sci->totalclients;
249 * However, there's the possibility of wrapping the link count
250 * (this is especially true for shadows, which are expected to
251 * be shared amongst many files). This means that we have to
252 * range-check before changing anything, and if the check
253 * fails, offer to clear the shadow or attribute. If we do
254 * clear it, then we have to remove it from the linked list of
255 * all of the type of inodes that we're going through.
257 * Just to make things a little more complicated, these are
258 * singly-linked lists, so we have to do all the extra
259 * bookkeeping that goes along with that as well.
261 * The only connection between the shadowclientinfo and
262 * attrclientinfo lists is that they use the same underlying
263 * struct. Both need this scan, so the outer loop is just to
264 * pick which one we're working on at the moment. There is no
265 * requirement as to which of these lists is scanned first.
267 for (loopcnt = 0; loopcnt < 2; loopcnt++) {
268 if (loopcnt == 0)
269 sci_rootp = &shadowclientinfo;
270 else
271 sci_rootp = &attrclientinfo;
273 sci = *sci_rootp;
274 sci_prev = NULL;
275 while (sci != NULL) {
276 sci_victim = NULL;
277 LINK_RANGE(flow, lncntp[sci->shadow],
278 -(sci->totalClients));
279 if (flow != NULL) {
281 * Overflowed the link count.
283 dp = ginode(sci->shadow);
284 LINK_CLEAR(flow, sci->shadow, dp->di_mode,
285 &idesc);
286 if (statemap[sci->shadow] == USTATE) {
288 * It's been cleared, fix the
289 * lists.
291 if (sci_prev == NULL) {
292 *sci_rootp = sci->next;
293 } else {
294 sci_prev->next = sci->next;
296 sci_victim = sci;
301 * If we did not clear the shadow, then we
302 * need to update the count and advance the
303 * previous pointer. Otherwise, finish the
304 * clean up once we're done with the struct.
306 if (sci_victim == NULL) {
307 TRACK_LNCNTP(sci->shadow,
308 lncntp[sci->shadow] -= sci->totalClients);
309 sci_prev = sci;
311 sci = sci->next;
312 if (sci_victim != NULL)
313 deshadow(sci_victim, NULL);
320 * This is used to verify the cflags of files
321 * under a directory that used to be an attrdir.
324 static int
325 pass3acheck(struct inodesc *idesc)
327 struct direct *dirp = idesc->id_dirp;
328 int n = 0, ret = 0;
329 struct dinode *dp, *pdirp;
330 int isattr;
331 int dirtype;
332 int inotype;
334 if (dirp->d_ino == 0)
335 return (KEEPON);
337 idesc->id_entryno++;
338 if ((strcmp(dirp->d_name, ".") == 0) ||
339 (strcmp(dirp->d_name, "..") == 0)) {
340 return (KEEPON);
343 switch (statemap[dirp->d_ino] & ~(INDELAYD)) {
344 case DSTATE:
345 case DFOUND:
346 case FSTATE:
348 * Accept DSTATE and DFOUND so we can handle normal
349 * directories as well as xattr directories.
351 * For extended attribute directories .. may point
352 * to a file. In this situation we don't want
353 * to decrement link count as it was already
354 * decremented when the entry was seen and decremented
355 * in the directory it actually lives in.
357 dp = ginode(dirp->d_ino);
358 isattr = (dp->di_cflags & IXATTR);
359 inotype = (dp->di_mode & IFMT);
360 pdirp = ginode(idesc->id_number);
361 dirtype = (pdirp->di_mode & IFMT);
363 * IXATTR indicates that an object is itself an extended
364 * attribute. An IFMT of IFATTRDIR means we are looking
365 * at a directory which contains files which should all
366 * have IXATTR set. The IFATTRDIR case was handled in
367 * pass 2b.
369 * Note that the following code actually handles
370 * anything that's marked as an extended attribute but
371 * in a regular directory, not just files.
373 if ((dirtype == IFDIR) && isattr) {
374 fileerror(idesc->id_number, dirp->d_ino,
375 "%s I=%d should NOT be marked as extended attribute\n",
376 (inotype == IFDIR) ? "Directory" : "File",
377 dirp->d_ino);
378 dp = ginode(dirp->d_ino);
379 dp->di_cflags &= ~IXATTR;
380 if ((n = reply("FIX")) == 1) {
381 inodirty();
382 } else {
383 iscorrupt = 1;
385 if (n != 0)
386 return (KEEPON | ALTERED);
388 break;
389 default:
390 errexit("PASS3: BAD STATE %d FOR INODE I=%d",
391 statemap[dirp->d_ino], dirp->d_ino);
392 /* NOTREACHED */
394 if (n == 0)
395 return (ret|KEEPON);
396 return (ret|KEEPON|ALTERED);
399 static void
400 setcurino(struct inodesc *idesc, struct dinode *dp, struct inoinfo *inp)
402 (void) memmove((void *)&dp->di_db[0], (void *)&inp->i_blks[0],
403 inp->i_blkssize);
405 init_inodesc(idesc);
406 idesc->id_number = inp->i_number;
407 idesc->id_parent = inp->i_parent;
408 idesc->id_fix = DONTKNOW;
409 idesc->id_type = DATA;
410 idesc->id_func = pass3acheck;
413 void
414 maybe_convert_attrdir_to_dir(fsck_ino_t orphan)
416 struct dinode *dp = ginode(orphan);
417 struct inoinfo *inp = getinoinfo(orphan);
418 struct inodesc idesc;
420 if (dp->di_cflags & IXATTR) {
421 dp->di_cflags &= ~IXATTR;
422 inodirty();
425 if ((dp->di_mode & IFMT) == IFATTRDIR) {
426 dp->di_mode &= ~IFATTRDIR;
427 dp->di_mode |= IFDIR;
428 inodirty();
430 setcurino(&idesc, dp, inp);
431 idesc.id_fix = FIX;
432 idesc.id_filesize = dp->di_size;
433 (void) ckinode(dp, &idesc, CKI_TRAVERSE);