pass3.c revision 114589
11556Srgrimes/*
21556Srgrimes * Copyright (c) 1980, 1986, 1993
31556Srgrimes *	The Regents of the University of California.  All rights reserved.
41556Srgrimes *
51556Srgrimes * Redistribution and use in source and binary forms, with or without
61556Srgrimes * modification, are permitted provided that the following conditions
71556Srgrimes * are met:
81556Srgrimes * 1. Redistributions of source code must retain the above copyright
91556Srgrimes *    notice, this list of conditions and the following disclaimer.
101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111556Srgrimes *    notice, this list of conditions and the following disclaimer in the
121556Srgrimes *    documentation and/or other materials provided with the distribution.
131556Srgrimes * 3. All advertising materials mentioning features or use of this software
141556Srgrimes *    must display the following acknowledgement:
151556Srgrimes *	This product includes software developed by the University of
161556Srgrimes *	California, Berkeley and its contributors.
171556Srgrimes * 4. Neither the name of the University nor the names of its contributors
181556Srgrimes *    may be used to endorse or promote products derived from this software
191556Srgrimes *    without specific prior written permission.
201556Srgrimes *
211556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311556Srgrimes * SUCH DAMAGE.
321556Srgrimes */
331556Srgrimes
341556Srgrimes#if 0
351556Srgrimes#ifndef lint
361556Srgrimesstatic const char sccsid[] = "@(#)pass3.c	8.2 (Berkeley) 4/27/95";
371556Srgrimes#endif /* not lint */
3836150Scharnier#endif
3936150Scharnier#include <sys/cdefs.h>
4036150Scharnier__FBSDID("$FreeBSD: head/sbin/fsck_ffs/pass3.c 114589 2003-05-03 18:41:59Z obrien $");
4136150Scharnier
4236150Scharnier#include <sys/param.h>
431556Srgrimes
441556Srgrimes#include <ufs/ufs/dinode.h>
4517987Speter#include <ufs/ufs/dir.h>
4617987Speter#include <ufs/ffs/fs.h>
4717987Speter
4817987Speter#include <string.h>
4917987Speter
5017987Speter#include "fsck.h"
5117987Speter
5217987Spetervoid
5319281Sachepass3(void)
5417987Speter{
551556Srgrimes	struct inoinfo *inp;
561556Srgrimes	int loopcnt, inpindex, state;
571556Srgrimes	ino_t orphan;
581556Srgrimes	struct inodesc idesc;
591556Srgrimes	char namebuf[MAXNAMLEN+1];
601556Srgrimes
611556Srgrimes	for (inpindex = inplast - 1; inpindex >= 0; inpindex--) {
621556Srgrimes		if (got_siginfo) {
631556Srgrimes			printf("%s: phase 3: dir %d of %d (%d%%)\n", cdevname,
641556Srgrimes			    (int)(inplast - inpindex - 1), (int)inplast,
651556Srgrimes			    (int)((inplast - inpindex - 1) * 100 / inplast));
661556Srgrimes			got_siginfo = 0;
671556Srgrimes		}
681556Srgrimes		inp = inpsort[inpindex];
691556Srgrimes		state = inoinfo(inp->i_number)->ino_state;
701556Srgrimes		if (inp->i_number == ROOTINO ||
711556Srgrimes		    (inp->i_parent != 0 && state != DSTATE))
721556Srgrimes			continue;
731556Srgrimes		if (state == DCLEAR)
741556Srgrimes			continue;
7517987Speter		/*
7617987Speter		 * If we are running with soft updates and we come
771556Srgrimes		 * across unreferenced directories, we just leave
781556Srgrimes		 * them in DSTATE which will cause them to be pitched
791556Srgrimes		 * in pass 4.
801556Srgrimes		 */
811556Srgrimes		if ((preen || bkgrdflag) &&
821556Srgrimes		    resolved && usedsoftdep && state == DSTATE) {
831556Srgrimes			if (inp->i_dotdot >= ROOTINO)
841556Srgrimes				inoinfo(inp->i_dotdot)->ino_linkcnt++;
851556Srgrimes			continue;
861556Srgrimes		}
871556Srgrimes		for (loopcnt = 0; ; loopcnt++) {
881556Srgrimes			orphan = inp->i_number;
891556Srgrimes			if (inp->i_parent == 0 ||
901556Srgrimes			    inoinfo(inp->i_parent)->ino_state != DSTATE ||
911556Srgrimes			    loopcnt > countdirs)
921556Srgrimes				break;
931556Srgrimes			inp = getinoinfo(inp->i_parent);
941556Srgrimes		}
951556Srgrimes		if (loopcnt <= countdirs) {
961556Srgrimes			if (linkup(orphan, inp->i_dotdot, NULL)) {
9717987Speter				inp->i_parent = inp->i_dotdot = lfdir;
9817987Speter				inoinfo(lfdir)->ino_linkcnt--;
9917987Speter			}
10020425Ssteve			inoinfo(orphan)->ino_state = DFOUND;
10117987Speter			propagate();
10225233Ssteve			continue;
10318202Speter		}
10417987Speter		pfatal("ORPHANED DIRECTORY LOOP DETECTED I=%lu",
10517987Speter		    (u_long)orphan);
10617987Speter		if (reply("RECONNECT") == 0)
10717987Speter			continue;
10817987Speter		memset(&idesc, 0, sizeof(struct inodesc));
10917987Speter		idesc.id_type = DATA;
11017987Speter		idesc.id_number = inp->i_parent;
11117987Speter		idesc.id_parent = orphan;
11217987Speter		idesc.id_func = findname;
11319281Sache		idesc.id_name = namebuf;
1141556Srgrimes		if ((ckinode(ginode(inp->i_parent), &idesc) & FOUND) == 0)
11519281Sache			pfatal("COULD NOT FIND NAME IN PARENT DIRECTORY");
11619281Sache		if (linkup(orphan, inp->i_parent, namebuf)) {
11719281Sache			idesc.id_func = clearentry;
11819281Sache			if (ckinode(ginode(inp->i_parent), &idesc) & FOUND)
11919281Sache				inoinfo(orphan)->ino_linkcnt++;
12019281Sache			inp->i_parent = inp->i_dotdot = lfdir;
12119281Sache			inoinfo(lfdir)->ino_linkcnt--;
12219281Sache		}
12319281Sache		inoinfo(orphan)->ino_state = DFOUND;
12419281Sache		propagate();
12519281Sache	}
12619281Sache}
12719281Sache