1/*
2 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
7/*	  All Rights Reserved  	*/
8
9/*
10 * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms are permitted
14 * provided that: (1) source distributions retain this entire copyright
15 * notice and comment, and (2) distributions including binaries display
16 * the following acknowledgement:  ``This product includes software
17 * developed by the University of California, Berkeley and its contributors''
18 * in the documentation or other materials provided with the distribution
19 * and in all advertising materials mentioning features or use of this
20 * software. Neither the name of the University nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26 */
27
28#pragma ident	"%Z%%M%	%I%	%E% SMI"
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <unistd.h>
33#include <string.h>
34#include <sys/param.h>
35#include <sys/types.h>
36#include <sys/mntent.h>
37#include <sys/fs/ufs_fs.h>
38#include <sys/vnode.h>
39#define	_KERNEL
40#include <sys/fs/ufs_fsdir.h>
41#undef _KERNEL
42#include <sys/fs/ufs_inode.h>
43#include "fsck.h"
44
45/*
46 * for each large file (size > MAXOFF_T), the global largefile_count
47 * gets incremented during this pass.
48 */
49
50static uint32_t badblk;		/* number seen for the current inode */
51static uint32_t dupblk;		/* number seen for the current inode */
52
53static void clear_attr_acl(fsck_ino_t, fsck_ino_t, char *);
54static void verify_inode(fsck_ino_t, struct inodesc *, fsck_ino_t);
55static void check_dirholes(fsck_ino_t, struct inodesc *);
56static void collapse_dirhole(fsck_ino_t, struct inodesc *);
57static void note_used(daddr32_t);
58
59void
60pass1(void)
61{
62	uint_t c, i;
63	daddr32_t cgd;
64	struct inodesc idesc;
65	fsck_ino_t inumber;
66	fsck_ino_t maxinumber;
67
68	/*
69	 * Set file system reserved blocks in used block map.
70	 */
71	for (c = 0; c < sblock.fs_ncg; c++) {
72		cgd = cgdmin(&sblock, c);
73		if (c == 0) {
74			/*
75			 * Doing the first cylinder group, account for
76			 * the cg summaries as well.
77			 */
78			i = cgbase(&sblock, c);
79			cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
80		} else {
81			i = cgsblock(&sblock, c);
82		}
83		for (; i < cgd; i++) {
84			note_used(i);
85		}
86	}
87	/*
88	 * Note blocks being used by the log, so we don't declare
89	 * them as available and some time in the future we get a
90	 * freeing free block panic.
91	 */
92	if (islog && islogok && sblock.fs_logbno)
93		examinelog(&note_used);
94
95	/*
96	 * Find all allocated blocks.  This must be completed before
97	 * we read the contents of any directories, as dirscan() et al
98	 * don't want to know about block allocation holes.  So, part
99	 * of this pass is to truncate any directories with holes to
100	 * just before those holes, so dirscan() can remain blissfully
101	 * ignorant.
102	 */
103	inumber = 0;
104	n_files = n_blks = 0;
105	resetinodebuf();
106	maxinumber = sblock.fs_ncg * sblock.fs_ipg;
107	for (c = 0; c < sblock.fs_ncg; c++) {
108		for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
109			if (inumber < UFSROOTINO)
110				continue;
111			init_inodesc(&idesc);
112			idesc.id_type = ADDR;
113			idesc.id_func = pass1check;
114			verify_inode(inumber, &idesc, maxinumber);
115		}
116	}
117	freeinodebuf();
118}
119
120/*
121 * Perform checks on an inode and setup/track the state of the inode
122 * in maps (statemap[], lncntp[]) for future reference and validation.
123 * Initiate the calls to ckinode and in turn pass1check() to handle
124 * further validation.
125 */
126static void
127verify_inode(fsck_ino_t inumber, struct inodesc *idesc, fsck_ino_t maxinumber)
128{
129	int j, clear, flags;
130	int isdir;
131	char *err;
132	fsck_ino_t shadow, attrinode;
133	daddr32_t ndb;
134	struct dinode *dp;
135	struct inoinfo *iip;
136
137	dp = getnextinode(inumber);
138	if ((dp->di_mode & IFMT) == 0) {
139		/* mode and type of file is not set */
140		if ((memcmp((void *)dp->di_db, (void *)zino.di_db,
141		    NDADDR * sizeof (daddr32_t)) != 0) ||
142		    (memcmp((void *)dp->di_ib, (void *)zino.di_ib,
143		    NIADDR * sizeof (daddr32_t)) != 0) ||
144		    (dp->di_mode != 0) || (dp->di_size != 0)) {
145			pfatal("PARTIALLY ALLOCATED INODE I=%u", inumber);
146			if (reply("CLEAR") == 1) {
147				dp = ginode(inumber);
148				clearinode(dp);
149				inodirty();
150			} else {
151				iscorrupt = 1;
152			}
153		}
154		statemap[inumber] = USTATE;
155		return;
156	}
157
158	isdir = ((dp->di_mode & IFMT) == IFDIR) ||
159	    ((dp->di_mode & IFMT) == IFATTRDIR);
160
161	lastino = inumber;
162	if (dp->di_size > (u_offset_t)UFS_MAXOFFSET_T) {
163		pfatal("NEGATIVE SIZE %lld I=%d",
164		    (longlong_t)dp->di_size, inumber);
165		goto bogus;
166	}
167
168	/*
169	 * A more precise test of the type is done later on.  Just get
170	 * rid of the blatantly-wrong ones before we do any
171	 * significant work.
172	 */
173	if ((dp->di_mode & IFMT) == IFMT) {
174		pfatal("BAD MODE 0%o I=%d",
175		    dp->di_mode & IFMT, inumber);
176		if (reply("BAD MODE: MAKE IT A FILE") == 1) {
177			statemap[inumber] = FSTATE;
178			dp = ginode(inumber);
179			dp->di_mode = IFREG | 0600;
180			inodirty();
181			truncino(inumber, sblock.fs_fsize, TI_NOPARENT);
182			dp = getnextrefresh();
183		} else {
184			iscorrupt = 1;
185		}
186	}
187
188	ndb = howmany(dp->di_size, (u_offset_t)sblock.fs_bsize);
189	if (ndb < 0) {
190		/* extra space to distinguish from previous pfatal() */
191		pfatal("NEGATIVE SIZE %lld  I=%d",
192		    (longlong_t)dp->di_size, inumber);
193		goto bogus;
194	}
195
196	if ((dp->di_mode & IFMT) == IFBLK ||
197	    (dp->di_mode & IFMT) == IFCHR) {
198		if (dp->di_size != 0) {
199			pfatal("SPECIAL FILE WITH NON-ZERO LENGTH %lld I=%d",
200			    (longlong_t)dp->di_size, inumber);
201			goto bogus;
202		}
203
204		for (j = 0; j < NDADDR; j++) {
205			/*
206			 * It's a device, so all the block pointers
207			 * should be zero except for di_ordev.
208			 * di_ordev is overlayed on the block array,
209			 * but where varies between big and little
210			 * endian, so make sure that the only non-zero
211			 * element is the correct one.  There can be
212			 * a device whose ordev is zero, so we can't
213			 * check for the reverse.
214			 */
215			if (dp->di_db[j] != 0 &&
216			    &dp->di_db[j] != &dp->di_ordev) {
217				if (debug) {
218					(void) printf(
219					    "spec file di_db[%d] has %d\n",
220					    j, dp->di_db[j]);
221				}
222				pfatal(
223			    "SPECIAL FILE WITH NON-ZERO FRAGMENT LIST  I=%d",
224				    inumber);
225				goto bogus;
226			}
227		}
228
229		for (j = 0; j < NIADDR; j++) {
230			if (dp->di_ib[j] != 0) {
231				if (debug)
232					(void) printf(
233					    "special has %d at ib[%d]\n",
234					    dp->di_ib[j], j);
235				pfatal(
236			    "SPECIAL FILE WITH NON-ZERO FRAGMENT LIST  I=%d",
237				    inumber);
238				goto bogus;
239			}
240		}
241	} else {
242		/*
243		 * This assignment is mostly here to appease lint, but
244		 * doesn't hurt.
245		 */
246		err = "Internal error: unexpected variant of having "
247		    "blocks past end of file  I=%d";
248
249		clear = 0;
250
251		/*
252		 * If it's not a device, it has to follow the
253		 * rules for files.  In particular, no blocks after
254		 * the last one that di_size says is in use.
255		 */
256		for (j = ndb; j < NDADDR; j++) {
257			if (dp->di_db[j] != 0) {
258				if (debug) {
259					(void) printf("bad file direct "
260					    "addr[%d]: block 0x%x "
261					    "format: 0%o\n",
262					    j, dp->di_db[j],
263					    dp->di_mode & IFMT);
264				}
265				err = "FILE WITH FRAGMENTS PAST END  I=%d";
266				clear = 1;
267				break;
268			}
269		}
270
271		/*
272		 * Find last indirect pointer that should be in use,
273		 * and make sure any after it are clear.
274		 */
275		if (!clear) {
276			for (j = 0, ndb -= NDADDR; ndb > 0; j++) {
277				ndb /= NINDIR(&sblock);
278			}
279			for (; j < NIADDR; j++) {
280				if (dp->di_ib[j] != 0) {
281					if (debug) {
282						(void) printf("bad file "
283						    "indirect addr: block %d\n",
284						    dp->di_ib[j]);
285					}
286					err =
287					    "FILE WITH FRAGMENTS PAST END I=%d";
288					clear = 2;
289					break;
290				}
291			}
292		}
293
294		if (clear) {
295			/*
296			 * The discarded blocks will be garbage-
297			 * collected in pass5.  If we're told not to
298			 * discard them, it's just lost blocks, which
299			 * isn't worth setting iscorrupt for.
300			 */
301			pwarn(err, inumber);
302			if (preen || reply("DISCARD EXCESS FRAGMENTS") == 1) {
303				dp = ginode(inumber);
304				if (clear == 1) {
305					for (; j < NDADDR; j++)
306						dp->di_db[j] = 0;
307					j = 0;
308				}
309				for (; j < NIADDR; j++)
310					dp->di_ib[j] = 0;
311				inodirty();
312				dp = getnextrefresh();
313				if (preen)
314					(void) printf(" (TRUNCATED)");
315			}
316		}
317	}
318
319	if (ftypeok(dp) == 0) {
320		pfatal("UNKNOWN FILE TYPE 0%o  I=%d", dp->di_mode, inumber);
321		goto bogus;
322	}
323	n_files++;
324	TRACK_LNCNTP(inumber, lncntp[inumber] = dp->di_nlink);
325
326	/*
327	 * We can't do anything about it right now, so note that its
328	 * processing is being delayed.  Otherwise, we'd be changing
329	 * the block allocations out from under ourselves, which causes
330	 * no end of confusion.
331	 */
332	flags = statemap[inumber] & INDELAYD;
333
334	/*
335	 * if errorlocked or logging, then open deleted files will
336	 * manifest as di_nlink <= 0 and di_mode != 0
337	 * so skip them; they're ok.
338	 * Also skip anything already marked to be cleared.
339	 */
340	if (dp->di_nlink <= 0 &&
341	    !((errorlocked || islog) && dp->di_mode == 0) &&
342	    !(flags & INCLEAR)) {
343		flags |= INZLINK;
344		if (debug)
345			(void) printf(
346		    "marking i=%d INZLINK; nlink %d, mode 0%o, islog %d\n",
347			    inumber, dp->di_nlink, dp->di_mode, islog);
348	}
349
350	switch (dp->di_mode & IFMT) {
351	case IFDIR:
352	case IFATTRDIR:
353		if (dp->di_size == 0) {
354			/*
355			 * INCLEAR means it will be ignored by passes 2 & 3.
356			 */
357			if ((dp->di_mode & IFMT) == IFDIR)
358				(void) printf("ZERO-LENGTH DIR  I=%d\n",
359				    inumber);
360			else
361				(void) printf("ZERO-LENGTH ATTRDIR  I=%d\n",
362				    inumber);
363			add_orphan_dir(inumber);
364			flags |= INCLEAR;
365			flags &= ~INZLINK;	/* It will be cleared anyway */
366		}
367		statemap[inumber] = DSTATE | flags;
368		cacheino(dp, inumber);
369		countdirs++;
370		break;
371
372	case IFSHAD:
373		if (dp->di_size == 0) {
374			(void) printf("ZERO-LENGTH SHADOW  I=%d\n", inumber);
375			flags |= INCLEAR;
376			flags &= ~INZLINK;	/* It will be cleared anyway */
377		}
378		statemap[inumber] = SSTATE | flags;
379		cacheacl(dp, inumber);
380		break;
381
382	default:
383		statemap[inumber] = FSTATE | flags;
384	}
385
386	badblk = 0;
387	dupblk = 0;
388	idesc->id_number = inumber;
389	idesc->id_fix = DONTKNOW;
390	if (dp->di_size > (u_offset_t)MAXOFF_T) {
391		largefile_count++;
392	}
393
394	(void) ckinode(dp, idesc, CKI_TRAVERSE);
395	if (isdir && (idesc->id_firsthole >= 0))
396		check_dirholes(inumber, idesc);
397
398	if (dp->di_blocks != idesc->id_entryno) {
399		/*
400		 * The kernel releases any blocks it finds in the lists,
401		 * ignoring the block count itself.  So, a bad count is
402		 * not grounds for setting iscorrupt.
403		 */
404		pwarn("INCORRECT DISK BLOCK COUNT I=%u (%d should be %d)",
405		    inumber, (uint32_t)dp->di_blocks, idesc->id_entryno);
406		if (!preen && (reply("CORRECT") == 0))
407			return;
408		dp = ginode(inumber);
409		dp->di_blocks = idesc->id_entryno;
410		iip = getinoinfo(inumber);
411		if (iip != NULL)
412			iip->i_isize = dp->di_size;
413		inodirty();
414		if (preen)
415			(void) printf(" (CORRECTED)\n");
416	}
417	if (isdir && (dp->di_blocks == 0)) {
418		/*
419		 * INCLEAR will cause passes 2 and 3 to skip it.
420		 */
421		(void) printf("DIR WITH ZERO BLOCKS  I=%d\n", inumber);
422		statemap[inumber] = DCLEAR;
423		add_orphan_dir(inumber);
424	}
425
426	/*
427	 * Check that the ACL is on a valid file type
428	 */
429	shadow = dp->di_shadow;
430	if (shadow != 0) {
431		if (acltypeok(dp) == 0) {
432			clear_attr_acl(inumber, -1,
433			    "NON-ZERO ACL REFERENCE, I=%d\n");
434		} else if ((shadow <= UFSROOTINO) ||
435		    (shadow > maxinumber)) {
436			clear_attr_acl(inumber, -1,
437			    "BAD ACL REFERENCE I=%d\n");
438		} else {
439			registershadowclient(shadow,
440			    inumber, &shadowclientinfo);
441		}
442	}
443
444	attrinode = dp->di_oeftflag;
445	if (attrinode != 0) {
446		if ((attrinode <= UFSROOTINO) ||
447		    (attrinode > maxinumber)) {
448			clear_attr_acl(attrinode, inumber,
449			    "BAD ATTRIBUTE REFERENCE TO I=%d FROM I=%d\n");
450		} else {
451			dp = ginode(attrinode);
452			if ((dp->di_mode & IFMT) != IFATTRDIR) {
453				clear_attr_acl(attrinode, inumber,
454			    "BAD ATTRIBUTE DIR REF TO I=%d FROM I=%d\n");
455			} else if (dp->di_size == 0) {
456				clear_attr_acl(attrinode, inumber,
457		    "REFERENCE TO ZERO-LENGTH ATTRIBUTE DIR I=%d from I=%d\n");
458			} else {
459				registershadowclient(attrinode, inumber,
460				    &attrclientinfo);
461			}
462		}
463	}
464	return;
465
466	/*
467	 * If we got here, we've not had the chance to see if a
468	 * directory has holes, but we know the directory's bad,
469	 * so it's safe to always return false (no holes found).
470	 *
471	 * Also, a pfatal() is always done before jumping here, so
472	 * we know we're not in preen mode.
473	 */
474bogus:
475	if (isdir) {
476		/*
477		 * INCLEAR makes passes 2 & 3 skip it.
478		 */
479		statemap[inumber] = DCLEAR;
480		add_orphan_dir(inumber);
481		cacheino(dp, inumber);
482	} else {
483		statemap[inumber] = FCLEAR;
484	}
485	if (reply("CLEAR") == 1) {
486		(void) tdelete((void *)inumber, &limbo_dirs, ino_t_cmp);
487		freeino(inumber, TI_PARENT);
488		inodirty();
489	} else {
490		iscorrupt = 1;
491	}
492}
493
494/*
495 * Do fixup for bad acl/attr references.  If PARENT is -1, then
496 * we assume we're working on a shadow, otherwise an extended attribute.
497 * FMT must be a printf format string, with one %d directive for
498 * the inode number.
499 */
500static void
501clear_attr_acl(fsck_ino_t inumber, fsck_ino_t parent, char *fmt)
502{
503	fsck_ino_t victim = inumber;
504	struct dinode *dp;
505
506	if (parent != -1)
507		victim = parent;
508
509	if (fmt != NULL) {
510		if (parent == -1)
511			pwarn(fmt, (int)inumber);
512		else
513			pwarn(fmt, (int)inumber, (int)parent);
514	}
515
516	if (debug)
517		(void) printf("parent file/dir I=%d\nvictim I=%d",
518		    (int)parent, (int)victim);
519
520	if (!preen && (reply("REMOVE REFERENCE") == 0)) {
521		iscorrupt = 1;
522		return;
523	}
524
525	dp = ginode(victim);
526	if (parent == -1) {
527		/*
528		 * The file had a bad shadow/acl, so lock it down
529		 * until someone can protect it the way they need it
530		 * to be (i.e., be conservatively paranoid).
531		 */
532		dp->di_shadow = 0;
533		dp->di_mode &= IFMT;
534	} else {
535		dp->di_oeftflag = 0;
536	}
537
538	inodirty();
539	if (preen)
540		(void) printf(" (CORRECTED)\n");
541}
542
543/*
544 * Check if we have holes in the directory's indirect
545 * blocks.  If there are, get rid of everything after
546 * the first hole.
547 */
548static void
549check_dirholes(fsck_ino_t inumber, struct inodesc *idesc)
550{
551	char pathbuf[MAXPATHLEN + 1];
552
553	getpathname(pathbuf, idesc->id_number, idesc->id_number);
554	pfatal("I=%d  DIRECTORY %s: CONTAINS EMPTY BLOCKS",
555	    idesc->id_number, pathbuf);
556	if (reply("TRUNCATE AT FIRST EMPTY BLOCK") == 1) {
557		/*
558		 * We found a hole, so get rid of it.
559		 */
560		collapse_dirhole(inumber, idesc);
561
562		if (preen)
563			(void) printf(" (TRUNCATED)\n");
564	} else {
565		iscorrupt = 1;
566	}
567}
568
569/*
570 * Truncate a directory to its first hole.  If there are non-holes
571 * in the direct blocks after the problem block, move them down so
572 * that there's somewhat less lossage.  Doing this for indirect blocks
573 * is left as an exercise for the reader.
574 */
575static void
576collapse_dirhole(fsck_ino_t inumber, struct inodesc *idesc)
577{
578	offset_t new_size;
579	int blocks;
580
581	if (idesc->id_firsthole < 0) {
582		return;
583	}
584
585	/*
586	 * Since truncino() adjusts the size, we don't need to do that here,
587	 * but we have to tell it what final size we want.
588	 *
589	 * We need to count from block zero up through the last block
590	 * before the hole.  If the hole is in the indirect blocks, chop at
591	 * the start of the nearest level of indirection.  Orphans will
592	 * get reconnected, so we're not actually losing anything by doing
593	 * it this way, and we're simplifying truncation significantly.
594	 */
595	new_size = idesc->id_firsthole * (offset_t)sblock.fs_bsize;
596	blocks = howmany(new_size, sblock.fs_bsize);
597	if (blocks > NDADDR) {
598		if (blocks < (NDADDR + NINDIR(&sblock)))
599			blocks = NDADDR;
600		else if (blocks < (NDADDR + NINDIR(&sblock) +
601		    (NINDIR(&sblock) * NINDIR(&sblock))))
602			blocks = NDADDR + NINDIR(&sblock);
603		else
604			blocks = NDADDR + NINDIR(&sblock) +
605			    (NINDIR(&sblock) * NINDIR(&sblock));
606		new_size = blocks * sblock.fs_bsize;
607		if (debug)
608			(void) printf("to %lld (blocks %d)\n",
609			    (longlong_t)new_size, blocks);
610	}
611	truncino(inumber, new_size, TI_NOPARENT);
612
613	/*
614	 * Technically, there are still the original number of fragments
615	 * associated with the object.  However, that number is not used
616	 * to control anything, so we can do the in-memory truncation of
617	 * it without bad things happening.
618	 */
619	idesc->id_entryno = btodb(new_size);
620}
621
622int
623pass1check(struct inodesc *idesc)
624{
625	int res = KEEPON;
626	int anyout;
627	int nfrags;
628	daddr32_t lbn;
629	daddr32_t fragno = idesc->id_blkno;
630	struct dinode *dp;
631
632	/*
633	 * If this is a fallocate'd file, block numbers may be stored
634	 * as negative. In that case negate the negative numbers.
635	 */
636	dp = ginode(idesc->id_number);
637	if (dp->di_cflags & IFALLOCATE && fragno < 0)
638		fragno = -fragno;
639
640	if ((anyout = chkrange(fragno, idesc->id_numfrags)) != 0) {
641		/*
642		 * Note that blkerror() exits when preening.
643		 */
644		blkerror(idesc->id_number, "OUT OF RANGE",
645		    fragno, idesc->id_lbn * sblock.fs_frag);
646
647		dp = ginode(idesc->id_number);
648		if ((((dp->di_mode & IFMT) == IFDIR) ||
649		    ((dp->di_mode & IFMT) == IFATTRDIR)) &&
650		    (idesc->id_firsthole < 0)) {
651			idesc->id_firsthole = idesc->id_lbn;
652		}
653
654		if (++badblk >= MAXBAD) {
655			pwarn("EXCESSIVE BAD FRAGMENTS I=%u",
656			    idesc->id_number);
657			if (reply("CONTINUE") == 0)
658				errexit("Program terminated.");
659			/*
660			 * See discussion below as to why we don't
661			 * want to short-circuit the processing of
662			 * this inode.  However, we know that this
663			 * particular block is bad, so we don't need
664			 * to go through the dup check loop.
665			 */
666			return (SKIP | STOP);
667		}
668	}
669
670	/*
671	 * For each fragment, verify that it is a legal one (either
672	 * by having already found the entire run to be legal, or by
673	 * individual inspection), and if it is legal, see if we've
674	 * seen it before or not.  If we haven't, note that we've seen
675	 * it and continue on.  If we have (our in-core bitmap shows
676	 * it as already being busy), then this must be a duplicate
677	 * allocation.  Whine and moan accordingly.
678	 *
679	 * Note that for full-block allocations, this will produce
680	 * a complaint for each fragment making up the block (i.e.,
681	 * fs_frags' worth).  Among other things, this could be
682	 * considered artificially inflating the dup-block count.
683	 * However, since it is possible that one file has a full
684	 * fs block allocated, but another is only claiming a frag
685	 * or two out of the middle, we'll just live it.
686	 */
687	for (nfrags = 0; nfrags < idesc->id_numfrags; fragno++, nfrags++) {
688		if (anyout && chkrange(fragno, 1)) {
689			/* bad fragment number */
690			res = SKIP;
691		} else if (!testbmap(fragno)) {
692			/* no other claims seen as yet */
693			note_used(fragno);
694		} else {
695			/*
696			 * We have a duplicate claim for the same fragment.
697			 *
698			 * blkerror() exits when preening.
699			 *
700			 * We want to report all the dups up until
701			 * hitting MAXDUP.  Fortunately, blkerror()'s
702			 * side-effects on statemap[] are idempotent,
703			 * so the ``extra'' calls are harmless.
704			 */
705			lbn = idesc->id_lbn * sblock.fs_frag + nfrags;
706			if (dupblk < MAXDUP)
707				blkerror(idesc->id_number, "DUP", fragno, lbn);
708
709			/*
710			 * Use ==, so we only complain once, no matter
711			 * how far over the limit we end up going.
712			 */
713			if (++dupblk == MAXDUP) {
714				pwarn("EXCESSIVE DUPLICATE FRAGMENTS I=%u",
715				    idesc->id_number);
716				if (reply("CONTINUE") == 0)
717					errexit("Program terminated.");
718
719				/*
720				 * If we stop the traversal here, then
721				 * there may be more dups in the
722				 * inode's block list that don't get
723				 * flagged.  Later, if we're told to
724				 * clear one of the files claiming
725				 * these blocks, but not the other, we
726				 * will release blocks that are
727				 * actually still in use.  An additional
728				 * fsck run would be necessary to undo
729				 * the damage.  So, instead of the
730				 * traditional return (STOP) when told
731				 * to continue, we really do just continue.
732				 */
733			}
734			(void) find_dup_ref(fragno, idesc->id_number, lbn,
735			    DB_CREATE | DB_INCR);
736		}
737		/*
738		 * id_entryno counts the number of disk blocks found.
739		 */
740		idesc->id_entryno += btodb(sblock.fs_fsize);
741	}
742	return (res);
743}
744
745static void
746note_used(daddr32_t frag)
747{
748	n_blks++;
749	setbmap(frag);
750}
751