1 1.31 riastrad /* $NetBSD: pass4.c,v 1.31 2023/07/04 20:40:53 riastradh Exp $ */ 2 1.9 cgd 3 1.1 cgd /* 4 1.6 mycroft * Copyright (c) 1980, 1986, 1993 5 1.6 mycroft * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.18 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.12 lukem #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.9 cgd #if 0 35 1.13 lukem static char sccsid[] = "@(#)pass4.c 8.4 (Berkeley) 4/28/95"; 36 1.9 cgd #else 37 1.31 riastrad __RCSID("$NetBSD: pass4.c,v 1.31 2023/07/04 20:40:53 riastradh Exp $"); 38 1.9 cgd #endif 39 1.1 cgd #endif /* not lint */ 40 1.1 cgd 41 1.1 cgd #include <sys/param.h> 42 1.5 cgd #include <sys/time.h> 43 1.26 bouyer #include <sys/stat.h> 44 1.13 lukem 45 1.26 bouyer #include <ufs/ufs/ufs_bswap.h> 46 1.6 mycroft #include <ufs/ufs/dinode.h> 47 1.6 mycroft #include <ufs/ffs/fs.h> 48 1.26 bouyer #include <ufs/ffs/ffs_extern.h> 49 1.13 lukem 50 1.13 lukem #include <err.h> 51 1.14 lukem #include <stdlib.h> 52 1.1 cgd #include <string.h> 53 1.10 christos 54 1.11 christos #include "fsutil.h" 55 1.1 cgd #include "fsck.h" 56 1.8 cgd #include "extern.h" 57 1.1 cgd 58 1.8 cgd void 59 1.21 xtraeme pass4(void) 60 1.1 cgd { 61 1.12 lukem ino_t inumber; 62 1.12 lukem struct zlncnt *zlnp; 63 1.17 fvdl union dinode *dp; 64 1.1 cgd struct inodesc idesc; 65 1.30 christos int n; 66 1.30 christos size_t i; 67 1.29 chs uint32_t cg; 68 1.17 fvdl struct inostat *info; 69 1.1 cgd 70 1.7 mycroft memset(&idesc, 0, sizeof(struct inodesc)); 71 1.1 cgd idesc.id_func = pass4check; 72 1.17 fvdl 73 1.17 fvdl for (cg = 0; cg < sblock->fs_ncg; cg++) { 74 1.15 lukem if (got_siginfo) { 75 1.15 lukem fprintf(stderr, 76 1.15 lukem "%s: phase 4: cyl group %d of %d (%d%%)\n", 77 1.17 fvdl cdevname(), cg, sblock->fs_ncg, 78 1.17 fvdl cg * 100 / sblock->fs_ncg); 79 1.15 lukem got_siginfo = 0; 80 1.15 lukem } 81 1.20 christos #ifdef PROGRESS 82 1.19 christos progress_bar(cdevname(), preen ? NULL : "phase 4", 83 1.19 christos cg, sblock->fs_ncg); 84 1.20 christos #endif /* PROGRESS */ 85 1.17 fvdl inumber = cg * sblock->fs_ipg; 86 1.17 fvdl for (i = 0; i < inostathead[cg].il_numalloced; i++, inumber++) { 87 1.27 dholland if (inumber < UFS_ROOTINO) 88 1.17 fvdl continue; 89 1.26 bouyer dp = ginode(inumber); 90 1.17 fvdl info = inoinfo(inumber); 91 1.17 fvdl idesc.id_number = inumber; 92 1.26 bouyer idesc.id_uid = iswap32(DIP(dp, uid)); 93 1.26 bouyer idesc.id_gid = iswap32(DIP(dp, gid)); 94 1.26 bouyer if (iswap32(DIP(dp, flags)) & SF_SNAPSHOT) 95 1.26 bouyer idesc.id_type = SNAP; 96 1.26 bouyer else 97 1.26 bouyer idesc.id_type = ADDR; 98 1.17 fvdl switch (info->ino_state) { 99 1.17 fvdl case FSTATE: 100 1.17 fvdl case DFOUND: 101 1.17 fvdl n = info->ino_linkcnt; 102 1.17 fvdl if (n) { 103 1.25 simonb if (is_journal_inode(inumber)) { 104 1.25 simonb if (debug) 105 1.25 simonb printf( 106 1.25 simonb "skipping unreferenced journal inode %" PRId64 "\n", inumber); 107 1.25 simonb break; 108 1.26 bouyer } else if (is_quota_inode(inumber)) { 109 1.26 bouyer if (debug) 110 1.26 bouyer printf( 111 1.26 bouyer "skipping unreferenced quota inode %" PRId64 "\n", inumber); 112 1.26 bouyer break; 113 1.25 simonb } else { 114 1.25 simonb adjust(&idesc, (short)n); 115 1.25 simonb } 116 1.17 fvdl break; 117 1.17 fvdl } 118 1.1 cgd for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) 119 1.1 cgd if (zlnp->zlncnt == inumber) { 120 1.1 cgd zlnp->zlncnt = zlnhead->zlncnt; 121 1.1 cgd zlnp = zlnhead; 122 1.1 cgd zlnhead = zlnhead->next; 123 1.1 cgd free((char *)zlnp); 124 1.1 cgd clri(&idesc, "UNREF", 1); 125 1.1 cgd break; 126 1.1 cgd } 127 1.17 fvdl break; 128 1.17 fvdl 129 1.17 fvdl case DSTATE: 130 1.17 fvdl clri(&idesc, "UNREF", 1); 131 1.17 fvdl break; 132 1.17 fvdl 133 1.17 fvdl case DCLEAR: 134 1.17 fvdl if (DIP(dp, size) == 0) { 135 1.17 fvdl clri(&idesc, "ZERO LENGTH", 1); 136 1.17 fvdl break; 137 1.17 fvdl } 138 1.17 fvdl /* fall through */ 139 1.17 fvdl case FCLEAR: 140 1.17 fvdl clri(&idesc, "BAD/DUP", 1); 141 1.17 fvdl break; 142 1.1 cgd 143 1.17 fvdl case USTATE: 144 1.1 cgd break; 145 1.17 fvdl 146 1.17 fvdl default: 147 1.24 christos errexit("BAD STATE %d FOR INODE I=%llu", 148 1.22 christos info->ino_state, 149 1.22 christos (unsigned long long)inumber); 150 1.1 cgd } 151 1.1 cgd } 152 1.1 cgd } 153 1.20 christos #ifdef PROGRESS 154 1.23 apb if (!preen) 155 1.19 christos progress_done(); 156 1.20 christos #endif /* PROGRESS */ 157 1.1 cgd } 158 1.1 cgd 159 1.8 cgd int 160 1.21 xtraeme pass4check(struct inodesc *idesc) 161 1.1 cgd { 162 1.12 lukem struct dups *dlp; 163 1.26 bouyer int cg, nfrags, res = KEEPON; 164 1.16 fvdl daddr_t blkno = idesc->id_blkno; 165 1.26 bouyer struct cg *cgp = cgrp; 166 1.26 bouyer 167 1.26 bouyer cg = dtog(sblock, blkno); 168 1.26 bouyer getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize); 169 1.26 bouyer memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize); 170 1.26 bouyer if ((doswap && !needswap) || (!doswap && needswap)) 171 1.26 bouyer ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock); 172 1.26 bouyer if (!cg_chkmagic(cgp, 0)) { 173 1.26 bouyer pwarn("CG %d: ALLOCBLK: BAD MAGIC NUMBER\n", cg); 174 1.26 bouyer cgp = NULL; 175 1.26 bouyer } 176 1.1 cgd 177 1.1 cgd for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 178 1.1 cgd if (chkrange(blkno, 1)) { 179 1.1 cgd res = SKIP; 180 1.1 cgd } else if (testbmap(blkno)) { 181 1.1 cgd for (dlp = duplist; dlp; dlp = dlp->next) { 182 1.1 cgd if (dlp->dup != blkno) 183 1.1 cgd continue; 184 1.1 cgd dlp->dup = duplist->dup; 185 1.1 cgd dlp = duplist; 186 1.1 cgd duplist = duplist->next; 187 1.1 cgd free((char *)dlp); 188 1.1 cgd break; 189 1.1 cgd } 190 1.1 cgd if (dlp == 0) { 191 1.1 cgd clrbmap(blkno); 192 1.26 bouyer if (cgp) 193 1.26 bouyer setbit(cg_blksfree(cgp, 0), 194 1.26 bouyer dtogd(sblock, blkno)); 195 1.26 bouyer 196 1.1 cgd n_blks--; 197 1.26 bouyer if (idesc->id_type != SNAP) { 198 1.26 bouyer update_uquot(idesc->id_number, 199 1.31 riastrad idesc->id_uid, idesc->id_gid, 200 1.26 bouyer -btodb(sblock->fs_fsize), 0); 201 1.26 bouyer } 202 1.26 bouyer if (idesc->id_numfrags != sblock->fs_frag && 203 1.26 bouyer cgp) { 204 1.26 bouyer cgp->cg_cs.cs_nffree ++; 205 1.26 bouyer sblock->fs_cstotal.cs_nffree ++; 206 1.26 bouyer sblock->fs_cs(fs, cg).cs_nffree ++; 207 1.26 bouyer } 208 1.1 cgd } 209 1.1 cgd } 210 1.1 cgd } 211 1.26 bouyer if (cgp && res != SKIP && idesc->id_numfrags == sblock->fs_frag) { 212 1.26 bouyer cgp->cg_cs.cs_nbfree++; 213 1.26 bouyer sblock->fs_cstotal.cs_nbfree++; 214 1.26 bouyer sblock->fs_cs(fs, cg).cs_nbfree++; 215 1.26 bouyer ffs_clusteracct(sblock, cgp, 216 1.28 dholland ffs_fragstoblks(sblock, dtogd(sblock, idesc->id_blkno)), 1); 217 1.26 bouyer } 218 1.26 bouyer sbdirty(); 219 1.26 bouyer cgdirty(); 220 1.1 cgd return (res); 221 1.1 cgd } 222