xref: /openbsd-src/sbin/fsck_ffs/pass1.c (revision f6e4162f05818bbc182b2d0e7e8682ece0079a77)
1*f6e4162fSjsg /*	$OpenBSD: pass1.c,v 1.50 2024/09/15 07:14:58 jsg Exp $	*/
287304b87Stholo /*	$NetBSD: pass1.c,v 1.16 1996/09/27 22:45:15 christos Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*
5df930be7Sderaadt  * Copyright (c) 1980, 1986, 1993
6df930be7Sderaadt  *	The Regents of the University of California.  All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
9df930be7Sderaadt  * modification, are permitted provided that the following conditions
10df930be7Sderaadt  * are met:
11df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
12df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
13df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
14df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
15df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
161ef0d710Smillert  * 3. Neither the name of the University nor the names of its contributors
17df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
18df930be7Sderaadt  *    without specific prior written permission.
19df930be7Sderaadt  *
20df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30df930be7Sderaadt  * SUCH DAMAGE.
31df930be7Sderaadt  */
32df930be7Sderaadt 
3378eb0b7eSderaadt #include <sys/param.h>	/* MIN setbit btodb isset */
34df930be7Sderaadt #include <sys/time.h>
35df930be7Sderaadt #include <ufs/ufs/dinode.h>
36df930be7Sderaadt #include <ufs/ufs/dir.h>
37df930be7Sderaadt #include <ufs/ffs/fs.h>
38df930be7Sderaadt 
39df930be7Sderaadt #include <stdio.h>
40df930be7Sderaadt #include <stdlib.h>
41df930be7Sderaadt #include <string.h>
429ce41040Schl #include <unistd.h>
43b9fc9a72Sderaadt #include <limits.h>
44df930be7Sderaadt 
45df930be7Sderaadt #include "fsck.h"
46df930be7Sderaadt #include "extern.h"
4787304b87Stholo #include "fsutil.h"
48df930be7Sderaadt 
491abdbfdeSderaadt static daddr_t badblk;
501abdbfdeSderaadt static daddr_t dupblk;
51c72b5b24Smillert static void checkinode(ino_t, struct inodesc *);
52df930be7Sderaadt 
53af9e537cSd static ino_t info_inumber;
54af9e537cSd 
55af9e537cSd static int
56379d1969Sderaadt pass1_info(char *buf, size_t buflen)
57af9e537cSd {
583b92bd08Sderaadt 	return (snprintf(buf, buflen, "phase 1, inode %llu/%llu",
593b92bd08Sderaadt 	    (unsigned long long)info_inumber,
603b92bd08Sderaadt 	    (unsigned long long)sblock.fs_ipg * sblock.fs_ncg) > 0);
61af9e537cSd }
62af9e537cSd 
63df930be7Sderaadt void
6460d6b16fSgluk pass1(void)
65df930be7Sderaadt {
664d91232bSotto 	ino_t inumber, inosused, ninosused;
674d91232bSotto 	size_t inospace;
684d91232bSotto 	struct inostat *info;
692062fcb1Sotto 	struct bufarea *cgbp;
702062fcb1Sotto 	struct cg *cgp;
71abbb3558Sotto 	u_int c;
724d91232bSotto 	struct inodesc idesc;
731abdbfdeSderaadt 	daddr_t i, cgd;
74df930be7Sderaadt 
75df930be7Sderaadt 	/*
76df930be7Sderaadt 	 * Set file system reserved blocks in used block map.
77df930be7Sderaadt 	 */
78df930be7Sderaadt 	for (c = 0; c < sblock.fs_ncg; c++) {
79df930be7Sderaadt 		cgd = cgdmin(&sblock, c);
80e7bce8e3Sderaadt 		if (c == 0)
81df930be7Sderaadt 			i = cgbase(&sblock, c);
82e7bce8e3Sderaadt 		else
83df930be7Sderaadt 			i = cgsblock(&sblock, c);
84df930be7Sderaadt 		for (; i < cgd; i++)
85df930be7Sderaadt 			setbmap(i);
86df930be7Sderaadt 	}
872fffe0e0Smillert 	i = sblock.fs_csaddr;
88e7bce8e3Sderaadt 	cgd = i + howmany(sblock.fs_cssize, sblock.fs_fsize);
89e7bce8e3Sderaadt 	for (; i < cgd; i++)
90e7bce8e3Sderaadt 		setbmap(i);
91df930be7Sderaadt 	/*
92df930be7Sderaadt 	 * Find all allocated blocks.
93df930be7Sderaadt 	 */
94df930be7Sderaadt 	memset(&idesc, 0, sizeof(struct inodesc));
95df930be7Sderaadt 	idesc.id_type = ADDR;
96df930be7Sderaadt 	idesc.id_func = pass1check;
97df930be7Sderaadt 	n_files = n_blks = 0;
98af9e537cSd 	info_inumber = 0;
99af9e537cSd 	info_fn = pass1_info;
100df930be7Sderaadt 	for (c = 0; c < sblock.fs_ncg; c++) {
1012fffe0e0Smillert 		inumber = c * sblock.fs_ipg;
1022fffe0e0Smillert 		setinodebuf(inumber);
1032062fcb1Sotto 		cgbp = cglookup(c);
1042062fcb1Sotto 		cgp = cgbp->b_un.b_cg;
105f88b7ac5Sotto 		if (sblock.fs_magic == FS_UFS2_MAGIC) {
1062062fcb1Sotto 			inosused = cgp->cg_initediblk;
107f88b7ac5Sotto 			if (inosused > sblock.fs_ipg)
108f88b7ac5Sotto 				inosused = sblock.fs_ipg;
109f88b7ac5Sotto 		} else
1102fffe0e0Smillert 			inosused = sblock.fs_ipg;
1114d91232bSotto 
1124d91232bSotto 		/*
1134d91232bSotto 		 * Allocate inoinfo structures for the allocated inodes.
1144d91232bSotto 		 */
1154d91232bSotto 		inostathead[c].il_numalloced = inosused;
1164d91232bSotto 		if (inosused == 0) {
1174d91232bSotto 			inostathead[c].il_stat = 0;
1184d91232bSotto 			continue;
1194d91232bSotto 		}
1202062fcb1Sotto 		info = Calloc((unsigned)inosused, sizeof(struct inostat));
1214d91232bSotto 		inospace = (unsigned)inosused * sizeof(struct inostat);
1224d91232bSotto 		if (info == NULL)
1232062fcb1Sotto 			errexit("cannot alloc %zu bytes for inoinfo\n", inospace);
1244d91232bSotto 		inostathead[c].il_stat = info;
1254d91232bSotto 		/*
1264d91232bSotto 		 * Scan the allocated inodes.
1274d91232bSotto 		 */
1282fffe0e0Smillert 		for (i = 0; i < inosused; i++, inumber++) {
129af9e537cSd 			info_inumber = inumber;
1304d91232bSotto 			if (inumber < ROOTINO) {
1314d91232bSotto 				(void)getnextinode(inumber);
132df930be7Sderaadt 				continue;
1334d91232bSotto 			}
134df930be7Sderaadt 			checkinode(inumber, &idesc);
135df930be7Sderaadt 		}
1364d91232bSotto 		lastino += 1;
1374d91232bSotto 		if (inosused < sblock.fs_ipg || inumber == lastino)
1384d91232bSotto 			continue;
1394d91232bSotto 		/*
1404d91232bSotto 		 * If we were not able to determine in advance which inodes
1414d91232bSotto 		 * were in use, then reduce the size of the inoinfo structure
1424d91232bSotto 		 * to the size necessary to describe the inodes that we
1434d91232bSotto 		 * really found.
1444d91232bSotto 		 */
1454d91232bSotto 		if (lastino < (c * sblock.fs_ipg))
1464d91232bSotto 			ninosused = 0;
1474d91232bSotto 		else
1484d91232bSotto 			ninosused = lastino - (c * sblock.fs_ipg);
1494d91232bSotto 		inostathead[c].il_numalloced = ninosused;
1504d91232bSotto 		if (ninosused == 0) {
1514d91232bSotto 			free(inostathead[c].il_stat);
1524d91232bSotto 			inostathead[c].il_stat = 0;
1534d91232bSotto 			continue;
1544d91232bSotto 		}
1554d91232bSotto 		if (ninosused != inosused) {
1564d91232bSotto 			struct inostat *ninfo;
157527c1077Sderaadt 			size_t ninospace;
1586a0422b3Sguenther 
1592062fcb1Sotto 			ninfo = Reallocarray(info, ninosused, sizeof(*ninfo));
160527c1077Sderaadt 			if (ninfo == NULL) {
161527c1077Sderaadt 				pfatal("too many inodes %llu, or out of memory\n",
1624d91232bSotto 				    (unsigned long long)ninosused);
1634d91232bSotto 				exit(8);
1644d91232bSotto 			}
165527c1077Sderaadt 			ninospace = ninosused * sizeof(*ninfo);
1664d91232bSotto 			if (ninosused > inosused)
167527c1077Sderaadt 				memset(&ninfo[inosused], 0, ninospace - inospace);
1684d91232bSotto 			inostathead[c].il_stat = ninfo;
1694d91232bSotto 		}
170df930be7Sderaadt 	}
171af9e537cSd 	info_fn = NULL;
172df930be7Sderaadt 	freeinodebuf();
173df930be7Sderaadt }
174df930be7Sderaadt 
17587304b87Stholo static void
17660d6b16fSgluk checkinode(ino_t inumber, struct inodesc *idesc)
177df930be7Sderaadt {
1782fffe0e0Smillert 	union dinode *dp;
17916f07c23Sotto 	off_t kernmaxfilesize;
180df930be7Sderaadt 	struct zlncnt *zlnp;
181df930be7Sderaadt 	int ndb, j;
182df930be7Sderaadt 	mode_t mode;
183ac7b90deSotto 	u_int64_t lndb;
184df930be7Sderaadt 
185df930be7Sderaadt 	dp = getnextinode(inumber);
1862fffe0e0Smillert 	mode = DIP(dp, di_mode) & IFMT;
187df930be7Sderaadt 	if (mode == 0) {
1882fffe0e0Smillert 		if ((sblock.fs_magic == FS_UFS1_MAGIC &&
1892fffe0e0Smillert 		     (memcmp(dp->dp1.di_db, ufs1_zino.di_db,
190c29211cfSpedro 			NDADDR * sizeof(int32_t)) ||
1912fffe0e0Smillert 		      memcmp(dp->dp1.di_ib, ufs1_zino.di_ib,
192c29211cfSpedro 			NIADDR * sizeof(int32_t)) ||
1932fffe0e0Smillert 		      dp->dp1.di_mode || dp->dp1.di_size)) ||
1942fffe0e0Smillert 		    (sblock.fs_magic == FS_UFS2_MAGIC &&
1952fffe0e0Smillert 		     (memcmp(dp->dp2.di_db, ufs2_zino.di_db,
1961abdbfdeSderaadt 			NDADDR * sizeof(daddr_t)) ||
1972fffe0e0Smillert 		      memcmp(dp->dp2.di_ib, ufs2_zino.di_ib,
1981abdbfdeSderaadt 			NIADDR * sizeof(daddr_t)) ||
1992fffe0e0Smillert 		      dp->dp2.di_mode || dp->dp2.di_size))) {
2003b92bd08Sderaadt 			pfatal("PARTIALLY ALLOCATED INODE I=%llu",
2013b92bd08Sderaadt 			    (unsigned long long)inumber);
202df930be7Sderaadt 			if (reply("CLEAR") == 1) {
203df930be7Sderaadt 				dp = ginode(inumber);
204df930be7Sderaadt 				clearinode(dp);
205df930be7Sderaadt 				inodirty();
206df930be7Sderaadt 			}
207df930be7Sderaadt 		}
2084aab0ea5Sotto 		SET_ISTATE(inumber, USTATE);
209df930be7Sderaadt 		return;
210df930be7Sderaadt 	}
211df930be7Sderaadt 	lastino = inumber;
21216f07c23Sotto 	/* This should match the file size limit in ffs_mountfs(). */
213e4b46811Sderaadt 	kernmaxfilesize = FS_KERNMAXFILESIZE(getpagesize(), &sblock);
21416f07c23Sotto 	if (DIP(dp, di_size) > kernmaxfilesize ||
21516f07c23Sotto 	    DIP(dp, di_size) > sblock.fs_maxfilesize ||
21616f07c23Sotto 	    (mode == IFDIR && DIP(dp, di_size) > MAXDIRSIZE)) {
217df930be7Sderaadt 		if (debug)
2182fffe0e0Smillert 			printf("bad size %llu:",
2192fffe0e0Smillert 			    (unsigned long long)DIP(dp, di_size));
220df930be7Sderaadt 		goto unknown;
221df930be7Sderaadt 	}
222df930be7Sderaadt 	if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) {
223df930be7Sderaadt 		dp = ginode(inumber);
2242fffe0e0Smillert 		DIP_SET(dp, di_size, sblock.fs_fsize);
2252fffe0e0Smillert 		DIP_SET(dp, di_mode, IFREG|0600);
226df930be7Sderaadt 		inodirty();
227df930be7Sderaadt 	}
2282fffe0e0Smillert 	lndb = howmany(DIP(dp, di_size), sblock.fs_bsize);
229ac7b90deSotto 	ndb = lndb > (u_int64_t)INT_MAX ? -1 : (int)lndb;
230df930be7Sderaadt 	if (ndb < 0) {
231df930be7Sderaadt 		if (debug)
232a4df0321Sderaadt 			printf("bad size %llu ndb %d:",
2332fffe0e0Smillert 			    (unsigned long long)DIP(dp, di_size), ndb);
234df930be7Sderaadt 		goto unknown;
235df930be7Sderaadt 	}
236df930be7Sderaadt 	if (mode == IFBLK || mode == IFCHR)
237df930be7Sderaadt 		ndb++;
238df930be7Sderaadt 	if (mode == IFLNK) {
239df930be7Sderaadt 		/*
240df930be7Sderaadt 		 * Fake ndb value so direct/indirect block checks below
241df930be7Sderaadt 		 * will detect any garbage after symlink string.
242df930be7Sderaadt 		 */
243da5362d5Sguenther 		if (DIP(dp, di_size) < sblock.fs_maxsymlinklen) {
2442fffe0e0Smillert 			if (sblock.fs_magic == FS_UFS1_MAGIC)
2452fffe0e0Smillert 				ndb = howmany(DIP(dp, di_size),
246c29211cfSpedro 				    sizeof(int32_t));
2472fffe0e0Smillert 			else
2482fffe0e0Smillert 				ndb = howmany(DIP(dp, di_size),
249c29211cfSpedro 				    sizeof(int64_t));
250df930be7Sderaadt 			if (ndb > NDADDR) {
251df930be7Sderaadt 				j = ndb - NDADDR;
252df930be7Sderaadt 				for (ndb = 1; j > 1; j--)
253df930be7Sderaadt 					ndb *= NINDIR(&sblock);
254df930be7Sderaadt 				ndb += NDADDR;
255df930be7Sderaadt 			}
256df930be7Sderaadt 		}
257df930be7Sderaadt 	}
258df930be7Sderaadt 	for (j = ndb; j < NDADDR; j++)
2592fffe0e0Smillert 		if (DIP(dp, di_db[j]) != 0) {
260df930be7Sderaadt 			if (debug)
2616a0422b3Sguenther 				printf("bad direct addr: %lld\n",
2626a0422b3Sguenther 				    (long long)DIP(dp, di_db[j]));
263df930be7Sderaadt 			goto unknown;
264df930be7Sderaadt 		}
265df930be7Sderaadt 	for (j = 0, ndb -= NDADDR; ndb > 0; j++)
266df930be7Sderaadt 		ndb /= NINDIR(&sblock);
267df930be7Sderaadt 	for (; j < NIADDR; j++)
2682fffe0e0Smillert 		if (DIP(dp, di_ib[j]) != 0) {
269df930be7Sderaadt 			if (debug)
2706a0422b3Sguenther 				printf("bad indirect addr: %lld\n",
2716a0422b3Sguenther 				    (long long)DIP(dp, di_ib[j]));
272df930be7Sderaadt 			goto unknown;
273df930be7Sderaadt 		}
274df930be7Sderaadt 	if (ftypeok(dp) == 0)
275df930be7Sderaadt 		goto unknown;
276df930be7Sderaadt 	n_files++;
2774d91232bSotto 	ILNCOUNT(inumber) = DIP(dp, di_nlink);
2782fffe0e0Smillert 	if (DIP(dp, di_nlink) <= 0) {
2792062fcb1Sotto 		zlnp = Malloc(sizeof *zlnp);
280df930be7Sderaadt 		if (zlnp == NULL) {
281df930be7Sderaadt 			pfatal("LINK COUNT TABLE OVERFLOW");
282767b3369Sart 			if (reply("CONTINUE") == 0) {
283767b3369Sart 				ckfini(0);
28487304b87Stholo 				errexit("%s", "");
285767b3369Sart 			}
286df930be7Sderaadt 		} else {
287df930be7Sderaadt 			zlnp->zlncnt = inumber;
288df930be7Sderaadt 			zlnp->next = zlnhead;
289df930be7Sderaadt 			zlnhead = zlnp;
290df930be7Sderaadt 		}
291df930be7Sderaadt 	}
292df930be7Sderaadt 	if (mode == IFDIR) {
2932fffe0e0Smillert 		if (DIP(dp, di_size) == 0)
2944aab0ea5Sotto 			SET_ISTATE(inumber, DCLEAR);
295df930be7Sderaadt 		else
2964aab0ea5Sotto 			SET_ISTATE(inumber, DSTATE);
297df930be7Sderaadt 		cacheino(dp, inumber);
298df930be7Sderaadt 	} else
2994aab0ea5Sotto 		SET_ISTATE(inumber, FSTATE);
3004aab0ea5Sotto 	SET_ITYPE(inumber, IFTODT(mode));
301df930be7Sderaadt 	badblk = dupblk = 0;
302df930be7Sderaadt 	idesc->id_number = inumber;
303df930be7Sderaadt 	(void)ckinode(dp, idesc);
304df930be7Sderaadt 	idesc->id_entryno *= btodb(sblock.fs_fsize);
3052fffe0e0Smillert 	if (DIP(dp, di_blocks) != idesc->id_entryno) {
3066a0422b3Sguenther 		pwarn("INCORRECT BLOCK COUNT I=%llu (%lld should be %lld)",
3076a0422b3Sguenther 		    (unsigned long long)inumber, (long long)DIP(dp, di_blocks),
3086a0422b3Sguenther 		    (long long)idesc->id_entryno);
309df930be7Sderaadt 		if (preen)
310df930be7Sderaadt 			printf(" (CORRECTED)\n");
311df930be7Sderaadt 		else if (reply("CORRECT") == 0)
312df930be7Sderaadt 			return;
313df930be7Sderaadt 		dp = ginode(inumber);
3142fffe0e0Smillert 		DIP_SET(dp, di_blocks, idesc->id_entryno);
315df930be7Sderaadt 		inodirty();
316df930be7Sderaadt 	}
317df930be7Sderaadt 	return;
318df930be7Sderaadt unknown:
3193b92bd08Sderaadt 	pfatal("UNKNOWN FILE TYPE I=%llu", (unsigned long long)inumber);
3204aab0ea5Sotto 	SET_ISTATE(inumber, FCLEAR);
321df930be7Sderaadt 	if (reply("CLEAR") == 1) {
3224aab0ea5Sotto 		SET_ISTATE(inumber, USTATE);
323df930be7Sderaadt 		dp = ginode(inumber);
324df930be7Sderaadt 		clearinode(dp);
325df930be7Sderaadt 		inodirty();
326df930be7Sderaadt 	}
327df930be7Sderaadt }
328df930be7Sderaadt 
329df930be7Sderaadt int
33060d6b16fSgluk pass1check(struct inodesc *idesc)
331df930be7Sderaadt {
332df930be7Sderaadt 	int res = KEEPON;
333df930be7Sderaadt 	int anyout, nfrags;
3341abdbfdeSderaadt 	daddr_t blkno = idesc->id_blkno;
335e073c79dSmpech 	struct dups *dlp;
336df930be7Sderaadt 	struct dups *new;
337df930be7Sderaadt 
338df930be7Sderaadt 	if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
339df930be7Sderaadt 		blkerror(idesc->id_number, "BAD", blkno);
340df930be7Sderaadt 		if (badblk++ >= MAXBAD) {
3413b92bd08Sderaadt 			pwarn("EXCESSIVE BAD BLKS I=%llu",
3423b92bd08Sderaadt 			    (unsigned long long)idesc->id_number);
343df930be7Sderaadt 			if (preen)
344df930be7Sderaadt 				printf(" (SKIPPING)\n");
345767b3369Sart 			else if (reply("CONTINUE") == 0) {
346767b3369Sart 				ckfini(0);
34787304b87Stholo 				errexit("%s", "");
348767b3369Sart 			}
349df930be7Sderaadt 			return (STOP);
350df930be7Sderaadt 		}
351df930be7Sderaadt 	}
352df930be7Sderaadt 	for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
353df930be7Sderaadt 		if (anyout && chkrange(blkno, 1)) {
354df930be7Sderaadt 			res = SKIP;
355df930be7Sderaadt 		} else if (!testbmap(blkno)) {
356df930be7Sderaadt 			n_blks++;
357df930be7Sderaadt 			setbmap(blkno);
358df930be7Sderaadt 		} else {
359df930be7Sderaadt 			blkerror(idesc->id_number, "DUP", blkno);
360df930be7Sderaadt 			if (dupblk++ >= MAXDUP) {
3613b92bd08Sderaadt 				pwarn("EXCESSIVE DUP BLKS I=%llu",
3623b92bd08Sderaadt 				    (unsigned long long)idesc->id_number);
363df930be7Sderaadt 				if (preen)
364df930be7Sderaadt 					printf(" (SKIPPING)\n");
365767b3369Sart 				else if (reply("CONTINUE") == 0) {
366767b3369Sart 					ckfini(0);
36787304b87Stholo 					errexit("%s", "");
368767b3369Sart 				}
369df930be7Sderaadt 				return (STOP);
370df930be7Sderaadt 			}
3712062fcb1Sotto 			new = Malloc(sizeof(struct dups));
372df930be7Sderaadt 			if (new == NULL) {
373df930be7Sderaadt 				pfatal("DUP TABLE OVERFLOW.");
374767b3369Sart 				if (reply("CONTINUE") == 0) {
375767b3369Sart 					ckfini(0);
37687304b87Stholo 					errexit("%s", "");
377767b3369Sart 				}
378df930be7Sderaadt 				return (STOP);
379df930be7Sderaadt 			}
380df930be7Sderaadt 			new->dup = blkno;
381df930be7Sderaadt 			if (muldup == 0) {
382df930be7Sderaadt 				duplist = muldup = new;
383df930be7Sderaadt 				new->next = 0;
384df930be7Sderaadt 			} else {
385df930be7Sderaadt 				new->next = muldup->next;
386df930be7Sderaadt 				muldup->next = new;
387df930be7Sderaadt 			}
388df930be7Sderaadt 			for (dlp = duplist; dlp != muldup; dlp = dlp->next)
389df930be7Sderaadt 				if (dlp->dup == blkno)
390df930be7Sderaadt 					break;
391df930be7Sderaadt 			if (dlp == muldup && dlp->dup != blkno)
392df930be7Sderaadt 				muldup = new;
393df930be7Sderaadt 		}
394df930be7Sderaadt 		/*
395df930be7Sderaadt 		 * count the number of blocks found in id_entryno
396df930be7Sderaadt 		 */
397df930be7Sderaadt 		idesc->id_entryno++;
398df930be7Sderaadt 	}
399df930be7Sderaadt 	return (res);
400df930be7Sderaadt }
401