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