Home | History | Annotate | Line # | Download | only in fsck_ffs
pass3.c revision 1.18
      1 /*	$NetBSD: pass3.c,v 1.18 2005/01/13 19:56:02 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1980, 1986, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #ifndef lint
     34 #if 0
     35 static char sccsid[] = "@(#)pass3.c	8.2 (Berkeley) 4/27/95";
     36 #else
     37 __RCSID("$NetBSD: pass3.c,v 1.18 2005/01/13 19:56:02 christos Exp $");
     38 #endif
     39 #endif /* not lint */
     40 
     41 #include <sys/param.h>
     42 #include <sys/time.h>
     43 #include <string.h>
     44 
     45 #include <ufs/ufs/dinode.h>
     46 #include <ufs/ffs/fs.h>
     47 
     48 #include <dirent.h>
     49 
     50 #include "fsck.h"
     51 #include "extern.h"
     52 #include "fsutil.h"
     53 
     54 void
     55 pass3(void)
     56 {
     57 	struct inoinfo *inp, **inpp;
     58 	int loopcnt, state;
     59 	ino_t orphan;
     60 	struct inodesc idesc;
     61 	char namebuf[MAXNAMLEN+1];
     62 
     63 	for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) {
     64 		int inpindex = inpp - inpsort;
     65 		if (got_siginfo) {
     66 			fprintf(stderr,
     67 			    "%s: phase 3: dir %d of %d (%d%%)\n", cdevname(),
     68 			    (int)(inplast - inpindex - 1), (int)inplast,
     69 			    (int)((inplast - inpindex - 1) * 100 / inplast));
     70 			got_siginfo = 0;
     71 		}
     72 #ifdef PROGRESS
     73 		progress_bar(cdevname(), preen ? NULL : "phase 3",
     74 			    inplast - inpindex - 1, inplast);
     75 #endif /* PROGRESS */
     76 		inp = *inpp;
     77 		state = inoinfo(inp->i_number)->ino_state;
     78 		if (inp->i_number == ROOTINO ||
     79 		    (inp->i_parent != 0 && state != DSTATE))
     80 			continue;
     81 		if (state == DCLEAR)
     82 			continue;
     83 		/*
     84 		 * If we are running with soft updates and we come
     85 		 * across unreferenced directories, we just leave
     86 		 * them in DSTATE which will cause them to be pitched
     87 		 * in pass 4.
     88 		 */
     89 		if (preen &&
     90 		    resolved && usedsoftdep && state == DSTATE) {
     91 			if (inp->i_dotdot >= ROOTINO)
     92 				inoinfo(inp->i_dotdot)->ino_linkcnt++;
     93 			continue;
     94 		}
     95 		for (loopcnt = 0; ; loopcnt++) {
     96 			orphan = inp->i_number;
     97 			if (inp->i_parent == 0 ||
     98 			    inoinfo(inp->i_parent)->ino_state != DSTATE ||
     99 			    loopcnt > countdirs)
    100 				break;
    101 			inp = getinoinfo(inp->i_parent);
    102 		}
    103 		if (loopcnt <= countdirs) {
    104 			if (linkup(orphan, inp->i_dotdot, NULL))
    105 				inoinfo(lfdir)->ino_linkcnt--;
    106 			continue;
    107 		}
    108 		pfatal("ORPHANED DIRECTORY LOOP DETECTED I=%lu",
    109 		    (u_long)orphan);
    110 		if (reply("RECONNECT") == 0)
    111 			continue;
    112 		memset(&idesc, 0, sizeof(struct inodesc));
    113 		idesc.id_type = DATA;
    114 		idesc.id_number = inp->i_parent;
    115 		idesc.id_parent = orphan;
    116 		idesc.id_func = findname;
    117 		idesc.id_name = namebuf;
    118 		if ((ckinode(ginode(inp->i_parent), &idesc) & FOUND) == 0)
    119 			pfatal("COULD NOT FIND NAME IN PARENT DIRECTORY");
    120 		if (linkup(orphan, inp->i_parent, namebuf)) {
    121 			idesc.id_func = clearentry;
    122 			if (ckinode(ginode(inp->i_parent), &idesc) & FOUND)
    123 				inoinfo(orphan)->ino_linkcnt++;
    124 			inoinfo(lfdir)->ino_linkcnt--;
    125 		}
    126 	}
    127 #ifdef PROGRESS
    128 	if (preen)
    129 		progress_add(inplast);
    130 	else
    131 		progress_done();
    132 #endif /* PROGRESS */
    133 }
    134