xref: /csrg-svn/sbin/fsck/inode.c (revision 52983)
122046Sdist /*
239976Smckusick  * Copyright (c) 1980, 1986 The Regents of the University of California.
339976Smckusick  * All rights reserved.
439976Smckusick  *
542701Sbostic  * %sccs.include.redist.c%
622046Sdist  */
722046Sdist 
816261Smckusick #ifndef lint
9*52983Smckusick static char sccsid[] = "@(#)inode.c	5.20 (Berkeley) 03/16/92";
1039976Smckusick #endif /* not lint */
1116261Smckusick 
1216261Smckusick #include <sys/param.h>
1351532Sbostic #include <ufs/ufs/dinode.h>
1451532Sbostic #include <ufs/ufs/dir.h>
1551532Sbostic #include <ufs/ffs/fs.h>
1636963Sbostic #include <pwd.h>
1744934Smckusick #include <stdlib.h>
1844934Smckusick #include <string.h>
1916261Smckusick #include "fsck.h"
2016261Smckusick 
2140647Smckusick static ino_t startinum;
2234225Smckusick 
2316261Smckusick ckinode(dp, idesc)
2439973Smckusick 	struct dinode *dp;
2516261Smckusick 	register struct inodesc *idesc;
2616261Smckusick {
2716261Smckusick 	register daddr_t *ap;
2839973Smckusick 	long ret, n, ndb, offset;
2939973Smckusick 	struct dinode dino;
3016261Smckusick 
3144998Smckusick 	if (idesc->id_fix != IGNORE)
3244998Smckusick 		idesc->id_fix = DONTKNOW;
3318000Smckusick 	idesc->id_entryno = 0;
3418000Smckusick 	idesc->id_filesize = dp->di_size;
3539973Smckusick 	if ((dp->di_mode & IFMT) == IFBLK || (dp->di_mode & IFMT) == IFCHR)
3616261Smckusick 		return (KEEPON);
3716261Smckusick 	dino = *dp;
3816261Smckusick 	ndb = howmany(dino.di_size, sblock.fs_bsize);
3916261Smckusick 	for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
4016261Smckusick 		if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
4116261Smckusick 			idesc->id_numfrags =
4216261Smckusick 				numfrags(&sblock, fragroundup(&sblock, offset));
4316261Smckusick 		else
4416261Smckusick 			idesc->id_numfrags = sblock.fs_frag;
4516261Smckusick 		if (*ap == 0)
4616261Smckusick 			continue;
4716261Smckusick 		idesc->id_blkno = *ap;
4816261Smckusick 		if (idesc->id_type == ADDR)
4916261Smckusick 			ret = (*idesc->id_func)(idesc);
5016261Smckusick 		else
5116261Smckusick 			ret = dirscan(idesc);
5216261Smckusick 		if (ret & STOP)
5316261Smckusick 			return (ret);
5416261Smckusick 	}
5516261Smckusick 	idesc->id_numfrags = sblock.fs_frag;
5617930Smckusick 	for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
5716261Smckusick 		if (*ap) {
5816261Smckusick 			idesc->id_blkno = *ap;
5916261Smckusick 			ret = iblock(idesc, n,
6016261Smckusick 				dino.di_size - sblock.fs_bsize * NDADDR);
6116261Smckusick 			if (ret & STOP)
6216261Smckusick 				return (ret);
6316261Smckusick 		}
6416261Smckusick 	}
6516261Smckusick 	return (KEEPON);
6616261Smckusick }
6716261Smckusick 
6816261Smckusick iblock(idesc, ilevel, isize)
6916261Smckusick 	struct inodesc *idesc;
7039973Smckusick 	register long ilevel;
71*52983Smckusick 	quad_t isize;
7216261Smckusick {
7316261Smckusick 	register daddr_t *ap;
7416261Smckusick 	register daddr_t *aplim;
7517930Smckusick 	int i, n, (*func)(), nif, sizepb;
7639973Smckusick 	register struct bufarea *bp;
7723876Smckusick 	char buf[BUFSIZ];
7833083Sbostic 	extern int dirscan(), pass1check();
7916261Smckusick 
8016261Smckusick 	if (idesc->id_type == ADDR) {
8116261Smckusick 		func = idesc->id_func;
8216261Smckusick 		if (((n = (*func)(idesc)) & KEEPON) == 0)
8316261Smckusick 			return (n);
8416261Smckusick 	} else
8516261Smckusick 		func = dirscan;
8639973Smckusick 	if (chkrange(idesc->id_blkno, idesc->id_numfrags))
8716261Smckusick 		return (SKIP);
8834225Smckusick 	bp = getdatablk(idesc->id_blkno, sblock.fs_bsize);
8916261Smckusick 	ilevel--;
9017930Smckusick 	for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
9117930Smckusick 		sizepb *= NINDIR(&sblock);
9217930Smckusick 	nif = isize / sizepb + 1;
9316261Smckusick 	if (nif > NINDIR(&sblock))
9416261Smckusick 		nif = NINDIR(&sblock);
9517950Smckusick 	if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
9634225Smckusick 		aplim = &bp->b_un.b_indir[NINDIR(&sblock)];
9734225Smckusick 		for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) {
9817950Smckusick 			if (*ap == 0)
9917950Smckusick 				continue;
10044934Smckusick 			(void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu",
10123876Smckusick 				idesc->id_number);
10223876Smckusick 			if (dofix(idesc, buf)) {
10317950Smckusick 				*ap = 0;
10434225Smckusick 				dirty(bp);
10517950Smckusick 			}
10617950Smckusick 		}
10739973Smckusick 		flush(fswritefd, bp);
10817950Smckusick 	}
10934225Smckusick 	aplim = &bp->b_un.b_indir[nif];
11034225Smckusick 	for (ap = bp->b_un.b_indir, i = 1; ap < aplim; ap++, i++) {
11116261Smckusick 		if (*ap) {
11216261Smckusick 			idesc->id_blkno = *ap;
11316261Smckusick 			if (ilevel > 0)
11417930Smckusick 				n = iblock(idesc, ilevel, isize - i * sizepb);
11516261Smckusick 			else
11616261Smckusick 				n = (*func)(idesc);
11734225Smckusick 			if (n & STOP) {
11834225Smckusick 				bp->b_flags &= ~B_INUSE;
11916261Smckusick 				return (n);
12034225Smckusick 			}
12116261Smckusick 		}
12234225Smckusick 	}
12334225Smckusick 	bp->b_flags &= ~B_INUSE;
12416261Smckusick 	return (KEEPON);
12516261Smckusick }
12616261Smckusick 
12739973Smckusick /*
12839973Smckusick  * Check that a block in a legal block number.
12939973Smckusick  * Return 0 if in range, 1 if out of range.
13039973Smckusick  */
13139973Smckusick chkrange(blk, cnt)
13216261Smckusick 	daddr_t blk;
13316261Smckusick 	int cnt;
13416261Smckusick {
13516261Smckusick 	register int c;
13616261Smckusick 
13739973Smckusick 	if ((unsigned)(blk + cnt) > maxfsblock)
13816261Smckusick 		return (1);
13916261Smckusick 	c = dtog(&sblock, blk);
14016261Smckusick 	if (blk < cgdmin(&sblock, c)) {
14139973Smckusick 		if ((blk + cnt) > cgsblock(&sblock, c)) {
14216261Smckusick 			if (debug) {
14344934Smckusick 				printf("blk %ld < cgdmin %ld;",
14416261Smckusick 				    blk, cgdmin(&sblock, c));
14544934Smckusick 				printf(" blk + cnt %ld > cgsbase %ld\n",
14639973Smckusick 				    blk + cnt, cgsblock(&sblock, c));
14716261Smckusick 			}
14816261Smckusick 			return (1);
14916261Smckusick 		}
15016261Smckusick 	} else {
15139973Smckusick 		if ((blk + cnt) > cgbase(&sblock, c+1)) {
15216261Smckusick 			if (debug)  {
15344934Smckusick 				printf("blk %ld >= cgdmin %ld;",
15416261Smckusick 				    blk, cgdmin(&sblock, c));
15544934Smckusick 				printf(" blk + cnt %ld > sblock.fs_fpg %ld\n",
15616261Smckusick 				    blk+cnt, sblock.fs_fpg);
15716261Smckusick 			}
15816261Smckusick 			return (1);
15916261Smckusick 		}
16016261Smckusick 	}
16116261Smckusick 	return (0);
16216261Smckusick }
16316261Smckusick 
16440024Smckusick /*
16540024Smckusick  * General purpose interface for reading inodes.
16640024Smckusick  */
16739973Smckusick struct dinode *
16816261Smckusick ginode(inumber)
16916261Smckusick 	ino_t inumber;
17016261Smckusick {
17116261Smckusick 	daddr_t iblk;
17216261Smckusick 
17339973Smckusick 	if (inumber < ROOTINO || inumber > maxino)
17417943Smckusick 		errexit("bad inode number %d to ginode\n", inumber);
17516261Smckusick 	if (startinum == 0 ||
17616261Smckusick 	    inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
17716261Smckusick 		iblk = itod(&sblock, inumber);
17834225Smckusick 		if (pbp != 0)
17934225Smckusick 			pbp->b_flags &= ~B_INUSE;
18034225Smckusick 		pbp = getdatablk(iblk, sblock.fs_bsize);
18116261Smckusick 		startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
18216261Smckusick 	}
18334225Smckusick 	return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]);
18416261Smckusick }
18516261Smckusick 
18640024Smckusick /*
18740024Smckusick  * Special purpose version of ginode used to optimize first pass
18840024Smckusick  * over all the inodes in numerical order.
18940024Smckusick  */
19040024Smckusick ino_t nextino, lastinum;
19140024Smckusick long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
19240024Smckusick struct dinode *inodebuf;
19340024Smckusick 
19440024Smckusick struct dinode *
19540024Smckusick getnextinode(inumber)
19640024Smckusick 	ino_t inumber;
19740024Smckusick {
19840024Smckusick 	long size;
19940024Smckusick 	daddr_t dblk;
20040024Smckusick 	static struct dinode *dp;
20140024Smckusick 
20240024Smckusick 	if (inumber != nextino++ || inumber > maxino)
20340024Smckusick 		errexit("bad inode number %d to nextinode\n", inumber);
20440024Smckusick 	if (inumber >= lastinum) {
20540024Smckusick 		readcnt++;
20640024Smckusick 		dblk = fsbtodb(&sblock, itod(&sblock, lastinum));
20740024Smckusick 		if (readcnt % readpercg == 0) {
20840024Smckusick 			size = partialsize;
20940024Smckusick 			lastinum += partialcnt;
21040024Smckusick 		} else {
21140024Smckusick 			size = inobufsize;
21240024Smckusick 			lastinum += fullcnt;
21340024Smckusick 		}
21444934Smckusick 		(void)bread(fsreadfd, (char *)inodebuf, dblk, size); /* ??? */
21540024Smckusick 		dp = inodebuf;
21640024Smckusick 	}
21740024Smckusick 	return (dp++);
21840024Smckusick }
21940024Smckusick 
22040024Smckusick resetinodebuf()
22140024Smckusick {
22240024Smckusick 
22340647Smckusick 	startinum = 0;
22440024Smckusick 	nextino = 0;
22540024Smckusick 	lastinum = 0;
22640024Smckusick 	readcnt = 0;
22740024Smckusick 	inobufsize = blkroundup(&sblock, INOBUFSIZE);
22840024Smckusick 	fullcnt = inobufsize / sizeof(struct dinode);
22940024Smckusick 	readpercg = sblock.fs_ipg / fullcnt;
23040024Smckusick 	partialcnt = sblock.fs_ipg % fullcnt;
23140024Smckusick 	partialsize = partialcnt * sizeof(struct dinode);
23240024Smckusick 	if (partialcnt != 0) {
23340024Smckusick 		readpercg++;
23440024Smckusick 	} else {
23540024Smckusick 		partialcnt = fullcnt;
23640024Smckusick 		partialsize = inobufsize;
23740024Smckusick 	}
23840024Smckusick 	if (inodebuf == NULL &&
23940024Smckusick 	    (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL)
24040024Smckusick 		errexit("Cannot allocate space for inode buffer\n");
24140024Smckusick 	while (nextino < ROOTINO)
24244934Smckusick 		(void)getnextinode(nextino);
24340024Smckusick }
24440024Smckusick 
24540024Smckusick freeinodebuf()
24640024Smckusick {
24740024Smckusick 
24840024Smckusick 	if (inodebuf != NULL)
24940024Smckusick 		free((char *)inodebuf);
25040024Smckusick 	inodebuf = NULL;
25140024Smckusick }
25240024Smckusick 
25340024Smckusick /*
25440024Smckusick  * Routines to maintain information about directory inodes.
25540024Smckusick  * This is built during the first pass and used during the
25640024Smckusick  * second and third passes.
25740024Smckusick  *
25840024Smckusick  * Enter inodes into the cache.
25940024Smckusick  */
26039980Smckusick cacheino(dp, inumber)
26139980Smckusick 	register struct dinode *dp;
26239980Smckusick 	ino_t inumber;
26339980Smckusick {
26439980Smckusick 	register struct inoinfo *inp;
26539980Smckusick 	struct inoinfo **inpp;
26639980Smckusick 	unsigned int blks;
26739980Smckusick 
26839980Smckusick 	blks = howmany(dp->di_size, sblock.fs_bsize);
26939980Smckusick 	if (blks > NDADDR)
27039980Smckusick 		blks = NDADDR + NIADDR;
27139980Smckusick 	inp = (struct inoinfo *)
27239980Smckusick 		malloc(sizeof(*inp) + (blks - 1) * sizeof(daddr_t));
27339980Smckusick 	if (inp == NULL)
27439980Smckusick 		return;
27540024Smckusick 	inpp = &inphead[inumber % numdirs];
27640024Smckusick 	inp->i_nexthash = *inpp;
27739980Smckusick 	*inpp = inp;
27840024Smckusick 	inp->i_parent = (ino_t)0;
27940024Smckusick 	inp->i_dotdot = (ino_t)0;
28039980Smckusick 	inp->i_number = inumber;
28140024Smckusick 	inp->i_isize = dp->di_size;
28239980Smckusick 	inp->i_numblks = blks * sizeof(daddr_t);
28340024Smckusick 	bcopy((char *)&dp->di_db[0], (char *)&inp->i_blks[0],
28444934Smckusick 	    (size_t)inp->i_numblks);
28540024Smckusick 	if (inplast == listmax) {
28640024Smckusick 		listmax += 100;
28740024Smckusick 		inpsort = (struct inoinfo **)realloc((char *)inpsort,
28840024Smckusick 		    (unsigned)listmax * sizeof(struct inoinfo *));
28940024Smckusick 		if (inpsort == NULL)
29040024Smckusick 			errexit("cannot increase directory list");
29140024Smckusick 	}
29240024Smckusick 	inpsort[inplast++] = inp;
29339980Smckusick }
29439980Smckusick 
29540024Smckusick /*
29640024Smckusick  * Look up an inode cache structure.
29740024Smckusick  */
29840024Smckusick struct inoinfo *
29940024Smckusick getinoinfo(inumber)
30039980Smckusick 	ino_t inumber;
30139980Smckusick {
30239980Smckusick 	register struct inoinfo *inp;
30339980Smckusick 
30440024Smckusick 	for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) {
30539980Smckusick 		if (inp->i_number != inumber)
30639980Smckusick 			continue;
30740024Smckusick 		return (inp);
30839980Smckusick 	}
30940024Smckusick 	errexit("cannot find inode %d\n", inumber);
31040024Smckusick 	return ((struct inoinfo *)0);
31139980Smckusick }
31239980Smckusick 
31340024Smckusick /*
31440024Smckusick  * Clean up all the inode cache structure.
31540024Smckusick  */
31639980Smckusick inocleanup()
31739980Smckusick {
31840024Smckusick 	register struct inoinfo **inpp;
31939980Smckusick 
32039980Smckusick 	if (inphead == NULL)
32139980Smckusick 		return;
32240024Smckusick 	for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--)
32340024Smckusick 		free((char *)(*inpp));
32440024Smckusick 	free((char *)inphead);
32540024Smckusick 	free((char *)inpsort);
32640024Smckusick 	inphead = inpsort = NULL;
32739980Smckusick }
32839980Smckusick 
32934225Smckusick inodirty()
33034225Smckusick {
33134225Smckusick 
33234225Smckusick 	dirty(pbp);
33334225Smckusick }
33434225Smckusick 
33539973Smckusick clri(idesc, type, flag)
33616261Smckusick 	register struct inodesc *idesc;
33739973Smckusick 	char *type;
33839973Smckusick 	int flag;
33916261Smckusick {
34039973Smckusick 	register struct dinode *dp;
34116261Smckusick 
34217943Smckusick 	dp = ginode(idesc->id_number);
34339973Smckusick 	if (flag == 1) {
34439973Smckusick 		pwarn("%s %s", type,
34539973Smckusick 		    (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE");
34616261Smckusick 		pinode(idesc->id_number);
34716261Smckusick 	}
34816261Smckusick 	if (preen || reply("CLEAR") == 1) {
34916261Smckusick 		if (preen)
35016261Smckusick 			printf(" (CLEARED)\n");
35116261Smckusick 		n_files--;
35216261Smckusick 		(void)ckinode(dp, idesc);
35339973Smckusick 		clearinode(dp);
35416261Smckusick 		statemap[idesc->id_number] = USTATE;
35516261Smckusick 		inodirty();
35616261Smckusick 	}
35716261Smckusick }
35816261Smckusick 
35917991Smckusick findname(idesc)
36017991Smckusick 	struct inodesc *idesc;
36117991Smckusick {
36239973Smckusick 	register struct direct *dirp = idesc->id_dirp;
36317991Smckusick 
36417991Smckusick 	if (dirp->d_ino != idesc->id_parent)
36517991Smckusick 		return (KEEPON);
36644934Smckusick 	bcopy(dirp->d_name, idesc->id_name, (size_t)dirp->d_namlen + 1);
36730354Smckusick 	return (STOP|FOUND);
36817991Smckusick }
36917991Smckusick 
37016261Smckusick findino(idesc)
37116261Smckusick 	struct inodesc *idesc;
37216261Smckusick {
37339973Smckusick 	register struct direct *dirp = idesc->id_dirp;
37416261Smckusick 
37516261Smckusick 	if (dirp->d_ino == 0)
37616261Smckusick 		return (KEEPON);
37717991Smckusick 	if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
37839973Smckusick 	    dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) {
37917991Smckusick 		idesc->id_parent = dirp->d_ino;
38030354Smckusick 		return (STOP|FOUND);
38116261Smckusick 	}
38216261Smckusick 	return (KEEPON);
38316261Smckusick }
38416261Smckusick 
38516261Smckusick pinode(ino)
38616261Smckusick 	ino_t ino;
38716261Smckusick {
38839973Smckusick 	register struct dinode *dp;
38916261Smckusick 	register char *p;
39018102Smckusick 	struct passwd *pw;
39116261Smckusick 	char *ctime();
39216261Smckusick 
39344934Smckusick 	printf(" I=%lu ", ino);
39439973Smckusick 	if (ino < ROOTINO || ino > maxino)
39516261Smckusick 		return;
39617943Smckusick 	dp = ginode(ino);
39716261Smckusick 	printf(" OWNER=");
39818102Smckusick 	if ((pw = getpwuid((int)dp->di_uid)) != 0)
39918102Smckusick 		printf("%s ", pw->pw_name);
40018102Smckusick 	else
40144934Smckusick 		printf("%u ", (unsigned)dp->di_uid);
40216261Smckusick 	printf("MODE=%o\n", dp->di_mode);
40316261Smckusick 	if (preen)
40416261Smckusick 		printf("%s: ", devname);
40544934Smckusick 	printf("SIZE=%lu ", dp->di_size);
40616261Smckusick 	p = ctime(&dp->di_mtime);
40747579Smckusick 	printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]);
40816261Smckusick }
40916261Smckusick 
41039973Smckusick blkerror(ino, type, blk)
41116261Smckusick 	ino_t ino;
41239973Smckusick 	char *type;
41316261Smckusick 	daddr_t blk;
41416261Smckusick {
41516261Smckusick 
41644934Smckusick 	pfatal("%ld %s I=%lu", blk, type, ino);
41716261Smckusick 	printf("\n");
41817936Smckusick 	switch (statemap[ino]) {
41917936Smckusick 
42017936Smckusick 	case FSTATE:
42117936Smckusick 		statemap[ino] = FCLEAR;
42217936Smckusick 		return;
42317936Smckusick 
42417936Smckusick 	case DSTATE:
42517936Smckusick 		statemap[ino] = DCLEAR;
42617936Smckusick 		return;
42717936Smckusick 
42817936Smckusick 	case FCLEAR:
42917936Smckusick 	case DCLEAR:
43017936Smckusick 		return;
43117936Smckusick 
43217936Smckusick 	default:
43317936Smckusick 		errexit("BAD STATE %d TO BLKERR", statemap[ino]);
43417936Smckusick 		/* NOTREACHED */
43517936Smckusick 	}
43616261Smckusick }
43717955Smckusick 
43817955Smckusick /*
43917955Smckusick  * allocate an unused inode
44017955Smckusick  */
44117955Smckusick ino_t
44217955Smckusick allocino(request, type)
44317955Smckusick 	ino_t request;
44417955Smckusick 	int type;
44517955Smckusick {
44617955Smckusick 	register ino_t ino;
44739973Smckusick 	register struct dinode *dp;
44817955Smckusick 
44917955Smckusick 	if (request == 0)
45017955Smckusick 		request = ROOTINO;
45117955Smckusick 	else if (statemap[request] != USTATE)
45217955Smckusick 		return (0);
45339973Smckusick 	for (ino = request; ino < maxino; ino++)
45417955Smckusick 		if (statemap[ino] == USTATE)
45517955Smckusick 			break;
45639973Smckusick 	if (ino == maxino)
45717955Smckusick 		return (0);
45817955Smckusick 	switch (type & IFMT) {
45917955Smckusick 	case IFDIR:
46017955Smckusick 		statemap[ino] = DSTATE;
46117955Smckusick 		break;
46217955Smckusick 	case IFREG:
46317955Smckusick 	case IFLNK:
46417955Smckusick 		statemap[ino] = FSTATE;
46517955Smckusick 		break;
46617955Smckusick 	default:
46717955Smckusick 		return (0);
46817955Smckusick 	}
46917955Smckusick 	dp = ginode(ino);
47039973Smckusick 	dp->di_db[0] = allocblk((long)1);
47117955Smckusick 	if (dp->di_db[0] == 0) {
47217955Smckusick 		statemap[ino] = USTATE;
47317955Smckusick 		return (0);
47417955Smckusick 	}
47517955Smckusick 	dp->di_mode = type;
47644934Smckusick 	(void)time(&dp->di_atime);
47717955Smckusick 	dp->di_mtime = dp->di_ctime = dp->di_atime;
47817955Smckusick 	dp->di_size = sblock.fs_fsize;
47917955Smckusick 	dp->di_blocks = btodb(sblock.fs_fsize);
48017955Smckusick 	n_files++;
48117955Smckusick 	inodirty();
48217955Smckusick 	return (ino);
48317955Smckusick }
48417955Smckusick 
48517955Smckusick /*
48617955Smckusick  * deallocate an inode
48717955Smckusick  */
48817955Smckusick freeino(ino)
48917955Smckusick 	ino_t ino;
49017955Smckusick {
49117955Smckusick 	struct inodesc idesc;
49217955Smckusick 	extern int pass4check();
49339973Smckusick 	struct dinode *dp;
49417955Smckusick 
49517955Smckusick 	bzero((char *)&idesc, sizeof(struct inodesc));
49617955Smckusick 	idesc.id_type = ADDR;
49717955Smckusick 	idesc.id_func = pass4check;
49817955Smckusick 	idesc.id_number = ino;
49917955Smckusick 	dp = ginode(ino);
50017955Smckusick 	(void)ckinode(dp, &idesc);
50139973Smckusick 	clearinode(dp);
50217955Smckusick 	inodirty();
50317955Smckusick 	statemap[ino] = USTATE;
50417955Smckusick 	n_files--;
50517955Smckusick }
506