8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / fs.d / ufs / fsck / pass4.c
blobbb5015fb3227ce4be00d3140d61a622450ee6e07
1 /*
2 * Copyright 2006 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 <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/mntent.h>
36 #include <sys/fs/ufs_fs.h>
37 #include <sys/vnode.h>
38 #include <sys/fs/ufs_inode.h>
39 #include "fsck.h"
41 void
42 pass4(void)
44 fsck_ino_t inumber;
45 struct dinode *dp;
46 struct inodesc idesc;
47 int n, was_dir;
48 int need_rescan;
49 int scan_pass = 0;
52 * If we clear a directory, it may have produced orphans which
53 * we need to go pick up. So, do this until done. It can be
54 * proven that the loop terminates because at most there can
55 * be lastino directories, and we only rescan if we clear a
56 * directory.
58 do {
59 if (debug)
60 (void) printf("pass4 scan %d\n", scan_pass++);
62 need_rescan = 0;
63 for (inumber = UFSROOTINO; inumber <= lastino; inumber++) {
64 init_inodesc(&idesc);
65 idesc.id_type = ADDR;
66 idesc.id_func = pass4check;
67 idesc.id_number = inumber;
69 was_dir = (statemap[inumber] & DSTATE) == DSTATE;
71 switch (statemap[inumber] & ~(INORPHAN | INDELAYD
72 | INZLINK)) {
74 case FZLINK:
75 case DZLINK:
77 * INZLINK gets set if the inode claimed zero
78 * links when we first looked at it in pass 1.
79 * If lncntp[] also claims it has zero links,
80 * it really is unreferenced. However, we
81 * could have found a link to it during one of
82 * the other passes, so we have to check the
83 * final count in lncntp[].
85 if (lncntp[inumber] == 0) {
86 clri(&idesc, "UNREF", CLRI_VERBOSE,
87 CLRI_NOP_OK);
88 if (was_dir &&
89 (statemap[inumber] == USTATE))
90 need_rescan = 1;
91 break;
93 /* FALLTHROUGH */
95 case FSTATE:
96 case DFOUND:
97 case SSTATE:
98 n = lncntp[inumber];
99 if (n || (statemap[inumber] &
100 (INDELAYD | INZLINK))) {
102 * adjust() will clear the inode if
103 * the link count goes to zero. If
104 * it isn't cleared, we need to note
105 * that we've adjusted the count
106 * already, so we don't do it again
107 * on a rescan.
109 adjust(&idesc, n);
110 if (was_dir &&
111 (statemap[inumber] == USTATE)) {
112 need_rescan = 1;
113 } else {
114 TRACK_LNCNTP(inumber,
115 lncntp[inumber] = 0);
118 break;
120 case DSTATE:
121 clri(&idesc, "UNREF", CLRI_VERBOSE,
122 CLRI_NOP_OK);
123 if (was_dir && (statemap[inumber] == USTATE))
124 need_rescan = 1;
125 break;
127 case DCLEAR:
128 dp = ginode(inumber);
129 if (dp->di_size == 0) {
130 clri(&idesc, "ZERO LENGTH",
131 CLRI_VERBOSE, CLRI_NOP_CORRUPT);
132 break;
134 /* FALLTHROUGH */
136 case FCLEAR:
137 clri(&idesc, "BAD/DUP", CLRI_VERBOSE,
138 CLRI_NOP_CORRUPT);
139 break;
141 case SCLEAR:
142 clri(&idesc, "BAD", CLRI_VERBOSE,
143 CLRI_NOP_CORRUPT);
144 break;
146 case USTATE:
147 break;
149 default:
150 errexit("BAD STATE 0x%x FOR INODE I=%d",
151 (int)statemap[inumber], inumber);
154 } while (need_rescan);
158 pass4check(struct inodesc *idesc)
160 int fragnum, cg_frag;
161 int res = KEEPON;
162 daddr32_t blkno = idesc->id_blkno;
163 int cylno;
164 struct cg *cgp = &cgrp;
165 caddr_t err;
167 if ((idesc->id_truncto >= 0) && (idesc->id_lbn < idesc->id_truncto)) {
168 if (debug)
169 (void) printf(
170 "pass4check: skipping inode %d lbn %d with truncto %d\n",
171 idesc->id_number, idesc->id_lbn,
172 idesc->id_truncto);
173 return (KEEPON);
176 for (fragnum = 0; fragnum < idesc->id_numfrags; fragnum++) {
177 if (chkrange(blkno + fragnum, 1)) {
178 res = SKIP;
179 } else if (testbmap(blkno + fragnum)) {
181 * The block's in use. Remove our reference
182 * from it.
184 * If it wasn't a dup, or everybody's done with
185 * it, then this is the last reference and it's
186 * safe to actually deallocate the on-disk block.
188 * We depend on pass 5 resolving the on-disk bitmap
189 * effects.
191 cg_frag = blkno + fragnum;
192 if (!find_dup_ref(cg_frag, idesc->id_number,
193 idesc->id_lbn * sblock.fs_frag + fragnum,
194 DB_DECR)) {
196 if (debug)
197 (void) printf("p4c marking %d avail\n",
198 cg_frag);
199 clrbmap(cg_frag);
200 n_blks--;
203 * Do the same for the on-disk bitmap, so
204 * that we don't need another pass to figure
205 * out what's really being used. We'll let
206 * pass5() work out the fragment/block
207 * accounting.
209 cylno = dtog(&sblock, cg_frag);
210 (void) getblk(&cgblk, cgtod(&sblock, cylno),
211 (size_t)sblock.fs_cgsize);
212 err = cg_sanity(cgp, cylno);
213 if (err != NULL) {
214 pfatal("CG %d: %s\n", cylno, err);
215 free((void *)err);
216 if (reply("REPAIR") == 0)
217 errexit("Program terminated.");
218 fix_cg(cgp, cylno);
220 clrbit(cg_blksfree(cgp),
221 dtogd(&sblock, cg_frag));
222 cgdirty();
224 res |= ALTERED;
228 return (res);