xref: /csrg-svn/sbin/fsck/inode.c (revision 68992)
122046Sdist /*
261492Sbostic  * Copyright (c) 1980, 1986, 1993
361492Sbostic  *	The Regents of the University of California.  All rights reserved.
439976Smckusick  *
542701Sbostic  * %sccs.include.redist.c%
622046Sdist  */
722046Sdist 
816261Smckusick #ifndef lint
9*68992Sbostic static char sccsid[] = "@(#)inode.c	8.8 (Berkeley) 04/28/95";
1039976Smckusick #endif /* not lint */
1116261Smckusick 
1216261Smckusick #include <sys/param.h>
1353821Smckusick #include <sys/time.h>
1468908Smckusick 
1551532Sbostic #include <ufs/ufs/dinode.h>
1651532Sbostic #include <ufs/ufs/dir.h>
1751532Sbostic #include <ufs/ffs/fs.h>
1868908Smckusick 
1968908Smckusick #include <err.h>
2036963Sbostic #include <pwd.h>
2144934Smckusick #include <string.h>
2268908Smckusick 
2316261Smckusick #include "fsck.h"
2416261Smckusick 
2540647Smckusick static ino_t startinum;
2634225Smckusick 
2768908Smckusick static int iblock __P((struct inodesc *, long ilevel, quad_t isize));
2868908Smckusick 
2968908Smckusick int
ckinode(dp,idesc)3016261Smckusick ckinode(dp, idesc)
3139973Smckusick 	struct dinode *dp;
3216261Smckusick 	register struct inodesc *idesc;
3316261Smckusick {
3468548Smckusick 	ufs_daddr_t *ap;
3539973Smckusick 	long ret, n, ndb, offset;
3639973Smckusick 	struct dinode dino;
3753825Smckusick 	quad_t remsize, sizepb;
3854599Smckusick 	mode_t mode;
3916261Smckusick 
4044998Smckusick 	if (idesc->id_fix != IGNORE)
4144998Smckusick 		idesc->id_fix = DONTKNOW;
4218000Smckusick 	idesc->id_entryno = 0;
4318000Smckusick 	idesc->id_filesize = dp->di_size;
4454599Smckusick 	mode = dp->di_mode & IFMT;
4554599Smckusick 	if (mode == IFBLK || mode == IFCHR || (mode == IFLNK &&
4654599Smckusick 	    dp->di_size < sblock.fs_maxsymlinklen))
4716261Smckusick 		return (KEEPON);
4816261Smckusick 	dino = *dp;
4916261Smckusick 	ndb = howmany(dino.di_size, sblock.fs_bsize);
5016261Smckusick 	for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
5116261Smckusick 		if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
5216261Smckusick 			idesc->id_numfrags =
5316261Smckusick 				numfrags(&sblock, fragroundup(&sblock, offset));
5416261Smckusick 		else
5516261Smckusick 			idesc->id_numfrags = sblock.fs_frag;
5616261Smckusick 		if (*ap == 0)
5716261Smckusick 			continue;
5816261Smckusick 		idesc->id_blkno = *ap;
5916261Smckusick 		if (idesc->id_type == ADDR)
6016261Smckusick 			ret = (*idesc->id_func)(idesc);
6116261Smckusick 		else
6216261Smckusick 			ret = dirscan(idesc);
6316261Smckusick 		if (ret & STOP)
6416261Smckusick 			return (ret);
6516261Smckusick 	}
6616261Smckusick 	idesc->id_numfrags = sblock.fs_frag;
6753825Smckusick 	remsize = dino.di_size - sblock.fs_bsize * NDADDR;
6853825Smckusick 	sizepb = sblock.fs_bsize;
6917930Smckusick 	for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
7016261Smckusick 		if (*ap) {
7116261Smckusick 			idesc->id_blkno = *ap;
7253825Smckusick 			ret = iblock(idesc, n, remsize);
7316261Smckusick 			if (ret & STOP)
7416261Smckusick 				return (ret);
7516261Smckusick 		}
7653825Smckusick 		sizepb *= NINDIR(&sblock);
7753825Smckusick 		remsize -= sizepb;
7816261Smckusick 	}
7916261Smckusick 	return (KEEPON);
8016261Smckusick }
8116261Smckusick 
8268908Smckusick static int
iblock(idesc,ilevel,isize)8316261Smckusick iblock(idesc, ilevel, isize)
8416261Smckusick 	struct inodesc *idesc;
8553825Smckusick 	long ilevel;
8652983Smckusick 	quad_t isize;
8716261Smckusick {
8868548Smckusick 	ufs_daddr_t *ap;
8968548Smckusick 	ufs_daddr_t *aplim;
9068548Smckusick 	struct bufarea *bp;
9153821Smckusick 	int i, n, (*func)(), nif;
9253821Smckusick 	quad_t sizepb;
9323876Smckusick 	char buf[BUFSIZ];
9416261Smckusick 
9516261Smckusick 	if (idesc->id_type == ADDR) {
9616261Smckusick 		func = idesc->id_func;
9716261Smckusick 		if (((n = (*func)(idesc)) & KEEPON) == 0)
9816261Smckusick 			return (n);
9916261Smckusick 	} else
10016261Smckusick 		func = dirscan;
10139973Smckusick 	if (chkrange(idesc->id_blkno, idesc->id_numfrags))
10216261Smckusick 		return (SKIP);
10334225Smckusick 	bp = getdatablk(idesc->id_blkno, sblock.fs_bsize);
10416261Smckusick 	ilevel--;
10517930Smckusick 	for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
10617930Smckusick 		sizepb *= NINDIR(&sblock);
10753825Smckusick 	nif = howmany(isize , sizepb);
10816261Smckusick 	if (nif > NINDIR(&sblock))
10916261Smckusick 		nif = NINDIR(&sblock);
11017950Smckusick 	if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
11134225Smckusick 		aplim = &bp->b_un.b_indir[NINDIR(&sblock)];
11234225Smckusick 		for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) {
11317950Smckusick 			if (*ap == 0)
11417950Smckusick 				continue;
11544934Smckusick 			(void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu",
11623876Smckusick 				idesc->id_number);
11723876Smckusick 			if (dofix(idesc, buf)) {
11817950Smckusick 				*ap = 0;
11934225Smckusick 				dirty(bp);
12017950Smckusick 			}
12117950Smckusick 		}
12239973Smckusick 		flush(fswritefd, bp);
12317950Smckusick 	}
12434225Smckusick 	aplim = &bp->b_un.b_indir[nif];
12553825Smckusick 	for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
12616261Smckusick 		if (*ap) {
12716261Smckusick 			idesc->id_blkno = *ap;
12866898Smckusick 			if (ilevel == 0)
12916261Smckusick 				n = (*func)(idesc);
13066898Smckusick 			else
13153825Smckusick 				n = iblock(idesc, ilevel, isize);
13234225Smckusick 			if (n & STOP) {
13334225Smckusick 				bp->b_flags &= ~B_INUSE;
13416261Smckusick 				return (n);
13534225Smckusick 			}
13616261Smckusick 		}
13766898Smckusick 		isize -= sizepb;
13834225Smckusick 	}
13934225Smckusick 	bp->b_flags &= ~B_INUSE;
14016261Smckusick 	return (KEEPON);
14116261Smckusick }
14216261Smckusick 
14339973Smckusick /*
14439973Smckusick  * Check that a block in a legal block number.
14539973Smckusick  * Return 0 if in range, 1 if out of range.
14639973Smckusick  */
14768908Smckusick int
chkrange(blk,cnt)14839973Smckusick chkrange(blk, cnt)
14968548Smckusick 	ufs_daddr_t blk;
15016261Smckusick 	int cnt;
15116261Smckusick {
15216261Smckusick 	register int c;
15316261Smckusick 
15439973Smckusick 	if ((unsigned)(blk + cnt) > maxfsblock)
15516261Smckusick 		return (1);
15616261Smckusick 	c = dtog(&sblock, blk);
15716261Smckusick 	if (blk < cgdmin(&sblock, c)) {
15839973Smckusick 		if ((blk + cnt) > cgsblock(&sblock, c)) {
15916261Smckusick 			if (debug) {
16044934Smckusick 				printf("blk %ld < cgdmin %ld;",
16116261Smckusick 				    blk, cgdmin(&sblock, c));
16244934Smckusick 				printf(" blk + cnt %ld > cgsbase %ld\n",
16339973Smckusick 				    blk + cnt, cgsblock(&sblock, c));
16416261Smckusick 			}
16516261Smckusick 			return (1);
16616261Smckusick 		}
16716261Smckusick 	} else {
16839973Smckusick 		if ((blk + cnt) > cgbase(&sblock, c+1)) {
16916261Smckusick 			if (debug)  {
17044934Smckusick 				printf("blk %ld >= cgdmin %ld;",
17116261Smckusick 				    blk, cgdmin(&sblock, c));
17244934Smckusick 				printf(" blk + cnt %ld > sblock.fs_fpg %ld\n",
17316261Smckusick 				    blk+cnt, sblock.fs_fpg);
17416261Smckusick 			}
17516261Smckusick 			return (1);
17616261Smckusick 		}
17716261Smckusick 	}
17816261Smckusick 	return (0);
17916261Smckusick }
18016261Smckusick 
18140024Smckusick /*
18240024Smckusick  * General purpose interface for reading inodes.
18340024Smckusick  */
18439973Smckusick struct dinode *
ginode(inumber)18516261Smckusick ginode(inumber)
18616261Smckusick 	ino_t inumber;
18716261Smckusick {
18868548Smckusick 	ufs_daddr_t iblk;
18916261Smckusick 
19039973Smckusick 	if (inumber < ROOTINO || inumber > maxino)
19168908Smckusick 		errx(EEXIT, "bad inode number %d to ginode", inumber);
19216261Smckusick 	if (startinum == 0 ||
19316261Smckusick 	    inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
19464639Sbostic 		iblk = ino_to_fsba(&sblock, inumber);
19534225Smckusick 		if (pbp != 0)
19634225Smckusick 			pbp->b_flags &= ~B_INUSE;
19734225Smckusick 		pbp = getdatablk(iblk, sblock.fs_bsize);
19816261Smckusick 		startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
19916261Smckusick 	}
20034225Smckusick 	return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]);
20116261Smckusick }
20216261Smckusick 
20340024Smckusick /*
20440024Smckusick  * Special purpose version of ginode used to optimize first pass
20540024Smckusick  * over all the inodes in numerical order.
20640024Smckusick  */
20740024Smckusick ino_t nextino, lastinum;
20840024Smckusick long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
20940024Smckusick struct dinode *inodebuf;
21040024Smckusick 
21140024Smckusick struct dinode *
getnextinode(inumber)21240024Smckusick getnextinode(inumber)
21340024Smckusick 	ino_t inumber;
21440024Smckusick {
21540024Smckusick 	long size;
21668548Smckusick 	ufs_daddr_t dblk;
21740024Smckusick 	static struct dinode *dp;
21840024Smckusick 
21940024Smckusick 	if (inumber != nextino++ || inumber > maxino)
22068908Smckusick 		errx(EEXIT, "bad inode number %d to nextinode", inumber);
22140024Smckusick 	if (inumber >= lastinum) {
22240024Smckusick 		readcnt++;
22364639Sbostic 		dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum));
22440024Smckusick 		if (readcnt % readpercg == 0) {
22540024Smckusick 			size = partialsize;
22640024Smckusick 			lastinum += partialcnt;
22740024Smckusick 		} else {
22840024Smckusick 			size = inobufsize;
22940024Smckusick 			lastinum += fullcnt;
23040024Smckusick 		}
23144934Smckusick 		(void)bread(fsreadfd, (char *)inodebuf, dblk, size); /* ??? */
23240024Smckusick 		dp = inodebuf;
23340024Smckusick 	}
23440024Smckusick 	return (dp++);
23540024Smckusick }
23640024Smckusick 
23768908Smckusick void
resetinodebuf()23840024Smckusick resetinodebuf()
23940024Smckusick {
24040024Smckusick 
24140647Smckusick 	startinum = 0;
24240024Smckusick 	nextino = 0;
24340024Smckusick 	lastinum = 0;
24440024Smckusick 	readcnt = 0;
24540024Smckusick 	inobufsize = blkroundup(&sblock, INOBUFSIZE);
24640024Smckusick 	fullcnt = inobufsize / sizeof(struct dinode);
24740024Smckusick 	readpercg = sblock.fs_ipg / fullcnt;
24840024Smckusick 	partialcnt = sblock.fs_ipg % fullcnt;
24940024Smckusick 	partialsize = partialcnt * sizeof(struct dinode);
25040024Smckusick 	if (partialcnt != 0) {
25140024Smckusick 		readpercg++;
25240024Smckusick 	} else {
25340024Smckusick 		partialcnt = fullcnt;
25440024Smckusick 		partialsize = inobufsize;
25540024Smckusick 	}
25640024Smckusick 	if (inodebuf == NULL &&
25740024Smckusick 	    (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL)
25868908Smckusick 		errx(EEXIT, "Cannot allocate space for inode buffer");
25940024Smckusick 	while (nextino < ROOTINO)
26044934Smckusick 		(void)getnextinode(nextino);
26140024Smckusick }
26240024Smckusick 
26368908Smckusick void
freeinodebuf()26440024Smckusick freeinodebuf()
26540024Smckusick {
26640024Smckusick 
26740024Smckusick 	if (inodebuf != NULL)
26840024Smckusick 		free((char *)inodebuf);
26940024Smckusick 	inodebuf = NULL;
27040024Smckusick }
27140024Smckusick 
27240024Smckusick /*
27340024Smckusick  * Routines to maintain information about directory inodes.
27440024Smckusick  * This is built during the first pass and used during the
27540024Smckusick  * second and third passes.
27640024Smckusick  *
27740024Smckusick  * Enter inodes into the cache.
27840024Smckusick  */
27968908Smckusick void
cacheino(dp,inumber)28039980Smckusick cacheino(dp, inumber)
28139980Smckusick 	register struct dinode *dp;
28239980Smckusick 	ino_t inumber;
28339980Smckusick {
28439980Smckusick 	register struct inoinfo *inp;
28539980Smckusick 	struct inoinfo **inpp;
28639980Smckusick 	unsigned int blks;
28739980Smckusick 
28839980Smckusick 	blks = howmany(dp->di_size, sblock.fs_bsize);
28939980Smckusick 	if (blks > NDADDR)
29039980Smckusick 		blks = NDADDR + NIADDR;
29139980Smckusick 	inp = (struct inoinfo *)
29268548Smckusick 		malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t));
29339980Smckusick 	if (inp == NULL)
29439980Smckusick 		return;
29540024Smckusick 	inpp = &inphead[inumber % numdirs];
29640024Smckusick 	inp->i_nexthash = *inpp;
29739980Smckusick 	*inpp = inp;
29868249Smckusick 	if (inumber == ROOTINO)
29968249Smckusick 		inp->i_parent = ROOTINO;
30068249Smckusick 	else
30168249Smckusick 		inp->i_parent = (ino_t)0;
30240024Smckusick 	inp->i_dotdot = (ino_t)0;
30339980Smckusick 	inp->i_number = inumber;
30440024Smckusick 	inp->i_isize = dp->di_size;
30568548Smckusick 	inp->i_numblks = blks * sizeof(ufs_daddr_t);
306*68992Sbostic 	memmove(&inp->i_blks[0], &dp->di_db[0], (size_t)inp->i_numblks);
30740024Smckusick 	if (inplast == listmax) {
30840024Smckusick 		listmax += 100;
30940024Smckusick 		inpsort = (struct inoinfo **)realloc((char *)inpsort,
31040024Smckusick 		    (unsigned)listmax * sizeof(struct inoinfo *));
31140024Smckusick 		if (inpsort == NULL)
31268908Smckusick 			errx(EEXIT, "cannot increase directory list");
31340024Smckusick 	}
31440024Smckusick 	inpsort[inplast++] = inp;
31539980Smckusick }
31639980Smckusick 
31740024Smckusick /*
31840024Smckusick  * Look up an inode cache structure.
31940024Smckusick  */
32040024Smckusick struct inoinfo *
getinoinfo(inumber)32140024Smckusick getinoinfo(inumber)
32239980Smckusick 	ino_t inumber;
32339980Smckusick {
32439980Smckusick 	register struct inoinfo *inp;
32539980Smckusick 
32640024Smckusick 	for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) {
32739980Smckusick 		if (inp->i_number != inumber)
32839980Smckusick 			continue;
32940024Smckusick 		return (inp);
33039980Smckusick 	}
33168908Smckusick 	errx(EEXIT, "cannot find inode %d", inumber);
33240024Smckusick 	return ((struct inoinfo *)0);
33339980Smckusick }
33439980Smckusick 
33540024Smckusick /*
33640024Smckusick  * Clean up all the inode cache structure.
33740024Smckusick  */
33868908Smckusick void
inocleanup()33939980Smckusick inocleanup()
34039980Smckusick {
34140024Smckusick 	register struct inoinfo **inpp;
34239980Smckusick 
34339980Smckusick 	if (inphead == NULL)
34439980Smckusick 		return;
34540024Smckusick 	for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--)
34640024Smckusick 		free((char *)(*inpp));
34740024Smckusick 	free((char *)inphead);
34840024Smckusick 	free((char *)inpsort);
34940024Smckusick 	inphead = inpsort = NULL;
35039980Smckusick }
35139980Smckusick 
35268908Smckusick void
inodirty()35334225Smckusick inodirty()
35434225Smckusick {
35534225Smckusick 
35634225Smckusick 	dirty(pbp);
35734225Smckusick }
35834225Smckusick 
35968908Smckusick void
clri(idesc,type,flag)36039973Smckusick clri(idesc, type, flag)
36116261Smckusick 	register struct inodesc *idesc;
36239973Smckusick 	char *type;
36339973Smckusick 	int flag;
36416261Smckusick {
36539973Smckusick 	register struct dinode *dp;
36616261Smckusick 
36717943Smckusick 	dp = ginode(idesc->id_number);
36839973Smckusick 	if (flag == 1) {
36939973Smckusick 		pwarn("%s %s", type,
37039973Smckusick 		    (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE");
37116261Smckusick 		pinode(idesc->id_number);
37216261Smckusick 	}
37316261Smckusick 	if (preen || reply("CLEAR") == 1) {
37416261Smckusick 		if (preen)
37516261Smckusick 			printf(" (CLEARED)\n");
37616261Smckusick 		n_files--;
37716261Smckusick 		(void)ckinode(dp, idesc);
37839973Smckusick 		clearinode(dp);
37916261Smckusick 		statemap[idesc->id_number] = USTATE;
38016261Smckusick 		inodirty();
38116261Smckusick 	}
38216261Smckusick }
38316261Smckusick 
38468908Smckusick int
findname(idesc)38517991Smckusick findname(idesc)
38617991Smckusick 	struct inodesc *idesc;
38717991Smckusick {
38839973Smckusick 	register struct direct *dirp = idesc->id_dirp;
38917991Smckusick 
39017991Smckusick 	if (dirp->d_ino != idesc->id_parent)
39117991Smckusick 		return (KEEPON);
392*68992Sbostic 	memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1);
39330354Smckusick 	return (STOP|FOUND);
39417991Smckusick }
39517991Smckusick 
39668908Smckusick int
findino(idesc)39716261Smckusick findino(idesc)
39816261Smckusick 	struct inodesc *idesc;
39916261Smckusick {
40039973Smckusick 	register struct direct *dirp = idesc->id_dirp;
40116261Smckusick 
40216261Smckusick 	if (dirp->d_ino == 0)
40316261Smckusick 		return (KEEPON);
40417991Smckusick 	if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
40539973Smckusick 	    dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) {
40617991Smckusick 		idesc->id_parent = dirp->d_ino;
40730354Smckusick 		return (STOP|FOUND);
40816261Smckusick 	}
40916261Smckusick 	return (KEEPON);
41016261Smckusick }
41116261Smckusick 
41268908Smckusick void
pinode(ino)41316261Smckusick pinode(ino)
41416261Smckusick 	ino_t ino;
41516261Smckusick {
41639973Smckusick 	register struct dinode *dp;
41716261Smckusick 	register char *p;
41818102Smckusick 	struct passwd *pw;
41916261Smckusick 	char *ctime();
42016261Smckusick 
42144934Smckusick 	printf(" I=%lu ", ino);
42239973Smckusick 	if (ino < ROOTINO || ino > maxino)
42316261Smckusick 		return;
42417943Smckusick 	dp = ginode(ino);
42516261Smckusick 	printf(" OWNER=");
42618102Smckusick 	if ((pw = getpwuid((int)dp->di_uid)) != 0)
42718102Smckusick 		printf("%s ", pw->pw_name);
42818102Smckusick 	else
42944934Smckusick 		printf("%u ", (unsigned)dp->di_uid);
43016261Smckusick 	printf("MODE=%o\n", dp->di_mode);
43116261Smckusick 	if (preen)
43261110Sbostic 		printf("%s: ", cdevname);
43353821Smckusick 	printf("SIZE=%qu ", dp->di_size);
43468548Smckusick 	p = ctime(&dp->di_mtime);
43547579Smckusick 	printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]);
43616261Smckusick }
43716261Smckusick 
43868908Smckusick void
blkerror(ino,type,blk)43939973Smckusick blkerror(ino, type, blk)
44016261Smckusick 	ino_t ino;
44139973Smckusick 	char *type;
44268548Smckusick 	ufs_daddr_t blk;
44316261Smckusick {
44416261Smckusick 
44544934Smckusick 	pfatal("%ld %s I=%lu", blk, type, ino);
44616261Smckusick 	printf("\n");
44717936Smckusick 	switch (statemap[ino]) {
44817936Smckusick 
44917936Smckusick 	case FSTATE:
45017936Smckusick 		statemap[ino] = FCLEAR;
45117936Smckusick 		return;
45217936Smckusick 
45317936Smckusick 	case DSTATE:
45417936Smckusick 		statemap[ino] = DCLEAR;
45517936Smckusick 		return;
45617936Smckusick 
45717936Smckusick 	case FCLEAR:
45817936Smckusick 	case DCLEAR:
45917936Smckusick 		return;
46017936Smckusick 
46117936Smckusick 	default:
46268908Smckusick 		errx(EEXIT, "BAD STATE %d TO BLKERR", statemap[ino]);
46317936Smckusick 		/* NOTREACHED */
46417936Smckusick 	}
46516261Smckusick }
46617955Smckusick 
46717955Smckusick /*
46817955Smckusick  * allocate an unused inode
46917955Smckusick  */
47017955Smckusick ino_t
allocino(request,type)47117955Smckusick allocino(request, type)
47217955Smckusick 	ino_t request;
47317955Smckusick 	int type;
47417955Smckusick {
47517955Smckusick 	register ino_t ino;
47639973Smckusick 	register struct dinode *dp;
47717955Smckusick 
47817955Smckusick 	if (request == 0)
47917955Smckusick 		request = ROOTINO;
48017955Smckusick 	else if (statemap[request] != USTATE)
48117955Smckusick 		return (0);
48239973Smckusick 	for (ino = request; ino < maxino; ino++)
48317955Smckusick 		if (statemap[ino] == USTATE)
48417955Smckusick 			break;
48539973Smckusick 	if (ino == maxino)
48617955Smckusick 		return (0);
48717955Smckusick 	switch (type & IFMT) {
48817955Smckusick 	case IFDIR:
48917955Smckusick 		statemap[ino] = DSTATE;
49017955Smckusick 		break;
49117955Smckusick 	case IFREG:
49217955Smckusick 	case IFLNK:
49317955Smckusick 		statemap[ino] = FSTATE;
49417955Smckusick 		break;
49517955Smckusick 	default:
49617955Smckusick 		return (0);
49717955Smckusick 	}
49817955Smckusick 	dp = ginode(ino);
49939973Smckusick 	dp->di_db[0] = allocblk((long)1);
50017955Smckusick 	if (dp->di_db[0] == 0) {
50117955Smckusick 		statemap[ino] = USTATE;
50217955Smckusick 		return (0);
50317955Smckusick 	}
50417955Smckusick 	dp->di_mode = type;
50568548Smckusick 	(void)time(&dp->di_atime);
50617955Smckusick 	dp->di_mtime = dp->di_ctime = dp->di_atime;
50717955Smckusick 	dp->di_size = sblock.fs_fsize;
50817955Smckusick 	dp->di_blocks = btodb(sblock.fs_fsize);
50917955Smckusick 	n_files++;
51017955Smckusick 	inodirty();
51166277Smkm 	if (newinofmt)
51266277Smkm 		typemap[ino] = IFTODT(type);
51317955Smckusick 	return (ino);
51417955Smckusick }
51517955Smckusick 
51617955Smckusick /*
51717955Smckusick  * deallocate an inode
51817955Smckusick  */
51968908Smckusick void
freeino(ino)52017955Smckusick freeino(ino)
52117955Smckusick 	ino_t ino;
52217955Smckusick {
52317955Smckusick 	struct inodesc idesc;
52439973Smckusick 	struct dinode *dp;
52517955Smckusick 
526*68992Sbostic 	memset(&idesc, 0, sizeof(struct inodesc));
52717955Smckusick 	idesc.id_type = ADDR;
52817955Smckusick 	idesc.id_func = pass4check;
52917955Smckusick 	idesc.id_number = ino;
53017955Smckusick 	dp = ginode(ino);
53117955Smckusick 	(void)ckinode(dp, &idesc);
53239973Smckusick 	clearinode(dp);
53317955Smckusick 	inodirty();
53417955Smckusick 	statemap[ino] = USTATE;
53517955Smckusick 	n_files--;
53617955Smckusick }
537