Beispiel #1
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);
}
Beispiel #2
0
/*
 * allocate a data block with the specified number of fragments
 */
ufs2_daddr_t
allocblk(long frags)
{
    int i, j, k, cg, baseblk;
    struct cg *cgp = &cgrp;

    if (frags <= 0 || frags > sblock.fs_frag)
        return (0);
    for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) {
        for (j = 0; j <= sblock.fs_frag - frags; j++) {
            if (testbmap(i + j))
                continue;
            for (k = 1; k < frags; k++)
                if (testbmap(i + j + k))
                    break;
            if (k < frags) {
                j += k;
                continue;
            }
            cg = dtog(&sblock, i + j);
            getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
            if (!check_cgmagic(cg, cgp))
                return (0);
            baseblk = dtogd(&sblock, i + j);
            for (k = 0; k < frags; k++) {
                setbmap(i + j + k);
                clrbit(cg_blksfree(cgp), baseblk + k);
            }
            n_blks += frags;
            if (frags == sblock.fs_frag)
                cgp->cg_cs.cs_nbfree--;
            else
                cgp->cg_cs.cs_nffree -= frags;
            cgdirty();
            return (i + j);
        }
    }
    return (0);
}
Beispiel #3
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;
    }