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: releng/10.2/sbin/fsck_ffs/pass1.c 260178 2014-01-02 01:44:14Z scottl $"); 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; 64248658Smckusick struct bufarea *cgbp; 65248658Smckusick 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 71260178Sscottl badblk = dupblk = lastino = 0; 72260178Sscottl 731558Srgrimes /* 74102231Strhodes * Set file system reserved blocks in used block map. 751558Srgrimes */ 761558Srgrimes for (c = 0; c < sblock.fs_ncg; c++) { 771558Srgrimes cgd = cgdmin(&sblock, c); 781558Srgrimes if (c == 0) { 791558Srgrimes i = cgbase(&sblock, c); 801558Srgrimes } else 811558Srgrimes i = cgsblock(&sblock, c); 821558Srgrimes for (; i < cgd; i++) 831558Srgrimes setbmap(i); 841558Srgrimes } 8569800Stomsoft i = sblock.fs_csaddr; 8669800Stomsoft cgd = i + howmany(sblock.fs_cssize, sblock.fs_fsize); 8769800Stomsoft for (; i < cgd; i++) 8869800Stomsoft setbmap(i); 8969800Stomsoft 901558Srgrimes /* 911558Srgrimes * Find all allocated blocks. 921558Srgrimes */ 9323675Speter memset(&idesc, 0, sizeof(struct inodesc)); 941558Srgrimes idesc.id_func = pass1check; 951558Srgrimes n_files = n_blks = 0; 961558Srgrimes for (c = 0; c < sblock.fs_ncg; c++) { 9741474Sjulian inumber = c * sblock.fs_ipg; 9841474Sjulian setinodebuf(inumber); 99248658Smckusick cgbp = cgget(c); 100248658Smckusick cgp = cgbp->b_un.b_cg; 101188110Smckusick rebuildcg = 0; 102248658Smckusick if (!check_cgmagic(c, cgbp)) 103188110Smckusick rebuildcg = 1; 104188110Smckusick if (!rebuildcg && sblock.fs_magic == FS_UFS2_MAGIC) { 105248658Smckusick inosused = cgp->cg_initediblk; 106201708Smckusick if (inosused > sblock.fs_ipg) { 107241035Smdf pfatal( 108241035Smdf"Too many initialized inodes (%ju > %d) in cylinder group %d\nReset to %d\n", 109241012Smdf (uintmax_t)inosused, 110241035Smdf sblock.fs_ipg, c, sblock.fs_ipg); 111176575Sdelphij inosused = sblock.fs_ipg; 112201708Smckusick } 113201708Smckusick } else { 11498542Smckusick inosused = sblock.fs_ipg; 115201708Smckusick } 11670050Siedowse if (got_siginfo) { 11770050Siedowse printf("%s: phase 1: cyl group %d of %d (%d%%)\n", 11870050Siedowse cdevname, c, sblock.fs_ncg, 11970050Siedowse c * 100 / sblock.fs_ncg); 12070050Siedowse got_siginfo = 0; 12170050Siedowse } 122126345Sscottl if (got_sigalarm) { 123126345Sscottl setproctitle("%s p1 %d%%", cdevname, 124126345Sscottl c * 100 / sblock.fs_ncg); 125126345Sscottl got_sigalarm = 0; 126126345Sscottl } 12741474Sjulian /* 12841474Sjulian * If we are using soft updates, then we can trust the 12941474Sjulian * cylinder group inode allocation maps to tell us which 13041474Sjulian * inodes are allocated. We will scan the used inode map 13141474Sjulian * to find the inodes that are really in use, and then 13241474Sjulian * read only those inodes in from disk. 13341474Sjulian */ 134188110Smckusick if ((preen || inoopt) && usedsoftdep && !rebuildcg) { 135248658Smckusick cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT]; 136103949Smike for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) { 13741474Sjulian if (*cp == 0) 13841474Sjulian continue; 139103949Smike for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) { 14041474Sjulian if (*cp & i) 14141474Sjulian break; 14241474Sjulian inosused--; 14341474Sjulian } 14441474Sjulian break; 14541474Sjulian } 14641474Sjulian if (inosused < 0) 14741474Sjulian inosused = 0; 14841474Sjulian } 14941474Sjulian /* 15041474Sjulian * Allocate inoinfo structures for the allocated inodes. 15141474Sjulian */ 15241474Sjulian inostathead[c].il_numalloced = inosused; 15341474Sjulian if (inosused == 0) { 15441474Sjulian inostathead[c].il_stat = 0; 15541474Sjulian continue; 15641474Sjulian } 157248658Smckusick info = Calloc((unsigned)inosused, sizeof(struct inostat)); 15841474Sjulian if (info == NULL) 159125036Scperciva errx(EEXIT, "cannot alloc %u bytes for inoinfo", 16041474Sjulian (unsigned)(sizeof(struct inostat) * inosused)); 16141474Sjulian inostathead[c].il_stat = info; 16241474Sjulian /* 16341474Sjulian * Scan the allocated inodes. 16441474Sjulian */ 16541474Sjulian for (i = 0; i < inosused; i++, inumber++) { 16641474Sjulian if (inumber < ROOTINO) { 167188110Smckusick (void)getnextinode(inumber, rebuildcg); 1681558Srgrimes continue; 16941474Sjulian } 170188110Smckusick /* 171188110Smckusick * NULL return indicates probable end of allocated 172188110Smckusick * inodes during cylinder group rebuild attempt. 173188110Smckusick * We always keep trying until we get to the minimum 174188110Smckusick * valid number for this cylinder group. 175188110Smckusick */ 176188110Smckusick if (checkinode(inumber, &idesc, rebuildcg) == 0 && 177248658Smckusick i > cgp->cg_initediblk) 178188110Smckusick break; 1791558Srgrimes } 180188110Smckusick /* 181188110Smckusick * This optimization speeds up future runs of fsck 182188110Smckusick * by trimming down the number of inodes in cylinder 183188110Smckusick * groups that formerly had many inodes but now have 184188110Smckusick * fewer in use. 185188110Smckusick */ 186188110Smckusick mininos = roundup(inosused + INOPB(&sblock), INOPB(&sblock)); 187188110Smckusick if (inoopt && !preen && !rebuildcg && 188188110Smckusick sblock.fs_magic == FS_UFS2_MAGIC && 189248658Smckusick cgp->cg_initediblk > 2 * INOPB(&sblock) && 190248658Smckusick mininos < cgp->cg_initediblk) { 191248658Smckusick i = cgp->cg_initediblk; 192188110Smckusick if (mininos < 2 * INOPB(&sblock)) 193248658Smckusick cgp->cg_initediblk = 2 * INOPB(&sblock); 194188110Smckusick else 195248658Smckusick cgp->cg_initediblk = mininos; 196188110Smckusick pwarn("CYLINDER GROUP %d: RESET FROM %ju TO %d %s\n", 197248658Smckusick c, i, cgp->cg_initediblk, "VALID INODES"); 198248658Smckusick dirty(cgbp); 199188110Smckusick } 200188110Smckusick if (inosused < sblock.fs_ipg) 201188110Smckusick continue; 20241474Sjulian lastino += 1; 203188110Smckusick if (lastino < (c * sblock.fs_ipg)) 204188110Smckusick inosused = 0; 205188110Smckusick else 206188110Smckusick inosused = lastino - (c * sblock.fs_ipg); 207248658Smckusick if (rebuildcg && inosused > cgp->cg_initediblk && 208188110Smckusick sblock.fs_magic == FS_UFS2_MAGIC) { 209248658Smckusick cgp->cg_initediblk = roundup(inosused, INOPB(&sblock)); 210188110Smckusick pwarn("CYLINDER GROUP %d: FOUND %d VALID INODES\n", c, 211248658Smckusick cgp->cg_initediblk); 212188110Smckusick } 21341474Sjulian /* 21441474Sjulian * If we were not able to determine in advance which inodes 21541474Sjulian * were in use, then reduce the size of the inoinfo structure 21641474Sjulian * to the size necessary to describe the inodes that we 21741474Sjulian * really found. 21841474Sjulian */ 219188110Smckusick if (inumber == lastino) 220188110Smckusick continue; 22141474Sjulian inostathead[c].il_numalloced = inosused; 22241474Sjulian if (inosused == 0) { 22341474Sjulian free(inostathead[c].il_stat); 22441474Sjulian inostathead[c].il_stat = 0; 22541474Sjulian continue; 22641474Sjulian } 227248658Smckusick info = Calloc((unsigned)inosused, sizeof(struct inostat)); 22841474Sjulian if (info == NULL) 229125036Scperciva errx(EEXIT, "cannot alloc %u bytes for inoinfo", 23041474Sjulian (unsigned)(sizeof(struct inostat) * inosused)); 23141474Sjulian memmove(info, inostathead[c].il_stat, inosused * sizeof(*info)); 23241474Sjulian free(inostathead[c].il_stat); 23341474Sjulian inostathead[c].il_stat = info; 2341558Srgrimes } 2351558Srgrimes freeinodebuf(); 2361558Srgrimes} 2371558Srgrimes 238188110Smckusickstatic int 239188110Smckusickcheckinode(ino_t inumber, struct inodesc *idesc, int rebuildcg) 2401558Srgrimes{ 24198542Smckusick union dinode *dp; 24298542Smckusick off_t kernmaxfilesize; 24398542Smckusick ufs2_daddr_t ndb; 2441558Srgrimes mode_t mode; 245103885Smckusick int j, ret, offset; 2461558Srgrimes 247188110Smckusick if ((dp = getnextinode(inumber, rebuildcg)) == NULL) 248188110Smckusick return (0); 24998542Smckusick mode = DIP(dp, di_mode) & IFMT; 2501558Srgrimes if (mode == 0) { 25198542Smckusick if ((sblock.fs_magic == FS_UFS1_MAGIC && 25298542Smckusick (memcmp(dp->dp1.di_db, ufs1_zino.di_db, 25398542Smckusick NDADDR * sizeof(ufs1_daddr_t)) || 25498542Smckusick memcmp(dp->dp1.di_ib, ufs1_zino.di_ib, 25598542Smckusick NIADDR * sizeof(ufs1_daddr_t)) || 25698542Smckusick dp->dp1.di_mode || dp->dp1.di_size)) || 25798542Smckusick (sblock.fs_magic == FS_UFS2_MAGIC && 25898542Smckusick (memcmp(dp->dp2.di_db, ufs2_zino.di_db, 25998542Smckusick NDADDR * sizeof(ufs2_daddr_t)) || 26098542Smckusick memcmp(dp->dp2.di_ib, ufs2_zino.di_ib, 26198542Smckusick NIADDR * sizeof(ufs2_daddr_t)) || 26298542Smckusick dp->dp2.di_mode || dp->dp2.di_size))) { 26386514Siedowse pfatal("PARTIALLY ALLOCATED INODE I=%lu", 26486514Siedowse (u_long)inumber); 2651558Srgrimes if (reply("CLEAR") == 1) { 2661558Srgrimes dp = ginode(inumber); 2671558Srgrimes clearinode(dp); 2681558Srgrimes inodirty(); 2691558Srgrimes } 2701558Srgrimes } 27141474Sjulian inoinfo(inumber)->ino_state = USTATE; 272188110Smckusick return (1); 2731558Srgrimes } 2741558Srgrimes lastino = inumber; 27571884Siedowse /* This should match the file size limit in ffs_mountfs(). */ 27698888Siedowse if (sblock.fs_magic == FS_UFS1_MAGIC) 27798888Siedowse kernmaxfilesize = (off_t)0x40000000 * sblock.fs_bsize - 1; 27898888Siedowse else 27998888Siedowse kernmaxfilesize = sblock.fs_maxfilesize; 28098542Smckusick if (DIP(dp, di_size) > kernmaxfilesize || 28198542Smckusick DIP(dp, di_size) > sblock.fs_maxfilesize || 28298542Smckusick (mode == IFDIR && DIP(dp, di_size) > MAXDIRSIZE)) { 2831558Srgrimes if (debug) 284101037Smux printf("bad size %ju:", (uintmax_t)DIP(dp, di_size)); 2851558Srgrimes goto unknown; 2861558Srgrimes } 2871558Srgrimes if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { 2881558Srgrimes dp = ginode(inumber); 289134589Sscottl DIP_SET(dp, di_size, sblock.fs_fsize); 290134589Sscottl DIP_SET(dp, di_mode, IFREG|0600); 2911558Srgrimes inodirty(); 2921558Srgrimes } 29363003Smckusick if ((mode == IFBLK || mode == IFCHR || mode == IFIFO || 29498542Smckusick mode == IFSOCK) && DIP(dp, di_size) != 0) { 29563003Smckusick if (debug) 296101037Smux printf("bad special-file size %ju:", 297101037Smux (uintmax_t)DIP(dp, di_size)); 29863003Smckusick goto unknown; 29963003Smckusick } 30098542Smckusick if ((mode == IFBLK || mode == IFCHR) && 30198542Smckusick (dev_t)DIP(dp, di_rdev) == NODEV) { 30272525Stegge if (debug) 30372525Stegge printf("bad special-file rdev NODEV:"); 30472525Stegge goto unknown; 30572525Stegge } 30698542Smckusick ndb = howmany(DIP(dp, di_size), sblock.fs_bsize); 3071558Srgrimes if (ndb < 0) { 3081558Srgrimes if (debug) 309101037Smux printf("bad size %ju ndb %ju:", 310101037Smux (uintmax_t)DIP(dp, di_size), (uintmax_t)ndb); 3111558Srgrimes goto unknown; 3121558Srgrimes } 3131558Srgrimes if (mode == IFBLK || mode == IFCHR) 3141558Srgrimes ndb++; 3151558Srgrimes if (mode == IFLNK) { 3161558Srgrimes /* 3171558Srgrimes * Fake ndb value so direct/indirect block checks below 3181558Srgrimes * will detect any garbage after symlink string. 3191558Srgrimes */ 32098542Smckusick if (DIP(dp, di_size) < (off_t)sblock.fs_maxsymlinklen) { 32198542Smckusick if (sblock.fs_magic == FS_UFS1_MAGIC) 32298542Smckusick ndb = howmany(DIP(dp, di_size), 32398542Smckusick sizeof(ufs1_daddr_t)); 32498542Smckusick else 32598542Smckusick ndb = howmany(DIP(dp, di_size), 32698542Smckusick sizeof(ufs2_daddr_t)); 3271558Srgrimes if (ndb > NDADDR) { 3281558Srgrimes j = ndb - NDADDR; 3291558Srgrimes for (ndb = 1; j > 1; j--) 3301558Srgrimes ndb *= NINDIR(&sblock); 3311558Srgrimes ndb += NDADDR; 3321558Srgrimes } 3331558Srgrimes } 3341558Srgrimes } 33598879Siedowse for (j = ndb; ndb < NDADDR && j < NDADDR; j++) 33698542Smckusick if (DIP(dp, di_db[j]) != 0) { 3371558Srgrimes if (debug) 338101037Smux printf("bad direct addr[%d]: %ju\n", j, 339101037Smux (uintmax_t)DIP(dp, di_db[j])); 3401558Srgrimes goto unknown; 3411558Srgrimes } 3421558Srgrimes for (j = 0, ndb -= NDADDR; ndb > 0; j++) 3431558Srgrimes ndb /= NINDIR(&sblock); 3441558Srgrimes for (; j < NIADDR; j++) 34598542Smckusick if (DIP(dp, di_ib[j]) != 0) { 3461558Srgrimes if (debug) 347101037Smux printf("bad indirect addr: %ju\n", 348101037Smux (uintmax_t)DIP(dp, di_ib[j])); 3491558Srgrimes goto unknown; 3501558Srgrimes } 3511558Srgrimes if (ftypeok(dp) == 0) 3521558Srgrimes goto unknown; 3531558Srgrimes n_files++; 35498542Smckusick inoinfo(inumber)->ino_linkcnt = DIP(dp, di_nlink); 3551558Srgrimes if (mode == IFDIR) { 35698542Smckusick if (DIP(dp, di_size) == 0) 35741474Sjulian inoinfo(inumber)->ino_state = DCLEAR; 358136281Struckman else if (DIP(dp, di_nlink) <= 0) 359136281Struckman inoinfo(inumber)->ino_state = DZLINK; 3601558Srgrimes else 36141474Sjulian inoinfo(inumber)->ino_state = DSTATE; 3621558Srgrimes cacheino(dp, inumber); 36341474Sjulian countdirs++; 364136281Struckman } else if (DIP(dp, di_nlink) <= 0) 365136281Struckman inoinfo(inumber)->ino_state = FZLINK; 366136281Struckman else 36741474Sjulian inoinfo(inumber)->ino_state = FSTATE; 36841474Sjulian inoinfo(inumber)->ino_type = IFTODT(mode); 3691558Srgrimes badblk = dupblk = 0; 3701558Srgrimes idesc->id_number = inumber; 37198542Smckusick if (DIP(dp, di_flags) & SF_SNAPSHOT) 37262668Smckusick idesc->id_type = SNAP; 37362668Smckusick else 37462668Smckusick idesc->id_type = ADDR; 3751558Srgrimes (void)ckinode(dp, idesc); 376103885Smckusick if (sblock.fs_magic == FS_UFS2_MAGIC && dp->dp2.di_extsize > 0) { 377103885Smckusick idesc->id_type = ADDR; 378103885Smckusick ndb = howmany(dp->dp2.di_extsize, sblock.fs_bsize); 379103885Smckusick for (j = 0; j < NXADDR; j++) { 380103885Smckusick if (--ndb == 0 && 381103885Smckusick (offset = blkoff(&sblock, dp->dp2.di_extsize)) != 0) 382103885Smckusick idesc->id_numfrags = numfrags(&sblock, 383103885Smckusick fragroundup(&sblock, offset)); 384103885Smckusick else 385103885Smckusick idesc->id_numfrags = sblock.fs_frag; 386103885Smckusick if (dp->dp2.di_extb[j] == 0) 387103885Smckusick continue; 388103885Smckusick idesc->id_blkno = dp->dp2.di_extb[j]; 389103885Smckusick ret = (*idesc->id_func)(idesc); 390103885Smckusick if (ret & STOP) 391103885Smckusick break; 392103885Smckusick } 393103885Smckusick } 394103398Sphk if (sblock.fs_magic == FS_UFS2_MAGIC) 395103398Sphk eascan(idesc, &dp->dp2); 3961558Srgrimes idesc->id_entryno *= btodb(sblock.fs_fsize); 39798542Smckusick if (DIP(dp, di_blocks) != idesc->id_entryno) { 398101037Smux pwarn("INCORRECT BLOCK COUNT I=%lu (%ju should be %ju)", 399101037Smux (u_long)inumber, (uintmax_t)DIP(dp, di_blocks), 400101037Smux (uintmax_t)idesc->id_entryno); 4011558Srgrimes if (preen) 4021558Srgrimes printf(" (CORRECTED)\n"); 4031558Srgrimes else if (reply("CORRECT") == 0) 404188110Smckusick return (1); 40574556Smckusick if (bkgrdflag == 0) { 40674556Smckusick dp = ginode(inumber); 407134589Sscottl DIP_SET(dp, di_blocks, idesc->id_entryno); 40874556Smckusick inodirty(); 40974556Smckusick } else { 41074556Smckusick cmd.value = idesc->id_number; 41198542Smckusick cmd.size = idesc->id_entryno - DIP(dp, di_blocks); 41274556Smckusick if (debug) 413101037Smux printf("adjblkcnt ino %ju amount %lld\n", 414101037Smux (uintmax_t)cmd.value, (long long)cmd.size); 41574556Smckusick if (sysctl(adjblkcnt, MIBSIZE, 0, 0, 41674556Smckusick &cmd, sizeof cmd) == -1) 41774556Smckusick rwerror("ADJUST INODE BLOCK COUNT", cmd.value); 41874556Smckusick } 4191558Srgrimes } 420188110Smckusick return (1); 4211558Srgrimesunknown: 42286514Siedowse pfatal("UNKNOWN FILE TYPE I=%lu", (u_long)inumber); 42341474Sjulian inoinfo(inumber)->ino_state = FCLEAR; 4241558Srgrimes if (reply("CLEAR") == 1) { 42541474Sjulian inoinfo(inumber)->ino_state = USTATE; 4261558Srgrimes dp = ginode(inumber); 4271558Srgrimes clearinode(dp); 4281558Srgrimes inodirty(); 4291558Srgrimes } 430188110Smckusick return (1); 4311558Srgrimes} 4321558Srgrimes 4337585Sbdeint 43492839Simppass1check(struct inodesc *idesc) 4351558Srgrimes{ 4361558Srgrimes int res = KEEPON; 4371558Srgrimes int anyout, nfrags; 43898542Smckusick ufs2_daddr_t blkno = idesc->id_blkno; 43992806Sobrien struct dups *dlp; 4401558Srgrimes struct dups *new; 4411558Srgrimes 44262668Smckusick if (idesc->id_type == SNAP) { 44362668Smckusick if (blkno == BLK_NOCOPY) 44462668Smckusick return (KEEPON); 44562668Smckusick if (idesc->id_number == cursnapshot) { 44662668Smckusick if (blkno == blkstofrags(&sblock, idesc->id_lbn)) 44762668Smckusick return (KEEPON); 44862668Smckusick if (blkno == BLK_SNAP) { 44962668Smckusick blkno = blkstofrags(&sblock, idesc->id_lbn); 45062668Smckusick idesc->id_entryno -= idesc->id_numfrags; 45162668Smckusick } 45262668Smckusick } else { 45362668Smckusick if (blkno == BLK_SNAP) 45462668Smckusick return (KEEPON); 45562668Smckusick } 45662668Smckusick } 4571558Srgrimes if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { 4581558Srgrimes blkerror(idesc->id_number, "BAD", blkno); 4591558Srgrimes if (badblk++ >= MAXBAD) { 4601558Srgrimes pwarn("EXCESSIVE BAD BLKS I=%lu", 46186514Siedowse (u_long)idesc->id_number); 4621558Srgrimes if (preen) 4631558Srgrimes printf(" (SKIPPING)\n"); 46434266Sjulian else if (reply("CONTINUE") == 0) { 46534266Sjulian ckfini(0); 46623675Speter exit(EEXIT); 46734266Sjulian } 468260178Sscottl rerun = 1; 4691558Srgrimes return (STOP); 4701558Srgrimes } 4711558Srgrimes } 4721558Srgrimes for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 4731558Srgrimes if (anyout && chkrange(blkno, 1)) { 4741558Srgrimes res = SKIP; 4751558Srgrimes } else if (!testbmap(blkno)) { 4761558Srgrimes n_blks++; 4771558Srgrimes setbmap(blkno); 4781558Srgrimes } else { 4791558Srgrimes blkerror(idesc->id_number, "DUP", blkno); 4801558Srgrimes if (dupblk++ >= MAXDUP) { 4811558Srgrimes pwarn("EXCESSIVE DUP BLKS I=%lu", 48286514Siedowse (u_long)idesc->id_number); 4831558Srgrimes if (preen) 4841558Srgrimes printf(" (SKIPPING)\n"); 48534266Sjulian else if (reply("CONTINUE") == 0) { 48634266Sjulian ckfini(0); 48723675Speter exit(EEXIT); 48834266Sjulian } 489260178Sscottl rerun = 1; 4901558Srgrimes return (STOP); 4911558Srgrimes } 492248658Smckusick new = (struct dups *)Malloc(sizeof(struct dups)); 4931558Srgrimes if (new == NULL) { 4941558Srgrimes pfatal("DUP TABLE OVERFLOW."); 49534266Sjulian if (reply("CONTINUE") == 0) { 49634266Sjulian ckfini(0); 49723675Speter exit(EEXIT); 49834266Sjulian } 499260178Sscottl rerun = 1; 5001558Srgrimes return (STOP); 5011558Srgrimes } 5021558Srgrimes new->dup = blkno; 5031558Srgrimes if (muldup == 0) { 5041558Srgrimes duplist = muldup = new; 5051558Srgrimes new->next = 0; 5061558Srgrimes } else { 5071558Srgrimes new->next = muldup->next; 5081558Srgrimes muldup->next = new; 5091558Srgrimes } 5101558Srgrimes for (dlp = duplist; dlp != muldup; dlp = dlp->next) 5111558Srgrimes if (dlp->dup == blkno) 5121558Srgrimes break; 5131558Srgrimes if (dlp == muldup && dlp->dup != blkno) 5141558Srgrimes muldup = new; 5151558Srgrimes } 5161558Srgrimes /* 5171558Srgrimes * count the number of blocks found in id_entryno 5181558Srgrimes */ 5191558Srgrimes idesc->id_entryno++; 5201558Srgrimes } 5211558Srgrimes return (res); 5221558Srgrimes} 523