Пример #1
0
/*
 * Compare the original cylinder group inode and block bitmaps with the
 * updated cylinder group inode and block bitmaps. Free inodes and blocks
 * that have been added. Complain if any previously freed inodes blocks
 * are now allocated.
 */
void
update_maps(
	struct cg *oldcg,	/* cylinder group of claimed allocations */
	struct cg *newcg,	/* cylinder group of determined allocations */
	int usesysctl)		/* 1 => use sysctl interface to update maps */
{
	int inomapsize, excessdirs;
	struct fs *fs = &sblock;

	inomapsize = howmany(fs->fs_ipg, CHAR_BIT);
	excessdirs = oldcg->cg_cs.cs_ndir - newcg->cg_cs.cs_ndir;
	if (excessdirs < 0) {
		pfatal("LOST %d DIRECTORIES\n", -excessdirs);
		excessdirs = 0;
	}
	if (excessdirs > 0)
		check_maps(cg_inosused(newcg), cg_inosused(oldcg), inomapsize,
		    oldcg->cg_cgx * (ufs2_daddr_t)fs->fs_ipg, "DIR", freedirs,
		    0, excessdirs, usesysctl);
	check_maps(cg_inosused(newcg), cg_inosused(oldcg), inomapsize,
	    oldcg->cg_cgx * (ufs2_daddr_t)fs->fs_ipg, "FILE", freefiles,
	    excessdirs, fs->fs_ipg, usesysctl);
	check_maps(cg_blksfree(oldcg), cg_blksfree(newcg),
	    howmany(fs->fs_fpg, CHAR_BIT),
	    oldcg->cg_cgx * (ufs2_daddr_t)fs->fs_fpg, "FRAG",
	    freeblks, 0, fs->fs_fpg, usesysctl);
}
Пример #2
0
/*
 * Allocate an inode on the disk
 */
void
iput(union dinode *ip, ino_t ino)
{
	union dinodep dp;

	bread(&disk, part_ofs + fsbtodb(&sblock, cgtod(&sblock, 0)), (char *)&acg,
	    sblock.fs_cgsize);
	if (acg.cg_magic != CG_MAGIC) {
		printf("cg 0: bad magic number\n");
		exit(31);
	}
	acg.cg_cs.cs_nifree--;
	setbit(cg_inosused(&acg), ino);
	if (cgput(&disk, &acg) != 0)
		err(1, "iput: cgput: %s", disk.d_error);
	sblock.fs_cstotal.cs_nifree--;
	fscs[0].cs_nifree--;
	if (getinode(&disk, &dp, ino) == -1) {
		printf("iput: %s\n", disk.d_error);
		exit(32);
	}
	if (sblock.fs_magic == FS_UFS1_MAGIC)
		*dp.dp1 = ip->dp1;
	else
		*dp.dp2 = ip->dp2;
	putinode(&disk);
}
Пример #3
0
int
dumpcg(void)
{
	time_t cgtime;
	off_t cur;
	int i, j;

	printf("\ncg %d:\n", disk.d_lcg);
	cur = fsbtodb(&afs, cgtod(&afs, disk.d_lcg)) * disk.d_bsize;
	switch (disk.d_ufs) {
	case 2:
		cgtime = acg.cg_time;
		printf("magic\t%x\ttell\t%jx\ttime\t%s",
		    acg.cg_magic, (intmax_t)cur, ctime(&cgtime));
		printf("cgx\t%d\tndblk\t%d\tniblk\t%d\tinitiblk %d\tunrefs %d\n",
		    acg.cg_cgx, acg.cg_ndblk, acg.cg_niblk, acg.cg_initediblk,
		    acg.cg_unrefs);
		break;
	case 1:
		cgtime = acg.cg_old_time;
		printf("magic\t%x\ttell\t%jx\ttime\t%s",
		    acg.cg_magic, (intmax_t)cur, ctime(&cgtime));
		printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n",
		    acg.cg_cgx, acg.cg_old_ncyl, acg.cg_old_niblk,
		    acg.cg_ndblk);
		break;
	default:
		break;
	}
	printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
	    acg.cg_cs.cs_nbfree, acg.cg_cs.cs_ndir,
	    acg.cg_cs.cs_nifree, acg.cg_cs.cs_nffree);
	printf("rotor\t%d\tirotor\t%d\tfrotor\t%d\nfrsum",
	    acg.cg_rotor, acg.cg_irotor, acg.cg_frotor);
	for (i = 1, j = 0; i < afs.fs_frag; i++) {
		printf("\t%d", acg.cg_frsum[i]);
		j += i * acg.cg_frsum[i];
	}
	printf("\nsum of frsum: %d", j);
	if (afs.fs_contigsumsize > 0) {
		for (i = 1; i < afs.fs_contigsumsize; i++) {
			if ((i - 1) % 8 == 0)
				printf("\nclusters %d-%d:", i,
				    afs.fs_contigsumsize - 1 < i + 7 ?
				    afs.fs_contigsumsize - 1 : i + 7);
			printf("\t%d", cg_clustersum(&acg)[i]);
		}
		printf("\nclusters size %d and over: %d\n",
		    afs.fs_contigsumsize,
		    cg_clustersum(&acg)[afs.fs_contigsumsize]);
		printf("clusters free:\t");
		pbits(cg_clustersfree(&acg), acg.cg_nclusterblks);
	} else
		printf("\n");
	printf("inodes used:\t");
	pbits(cg_inosused(&acg), afs.fs_ipg);
	printf("blks free:\t");
	pbits(cg_blksfree(&acg), afs.fs_fpg);
	return (0);
}
Пример #4
0
/*
 * Allocate an inode on the disk
 */
void
iput(union dinode *ip, ino_t ino)
{
	ufs2_daddr_t d;

	bread(&disk, part_ofs + fsbtodb(&sblock, cgtod(&sblock, 0)), (char *)&acg,
	    sblock.fs_cgsize);
	if (acg.cg_magic != CG_MAGIC) {
		printf("cg 0: bad magic number\n");
		exit(31);
	}
	acg.cg_cs.cs_nifree--;
	setbit(cg_inosused(&acg), ino);
	wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
	    (char *)&acg);
	sblock.fs_cstotal.cs_nifree--;
	fscs[0].cs_nifree--;
	if (ino >= (unsigned long)sblock.fs_ipg * sblock.fs_ncg) {
		printf("fsinit: inode value out of range (%ju).\n",
		    (uintmax_t)ino);
		exit(32);
	}
	d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino));
	bread(&disk, part_ofs + d, (char *)iobuf, sblock.fs_bsize);
	if (sblock.fs_magic == FS_UFS1_MAGIC)
		((struct ufs1_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] =
		    ip->dp1;
	else
		((struct ufs2_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] =
		    ip->dp2;
	wtfs(d, sblock.fs_bsize, (char *)iobuf);
}
Пример #5
0
/*
 * allocate an unused inode
 */
ino_t
allocino(ino_t request, int type)
{
	ino_t ino;
	union dinode *dp;
	struct bufarea *cgbp;
	struct cg *cgp;
	int cg;

	if (request == 0)
		request = ROOTINO;
	else if (inoinfo(request)->ino_state != USTATE)
		return (0);
	for (ino = request; ino < maxino; ino++)
		if (inoinfo(ino)->ino_state == USTATE)
			break;
	if (ino == maxino)
		return (0);
	cg = ino_to_cg(&sblock, ino);
	cgbp = cgget(cg);
	cgp = cgbp->b_un.b_cg;
	if (!check_cgmagic(cg, cgbp))
		return (0);
	setbit(cg_inosused(cgp), ino % sblock.fs_ipg);
	cgp->cg_cs.cs_nifree--;
	switch (type & IFMT) {
	case IFDIR:
		inoinfo(ino)->ino_state = DSTATE;
		cgp->cg_cs.cs_ndir++;
		break;
	case IFREG:
	case IFLNK:
		inoinfo(ino)->ino_state = FSTATE;
		break;
	default:
		return (0);
	}
	dirty(cgbp);
	dp = ginode(ino);
	DIP_SET(dp, di_db[0], allocblk((long)1));
	if (DIP(dp, di_db[0]) == 0) {
		inoinfo(ino)->ino_state = USTATE;
		return (0);
	}
	DIP_SET(dp, di_mode, type);
	DIP_SET(dp, di_flags, 0);
	DIP_SET(dp, di_atime, time(NULL));
	DIP_SET(dp, di_ctime, DIP(dp, di_atime));
	DIP_SET(dp, di_mtime, DIP(dp, di_ctime));
	DIP_SET(dp, di_mtimensec, 0);
	DIP_SET(dp, di_ctimensec, 0);
	DIP_SET(dp, di_atimensec, 0);
	DIP_SET(dp, di_size, sblock.fs_fsize);
	DIP_SET(dp, di_blocks, btodb(sblock.fs_fsize));
	n_files++;
	inodirty();
	inoinfo(ino)->ino_type = IFTODT(type);
	return (ino);
}
Пример #6
0
/*
 * allocate an unused inode
 */
ufs1_ino_t
allocino(ufs1_ino_t request, int type)
{
	ufs1_ino_t ino;
	struct ufs1_dinode *dp;
	struct cg *cgp = &cgrp;
	int cg;

	if (request == 0)
		request = ROOTINO;
	else if (inoinfo(request)->ino_state != USTATE)
		return (0);
	for (ino = request; ino < maxino; ino++)
		if (inoinfo(ino)->ino_state == USTATE)
			break;
	if (ino == maxino)
		return (0);
	cg = ino_to_cg(&sblock, ino);
	getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
	if (!cg_chkmagic(cgp))
		pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
	setbit(cg_inosused(cgp), ino % sblock.fs_ipg);
	cgp->cg_cs.cs_nifree--;
	switch (type & IFMT) {
	case IFDIR:
		inoinfo(ino)->ino_state = DSTATE;
		cgp->cg_cs.cs_ndir++;
		break;
	case IFREG:
	case IFLNK:
		inoinfo(ino)->ino_state = FSTATE;
		break;
	default:
		return (0);
	}
	cgdirty();
	dp = ginode(ino);
	dp->di_db[0] = allocblk((long)1);
	if (dp->di_db[0] == 0) {
		inoinfo(ino)->ino_state = USTATE;
		return (0);
	}
	dp->di_mode = type;
	dp->di_flags = 0;
	dp->di_atime = time(NULL);
	dp->di_mtime = dp->di_ctime = dp->di_atime;
	dp->di_mtimensec = dp->di_ctimensec = dp->di_atimensec = 0;
	dp->di_size = sblock.fs_fsize;
	dp->di_blocks = btodb(sblock.fs_fsize);
	n_files++;
	inodirty();
	if (newinofmt)
		inoinfo(ino)->ino_type = IFTODT(type);
	return (ino);
}
Пример #7
0
static union dinode *
get_inode(int fd, struct fs *super, ino_t ino)
{
	static caddr_t ipbuf;
	static struct cg *cgp;
	static ino_t last;
	static int cg;
	struct ufs2_dinode *di2;

	if (fd < 0) {		/* flush cache */
		if (ipbuf) {
			free(ipbuf);
			ipbuf = NULL;
			if (super != NULL && super->fs_magic == FS_UFS2_MAGIC) {
				free(cgp);
				cgp = NULL;
			}
		}
		return 0;
	}

	if (!ipbuf || ino < last || ino >= last + INOCNT(super)) {
		if (super->fs_magic == FS_UFS2_MAGIC &&
		    (!cgp || cg != ino_to_cg(super, ino))) {
			cg = ino_to_cg(super, ino);
			if (!cgp && !(cgp = malloc(super->fs_cgsize)))
				errx(1, "allocate cg");
			if (pread(fd, cgp, super->fs_cgsize,
			    (off_t)cgtod(super, cg) << super->fs_fshift)
			    != super->fs_cgsize)
			if (read(fd, cgp, super->fs_cgsize) != super->fs_cgsize)
				err(1, "read cg");
			if (!cg_chkmagic(cgp))
				errx(1, "cg has bad magic");
		}
		if (!ipbuf && !(ipbuf = malloc(INOSZ(super))))
			err(1, "allocate inodes");
		last = (ino / INOCNT(super)) * INOCNT(super);
		if (lseek(fd, (off_t)ino_to_fsba(super, last)
		    << super->fs_fshift, SEEK_SET) < 0 ||
		    read(fd, ipbuf, INOSZ(super)) != INOSZ(super)) {
			err(1, "read inodes");
		}
	}

	if (super->fs_magic == FS_UFS1_MAGIC)
		return ((union dinode *)
		    &((struct ufs1_dinode *)ipbuf)[ino % INOCNT(super)]);
	di2 = &((struct ufs2_dinode *)ipbuf)[ino % INOCNT(super)];
	/* If the inode is unused, it might be unallocated too, so zero it. */
	if (isclr(cg_inosused(cgp), ino % super->fs_ipg))
		memset(di2, 0, sizeof(*di2));
	return ((union dinode *)di2);
}
Пример #8
0
void
fs_mapinodes(ino_t maxino, int64_t *tapesize, int *anydirskipped)
{
	int i, cg, inosused;
	struct cg *cgp;
	ino_t ino;
	char *cp;

	if ((cgp = malloc(sblock->fs_cgsize)) == NULL)
		quit("fs_mapinodes: cannot allocate memory.\n");

	for (cg = 0; cg < sblock->fs_ncg; cg++) {
		ino = cg * sblock->fs_ipg;
		bread(fsbtodb(sblock, cgtod(sblock, cg)), (char *)cgp,
		    sblock->fs_cgsize);
		if (sblock->fs_magic == FS_UFS2_MAGIC)
			inosused = cgp->cg_initediblk;
		else
			inosused = sblock->fs_ipg;
		/*
		 * If we are using soft updates, then we can trust the
		 * cylinder group inode allocation maps to tell us which
		 * inodes are allocated. We will scan the used inode map
		 * to find the inodes that are really in use, and then
		 * read only those inodes in from disk.
		 */
		if (sblock->fs_flags & FS_DOSOFTDEP) {
			if (!cg_chkmagic(cgp))
				quit("mapfiles: cg %d: bad magic number\n", cg);
			cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT];
			for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) {
				if (*cp == 0)
					continue;
				for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) {
					if (*cp & i)
						break;
					inosused--;
				}
				break;
			}
			if (inosused <= 0)
				continue;
		}
		for (i = 0; i < inosused; i++, ino++) {
			if (ino < ROOTINO)
				continue;
			mapfileino(ino, tapesize, anydirskipped);
		}
	}

	free(cgp);
}
Пример #9
0
ino_t
cgialloc(struct uufsd *disk)
{
	struct ufs2_dinode *dp2;
	u_int8_t *inosused;
	struct cg *cgp;
	struct fs *fs;
	ino_t ino;
	int i;

	fs = &disk->d_fs;
	cgp = &disk->d_cg;
	inosused = cg_inosused(cgp);
	for (ino = 0; ino < fs->fs_ipg; ino++)
		if (isclr(inosused, ino))
			goto gotit;
	return (0);
gotit:
	if (fs->fs_magic == FS_UFS2_MAGIC &&
	    ino + INOPB(fs) > cgp->cg_initediblk &&
	    cgp->cg_initediblk < cgp->cg_niblk) {
		char block[MAXBSIZE];
		bzero(block, (int)fs->fs_bsize);
		dp2 = (struct ufs2_dinode *)&block;
		for (i = 0; i < INOPB(fs); i++) {
			dp2->di_gen = arc4random() / 2 + 1;
			dp2++;
		}
		if (bwrite(disk, ino_to_fsba(fs,
		    cgp->cg_cgx * fs->fs_ipg + cgp->cg_initediblk),
		    block, fs->fs_bsize))
			return (0);
		cgp->cg_initediblk += INOPB(fs);
	}

	setbit(inosused, ino);
	cgp->cg_irotor = ino;
	cgp->cg_cs.cs_nifree--;
	fs->fs_cstotal.cs_nifree--;
	fs->fs_cs(fs, cgp->cg_cgx).cs_nifree--;
	fs->fs_fmod = 1;

	return (ino + (cgp->cg_cgx * fs->fs_ipg));
}
Пример #10
0
/*
 * Dump the inode allocation map in one cylinder group.
 */
void
dbg_dump_inmap(struct fs *sb, const char *comment, struct cg *cgr)
{
	int j,k,l,e;
	unsigned char *cp;

	if (!dbg_log)
		return;

	fprintf(dbg_log, "===== START INODE ALLOCATION MAP =====\n");
	fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment);
	indent++;

	cp = (unsigned char *)cg_inosused(cgr);
	e = sb->fs_ipg / 8;
	for (j = 0; j < e; j += 32) {
		fprintf(dbg_log, "%08x: ", j);
		for (k = 0; k < 32; k += 8) {
			if (j + k + 8 < e) {
				fprintf(dbg_log,
				    "%02x%02x%02x%02x%02x%02x%02x%02x ", 
				    cp[0], cp[1], cp[2], cp[3],
				    cp[4], cp[5], cp[6], cp[7]);
			} else {
				for (l = 0; (l < 8) && (j + k + l < e); l++) {
					fprintf(dbg_log, "%02x", cp[l]);
				}
			}
			cp += 8;
		}
		fprintf(dbg_log, "\n");
	}

	indent--;
	fprintf(dbg_log, "===== END INODE ALLOCATION MAP =====\n");

	return;
}
Пример #11
0
/*
 * Allocate an inode on the disk
 */
void
iput(union dinode *ip, ino_t ino)
{
	daddr64_t d;

	if (Oflag <= 1)
		ip->dp1.di_gen = (u_int32_t)arc4random();
	else
		ip->dp2.di_gen = (u_int32_t)arc4random();

	rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
	    (char *)&acg);
	if (acg.cg_magic != CG_MAGIC)
		errx(41, "cg 0: bad magic number");

	acg.cg_cs.cs_nifree--;
	setbit(cg_inosused(&acg), ino);

	wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
	    (char *)&acg);

	sblock.fs_cstotal.cs_nifree--;
	fscs[0].cs_nifree--;
	if (ino >= sblock.fs_ipg * sblock.fs_ncg)
		errx(32, "fsinit: inode value %d out of range", ino);
	d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino));
	rdfs(d, sblock.fs_bsize, iobuf);

	if (Oflag <= 1)
		((struct ufs1_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] =
		    ip->dp1;
	else
		((struct ufs2_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] =
		    ip->dp2;

	wtfs(d, sblock.fs_bsize, iobuf);
}
Пример #12
0
void
pass1(void)
{
    struct inostat *info;
    struct inodesc idesc;
    struct bufarea *cgbp;
    struct cg *cgp;
    ino_t inumber, inosused, mininos;
    ufs2_daddr_t i, cgd;
    u_int8_t *cp;
    int c, rebuildcg;

    badblk = dupblk = lastino = 0;

    /*
     * Set file system reserved blocks in used block map.
     */
    for (c = 0; c < sblock.fs_ncg; c++) {
        cgd = cgdmin(&sblock, c);
        if (c == 0) {
            i = cgbase(&sblock, c);
        } else
            i = cgsblock(&sblock, c);
        for (; i < cgd; i++)
            setbmap(i);
    }
    i = sblock.fs_csaddr;
    cgd = i + howmany(sblock.fs_cssize, sblock.fs_fsize);
    for (; i < cgd; i++)
        setbmap(i);

    /*
     * Find all allocated blocks.
     */
    memset(&idesc, 0, sizeof(struct inodesc));
    idesc.id_func = pass1check;
    n_files = n_blks = 0;
    for (c = 0; c < sblock.fs_ncg; c++) {
        inumber = c * sblock.fs_ipg;
        setinodebuf(inumber);
        cgbp = cgget(c);
        cgp = cgbp->b_un.b_cg;
        rebuildcg = 0;
        if (!check_cgmagic(c, cgbp))
            rebuildcg = 1;
        if (!rebuildcg && sblock.fs_magic == FS_UFS2_MAGIC) {
            inosused = cgp->cg_initediblk;
            if (inosused > sblock.fs_ipg) {
                pfatal(
                    "Too many initialized inodes (%ju > %d) in cylinder group %d\nReset to %d\n",
                    (uintmax_t)inosused,
                    sblock.fs_ipg, c, sblock.fs_ipg);
                inosused = sblock.fs_ipg;
            }
        } else {
            inosused = sblock.fs_ipg;
        }
        if (got_siginfo) {
            printf("%s: phase 1: cyl group %d of %d (%d%%)\n",
                   cdevname, c, sblock.fs_ncg,
                   c * 100 / sblock.fs_ncg);
            got_siginfo = 0;
        }
        if (got_sigalarm) {
            setproctitle("%s p1 %d%%", cdevname,
                         c * 100 / sblock.fs_ncg);
            got_sigalarm = 0;
        }
        /*
         * If we are using soft updates, then we can trust the
         * cylinder group inode allocation maps to tell us which
         * inodes are allocated. We will scan the used inode map
         * to find the inodes that are really in use, and then
         * read only those inodes in from disk.
         */
        if ((preen || inoopt) && usedsoftdep && !rebuildcg) {
            cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT];
            for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) {
                if (*cp == 0)
                    continue;
                for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) {
                    if (*cp & i)
                        break;
                    inosused--;
                }
                break;
            }
            if (inosused < 0)
                inosused = 0;
        }
        /*
         * Allocate inoinfo structures for the allocated inodes.
         */
        inostathead[c].il_numalloced = inosused;
        if (inosused == 0) {
            inostathead[c].il_stat = NULL;
            continue;
        }
        info = Calloc((unsigned)inosused, sizeof(struct inostat));
        if (info == NULL)
            errx(EEXIT, "cannot alloc %u bytes for inoinfo",
                 (unsigned)(sizeof(struct inostat) * inosused));
        inostathead[c].il_stat = info;
        /*
         * Scan the allocated inodes.
         */
        for (i = 0; i < inosused; i++, inumber++) {
            if (inumber < ROOTINO) {
                (void)getnextinode(inumber, rebuildcg);
                continue;
            }
            /*
             * NULL return indicates probable end of allocated
             * inodes during cylinder group rebuild attempt.
             * We always keep trying until we get to the minimum
             * valid number for this cylinder group.
             */
            if (checkinode(inumber, &idesc, rebuildcg) == 0 &&
                    i > cgp->cg_initediblk)
                break;
        }
        /*
         * This optimization speeds up future runs of fsck
         * by trimming down the number of inodes in cylinder
         * groups that formerly had many inodes but now have
         * fewer in use.
         */
        mininos = roundup(inosused + INOPB(&sblock), INOPB(&sblock));
        if (inoopt && !preen && !rebuildcg &&
                sblock.fs_magic == FS_UFS2_MAGIC &&
                cgp->cg_initediblk > 2 * INOPB(&sblock) &&
                mininos < cgp->cg_initediblk) {
            i = cgp->cg_initediblk;
            if (mininos < 2 * INOPB(&sblock))
                cgp->cg_initediblk = 2 * INOPB(&sblock);
            else
                cgp->cg_initediblk = mininos;
            pwarn("CYLINDER GROUP %d: RESET FROM %ju TO %d %s\n",
                  c, i, cgp->cg_initediblk, "VALID INODES");
            dirty(cgbp);
        }
        if (inosused < sblock.fs_ipg)
            continue;
        lastino += 1;
        if (lastino < (c * sblock.fs_ipg))
            inosused = 0;
        else
            inosused = lastino - (c * sblock.fs_ipg);
        if (rebuildcg && inosused > cgp->cg_initediblk &&
                sblock.fs_magic == FS_UFS2_MAGIC) {
            cgp->cg_initediblk = roundup(inosused, INOPB(&sblock));
            pwarn("CYLINDER GROUP %d: FOUND %d VALID INODES\n", c,
                  cgp->cg_initediblk);
        }
        /*
         * If we were not able to determine in advance which inodes
         * were in use, then reduce the size of the inoinfo structure
         * to the size necessary to describe the inodes that we
         * really found.
         */
        if (inumber == lastino)
            continue;
        inostathead[c].il_numalloced = inosused;
        if (inosused == 0) {
            free(inostathead[c].il_stat);
            inostathead[c].il_stat = NULL;
            continue;
        }
        info = Calloc((unsigned)inosused, sizeof(struct inostat));
        if (info == NULL)
            errx(EEXIT, "cannot alloc %u bytes for inoinfo",
                 (unsigned)(sizeof(struct inostat) * inosused));
        memmove(info, inostathead[c].il_stat, inosused * sizeof(*info));
        free(inostathead[c].il_stat);
        inostathead[c].il_stat = info;
    }
Пример #13
0
/*
 * Initialize a cylinder group.
 */
void
initcg(int cylno, time_t utime)
{
	int i, j, d, dlower, dupper, blkno, start;
	daddr64_t cbase, dmax;
	struct ufs1_dinode *dp1;
	struct ufs2_dinode *dp2;
	struct csum *cs;

	/*
	 * Determine block bounds for cylinder group.  Allow space for
	 * super block summary information in first cylinder group.
	 */
	cbase = cgbase(&sblock, cylno);
	dmax = cbase + sblock.fs_fpg;
	if (dmax > sblock.fs_size)
		dmax = sblock.fs_size;
	if (fsbtodb(&sblock, cgsblock(&sblock, cylno)) + iobufsize / sectorsize
	    > fssize)
		errx(40, "inode table does not fit in cylinder group");

	dlower = cgsblock(&sblock, cylno) - cbase;
	dupper = cgdmin(&sblock, cylno) - cbase;
	if (cylno == 0)
		dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
	cs = &fscs[cylno];
	memset(&acg, 0, sblock.fs_cgsize);
	acg.cg_ffs2_time = utime;
	acg.cg_magic = CG_MAGIC;
	acg.cg_cgx = cylno;
	acg.cg_ffs2_niblk = sblock.fs_ipg;
	acg.cg_initediblk = MIN(sblock.fs_ipg, 2 * INOPB(&sblock));
	acg.cg_ndblk = dmax - cbase;

	start = sizeof(struct cg);
	if (Oflag <= 1) {
		/* Hack to maintain compatibility with old fsck. */
		if (cylno == sblock.fs_ncg - 1)
			acg.cg_ncyl = 0;
		else
			acg.cg_ncyl = sblock.fs_cpg;
		acg.cg_time = acg.cg_ffs2_time;
		acg.cg_ffs2_time = 0;
		acg.cg_niblk = acg.cg_ffs2_niblk;
		acg.cg_ffs2_niblk = 0;
		acg.cg_initediblk = 0;
		acg.cg_btotoff = start;
		acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t);
		acg.cg_iusedoff = acg.cg_boff +
		    sblock.fs_cpg * sizeof(u_int16_t);
	} else {
		acg.cg_iusedoff = start;
	}

	acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT);
	acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT);
	if (acg.cg_nextfreeoff > sblock.fs_cgsize)
		errx(37, "panic: cylinder group too big: %d > %d",
		    acg.cg_nextfreeoff, sblock.fs_cgsize);
	acg.cg_cs.cs_nifree += sblock.fs_ipg;
	if (cylno == 0) {
		for (i = 0; i < ROOTINO; i++) {
			setbit(cg_inosused(&acg), i);
			acg.cg_cs.cs_nifree--;
		}
	}
	if (cylno > 0) {
		/*
		 * In cylno 0, space is reserved for boot and super blocks.
		 */
		for (d = 0; d < dlower; d += sblock.fs_frag) {
			blkno = d / sblock.fs_frag;
			setblock(&sblock, cg_blksfree(&acg), blkno);
			acg.cg_cs.cs_nbfree++;
			if (Oflag <= 1) {
				cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
				cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
				    [cbtorpos(&sblock, d)]++;
			}
		}
	}
	if ((i = dupper % sblock.fs_frag)) {
		acg.cg_frsum[sblock.fs_frag - i]++;
		for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
			setbit(cg_blksfree(&acg), dupper);
			acg.cg_cs.cs_nffree++;
		}
	}
	for (d = dupper;
	    d + sblock.fs_frag <= acg.cg_ndblk;
	    d += sblock.fs_frag) {
		blkno = d / sblock.fs_frag;
		setblock(&sblock, cg_blksfree(&acg), blkno);
		acg.cg_cs.cs_nbfree++;
		if (Oflag <= 1) {
			cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
			cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
			    [cbtorpos(&sblock, d)]++;
		}
	}
	if (d < acg.cg_ndblk) {
		acg.cg_frsum[acg.cg_ndblk - d]++;
		for (; d < acg.cg_ndblk; d++) {
			setbit(cg_blksfree(&acg), d);
			acg.cg_cs.cs_nffree++;
		}
	}
	*cs = acg.cg_cs;

	/*
	 * Write out the duplicate superblock, the cylinder group map
	 * and two blocks worth of inodes in a single write.
	 */
	start = sblock.fs_bsize > SBLOCKSIZE ? sblock.fs_bsize : SBLOCKSIZE;
	bcopy((char *)&acg, &iobuf[start], sblock.fs_cgsize);
	start += sblock.fs_bsize;
	dp1 = (struct ufs1_dinode *)(&iobuf[start]);
	dp2 = (struct ufs2_dinode *)(&iobuf[start]);
	for (i = MIN(sblock.fs_ipg, 2 * INOPB(&sblock)); i != 0; i--) {
		if (sblock.fs_magic == FS_UFS1_MAGIC) {
			dp1->di_gen = (u_int32_t)arc4random();
			dp1++;
		} else {
			dp2->di_gen = (u_int32_t)arc4random();
			dp2++;
		}
	}
	wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf);

	if (Oflag <= 1) {
		/* Initialize inodes for FFS1. */
		for (i = 2 * sblock.fs_frag;
		    i < sblock.fs_ipg / INOPF(&sblock);
		    i += sblock.fs_frag) {
			dp1 = (struct ufs1_dinode *)(&iobuf[start]);
			for (j = 0; j < INOPB(&sblock); j++) {
				dp1->di_gen = (u_int32_t)arc4random();
				dp1++;
			}
			wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
			    sblock.fs_bsize, &iobuf[start]);
		}
	}
}
Пример #14
0
/*
 * Scan the specified file system to check quota(s) present on it.
 */
int
chkquota(char *specname, struct quotafile *qfu, struct quotafile *qfg)
{
	struct fileusage *fup;
	union dinode *dp;
	int cg, i, mode, errs = 0;
	ino_t ino, inosused, userino = 0, groupino = 0;
	dev_t dev, userdev = 0, groupdev = 0;
	struct stat sb;
	const char *mntpt;
	char *cp;

	if (qfu != NULL)
		mntpt = quota_fsname(qfu);
	else if (qfg != NULL)
		mntpt = quota_fsname(qfg);
	else
		errx(1, "null quotafile information passed to chkquota()\n");
	if (cflag) {
		if (vflag && qfu != NULL)
			printf("%s: convert user quota to %d bits\n",
			    mntpt, cflag);
		if (qfu != NULL && quota_convert(qfu, cflag) < 0) {
			if (errno == EBADF)
				errx(1,
				    "%s: cannot convert an active quota file",
				    mntpt);
			err(1, "user quota conversion to size %d failed",
			    cflag);
		}
		if (vflag && qfg != NULL)
			printf("%s: convert group quota to %d bits\n",
			    mntpt, cflag);
		if (qfg != NULL && quota_convert(qfg, cflag) < 0) {
			if (errno == EBADF)
				errx(1,
				    "%s: cannot convert an active quota file",
				    mntpt);
			err(1, "group quota conversion to size %d failed",
			    cflag);
		}
	}
	if ((fi = open(specname, O_RDONLY, 0)) < 0) {
		warn("%s", specname);
		return (1);
	}
	if ((stat(mntpt, &sb)) < 0) {
		warn("%s", mntpt);
		return (1);
	}
	dev = sb.st_dev;
	if (vflag) {
		(void)printf("*** Checking ");
		if (qfu)
			(void)printf("user%s", qfg ? " and " : "");
		if (qfg)
			(void)printf("group");
		(void)printf(" quotas for %s (%s)\n", specname, mntpt);
	}
	if (qfu) {
		if (stat(quota_qfname(qfu), &sb) == 0) {
			userino = sb.st_ino;
			userdev = sb.st_dev;
		}
	}
	if (qfg) {
		if (stat(quota_qfname(qfg), &sb) == 0) {
			groupino = sb.st_ino;
			groupdev = sb.st_dev;
		}
	}
	sync();
	dev_bsize = 1;
	for (i = 0; sblock_try[i] != -1; i++) {
		bread(sblock_try[i], (char *)&sblock, (long)SBLOCKSIZE);
		if ((sblock.fs_magic == FS_UFS1_MAGIC ||
		     (sblock.fs_magic == FS_UFS2_MAGIC &&
		      sblock.fs_sblockloc == sblock_try[i])) &&
		    sblock.fs_bsize <= MAXBSIZE &&
		    sblock.fs_bsize >= sizeof(struct fs))
			break;
	}
	if (sblock_try[i] == -1) {
		warn("Cannot find file system superblock");
		return (1);
	}
	dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
	maxino = sblock.fs_ncg * sblock.fs_ipg;
	for (cg = 0; cg < sblock.fs_ncg; cg++) {
		ino = cg * sblock.fs_ipg;
		setinodebuf(ino);
		bread(fsbtodb(&sblock, cgtod(&sblock, cg)), (char *)(&cgblk),
		    sblock.fs_cgsize);
		if (sblock.fs_magic == FS_UFS2_MAGIC)
			inosused = cgblk.cg_initediblk;
		else
			inosused = sblock.fs_ipg;
		/*
		 * If we are using soft updates, then we can trust the
		 * cylinder group inode allocation maps to tell us which
		 * inodes are allocated. We will scan the used inode map
		 * to find the inodes that are really in use, and then
		 * read only those inodes in from disk.
		 */
		if (sblock.fs_flags & FS_DOSOFTDEP) {
			if (!cg_chkmagic(&cgblk))
				errx(1, "CG %d: BAD MAGIC NUMBER\n", cg);
			cp = &cg_inosused(&cgblk)[(inosused - 1) / CHAR_BIT];
			for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) {
				if (*cp == 0)
					continue;
				for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) {
					if (*cp & i)
						break;
					inosused--;
				}
				break;
			}
			if (inosused <= 0)
				continue;
		}
		for (i = 0; i < inosused; i++, ino++) {
			if ((dp = getnextinode(ino)) == NULL || ino < ROOTINO ||
			    (mode = DIP(dp, di_mode) & IFMT) == 0)
				continue;
			/*
			 * XXX: Do not account for UIDs or GIDs that appear
			 * to be negative to prevent generating 100GB+
			 * quota files.
			 */
			if ((int)DIP(dp, di_uid) < 0 ||
			    (int)DIP(dp, di_gid) < 0) {
				if (vflag) {
					if (aflag)
						(void)printf("%s: ", mntpt);
			(void)printf("out of range UID/GID (%u/%u) ino=%ju\n",
					    DIP(dp, di_uid), DIP(dp,di_gid),
					    (uintmax_t)ino);
				}
				continue;
			}

			/*
			 * Do not account for file system snapshot files
			 * or the actual quota data files to be consistent
			 * with how they are handled inside the kernel.
			 */
#ifdef	SF_SNAPSHOT
			if (DIP(dp, di_flags) & SF_SNAPSHOT)
				continue;
#endif
			if ((ino == userino && dev == userdev) ||
			    (ino == groupino && dev == groupdev))
				continue;
			if (qfg) {
				fup = addid((u_long)DIP(dp, di_gid), GRPQUOTA,
				    (char *)0, mntpt);
				fup->fu_curinodes++;
				if (mode == IFREG || mode == IFDIR ||
				    mode == IFLNK)
					fup->fu_curblocks += DIP(dp, di_blocks);
			}
			if (qfu) {
				fup = addid((u_long)DIP(dp, di_uid), USRQUOTA,
				    (char *)0, mntpt);
				fup->fu_curinodes++;
				if (mode == IFREG || mode == IFDIR ||
				    mode == IFLNK)
					fup->fu_curblocks += DIP(dp, di_blocks);
			}
		}
	}
	freeinodebuf();
	if (qfu)
		errs += update(mntpt, qfu, USRQUOTA);
	if (qfg)
		errs += update(mntpt, qfg, GRPQUOTA);
	close(fi);
	(void)fflush(stdout);
	return (errs);
}
/*
 * Initialize a cylinder group.
 */
static void
initcg(int cylno, time_t utime, const fsinfo_t *fsopts)
{
	daddr_t cbase, dmax;
	int i, j, d, dlower, dupper, blkno;
	struct ufs1_dinode *dp1;
	struct ufs2_dinode *dp2;
	int start;

	/*
	 * Determine block bounds for cylinder group.
	 * Allow space for super block summary information in first
	 * cylinder group.
	 */
	cbase = cgbase(&sblock, cylno);
	dmax = cbase + sblock.fs_fpg;
	if (dmax > sblock.fs_size)
		dmax = sblock.fs_size;
	dlower = cgsblock(&sblock, cylno) - cbase;
	dupper = cgdmin(&sblock, cylno) - cbase;
	if (cylno == 0)
		dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
	memset(&acg, 0, sblock.fs_cgsize);
	acg.cg_time = utime;
	acg.cg_magic = CG_MAGIC;
	acg.cg_cgx = cylno;
	acg.cg_niblk = sblock.fs_ipg;
	acg.cg_initediblk = sblock.fs_ipg < 2 * FFS_INOPB(&sblock) ?
	    sblock.fs_ipg : 2 * FFS_INOPB(&sblock);
	acg.cg_ndblk = dmax - cbase;
	if (sblock.fs_contigsumsize > 0)
		acg.cg_nclusterblks = acg.cg_ndblk >> sblock.fs_fragshift;
	start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
	if (Oflag == 2) {
		acg.cg_iusedoff = start;
	} else {
		if (cylno == sblock.fs_ncg - 1)
			acg.cg_old_ncyl = howmany(acg.cg_ndblk,
			    sblock.fs_fpg / sblock.fs_old_cpg);
		else
			acg.cg_old_ncyl = sblock.fs_old_cpg;
		acg.cg_old_time = acg.cg_time;
		acg.cg_time = 0;
		acg.cg_old_niblk = acg.cg_niblk;
		acg.cg_niblk = 0;
		acg.cg_initediblk = 0;
		acg.cg_old_btotoff = start;
		acg.cg_old_boff = acg.cg_old_btotoff +
		    sblock.fs_old_cpg * sizeof(int32_t);
		acg.cg_iusedoff = acg.cg_old_boff +
		    sblock.fs_old_cpg * sizeof(u_int16_t);
	}
	acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT);
	if (sblock.fs_contigsumsize <= 0) {
		acg.cg_nextfreeoff = acg.cg_freeoff +
		   howmany(sblock.fs_fpg, CHAR_BIT);
	} else {
		acg.cg_clustersumoff = acg.cg_freeoff +
		    howmany(sblock.fs_fpg, CHAR_BIT) - sizeof(int32_t);
		acg.cg_clustersumoff =
		    roundup(acg.cg_clustersumoff, sizeof(int32_t));
		acg.cg_clusteroff = acg.cg_clustersumoff +
		    (sblock.fs_contigsumsize + 1) * sizeof(int32_t);
		acg.cg_nextfreeoff = acg.cg_clusteroff +
		    howmany(ffs_fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
	}
	if (acg.cg_nextfreeoff > sblock.fs_cgsize) {
		printf("Panic: cylinder group too big\n");
		exit(37);
	}
	acg.cg_cs.cs_nifree += sblock.fs_ipg;
	if (cylno == 0) {
		size_t r;

		for (r = 0; r < UFS_ROOTINO; r++) {
			setbit(cg_inosused(&acg, 0), r);
			acg.cg_cs.cs_nifree--;
		}
	}
	if (cylno > 0) {
		/*
		 * In cylno 0, beginning space is reserved
		 * for boot and super blocks.
		 */
		for (d = 0, blkno = 0; d < dlower;) {
			ffs_setblock(&sblock, cg_blksfree(&acg, 0), blkno);
			if (sblock.fs_contigsumsize > 0)
				setbit(cg_clustersfree(&acg, 0), blkno);
			acg.cg_cs.cs_nbfree++;
			d += sblock.fs_frag;
			blkno++;
		}
	}
	if ((i = (dupper & (sblock.fs_frag - 1))) != 0) {
		acg.cg_frsum[sblock.fs_frag - i]++;
		for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
			setbit(cg_blksfree(&acg, 0), dupper);
			acg.cg_cs.cs_nffree++;
		}
	}
	for (d = dupper, blkno = dupper >> sblock.fs_fragshift;
	     d + sblock.fs_frag <= acg.cg_ndblk; ) {
Пример #16
0
/*
 * Initialize a cylinder group.
 */
void
initcg(int cylno, time_t utime)
{
	long blkno, start;
	uint i, j, d, dlower, dupper;
	ufs2_daddr_t cbase, dmax;
	struct ufs1_dinode *dp1;
	struct ufs2_dinode *dp2;
	struct csum *cs;

	/*
	 * Determine block bounds for cylinder group.
	 * Allow space for super block summary information in first
	 * cylinder group.
	 */
	cbase = cgbase(&sblock, cylno);
	dmax = cbase + sblock.fs_fpg;
	if (dmax > sblock.fs_size)
		dmax = sblock.fs_size;
	dlower = cgsblock(&sblock, cylno) - cbase;
	dupper = cgdmin(&sblock, cylno) - cbase;
	if (cylno == 0)
		dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
	cs = &fscs[cylno];
	memset(&acg, 0, sblock.fs_cgsize);
	acg.cg_time = utime;
	acg.cg_magic = CG_MAGIC;
	acg.cg_cgx = cylno;
	acg.cg_niblk = sblock.fs_ipg;
	acg.cg_initediblk = sblock.fs_ipg < 2 * INOPB(&sblock) ?
	    sblock.fs_ipg : 2 * INOPB(&sblock);
	acg.cg_ndblk = dmax - cbase;
	if (sblock.fs_contigsumsize > 0)
		acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
	start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
	if (Oflag == 2) {
		acg.cg_iusedoff = start;
	} else {
		acg.cg_old_ncyl = sblock.fs_old_cpg;
		acg.cg_old_time = acg.cg_time;
		acg.cg_time = 0;
		acg.cg_old_niblk = acg.cg_niblk;
		acg.cg_niblk = 0;
		acg.cg_initediblk = 0;
		acg.cg_old_btotoff = start;
		acg.cg_old_boff = acg.cg_old_btotoff +
		    sblock.fs_old_cpg * sizeof(int32_t);
		acg.cg_iusedoff = acg.cg_old_boff +
		    sblock.fs_old_cpg * sizeof(u_int16_t);
	}
	acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT);
	acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT);
	if (sblock.fs_contigsumsize > 0) {
		acg.cg_clustersumoff =
		    roundup(acg.cg_nextfreeoff, sizeof(u_int32_t));
		acg.cg_clustersumoff -= sizeof(u_int32_t);
		acg.cg_clusteroff = acg.cg_clustersumoff +
		    (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t);
		acg.cg_nextfreeoff = acg.cg_clusteroff +
		    howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
	}
	if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) {
		printf("Panic: cylinder group too big\n");
		exit(37);
	}
	acg.cg_cs.cs_nifree += sblock.fs_ipg;
	if (cylno == 0)
		for (i = 0; i < (long)ROOTINO; i++) {
			setbit(cg_inosused(&acg), i);
			acg.cg_cs.cs_nifree--;
		}
	if (cylno > 0) {
		/*
		 * In cylno 0, beginning space is reserved
		 * for boot and super blocks.
		 */
		for (d = 0; d < dlower; d += sblock.fs_frag) {
			blkno = d / sblock.fs_frag;
			setblock(&sblock, cg_blksfree(&acg), blkno);
			if (sblock.fs_contigsumsize > 0)
				setbit(cg_clustersfree(&acg), blkno);
			acg.cg_cs.cs_nbfree++;
		}
	}
	if ((i = dupper % sblock.fs_frag)) {
		acg.cg_frsum[sblock.fs_frag - i]++;
		for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
			setbit(cg_blksfree(&acg), dupper);
			acg.cg_cs.cs_nffree++;
		}
	}
	for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk;
	     d += sblock.fs_frag) {
		blkno = d / sblock.fs_frag;
		setblock(&sblock, cg_blksfree(&acg), blkno);
		if (sblock.fs_contigsumsize > 0)
			setbit(cg_clustersfree(&acg), blkno);
		acg.cg_cs.cs_nbfree++;
	}
	if (d < acg.cg_ndblk) {
		acg.cg_frsum[acg.cg_ndblk - d]++;
		for (; d < acg.cg_ndblk; d++) {
			setbit(cg_blksfree(&acg), d);
			acg.cg_cs.cs_nffree++;
		}
	}
	if (sblock.fs_contigsumsize > 0) {
		int32_t *sump = cg_clustersum(&acg);
		u_char *mapp = cg_clustersfree(&acg);
		int map = *mapp++;
		int bit = 1;
		int run = 0;

		for (i = 0; i < acg.cg_nclusterblks; i++) {
			if ((map & bit) != 0)
				run++;
			else if (run != 0) {
				if (run > sblock.fs_contigsumsize)
					run = sblock.fs_contigsumsize;
				sump[run]++;
				run = 0;
			}
			if ((i & (CHAR_BIT - 1)) != CHAR_BIT - 1)
				bit <<= 1;
			else {
				map = *mapp++;
				bit = 1;
			}
		}
		if (run != 0) {
			if (run > sblock.fs_contigsumsize)
				run = sblock.fs_contigsumsize;
			sump[run]++;
		}
	}
	*cs = acg.cg_cs;
	/*
	 * Write out the duplicate super block, the cylinder group map
	 * and two blocks worth of inodes in a single write.
	 */
	start = sblock.fs_bsize > SBLOCKSIZE ? sblock.fs_bsize : SBLOCKSIZE;
	bcopy((char *)&acg, &iobuf[start], sblock.fs_cgsize);
	start += sblock.fs_bsize;
	dp1 = (struct ufs1_dinode *)(&iobuf[start]);
	dp2 = (struct ufs2_dinode *)(&iobuf[start]);
	for (i = 0; i < acg.cg_initediblk; i++) {
		if (sblock.fs_magic == FS_UFS1_MAGIC) {
			dp1->di_gen = newfs_random();
			dp1++;
		} else {
			dp2->di_gen = newfs_random();
			dp2++;
		}
	}
	wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf);
	/*
	 * For the old file system, we have to initialize all the inodes.
	 */
	if (Oflag == 1) {
		for (i = 2 * sblock.fs_frag;
		     i < sblock.fs_ipg / INOPF(&sblock);
		     i += sblock.fs_frag) {
			dp1 = (struct ufs1_dinode *)(&iobuf[start]);
			for (j = 0; j < INOPB(&sblock); j++) {
				dp1->di_gen = newfs_random();
				dp1++;
			}
			wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
			    sblock.fs_bsize, &iobuf[start]);
		}
	}
}
Пример #17
0
/*
 * Scan the specified file system to check quota(s) present on it.
 */
int
chkquota(const char *vfstype, const char *fsname, const char *mntpt,
    void *auxarg, pid_t *pidp)
{
	struct quotaname *qnp = auxarg;
	struct fileusage *fup;
	union dinode *dp;
	int cg, i, mode, errs = 0, status;
	ino_t ino, inosused;
	pid_t pid;
	char *cp;

	switch (pid = fork()) {
	case -1:	/* error */
		warn("fork");
		return 1;
	case 0:		/* child */
		if ((fi = open(fsname, O_RDONLY, 0)) < 0)
			err(1, "%s", fsname);
		sync();
		dev_bsize = 1;
		for (i = 0; sblock_try[i] != -1; i++) {
			bread(sblock_try[i], (char *)&sblock, (long)SBLOCKSIZE);
			if ((sblock.fs_magic == FS_UFS1_MAGIC ||
			     (sblock.fs_magic == FS_UFS2_MAGIC &&
			      sblock.fs_sblockloc == sblock_try[i])) &&
			    sblock.fs_bsize <= MAXBSIZE &&
			    sblock.fs_bsize >= sizeof(struct fs))
				break;
		}
		if (sblock_try[i] == -1) {
			warn("Cannot find file system superblock");
			return (1);
		}
		dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
		maxino = sblock.fs_ncg * sblock.fs_ipg;
		for (cg = 0; cg < sblock.fs_ncg; cg++) {
			ino = cg * sblock.fs_ipg;
			setinodebuf(ino);
			bread(fsbtodb(&sblock, cgtod(&sblock, cg)),
			    (char *)(&cgblk), sblock.fs_cgsize);
			if (sblock.fs_magic == FS_UFS2_MAGIC)
				inosused = cgblk.cg_initediblk;
			else
				inosused = sblock.fs_ipg;
			/*
			 * If we are using soft updates, then we can trust the
			 * cylinder group inode allocation maps to tell us which
			 * inodes are allocated. We will scan the used inode map
			 * to find the inodes that are really in use, and then
			 * read only those inodes in from disk.
			 */
			if (sblock.fs_flags & FS_DOSOFTDEP) {
				if (!cg_chkmagic(&cgblk))
					errx(1, "CG %d: BAD MAGIC NUMBER\n", cg);
				cp = &cg_inosused(&cgblk)[(inosused - 1) / CHAR_BIT];
				for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) {
					if (*cp == 0)
						continue;
					for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) {
						if (*cp & i)
							break;
						inosused--;
					}
					break;
				}
				if (inosused <= 0)
					continue;
			}
			for (i = 0; i < inosused; i++, ino++) {
				if ((dp = getnextinode(ino)) == NULL ||
				    ino < ROOTINO ||
				    (mode = DIP(dp, di_mode) & IFMT) == 0)
					continue;
				if (qnp->flags & HASGRP) {
					fup = addid(DIP(dp, di_gid),
					    GRPQUOTA, NULL);
					fup->fu_curinodes++;
					if (mode == IFREG || mode == IFDIR ||
					    mode == IFLNK)
						fup->fu_curblocks +=
						    DIP(dp, di_blocks);
				}
				if (qnp->flags & HASUSR) {
					fup = addid(DIP(dp, di_uid),
					    USRQUOTA, NULL);
					fup->fu_curinodes++;
					if (mode == IFREG || mode == IFDIR ||
					    mode == IFLNK)
						fup->fu_curblocks +=
						    DIP(dp, di_blocks);
				}
			}
		}
		freeinodebuf();
		if (flags&(CHECK_DEBUG|CHECK_VERBOSE)) {
			(void)printf("*** Checking ");
			if (qnp->flags & HASUSR) {
				(void)printf("%s", qfextension[USRQUOTA]);
				if (qnp->flags & HASGRP)
					(void)printf(" and ");
			}
			if (qnp->flags & HASGRP)
				(void)printf("%s", qfextension[GRPQUOTA]);
			(void)printf(" quotas for %s (%s), %swait\n",
			    fsname, mntpt, pidp? "no" : "");
		}
		if (qnp->flags & HASUSR)
			errs += update(mntpt, qnp->usrqfname, USRQUOTA);
		if (qnp->flags & HASGRP)
			errs += update(mntpt, qnp->grpqfname, GRPQUOTA);
		close(fi);
		exit (errs);
		break;
	default:	/* parent */
		if (pidp != NULL) {
			*pidp = pid;
			return 0;
		}
		if (waitpid(pid, &status, 0) < 0) {
			warn("waitpid");
			return 1;
		}
		if (WIFEXITED(status)) {
			if (WEXITSTATUS(status) != 0)
				return WEXITSTATUS(status);
		} else if (WIFSIGNALED(status)) {
			warnx("%s: %s", fsname, strsignal(WTERMSIG(status)));
			return 1;
		}
		break;
	}
	return (0);
}
Пример #18
0
void
pass5(void)
{
	int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
	int inomapsize, blkmapsize;
	struct fs *fs = &sblock;
	struct cg *cg = &cgrp;
	ufs_daddr_t dbase, dmax;
	ufs_daddr_t d;
	long i, j, k;
	struct csum *cs;
	struct csum cstotal;
	struct inodesc idesc[3];
	char buf[MAXBSIZE];
	struct cg *newcg = (struct cg *)buf;
	struct ocg *ocg = (struct ocg *)buf;

	inoinfo(WINO)->ino_state = USTATE;
	memset(newcg, 0, (size_t)fs->fs_cgsize);
	newcg->cg_niblk = fs->fs_ipg;
	if (cvtlevel >= 3) {
		if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
			if (preen)
				pwarn("DELETING CLUSTERING MAPS\n");
			if (preen || reply("DELETE CLUSTERING MAPS")) {
				fs->fs_contigsumsize = 0;
				doinglevel1 = 1;
				sbdirty();
			}
		}
		if (fs->fs_maxcontig > 1) {
			char *doit = NULL;

			if (fs->fs_contigsumsize < 1) {
				doit = "CREAT";
			} else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
				   fs->fs_contigsumsize < FS_MAXCONTIG) {
				doit = "EXPAND";
			}
			if (doit) {
				i = fs->fs_contigsumsize;
				fs->fs_contigsumsize =
				    MIN(fs->fs_maxcontig, FS_MAXCONTIG);
				if (CGSIZE(fs) > fs->fs_bsize) {
					pwarn("CANNOT %s CLUSTER MAPS\n", doit);
					fs->fs_contigsumsize = i;
				} else if (preen ||
				    reply("CREATE CLUSTER MAPS")) {
					if (preen)
						pwarn("%sING CLUSTER MAPS\n",
						    doit);
					fs->fs_cgsize =
					    fragroundup(fs, CGSIZE(fs));
					doinglevel1 = 1;
					sbdirty();
				}
			}
		}
	}
	switch ((int)fs->fs_postblformat) {

	case FS_42POSTBLFMT:
		basesize = (char *)(&ocg->cg_btot[0]) -
		    (char *)(&ocg->cg_firstfield);
		sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
		mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
			(u_char *)&ocg->cg_iused[0];
		blkmapsize = howmany(fs->fs_fpg, NBBY);
		inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0];
		ocg->cg_magic = CG_MAGIC;
		savednrpos = fs->fs_nrpos;
		fs->fs_nrpos = 8;
		break;

	case FS_DYNAMICPOSTBLFMT:
		newcg->cg_btotoff =
		     &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
		newcg->cg_boff =
		    newcg->cg_btotoff + fs->fs_cpg * sizeof(int32_t);
		newcg->cg_iusedoff = newcg->cg_boff +
		    fs->fs_cpg * fs->fs_nrpos * sizeof(u_int16_t);
		newcg->cg_freeoff =
		    newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
		inomapsize = newcg->cg_freeoff - newcg->cg_iusedoff;
		newcg->cg_nextfreeoff = newcg->cg_freeoff +
		    howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
		blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff;
		if (fs->fs_contigsumsize > 0) {
			newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
			    sizeof(u_int32_t);
			newcg->cg_clustersumoff =
			    roundup(newcg->cg_clustersumoff, sizeof(u_int32_t));
			newcg->cg_clusteroff = newcg->cg_clustersumoff +
			    (fs->fs_contigsumsize + 1) * sizeof(u_int32_t);
			newcg->cg_nextfreeoff = newcg->cg_clusteroff +
			    howmany(fs->fs_cpg * fs->fs_spc / NSPB(fs), NBBY);
		}
		newcg->cg_magic = CG_MAGIC;
		basesize = &newcg->cg_space[0] -
		    (u_char *)(&newcg->cg_firstfield);
		sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
		mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
		break;

	default:
		inomapsize = blkmapsize = sumsize = 0;	/* keep lint happy */
		errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d",
			fs->fs_postblformat);
	}
	memset(&idesc[0], 0, sizeof idesc);
	for (i = 0; i < 3; i++) {
		idesc[i].id_type = ADDR;
		if (doinglevel2)
			idesc[i].id_fix = FIX;
	}
	memset(&cstotal, 0, sizeof(struct csum));
	j = blknum(fs, fs->fs_size + fs->fs_frag - 1);
	for (i = fs->fs_size; i < j; i++)
		setbmap(i);
	for (c = 0; c < fs->fs_ncg; c++) {
		if (got_siginfo) {
			printf("%s: phase 5: cyl group %d of %d (%d%%)\n",
			    cdevname, c, sblock.fs_ncg,
			    c * 100 / sblock.fs_ncg);
			got_siginfo = 0;
		}
		getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
		if (!cg_chkmagic(cg))
			pfatal("CG %d: BAD MAGIC NUMBER\n", c);
		dbase = cgbase(fs, c);
		dmax = dbase + fs->fs_fpg;
		if (dmax > fs->fs_size)
			dmax = fs->fs_size;
		newcg->cg_time = cg->cg_time;
		newcg->cg_cgx = c;
		if (c == fs->fs_ncg - 1)
			newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
		else
			newcg->cg_ncyl = fs->fs_cpg;
		newcg->cg_ndblk = dmax - dbase;
		if (fs->fs_contigsumsize > 0)
			newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
		newcg->cg_cs.cs_ndir = 0;
		newcg->cg_cs.cs_nffree = 0;
		newcg->cg_cs.cs_nbfree = 0;
		newcg->cg_cs.cs_nifree = fs->fs_ipg;
		if ((cg->cg_rotor >= 0) && (cg->cg_rotor < newcg->cg_ndblk))
			newcg->cg_rotor = cg->cg_rotor;
		else
			newcg->cg_rotor = 0;
		if ((cg->cg_frotor >= 0) && (cg->cg_frotor < newcg->cg_ndblk))
			newcg->cg_frotor = cg->cg_frotor;
		else
			newcg->cg_frotor = 0;
		if ((cg->cg_irotor >= 0) && (cg->cg_irotor < newcg->cg_niblk))
			newcg->cg_irotor = cg->cg_irotor;
		else
			newcg->cg_irotor = 0;
		memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
		memset(&cg_blktot(newcg)[0], 0,
		      (size_t)(sumsize + mapsize));
		if (fs->fs_postblformat == FS_42POSTBLFMT)
			ocg->cg_magic = CG_MAGIC;
		j = fs->fs_ipg * c;
		for (i = 0; i < inostathead[c].il_numalloced; j++, i++) {
			switch (inoinfo(j)->ino_state) {

			case USTATE:
				break;

			case DSTATE:
			case DCLEAR:
			case DFOUND:
				newcg->cg_cs.cs_ndir++;
				/* fall through */

			case FSTATE:
			case FCLEAR:
				newcg->cg_cs.cs_nifree--;
				setbit(cg_inosused(newcg), i);
				break;

			default:
				if (j < ROOTINO)
					break;
				errx(EEXIT, "BAD STATE %d FOR INODE I=%ld",
				    inoinfo(j)->ino_state, j);
			}
		}
		if (c == 0)
			for (i = 0; i < ROOTINO; i++) {
				setbit(cg_inosused(newcg), i);
				newcg->cg_cs.cs_nifree--;
			}
		for (i = 0, d = dbase;
		     d < dmax;
		     d += fs->fs_frag, i += fs->fs_frag) {
			frags = 0;
			for (j = 0; j < fs->fs_frag; j++) {
				if (testbmap(d + j))
					continue;
				setbit(cg_blksfree(newcg), i + j);
				frags++;
			}
			if (frags == fs->fs_frag) {
				newcg->cg_cs.cs_nbfree++;
				j = cbtocylno(fs, i);
				cg_blktot(newcg)[j]++;
				cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++;
				if (fs->fs_contigsumsize > 0)
					setbit(cg_clustersfree(newcg),
					    i / fs->fs_frag);
			} else if (frags > 0) {
				newcg->cg_cs.cs_nffree += frags;
				blk = blkmap(fs, cg_blksfree(newcg), i);
				ffs_fragacct(fs, blk, newcg->cg_frsum, 1);
			}
		}
		if (fs->fs_contigsumsize > 0) {
			int32_t *sump = cg_clustersum(newcg);
			u_char *mapp = cg_clustersfree(newcg);
			int map = *mapp++;
			int bit = 1;
			int run = 0;

			for (i = 0; i < newcg->cg_nclusterblks; i++) {
				if ((map & bit) != 0) {
					run++;
				} else if (run != 0) {
					if (run > fs->fs_contigsumsize)
						run = fs->fs_contigsumsize;
					sump[run]++;
					run = 0;
				}
				if ((i & (NBBY - 1)) != (NBBY - 1)) {
					bit <<= 1;
				} else {
					map = *mapp++;
					bit = 1;
				}
			}
			if (run != 0) {
				if (run > fs->fs_contigsumsize)
					run = fs->fs_contigsumsize;
				sump[run]++;
			}
		}
		cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
		cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
		cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
		cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
		cs = &fs->fs_cs(fs, c);
		if (memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0 &&
		    dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
			memmove(cs, &newcg->cg_cs, sizeof *cs);
			sbdirty();
		}
		if (doinglevel1) {
			memmove(cg, newcg, (size_t)fs->fs_cgsize);
			cgdirty();
			continue;
		}
		if ((memcmp(newcg, cg, basesize) != 0 ||
		     memcmp(&cg_blktot(newcg)[0],
			  &cg_blktot(cg)[0], sumsize) != 0) &&
		    dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
			memmove(cg, newcg, (size_t)basesize);
			memmove(&cg_blktot(cg)[0],
			       &cg_blktot(newcg)[0], (size_t)sumsize);
			cgdirty();
		}
		if (usedsoftdep) {
			for (i = 0; i < inomapsize; i++) {
				j = cg_inosused(newcg)[i];
				if ((cg_inosused(cg)[i] & j) == j)
					continue;
				for (k = 0; k < NBBY; k++) {
					if ((j & (1 << k)) == 0)
						continue;
					if (cg_inosused(cg)[i] & (1 << k))
						continue;
					pwarn("ALLOCATED INODE %d MARKED FREE\n",
					    c * fs->fs_ipg + i * NBBY + k);
				}
			}
			for (i = 0; i < blkmapsize; i++) {
				j = cg_blksfree(cg)[i];
				if ((cg_blksfree(newcg)[i] & j) == j)
					continue;
				for (k = 0; k < NBBY; k++) {
					if ((j & (1 << k)) == 0)
						continue;
					if (cg_blksfree(newcg)[i] & (1 << k))
						continue;
					pwarn("ALLOCATED FRAG %d MARKED FREE\n",
					    c * fs->fs_fpg + i * NBBY + k);
				}
			}
		}
		if (memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0 &&
		    dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
			memmove(cg_inosused(cg), cg_inosused(newcg),
			      (size_t)mapsize);
			cgdirty();
		}
	}
	if (fs->fs_postblformat == FS_42POSTBLFMT)
		fs->fs_nrpos = savednrpos;
	if (memcmp(&cstotal, &fs->fs_cstotal, sizeof *cs) != 0
	    && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
		memmove(&fs->fs_cstotal, &cstotal, sizeof *cs);
		fs->fs_ronly = 0;
		fs->fs_fmod = 0;
		sbdirty();
	}
}
Пример #19
0
void
pass1(void)
{
	ino_t inumber, inosused, ninosused;
	size_t inospace;
	struct inostat *info;
	int c;
	struct inodesc idesc;
	daddr_t i, cgd;
	u_int8_t *cp;

	/*
	 * Set file system reserved blocks in used block map.
	 */
	for (c = 0; c < sblock.fs_ncg; c++) {
		cgd = cgdmin(&sblock, c);
		if (c == 0)
			i = cgbase(&sblock, c);
		else
			i = cgsblock(&sblock, c);
		for (; i < cgd; i++)
			setbmap(i);
	}
	i = sblock.fs_csaddr;
	cgd = i + howmany(sblock.fs_cssize, sblock.fs_fsize);
	for (; i < cgd; i++)
		setbmap(i);
	/*
	 * Find all allocated blocks.
	 */
	memset(&idesc, 0, sizeof(struct inodesc));
	idesc.id_type = ADDR;
	idesc.id_func = pass1check;
	n_files = n_blks = 0;
	info_inumber = 0;
	info_fn = pass1_info;
	for (c = 0; c < sblock.fs_ncg; c++) {
		inumber = c * sblock.fs_ipg;
		setinodebuf(inumber);
		getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize);
		if (sblock.fs_magic == FS_UFS2_MAGIC) {
			inosused = cgrp.cg_initediblk;
			if (inosused > sblock.fs_ipg)
				inosused = sblock.fs_ipg;
		} else
			inosused = sblock.fs_ipg;

		/*
		 * If we are using soft updates, then we can trust the
		 * cylinder group inode allocation maps to tell us which
		 * inodes are allocated. We will scan the used inode map
		 * to find the inodes that are really in use, and then
		 * read only those inodes in from disk.
		 */
		if (preen && usedsoftdep) {
			cp = &cg_inosused(&cgrp)[(inosused - 1) / CHAR_BIT];
			for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) {
				if (*cp == 0)
					continue;
				for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) {
					if (*cp & i)
						break;
					inosused--;
				}
				break;
			}
			if (inosused < 0)
				inosused = 0;
		}
		/*
 		 * Allocate inoinfo structures for the allocated inodes.
		 */
		inostathead[c].il_numalloced = inosused;
		if (inosused == 0) {
			inostathead[c].il_stat = 0;
			continue;
		}
		info = calloc((unsigned)inosused, sizeof(struct inostat));
		inospace = (unsigned)inosused * sizeof(struct inostat);
		if (info == NULL)
			errexit("cannot alloc %zu bytes for inoinfo", inospace);
		inostathead[c].il_stat = info;
		/*
		 * Scan the allocated inodes.
		 */
		for (i = 0; i < inosused; i++, inumber++) {
			info_inumber = inumber;
			if (inumber < ROOTINO) {
				(void)getnextinode(inumber);
				continue;
			}
			checkinode(inumber, &idesc);
		}
		lastino += 1;
		if (inosused < sblock.fs_ipg || inumber == lastino)
			continue;
		/*
		 * If we were not able to determine in advance which inodes
		 * were in use, then reduce the size of the inoinfo structure
		 * to the size necessary to describe the inodes that we
		 * really found.
		 */
		if (lastino < (c * sblock.fs_ipg))
			ninosused = 0;
		else
			ninosused = lastino - (c * sblock.fs_ipg);
		inostathead[c].il_numalloced = ninosused;
		if (ninosused == 0) {
			free(inostathead[c].il_stat);
			inostathead[c].il_stat = 0;
			continue;
		}
		if (ninosused != inosused) {
			struct inostat *ninfo;
			size_t ninospace;

			ninfo = reallocarray(info, ninosused, sizeof(*ninfo));
			if (ninfo == NULL) {
				pfatal("too many inodes %llu, or out of memory\n",
				    (unsigned long long)ninosused);
				exit(8);
			}
			ninospace = ninosused * sizeof(*ninfo);
			if (ninosused > inosused)
				memset(&ninfo[inosused], 0, ninospace - inospace);
			inostathead[c].il_stat = ninfo;
		}
	}
Пример #20
0
void
pass5(void)
{
	int c, blk, frags, basesize, sumsize, mapsize, cssize;
	int inomapsize, blkmapsize;
	struct fs *fs = sblock;
	daddr_t dbase, dmax;
	daddr_t d;
	long i, j, k;
	struct csum *cs;
	struct csum_total cstotal;
	struct inodesc idesc[4];
	char buf[MAXBSIZE];
	struct cg *newcg = (struct cg *)buf;
	struct ocg *ocg = (struct ocg *)buf;
	struct cg *cg = cgrp, *ncg;
	struct inostat *info;
	u_int32_t ncgsize;

	inoinfo(WINO)->ino_state = USTATE;
	memset(newcg, 0, (size_t)fs->fs_cgsize);
	newcg->cg_niblk = fs->fs_ipg;
	if (cvtlevel >= 3) {
		if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
			if (preen)
				pwarn("DELETING CLUSTERING MAPS\n");
			if (preen || reply("DELETE CLUSTERING MAPS")) {
				fs->fs_contigsumsize = 0;
				doinglevel1 = 1;
				sbdirty();
			}
		}
		if (fs->fs_maxcontig > 1) {
			const char *doit = NULL;

			if (fs->fs_contigsumsize < 1) {
				doit = "CREAT";
			} else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
				   fs->fs_contigsumsize < FS_MAXCONTIG) {
				doit = "EXPAND";
			}
			if (doit) {
				i = fs->fs_contigsumsize;
				fs->fs_contigsumsize =
				    MIN(fs->fs_maxcontig, FS_MAXCONTIG);
				if (CGSIZE(fs) > fs->fs_bsize) {
					pwarn("CANNOT %s CLUSTER MAPS\n", doit);
					fs->fs_contigsumsize = i;
				} else if (preen ||
				    reply("CREATE CLUSTER MAPS")) {
					if (preen)
						pwarn("%sING CLUSTER MAPS\n",
						    doit);
					ncgsize = fragroundup(fs, CGSIZE(fs));
					ncg = realloc(cgrp, ncgsize);
					if (ncg == NULL)
						errexit(
						"cannot reallocate cg space");
					cg = cgrp = ncg;
					fs->fs_cgsize = ncgsize;
					doinglevel1 = 1;
					sbdirty();
				}
			}
		}
	}
	basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
	cssize = (u_char *)&cstotal.cs_spare[0] - (u_char *)&cstotal.cs_ndir;
	sumsize = 0;
	if (is_ufs2) {
		newcg->cg_iusedoff = basesize;
	} else {
		/*
		 * We reserve the space for the old rotation summary
		 * tables for the benefit of old kernels, but do not
		 * maintain them in modern kernels. In time, they can
		 * go away.
		 */
		newcg->cg_old_btotoff = basesize;
		newcg->cg_old_boff = newcg->cg_old_btotoff +
		    fs->fs_old_cpg * sizeof(int32_t);
		newcg->cg_iusedoff = newcg->cg_old_boff +
		    fs->fs_old_cpg * fs->fs_old_nrpos * sizeof(u_int16_t);
		memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize);
	}
	inomapsize = howmany(fs->fs_ipg, CHAR_BIT);
	newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize;
	blkmapsize = howmany(fs->fs_fpg, CHAR_BIT);
	newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize;
	if (fs->fs_contigsumsize > 0) {
		newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
		    sizeof(u_int32_t);
		if (isappleufs) {
			/* Apple PR2216969 gives rationale for this change.
			 * I believe they were mistaken, but we need to
			 * duplicate it for compatibility.  -- [email protected]
			 */
			newcg->cg_clustersumoff += sizeof(u_int32_t);
		}
		newcg->cg_clustersumoff =
		    roundup(newcg->cg_clustersumoff, sizeof(u_int32_t));
		newcg->cg_clusteroff = newcg->cg_clustersumoff +
		    (fs->fs_contigsumsize + 1) * sizeof(u_int32_t);
		newcg->cg_nextfreeoff = newcg->cg_clusteroff +
		    howmany(fragstoblks(fs, fs->fs_fpg), CHAR_BIT);
	}
	newcg->cg_magic = CG_MAGIC;
	mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
	if (!is_ufs2 && ((fs->fs_old_flags & FS_FLAGS_UPDATED) == 0)) {
		switch ((int)fs->fs_old_postblformat) {

		case FS_42POSTBLFMT:
			basesize = (char *)(&ocg->cg_btot[0]) -
			    (char *)(&ocg->cg_firstfield);
			sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
			mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
			    (u_char *)&ocg->cg_iused[0];
			blkmapsize = howmany(fs->fs_fpg, NBBY);
			inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0];
			ocg->cg_magic = CG_MAGIC;
			newcg->cg_magic = 0;
			break;

		case FS_DYNAMICPOSTBLFMT:
			sumsize = newcg->cg_iusedoff - newcg->cg_old_btotoff;
			break;

		default:
			errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d",
			    fs->fs_old_postblformat);
		}
	}
	memset(&idesc[0], 0, sizeof idesc);
	for (i = 0; i < 4; i++) {
		idesc[i].id_type = ADDR;
		if (!is_ufs2 && doinglevel2)
			idesc[i].id_fix = FIX;
	}
	memset(&cstotal, 0, sizeof(struct csum_total));
	dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1);
	for (d = fs->fs_size; d < dmax; d++)
		setbmap(d);
	for (c = 0; c < fs->fs_ncg; c++) {
		if (got_siginfo) {
			fprintf(stderr,
			    "%s: phase 5: cyl group %d of %d (%d%%)\n",
			    cdevname(), c, fs->fs_ncg,
			    c * 100 / fs->fs_ncg);
			got_siginfo = 0;
		}
#ifdef PROGRESS
		progress_bar(cdevname(), preen ? NULL : "phase 5",
			    c, fs->fs_ncg);
#endif /* PROGRESS */
		getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
		memcpy(cg, cgblk.b_un.b_cg, fs->fs_cgsize);
		if((doswap && !needswap) || (!doswap && needswap))
			ffs_cg_swap(cgblk.b_un.b_cg, cg, sblock);
		if (!doinglevel1 && !cg_chkmagic(cg, 0))
			pfatal("CG %d: PASS5: BAD MAGIC NUMBER\n", c);
		if(doswap)
			cgdirty();
		/*
		 * While we have the disk head where we want it,
		 * write back the superblock to the spare at this
		 * cylinder group.
		 */
		if ((cvtlevel && sblk.b_dirty) || doswap) {
			bwrite(fswritefd, sblk.b_un.b_buf,
			    fsbtodb(sblock, cgsblock(sblock, c)),
			    sblock->fs_sbsize);
		} else {
			/*
			 * Read in the current alternate superblock,
			 * and compare it to the master.  If it's
			 * wrong, fix it up.
			 */
			getblk(&asblk, cgsblock(sblock, c), sblock->fs_sbsize);
			if (asblk.b_errs)
				pfatal("CG %d: UNABLE TO READ ALTERNATE "
				    "SUPERBLK\n", c);
			else {
				memmove(altsblock, asblk.b_un.b_fs,
				    sblock->fs_sbsize);
				if (needswap)
					ffs_sb_swap(asblk.b_un.b_fs, altsblock);
			}
			sb_oldfscompat_write(sblock, sblocksave);
			if ((asblk.b_errs || cmpsblks(sblock, altsblock)) &&
			     dofix(&idesc[3],
				   "ALTERNATE SUPERBLK(S) ARE INCORRECT")) {
				bwrite(fswritefd, sblk.b_un.b_buf,
				    fsbtodb(sblock, cgsblock(sblock, c)),
				    sblock->fs_sbsize);
			}
			sb_oldfscompat_read(sblock, 0);
		}
		dbase = cgbase(fs, c);
		dmax = dbase + fs->fs_fpg;
		if (dmax > fs->fs_size)
			dmax = fs->fs_size;
		if (is_ufs2 || (fs->fs_old_flags & FS_FLAGS_UPDATED))
			newcg->cg_time = cg->cg_time;
		newcg->cg_old_time = cg->cg_old_time;
		newcg->cg_cgx = c;
		newcg->cg_ndblk = dmax - dbase;
		if (!is_ufs2) {
			if (c == fs->fs_ncg - 1) {
				/* Avoid fighting old fsck for this value.  Its never used
				 * outside of this check anyway.
				 */
				if ((fs->fs_old_flags & FS_FLAGS_UPDATED) == 0)
					newcg->cg_old_ncyl = fs->fs_old_ncyl % fs->fs_old_cpg;
				else
					newcg->cg_old_ncyl = howmany(newcg->cg_ndblk,
					    fs->fs_fpg / fs->fs_old_cpg);
			} else
				newcg->cg_old_ncyl = fs->fs_old_cpg;
			newcg->cg_old_niblk = fs->fs_ipg;
			newcg->cg_niblk = 0;
		}
		if (fs->fs_contigsumsize > 0)
			newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
		newcg->cg_cs.cs_ndir = 0;
		newcg->cg_cs.cs_nffree = 0;
		newcg->cg_cs.cs_nbfree = 0;
		newcg->cg_cs.cs_nifree = fs->fs_ipg;
		if (cg->cg_rotor >= 0 && cg->cg_rotor < newcg->cg_ndblk)
			newcg->cg_rotor = cg->cg_rotor;
		else
			newcg->cg_rotor = 0;
		if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk)
			newcg->cg_frotor = cg->cg_frotor;
		else
			newcg->cg_frotor = 0;
		if (cg->cg_irotor >= 0 && cg->cg_irotor < fs->fs_ipg)
			newcg->cg_irotor = cg->cg_irotor;
		else
			newcg->cg_irotor = 0;
		if (!is_ufs2) {
			newcg->cg_initediblk = 0;
		} else {
			if ((unsigned)cg->cg_initediblk > fs->fs_ipg)
				newcg->cg_initediblk = fs->fs_ipg;
			else
				newcg->cg_initediblk = cg->cg_initediblk;
		}
		memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
		memset(&old_cg_blktot(newcg, 0)[0], 0, (size_t)(sumsize));
		memset(cg_inosused(newcg, 0), 0, (size_t)(mapsize));
		if (!is_ufs2 && ((fs->fs_old_flags & FS_FLAGS_UPDATED) == 0) &&
		    fs->fs_old_postblformat == FS_42POSTBLFMT)
			ocg->cg_magic = CG_MAGIC;
		j = fs->fs_ipg * c;
		for (i = 0; i < fs->fs_ipg; j++, i++) {
			info = inoinfo(j);
			switch (info->ino_state) {

			case USTATE:
				break;

			case DSTATE:
			case DCLEAR:
			case DFOUND:
				newcg->cg_cs.cs_ndir++;
				/* fall through */

			case FSTATE:
			case FCLEAR:
				newcg->cg_cs.cs_nifree--;
				setbit(cg_inosused(newcg, 0), i);
				break;

			default:
				if (j < ROOTINO)
					break;
				errexit("BAD STATE %d FOR INODE I=%ld",
				    info->ino_state, (long)j);
			}
		}
		if (c == 0)
			for (i = 0; i < ROOTINO; i++) {
				setbit(cg_inosused(newcg, 0), i);
				newcg->cg_cs.cs_nifree--;
			}
		for (i = 0, d = dbase;
		     d < dmax;
		     d += fs->fs_frag, i += fs->fs_frag) {
			frags = 0;
			for (j = 0; j < fs->fs_frag; j++) {
				if (testbmap(d + j))
					continue;
				setbit(cg_blksfree(newcg, 0), i + j);
				frags++;
			}
			if (frags == fs->fs_frag) {
				newcg->cg_cs.cs_nbfree++;
				if (sumsize) {
					j = old_cbtocylno(fs, i);
					old_cg_blktot(newcg, 0)[j]++;
					old_cg_blks(fs, newcg, j, 0)[old_cbtorpos(fs, i)]++;
				}
				if (fs->fs_contigsumsize > 0)
					setbit(cg_clustersfree(newcg, 0),
					    fragstoblks(fs, i));
			} else if (frags > 0) {
				newcg->cg_cs.cs_nffree += frags;
				blk = blkmap(fs, cg_blksfree(newcg, 0), i);
				ffs_fragacct(fs, blk, newcg->cg_frsum, 1, 0);
			}
		}
		if (fs->fs_contigsumsize > 0) {
			int32_t *sump = cg_clustersum(newcg, 0);
			u_char *mapp = cg_clustersfree(newcg, 0);
			int map = *mapp++;
			int bit = 1;
			int run = 0;

			for (i = 0; i < newcg->cg_nclusterblks; i++) {
				if ((map & bit) != 0) {
					run++;
				} else if (run != 0) {
					if (run > fs->fs_contigsumsize)
						run = fs->fs_contigsumsize;
					sump[run]++;
					run = 0;
				}
				if ((i & (NBBY - 1)) != (NBBY - 1)) {
					bit <<= 1;
				} else {
					map = *mapp++;
					bit = 1;
				}
			}
			if (run != 0) {
				if (run > fs->fs_contigsumsize)
					run = fs->fs_contigsumsize;
				sump[run]++;
			}
		}
		cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
		cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
		cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
		cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
		cs = &fs->fs_cs(fs, c);
		if (memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0) {
			if (debug) {
				printf("cg %d: nffree: %d/%d nbfree %d/%d"
					" nifree %d/%d ndir %d/%d\n",
					c, cs->cs_nffree,newcg->cg_cs.cs_nffree,
					cs->cs_nbfree,newcg->cg_cs.cs_nbfree,
					cs->cs_nifree,newcg->cg_cs.cs_nifree,
					cs->cs_ndir,newcg->cg_cs.cs_ndir);
			}
			if (dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
				memmove(cs, &newcg->cg_cs, sizeof *cs);
				sbdirty();
			} else
				markclean = 0;
		}
		if (doinglevel1) {
			memmove(cg, newcg, (size_t)fs->fs_cgsize);
			cgdirty();
			continue;
		}
		if ((memcmp(newcg, cg, basesize) != 0) ||
		    (memcmp(&old_cg_blktot(newcg, 0)[0],
		        &old_cg_blktot(cg, 0)[0], sumsize) != 0)) {
		 	if (dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
				memmove(cg, newcg, (size_t)basesize);
				memmove(&old_cg_blktot(cg, 0)[0],
			       &old_cg_blktot(newcg, 0)[0], (size_t)sumsize);
				cgdirty();
			} else
				markclean = 0;
		}
		if (usedsoftdep) {
			for (i = 0; i < inomapsize; i++) {
				j = cg_inosused(newcg, 0)[i];
				if ((cg_inosused(cg, 0)[i] & j) == j)
					continue;
				for (k = 0; k < NBBY; k++) {
					if ((j & (1 << k)) == 0)
						continue;
					if (cg_inosused(cg, 0)[i] & (1 << k))
						continue;
					pwarn("ALLOCATED INODE %ld "
					    "MARKED FREE\n",
					    c * fs->fs_ipg + i * 8 + k);
				}
			}
			for (i = 0; i < blkmapsize; i++) {
				j = cg_blksfree(cg, 0)[i];
				if ((cg_blksfree(newcg, 0)[i] & j) == j)
					continue;
				for (k = 0; k < NBBY; k++) {
					if ((j & (1 << k)) == 0)
						continue;
					if (cg_inosused(cg, 0)[i] & (1 << k))
						continue;
					pwarn("ALLOCATED FRAG %ld "
					    "MARKED FREE\n",
					    c * fs->fs_fpg + i * 8 + k);
				}
			}
		}
		if (memcmp(cg_inosused(newcg, 0), cg_inosused(cg, 0), mapsize)
		    != 0 && dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
			memmove(cg_inosused(cg, 0), cg_inosused(newcg, 0),
			    (size_t)mapsize);
                        cgdirty();
                }
	}
	if (memcmp(&cstotal, &fs->fs_cstotal, cssize) != 0) {
		if (debug) {
			printf("total: nffree: %lld/%lld nbfree %lld/%lld"
				" nifree %lld/%lld ndir %lld/%lld\n",
				(long long int)fs->fs_cstotal.cs_nffree,
				(long long int)cstotal.cs_nffree,
				(long long int)fs->fs_cstotal.cs_nbfree,
				(long long int)cstotal.cs_nbfree,
				(long long int)fs->fs_cstotal.cs_nifree,
				(long long int)cstotal.cs_nifree,
				(long long int)fs->fs_cstotal.cs_ndir,
				(long long int)cstotal.cs_ndir);
		}
		if (dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
			memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal);
			fs->fs_ronly = 0;
			fs->fs_fmod = 0;
			sbdirty();
		} else
			markclean = 0;
	}
#ifdef PROGRESS
	if (!preen)
		progress_done();
#endif /* PROGRESS */
}
Пример #21
0
/*
 * Dump pass 1.
 *
 * Walk the inode list for a file system to find all allocated inodes
 * that have been modified since the previous dump time. Also, find all
 * the directories in the file system.
 */
int
mapfiles(ino_t maxino, long *tapesize)
{
	int i, cg, mode, inosused;
	int anydirskipped = 0;
	union dinode *dp;
	struct cg *cgp;
	ino_t ino;
	u_char *cp;

	if ((cgp = malloc(sblock->fs_cgsize)) == NULL)
		quit("mapfiles: cannot allocate memory.\n");
	for (cg = 0; cg < sblock->fs_ncg; cg++) {
		ino = cg * sblock->fs_ipg;
		bread(fsbtodb(sblock, cgtod(sblock, cg)), (char *)cgp,
		    sblock->fs_cgsize);
		if (sblock->fs_magic == FS_UFS2_MAGIC)
			inosused = cgp->cg_initediblk;
		else
			inosused = sblock->fs_ipg;
		/*
		 * If we are using soft updates, then we can trust the
		 * cylinder group inode allocation maps to tell us which
		 * inodes are allocated. We will scan the used inode map
		 * to find the inodes that are really in use, and then
		 * read only those inodes in from disk.
		 */
		if (sblock->fs_flags & FS_DOSOFTDEP) {
			if (!cg_chkmagic(cgp))
				quit("mapfiles: cg %d: bad magic number\n", cg);
			cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT];
			for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) {
				if (*cp == 0)
					continue;
				for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) {
					if (*cp & i)
						break;
					inosused--;
				}
				break;
			}
			if (inosused <= 0)
				continue;
		}
		for (i = 0; i < inosused; i++, ino++) {
			if (ino < ROOTINO ||
			    (dp = getino(ino, &mode)) == NULL ||
			    (mode & IFMT) == 0)
				continue;
			if (ino >= maxino) {
				msg("Skipping inode %d >= maxino %d\n",
				    ino, maxino);
				continue;
			}
			/*
			 * Everything must go in usedinomap so that a check
			 * for "in dumpdirmap but not in usedinomap" to detect
			 * dirs with nodump set has a chance of succeeding
			 * (this is used in mapdirs()).
			 */
			SETINO(ino, usedinomap);
			if (mode == IFDIR)
				SETINO(ino, dumpdirmap);
			if (WANTTODUMP(dp)) {
				SETINO(ino, dumpinomap);
				if (mode != IFREG &&
				    mode != IFDIR &&
				    mode != IFLNK)
					*tapesize += 1;
				else
					*tapesize += blockest(dp);
				continue;
			}
			if (mode == IFDIR) {
				if (!nonodump &&
				    (DIP(dp, di_flags) & UF_NODUMP))
					CLRINO(ino, usedinomap);
				anydirskipped = 1;
			}
		}
	}
	/*
	 * Restore gets very upset if the root is not dumped,
	 * so ensure that it always is dumped.
	 */
	SETINO(ROOTINO, dumpinomap);
	return (anydirskipped);
}
Пример #22
0
void
pass5(void)
{
	int c, i, j, blk, frags, basesize, mapsize;
	int inomapsize, blkmapsize;
	struct fs *fs = &sblock;
	ufs2_daddr_t d, dbase, dmax, start;
	int rewritecg = 0;
	struct csum *cs;
	struct csum_total cstotal;
	struct inodesc idesc[3];
	char buf[MAXBSIZE];
	struct cg *cg, *newcg = (struct cg *)buf;
	struct bufarea *cgbp;

	inoinfo(WINO)->ino_state = USTATE;
	memset(newcg, 0, (size_t)fs->fs_cgsize);
	newcg->cg_niblk = fs->fs_ipg;
	if (cvtlevel >= 3) {
		if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
			if (preen)
				pwarn("DELETING CLUSTERING MAPS\n");
			if (preen || reply("DELETE CLUSTERING MAPS")) {
				fs->fs_contigsumsize = 0;
				rewritecg = 1;
				sbdirty();
			}
		}
		if (fs->fs_maxcontig > 1) {
			const char *doit = 0;

			if (fs->fs_contigsumsize < 1) {
				doit = "CREAT";
			} else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
				   fs->fs_contigsumsize < FS_MAXCONTIG) {
				doit = "EXPAND";
			}
			if (doit) {
				i = fs->fs_contigsumsize;
				fs->fs_contigsumsize =
				    MIN(fs->fs_maxcontig, FS_MAXCONTIG);
				if (CGSIZE(fs) > (u_int)fs->fs_bsize) {
					pwarn("CANNOT %s CLUSTER MAPS\n", doit);
					fs->fs_contigsumsize = i;
				} else if (preen ||
				    reply("CREATE CLUSTER MAPS")) {
					if (preen)
						pwarn("%sING CLUSTER MAPS\n",
						    doit);
					fs->fs_cgsize =
					    fragroundup(fs, CGSIZE(fs));
					rewritecg = 1;
					sbdirty();
				}
			}
		}
	}
	basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
	if (sblock.fs_magic == FS_UFS2_MAGIC) {
		newcg->cg_iusedoff = basesize;
	} else {
		/*
		 * We reserve the space for the old rotation summary
		 * tables for the benefit of old kernels, but do not
		 * maintain them in modern kernels. In time, they can
		 * go away.
		 */
		newcg->cg_old_btotoff = basesize;
		newcg->cg_old_boff = newcg->cg_old_btotoff +
		    fs->fs_old_cpg * sizeof(int32_t);
		newcg->cg_iusedoff = newcg->cg_old_boff +
		    fs->fs_old_cpg * fs->fs_old_nrpos * sizeof(u_int16_t);
		memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize);
	}
	inomapsize = howmany(fs->fs_ipg, CHAR_BIT);
	newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize;
	blkmapsize = howmany(fs->fs_fpg, CHAR_BIT);
	newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize;
	if (fs->fs_contigsumsize > 0) {
		newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
		    sizeof(u_int32_t);
		newcg->cg_clustersumoff =
		    roundup(newcg->cg_clustersumoff, sizeof(u_int32_t));
		newcg->cg_clusteroff = newcg->cg_clustersumoff +
		    (fs->fs_contigsumsize + 1) * sizeof(u_int32_t);
		newcg->cg_nextfreeoff = newcg->cg_clusteroff +
		    howmany(fragstoblks(fs, fs->fs_fpg), CHAR_BIT);
	}
	newcg->cg_magic = CG_MAGIC;
	mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
	memset(&idesc[0], 0, sizeof idesc);
	for (i = 0; i < 3; i++)
		idesc[i].id_type = ADDR;
	memset(&cstotal, 0, sizeof(struct csum_total));
	dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1);
	for (d = fs->fs_size; d < dmax; d++)
		setbmap(d);
	for (c = 0; c < fs->fs_ncg; c++) {
		if (got_siginfo) {
			printf("%s: phase 5: cyl group %d of %d (%d%%)\n",
			    cdevname, c, sblock.fs_ncg,
			    c * 100 / sblock.fs_ncg);
			got_siginfo = 0;
		}
		if (got_sigalarm) {
			setproctitle("%s p5 %d%%", cdevname,
			    c * 100 / sblock.fs_ncg);
			got_sigalarm = 0;
		}
		cgbp = cgget(c);
		cg = cgbp->b_un.b_cg;
		if (!cg_chkmagic(cg))
			pfatal("CG %d: BAD MAGIC NUMBER\n", c);
		newcg->cg_time = cg->cg_time;
		newcg->cg_old_time = cg->cg_old_time;
		newcg->cg_unrefs = cg->cg_unrefs;
		newcg->cg_cgx = c;
		dbase = cgbase(fs, c);
		dmax = dbase + fs->fs_fpg;
		if (dmax > fs->fs_size)
			dmax = fs->fs_size;
		newcg->cg_ndblk = dmax - dbase;
		if (fs->fs_magic == FS_UFS1_MAGIC) {
			if (c == fs->fs_ncg - 1)
				newcg->cg_old_ncyl = howmany(newcg->cg_ndblk,
				    fs->fs_fpg / fs->fs_old_cpg);
			else
				newcg->cg_old_ncyl = fs->fs_old_cpg;
			newcg->cg_old_niblk = fs->fs_ipg;
			newcg->cg_niblk = 0;
		}
		if (fs->fs_contigsumsize > 0)
			newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
		newcg->cg_cs.cs_ndir = 0;
		newcg->cg_cs.cs_nffree = 0;
		newcg->cg_cs.cs_nbfree = 0;
		newcg->cg_cs.cs_nifree = fs->fs_ipg;
		if (cg->cg_rotor >= 0 && cg->cg_rotor < newcg->cg_ndblk)
			newcg->cg_rotor = cg->cg_rotor;
		else
			newcg->cg_rotor = 0;
		if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk)
			newcg->cg_frotor = cg->cg_frotor;
		else
			newcg->cg_frotor = 0;
		if (cg->cg_irotor >= 0 && cg->cg_irotor < fs->fs_ipg)
			newcg->cg_irotor = cg->cg_irotor;
		else
			newcg->cg_irotor = 0;
		if (fs->fs_magic == FS_UFS1_MAGIC) {
			newcg->cg_initediblk = 0;
		} else {
			if ((unsigned)cg->cg_initediblk > fs->fs_ipg)
				newcg->cg_initediblk = fs->fs_ipg;
			else
				newcg->cg_initediblk = cg->cg_initediblk;
		}
		memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
		memset(cg_inosused(newcg), 0, (size_t)(mapsize));
		j = fs->fs_ipg * c;
		for (i = 0; i < inostathead[c].il_numalloced; j++, i++) {
			switch (inoinfo(j)->ino_state) {

			case USTATE:
				break;

			case DSTATE:
			case DCLEAR:
			case DFOUND:
			case DZLINK:
				newcg->cg_cs.cs_ndir++;
				/* FALLTHROUGH */

			case FSTATE:
			case FCLEAR:
			case FZLINK:
				newcg->cg_cs.cs_nifree--;
				setbit(cg_inosused(newcg), i);
				break;

			default:
				if (j < (int)ROOTINO)
					break;
				errx(EEXIT, "BAD STATE %d FOR INODE I=%d",
				    inoinfo(j)->ino_state, j);
			}
		}
		if (c == 0)
			for (i = 0; i < (int)ROOTINO; i++) {
				setbit(cg_inosused(newcg), i);
				newcg->cg_cs.cs_nifree--;
			}
		start = -1;
		for (i = 0, d = dbase;
		     d < dmax;
		     d += fs->fs_frag, i += fs->fs_frag) {
			frags = 0;
			for (j = 0; j < fs->fs_frag; j++) {
				if (testbmap(d + j)) {
					if (Eflag && start != -1) {
						clear_blocks(start, d + j - 1);
						start = -1;
					}
					continue;
				}
				if (start == -1)
					start = d + j;
				setbit(cg_blksfree(newcg), i + j);
				frags++;
			}
			if (frags == fs->fs_frag) {
				newcg->cg_cs.cs_nbfree++;
				if (fs->fs_contigsumsize > 0)
					setbit(cg_clustersfree(newcg),
					    i / fs->fs_frag);
			} else if (frags > 0) {
				newcg->cg_cs.cs_nffree += frags;
				blk = blkmap(fs, cg_blksfree(newcg), i);
				ffs_fragacct(fs, blk, newcg->cg_frsum, 1);
			}
		}
		if (Eflag && start != -1)
			clear_blocks(start, d - 1);
		if (fs->fs_contigsumsize > 0) {
			int32_t *sump = cg_clustersum(newcg);
			u_char *mapp = cg_clustersfree(newcg);
			int map = *mapp++;
			int bit = 1;
			int run = 0;

			for (i = 0; i < newcg->cg_nclusterblks; i++) {
				if ((map & bit) != 0) {
					run++;
				} else if (run != 0) {
					if (run > fs->fs_contigsumsize)
						run = fs->fs_contigsumsize;
					sump[run]++;
					run = 0;
				}
				if ((i & (CHAR_BIT - 1)) != (CHAR_BIT - 1)) {
					bit <<= 1;
				} else {
					map = *mapp++;
					bit = 1;
				}
			}
			if (run != 0) {
				if (run > fs->fs_contigsumsize)
					run = fs->fs_contigsumsize;
				sump[run]++;
			}
		}
		if (bkgrdflag != 0) {
			cstotal.cs_nffree += cg->cg_cs.cs_nffree;
			cstotal.cs_nbfree += cg->cg_cs.cs_nbfree;
			cstotal.cs_nifree += cg->cg_cs.cs_nifree;
			cstotal.cs_ndir += cg->cg_cs.cs_ndir;
		} else {
			cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
			cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
			cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
			cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
		}
		cs = &fs->fs_cs(fs, c);
		if (cursnapshot == 0 &&
		    memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0 &&
		    dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
			memmove(cs, &newcg->cg_cs, sizeof *cs);
			sbdirty();
		}
		if (rewritecg) {
			memmove(cg, newcg, (size_t)fs->fs_cgsize);
			dirty(cgbp);
			continue;
		}
		if (cursnapshot == 0 &&
		    memcmp(newcg, cg, basesize) != 0 &&
		    dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
			memmove(cg, newcg, (size_t)basesize);
			dirty(cgbp);
		}
		if (bkgrdflag != 0 || usedsoftdep || debug)
			update_maps(cg, newcg, bkgrdflag);
		if (cursnapshot == 0 &&
		    memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0 &&
		    dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
			memmove(cg_inosused(cg), cg_inosused(newcg),
			      (size_t)mapsize);
			dirty(cgbp);
		}
	}
	if (cursnapshot == 0 &&
	    memcmp(&cstotal, &fs->fs_cstotal, sizeof cstotal) != 0
	    && dofix(&idesc[0], "SUMMARY BLK COUNT(S) WRONG IN SUPERBLK")) {
		memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal);
		fs->fs_ronly = 0;
		fs->fs_fmod = 0;
		sbdirty();
	}

	/*
	 * When doing background fsck on a snapshot, figure out whether
	 * the superblock summary is inaccurate and correct it when
	 * necessary.
	 */
	if (cursnapshot != 0) {
		cmd.size = 1;

		cmd.value = cstotal.cs_ndir - fs->fs_cstotal.cs_ndir;
		if (cmd.value != 0) {
			if (debug)
				printf("adjndir by %+" PRIi64 "\n", cmd.value);
			if (bkgrdsumadj == 0 || sysctl(adjndir, MIBSIZE, 0, 0,
			    &cmd, sizeof cmd) == -1)
				rwerror("ADJUST NUMBER OF DIRECTORIES", cmd.value);
		}

		cmd.value = cstotal.cs_nbfree - fs->fs_cstotal.cs_nbfree;
		if (cmd.value != 0) {
			if (debug)
				printf("adjnbfree by %+" PRIi64 "\n", cmd.value);
			if (bkgrdsumadj == 0 || sysctl(adjnbfree, MIBSIZE, 0, 0,
			    &cmd, sizeof cmd) == -1)
				rwerror("ADJUST NUMBER OF FREE BLOCKS", cmd.value);
		}

		cmd.value = cstotal.cs_nifree - fs->fs_cstotal.cs_nifree;
		if (cmd.value != 0) {
			if (debug)
				printf("adjnifree by %+" PRIi64 "\n", cmd.value);
			if (bkgrdsumadj == 0 || sysctl(adjnifree, MIBSIZE, 0, 0,
			    &cmd, sizeof cmd) == -1)
				rwerror("ADJUST NUMBER OF FREE INODES", cmd.value);
		}

		cmd.value = cstotal.cs_nffree - fs->fs_cstotal.cs_nffree;
		if (cmd.value != 0) {
			if (debug)
				printf("adjnffree by %+" PRIi64 "\n", cmd.value);
			if (bkgrdsumadj == 0 || sysctl(adjnffree, MIBSIZE, 0, 0,
			    &cmd, sizeof cmd) == -1)
				rwerror("ADJUST NUMBER OF FREE FRAGS", cmd.value);
		}

		cmd.value = cstotal.cs_numclusters - fs->fs_cstotal.cs_numclusters;
		if (cmd.value != 0) {
			if (debug)
				printf("adjnumclusters by %+" PRIi64 "\n", cmd.value);
			if (bkgrdsumadj == 0 || sysctl(adjnumclusters, MIBSIZE, 0, 0,
			    &cmd, sizeof cmd) == -1)
				rwerror("ADJUST NUMBER OF FREE CLUSTERS", cmd.value);
		}
	}
}
Пример #23
0
pass5()
{
	int c, blk, frags, basesize, sumsize, mapsize, savednrpos;
	register struct fs *fs = &sblock;
	register struct cg *cg = &cgrp;
	daddr_t dbase, dmax;
	register daddr_t d;
	register long i, j;
	struct csum *cs;
	time_t now;
	struct csum cstotal;
	struct inodesc idesc;
	char buf[MAXBSIZE];
	register struct cg *newcg = (struct cg *)buf;
	struct ocg *ocg = (struct ocg *)buf;

	bzero((char *)newcg, fs->fs_cgsize);
	newcg->cg_niblk = fs->fs_ipg;
	switch (fs->fs_postblformat) {

	case FS_42POSTBLFMT:
		basesize = (char *)(&ocg->cg_btot[0]) - (char *)(&ocg->cg_link);
		sumsize = &ocg->cg_iused[0] - (char *)(&ocg->cg_btot[0]);
		mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
			(u_char *)&ocg->cg_iused[0];
		ocg->cg_magic = CG_MAGIC;
		savednrpos = fs->fs_nrpos;
		fs->fs_nrpos = 8;
		break;

	case FS_DYNAMICPOSTBLFMT:
		newcg->cg_btotoff =
		 	&newcg->cg_space[0] - (u_char *)(&newcg->cg_link);
		newcg->cg_boff =
			newcg->cg_btotoff + fs->fs_cpg * sizeof(long);
		newcg->cg_iusedoff = newcg->cg_boff + 
			fs->fs_cpg * fs->fs_nrpos * sizeof(short);
		newcg->cg_freeoff =
			newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
		newcg->cg_nextfreeoff = newcg->cg_freeoff +
			howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs),
				NBBY);
		newcg->cg_magic = CG_MAGIC;
		basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_link);
		sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
		mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
		break;

	default:
		errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d\n",
			fs->fs_postblformat);
	}
	bzero((char *)&idesc, sizeof(struct inodesc));
	idesc.id_type = ADDR;
	bzero((char *)&cstotal, sizeof(struct csum));
	(void)time(&now);
	for (i = fs->fs_size; i < fragroundup(fs, fs->fs_size); i++)
		setbmap(i);
	for (c = 0; c < fs->fs_ncg; c++) {
		getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
		if (!cg_chkmagic(cg))
			pfatal("CG %d: BAD MAGIC NUMBER\n", c);
		dbase = cgbase(fs, c);
		dmax = dbase + fs->fs_fpg;
		if (dmax > fs->fs_size)
			dmax = fs->fs_size;
		if (now > cg->cg_time)
			newcg->cg_time = cg->cg_time;
		else
			newcg->cg_time = now;
		newcg->cg_cgx = c;
		if (c == fs->fs_ncg - 1)
			newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
		else
			newcg->cg_ncyl = fs->fs_cpg;
		newcg->cg_ndblk = dmax - dbase;
		newcg->cg_cs.cs_ndir = 0;
		newcg->cg_cs.cs_nffree = 0;
		newcg->cg_cs.cs_nbfree = 0;
		newcg->cg_cs.cs_nifree = fs->fs_ipg;
		if (cg->cg_rotor < newcg->cg_ndblk)
			newcg->cg_rotor = cg->cg_rotor;
		else
			newcg->cg_rotor = 0;
		if (cg->cg_frotor < newcg->cg_ndblk)
			newcg->cg_frotor = cg->cg_frotor;
		else
			newcg->cg_frotor = 0;
		if (cg->cg_irotor < newcg->cg_niblk)
			newcg->cg_irotor = cg->cg_irotor;
		else
			newcg->cg_irotor = 0;
		bzero((char *)&newcg->cg_frsum[0], sizeof newcg->cg_frsum);
		bzero((char *)&cg_blktot(newcg)[0], sumsize + mapsize);
		if (fs->fs_postblformat == FS_42POSTBLFMT)
			ocg->cg_magic = CG_MAGIC;
		j = fs->fs_ipg * c;
		for (i = 0; i < fs->fs_ipg; j++, i++) {
			switch (statemap[j]) {

			case USTATE:
				break;

			case DSTATE:
			case DCLEAR:
			case DFOUND:
				newcg->cg_cs.cs_ndir++;
				/* fall through */

			case FSTATE:
			case FCLEAR:
				newcg->cg_cs.cs_nifree--;
				setbit(cg_inosused(newcg), i);
				break;

			default:
				if (j < ROOTINO)
					break;
				errexit("BAD STATE %d FOR INODE I=%d",
				    statemap[j], j);
			}
		}
		if (c == 0)
			for (i = 0; i < ROOTINO; i++) {
				setbit(cg_inosused(newcg), i);
				newcg->cg_cs.cs_nifree--;
			}
		for (i = 0, d = dbase;
		     d < dmax;
		     d += fs->fs_frag, i += fs->fs_frag) {
			frags = 0;
			for (j = 0; j < fs->fs_frag; j++) {
				if (getbmap(d + j))
					continue;
				setbit(cg_blksfree(newcg), i + j);
				frags++;
			}
			if (frags == fs->fs_frag) {
				newcg->cg_cs.cs_nbfree++;
				j = cbtocylno(fs, i);
				cg_blktot(newcg)[j]++;
				cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++;
			} else if (frags > 0) {
				newcg->cg_cs.cs_nffree += frags;
				blk = blkmap(fs, cg_blksfree(newcg), i);
				fragacct(fs, blk, newcg->cg_frsum, 1);
			}
		}
		cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
		cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
		cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
		cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
		cs = &fs->fs_cs(fs, c);
		if (bcmp((char *)&newcg->cg_cs, (char *)cs, sizeof *cs) != 0 &&
		    dofix(&idesc, "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
			bcopy((char *)&newcg->cg_cs, (char *)cs, sizeof *cs);
			sbdirty();
		}
		if (cvtflag) {
			bcopy((char *)newcg, (char *)cg, fs->fs_cgsize);
			cgdirty();
			continue;
		}
		if (bcmp(cg_inosused(newcg),
			 cg_inosused(cg), mapsize) != 0 &&
		    dofix(&idesc, "BLK(S) MISSING IN BIT MAPS")) {
			bcopy(cg_inosused(newcg), cg_inosused(cg), mapsize);
			cgdirty();
		}
		if ((bcmp((char *)newcg, (char *)cg, basesize) != 0 ||
		     bcmp((char *)&cg_blktot(newcg)[0],
			  (char *)&cg_blktot(cg)[0], sumsize) != 0) &&
		    dofix(&idesc, "SUMMARY INFORMATION BAD")) {
			bcopy((char *)newcg, (char *)cg, basesize);
			bcopy((char *)&cg_blktot(newcg)[0],
			      (char *)&cg_blktot(cg)[0], sumsize);
			cgdirty();
		}
	}
	if (fs->fs_postblformat == FS_42POSTBLFMT)
		fs->fs_nrpos = savednrpos;
	if (bcmp((char *)&cstotal, (char *)&fs->fs_cstotal, sizeof *cs) != 0
	    && dofix(&idesc, "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
		bcopy((char *)&cstotal, (char *)&fs->fs_cstotal, sizeof *cs);
		fs->fs_ronly = 0;
		fs->fs_fmod = 0;
		sbdirty();
	}
}
Пример #24
0
static int
read_bsdcg(struct fs *fsp, struct cg *cgp, int cg, u_int32_t offset)
{
	int  i, max;
	u_int8_t *p;
	int count, j;
	unsigned long dboff, dbcount, dbstart;

	max = fsp->fs_fpg;
	p   = cg_blksfree(cgp);

	/* paranoia: make sure we stay in the buffer */
	assert(&p[max/NBBY] <= (u_int8_t *)cgp + fsp->fs_cgsize);

	/*
	 * XXX The bitmap is fragments, not FS blocks.
	 *
	 * The block bitmap lists blocks relative to the base (cgbase()) of
	 * the cylinder group. cgdmin() is the first actual datablock, but
	 * the bitmap includes all the blocks used for all the blocks
	 * comprising the cg. These include the superblock, cg, inodes,
	 * datablocks and the variable-sized padding before all of these
	 * (used to skew the offset of consecutive cgs).
	 * The "dbstart" parameter is thus the beginning of the cg, to which
	 * we add the bitmap offset. All blocks before cgdmin() will always
	 * be allocated, but we scan them anyway. 
	 */
	//assert(cgbase(fsp, cg) == cgstart(fsp, cg));
	dbstart = fsbtodb(fsp, cgbase(fsp, cg)) + offset;

	if (debug > 2)
		fprintf(stderr, "                   ");
	for (count = i = 0; i < max; i++)
		if (isset(p, i)) {
			j = i;
			while ((i+1)<max && isset(p, i+1))
				i++;

			dboff = dbstart + fsbtodb(fsp, j);
			dbcount = fsbtodb(fsp, (i-j) + 1);
			freecount += (i-j) + 1;
					
			if (debug > 2) {
				if (count)
					fprintf(stderr, ",%s",
						count % 4 ?
						" " : "\n                   ");
				fprintf(stderr, "%lu:%ld", dboff, dbcount);
			}
			addskip(dboff, dbcount);
			count++;
		}
	if (debug > 2)
		fprintf(stderr, "\n");

#ifdef DO_INODES
	/*
	 * Look for free inodes
	 */
	if (cgp->cg_cs.cs_nifree != 0) {
		int tifree = 0;
		unsigned long edboff;
		int ino;

		p = cg_inosused(cgp);
		max = fsp->fs_ipg;
		assert(&p[max/NBBY] <= (u_int8_t *)cgp + fsp->fs_cgsize);

		/*
		 * For UFS2, (cylinder-group relative) inode numbers beyond
		 * initediblk are uninitialized.  We do not process those
		 * now.  They are treated as regular free blocks below.
		 */
		if (fsp->fs_magic == FS_UFS2_MAGIC) {
			assert(cgp->cg_initediblk > 0);
			assert(cgp->cg_initediblk <= fsp->fs_ipg);
			assert((cgp->cg_initediblk % INOPB(fsp)) == 0);
			max = cgp->cg_initediblk;
		}
		ino = cg * fsp->fs_ipg;

#ifdef CLEAR_FREE_INODES
		if (metaoptimize) {
			static uint32_t ufs1_magic = FS_UFS1_MAGIC;
			static uint32_t ufs2_magic = FS_UFS2_MAGIC;
			uint32_t *magic;

			if (debug > 1)
				fprintf(stderr,
					"        \t ifree  %9d\n",
					cgp->cg_cs.cs_nifree);
			if (debug > 2)
				fprintf(stderr, "                   ");

			magic = (fsp->fs_magic == FS_UFS2_MAGIC) ?
				&ufs2_magic : &ufs1_magic;
			for (count = i = 0; i < max; i++) {
				if (isset(p, i)) {
					continue;
				}
				if (ino_to_fsbo(fsp, ino+i) == 0) {
					j = i;
					while ((i+1) < max && !isset(p, i+1))
						i++;

					dboff = fsbtodb(fsp,
							ino_to_fsba(fsp, ino+j));
					edboff = fsbtodb(fsp,
							 ino_to_fsba(fsp, ino+i));
#if 0
					fprintf(stderr, "      found free inodes %d-%d"
						" db %lu.%u to %lu.%u\n",
						ino+j, ino+i,
						dboff+offset, ino_to_fsbo(fsp, ino+j),
						edboff+offset, ino_to_fsbo(fsp, ino+i));
#endif
					tifree += (i+1 - j);
					dbcount = edboff - dboff;
					if ((i+1) == max)
						dbcount++;
					if (dbcount == 0)
						continue;

					addfixupfunc(inodefixup,
						     sectobytes(dboff+offset),
						     sectobytes(offset),
						     sectobytes(dbcount),
						     magic, sizeof(magic),
						     RELOC_NONE);
					if (debug > 2) {
						if (count)
							fprintf(stderr, ",%s",
								count % 4 ?
								" " :
								"\n                   ");
						fprintf(stderr, "%lu:%ld",
							dboff+offset, dbcount);
					}
					count++;
				} else
					tifree++;
			}
			assert(i == max);

			if (debug > 2)
				fprintf(stderr, "\n");
		}
#endif

		/*
		 * For UFS2, deal with uninitialized inodes.
		 * These are sweet, we just add them to the skip list.
		 */
		if (fsp->fs_magic == FS_UFS2_MAGIC && max < fsp->fs_ipg) {
			i = max;
			if (debug > 1)
				fprintf(stderr,
					"        \t uninit %9d\n",
					fsp->fs_ipg - i);
			if (debug > 2)
				fprintf(stderr, "                   ");

			max = fsp->fs_ipg;
#if 1
			/*
			 * Paranoia!
			 */
			j = i;
			while ((j+1) < max) {
				assert(!isset(p, j+1));
				j++;
			}
#endif
			tifree += (max - i);
			dboff = fsbtodb(fsp, ino_to_fsba(fsp, ino+i));
			edboff = fsbtodb(fsp, ino_to_fsba(fsp, ino+max-1));
			dbcount = edboff - dboff + 1;

			if (debug > 2)
				fprintf(stderr, "%lu:%ld",
					dboff+offset, dbcount);

			addskip(dboff+offset, dbcount);
			if (debug > 2)
				fprintf(stderr, "\n");
		}

#ifdef CLEAR_FREE_INODES
		if (metaoptimize && tifree != cgp->cg_cs.cs_nifree)
			fprintf(stderr, "Uh-oh! found %d free inodes, "
				"shoulda found %d\n",
				tifree, cgp->cg_cs.cs_nifree);
#endif
	}
#endif

	return 0;
}