inode.c revision 8871
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1980, 1986, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 357585Sbdestatic const char sccsid[] = "@(#)inode.c 8.5 (Berkeley) 2/8/95"; 361558Srgrimes#endif /* not lint */ 371558Srgrimes 381558Srgrimes#include <sys/param.h> 391558Srgrimes#include <sys/time.h> 401558Srgrimes#include <ufs/ufs/dinode.h> 411558Srgrimes#include <ufs/ufs/dir.h> 421558Srgrimes#include <ufs/ffs/fs.h> 431558Srgrimes#include <pwd.h> 447585Sbde#include <stdio.h> 451558Srgrimes#include <stdlib.h> 461558Srgrimes#include <string.h> 471558Srgrimes#include "fsck.h" 481558Srgrimes 491558Srgrimesstatic ino_t startinum; 501558Srgrimes 517585Sbdestatic int iblock __P((struct inodesc *idesc, long ilevel, quad_t isize)); 527585Sbde 537585Sbdeint 541558Srgrimesckinode(dp, idesc) 551558Srgrimes struct dinode *dp; 561558Srgrimes register struct inodesc *idesc; 571558Srgrimes{ 581558Srgrimes register daddr_t *ap; 597586Sbde int ret; 607586Sbde long n, ndb, offset; 611558Srgrimes struct dinode dino; 621558Srgrimes quad_t remsize, sizepb; 631558Srgrimes mode_t mode; 641558Srgrimes 651558Srgrimes if (idesc->id_fix != IGNORE) 661558Srgrimes idesc->id_fix = DONTKNOW; 671558Srgrimes idesc->id_entryno = 0; 681558Srgrimes idesc->id_filesize = dp->di_size; 691558Srgrimes mode = dp->di_mode & IFMT; 701558Srgrimes if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && 711820Sdg (dp->di_size < sblock.fs_maxsymlinklen || dp->di_blocks == 0))) 721558Srgrimes return (KEEPON); 731558Srgrimes dino = *dp; 741558Srgrimes ndb = howmany(dino.di_size, sblock.fs_bsize); 751558Srgrimes for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { 761558Srgrimes if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0) 771558Srgrimes idesc->id_numfrags = 781558Srgrimes numfrags(&sblock, fragroundup(&sblock, offset)); 791558Srgrimes else 801558Srgrimes idesc->id_numfrags = sblock.fs_frag; 811558Srgrimes if (*ap == 0) 821558Srgrimes continue; 831558Srgrimes idesc->id_blkno = *ap; 841558Srgrimes if (idesc->id_type == ADDR) 851558Srgrimes ret = (*idesc->id_func)(idesc); 861558Srgrimes else 871558Srgrimes ret = dirscan(idesc); 881558Srgrimes if (ret & STOP) 891558Srgrimes return (ret); 901558Srgrimes } 911558Srgrimes idesc->id_numfrags = sblock.fs_frag; 921558Srgrimes remsize = dino.di_size - sblock.fs_bsize * NDADDR; 931558Srgrimes sizepb = sblock.fs_bsize; 941558Srgrimes for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) { 951558Srgrimes if (*ap) { 961558Srgrimes idesc->id_blkno = *ap; 971558Srgrimes ret = iblock(idesc, n, remsize); 981558Srgrimes if (ret & STOP) 991558Srgrimes return (ret); 1001558Srgrimes } 1011558Srgrimes sizepb *= NINDIR(&sblock); 1021558Srgrimes remsize -= sizepb; 1031558Srgrimes } 1041558Srgrimes return (KEEPON); 1051558Srgrimes} 1061558Srgrimes 1077585Sbdestatic int 1081558Srgrimesiblock(idesc, ilevel, isize) 1091558Srgrimes struct inodesc *idesc; 1101558Srgrimes long ilevel; 1111558Srgrimes quad_t isize; 1121558Srgrimes{ 1131558Srgrimes register daddr_t *ap; 1141558Srgrimes register daddr_t *aplim; 1151558Srgrimes register struct bufarea *bp; 1161558Srgrimes int i, n, (*func)(), nif; 1171558Srgrimes quad_t sizepb; 1181558Srgrimes char buf[BUFSIZ]; 1191558Srgrimes 1201558Srgrimes if (idesc->id_type == ADDR) { 1211558Srgrimes func = idesc->id_func; 1221558Srgrimes if (((n = (*func)(idesc)) & KEEPON) == 0) 1231558Srgrimes return (n); 1241558Srgrimes } else 1251558Srgrimes func = dirscan; 1261558Srgrimes if (chkrange(idesc->id_blkno, idesc->id_numfrags)) 1271558Srgrimes return (SKIP); 1281558Srgrimes bp = getdatablk(idesc->id_blkno, sblock.fs_bsize); 1291558Srgrimes ilevel--; 1301558Srgrimes for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) 1311558Srgrimes sizepb *= NINDIR(&sblock); 1321558Srgrimes nif = howmany(isize , sizepb); 1331558Srgrimes if (nif > NINDIR(&sblock)) 1341558Srgrimes nif = NINDIR(&sblock); 1351558Srgrimes if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { 1361558Srgrimes aplim = &bp->b_un.b_indir[NINDIR(&sblock)]; 1371558Srgrimes for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) { 1381558Srgrimes if (*ap == 0) 1391558Srgrimes continue; 1401558Srgrimes (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu", 1411558Srgrimes idesc->id_number); 1421558Srgrimes if (dofix(idesc, buf)) { 1431558Srgrimes *ap = 0; 1441558Srgrimes dirty(bp); 1451558Srgrimes } 1461558Srgrimes } 1471558Srgrimes flush(fswritefd, bp); 1481558Srgrimes } 1491558Srgrimes aplim = &bp->b_un.b_indir[nif]; 1501558Srgrimes for (ap = bp->b_un.b_indir; ap < aplim; ap++) { 1511558Srgrimes if (*ap) { 1521558Srgrimes idesc->id_blkno = *ap; 1531558Srgrimes if (ilevel == 0) 1541558Srgrimes n = (*func)(idesc); 1551558Srgrimes else 1561558Srgrimes n = iblock(idesc, ilevel, isize); 1571558Srgrimes if (n & STOP) { 1581558Srgrimes bp->b_flags &= ~B_INUSE; 1591558Srgrimes return (n); 1601558Srgrimes } 1611558Srgrimes } 1621558Srgrimes isize -= sizepb; 1631558Srgrimes } 1641558Srgrimes bp->b_flags &= ~B_INUSE; 1651558Srgrimes return (KEEPON); 1661558Srgrimes} 1671558Srgrimes 1681558Srgrimes/* 1691558Srgrimes * Check that a block in a legal block number. 1701558Srgrimes * Return 0 if in range, 1 if out of range. 1711558Srgrimes */ 1727585Sbdeint 1731558Srgrimeschkrange(blk, cnt) 1741558Srgrimes daddr_t blk; 1751558Srgrimes int cnt; 1761558Srgrimes{ 1771558Srgrimes register int c; 1781558Srgrimes 1791558Srgrimes if ((unsigned)(blk + cnt) > maxfsblock) 1801558Srgrimes return (1); 1811558Srgrimes c = dtog(&sblock, blk); 1821558Srgrimes if (blk < cgdmin(&sblock, c)) { 1831558Srgrimes if ((blk + cnt) > cgsblock(&sblock, c)) { 1841558Srgrimes if (debug) { 1851558Srgrimes printf("blk %ld < cgdmin %ld;", 1861558Srgrimes blk, cgdmin(&sblock, c)); 1871558Srgrimes printf(" blk + cnt %ld > cgsbase %ld\n", 1881558Srgrimes blk + cnt, cgsblock(&sblock, c)); 1891558Srgrimes } 1901558Srgrimes return (1); 1911558Srgrimes } 1921558Srgrimes } else { 1931558Srgrimes if ((blk + cnt) > cgbase(&sblock, c+1)) { 1941558Srgrimes if (debug) { 1951558Srgrimes printf("blk %ld >= cgdmin %ld;", 1961558Srgrimes blk, cgdmin(&sblock, c)); 1971558Srgrimes printf(" blk + cnt %ld > sblock.fs_fpg %ld\n", 1981558Srgrimes blk+cnt, sblock.fs_fpg); 1991558Srgrimes } 2001558Srgrimes return (1); 2011558Srgrimes } 2021558Srgrimes } 2031558Srgrimes return (0); 2041558Srgrimes} 2051558Srgrimes 2061558Srgrimes/* 2071558Srgrimes * General purpose interface for reading inodes. 2081558Srgrimes */ 2091558Srgrimesstruct dinode * 2101558Srgrimesginode(inumber) 2111558Srgrimes ino_t inumber; 2121558Srgrimes{ 2131558Srgrimes daddr_t iblk; 2141558Srgrimes 2151558Srgrimes if (inumber < ROOTINO || inumber > maxino) 2161558Srgrimes errexit("bad inode number %d to ginode\n", inumber); 2171558Srgrimes if (startinum == 0 || 2181558Srgrimes inumber < startinum || inumber >= startinum + INOPB(&sblock)) { 2191558Srgrimes iblk = ino_to_fsba(&sblock, inumber); 2201558Srgrimes if (pbp != 0) 2211558Srgrimes pbp->b_flags &= ~B_INUSE; 2221558Srgrimes pbp = getdatablk(iblk, sblock.fs_bsize); 2231558Srgrimes startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); 2241558Srgrimes } 2251558Srgrimes return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]); 2261558Srgrimes} 2271558Srgrimes 2281558Srgrimes/* 2291558Srgrimes * Special purpose version of ginode used to optimize first pass 2301558Srgrimes * over all the inodes in numerical order. 2311558Srgrimes */ 2321558Srgrimesino_t nextino, lastinum; 2331558Srgrimeslong readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; 2341558Srgrimesstruct dinode *inodebuf; 2351558Srgrimes 2361558Srgrimesstruct dinode * 2371558Srgrimesgetnextinode(inumber) 2381558Srgrimes ino_t inumber; 2391558Srgrimes{ 2401558Srgrimes long size; 2411558Srgrimes daddr_t dblk; 2421558Srgrimes static struct dinode *dp; 2431558Srgrimes 2441558Srgrimes if (inumber != nextino++ || inumber > maxino) 2451558Srgrimes errexit("bad inode number %d to nextinode\n", inumber); 2461558Srgrimes if (inumber >= lastinum) { 2471558Srgrimes readcnt++; 2481558Srgrimes dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum)); 2491558Srgrimes if (readcnt % readpercg == 0) { 2501558Srgrimes size = partialsize; 2511558Srgrimes lastinum += partialcnt; 2521558Srgrimes } else { 2531558Srgrimes size = inobufsize; 2541558Srgrimes lastinum += fullcnt; 2551558Srgrimes } 2561558Srgrimes (void)bread(fsreadfd, (char *)inodebuf, dblk, size); /* ??? */ 2571558Srgrimes dp = inodebuf; 2581558Srgrimes } 2591558Srgrimes return (dp++); 2601558Srgrimes} 2611558Srgrimes 2627585Sbdevoid 2631558Srgrimesresetinodebuf() 2641558Srgrimes{ 2651558Srgrimes 2661558Srgrimes startinum = 0; 2671558Srgrimes nextino = 0; 2681558Srgrimes lastinum = 0; 2691558Srgrimes readcnt = 0; 2701558Srgrimes inobufsize = blkroundup(&sblock, INOBUFSIZE); 2711558Srgrimes fullcnt = inobufsize / sizeof(struct dinode); 2721558Srgrimes readpercg = sblock.fs_ipg / fullcnt; 2731558Srgrimes partialcnt = sblock.fs_ipg % fullcnt; 2741558Srgrimes partialsize = partialcnt * sizeof(struct dinode); 2751558Srgrimes if (partialcnt != 0) { 2761558Srgrimes readpercg++; 2771558Srgrimes } else { 2781558Srgrimes partialcnt = fullcnt; 2791558Srgrimes partialsize = inobufsize; 2801558Srgrimes } 2811558Srgrimes if (inodebuf == NULL && 2821558Srgrimes (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL) 2831558Srgrimes errexit("Cannot allocate space for inode buffer\n"); 2841558Srgrimes while (nextino < ROOTINO) 2851558Srgrimes (void)getnextinode(nextino); 2861558Srgrimes} 2871558Srgrimes 2887585Sbdevoid 2891558Srgrimesfreeinodebuf() 2901558Srgrimes{ 2911558Srgrimes 2921558Srgrimes if (inodebuf != NULL) 2931558Srgrimes free((char *)inodebuf); 2941558Srgrimes inodebuf = NULL; 2951558Srgrimes} 2961558Srgrimes 2971558Srgrimes/* 2981558Srgrimes * Routines to maintain information about directory inodes. 2991558Srgrimes * This is built during the first pass and used during the 3001558Srgrimes * second and third passes. 3011558Srgrimes * 3021558Srgrimes * Enter inodes into the cache. 3031558Srgrimes */ 3047585Sbdevoid 3051558Srgrimescacheino(dp, inumber) 3061558Srgrimes register struct dinode *dp; 3071558Srgrimes ino_t inumber; 3081558Srgrimes{ 3091558Srgrimes register struct inoinfo *inp; 3101558Srgrimes struct inoinfo **inpp; 3111558Srgrimes unsigned int blks; 3121558Srgrimes 3131558Srgrimes blks = howmany(dp->di_size, sblock.fs_bsize); 3141558Srgrimes if (blks > NDADDR) 3151558Srgrimes blks = NDADDR + NIADDR; 3161558Srgrimes inp = (struct inoinfo *) 3171558Srgrimes malloc(sizeof(*inp) + (blks - 1) * sizeof(daddr_t)); 3181558Srgrimes if (inp == NULL) 3191558Srgrimes return; 3201558Srgrimes inpp = &inphead[inumber % numdirs]; 3211558Srgrimes inp->i_nexthash = *inpp; 3221558Srgrimes *inpp = inp; 3236404Sdg if (inumber == ROOTINO) 3246404Sdg inp->i_parent = ROOTINO; 3256404Sdg else 3266404Sdg inp->i_parent = (ino_t)0; 3271558Srgrimes inp->i_dotdot = (ino_t)0; 3281558Srgrimes inp->i_number = inumber; 3291558Srgrimes inp->i_isize = dp->di_size; 3301558Srgrimes inp->i_numblks = blks * sizeof(daddr_t); 3311558Srgrimes bcopy((char *)&dp->di_db[0], (char *)&inp->i_blks[0], 3321558Srgrimes (size_t)inp->i_numblks); 3331558Srgrimes if (inplast == listmax) { 3341558Srgrimes listmax += 100; 3351558Srgrimes inpsort = (struct inoinfo **)realloc((char *)inpsort, 3361558Srgrimes (unsigned)listmax * sizeof(struct inoinfo *)); 3371558Srgrimes if (inpsort == NULL) 3381558Srgrimes errexit("cannot increase directory list"); 3391558Srgrimes } 3401558Srgrimes inpsort[inplast++] = inp; 3411558Srgrimes} 3421558Srgrimes 3431558Srgrimes/* 3441558Srgrimes * Look up an inode cache structure. 3451558Srgrimes */ 3461558Srgrimesstruct inoinfo * 3471558Srgrimesgetinoinfo(inumber) 3481558Srgrimes ino_t inumber; 3491558Srgrimes{ 3501558Srgrimes register struct inoinfo *inp; 3511558Srgrimes 3521558Srgrimes for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) { 3531558Srgrimes if (inp->i_number != inumber) 3541558Srgrimes continue; 3551558Srgrimes return (inp); 3561558Srgrimes } 3571558Srgrimes errexit("cannot find inode %d\n", inumber); 3581558Srgrimes return ((struct inoinfo *)0); 3591558Srgrimes} 3601558Srgrimes 3611558Srgrimes/* 3621558Srgrimes * Clean up all the inode cache structure. 3631558Srgrimes */ 3647585Sbdevoid 3651558Srgrimesinocleanup() 3661558Srgrimes{ 3671558Srgrimes register struct inoinfo **inpp; 3681558Srgrimes 3691558Srgrimes if (inphead == NULL) 3701558Srgrimes return; 3711558Srgrimes for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) 3721558Srgrimes free((char *)(*inpp)); 3731558Srgrimes free((char *)inphead); 3741558Srgrimes free((char *)inpsort); 3751558Srgrimes inphead = inpsort = NULL; 3761558Srgrimes} 3778871Srgrimes 3787585Sbdevoid 3791558Srgrimesinodirty() 3801558Srgrimes{ 3811558Srgrimes dirty(pbp); 3821558Srgrimes} 3831558Srgrimes 3847585Sbdevoid 3851558Srgrimesclri(idesc, type, flag) 3861558Srgrimes register struct inodesc *idesc; 3871558Srgrimes char *type; 3881558Srgrimes int flag; 3891558Srgrimes{ 3901558Srgrimes register struct dinode *dp; 3911558Srgrimes 3921558Srgrimes dp = ginode(idesc->id_number); 3931558Srgrimes if (flag == 1) { 3941558Srgrimes pwarn("%s %s", type, 3951558Srgrimes (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"); 3961558Srgrimes pinode(idesc->id_number); 3971558Srgrimes } 3981558Srgrimes if (preen || reply("CLEAR") == 1) { 3991558Srgrimes if (preen) 4001558Srgrimes printf(" (CLEARED)\n"); 4011558Srgrimes n_files--; 4021558Srgrimes (void)ckinode(dp, idesc); 4031558Srgrimes clearinode(dp); 4041558Srgrimes statemap[idesc->id_number] = USTATE; 4051558Srgrimes inodirty(); 4061558Srgrimes } 4071558Srgrimes} 4081558Srgrimes 4097585Sbdeint 4101558Srgrimesfindname(idesc) 4111558Srgrimes struct inodesc *idesc; 4121558Srgrimes{ 4131558Srgrimes register struct direct *dirp = idesc->id_dirp; 4141558Srgrimes 4151558Srgrimes if (dirp->d_ino != idesc->id_parent) 4161558Srgrimes return (KEEPON); 4171558Srgrimes bcopy(dirp->d_name, idesc->id_name, (size_t)dirp->d_namlen + 1); 4181558Srgrimes return (STOP|FOUND); 4191558Srgrimes} 4201558Srgrimes 4217585Sbdeint 4221558Srgrimesfindino(idesc) 4231558Srgrimes struct inodesc *idesc; 4241558Srgrimes{ 4251558Srgrimes register struct direct *dirp = idesc->id_dirp; 4261558Srgrimes 4271558Srgrimes if (dirp->d_ino == 0) 4281558Srgrimes return (KEEPON); 4291558Srgrimes if (strcmp(dirp->d_name, idesc->id_name) == 0 && 4301558Srgrimes dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) { 4311558Srgrimes idesc->id_parent = dirp->d_ino; 4321558Srgrimes return (STOP|FOUND); 4331558Srgrimes } 4341558Srgrimes return (KEEPON); 4351558Srgrimes} 4361558Srgrimes 4377585Sbdevoid 4381558Srgrimespinode(ino) 4391558Srgrimes ino_t ino; 4401558Srgrimes{ 4411558Srgrimes register struct dinode *dp; 4421558Srgrimes register char *p; 4431558Srgrimes struct passwd *pw; 4441558Srgrimes char *ctime(); 4451558Srgrimes 4461558Srgrimes printf(" I=%lu ", ino); 4471558Srgrimes if (ino < ROOTINO || ino > maxino) 4481558Srgrimes return; 4491558Srgrimes dp = ginode(ino); 4501558Srgrimes printf(" OWNER="); 4511558Srgrimes if ((pw = getpwuid((int)dp->di_uid)) != 0) 4521558Srgrimes printf("%s ", pw->pw_name); 4531558Srgrimes else 4541558Srgrimes printf("%u ", (unsigned)dp->di_uid); 4551558Srgrimes printf("MODE=%o\n", dp->di_mode); 4561558Srgrimes if (preen) 4571558Srgrimes printf("%s: ", cdevname); 4581558Srgrimes printf("SIZE=%qu ", dp->di_size); 4591558Srgrimes p = ctime(&dp->di_mtime.ts_sec); 4601558Srgrimes printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); 4611558Srgrimes} 4621558Srgrimes 4637585Sbdevoid 4641558Srgrimesblkerror(ino, type, blk) 4651558Srgrimes ino_t ino; 4661558Srgrimes char *type; 4671558Srgrimes daddr_t blk; 4681558Srgrimes{ 4691558Srgrimes 4701558Srgrimes pfatal("%ld %s I=%lu", blk, type, ino); 4711558Srgrimes printf("\n"); 4721558Srgrimes switch (statemap[ino]) { 4731558Srgrimes 4741558Srgrimes case FSTATE: 4751558Srgrimes statemap[ino] = FCLEAR; 4761558Srgrimes return; 4771558Srgrimes 4781558Srgrimes case DSTATE: 4791558Srgrimes statemap[ino] = DCLEAR; 4801558Srgrimes return; 4811558Srgrimes 4821558Srgrimes case FCLEAR: 4831558Srgrimes case DCLEAR: 4841558Srgrimes return; 4851558Srgrimes 4861558Srgrimes default: 4871558Srgrimes errexit("BAD STATE %d TO BLKERR", statemap[ino]); 4881558Srgrimes /* NOTREACHED */ 4891558Srgrimes } 4901558Srgrimes} 4911558Srgrimes 4921558Srgrimes/* 4931558Srgrimes * allocate an unused inode 4941558Srgrimes */ 4951558Srgrimesino_t 4961558Srgrimesallocino(request, type) 4971558Srgrimes ino_t request; 4981558Srgrimes int type; 4991558Srgrimes{ 5001558Srgrimes register ino_t ino; 5011558Srgrimes register struct dinode *dp; 5021558Srgrimes 5031558Srgrimes if (request == 0) 5041558Srgrimes request = ROOTINO; 5051558Srgrimes else if (statemap[request] != USTATE) 5061558Srgrimes return (0); 5071558Srgrimes for (ino = request; ino < maxino; ino++) 5081558Srgrimes if (statemap[ino] == USTATE) 5091558Srgrimes break; 5101558Srgrimes if (ino == maxino) 5111558Srgrimes return (0); 5121558Srgrimes switch (type & IFMT) { 5131558Srgrimes case IFDIR: 5141558Srgrimes statemap[ino] = DSTATE; 5151558Srgrimes break; 5161558Srgrimes case IFREG: 5171558Srgrimes case IFLNK: 5181558Srgrimes statemap[ino] = FSTATE; 5191558Srgrimes break; 5201558Srgrimes default: 5211558Srgrimes return (0); 5221558Srgrimes } 5231558Srgrimes dp = ginode(ino); 5241558Srgrimes dp->di_db[0] = allocblk((long)1); 5251558Srgrimes if (dp->di_db[0] == 0) { 5261558Srgrimes statemap[ino] = USTATE; 5271558Srgrimes return (0); 5281558Srgrimes } 5291558Srgrimes dp->di_mode = type; 5301558Srgrimes (void)time(&dp->di_atime.ts_sec); 5311558Srgrimes dp->di_mtime = dp->di_ctime = dp->di_atime; 5321558Srgrimes dp->di_size = sblock.fs_fsize; 5331558Srgrimes dp->di_blocks = btodb(sblock.fs_fsize); 5341558Srgrimes n_files++; 5351558Srgrimes inodirty(); 5361558Srgrimes if (newinofmt) 5371558Srgrimes typemap[ino] = IFTODT(type); 5381558Srgrimes return (ino); 5391558Srgrimes} 5401558Srgrimes 5411558Srgrimes/* 5421558Srgrimes * deallocate an inode 5431558Srgrimes */ 5447585Sbdevoid 5451558Srgrimesfreeino(ino) 5461558Srgrimes ino_t ino; 5471558Srgrimes{ 5481558Srgrimes struct inodesc idesc; 5491558Srgrimes struct dinode *dp; 5501558Srgrimes 5511558Srgrimes bzero((char *)&idesc, sizeof(struct inodesc)); 5521558Srgrimes idesc.id_type = ADDR; 5531558Srgrimes idesc.id_func = pass4check; 5541558Srgrimes idesc.id_number = ino; 5551558Srgrimes dp = ginode(ino); 5561558Srgrimes (void)ckinode(dp, &idesc); 5571558Srgrimes clearinode(dp); 5581558Srgrimes inodirty(); 5591558Srgrimes statemap[ino] = USTATE; 5601558Srgrimes n_files--; 5611558Srgrimes} 562