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;
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