18871Srgrimes/* 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 30114589Sobrien#if 0 311558Srgrimes#ifndef lint 3223675Speterstatic const char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95"; 33114589Sobrien#endif /* not lint */ 3441477Sjulian#endif 35114589Sobrien#include <sys/cdefs.h> 36114589Sobrien__FBSDID("$FreeBSD$"); 371558Srgrimes 381558Srgrimes#include <sys/param.h> 3962668Smckusick#include <sys/stat.h> 4074556Smckusick#include <sys/sysctl.h> 4123675Speter 421558Srgrimes#include <ufs/ufs/dinode.h> 431558Srgrimes#include <ufs/ufs/dir.h> 441558Srgrimes#include <ufs/ffs/fs.h> 4523675Speter 4623675Speter#include <err.h> 47103949Smike#include <limits.h> 48101037Smux#include <stdint.h> 491558Srgrimes#include <string.h> 5023675Speter 511558Srgrimes#include "fsck.h" 521558Srgrimes 5398542Smckusickstatic ufs2_daddr_t badblk; 5498542Smckusickstatic ufs2_daddr_t dupblk; 5541474Sjulianstatic ino_t lastino; /* last inode in use */ 561558Srgrimes 57188110Smckusickstatic int checkinode(ino_t inumber, struct inodesc *, int rebuildcg); 587585Sbde 597585Sbdevoid 6092839Simppass1(void) 611558Srgrimes{ 6241474Sjulian struct inostat *info; 631558Srgrimes struct inodesc idesc; 64249788Smckusick struct bufarea *cgbp; 65249788Smckusick struct cg *cgp; 66188110Smckusick ino_t inumber, inosused, mininos; 6798542Smckusick ufs2_daddr_t i, cgd; 6898542Smckusick u_int8_t *cp; 69188110Smckusick int c, rebuildcg; 701558Srgrimes 711558Srgrimes /* 72102231Strhodes * Set file system reserved blocks in used block map. 731558Srgrimes */ 741558Srgrimes for (c = 0; c < sblock.fs_ncg; c++) { 751558Srgrimes cgd = cgdmin(&sblock, c); 761558Srgrimes if (c == 0) { 771558Srgrimes i = cgbase(&sblock, c); 781558Srgrimes } else 791558Srgrimes i = cgsblock(&sblock, c); 801558Srgrimes for (; i < cgd; i++) 811558Srgrimes setbmap(i); 821558Srgrimes } 8369800Stomsoft i = sblock.fs_csaddr; 8469800Stomsoft cgd = i + howmany(sblock.fs_cssize, sblock.fs_fsize); 8569800Stomsoft for (; i < cgd; i++) 8669800Stomsoft setbmap(i); 8769800Stomsoft 881558Srgrimes /* 891558Srgrimes * Find all allocated blocks. 901558Srgrimes */ 9123675Speter memset(&idesc, 0, sizeof(struct inodesc)); 921558Srgrimes idesc.id_func = pass1check; 931558Srgrimes n_files = n_blks = 0; 941558Srgrimes for (c = 0; c < sblock.fs_ncg; c++) { 9541474Sjulian inumber = c * sblock.fs_ipg; 9641474Sjulian setinodebuf(inumber); 97249788Smckusick cgbp = cgget(c); 98249788Smckusick cgp = cgbp->b_un.b_cg; 99188110Smckusick rebuildcg = 0; 100249788Smckusick if (!check_cgmagic(c, cgbp)) 101188110Smckusick rebuildcg = 1; 102188110Smckusick if (!rebuildcg && sblock.fs_magic == FS_UFS2_MAGIC) { 103249788Smckusick inosused = cgp->cg_initediblk; 104201708Smckusick if (inosused > sblock.fs_ipg) { 105201708Smckusick pfatal("%s (%d > %d) %s %d\nReset to %d\n", 106201708Smckusick "Too many initialized inodes", inosused, 107201708Smckusick sblock.fs_ipg, "in cylinder group", c, 108201708Smckusick sblock.fs_ipg); 109176575Sdelphij inosused = sblock.fs_ipg; 110201708Smckusick } 111201708Smckusick } else { 11298542Smckusick inosused = sblock.fs_ipg; 113201708Smckusick } 11470050Siedowse if (got_siginfo) { 11570050Siedowse printf("%s: phase 1: cyl group %d of %d (%d%%)\n", 11670050Siedowse cdevname, c, sblock.fs_ncg, 11770050Siedowse c * 100 / sblock.fs_ncg); 11870050Siedowse got_siginfo = 0; 11970050Siedowse } 120126345Sscottl if (got_sigalarm) { 121126345Sscottl setproctitle("%s p1 %d%%", cdevname, 122126345Sscottl c * 100 / sblock.fs_ncg); 123126345Sscottl got_sigalarm = 0; 124126345Sscottl } 12541474Sjulian /* 12641474Sjulian * If we are using soft updates, then we can trust the 12741474Sjulian * cylinder group inode allocation maps to tell us which 12841474Sjulian * inodes are allocated. We will scan the used inode map 12941474Sjulian * to find the inodes that are really in use, and then 13041474Sjulian * read only those inodes in from disk. 13141474Sjulian */ 132188110Smckusick if ((preen || inoopt) && usedsoftdep && !rebuildcg) { 133249788Smckusick cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT]; 134103949Smike for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) { 13541474Sjulian if (*cp == 0) 13641474Sjulian continue; 137103949Smike for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) { 13841474Sjulian if (*cp & i) 13941474Sjulian break; 14041474Sjulian inosused--; 14141474Sjulian } 14241474Sjulian break; 14341474Sjulian } 14441474Sjulian if (inosused < 0) 14541474Sjulian inosused = 0; 14641474Sjulian } 14741474Sjulian /* 14841474Sjulian * Allocate inoinfo structures for the allocated inodes. 14941474Sjulian */ 15041474Sjulian inostathead[c].il_numalloced = inosused; 15141474Sjulian if (inosused == 0) { 15241474Sjulian inostathead[c].il_stat = 0; 15341474Sjulian continue; 15441474Sjulian } 155249788Smckusick info = Calloc((unsigned)inosused, sizeof(struct inostat)); 15641474Sjulian if (info == NULL) 157125036Scperciva errx(EEXIT, "cannot alloc %u bytes for inoinfo", 15841474Sjulian (unsigned)(sizeof(struct inostat) * inosused)); 15941474Sjulian inostathead[c].il_stat = info; 16041474Sjulian /* 16141474Sjulian * Scan the allocated inodes. 16241474Sjulian */ 16341474Sjulian for (i = 0; i < inosused; i++, inumber++) { 16441474Sjulian if (inumber < ROOTINO) { 165188110Smckusick (void)getnextinode(inumber, rebuildcg); 1661558Srgrimes continue; 16741474Sjulian } 168188110Smckusick /* 169188110Smckusick * NULL return indicates probable end of allocated 170188110Smckusick * inodes during cylinder group rebuild attempt. 171188110Smckusick * We always keep trying until we get to the minimum 172188110Smckusick * valid number for this cylinder group. 173188110Smckusick */ 174188110Smckusick if (checkinode(inumber, &idesc, rebuildcg) == 0 && 175249788Smckusick i > cgp->cg_initediblk) 176188110Smckusick break; 1771558Srgrimes } 178188110Smckusick /* 179188110Smckusick * This optimization speeds up future runs of fsck 180188110Smckusick * by trimming down the number of inodes in cylinder 181188110Smckusick * groups that formerly had many inodes but now have 182188110Smckusick * fewer in use. 183188110Smckusick */ 184188110Smckusick mininos = roundup(inosused + INOPB(&sblock), INOPB(&sblock)); 185188110Smckusick if (inoopt && !preen && !rebuildcg && 186188110Smckusick sblock.fs_magic == FS_UFS2_MAGIC && 187249788Smckusick cgp->cg_initediblk > 2 * INOPB(&sblock) && 188249788Smckusick mininos < cgp->cg_initediblk) { 189249788Smckusick i = cgp->cg_initediblk; 190188110Smckusick if (mininos < 2 * INOPB(&sblock)) 191249788Smckusick cgp->cg_initediblk = 2 * INOPB(&sblock); 192188110Smckusick else 193249788Smckusick cgp->cg_initediblk = mininos; 194188110Smckusick pwarn("CYLINDER GROUP %d: RESET FROM %ju TO %d %s\n", 195249788Smckusick c, i, cgp->cg_initediblk, "VALID INODES"); 196249788Smckusick dirty(cgbp); 197188110Smckusick } 198188110Smckusick if (inosused < sblock.fs_ipg) 199188110Smckusick continue; 20041474Sjulian lastino += 1; 201188110Smckusick if (lastino < (c * sblock.fs_ipg)) 202188110Smckusick inosused = 0; 203188110Smckusick else 204188110Smckusick inosused = lastino - (c * sblock.fs_ipg); 205249788Smckusick if (rebuildcg && inosused > cgp->cg_initediblk && 206188110Smckusick sblock.fs_magic == FS_UFS2_MAGIC) { 207249788Smckusick cgp->cg_initediblk = roundup(inosused, INOPB(&sblock)); 208188110Smckusick pwarn("CYLINDER GROUP %d: FOUND %d VALID INODES\n", c, 209249788Smckusick cgp->cg_initediblk); 210188110Smckusick } 21141474Sjulian /* 21241474Sjulian * If we were not able to determine in advance which inodes 21341474Sjulian * were in use, then reduce the size of the inoinfo structure 21441474Sjulian * to the size necessary to describe the inodes that we 21541474Sjulian * really found. 21641474Sjulian */ 217188110Smckusick if (inumber == lastino) 218188110Smckusick continue; 21941474Sjulian inostathead[c].il_numalloced = inosused; 22041474Sjulian if (inosused == 0) { 22141474Sjulian free(inostathead[c].il_stat); 22241474Sjulian inostathead[c].il_stat = 0; 22341474Sjulian continue; 22441474Sjulian } 225249788Smckusick info = Calloc((unsigned)inosused, sizeof(struct inostat)); 22641474Sjulian if (info == NULL) 227125036Scperciva errx(EEXIT, "cannot alloc %u bytes for inoinfo", 22841474Sjulian (unsigned)(sizeof(struct inostat) * inosused)); 22941474Sjulian memmove(info, inostathead[c].il_stat, inosused * sizeof(*info)); 23041474Sjulian free(inostathead[c].il_stat); 23141474Sjulian inostathead[c].il_stat = info; 2321558Srgrimes } 2331558Srgrimes freeinodebuf(); 2341558Srgrimes} 2351558Srgrimes 236188110Smckusickstatic int 237188110Smckusickcheckinode(ino_t inumber, struct inodesc *idesc, int rebuildcg) 2381558Srgrimes{ 23998542Smckusick union dinode *dp; 24098542Smckusick off_t kernmaxfilesize; 24198542Smckusick ufs2_daddr_t ndb; 2421558Srgrimes mode_t mode; 243103885Smckusick int j, ret, offset; 2441558Srgrimes 245188110Smckusick if ((dp = getnextinode(inumber, rebuildcg)) == NULL) 246188110Smckusick return (0); 24798542Smckusick mode = DIP(dp, di_mode) & IFMT; 2481558Srgrimes if (mode == 0) { 24998542Smckusick if ((sblock.fs_magic == FS_UFS1_MAGIC && 25098542Smckusick (memcmp(dp->dp1.di_db, ufs1_zino.di_db, 25198542Smckusick NDADDR * sizeof(ufs1_daddr_t)) || 25298542Smckusick memcmp(dp->dp1.di_ib, ufs1_zino.di_ib, 25398542Smckusick NIADDR * sizeof(ufs1_daddr_t)) || 25498542Smckusick dp->dp1.di_mode || dp->dp1.di_size)) || 25598542Smckusick (sblock.fs_magic == FS_UFS2_MAGIC && 25698542Smckusick (memcmp(dp->dp2.di_db, ufs2_zino.di_db, 25798542Smckusick NDADDR * sizeof(ufs2_daddr_t)) || 25898542Smckusick memcmp(dp->dp2.di_ib, ufs2_zino.di_ib, 25998542Smckusick NIADDR * sizeof(ufs2_daddr_t)) || 26098542Smckusick dp->dp2.di_mode || dp->dp2.di_size))) { 26186514Siedowse pfatal("PARTIALLY ALLOCATED INODE I=%lu", 26286514Siedowse (u_long)inumber); 2631558Srgrimes if (reply("CLEAR") == 1) { 2641558Srgrimes dp = ginode(inumber); 2651558Srgrimes clearinode(dp); 2661558Srgrimes inodirty(); 2671558Srgrimes } 2681558Srgrimes } 26941474Sjulian inoinfo(inumber)->ino_state = USTATE; 270188110Smckusick return (1); 2711558Srgrimes } 2721558Srgrimes lastino = inumber; 27371884Siedowse /* This should match the file size limit in ffs_mountfs(). */ 27498888Siedowse if (sblock.fs_magic == FS_UFS1_MAGIC) 27598888Siedowse kernmaxfilesize = (off_t)0x40000000 * sblock.fs_bsize - 1; 27698888Siedowse else 27798888Siedowse kernmaxfilesize = sblock.fs_maxfilesize; 27898542Smckusick if (DIP(dp, di_size) > kernmaxfilesize || 27998542Smckusick DIP(dp, di_size) > sblock.fs_maxfilesize || 28098542Smckusick (mode == IFDIR && DIP(dp, di_size) > MAXDIRSIZE)) { 2811558Srgrimes if (debug) 282101037Smux printf("bad size %ju:", (uintmax_t)DIP(dp, di_size)); 2831558Srgrimes goto unknown; 2841558Srgrimes } 2851558Srgrimes if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { 2861558Srgrimes dp = ginode(inumber); 287134589Sscottl DIP_SET(dp, di_size, sblock.fs_fsize); 288134589Sscottl DIP_SET(dp, di_mode, IFREG|0600); 2891558Srgrimes inodirty(); 2901558Srgrimes } 29163003Smckusick if ((mode == IFBLK || mode == IFCHR || mode == IFIFO || 29298542Smckusick mode == IFSOCK) && DIP(dp, di_size) != 0) { 29363003Smckusick if (debug) 294101037Smux printf("bad special-file size %ju:", 295101037Smux (uintmax_t)DIP(dp, di_size)); 29663003Smckusick goto unknown; 29763003Smckusick } 29898542Smckusick if ((mode == IFBLK || mode == IFCHR) && 29998542Smckusick (dev_t)DIP(dp, di_rdev) == NODEV) { 30072525Stegge if (debug) 30172525Stegge printf("bad special-file rdev NODEV:"); 30272525Stegge goto unknown; 30372525Stegge } 30498542Smckusick ndb = howmany(DIP(dp, di_size), sblock.fs_bsize); 3051558Srgrimes if (ndb < 0) { 3061558Srgrimes if (debug) 307101037Smux printf("bad size %ju ndb %ju:", 308101037Smux (uintmax_t)DIP(dp, di_size), (uintmax_t)ndb); 3091558Srgrimes goto unknown; 3101558Srgrimes } 3111558Srgrimes if (mode == IFBLK || mode == IFCHR) 3121558Srgrimes ndb++; 3131558Srgrimes if (mode == IFLNK) { 3141558Srgrimes /* 3151558Srgrimes * Fake ndb value so direct/indirect block checks below 3161558Srgrimes * will detect any garbage after symlink string. 3171558Srgrimes */ 31898542Smckusick if (DIP(dp, di_size) < (off_t)sblock.fs_maxsymlinklen) { 31998542Smckusick if (sblock.fs_magic == FS_UFS1_MAGIC) 32098542Smckusick ndb = howmany(DIP(dp, di_size), 32198542Smckusick sizeof(ufs1_daddr_t)); 32298542Smckusick else 32398542Smckusick ndb = howmany(DIP(dp, di_size), 32498542Smckusick sizeof(ufs2_daddr_t)); 3251558Srgrimes if (ndb > NDADDR) { 3261558Srgrimes j = ndb - NDADDR; 3271558Srgrimes for (ndb = 1; j > 1; j--) 3281558Srgrimes ndb *= NINDIR(&sblock); 3291558Srgrimes ndb += NDADDR; 3301558Srgrimes } 3311558Srgrimes } 3321558Srgrimes } 33398879Siedowse for (j = ndb; ndb < NDADDR && j < NDADDR; j++) 33498542Smckusick if (DIP(dp, di_db[j]) != 0) { 3351558Srgrimes if (debug) 336101037Smux printf("bad direct addr[%d]: %ju\n", j, 337101037Smux (uintmax_t)DIP(dp, di_db[j])); 3381558Srgrimes goto unknown; 3391558Srgrimes } 3401558Srgrimes for (j = 0, ndb -= NDADDR; ndb > 0; j++) 3411558Srgrimes ndb /= NINDIR(&sblock); 3421558Srgrimes for (; j < NIADDR; j++) 34398542Smckusick if (DIP(dp, di_ib[j]) != 0) { 3441558Srgrimes if (debug) 345101037Smux printf("bad indirect addr: %ju\n", 346101037Smux (uintmax_t)DIP(dp, di_ib[j])); 3471558Srgrimes goto unknown; 3481558Srgrimes } 3491558Srgrimes if (ftypeok(dp) == 0) 3501558Srgrimes goto unknown; 3511558Srgrimes n_files++; 35298542Smckusick inoinfo(inumber)->ino_linkcnt = DIP(dp, di_nlink); 3531558Srgrimes if (mode == IFDIR) { 35498542Smckusick if (DIP(dp, di_size) == 0) 35541474Sjulian inoinfo(inumber)->ino_state = DCLEAR; 356136281Struckman else if (DIP(dp, di_nlink) <= 0) 357136281Struckman inoinfo(inumber)->ino_state = DZLINK; 3581558Srgrimes else 35941474Sjulian inoinfo(inumber)->ino_state = DSTATE; 3601558Srgrimes cacheino(dp, inumber); 36141474Sjulian countdirs++; 362136281Struckman } else if (DIP(dp, di_nlink) <= 0) 363136281Struckman inoinfo(inumber)->ino_state = FZLINK; 364136281Struckman else 36541474Sjulian inoinfo(inumber)->ino_state = FSTATE; 36641474Sjulian inoinfo(inumber)->ino_type = IFTODT(mode); 3671558Srgrimes badblk = dupblk = 0; 3681558Srgrimes idesc->id_number = inumber; 36998542Smckusick if (DIP(dp, di_flags) & SF_SNAPSHOT) 37062668Smckusick idesc->id_type = SNAP; 37162668Smckusick else 37262668Smckusick idesc->id_type = ADDR; 3731558Srgrimes (void)ckinode(dp, idesc); 374103885Smckusick if (sblock.fs_magic == FS_UFS2_MAGIC && dp->dp2.di_extsize > 0) { 375103885Smckusick idesc->id_type = ADDR; 376103885Smckusick ndb = howmany(dp->dp2.di_extsize, sblock.fs_bsize); 377103885Smckusick for (j = 0; j < NXADDR; j++) { 378103885Smckusick if (--ndb == 0 && 379103885Smckusick (offset = blkoff(&sblock, dp->dp2.di_extsize)) != 0) 380103885Smckusick idesc->id_numfrags = numfrags(&sblock, 381103885Smckusick fragroundup(&sblock, offset)); 382103885Smckusick else 383103885Smckusick idesc->id_numfrags = sblock.fs_frag; 384103885Smckusick if (dp->dp2.di_extb[j] == 0) 385103885Smckusick continue; 386103885Smckusick idesc->id_blkno = dp->dp2.di_extb[j]; 387103885Smckusick ret = (*idesc->id_func)(idesc); 388103885Smckusick if (ret & STOP) 389103885Smckusick break; 390103885Smckusick } 391103885Smckusick } 392103398Sphk if (sblock.fs_magic == FS_UFS2_MAGIC) 393103398Sphk eascan(idesc, &dp->dp2); 3941558Srgrimes idesc->id_entryno *= btodb(sblock.fs_fsize); 39598542Smckusick if (DIP(dp, di_blocks) != idesc->id_entryno) { 396101037Smux pwarn("INCORRECT BLOCK COUNT I=%lu (%ju should be %ju)", 397101037Smux (u_long)inumber, (uintmax_t)DIP(dp, di_blocks), 398101037Smux (uintmax_t)idesc->id_entryno); 3991558Srgrimes if (preen) 4001558Srgrimes printf(" (CORRECTED)\n"); 4011558Srgrimes else if (reply("CORRECT") == 0) 402188110Smckusick return (1); 40374556Smckusick if (bkgrdflag == 0) { 40474556Smckusick dp = ginode(inumber); 405134589Sscottl DIP_SET(dp, di_blocks, idesc->id_entryno); 40674556Smckusick inodirty(); 40774556Smckusick } else { 40874556Smckusick cmd.value = idesc->id_number; 40998542Smckusick cmd.size = idesc->id_entryno - DIP(dp, di_blocks); 41074556Smckusick if (debug) 411101037Smux printf("adjblkcnt ino %ju amount %lld\n", 412101037Smux (uintmax_t)cmd.value, (long long)cmd.size); 41374556Smckusick if (sysctl(adjblkcnt, MIBSIZE, 0, 0, 41474556Smckusick &cmd, sizeof cmd) == -1) 41574556Smckusick rwerror("ADJUST INODE BLOCK COUNT", cmd.value); 41674556Smckusick } 4171558Srgrimes } 418188110Smckusick return (1); 4191558Srgrimesunknown: 42086514Siedowse pfatal("UNKNOWN FILE TYPE I=%lu", (u_long)inumber); 42141474Sjulian inoinfo(inumber)->ino_state = FCLEAR; 4221558Srgrimes if (reply("CLEAR") == 1) { 42341474Sjulian inoinfo(inumber)->ino_state = USTATE; 4241558Srgrimes dp = ginode(inumber); 4251558Srgrimes clearinode(dp); 4261558Srgrimes inodirty(); 4271558Srgrimes } 428188110Smckusick return (1); 4291558Srgrimes} 4301558Srgrimes 4317585Sbdeint 43292839Simppass1check(struct inodesc *idesc) 4331558Srgrimes{ 4341558Srgrimes int res = KEEPON; 4351558Srgrimes int anyout, nfrags; 43698542Smckusick ufs2_daddr_t blkno = idesc->id_blkno; 43792806Sobrien struct dups *dlp; 4381558Srgrimes struct dups *new; 4391558Srgrimes 44062668Smckusick if (idesc->id_type == SNAP) { 44162668Smckusick if (blkno == BLK_NOCOPY) 44262668Smckusick return (KEEPON); 44362668Smckusick if (idesc->id_number == cursnapshot) { 44462668Smckusick if (blkno == blkstofrags(&sblock, idesc->id_lbn)) 44562668Smckusick return (KEEPON); 44662668Smckusick if (blkno == BLK_SNAP) { 44762668Smckusick blkno = blkstofrags(&sblock, idesc->id_lbn); 44862668Smckusick idesc->id_entryno -= idesc->id_numfrags; 44962668Smckusick } 45062668Smckusick } else { 45162668Smckusick if (blkno == BLK_SNAP) 45262668Smckusick return (KEEPON); 45362668Smckusick } 45462668Smckusick } 4551558Srgrimes if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { 4561558Srgrimes blkerror(idesc->id_number, "BAD", blkno); 4571558Srgrimes if (badblk++ >= MAXBAD) { 4581558Srgrimes pwarn("EXCESSIVE BAD BLKS I=%lu", 45986514Siedowse (u_long)idesc->id_number); 4601558Srgrimes if (preen) 4611558Srgrimes printf(" (SKIPPING)\n"); 46234266Sjulian else if (reply("CONTINUE") == 0) { 46334266Sjulian ckfini(0); 46423675Speter exit(EEXIT); 46534266Sjulian } 4661558Srgrimes return (STOP); 4671558Srgrimes } 4681558Srgrimes } 4691558Srgrimes for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 4701558Srgrimes if (anyout && chkrange(blkno, 1)) { 4711558Srgrimes res = SKIP; 4721558Srgrimes } else if (!testbmap(blkno)) { 4731558Srgrimes n_blks++; 4741558Srgrimes setbmap(blkno); 4751558Srgrimes } else { 4761558Srgrimes blkerror(idesc->id_number, "DUP", blkno); 4771558Srgrimes if (dupblk++ >= MAXDUP) { 4781558Srgrimes pwarn("EXCESSIVE DUP BLKS I=%lu", 47986514Siedowse (u_long)idesc->id_number); 4801558Srgrimes if (preen) 4811558Srgrimes printf(" (SKIPPING)\n"); 48234266Sjulian else if (reply("CONTINUE") == 0) { 48334266Sjulian ckfini(0); 48423675Speter exit(EEXIT); 48534266Sjulian } 4861558Srgrimes return (STOP); 4871558Srgrimes } 488249788Smckusick new = (struct dups *)Malloc(sizeof(struct dups)); 4891558Srgrimes if (new == NULL) { 4901558Srgrimes pfatal("DUP TABLE OVERFLOW."); 49134266Sjulian if (reply("CONTINUE") == 0) { 49234266Sjulian ckfini(0); 49323675Speter exit(EEXIT); 49434266Sjulian } 4951558Srgrimes return (STOP); 4961558Srgrimes } 4971558Srgrimes new->dup = blkno; 4981558Srgrimes if (muldup == 0) { 4991558Srgrimes duplist = muldup = new; 5001558Srgrimes new->next = 0; 5011558Srgrimes } else { 5021558Srgrimes new->next = muldup->next; 5031558Srgrimes muldup->next = new; 5041558Srgrimes } 5051558Srgrimes for (dlp = duplist; dlp != muldup; dlp = dlp->next) 5061558Srgrimes if (dlp->dup == blkno) 5071558Srgrimes break; 5081558Srgrimes if (dlp == muldup && dlp->dup != blkno) 5091558Srgrimes muldup = new; 5101558Srgrimes } 5111558Srgrimes /* 5121558Srgrimes * count the number of blocks found in id_entryno 5131558Srgrimes */ 5141558Srgrimes idesc->id_entryno++; 5151558Srgrimes } 5161558Srgrimes return (res); 5171558Srgrimes} 518