예제 #1
0
static int
pass1bcheck(struct inodesc *idesc)
{
	struct dups *dlp;
	int nfrags, res = KEEPON;
	daddr_t blkno = idesc->id_blkno;

	for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
		if (chkrange(blkno, 1))
			res = SKIP;
		for (dlp = duphead; dlp; dlp = dlp->next) {
			if (dlp->dup == blkno) {
				blkerror(idesc->id_number, "DUP", blkno);
				dlp->dup = duphead->dup;
				duphead->dup = blkno;
				duphead = duphead->next;
			}
			if (dlp == muldup)
				break;
		}
		if (muldup == 0 || duphead == muldup->next)
			return (STOP);
	}
	return (res);
}
예제 #2
0
int
pass1check(struct inodesc *idesc)
{
	int res = KEEPON;
	int anyout;
	int nfrags;
	daddr32_t lbn;
	daddr32_t fragno = idesc->id_blkno;
	struct dinode *dp;

	/*
	 * If this is a fallocate'd file, block numbers may be stored
	 * as negative. In that case negate the negative numbers.
	 */
	dp = ginode(idesc->id_number);
	if (dp->di_cflags & IFALLOCATE && fragno < 0)
		fragno = -fragno;

	if ((anyout = chkrange(fragno, idesc->id_numfrags)) != 0) {
		/*
		 * Note that blkerror() exits when preening.
		 */
		blkerror(idesc->id_number, "OUT OF RANGE",
		    fragno, idesc->id_lbn * sblock.fs_frag);

		dp = ginode(idesc->id_number);
		if ((((dp->di_mode & IFMT) == IFDIR) ||
		    ((dp->di_mode & IFMT) == IFATTRDIR)) &&
		    (idesc->id_firsthole < 0)) {
			idesc->id_firsthole = idesc->id_lbn;
		}

		if (++badblk >= MAXBAD) {
			pwarn("EXCESSIVE BAD FRAGMENTS I=%u",
			    idesc->id_number);
			if (reply("CONTINUE") == 0)
				errexit("Program terminated.");
			/*
			 * See discussion below as to why we don't
			 * want to short-circuit the processing of
			 * this inode.  However, we know that this
			 * particular block is bad, so we don't need
			 * to go through the dup check loop.
			 */
			return (SKIP | STOP);
		}
	}

	/*
	 * For each fragment, verify that it is a legal one (either
	 * by having already found the entire run to be legal, or by
	 * individual inspection), and if it is legal, see if we've
	 * seen it before or not.  If we haven't, note that we've seen
	 * it and continue on.  If we have (our in-core bitmap shows
	 * it as already being busy), then this must be a duplicate
	 * allocation.  Whine and moan accordingly.
	 *
	 * Note that for full-block allocations, this will produce
	 * a complaint for each fragment making up the block (i.e.,
	 * fs_frags' worth).  Among other things, this could be
	 * considered artificially inflating the dup-block count.
	 * However, since it is possible that one file has a full
	 * fs block allocated, but another is only claiming a frag
	 * or two out of the middle, we'll just live it.
	 */
	for (nfrags = 0; nfrags < idesc->id_numfrags; fragno++, nfrags++) {
		if (anyout && chkrange(fragno, 1)) {
			/* bad fragment number */
			res = SKIP;
		} else if (!testbmap(fragno)) {
			/* no other claims seen as yet */
			note_used(fragno);
		} else {
			/*
			 * We have a duplicate claim for the same fragment.
			 *
			 * blkerror() exits when preening.
			 *
			 * We want to report all the dups up until
			 * hitting MAXDUP.  Fortunately, blkerror()'s
			 * side-effects on statemap[] are idempotent,
			 * so the ``extra'' calls are harmless.
			 */
			lbn = idesc->id_lbn * sblock.fs_frag + nfrags;
			if (dupblk < MAXDUP)
				blkerror(idesc->id_number, "DUP", fragno, lbn);

			/*
			 * Use ==, so we only complain once, no matter
			 * how far over the limit we end up going.
			 */
			if (++dupblk == MAXDUP) {
				pwarn("EXCESSIVE DUPLICATE FRAGMENTS I=%u",
				    idesc->id_number);
				if (reply("CONTINUE") == 0)
					errexit("Program terminated.");

				/*
				 * If we stop the traversal here, then
				 * there may be more dups in the
				 * inode's block list that don't get
				 * flagged.  Later, if we're told to
				 * clear one of the files claiming
				 * these blocks, but not the other, we
				 * will release blocks that are
				 * actually still in use.  An additional
				 * fsck run would be necessary to undo
				 * the damage.  So, instead of the
				 * traditional return (STOP) when told
				 * to continue, we really do just continue.
				 */
			}
			(void) find_dup_ref(fragno, idesc->id_number, lbn,
			    DB_CREATE | DB_INCR);
		}
		/*
		 * id_entryno counts the number of disk blocks found.
		 */
		idesc->id_entryno += btodb(sblock.fs_fsize);
	}
	return (res);
}