xref: /illumos-gate/usr/src/cmd/fs.d/ufs/fsck/pass3.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
7*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
8*7c478bd9Sstevel@tonic-gate 
9*7c478bd9Sstevel@tonic-gate /*
10*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
11*7c478bd9Sstevel@tonic-gate  * All rights reserved.
12*7c478bd9Sstevel@tonic-gate  *
13*7c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms are permitted
14*7c478bd9Sstevel@tonic-gate  * provided that: (1) source distributions retain this entire copyright
15*7c478bd9Sstevel@tonic-gate  * notice and comment, and (2) distributions including binaries display
16*7c478bd9Sstevel@tonic-gate  * the following acknowledgement:  ``This product includes software
17*7c478bd9Sstevel@tonic-gate  * developed by the University of California, Berkeley and its contributors''
18*7c478bd9Sstevel@tonic-gate  * in the documentation or other materials provided with the distribution
19*7c478bd9Sstevel@tonic-gate  * and in all advertising materials mentioning features or use of this
20*7c478bd9Sstevel@tonic-gate  * software. Neither the name of the University nor the names of its
21*7c478bd9Sstevel@tonic-gate  * contributors may be used to endorse or promote products derived
22*7c478bd9Sstevel@tonic-gate  * from this software without specific prior written permission.
23*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24*7c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25*7c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26*7c478bd9Sstevel@tonic-gate  */
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #define	bcopy(f, t, n)    memcpy(t, f, n)
35*7c478bd9Sstevel@tonic-gate #define	bzero(s, n)	memset(s, 0, n)
36*7c478bd9Sstevel@tonic-gate #define	bcmp(s, d, n)	memcmp(s, d, n)
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate #define	index(s, r)	strchr(s, r)
39*7c478bd9Sstevel@tonic-gate #define	rindex(s, r)	strrchr(s, r)
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fs.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
44*7c478bd9Sstevel@tonic-gate #define	_KERNEL
45*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h>
46*7c478bd9Sstevel@tonic-gate #undef _KERNEL
47*7c478bd9Sstevel@tonic-gate #include "fsck.h"
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate int pass3check();
50*7c478bd9Sstevel@tonic-gate static void setcurino(struct inodesc *, struct dinode *, struct inoinfo *);
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate pass3()
53*7c478bd9Sstevel@tonic-gate {
54*7c478bd9Sstevel@tonic-gate 	struct inoinfo **inpp, *inp;
55*7c478bd9Sstevel@tonic-gate 	ino_t orphan;
56*7c478bd9Sstevel@tonic-gate 	int loopcnt;
57*7c478bd9Sstevel@tonic-gate 	ino_t inumber;
58*7c478bd9Sstevel@tonic-gate 	struct shadowclientinfo *sci;
59*7c478bd9Sstevel@tonic-gate 	struct inodesc curino;
60*7c478bd9Sstevel@tonic-gate 	struct dinode *dp;
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate 	for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) {
64*7c478bd9Sstevel@tonic-gate 		inp = *inpp;
65*7c478bd9Sstevel@tonic-gate 		if (inp->i_number == UFSROOTINO ||
66*7c478bd9Sstevel@tonic-gate 		    !(inp->i_parent == 0 || statemap[inp->i_number] == DSTATE))
67*7c478bd9Sstevel@tonic-gate 			continue;
68*7c478bd9Sstevel@tonic-gate 		if (statemap[inp->i_number] == DCLEAR ||
69*7c478bd9Sstevel@tonic-gate 		    statemap[inp->i_number] == USTATE)
70*7c478bd9Sstevel@tonic-gate 			continue;
71*7c478bd9Sstevel@tonic-gate 		for (loopcnt = 0; ; loopcnt++) {
72*7c478bd9Sstevel@tonic-gate 			orphan = inp->i_number;
73*7c478bd9Sstevel@tonic-gate 			if (inp->i_parent == 0 ||
74*7c478bd9Sstevel@tonic-gate 			    statemap[inp->i_parent] != DSTATE ||
75*7c478bd9Sstevel@tonic-gate 			    loopcnt > numdirs)
76*7c478bd9Sstevel@tonic-gate 				break;
77*7c478bd9Sstevel@tonic-gate 			inp = getinoinfo(inp->i_parent);
78*7c478bd9Sstevel@tonic-gate 		}
79*7c478bd9Sstevel@tonic-gate 		dp = ginode(orphan);
80*7c478bd9Sstevel@tonic-gate 		/*
81*7c478bd9Sstevel@tonic-gate 		 * A link count of 0 with parent and .. inodes of 0
82*7c478bd9Sstevel@tonic-gate 		 * indicates a partly deleted directory.
83*7c478bd9Sstevel@tonic-gate 		 * Clear it.
84*7c478bd9Sstevel@tonic-gate 		 */
85*7c478bd9Sstevel@tonic-gate 		if (dp->di_nlink == 0 && inp->i_dotdot == 0 &&
86*7c478bd9Sstevel@tonic-gate 		    inp->i_parent == 0) {
87*7c478bd9Sstevel@tonic-gate 			setcurino(&curino, dp, inp);
88*7c478bd9Sstevel@tonic-gate 			clri(&curino, "UNREF", 1);
89*7c478bd9Sstevel@tonic-gate 			continue;
90*7c478bd9Sstevel@tonic-gate 		}
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate 		if (linkup(orphan, inp->i_dotdot) == 1) {
93*7c478bd9Sstevel@tonic-gate 			if ((dp->di_mode & IFMT) == IFATTRDIR) {
94*7c478bd9Sstevel@tonic-gate 				dp->di_mode &= ~IFATTRDIR;
95*7c478bd9Sstevel@tonic-gate 				dp->di_mode |= IFDIR;
96*7c478bd9Sstevel@tonic-gate 				dp->di_cflags &= ~IXATTR;
97*7c478bd9Sstevel@tonic-gate 				dp->di_size = (u_offset_t)inp->i_isize;
98*7c478bd9Sstevel@tonic-gate 				setcurino(&curino, dp, inp);
99*7c478bd9Sstevel@tonic-gate 				(void) ckinode(dp, &curino);
100*7c478bd9Sstevel@tonic-gate 				inodirty();
101*7c478bd9Sstevel@tonic-gate 			}
102*7c478bd9Sstevel@tonic-gate 			inp->i_parent = inp->i_dotdot = lfdir;
103*7c478bd9Sstevel@tonic-gate 			lncntp[lfdir]--;
104*7c478bd9Sstevel@tonic-gate 			statemap[orphan] = DFOUND;
105*7c478bd9Sstevel@tonic-gate 			propagate();
106*7c478bd9Sstevel@tonic-gate 		}
107*7c478bd9Sstevel@tonic-gate 	}
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 	for (sci = shadowclientinfo; sci; sci = sci->next) {
110*7c478bd9Sstevel@tonic-gate 		lncntp[sci->shadow] -= sci->totalClients;
111*7c478bd9Sstevel@tonic-gate 	}
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 	for (sci = attrclientinfo; sci; sci = sci->next) {
114*7c478bd9Sstevel@tonic-gate 		lncntp[sci->shadow] -= sci->totalClients;
115*7c478bd9Sstevel@tonic-gate 	}
116*7c478bd9Sstevel@tonic-gate }
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate /*
120*7c478bd9Sstevel@tonic-gate  * This is used to verify the cflags of files
121*7c478bd9Sstevel@tonic-gate  * under a directory that used to be a attrdir.
122*7c478bd9Sstevel@tonic-gate  */
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate pass3check(idesc)
125*7c478bd9Sstevel@tonic-gate 	struct inodesc *idesc;
126*7c478bd9Sstevel@tonic-gate {
127*7c478bd9Sstevel@tonic-gate 	struct direct *dirp = idesc->id_dirp;
128*7c478bd9Sstevel@tonic-gate 	struct inoinfo *inp;
129*7c478bd9Sstevel@tonic-gate 	int n, entrysize, ret = 0;
130*7c478bd9Sstevel@tonic-gate 	struct dinode *dp, *pdirp;
131*7c478bd9Sstevel@tonic-gate 	int	isattr = 0;
132*7c478bd9Sstevel@tonic-gate 	int	dirtype = 0;
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 	if (dirp->d_ino == 0)
135*7c478bd9Sstevel@tonic-gate 		return (KEEPON);
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 	idesc->id_entryno++;
138*7c478bd9Sstevel@tonic-gate 	if ((strcmp(dirp->d_name, ".") == 0) ||
139*7c478bd9Sstevel@tonic-gate 	    (strcmp(dirp->d_name, "..") == 0)) {
140*7c478bd9Sstevel@tonic-gate 		return (KEEPON);
141*7c478bd9Sstevel@tonic-gate 	}
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	switch (statemap[dirp->d_ino]) {
145*7c478bd9Sstevel@tonic-gate 	case DSTATE:
146*7c478bd9Sstevel@tonic-gate 	case DFOUND:
147*7c478bd9Sstevel@tonic-gate 	case FSTATE:
148*7c478bd9Sstevel@tonic-gate 		/*
149*7c478bd9Sstevel@tonic-gate 		 * For extended attribute directories .. may point
150*7c478bd9Sstevel@tonic-gate 		 * to a file.  In this situation we don't want
151*7c478bd9Sstevel@tonic-gate 		 * to decrement link count as it was already
152*7c478bd9Sstevel@tonic-gate 		 * decremented when entry was seen and decremented
153*7c478bd9Sstevel@tonic-gate 		 * in the directory it actually lives in.
154*7c478bd9Sstevel@tonic-gate 		 */
155*7c478bd9Sstevel@tonic-gate 		dp = ginode(dirp->d_ino);
156*7c478bd9Sstevel@tonic-gate 		isattr = (dp->di_cflags & IXATTR);
157*7c478bd9Sstevel@tonic-gate 		pdirp = ginode(idesc->id_number);
158*7c478bd9Sstevel@tonic-gate 		dirtype = (pdirp->di_mode & IFMT);
159*7c478bd9Sstevel@tonic-gate 		n = 0;
160*7c478bd9Sstevel@tonic-gate 		if ((dirtype == IFDIR) && isattr) {
161*7c478bd9Sstevel@tonic-gate 			fileerror(idesc->id_number, dirp->d_ino,
162*7c478bd9Sstevel@tonic-gate 			    "File should NOT be marked as extended attribute");
163*7c478bd9Sstevel@tonic-gate 			dp = ginode(dirp->d_ino);
164*7c478bd9Sstevel@tonic-gate 			dp->di_cflags &= ~IXATTR;
165*7c478bd9Sstevel@tonic-gate 			if ((n = reply("FIX")) == 1) {
166*7c478bd9Sstevel@tonic-gate 				inodirty();
167*7c478bd9Sstevel@tonic-gate 			}
168*7c478bd9Sstevel@tonic-gate 			if (n != 0)
169*7c478bd9Sstevel@tonic-gate 				return (KEEPON | ALTERED);
170*7c478bd9Sstevel@tonic-gate 		}
171*7c478bd9Sstevel@tonic-gate 		break;
172*7c478bd9Sstevel@tonic-gate 	default:
173*7c478bd9Sstevel@tonic-gate 		errexit("PASS3: BAD STATE %d FOR INODE I=%d",
174*7c478bd9Sstevel@tonic-gate 		    statemap[dirp->d_ino], dirp->d_ino);
175*7c478bd9Sstevel@tonic-gate 	}
176*7c478bd9Sstevel@tonic-gate 	if (n == 0)
177*7c478bd9Sstevel@tonic-gate 		return (ret|KEEPON);
178*7c478bd9Sstevel@tonic-gate 	return (ret|KEEPON|ALTERED);
179*7c478bd9Sstevel@tonic-gate }
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate static void
182*7c478bd9Sstevel@tonic-gate setcurino(struct inodesc *ino, struct dinode *dp, struct inoinfo *inp)
183*7c478bd9Sstevel@tonic-gate {
184*7c478bd9Sstevel@tonic-gate 	bzero((char *)ino, sizeof (struct inodesc));
185*7c478bd9Sstevel@tonic-gate 	bcopy((char *)&inp->i_blks[0],
186*7c478bd9Sstevel@tonic-gate 	    (char *)&dp->di_db[0],
187*7c478bd9Sstevel@tonic-gate 	    (size_t)inp->i_numblks);
188*7c478bd9Sstevel@tonic-gate 	ino->id_number = inp->i_number;
189*7c478bd9Sstevel@tonic-gate 	ino->id_parent = inp->i_parent;
190*7c478bd9Sstevel@tonic-gate 	ino->id_fix = DONTKNOW;
191*7c478bd9Sstevel@tonic-gate 	ino->id_type = DATA;
192*7c478bd9Sstevel@tonic-gate 	ino->id_func = pass3check;
193*7c478bd9Sstevel@tonic-gate }
194