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