pass5.c revision 183820
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: head/sbin/fsck_ffs/pass5.c 183820 2008-10-13 13:56:23Z kib $"); 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> 4823675Speter 491558Srgrimes#include "fsck.h" 501558Srgrimes 51183820Skibstatic void check_maps(u_char *, u_char *, int, ufs2_daddr_t, const char *, int *, int, int); 5274556Smckusick 537585Sbdevoid 5492839Simppass5(void) 551558Srgrimes{ 5698542Smckusick int c, i, j, blk, frags, basesize, mapsize; 5774556Smckusick int inomapsize, blkmapsize; 5823675Speter struct fs *fs = &sblock; 5923675Speter struct cg *cg = &cgrp; 6098542Smckusick ufs2_daddr_t d, dbase, dmax; 6198542Smckusick int excessdirs, rewritecg = 0; 621558Srgrimes struct csum *cs; 6398542Smckusick struct csum_total cstotal; 641558Srgrimes struct inodesc idesc[3]; 651558Srgrimes char buf[MAXBSIZE]; 6692806Sobrien struct cg *newcg = (struct cg *)buf; 671558Srgrimes 6841474Sjulian inoinfo(WINO)->ino_state = USTATE; 6923675Speter memset(newcg, 0, (size_t)fs->fs_cgsize); 701558Srgrimes newcg->cg_niblk = fs->fs_ipg; 7123675Speter if (cvtlevel >= 3) { 721558Srgrimes if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) { 731558Srgrimes if (preen) 741558Srgrimes pwarn("DELETING CLUSTERING MAPS\n"); 751558Srgrimes if (preen || reply("DELETE CLUSTERING MAPS")) { 761558Srgrimes fs->fs_contigsumsize = 0; 7796483Sphk rewritecg = 1; 781558Srgrimes sbdirty(); 791558Srgrimes } 801558Srgrimes } 811558Srgrimes if (fs->fs_maxcontig > 1) { 82100935Sphk const char *doit = 0; 831558Srgrimes 841558Srgrimes if (fs->fs_contigsumsize < 1) { 851558Srgrimes doit = "CREAT"; 861558Srgrimes } else if (fs->fs_contigsumsize < fs->fs_maxcontig && 871558Srgrimes fs->fs_contigsumsize < FS_MAXCONTIG) { 881558Srgrimes doit = "EXPAND"; 891558Srgrimes } 901558Srgrimes if (doit) { 911558Srgrimes i = fs->fs_contigsumsize; 921558Srgrimes fs->fs_contigsumsize = 931558Srgrimes MIN(fs->fs_maxcontig, FS_MAXCONTIG); 9474556Smckusick if (CGSIZE(fs) > (u_int)fs->fs_bsize) { 951558Srgrimes pwarn("CANNOT %s CLUSTER MAPS\n", doit); 961558Srgrimes fs->fs_contigsumsize = i; 971558Srgrimes } else if (preen || 981558Srgrimes reply("CREATE CLUSTER MAPS")) { 991558Srgrimes if (preen) 1001558Srgrimes pwarn("%sING CLUSTER MAPS\n", 1011558Srgrimes doit); 1021558Srgrimes fs->fs_cgsize = 1031558Srgrimes fragroundup(fs, CGSIZE(fs)); 10496483Sphk rewritecg = 1; 1051558Srgrimes sbdirty(); 1061558Srgrimes } 1071558Srgrimes } 1081558Srgrimes } 1091558Srgrimes } 11098542Smckusick basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield); 11198542Smckusick if (sblock.fs_magic == FS_UFS2_MAGIC) { 11298542Smckusick newcg->cg_iusedoff = basesize; 11398542Smckusick } else { 11498542Smckusick /* 11598542Smckusick * We reserve the space for the old rotation summary 11698542Smckusick * tables for the benefit of old kernels, but do not 11798542Smckusick * maintain them in modern kernels. In time, they can 11898542Smckusick * go away. 11998542Smckusick */ 12098542Smckusick newcg->cg_old_btotoff = basesize; 12198542Smckusick newcg->cg_old_boff = newcg->cg_old_btotoff + 12298542Smckusick fs->fs_old_cpg * sizeof(int32_t); 12398542Smckusick newcg->cg_iusedoff = newcg->cg_old_boff + 12498542Smckusick fs->fs_old_cpg * fs->fs_old_nrpos * sizeof(u_int16_t); 12598542Smckusick memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize); 1261558Srgrimes } 127103949Smike inomapsize = howmany(fs->fs_ipg, CHAR_BIT); 12898542Smckusick newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize; 129103949Smike blkmapsize = howmany(fs->fs_fpg, CHAR_BIT); 13098542Smckusick newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize; 13198542Smckusick if (fs->fs_contigsumsize > 0) { 13298542Smckusick newcg->cg_clustersumoff = newcg->cg_nextfreeoff - 13398542Smckusick sizeof(u_int32_t); 13498542Smckusick newcg->cg_clustersumoff = 13598542Smckusick roundup(newcg->cg_clustersumoff, sizeof(u_int32_t)); 13698542Smckusick newcg->cg_clusteroff = newcg->cg_clustersumoff + 13798542Smckusick (fs->fs_contigsumsize + 1) * sizeof(u_int32_t); 13898542Smckusick newcg->cg_nextfreeoff = newcg->cg_clusteroff + 139103949Smike howmany(fragstoblks(fs, fs->fs_fpg), CHAR_BIT); 14098542Smckusick } 14198542Smckusick newcg->cg_magic = CG_MAGIC; 14298542Smckusick mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff; 14323675Speter memset(&idesc[0], 0, sizeof idesc); 14496483Sphk for (i = 0; i < 3; i++) 1451558Srgrimes idesc[i].id_type = ADDR; 14698542Smckusick memset(&cstotal, 0, sizeof(struct csum_total)); 14798542Smckusick dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1); 14898542Smckusick for (d = fs->fs_size; d < dmax; d++) 14998542Smckusick setbmap(d); 1501558Srgrimes for (c = 0; c < fs->fs_ncg; c++) { 15170050Siedowse if (got_siginfo) { 15270050Siedowse printf("%s: phase 5: cyl group %d of %d (%d%%)\n", 15370050Siedowse cdevname, c, sblock.fs_ncg, 15470050Siedowse c * 100 / sblock.fs_ncg); 15570050Siedowse got_siginfo = 0; 15670050Siedowse } 157126345Sscottl if (got_sigalarm) { 158127638Sdwmalone setproctitle("%s p5 %d%%", cdevname, 159126345Sscottl c * 100 / sblock.fs_ncg); 160126345Sscottl got_sigalarm = 0; 161126345Sscottl } 1621558Srgrimes getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize); 1631558Srgrimes if (!cg_chkmagic(cg)) 1641558Srgrimes pfatal("CG %d: BAD MAGIC NUMBER\n", c); 16598542Smckusick newcg->cg_time = cg->cg_time; 16698542Smckusick newcg->cg_old_time = cg->cg_old_time; 167163845Spjd newcg->cg_unrefs = cg->cg_unrefs; 16898542Smckusick newcg->cg_cgx = c; 1691558Srgrimes dbase = cgbase(fs, c); 1701558Srgrimes dmax = dbase + fs->fs_fpg; 1711558Srgrimes if (dmax > fs->fs_size) 1721558Srgrimes dmax = fs->fs_size; 1731558Srgrimes newcg->cg_ndblk = dmax - dbase; 17498542Smckusick if (fs->fs_magic == FS_UFS1_MAGIC) { 17598542Smckusick if (c == fs->fs_ncg - 1) 17698542Smckusick newcg->cg_old_ncyl = howmany(newcg->cg_ndblk, 17798542Smckusick fs->fs_fpg / fs->fs_old_cpg); 17898542Smckusick else 17998542Smckusick newcg->cg_old_ncyl = fs->fs_old_cpg; 18098542Smckusick newcg->cg_old_niblk = fs->fs_ipg; 18198542Smckusick newcg->cg_niblk = 0; 18298542Smckusick } 1831558Srgrimes if (fs->fs_contigsumsize > 0) 1841558Srgrimes newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag; 1851558Srgrimes newcg->cg_cs.cs_ndir = 0; 1861558Srgrimes newcg->cg_cs.cs_nffree = 0; 1871558Srgrimes newcg->cg_cs.cs_nbfree = 0; 1881558Srgrimes newcg->cg_cs.cs_nifree = fs->fs_ipg; 189107829Simp if (cg->cg_rotor >= 0 && cg->cg_rotor < newcg->cg_ndblk) 1901558Srgrimes newcg->cg_rotor = cg->cg_rotor; 1911558Srgrimes else 1921558Srgrimes newcg->cg_rotor = 0; 193107829Simp if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk) 1941558Srgrimes newcg->cg_frotor = cg->cg_frotor; 1951558Srgrimes else 1961558Srgrimes newcg->cg_frotor = 0; 197107829Simp if (cg->cg_irotor >= 0 && cg->cg_irotor < fs->fs_ipg) 1981558Srgrimes newcg->cg_irotor = cg->cg_irotor; 1991558Srgrimes else 2001558Srgrimes newcg->cg_irotor = 0; 20198542Smckusick if (fs->fs_magic == FS_UFS1_MAGIC) { 20298542Smckusick newcg->cg_initediblk = 0; 20398542Smckusick } else { 20498542Smckusick if ((unsigned)cg->cg_initediblk > fs->fs_ipg) 20598542Smckusick newcg->cg_initediblk = fs->fs_ipg; 20698542Smckusick else 20798542Smckusick newcg->cg_initediblk = cg->cg_initediblk; 20898542Smckusick } 20923675Speter memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum); 21098542Smckusick memset(cg_inosused(newcg), 0, (size_t)(mapsize)); 2111558Srgrimes j = fs->fs_ipg * c; 21241474Sjulian for (i = 0; i < inostathead[c].il_numalloced; j++, i++) { 21341474Sjulian switch (inoinfo(j)->ino_state) { 2141558Srgrimes 2151558Srgrimes case USTATE: 2161558Srgrimes break; 2171558Srgrimes 2181558Srgrimes case DSTATE: 2191558Srgrimes case DCLEAR: 2201558Srgrimes case DFOUND: 221136281Struckman case DZLINK: 2221558Srgrimes newcg->cg_cs.cs_ndir++; 223102411Scharnier /* FALLTHROUGH */ 2241558Srgrimes 2251558Srgrimes case FSTATE: 2261558Srgrimes case FCLEAR: 227136281Struckman case FZLINK: 2281558Srgrimes newcg->cg_cs.cs_nifree--; 2291558Srgrimes setbit(cg_inosused(newcg), i); 2301558Srgrimes break; 2311558Srgrimes 2321558Srgrimes default: 23374556Smckusick if (j < (int)ROOTINO) 2341558Srgrimes break; 23586514Siedowse errx(EEXIT, "BAD STATE %d FOR INODE I=%d", 23641474Sjulian inoinfo(j)->ino_state, j); 2371558Srgrimes } 2381558Srgrimes } 2391558Srgrimes if (c == 0) 24074556Smckusick for (i = 0; i < (int)ROOTINO; i++) { 2411558Srgrimes setbit(cg_inosused(newcg), i); 2421558Srgrimes newcg->cg_cs.cs_nifree--; 2431558Srgrimes } 2441558Srgrimes for (i = 0, d = dbase; 2451558Srgrimes d < dmax; 2461558Srgrimes d += fs->fs_frag, i += fs->fs_frag) { 2471558Srgrimes frags = 0; 2481558Srgrimes for (j = 0; j < fs->fs_frag; j++) { 2491558Srgrimes if (testbmap(d + j)) 2501558Srgrimes continue; 2511558Srgrimes setbit(cg_blksfree(newcg), i + j); 2521558Srgrimes frags++; 2531558Srgrimes } 2541558Srgrimes if (frags == fs->fs_frag) { 2551558Srgrimes newcg->cg_cs.cs_nbfree++; 2561558Srgrimes if (fs->fs_contigsumsize > 0) 2571558Srgrimes setbit(cg_clustersfree(newcg), 2581558Srgrimes i / fs->fs_frag); 2591558Srgrimes } else if (frags > 0) { 2601558Srgrimes newcg->cg_cs.cs_nffree += frags; 2611558Srgrimes blk = blkmap(fs, cg_blksfree(newcg), i); 2621558Srgrimes ffs_fragacct(fs, blk, newcg->cg_frsum, 1); 2631558Srgrimes } 2641558Srgrimes } 2651558Srgrimes if (fs->fs_contigsumsize > 0) { 26623675Speter int32_t *sump = cg_clustersum(newcg); 2671558Srgrimes u_char *mapp = cg_clustersfree(newcg); 2681558Srgrimes int map = *mapp++; 2691558Srgrimes int bit = 1; 2701558Srgrimes int run = 0; 2711558Srgrimes 2721558Srgrimes for (i = 0; i < newcg->cg_nclusterblks; i++) { 2731558Srgrimes if ((map & bit) != 0) { 2741558Srgrimes run++; 2751558Srgrimes } else if (run != 0) { 2761558Srgrimes if (run > fs->fs_contigsumsize) 2771558Srgrimes run = fs->fs_contigsumsize; 2781558Srgrimes sump[run]++; 2791558Srgrimes run = 0; 2801558Srgrimes } 281103949Smike if ((i & (CHAR_BIT - 1)) != (CHAR_BIT - 1)) { 2821558Srgrimes bit <<= 1; 2831558Srgrimes } else { 2841558Srgrimes map = *mapp++; 2851558Srgrimes bit = 1; 2861558Srgrimes } 2871558Srgrimes } 2881558Srgrimes if (run != 0) { 2891558Srgrimes if (run > fs->fs_contigsumsize) 2901558Srgrimes run = fs->fs_contigsumsize; 2911558Srgrimes sump[run]++; 2921558Srgrimes } 2931558Srgrimes } 2941558Srgrimes cstotal.cs_nffree += newcg->cg_cs.cs_nffree; 2951558Srgrimes cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree; 2961558Srgrimes cstotal.cs_nifree += newcg->cg_cs.cs_nifree; 2971558Srgrimes cstotal.cs_ndir += newcg->cg_cs.cs_ndir; 2981558Srgrimes cs = &fs->fs_cs(fs, c); 29974556Smckusick if (cursnapshot == 0 && 30074556Smckusick memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0 && 3011558Srgrimes dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { 30223675Speter memmove(cs, &newcg->cg_cs, sizeof *cs); 3031558Srgrimes sbdirty(); 3041558Srgrimes } 30596483Sphk if (rewritecg) { 30623675Speter memmove(cg, newcg, (size_t)fs->fs_cgsize); 3071558Srgrimes cgdirty(); 3081558Srgrimes continue; 3091558Srgrimes } 31074556Smckusick if (cursnapshot == 0 && 31198542Smckusick memcmp(newcg, cg, basesize) != 0 && 3121558Srgrimes dofix(&idesc[2], "SUMMARY INFORMATION BAD")) { 31323675Speter memmove(cg, newcg, (size_t)basesize); 3141558Srgrimes cgdirty(); 3151558Srgrimes } 31674556Smckusick if (bkgrdflag != 0 || usedsoftdep || debug) { 31774556Smckusick excessdirs = cg->cg_cs.cs_ndir - newcg->cg_cs.cs_ndir; 31874556Smckusick if (excessdirs < 0) { 31974556Smckusick pfatal("LOST %d DIRECTORIES\n", -excessdirs); 32074556Smckusick excessdirs = 0; 32162668Smckusick } 32274556Smckusick if (excessdirs > 0) 32374556Smckusick check_maps(cg_inosused(newcg), cg_inosused(cg), 324183820Skib inomapsize, 325183820Skib cg->cg_cgx * (ufs2_daddr_t) fs->fs_ipg, 326183820Skib "DIR", 32774556Smckusick freedirs, 0, excessdirs); 32874556Smckusick check_maps(cg_inosused(newcg), cg_inosused(cg), 329183820Skib inomapsize, 330183820Skib cg->cg_cgx * (ufs2_daddr_t) fs->fs_ipg, "FILE", 33174556Smckusick freefiles, excessdirs, fs->fs_ipg); 33274556Smckusick check_maps(cg_blksfree(cg), cg_blksfree(newcg), 333183820Skib blkmapsize, 334183820Skib cg->cg_cgx * (ufs2_daddr_t) fs->fs_fpg, "FRAG", 33574556Smckusick freeblks, 0, fs->fs_fpg); 33662668Smckusick } 33774556Smckusick if (cursnapshot == 0 && 33874556Smckusick memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0 && 33934266Sjulian dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) { 34034266Sjulian memmove(cg_inosused(cg), cg_inosused(newcg), 34134266Sjulian (size_t)mapsize); 34234266Sjulian cgdirty(); 34334266Sjulian } 3441558Srgrimes } 34574556Smckusick if (cursnapshot == 0 && 34698542Smckusick memcmp(&cstotal, &fs->fs_cstotal, sizeof cstotal) != 0 34798542Smckusick && dofix(&idesc[0], "SUMMARY BLK COUNT(S) WRONG IN SUPERBLK")) { 34898542Smckusick memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal); 3491558Srgrimes fs->fs_ronly = 0; 35041474Sjulian fs->fs_fmod = 0; 3511558Srgrimes sbdirty(); 3521558Srgrimes } 353142123Sdelphij 354142123Sdelphij /* 355142123Sdelphij * When doing background fsck on a snapshot, figure out whether 356142123Sdelphij * the superblock summary is inaccurate and correct it when 357142123Sdelphij * necessary. 358142123Sdelphij */ 359142123Sdelphij if (cursnapshot != 0) { 360142123Sdelphij cmd.size = 1; 361142123Sdelphij 362142123Sdelphij cmd.value = cstotal.cs_ndir - fs->fs_cstotal.cs_ndir; 363142123Sdelphij if (cmd.value != 0) { 364142123Sdelphij if (debug) 365142123Sdelphij printf("adjndir by %+" PRIi64 "\n", cmd.value); 366143235Sdelphij if (bkgrdsumadj == 0 || sysctl(adjndir, MIBSIZE, 0, 0, 367142123Sdelphij &cmd, sizeof cmd) == -1) 368142123Sdelphij rwerror("ADJUST NUMBER OF DIRECTORIES", cmd.value); 369142123Sdelphij } 370142123Sdelphij 371142123Sdelphij cmd.value = cstotal.cs_nbfree - fs->fs_cstotal.cs_nbfree; 372142123Sdelphij if (cmd.value != 0) { 373142123Sdelphij if (debug) 374142123Sdelphij printf("adjnbfree by %+" PRIi64 "\n", cmd.value); 375143235Sdelphij if (bkgrdsumadj == 0 || sysctl(adjnbfree, MIBSIZE, 0, 0, 376142123Sdelphij &cmd, sizeof cmd) == -1) 377142123Sdelphij rwerror("ADJUST NUMBER OF FREE BLOCKS", cmd.value); 378142123Sdelphij } 379142123Sdelphij 380142123Sdelphij cmd.value = cstotal.cs_nifree - fs->fs_cstotal.cs_nifree; 381142123Sdelphij if (cmd.value != 0) { 382142123Sdelphij if (debug) 383142123Sdelphij printf("adjnifree by %+" PRIi64 "\n", cmd.value); 384143235Sdelphij if (bkgrdsumadj == 0 || sysctl(adjnifree, MIBSIZE, 0, 0, 385142123Sdelphij &cmd, sizeof cmd) == -1) 386142123Sdelphij rwerror("ADJUST NUMBER OF FREE INODES", cmd.value); 387142123Sdelphij } 388142123Sdelphij 389142123Sdelphij cmd.value = cstotal.cs_nffree - fs->fs_cstotal.cs_nffree; 390142123Sdelphij if (cmd.value != 0) { 391142123Sdelphij if (debug) 392142123Sdelphij printf("adjnffree by %+" PRIi64 "\n", cmd.value); 393143235Sdelphij if (bkgrdsumadj == 0 || sysctl(adjnffree, MIBSIZE, 0, 0, 394142123Sdelphij &cmd, sizeof cmd) == -1) 395142123Sdelphij rwerror("ADJUST NUMBER OF FREE FRAGS", cmd.value); 396142123Sdelphij } 397142123Sdelphij 398142123Sdelphij cmd.value = cstotal.cs_numclusters - fs->fs_cstotal.cs_numclusters; 399142123Sdelphij if (cmd.value != 0) { 400142123Sdelphij if (debug) 401142123Sdelphij printf("adjnumclusters by %+" PRIi64 "\n", cmd.value); 402143235Sdelphij if (bkgrdsumadj == 0 || sysctl(adjnumclusters, MIBSIZE, 0, 0, 403142123Sdelphij &cmd, sizeof cmd) == -1) 404142123Sdelphij rwerror("ADJUST NUMBER OF FREE CLUSTERS", cmd.value); 405142123Sdelphij } 406142123Sdelphij } 4071558Srgrimes} 40874556Smckusick 40974556Smckusickstatic void 41092839Simpcheck_maps( 41192839Simp u_char *map1, /* map of claimed allocations */ 41292839Simp u_char *map2, /* map of determined allocations */ 41392839Simp int mapsize, /* size of above two maps */ 414183820Skib ufs2_daddr_t startvalue, /* resource value for first element in map */ 415100935Sphk const char *name, /* name of resource found in maps */ 41692839Simp int *opcode, /* sysctl opcode to free resource */ 41792839Simp int skip, /* number of entries to skip before starting to free */ 41892839Simp int limit) /* limit on number of entries to free */ 41974556Smckusick{ 42074556Smckusick# define BUFSIZE 16 42174556Smckusick char buf[BUFSIZE]; 422183820Skib long i, j, k, l, m, size; 423183820Skib ufs2_daddr_t n, astart, aend, ustart, uend; 42492839Simp void (*msg)(const char *fmt, ...); 42574556Smckusick 42675557Smckusick if (bkgrdflag) 42775557Smckusick msg = pfatal; 42875557Smckusick else 42975557Smckusick msg = pwarn; 43074556Smckusick astart = ustart = aend = uend = -1; 43174556Smckusick for (i = 0; i < mapsize; i++) { 43274556Smckusick j = *map1++; 43374556Smckusick k = *map2++; 43474556Smckusick if (j == k) 43574556Smckusick continue; 436103949Smike for (m = 0, l = 1; m < CHAR_BIT; m++, l <<= 1) { 43774556Smckusick if ((j & l) == (k & l)) 43874556Smckusick continue; 439103949Smike n = startvalue + i * CHAR_BIT + m; 44074556Smckusick if ((j & l) != 0) { 44174556Smckusick if (astart == -1) { 44274556Smckusick astart = aend = n; 44374556Smckusick continue; 44474556Smckusick } 44574556Smckusick if (aend + 1 == n) { 44674556Smckusick aend = n; 44774556Smckusick continue; 44874556Smckusick } 44974556Smckusick if (astart == aend) 450183820Skib (*msg)("ALLOCATED %s %" PRId64 451183820Skib " MARKED FREE\n", 45274556Smckusick name, astart); 45374556Smckusick else 454183820Skib (*msg)("%s %sS %" PRId64 "-%" PRId64 455183820Skib " MARKED FREE\n", 45674556Smckusick "ALLOCATED", name, astart, aend); 45774556Smckusick astart = aend = n; 45874556Smckusick } else { 45974556Smckusick if (ustart == -1) { 46074556Smckusick ustart = uend = n; 46174556Smckusick continue; 46274556Smckusick } 46374556Smckusick if (uend + 1 == n) { 46474556Smckusick uend = n; 46574556Smckusick continue; 46674556Smckusick } 46774556Smckusick size = uend - ustart + 1; 46874556Smckusick if (size <= skip) { 46974556Smckusick skip -= size; 47074556Smckusick ustart = uend = n; 47174556Smckusick continue; 47274556Smckusick } 47374556Smckusick if (skip > 0) { 47474556Smckusick ustart += skip; 47574556Smckusick size -= skip; 47674556Smckusick skip = 0; 47774556Smckusick } 47874556Smckusick if (size > limit) 47974556Smckusick size = limit; 48074556Smckusick if (debug && size == 1) 481183820Skib pwarn("%s %s %" PRId64 482183820Skib " MARKED USED\n", 48374556Smckusick "UNALLOCATED", name, ustart); 48474556Smckusick else if (debug) 485183820Skib pwarn("%s %sS %" PRId64 "-%" PRId64 486183820Skib " MARKED USED\n", 48774556Smckusick "UNALLOCATED", name, ustart, 48874556Smckusick ustart + size - 1); 48974556Smckusick if (bkgrdflag != 0) { 49074556Smckusick cmd.value = ustart; 49174556Smckusick cmd.size = size; 49274556Smckusick if (sysctl(opcode, MIBSIZE, 0, 0, 49374556Smckusick &cmd, sizeof cmd) == -1) { 49474556Smckusick snprintf(buf, BUFSIZE, 49574556Smckusick "FREE %s", name); 49674556Smckusick rwerror(buf, cmd.value); 49774556Smckusick } 49874556Smckusick } 49974556Smckusick limit -= size; 50074556Smckusick if (limit <= 0) 50174556Smckusick return; 50274556Smckusick ustart = uend = n; 50374556Smckusick } 50474556Smckusick } 50574556Smckusick } 50686514Siedowse if (astart != -1) { 50774556Smckusick if (astart == aend) 508183820Skib (*msg)("ALLOCATED %s %" PRId64 509183820Skib " MARKED FREE\n", name, astart); 51074556Smckusick else 511183820Skib (*msg)("ALLOCATED %sS %" PRId64 "-%" PRId64 512183820Skib " MARKED FREE\n", 51374556Smckusick name, astart, aend); 51486514Siedowse } 51574556Smckusick if (ustart != -1) { 51674556Smckusick size = uend - ustart + 1; 51774556Smckusick if (size <= skip) 51874556Smckusick return; 51974556Smckusick if (skip > 0) { 52074556Smckusick ustart += skip; 52174556Smckusick size -= skip; 52274556Smckusick } 52374556Smckusick if (size > limit) 52474556Smckusick size = limit; 52574556Smckusick if (debug) { 52674556Smckusick if (size == 1) 527183820Skib pwarn("UNALLOCATED %s %" PRId64 528183820Skib " MARKED USED\n", 52974556Smckusick name, ustart); 53074556Smckusick else 531183820Skib pwarn("UNALLOCATED %sS %" PRId64 "-%" PRId64 532183820Skib " MARKED USED\n", 53374556Smckusick name, ustart, ustart + size - 1); 53474556Smckusick } 53574556Smckusick if (bkgrdflag != 0) { 53674556Smckusick cmd.value = ustart; 53774556Smckusick cmd.size = size; 53874556Smckusick if (sysctl(opcode, MIBSIZE, 0, 0, &cmd, 53974556Smckusick sizeof cmd) == -1) { 54074556Smckusick snprintf(buf, BUFSIZE, "FREE %s", name); 54174556Smckusick rwerror(buf, cmd.value); 54274556Smckusick } 54374556Smckusick } 54474556Smckusick } 54574556Smckusick} 546