1*7492Skre /* lfs_inode.c 4.18 82/07/22 */ 224Sbill 324Sbill #include "../h/param.h" 424Sbill #include "../h/systm.h" 524Sbill #include "../h/mount.h" 624Sbill #include "../h/dir.h" 724Sbill #include "../h/user.h" 824Sbill #include "../h/inode.h" 96569Smckusic #include "../h/fs.h" 1024Sbill #include "../h/conf.h" 1124Sbill #include "../h/buf.h" 1224Sbill #include "../h/inline.h" 1324Sbill 1424Sbill #define INOHSZ 63 157334Skre #if ((INOHSZ&(INOHSZ-1)) == 0) 167334Skre #define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1)) 177334Skre #else 1824Sbill #define INOHASH(dev,ino) (((dev)+(ino))%INOHSZ) 197334Skre #endif 2024Sbill 217334Skre union ihead { /* inode LRU cache, Chris Maltby */ 227334Skre union ihead *ih_head[2]; 237334Skre struct inode *ih_chain[2]; 247334Skre } ihead[INOHSZ]; 257334Skre 267334Skre struct inode *ifreeh, **ifreet; 277334Skre 2824Sbill /* 2924Sbill * Initialize hash links for inodes 3024Sbill * and build inode free list. 3124Sbill */ 3224Sbill ihinit() 3324Sbill { 3424Sbill register int i; 352737Swnj register struct inode *ip = inode; 367334Skre register union ihead *ih = ihead; 3724Sbill 387334Skre for (i = INOHSZ; --i >= 0; ih++) { 397334Skre ih->ih_head[0] = ih; 407334Skre ih->ih_head[1] = ih; 417334Skre } 427334Skre ifreeh = ip; 437334Skre ifreet = &ip->i_freef; 447334Skre ip->i_freeb = &ifreeh; 457334Skre ip->i_forw = ip; 467334Skre ip->i_back = ip; 477334Skre for (i = ninode; --i > 0; ) { 487334Skre ++ip; 497334Skre ip->i_forw = ip; 507334Skre ip->i_back = ip; 517334Skre *ifreet = ip; 527334Skre ip->i_freeb = ifreet; 537334Skre ifreet = &ip->i_freef; 547334Skre } 557334Skre ip->i_freef = NULL; 5624Sbill } 5724Sbill 587334Skre #ifdef notdef 5924Sbill /* 607334Skre * Find an inode if it is incore. 617334Skre * This is the equivalent, for inodes, 627334Skre * of ``incore'' in bio.c or ``pfind'' in subr.c. 637334Skre */ 647334Skre struct inode * 657334Skre ifind(dev, ino) 667334Skre dev_t dev; 677334Skre ino_t ino; 687334Skre { 697334Skre register struct inode *ip; 707334Skre register union ihead *ih; 717334Skre 727334Skre ih = &ihead[INOHASH(dev, ino)]; 737334Skre for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) 747334Skre if (ino==ip->i_number && dev==ip->i_dev) 757334Skre return (ip); 767334Skre return ((struct inode *)0); 777334Skre } 787334Skre #endif notdef 797334Skre 807334Skre /* 8124Sbill * Look up an inode by device,inumber. 8224Sbill * If it is in core (in the inode structure), 8324Sbill * honor the locking protocol. 8424Sbill * If it is not in core, read it in from the 8524Sbill * specified device. 8624Sbill * If the inode is mounted on, perform 8724Sbill * the indicated indirection. 8824Sbill * In all cases, a pointer to a locked 8924Sbill * inode structure is returned. 9024Sbill * 9124Sbill * panic: no imt -- if the mounted file 9224Sbill * system is not in the mount table. 9324Sbill * "cannot happen" 9424Sbill */ 9524Sbill struct inode * 966569Smckusic iget(dev, fs, ino) 974818Swnj dev_t dev; 986569Smckusic register struct fs *fs; 994818Swnj ino_t ino; 10024Sbill { 1017335Skre register struct inode *ip; 1027335Skre register union ihead *ih; 10324Sbill register struct mount *mp; 10424Sbill register struct buf *bp; 10524Sbill register struct dinode *dp; 1067334Skre register struct inode *iq; 10724Sbill 10824Sbill loop: 1096569Smckusic if (getfs(dev) != fs) 1106569Smckusic panic("iget: bad fs"); 1117334Skre ih = &ihead[INOHASH(dev, ino)]; 1127334Skre for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) 1134818Swnj if (ino == ip->i_number && dev == ip->i_dev) { 1144818Swnj if ((ip->i_flag&ILOCK) != 0) { 11524Sbill ip->i_flag |= IWANT; 11624Sbill sleep((caddr_t)ip, PINOD); 11724Sbill goto loop; 11824Sbill } 1194818Swnj if ((ip->i_flag&IMOUNT) != 0) { 1206569Smckusic for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 1217334Skre if(mp->m_inodp == ip) { 1227334Skre dev = mp->m_dev; 1237334Skre fs = mp->m_bufp->b_un.b_fs; 1247334Skre ino = ROOTINO; 1257334Skre goto loop; 1267334Skre } 12724Sbill panic("no imt"); 12824Sbill } 1297334Skre if (ip->i_count == 0) { /* ino on free list */ 1307334Skre if (iq = ip->i_freef) 1317334Skre iq->i_freeb = ip->i_freeb; 1327334Skre else 1337334Skre ifreet = ip->i_freeb; 1347334Skre *ip->i_freeb = iq; 1357334Skre ip->i_freef = NULL; 1367334Skre ip->i_freeb = NULL; 1377334Skre } 13824Sbill ip->i_count++; 13924Sbill ip->i_flag |= ILOCK; 14024Sbill return(ip); 14124Sbill } 1427334Skre 1437334Skre if ((ip = ifreeh) == NULL) { 1442933Swnj tablefull("inode"); 14524Sbill u.u_error = ENFILE; 14624Sbill return(NULL); 14724Sbill } 1487334Skre if (iq = ip->i_freef) 1497334Skre iq->i_freeb = &ifreeh; 1507334Skre ifreeh = iq; 1517334Skre ip->i_freef = NULL; 1527334Skre ip->i_freeb = NULL; 1537334Skre /* 1547334Skre * Now to take inode off the hash chain it was on 1557334Skre * (initially, or after an iflush, it is on a "hash chain" 1567334Skre * consisting entirely of itself, and pointed to by no-one, 1577334Skre * but that doesn't matter), and put it on the chain for 1587334Skre * its new (ino, dev) pair 1597334Skre */ 1607335Skre remque(ip); 1617335Skre insque(ip, ih); 162*7492Skre #ifdef QUOTA 163*7492Skre dqrele(ip->i_dquot); 164*7492Skre #endif 16524Sbill ip->i_dev = dev; 1666569Smckusic ip->i_fs = fs; 16724Sbill ip->i_number = ino; 16824Sbill ip->i_flag = ILOCK; 16924Sbill ip->i_count++; 1706569Smckusic ip->i_lastr = 0; 1716569Smckusic bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize); 17224Sbill /* 17324Sbill * Check I/O errors 17424Sbill */ 1754818Swnj if ((bp->b_flags&B_ERROR) != 0) { 17624Sbill brelse(bp); 1777334Skre /* 1787334Skre * the inode doesn't contain anything useful, so it would 1797334Skre * be misleading to leave it on its hash chain. 1807334Skre * 'iput' will take care of putting it back on the free list. 1817334Skre */ 1827335Skre remque(ip); 1837334Skre ip->i_forw = ip; 1847334Skre ip->i_back = ip; 1857334Skre /* 1867334Skre * we also loose its inumber, just in case (as iput 1877334Skre * doesn't do that any more) - but as it isn't on its 1887334Skre * hash chain, I doubt if this is really necessary .. kre 1897334Skre * (probably the two methods are interchangable) 1907334Skre */ 1917334Skre ip->i_number = 0; 192*7492Skre #ifdef QUOTA 193*7492Skre ip->i_dquot = NODQUOT; 194*7492Skre #endif 19524Sbill iput(ip); 19624Sbill return(NULL); 19724Sbill } 19824Sbill dp = bp->b_un.b_dino; 1996569Smckusic dp += itoo(fs, ino); 2006569Smckusic ip->i_ic = dp->di_ic; 20124Sbill brelse(bp); 202*7492Skre #ifdef QUOTA 203*7492Skre if (ip->i_mode == 0) 204*7492Skre ip->i_dquot = NODQUOT; 205*7492Skre else 206*7492Skre ip->i_dquot = inoquota(ip); 207*7492Skre #endif 2086569Smckusic return (ip); 20924Sbill } 21024Sbill 21124Sbill /* 21224Sbill * Decrement reference count of 21324Sbill * an inode structure. 21424Sbill * On the last reference, 21524Sbill * write the inode out and if necessary, 21624Sbill * truncate and deallocate the file. 21724Sbill */ 21824Sbill iput(ip) 2194818Swnj register struct inode *ip; 22024Sbill { 2217118Smckusick 2227118Smckusick if ((ip->i_flag & ILOCK) == 0) 2237118Smckusick panic("iput"); 2247118Smckusick iunlock(ip); 2257118Smckusick irele(ip); 2267118Smckusick } 2277118Smckusick 2287118Smckusick irele(ip) 2297118Smckusick register struct inode *ip; 2307118Smckusick { 23124Sbill register int i, x; 23224Sbill register struct inode *jp; 2336569Smckusic int mode; 23424Sbill 2354818Swnj if (ip->i_count == 1) { 23624Sbill ip->i_flag |= ILOCK; 2374818Swnj if (ip->i_nlink <= 0) { 23824Sbill itrunc(ip); 2396569Smckusic mode = ip->i_mode; 24024Sbill ip->i_mode = 0; 2417351Skre ip->i_rdev = 0; 24224Sbill ip->i_flag |= IUPD|ICHG; 2436569Smckusic ifree(ip, ip->i_number, mode); 244*7492Skre #ifdef QUOTA 245*7492Skre chkiq(ip->i_dev, ip, ip->i_uid, 0); 246*7492Skre dqrele(ip->i_dquot); 247*7492Skre ip->i_dquot = NODQUOT; 248*7492Skre #endif 24924Sbill } 2501203Sbill IUPDAT(ip, &time, &time, 0); 2517118Smckusick iunlock(ip); 2527334Skre ip->i_flag = 0; 2537334Skre /* 2547334Skre * Put the inode on the end of the free list. 2557334Skre * Possibly in some cases it would be better to 2567334Skre * put the inode at the head of the free list, 2577334Skre * (eg: where i_mode == 0 || i_number == 0) 2587334Skre * but I will think about that later .. kre 2597334Skre * (i_number is rarely 0 - only after an i/o error in iget, 2607334Skre * where i_mode == 0, the inode will probably be wanted 2617334Skre * again soon for an ialloc, so possibly we should keep it) 2627334Skre */ 2637334Skre if (ifreeh) { 2647334Skre *ifreet = ip; 2657334Skre ip->i_freeb = ifreet; 26624Sbill } else { 2677334Skre ifreeh = ip; 2687334Skre ip->i_freeb = &ifreeh; 26924Sbill } 2707334Skre ip->i_freef = NULL; 2717334Skre ifreet = &ip->i_freef; 2727118Smckusick } 27324Sbill ip->i_count--; 27424Sbill } 27524Sbill 27624Sbill /* 27724Sbill * Check accessed and update flags on 27824Sbill * an inode structure. 27924Sbill * If any is on, update the inode 28024Sbill * with the current time. 2811203Sbill * If waitfor is given, then must insure 2821203Sbill * i/o order so wait for write to complete. 28324Sbill */ 2841203Sbill iupdat(ip, ta, tm, waitfor) 2854818Swnj register struct inode *ip; 2864818Swnj time_t *ta, *tm; 2874818Swnj int waitfor; 28824Sbill { 28924Sbill register struct buf *bp; 29024Sbill struct dinode *dp; 2916569Smckusic register struct fs *fp; 29224Sbill 2936569Smckusic fp = ip->i_fs; 2946569Smckusic if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) { 2956569Smckusic if (fp->fs_ronly) 29624Sbill return; 2976569Smckusic bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)), 2986569Smckusic fp->fs_bsize); 29924Sbill if (bp->b_flags & B_ERROR) { 30024Sbill brelse(bp); 30124Sbill return; 30224Sbill } 3034818Swnj if (ip->i_flag&IACC) 3046569Smckusic ip->i_atime = *ta; 3054818Swnj if (ip->i_flag&IUPD) 3066569Smckusic ip->i_mtime = *tm; 3074818Swnj if (ip->i_flag&ICHG) 3086569Smckusic ip->i_ctime = time; 30924Sbill ip->i_flag &= ~(IUPD|IACC|ICHG); 3107343Skre dp = bp->b_un.b_dino + itoo(fp, ip->i_number); 3117343Skre dp->di_ic = ip->i_ic; 3121203Sbill if (waitfor) 3131203Sbill bwrite(bp); 3141203Sbill else 3151203Sbill bdwrite(bp); 31624Sbill } 31724Sbill } 31824Sbill 31924Sbill /* 32024Sbill * Free all the disk blocks associated 32124Sbill * with the specified inode structure. 32224Sbill * The blocks of the file are removed 32324Sbill * in reverse order. This FILO 32424Sbill * algorithm will tend to maintain 32524Sbill * a contiguous free list much longer 32624Sbill * than FIFO. 32724Sbill */ 32824Sbill itrunc(ip) 3294818Swnj register struct inode *ip; 33024Sbill { 33124Sbill register i; 33224Sbill dev_t dev; 33324Sbill daddr_t bn; 3341203Sbill struct inode itmp; 3356569Smckusic register struct fs *fs; 336*7492Skre #ifdef QUOTA 337*7492Skre register long cnt = 0; 338*7492Skre long tloop(); 339*7492Skre #endif 34024Sbill 3411203Sbill /* 3421203Sbill * Clean inode on disk before freeing blocks 3431203Sbill * to insure no duplicates if system crashes. 3441203Sbill */ 3451203Sbill itmp = *ip; 3461203Sbill itmp.i_size = 0; 3476569Smckusic for (i = 0; i < NDADDR; i++) 3486569Smckusic itmp.i_db[i] = 0; 3496569Smckusic for (i = 0; i < NIADDR; i++) 3506569Smckusic itmp.i_ib[i] = 0; 3511203Sbill itmp.i_flag |= ICHG|IUPD; 3521203Sbill iupdat(&itmp, &time, &time, 1); 3531203Sbill ip->i_flag &= ~(IUPD|IACC|ICHG); 3541203Sbill 3551203Sbill /* 3567341Sroot * Only plain files, directories and symbolic 3577341Sroot * links contain blocks. 3587341Sroot */ 3597341Sroot i = ip->i_mode & IFMT; 3607341Sroot if (i != IFREG && i != IFDIR && i != IFLNK) 3617341Sroot return; 3627341Sroot /* 3631203Sbill * Now return blocks to free list... if machine 3641203Sbill * crashes, they will be harmless MISSING blocks. 3651203Sbill */ 36624Sbill dev = ip->i_dev; 3676569Smckusic fs = ip->i_fs; 3686569Smckusic /* 3696569Smckusic * release double indirect block first 3706569Smckusic */ 3716569Smckusic bn = ip->i_ib[NIADDR-1]; 3726569Smckusic if (bn != (daddr_t)0) { 3736569Smckusic ip->i_ib[NIADDR - 1] = (daddr_t)0; 374*7492Skre #ifdef QUOTA 375*7492Skre cnt += 376*7492Skre #endif 377*7492Skre tloop(ip, bn, 1); 3786569Smckusic } 3796569Smckusic /* 3806569Smckusic * release single indirect blocks second 3816569Smckusic */ 3826569Smckusic for (i = NIADDR - 2; i >= 0; i--) { 3836569Smckusic bn = ip->i_ib[i]; 3846569Smckusic if (bn != (daddr_t)0) { 3856569Smckusic ip->i_ib[i] = (daddr_t)0; 386*7492Skre #ifdef QUOTA 387*7492Skre cnt += 388*7492Skre #endif 389*7492Skre tloop(ip, bn, 0); 3906569Smckusic } 3916569Smckusic } 3926569Smckusic /* 3936569Smckusic * finally release direct blocks 3946569Smckusic */ 3956569Smckusic for (i = NDADDR - 1; i>=0; i--) { 396*7492Skre register size; 397*7492Skre 3986569Smckusic bn = ip->i_db[i]; 3994818Swnj if (bn == (daddr_t)0) 40024Sbill continue; 4016569Smckusic ip->i_db[i] = (daddr_t)0; 402*7492Skre fre(ip, bn, size = (off_t)blksize(fs, ip, i)); 403*7492Skre #ifdef QUOTA 404*7492Skre cnt += size / DEV_BSIZE; 405*7492Skre #endif 40624Sbill } 40724Sbill ip->i_size = 0; 4081203Sbill /* 4091203Sbill * Inode was written and flags updated above. 4101203Sbill * No need to modify flags here. 4111203Sbill */ 412*7492Skre #ifdef QUOTA 413*7492Skre (void) chkdq(ip, -cnt, 0); 414*7492Skre #endif 41524Sbill } 41624Sbill 417*7492Skre #ifdef QUOTA 418*7492Skre long 419*7492Skre #endif 4206569Smckusic tloop(ip, bn, indflg) 4216569Smckusic register struct inode *ip; 4226569Smckusic daddr_t bn; 4236569Smckusic int indflg; 42424Sbill { 42524Sbill register i; 42624Sbill register struct buf *bp; 42724Sbill register daddr_t *bap; 4286569Smckusic register struct fs *fs; 42924Sbill daddr_t nb; 430*7492Skre #ifdef QUOTA 431*7492Skre register long cnt = 0; 432*7492Skre #endif 43324Sbill 43424Sbill bp = NULL; 4356569Smckusic fs = ip->i_fs; 4366569Smckusic for (i = NINDIR(fs) - 1; i >= 0; i--) { 4374818Swnj if (bp == NULL) { 4386569Smckusic bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize); 43924Sbill if (bp->b_flags & B_ERROR) { 44024Sbill brelse(bp); 44124Sbill return; 44224Sbill } 44324Sbill bap = bp->b_un.b_daddr; 44424Sbill } 44524Sbill nb = bap[i]; 4464818Swnj if (nb == (daddr_t)0) 44724Sbill continue; 448*7492Skre if (indflg) { 449*7492Skre #ifdef QUOTA 450*7492Skre cnt += 451*7492Skre #endif 452*7492Skre tloop(ip, nb, 0); 453*7492Skre } else { 4546569Smckusic fre(ip, nb, fs->fs_bsize); 455*7492Skre #ifdef QUOTA 456*7492Skre cnt += fs->fs_bsize / DEV_BSIZE; 457*7492Skre #endif 458*7492Skre } 45924Sbill } 4604818Swnj if (bp != NULL) 46124Sbill brelse(bp); 4626569Smckusic fre(ip, bn, fs->fs_bsize); 463*7492Skre #ifdef QUOTA 464*7492Skre cnt += fs->fs_bsize / DEV_BSIZE; 465*7492Skre return(cnt); 466*7492Skre #endif 46724Sbill } 46824Sbill 46924Sbill /* 47024Sbill * Make a new file. 47124Sbill */ 47224Sbill struct inode * 47324Sbill maknode(mode) 4746569Smckusic int mode; 47524Sbill { 47624Sbill register struct inode *ip; 4776569Smckusic ino_t ipref; 47824Sbill 4796569Smckusic if ((mode & IFMT) == IFDIR) 4806569Smckusic ipref = dirpref(u.u_pdir->i_fs); 4816569Smckusic else 4826569Smckusic ipref = u.u_pdir->i_number; 4836569Smckusic ip = ialloc(u.u_pdir, ipref, mode); 4844818Swnj if (ip == NULL) { 48524Sbill iput(u.u_pdir); 48624Sbill return(NULL); 48724Sbill } 488*7492Skre #ifdef QUOTA 489*7492Skre if (ip->i_dquot != NODQUOT) 490*7492Skre panic("maknode: dquot"); 491*7492Skre #endif 49224Sbill ip->i_flag |= IACC|IUPD|ICHG; 4936569Smckusic if ((mode & IFMT) == 0) 49424Sbill mode |= IFREG; 49524Sbill ip->i_mode = mode & ~u.u_cmask; 49624Sbill ip->i_nlink = 1; 49724Sbill ip->i_uid = u.u_uid; 4985855Swnj ip->i_gid = u.u_pdir->i_gid; 499*7492Skre #ifdef QUOTA 500*7492Skre ip->i_dquot = inoquota(ip); 501*7492Skre #endif 5021203Sbill 5031203Sbill /* 5041203Sbill * Make sure inode goes to disk before directory entry. 5051203Sbill */ 5061203Sbill iupdat(ip, &time, &time, 1); 50724Sbill wdir(ip); 5086569Smckusic if (u.u_error) { 5096569Smckusic /* 5106569Smckusic * write error occurred trying to update directory 5116569Smckusic * so must deallocate the inode 5126569Smckusic */ 5136569Smckusic ip->i_nlink = 0; 5146569Smckusic ip->i_flag |= ICHG; 5156569Smckusic iput(ip); 5166569Smckusic return(NULL); 5176569Smckusic } 51824Sbill return(ip); 51924Sbill } 52024Sbill 52124Sbill /* 52224Sbill * Write a directory entry with 52324Sbill * parameters left as side effects 52424Sbill * to a call to namei. 52524Sbill */ 52624Sbill wdir(ip) 5274818Swnj struct inode *ip; 52824Sbill { 5296569Smckusic register struct direct *dp, *ndp; 5306569Smckusic struct fs *fs; 5316569Smckusic struct buf *bp; 5326569Smckusic int lbn, bn, base; 5336569Smckusic int loc, dsize, spccnt, newsize; 5346569Smckusic char *dirbuf; 53524Sbill 53624Sbill u.u_dent.d_ino = ip->i_number; 53724Sbill u.u_segflg = 1; 5386569Smckusic newsize = DIRSIZ(&u.u_dent); 5396569Smckusic /* 5406569Smckusic * if u.u_count == 0, a new directory block must be allocated. 5416569Smckusic */ 5426569Smckusic if (u.u_count == 0) { 5436569Smckusic u.u_dent.d_reclen = DIRBLKSIZ; 5446569Smckusic u.u_count = newsize; 5456569Smckusic u.u_base = (caddr_t)&u.u_dent; 5466569Smckusic writei(u.u_pdir); 5476569Smckusic iput(u.u_pdir); 5486569Smckusic return; 5496569Smckusic } 5506569Smckusic /* 5516569Smckusic * must read in an existing directory block 5526569Smckusic * to prepare to place the new entry into it. 5536569Smckusic */ 5546569Smckusic fs = u.u_pdir->i_fs; 5556569Smckusic lbn = lblkno(fs, u.u_offset); 5566569Smckusic base = blkoff(fs, u.u_offset); 5576569Smckusic bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count)); 5586569Smckusic if (u.u_offset + u.u_count > u.u_pdir->i_size) 5596569Smckusic u.u_pdir->i_size = u.u_offset + u.u_count; 5606569Smckusic bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn)); 5616569Smckusic if (bp->b_flags & B_ERROR) { 5626569Smckusic brelse(bp); 5636569Smckusic return; 5646569Smckusic } 5656569Smckusic dirbuf = bp->b_un.b_addr + base; 5666569Smckusic dp = (struct direct *)dirbuf; 5676569Smckusic dsize = DIRSIZ(dp); 5686569Smckusic spccnt = dp->d_reclen - dsize; 5696569Smckusic /* 5706569Smckusic * if there is insufficient room to make an entry at this point 5716569Smckusic * namei insures that compacting from u.u_offset for u.u_count 5726569Smckusic * bytes will provide the necessary space. 5736569Smckusic */ 5746569Smckusic for (loc = dp->d_reclen; loc < u.u_count; ) { 5756569Smckusic ndp = (struct direct *)(dirbuf + loc); 5766569Smckusic if (dp->d_ino == 0) { 5776569Smckusic spccnt += dsize; 5786569Smckusic } else { 5796569Smckusic dp->d_reclen = dsize; 5806569Smckusic dp = (struct direct *)((char *)dp + dsize); 5816569Smckusic } 5826569Smckusic dsize = DIRSIZ(ndp); 5836569Smckusic spccnt += ndp->d_reclen - dsize; 5846569Smckusic loc += ndp->d_reclen; 5856569Smckusic bcopy(ndp, dp, dsize); 5866569Smckusic } 5876569Smckusic /* 5886569Smckusic * Update the pointer fields in the previous entry (if any), 5896569Smckusic * copy in the new entry, and write out the block. 5906569Smckusic */ 5916569Smckusic if (dp->d_ino == 0) { 5926569Smckusic if (spccnt + dsize < newsize) 5936569Smckusic panic("wdir: compact failed"); 5946569Smckusic u.u_dent.d_reclen = spccnt + dsize; 5956569Smckusic } else { 5966569Smckusic if (spccnt < newsize) 5976569Smckusic panic("wdir: compact failed"); 5986569Smckusic u.u_dent.d_reclen = spccnt; 5996569Smckusic dp->d_reclen = dsize; 6006569Smckusic dp = (struct direct *)((char *)dp + dsize); 6016569Smckusic } 6026569Smckusic bcopy(&u.u_dent, dp, newsize); 6036569Smckusic bwrite(bp); 6046569Smckusic u.u_pdir->i_flag |= IUPD|ICHG; 60524Sbill iput(u.u_pdir); 60624Sbill } 6073617Sroot 6087334Skre /* 6097334Skre * remove any inodes in the inode cache belonging to dev 6107334Skre * 6117334Skre * There should not be any active ones, return error if any are found 6127334Skre * (nb: this is a user error, not a system err) 6137334Skre * 6147334Skre * Also, count the references to dev by block devices - this really 6157334Skre * has nothing to do with the object of the procedure, but as we have 6167334Skre * to scan the inode table here anyway, we might as well get the 6177334Skre * extra benefit. 6187334Skre * 6197334Skre * this is called from sumount()/sys3.c when dev is being unmounted 6207334Skre */ 621*7492Skre #ifdef QUOTA 622*7492Skre iflush(dev, qi); 623*7492Skre dev_t dev; 624*7492Skre struct inode *qi; 625*7492Skre #else 6267334Skre iflush(dev) 6277334Skre dev_t dev; 628*7492Skre #endif 6297334Skre { 6307335Skre register struct inode *ip; 6317334Skre register open = 0; 6327334Skre 6337334Skre for (ip = inode; ip < inodeNINODE; ip++) { 634*7492Skre #ifdef QUOTA 635*7492Skre if (ip != iq && ip->i_dev == dev) 636*7492Skre #else 6377334Skre if (ip->i_dev == dev) 638*7492Skre #endif 6397334Skre if (ip->i_count) 6407334Skre return(-1); 6417334Skre else { 6427335Skre remque(ip); 6437334Skre ip->i_forw = ip; 6447334Skre ip->i_back = ip; 6457334Skre /* 6467334Skre * as i_count == 0, the inode was on the free 6477334Skre * list already, just leave it there, it will 6487334Skre * fall off the bottom eventually. We could 6497334Skre * perhaps move it to the head of the free 6507334Skre * list, but as umounts are done so 6517334Skre * infrequently, we would gain very little, 6527334Skre * while making the code bigger. 6537334Skre */ 654*7492Skre #ifdef QUOTA 655*7492Skre dqrele(ip->i_dquot); 656*7492Skre ip->i_dquot = NODQUOT; 657*7492Skre #endif 6587334Skre } 6597334Skre else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK && 6607334Skre ip->i_rdev == dev) 6617334Skre open++; 6627334Skre } 6637334Skre return (open); 6647334Skre } 6657334Skre 6664818Swnj #ifdef ilock 6674818Swnj #undef ilock 6683617Sroot #endif 6697118Smckusick #ifdef iunlock 6707118Smckusick #undef iunlock 6713617Sroot #endif 6723617Sroot /* 6734818Swnj * Lock an inode. If its already locked, set the WANT bit and sleep. 6743617Sroot */ 6754818Swnj ilock(ip) 6764818Swnj register struct inode *ip; 6773617Sroot { 6783617Sroot 6794818Swnj while (ip->i_flag&ILOCK) { 6803617Sroot ip->i_flag |= IWANT; 6813617Sroot sleep((caddr_t)ip, PINOD); 6823617Sroot } 6833617Sroot ip->i_flag |= ILOCK; 6843617Sroot } 6853617Sroot 6863617Sroot /* 6874818Swnj * Unlock an inode. If WANT bit is on, wakeup. 6883617Sroot */ 6897118Smckusick iunlock(ip) 6904818Swnj register struct inode *ip; 6913617Sroot { 6923617Sroot 6933617Sroot ip->i_flag &= ~ILOCK; 6944818Swnj if (ip->i_flag&IWANT) { 6953617Sroot ip->i_flag &= ~IWANT; 6963617Sroot wakeup((caddr_t)ip); 6973617Sroot } 6983617Sroot } 699