11558Srgrimes/* 21558Srgrimes * Copyright (c) 1980, 1986, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 4. Neither the name of the University nor the names of its contributors 141558Srgrimes * may be used to endorse or promote products derived from this software 151558Srgrimes * without specific prior written permission. 161558Srgrimes * 171558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271558Srgrimes * SUCH DAMAGE. 281558Srgrimes */ 291558Srgrimes 30102411Scharnier#if 0 311558Srgrimes#ifndef lint 3223675Speterstatic const char sccsid[] = "@(#)pass5.c 8.9 (Berkeley) 4/28/95"; 33102411Scharnier#endif /* not lint */ 3441477Sjulian#endif 35102411Scharnier#include <sys/cdefs.h> 36102411Scharnier__FBSDID("$FreeBSD$"); 37102411Scharnier 381558Srgrimes#include <sys/param.h> 3974556Smckusick#include <sys/sysctl.h> 4023675Speter 411558Srgrimes#include <ufs/ufs/dinode.h> 421558Srgrimes#include <ufs/ffs/fs.h> 4323799Sbde 4423675Speter#include <err.h> 45142123Sdelphij#include <inttypes.h> 46103949Smike#include <limits.h> 471558Srgrimes#include <string.h> 48207141Sjeff#include <libufs.h> 4923675Speter 501558Srgrimes#include "fsck.h" 511558Srgrimes 52224059Smckusickstatic void check_maps(u_char *, u_char *, int, ufs2_daddr_t, const char *, 53224059Smckusick int *, int, int, int); 54221233Sdesstatic void clear_blocks(ufs2_daddr_t start, ufs2_daddr_t end); 55221233Sdes 567585Sbdevoid 5792839Simppass5(void) 581558Srgrimes{ 5998542Smckusick int c, i, j, blk, frags, basesize, mapsize; 6074556Smckusick int inomapsize, blkmapsize; 6123675Speter struct fs *fs = &sblock; 62221233Sdes ufs2_daddr_t d, dbase, dmax, start; 63224059Smckusick int rewritecg = 0; 641558Srgrimes struct csum *cs; 6598542Smckusick struct csum_total cstotal; 661558Srgrimes struct inodesc idesc[3]; 671558Srgrimes char buf[MAXBSIZE]; 68248658Smckusick struct cg *cg, *newcg = (struct cg *)buf; 69248658Smckusick struct bufarea *cgbp; 701558Srgrimes 7141474Sjulian inoinfo(WINO)->ino_state = USTATE; 7223675Speter memset(newcg, 0, (size_t)fs->fs_cgsize); 731558Srgrimes newcg->cg_niblk = fs->fs_ipg; 7423675Speter if (cvtlevel >= 3) { 751558Srgrimes if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) { 761558Srgrimes if (preen) 771558Srgrimes pwarn("DELETING CLUSTERING MAPS\n"); 781558Srgrimes if (preen || reply("DELETE CLUSTERING MAPS")) { 791558Srgrimes fs->fs_contigsumsize = 0; 8096483Sphk rewritecg = 1; 811558Srgrimes sbdirty(); 821558Srgrimes } 831558Srgrimes } 841558Srgrimes if (fs->fs_maxcontig > 1) { 85100935Sphk const char *doit = 0; 861558Srgrimes 871558Srgrimes if (fs->fs_contigsumsize < 1) { 881558Srgrimes doit = "CREAT"; 891558Srgrimes } else if (fs->fs_contigsumsize < fs->fs_maxcontig && 901558Srgrimes fs->fs_contigsumsize < FS_MAXCONTIG) { 911558Srgrimes doit = "EXPAND"; 921558Srgrimes } 931558Srgrimes if (doit) { 941558Srgrimes i = fs->fs_contigsumsize; 951558Srgrimes fs->fs_contigsumsize = 961558Srgrimes MIN(fs->fs_maxcontig, FS_MAXCONTIG); 9774556Smckusick if (CGSIZE(fs) > (u_int)fs->fs_bsize) { 981558Srgrimes pwarn("CANNOT %s CLUSTER MAPS\n", doit); 991558Srgrimes fs->fs_contigsumsize = i; 1001558Srgrimes } else if (preen || 1011558Srgrimes reply("CREATE CLUSTER MAPS")) { 1021558Srgrimes if (preen) 1031558Srgrimes pwarn("%sING CLUSTER MAPS\n", 1041558Srgrimes doit); 1051558Srgrimes fs->fs_cgsize = 1061558Srgrimes fragroundup(fs, CGSIZE(fs)); 10796483Sphk rewritecg = 1; 1081558Srgrimes sbdirty(); 1091558Srgrimes } 1101558Srgrimes } 1111558Srgrimes } 1121558Srgrimes } 11398542Smckusick basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield); 11498542Smckusick if (sblock.fs_magic == FS_UFS2_MAGIC) { 11598542Smckusick newcg->cg_iusedoff = basesize; 11698542Smckusick } else { 11798542Smckusick /* 11898542Smckusick * We reserve the space for the old rotation summary 11998542Smckusick * tables for the benefit of old kernels, but do not 12098542Smckusick * maintain them in modern kernels. In time, they can 12198542Smckusick * go away. 12298542Smckusick */ 12398542Smckusick newcg->cg_old_btotoff = basesize; 12498542Smckusick newcg->cg_old_boff = newcg->cg_old_btotoff + 12598542Smckusick fs->fs_old_cpg * sizeof(int32_t); 12698542Smckusick newcg->cg_iusedoff = newcg->cg_old_boff + 12798542Smckusick fs->fs_old_cpg * fs->fs_old_nrpos * sizeof(u_int16_t); 12898542Smckusick memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize); 1291558Srgrimes } 130103949Smike inomapsize = howmany(fs->fs_ipg, CHAR_BIT); 13198542Smckusick newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize; 132103949Smike blkmapsize = howmany(fs->fs_fpg, CHAR_BIT); 13398542Smckusick newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize; 13498542Smckusick if (fs->fs_contigsumsize > 0) { 13598542Smckusick newcg->cg_clustersumoff = newcg->cg_nextfreeoff - 13698542Smckusick sizeof(u_int32_t); 13798542Smckusick newcg->cg_clustersumoff = 13898542Smckusick roundup(newcg->cg_clustersumoff, sizeof(u_int32_t)); 13998542Smckusick newcg->cg_clusteroff = newcg->cg_clustersumoff + 14098542Smckusick (fs->fs_contigsumsize + 1) * sizeof(u_int32_t); 14198542Smckusick newcg->cg_nextfreeoff = newcg->cg_clusteroff + 142103949Smike howmany(fragstoblks(fs, fs->fs_fpg), CHAR_BIT); 14398542Smckusick } 14498542Smckusick newcg->cg_magic = CG_MAGIC; 14598542Smckusick mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff; 14623675Speter memset(&idesc[0], 0, sizeof idesc); 14796483Sphk for (i = 0; i < 3; i++) 1481558Srgrimes idesc[i].id_type = ADDR; 14998542Smckusick memset(&cstotal, 0, sizeof(struct csum_total)); 15098542Smckusick dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1); 15198542Smckusick for (d = fs->fs_size; d < dmax; d++) 15298542Smckusick setbmap(d); 1531558Srgrimes for (c = 0; c < fs->fs_ncg; c++) { 15470050Siedowse if (got_siginfo) { 15570050Siedowse printf("%s: phase 5: cyl group %d of %d (%d%%)\n", 15670050Siedowse cdevname, c, sblock.fs_ncg, 15770050Siedowse c * 100 / sblock.fs_ncg); 15870050Siedowse got_siginfo = 0; 15970050Siedowse } 160126345Sscottl if (got_sigalarm) { 161127638Sdwmalone setproctitle("%s p5 %d%%", cdevname, 162126345Sscottl c * 100 / sblock.fs_ncg); 163126345Sscottl got_sigalarm = 0; 164126345Sscottl } 165248658Smckusick cgbp = cgget(c); 166248658Smckusick cg = cgbp->b_un.b_cg; 1671558Srgrimes if (!cg_chkmagic(cg)) 1681558Srgrimes pfatal("CG %d: BAD MAGIC NUMBER\n", c); 16998542Smckusick newcg->cg_time = cg->cg_time; 17098542Smckusick newcg->cg_old_time = cg->cg_old_time; 171163845Spjd newcg->cg_unrefs = cg->cg_unrefs; 17298542Smckusick newcg->cg_cgx = c; 1731558Srgrimes dbase = cgbase(fs, c); 1741558Srgrimes dmax = dbase + fs->fs_fpg; 1751558Srgrimes if (dmax > fs->fs_size) 1761558Srgrimes dmax = fs->fs_size; 1771558Srgrimes newcg->cg_ndblk = dmax - dbase; 17898542Smckusick if (fs->fs_magic == FS_UFS1_MAGIC) { 17998542Smckusick if (c == fs->fs_ncg - 1) 18098542Smckusick newcg->cg_old_ncyl = howmany(newcg->cg_ndblk, 18198542Smckusick fs->fs_fpg / fs->fs_old_cpg); 18298542Smckusick else 18398542Smckusick newcg->cg_old_ncyl = fs->fs_old_cpg; 18498542Smckusick newcg->cg_old_niblk = fs->fs_ipg; 18598542Smckusick newcg->cg_niblk = 0; 18698542Smckusick } 1871558Srgrimes if (fs->fs_contigsumsize > 0) 1881558Srgrimes newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag; 1891558Srgrimes newcg->cg_cs.cs_ndir = 0; 1901558Srgrimes newcg->cg_cs.cs_nffree = 0; 1911558Srgrimes newcg->cg_cs.cs_nbfree = 0; 1921558Srgrimes newcg->cg_cs.cs_nifree = fs->fs_ipg; 193107829Simp if (cg->cg_rotor >= 0 && cg->cg_rotor < newcg->cg_ndblk) 1941558Srgrimes newcg->cg_rotor = cg->cg_rotor; 1951558Srgrimes else 1961558Srgrimes newcg->cg_rotor = 0; 197107829Simp if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk) 1981558Srgrimes newcg->cg_frotor = cg->cg_frotor; 1991558Srgrimes else 2001558Srgrimes newcg->cg_frotor = 0; 201107829Simp if (cg->cg_irotor >= 0 && cg->cg_irotor < fs->fs_ipg) 2021558Srgrimes newcg->cg_irotor = cg->cg_irotor; 2031558Srgrimes else 2041558Srgrimes newcg->cg_irotor = 0; 20598542Smckusick if (fs->fs_magic == FS_UFS1_MAGIC) { 20698542Smckusick newcg->cg_initediblk = 0; 20798542Smckusick } else { 20898542Smckusick if ((unsigned)cg->cg_initediblk > fs->fs_ipg) 20998542Smckusick newcg->cg_initediblk = fs->fs_ipg; 21098542Smckusick else 21198542Smckusick newcg->cg_initediblk = cg->cg_initediblk; 21298542Smckusick } 21323675Speter memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum); 21498542Smckusick memset(cg_inosused(newcg), 0, (size_t)(mapsize)); 2151558Srgrimes j = fs->fs_ipg * c; 21641474Sjulian for (i = 0; i < inostathead[c].il_numalloced; j++, i++) { 21741474Sjulian switch (inoinfo(j)->ino_state) { 2181558Srgrimes 2191558Srgrimes case USTATE: 2201558Srgrimes break; 2211558Srgrimes 2221558Srgrimes case DSTATE: 2231558Srgrimes case DCLEAR: 2241558Srgrimes case DFOUND: 225136281Struckman case DZLINK: 2261558Srgrimes newcg->cg_cs.cs_ndir++; 227102411Scharnier /* FALLTHROUGH */ 2281558Srgrimes 2291558Srgrimes case FSTATE: 2301558Srgrimes case FCLEAR: 231136281Struckman case FZLINK: 2321558Srgrimes newcg->cg_cs.cs_nifree--; 2331558Srgrimes setbit(cg_inosused(newcg), i); 2341558Srgrimes break; 2351558Srgrimes 2361558Srgrimes default: 23774556Smckusick if (j < (int)ROOTINO) 2381558Srgrimes break; 23986514Siedowse errx(EEXIT, "BAD STATE %d FOR INODE I=%d", 24041474Sjulian inoinfo(j)->ino_state, j); 2411558Srgrimes } 2421558Srgrimes } 2431558Srgrimes if (c == 0) 24474556Smckusick for (i = 0; i < (int)ROOTINO; i++) { 2451558Srgrimes setbit(cg_inosused(newcg), i); 2461558Srgrimes newcg->cg_cs.cs_nifree--; 2471558Srgrimes } 248221233Sdes start = -1; 2491558Srgrimes for (i = 0, d = dbase; 2501558Srgrimes d < dmax; 2511558Srgrimes d += fs->fs_frag, i += fs->fs_frag) { 2521558Srgrimes frags = 0; 2531558Srgrimes for (j = 0; j < fs->fs_frag; j++) { 254221233Sdes if (testbmap(d + j)) { 255250056Sdes if ((Eflag || Zflag) && start != -1) { 256221233Sdes clear_blocks(start, d + j - 1); 257221233Sdes start = -1; 258221233Sdes } 2591558Srgrimes continue; 260221233Sdes } 261221233Sdes if (start == -1) 262221233Sdes start = d + j; 2631558Srgrimes setbit(cg_blksfree(newcg), i + j); 2641558Srgrimes frags++; 2651558Srgrimes } 2661558Srgrimes if (frags == fs->fs_frag) { 2671558Srgrimes newcg->cg_cs.cs_nbfree++; 2681558Srgrimes if (fs->fs_contigsumsize > 0) 2691558Srgrimes setbit(cg_clustersfree(newcg), 2701558Srgrimes i / fs->fs_frag); 2711558Srgrimes } else if (frags > 0) { 2721558Srgrimes newcg->cg_cs.cs_nffree += frags; 2731558Srgrimes blk = blkmap(fs, cg_blksfree(newcg), i); 2741558Srgrimes ffs_fragacct(fs, blk, newcg->cg_frsum, 1); 2751558Srgrimes } 2761558Srgrimes } 277250056Sdes if ((Eflag || Zflag) && start != -1) 278221233Sdes clear_blocks(start, d - 1); 2791558Srgrimes if (fs->fs_contigsumsize > 0) { 28023675Speter int32_t *sump = cg_clustersum(newcg); 2811558Srgrimes u_char *mapp = cg_clustersfree(newcg); 2821558Srgrimes int map = *mapp++; 2831558Srgrimes int bit = 1; 2841558Srgrimes int run = 0; 2851558Srgrimes 2861558Srgrimes for (i = 0; i < newcg->cg_nclusterblks; i++) { 2871558Srgrimes if ((map & bit) != 0) { 2881558Srgrimes run++; 2891558Srgrimes } else if (run != 0) { 2901558Srgrimes if (run > fs->fs_contigsumsize) 2911558Srgrimes run = fs->fs_contigsumsize; 2921558Srgrimes sump[run]++; 2931558Srgrimes run = 0; 2941558Srgrimes } 295103949Smike if ((i & (CHAR_BIT - 1)) != (CHAR_BIT - 1)) { 2961558Srgrimes bit <<= 1; 2971558Srgrimes } else { 2981558Srgrimes map = *mapp++; 2991558Srgrimes bit = 1; 3001558Srgrimes } 3011558Srgrimes } 3021558Srgrimes if (run != 0) { 3031558Srgrimes if (run > fs->fs_contigsumsize) 3041558Srgrimes run = fs->fs_contigsumsize; 3051558Srgrimes sump[run]++; 3061558Srgrimes } 3071558Srgrimes } 308183821Skib if (bkgrdflag != 0) { 309183821Skib cstotal.cs_nffree += cg->cg_cs.cs_nffree; 310183821Skib cstotal.cs_nbfree += cg->cg_cs.cs_nbfree; 311183821Skib cstotal.cs_nifree += cg->cg_cs.cs_nifree; 312183821Skib cstotal.cs_ndir += cg->cg_cs.cs_ndir; 313183821Skib } else { 314183821Skib cstotal.cs_nffree += newcg->cg_cs.cs_nffree; 315183821Skib cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree; 316183821Skib cstotal.cs_nifree += newcg->cg_cs.cs_nifree; 317183821Skib cstotal.cs_ndir += newcg->cg_cs.cs_ndir; 318183821Skib } 3191558Srgrimes cs = &fs->fs_cs(fs, c); 32074556Smckusick if (cursnapshot == 0 && 32174556Smckusick memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0 && 3221558Srgrimes dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { 32323675Speter memmove(cs, &newcg->cg_cs, sizeof *cs); 3241558Srgrimes sbdirty(); 3251558Srgrimes } 32696483Sphk if (rewritecg) { 32723675Speter memmove(cg, newcg, (size_t)fs->fs_cgsize); 328248658Smckusick dirty(cgbp); 3291558Srgrimes continue; 3301558Srgrimes } 33174556Smckusick if (cursnapshot == 0 && 33298542Smckusick memcmp(newcg, cg, basesize) != 0 && 3331558Srgrimes dofix(&idesc[2], "SUMMARY INFORMATION BAD")) { 33423675Speter memmove(cg, newcg, (size_t)basesize); 335248658Smckusick dirty(cgbp); 3361558Srgrimes } 337224059Smckusick if (bkgrdflag != 0 || usedsoftdep || debug) 338224059Smckusick update_maps(cg, newcg, bkgrdflag); 33974556Smckusick if (cursnapshot == 0 && 34074556Smckusick memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0 && 34134266Sjulian dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) { 34234266Sjulian memmove(cg_inosused(cg), cg_inosused(newcg), 34334266Sjulian (size_t)mapsize); 344248658Smckusick dirty(cgbp); 34534266Sjulian } 3461558Srgrimes } 34774556Smckusick if (cursnapshot == 0 && 34898542Smckusick memcmp(&cstotal, &fs->fs_cstotal, sizeof cstotal) != 0 34998542Smckusick && dofix(&idesc[0], "SUMMARY BLK COUNT(S) WRONG IN SUPERBLK")) { 35098542Smckusick memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal); 3511558Srgrimes fs->fs_ronly = 0; 35241474Sjulian fs->fs_fmod = 0; 3531558Srgrimes sbdirty(); 3541558Srgrimes } 355142123Sdelphij 356142123Sdelphij /* 357142123Sdelphij * When doing background fsck on a snapshot, figure out whether 358142123Sdelphij * the superblock summary is inaccurate and correct it when 359142123Sdelphij * necessary. 360142123Sdelphij */ 361142123Sdelphij if (cursnapshot != 0) { 362142123Sdelphij cmd.size = 1; 363142123Sdelphij 364142123Sdelphij cmd.value = cstotal.cs_ndir - fs->fs_cstotal.cs_ndir; 365142123Sdelphij if (cmd.value != 0) { 366142123Sdelphij if (debug) 367142123Sdelphij printf("adjndir by %+" PRIi64 "\n", cmd.value); 368143235Sdelphij if (bkgrdsumadj == 0 || sysctl(adjndir, MIBSIZE, 0, 0, 369142123Sdelphij &cmd, sizeof cmd) == -1) 370142123Sdelphij rwerror("ADJUST NUMBER OF DIRECTORIES", cmd.value); 371142123Sdelphij } 372142123Sdelphij 373142123Sdelphij cmd.value = cstotal.cs_nbfree - fs->fs_cstotal.cs_nbfree; 374142123Sdelphij if (cmd.value != 0) { 375142123Sdelphij if (debug) 376142123Sdelphij printf("adjnbfree by %+" PRIi64 "\n", cmd.value); 377143235Sdelphij if (bkgrdsumadj == 0 || sysctl(adjnbfree, MIBSIZE, 0, 0, 378142123Sdelphij &cmd, sizeof cmd) == -1) 379142123Sdelphij rwerror("ADJUST NUMBER OF FREE BLOCKS", cmd.value); 380142123Sdelphij } 381142123Sdelphij 382142123Sdelphij cmd.value = cstotal.cs_nifree - fs->fs_cstotal.cs_nifree; 383142123Sdelphij if (cmd.value != 0) { 384142123Sdelphij if (debug) 385142123Sdelphij printf("adjnifree by %+" PRIi64 "\n", cmd.value); 386143235Sdelphij if (bkgrdsumadj == 0 || sysctl(adjnifree, MIBSIZE, 0, 0, 387142123Sdelphij &cmd, sizeof cmd) == -1) 388142123Sdelphij rwerror("ADJUST NUMBER OF FREE INODES", cmd.value); 389142123Sdelphij } 390142123Sdelphij 391142123Sdelphij cmd.value = cstotal.cs_nffree - fs->fs_cstotal.cs_nffree; 392142123Sdelphij if (cmd.value != 0) { 393142123Sdelphij if (debug) 394142123Sdelphij printf("adjnffree by %+" PRIi64 "\n", cmd.value); 395143235Sdelphij if (bkgrdsumadj == 0 || sysctl(adjnffree, MIBSIZE, 0, 0, 396142123Sdelphij &cmd, sizeof cmd) == -1) 397142123Sdelphij rwerror("ADJUST NUMBER OF FREE FRAGS", cmd.value); 398142123Sdelphij } 399142123Sdelphij 400142123Sdelphij cmd.value = cstotal.cs_numclusters - fs->fs_cstotal.cs_numclusters; 401142123Sdelphij if (cmd.value != 0) { 402142123Sdelphij if (debug) 403142123Sdelphij printf("adjnumclusters by %+" PRIi64 "\n", cmd.value); 404143235Sdelphij if (bkgrdsumadj == 0 || sysctl(adjnumclusters, MIBSIZE, 0, 0, 405142123Sdelphij &cmd, sizeof cmd) == -1) 406142123Sdelphij rwerror("ADJUST NUMBER OF FREE CLUSTERS", cmd.value); 407142123Sdelphij } 408142123Sdelphij } 4091558Srgrimes} 41074556Smckusick 411224059Smckusick/* 412224059Smckusick * Compare the original cylinder group inode and block bitmaps with the 413224059Smckusick * updated cylinder group inode and block bitmaps. Free inodes and blocks 414224059Smckusick * that have been added. Complain if any previously freed inodes blocks 415224059Smckusick * are now allocated. 416224059Smckusick */ 417224059Smckusickvoid 418224059Smckusickupdate_maps( 419224059Smckusick struct cg *oldcg, /* cylinder group of claimed allocations */ 420224059Smckusick struct cg *newcg, /* cylinder group of determined allocations */ 421224059Smckusick int usesysctl) /* 1 => use sysctl interface to update maps */ 422224059Smckusick{ 423224059Smckusick int inomapsize, excessdirs; 424224059Smckusick struct fs *fs = &sblock; 425224059Smckusick 426224059Smckusick inomapsize = howmany(fs->fs_ipg, CHAR_BIT); 427224059Smckusick excessdirs = oldcg->cg_cs.cs_ndir - newcg->cg_cs.cs_ndir; 428224059Smckusick if (excessdirs < 0) { 429224059Smckusick pfatal("LOST %d DIRECTORIES\n", -excessdirs); 430224059Smckusick excessdirs = 0; 431224059Smckusick } 432224059Smckusick if (excessdirs > 0) 433224059Smckusick check_maps(cg_inosused(newcg), cg_inosused(oldcg), inomapsize, 434224059Smckusick oldcg->cg_cgx * (ufs2_daddr_t)fs->fs_ipg, "DIR", freedirs, 435224059Smckusick 0, excessdirs, usesysctl); 436224059Smckusick check_maps(cg_inosused(newcg), cg_inosused(oldcg), inomapsize, 437224059Smckusick oldcg->cg_cgx * (ufs2_daddr_t)fs->fs_ipg, "FILE", freefiles, 438224059Smckusick excessdirs, fs->fs_ipg, usesysctl); 439224059Smckusick check_maps(cg_blksfree(oldcg), cg_blksfree(newcg), 440224059Smckusick howmany(fs->fs_fpg, CHAR_BIT), 441224059Smckusick oldcg->cg_cgx * (ufs2_daddr_t)fs->fs_fpg, "FRAG", 442224059Smckusick freeblks, 0, fs->fs_fpg, usesysctl); 443224059Smckusick} 444224059Smckusick 44574556Smckusickstatic void 44692839Simpcheck_maps( 44792839Simp u_char *map1, /* map of claimed allocations */ 44892839Simp u_char *map2, /* map of determined allocations */ 44992839Simp int mapsize, /* size of above two maps */ 450183820Skib ufs2_daddr_t startvalue, /* resource value for first element in map */ 451100935Sphk const char *name, /* name of resource found in maps */ 45292839Simp int *opcode, /* sysctl opcode to free resource */ 45392839Simp int skip, /* number of entries to skip before starting to free */ 454224059Smckusick int limit, /* limit on number of entries to free */ 455224059Smckusick int usesysctl) /* 1 => use sysctl interface to update maps */ 45674556Smckusick{ 45774556Smckusick# define BUFSIZE 16 45874556Smckusick char buf[BUFSIZE]; 459183820Skib long i, j, k, l, m, size; 460183820Skib ufs2_daddr_t n, astart, aend, ustart, uend; 46192839Simp void (*msg)(const char *fmt, ...); 46274556Smckusick 463224059Smckusick if (usesysctl) 46475557Smckusick msg = pfatal; 46575557Smckusick else 46675557Smckusick msg = pwarn; 46774556Smckusick astart = ustart = aend = uend = -1; 46874556Smckusick for (i = 0; i < mapsize; i++) { 46974556Smckusick j = *map1++; 47074556Smckusick k = *map2++; 47174556Smckusick if (j == k) 47274556Smckusick continue; 473103949Smike for (m = 0, l = 1; m < CHAR_BIT; m++, l <<= 1) { 47474556Smckusick if ((j & l) == (k & l)) 47574556Smckusick continue; 476103949Smike n = startvalue + i * CHAR_BIT + m; 47774556Smckusick if ((j & l) != 0) { 47874556Smckusick if (astart == -1) { 47974556Smckusick astart = aend = n; 48074556Smckusick continue; 48174556Smckusick } 48274556Smckusick if (aend + 1 == n) { 48374556Smckusick aend = n; 48474556Smckusick continue; 48574556Smckusick } 48674556Smckusick if (astart == aend) 487183820Skib (*msg)("ALLOCATED %s %" PRId64 488183820Skib " MARKED FREE\n", 48974556Smckusick name, astart); 49074556Smckusick else 491183820Skib (*msg)("%s %sS %" PRId64 "-%" PRId64 492183820Skib " MARKED FREE\n", 49374556Smckusick "ALLOCATED", name, astart, aend); 49474556Smckusick astart = aend = n; 49574556Smckusick } else { 49674556Smckusick if (ustart == -1) { 49774556Smckusick ustart = uend = n; 49874556Smckusick continue; 49974556Smckusick } 50074556Smckusick if (uend + 1 == n) { 50174556Smckusick uend = n; 50274556Smckusick continue; 50374556Smckusick } 50474556Smckusick size = uend - ustart + 1; 50574556Smckusick if (size <= skip) { 50674556Smckusick skip -= size; 50774556Smckusick ustart = uend = n; 50874556Smckusick continue; 50974556Smckusick } 51074556Smckusick if (skip > 0) { 51174556Smckusick ustart += skip; 51274556Smckusick size -= skip; 51374556Smckusick skip = 0; 51474556Smckusick } 51574556Smckusick if (size > limit) 51674556Smckusick size = limit; 51774556Smckusick if (debug && size == 1) 518183820Skib pwarn("%s %s %" PRId64 519183820Skib " MARKED USED\n", 52074556Smckusick "UNALLOCATED", name, ustart); 52174556Smckusick else if (debug) 522183820Skib pwarn("%s %sS %" PRId64 "-%" PRId64 523183820Skib " MARKED USED\n", 52474556Smckusick "UNALLOCATED", name, ustart, 52574556Smckusick ustart + size - 1); 526224059Smckusick if (usesysctl != 0) { 52774556Smckusick cmd.value = ustart; 52874556Smckusick cmd.size = size; 52974556Smckusick if (sysctl(opcode, MIBSIZE, 0, 0, 53074556Smckusick &cmd, sizeof cmd) == -1) { 53174556Smckusick snprintf(buf, BUFSIZE, 53274556Smckusick "FREE %s", name); 53374556Smckusick rwerror(buf, cmd.value); 53474556Smckusick } 53574556Smckusick } 53674556Smckusick limit -= size; 53774556Smckusick if (limit <= 0) 53874556Smckusick return; 53974556Smckusick ustart = uend = n; 54074556Smckusick } 54174556Smckusick } 54274556Smckusick } 54386514Siedowse if (astart != -1) { 54474556Smckusick if (astart == aend) 545183820Skib (*msg)("ALLOCATED %s %" PRId64 546183820Skib " MARKED FREE\n", name, astart); 54774556Smckusick else 548183820Skib (*msg)("ALLOCATED %sS %" PRId64 "-%" PRId64 549183820Skib " MARKED FREE\n", 55074556Smckusick name, astart, aend); 55186514Siedowse } 55274556Smckusick if (ustart != -1) { 55374556Smckusick size = uend - ustart + 1; 55474556Smckusick if (size <= skip) 55574556Smckusick return; 55674556Smckusick if (skip > 0) { 55774556Smckusick ustart += skip; 55874556Smckusick size -= skip; 55974556Smckusick } 56074556Smckusick if (size > limit) 56174556Smckusick size = limit; 56274556Smckusick if (debug) { 56374556Smckusick if (size == 1) 564183820Skib pwarn("UNALLOCATED %s %" PRId64 565183820Skib " MARKED USED\n", 56674556Smckusick name, ustart); 56774556Smckusick else 568183820Skib pwarn("UNALLOCATED %sS %" PRId64 "-%" PRId64 569183820Skib " MARKED USED\n", 57074556Smckusick name, ustart, ustart + size - 1); 57174556Smckusick } 572224059Smckusick if (usesysctl != 0) { 57374556Smckusick cmd.value = ustart; 57474556Smckusick cmd.size = size; 57574556Smckusick if (sysctl(opcode, MIBSIZE, 0, 0, &cmd, 57674556Smckusick sizeof cmd) == -1) { 57774556Smckusick snprintf(buf, BUFSIZE, "FREE %s", name); 57874556Smckusick rwerror(buf, cmd.value); 57974556Smckusick } 58074556Smckusick } 58174556Smckusick } 58274556Smckusick} 583221233Sdes 584250057Sdesstatic void 585250057Sdesclear_blocks(ufs2_daddr_t start, ufs2_daddr_t end) 586221233Sdes{ 587221233Sdes 588221233Sdes if (debug) 589221233Sdes printf("Zero frags %jd to %jd\n", start, end); 590250056Sdes if (Zflag) 591250056Sdes blzero(fswritefd, fsbtodb(&sblock, start), 592250056Sdes lfragtosize(&sblock, end - start + 1)); 593250056Sdes if (Eflag) 594250056Sdes blerase(fswritefd, fsbtodb(&sblock, start), 595250056Sdes lfragtosize(&sblock, end - start + 1)); 596221233Sdes} 597