pass4.c revision 1.29 1 /* $NetBSD: pass4.c,v 1.29 2023/01/07 19:41:29 chs 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[] = "@(#)pass4.c 8.4 (Berkeley) 4/28/95";
36 #else
37 __RCSID("$NetBSD: pass4.c,v 1.29 2023/01/07 19:41:29 chs Exp $");
38 #endif
39 #endif /* not lint */
40
41 #include <sys/param.h>
42 #include <sys/time.h>
43 #include <sys/stat.h>
44
45 #include <ufs/ufs/ufs_bswap.h>
46 #include <ufs/ufs/dinode.h>
47 #include <ufs/ffs/fs.h>
48 #include <ufs/ffs/ffs_extern.h>
49
50 #include <err.h>
51 #include <stdlib.h>
52 #include <string.h>
53
54 #include "fsutil.h"
55 #include "fsck.h"
56 #include "extern.h"
57
58 void
59 pass4(void)
60 {
61 ino_t inumber;
62 struct zlncnt *zlnp;
63 union dinode *dp;
64 struct inodesc idesc;
65 int n, i;
66 uint32_t cg;
67 struct inostat *info;
68
69 memset(&idesc, 0, sizeof(struct inodesc));
70 idesc.id_func = pass4check;
71
72 for (cg = 0; cg < sblock->fs_ncg; cg++) {
73 if (got_siginfo) {
74 fprintf(stderr,
75 "%s: phase 4: cyl group %d of %d (%d%%)\n",
76 cdevname(), cg, sblock->fs_ncg,
77 cg * 100 / sblock->fs_ncg);
78 got_siginfo = 0;
79 }
80 #ifdef PROGRESS
81 progress_bar(cdevname(), preen ? NULL : "phase 4",
82 cg, sblock->fs_ncg);
83 #endif /* PROGRESS */
84 inumber = cg * sblock->fs_ipg;
85 for (i = 0; i < inostathead[cg].il_numalloced; i++, inumber++) {
86 if (inumber < UFS_ROOTINO)
87 continue;
88 dp = ginode(inumber);
89 info = inoinfo(inumber);
90 idesc.id_number = inumber;
91 idesc.id_uid = iswap32(DIP(dp, uid));
92 idesc.id_gid = iswap32(DIP(dp, gid));
93 if (iswap32(DIP(dp, flags)) & SF_SNAPSHOT)
94 idesc.id_type = SNAP;
95 else
96 idesc.id_type = ADDR;
97 switch (info->ino_state) {
98 case FSTATE:
99 case DFOUND:
100 n = info->ino_linkcnt;
101 if (n) {
102 if (is_journal_inode(inumber)) {
103 if (debug)
104 printf(
105 "skipping unreferenced journal inode %" PRId64 "\n", inumber);
106 break;
107 } else if (is_quota_inode(inumber)) {
108 if (debug)
109 printf(
110 "skipping unreferenced quota inode %" PRId64 "\n", inumber);
111 break;
112 } else {
113 adjust(&idesc, (short)n);
114 }
115 break;
116 }
117 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
118 if (zlnp->zlncnt == inumber) {
119 zlnp->zlncnt = zlnhead->zlncnt;
120 zlnp = zlnhead;
121 zlnhead = zlnhead->next;
122 free((char *)zlnp);
123 clri(&idesc, "UNREF", 1);
124 break;
125 }
126 break;
127
128 case DSTATE:
129 clri(&idesc, "UNREF", 1);
130 break;
131
132 case DCLEAR:
133 if (DIP(dp, size) == 0) {
134 clri(&idesc, "ZERO LENGTH", 1);
135 break;
136 }
137 /* fall through */
138 case FCLEAR:
139 clri(&idesc, "BAD/DUP", 1);
140 break;
141
142 case USTATE:
143 break;
144
145 default:
146 errexit("BAD STATE %d FOR INODE I=%llu",
147 info->ino_state,
148 (unsigned long long)inumber);
149 }
150 }
151 }
152 #ifdef PROGRESS
153 if (!preen)
154 progress_done();
155 #endif /* PROGRESS */
156 }
157
158 int
159 pass4check(struct inodesc *idesc)
160 {
161 struct dups *dlp;
162 int cg, nfrags, res = KEEPON;
163 daddr_t blkno = idesc->id_blkno;
164 struct cg *cgp = cgrp;
165
166 cg = dtog(sblock, blkno);
167 getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize);
168 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize);
169 if ((doswap && !needswap) || (!doswap && needswap))
170 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock);
171 if (!cg_chkmagic(cgp, 0)) {
172 pwarn("CG %d: ALLOCBLK: BAD MAGIC NUMBER\n", cg);
173 cgp = NULL;
174 }
175
176 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
177 if (chkrange(blkno, 1)) {
178 res = SKIP;
179 } else if (testbmap(blkno)) {
180 for (dlp = duplist; dlp; dlp = dlp->next) {
181 if (dlp->dup != blkno)
182 continue;
183 dlp->dup = duplist->dup;
184 dlp = duplist;
185 duplist = duplist->next;
186 free((char *)dlp);
187 break;
188 }
189 if (dlp == 0) {
190 clrbmap(blkno);
191 if (cgp)
192 setbit(cg_blksfree(cgp, 0),
193 dtogd(sblock, blkno));
194
195 n_blks--;
196 if (idesc->id_type != SNAP) {
197 update_uquot(idesc->id_number,
198 idesc->id_uid, idesc->id_gid,
199 -btodb(sblock->fs_fsize), 0);
200 }
201 if (idesc->id_numfrags != sblock->fs_frag &&
202 cgp) {
203 cgp->cg_cs.cs_nffree ++;
204 sblock->fs_cstotal.cs_nffree ++;
205 sblock->fs_cs(fs, cg).cs_nffree ++;
206 }
207 }
208 }
209 }
210 if (cgp && res != SKIP && idesc->id_numfrags == sblock->fs_frag) {
211 cgp->cg_cs.cs_nbfree++;
212 sblock->fs_cstotal.cs_nbfree++;
213 sblock->fs_cs(fs, cg).cs_nbfree++;
214 ffs_clusteracct(sblock, cgp,
215 ffs_fragstoblks(sblock, dtogd(sblock, idesc->id_blkno)), 1);
216 }
217 sbdirty();
218 cgdirty();
219 return (res);
220 }
221