# 2.11BSD#431 - /usr/src/sys/sys/ufs_inode.c

##### Functions

    ifind             X
    iflush            X
    iget              X
    igrab             X
    ihinit            X
    ilock             X
    indirtrunc        X
    iput              X
    irele             X
    itrunc            X
    iunlock           X
    iupdat            X

##### Variables

    ifreeh            X
    ifreet            X
    ihead             X

##### Macros

    DOUBLE            X
    INOHASH           X
    INOHSZ            X
    SINGLE            X
    TRIPLE            X

##### unions's

    ihead             X

       1: /*
       2:  * Copyright (c) 1986 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  *
       6:  *	@(#)ufs_inode.c	1.7 (2.11BSD GTE) 1997/2/7
       7:  */
       8:
       9: #include "param.h"
      10: #include "../machine/seg.h"
      11:
      12: #include "user.h"
      13: #include "proc.h"
      14: #include "inode.h"
      15: #include "fs.h"
      16: #include "mount.h"
      17: #include "kernel.h"
      18: #include "buf.h"
      19: #include "text.h"
      20: #include "systm.h"
      21: #ifdef QUOTA
      22: #include "quota.h"
      23: #endif
      24: #include "syslog.h"
      25:
      26: #define INOHSZ  16      /* must be power of two */
      27: #define INOHASH(dev,ino)    (((dev)+(ino))&(INOHSZ-1))
      28:
      29: union ihead {               /* inode LRU cache, stolen */
      30:     union  ihead *ih_head[2];
      31:     struct inode *ih_chain[2];
      32: } ihead[INOHSZ];
      33:
      34: struct inode *ifreeh, **ifreet;
      35:
      36: /*
      37:  * Initialize hash links for inodes
      38:  * and build inode free list.
      39:  */
      40: ihinit()
      41: {
      42:     register int i;
      43:     register struct inode *ip = inode;
      44:     register union  ihead *ih = ihead;
      45:
      46:     for (i = INOHSZ; --i >= 0; ih++) {
      47:         ih->ih_head[0] = ih;
      48:         ih->ih_head[1] = ih;
      49:     }
      50:     ifreeh = ip;
      51:     ifreet = &ip->i_freef;
      52:     ip->i_freeb = &ifreeh;
      53:     ip->i_forw = ip;
      54:     ip->i_back = ip;
      55:     for (i = ninode; --i > 0; ) {
      56:         ++ip;
      57:         ip->i_forw = ip;
      58:         ip->i_back = ip;
      59:         *ifreet = ip;
      60:         ip->i_freeb = ifreet;
      61:         ifreet = &ip->i_freef;
      62:     }
      63:     ip->i_freef = NULL;
      64: }
      65:
      66: /*
      67:  * Find an inode if it is incore.
      68:  */
      69: struct inode *
      70: ifind(dev, ino)
      71:     register dev_t dev;
      72:     register ino_t ino;
      73: {
      74:     register struct inode *ip;
      75:     union ihead *ih;
      76:
      77:     ih = &ihead[INOHASH(dev, ino)];
      78:     for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
      79:         if (ino == ip->i_number && dev == ip->i_dev)
      80:             return(ip);
      81:     return((struct inode *)NULL);
      82: }
      83:
      84: /*
      85:  * Look up an inode by device,inumber.
      86:  * If it is in core (in the inode structure),
      87:  * honor the locking protocol.
      88:  * If it is not in core, read it in from the
      89:  * specified device.
      90:  * If the inode is mounted on, perform
      91:  * the indicated indirection.
      92:  * In all cases, a pointer to a locked
      93:  * inode structure is returned.
      94:  *
      95:  * panic: no imt -- if the mounted file
      96:  *	system is not in the mount table.
      97:  *	"cannot happen"
      98:  */
      99: struct inode *
     100: iget(dev, fs, ino)
     101:     dev_t dev;
     102:     register struct fs *fs;
     103:     ino_t ino;
     104: {
     105:     register struct inode *ip;
     106:     union ihead *ih;
     107:     struct buf *bp;
     108:     struct dinode *dp;
     109: #ifdef EXTERNALITIMES
     110:     struct icommon2 xic2;
     111: #endif
     112: #ifdef  QUOTA
     113:     struct dquot **xdq;
     114: #endif
     115:
     116: loop:
     117:     ih = &ihead[INOHASH(dev, ino)];
     118:     for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
     119:         if (ino == ip->i_number && dev == ip->i_dev) {
     120:             /*
     121: 			 * Following is essentially an inline expanded
     122: 			 * copy of igrab(), expanded inline for speed,
     123: 			 * and so that the test for a mounted on inode
     124: 			 * can be deferred until after we are sure that
     125: 			 * the inode isn't busy.
     126: 			 */
     127:             if ((ip->i_flag&ILOCKED) != 0) {
     128:                 ip->i_flag |= IWANT;
     129:                 sleep((caddr_t)ip, PINOD);
     130:                 goto loop;
     131:             }
     132:             if ((ip->i_flag&IMOUNT) != 0) {
     133:                 register struct mount *mp;
     134:
     135:                 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
     136:                     if(mp->m_inodp == ip) {
     137:                         dev = mp->m_dev;
     138:                         fs = &mp->m_filsys;
     139:                         ino = ROOTINO;
     140:                         goto loop;
     141:                     }
     142:                 panic("no imt");
     143:             }
     144:             if (ip->i_count == 0) {     /* ino on free list */
     145:                 register struct inode *iq;
     146:
     147:                 if (iq = ip->i_freef)
     148:                     iq->i_freeb = ip->i_freeb;
     149:                 else
     150:                     ifreet = ip->i_freeb;
     151:                 *ip->i_freeb = iq;
     152:                 ip->i_freef = NULL;
     153:                 ip->i_freeb = NULL;
     154:             }
     155:             ip->i_count++;
     156:             ip->i_flag |= ILOCKED;
     157:             return(ip);
     158:         }
     159:
     160:     if ((ip = ifreeh) == NULL) {
     161:         tablefull("inode");
     162:         u.u_error = ENFILE;
     163:         return(NULL);
     164:     }
     165:     if (ip->i_count)
     166:         panic("free inode isn't");
     167: {
     168:     register struct inode *iq;
     169:
     170:     if (iq = ip->i_freef)
     171:         iq->i_freeb = &ifreeh;
     172:     ifreeh = iq;
     173: }
     174:     ip->i_freef = NULL;
     175:     ip->i_freeb = NULL;
     176:     /*
     177: 	 * Now to take inode off the hash chain it was on
     178: 	 * (initially, or after an iflush, it is on a "hash chain"
     179: 	 * consisting entirely of itself, and pointed to by no-one,
     180: 	 * but that doesn't matter), and put it on the chain for
     181: 	 * its new (ino, dev) pair
     182: 	 */
     183:     remque(ip);
     184:     insque(ip, ih);
     185:     ip->i_dev = dev;
     186:     ip->i_fs = fs;
     187:     ip->i_number = ino;
     188:     cacheinval(ip);
     189:     ip->i_flag = ILOCKED;
     190:     ip->i_count++;
     191:     ip->i_lastr = 0;
     192: #ifdef QUOTA
     193:     QUOTAMAP();
     194:     xdq = &ix_dquot[ip - inode];
     195:     dqrele(*xdq);
     196:     QUOTAUNMAP();
     197: #endif
     198:     bp = bread(dev, itod(ino));
     199:     /*
     200: 	 * Check I/O errors
     201: 	 */
     202:     if ((bp->b_flags&B_ERROR) != 0) {
     203:         brelse(bp);
     204:         /*
     205: 		 * the inode doesn't contain anything useful, so it would
     206: 		 * be misleading to leave it on its hash chain.
     207: 		 * 'iput' will take care of putting it back on the free list.
     208: 		 */
     209:         remque(ip);
     210:         ip->i_forw = ip;
     211:         ip->i_back = ip;
     212:         /*
     213: 		 * we also loose its inumber, just in case (as iput
     214: 		 * doesn't do that any more) - but as it isn't on its
     215: 		 * hash chain, I doubt if this is really necessary .. kre
     216: 		 * (probably the two methods are interchangable)
     217: 		 */
     218:         ip->i_number = 0;
     219: #ifdef QUOTA
     220:         QUOTAMAP();
     221:         *xdq = NODQUOT;
     222:         QUOTAUNMAP();
     223: #endif
     224:         iput(ip);
     225:         return(NULL);
     226:     }
     227:     dp = (struct dinode *)mapin(bp);
     228:     dp += itoo(ino);
     229:     ip->i_ic1 = dp->di_ic1;
     230:     ip->i_flags = dp->di_flags;
     231: #ifdef EXTERNALITIMES
     232:     xic2 = dp->di_ic2;
     233: #else
     234:     ip->i_ic2 = dp->di_ic2;
     235: #endif
     236:     bcopy(dp->di_addr, ip->i_addr, NADDR * sizeof (daddr_t));
     237:     mapout(bp);
     238:     brelse(bp);
     239: #ifdef EXTERNALITIMES
     240:     mapseg5(xitimes, xitdesc);
     241:     ((struct icommon2 *)SEG5)[ip-inode] = xic2;
     242:     normalseg5();
     243: #endif
     244: #ifdef QUOTA
     245:     QUOTAMAP();
     246:     if  (ip->i_mode == 0)
     247:         *xdq = NODQUOT;
     248:     else
     249:         *xdq = inoquota(ip);
     250:     QUOTAUNMAP();
     251: #endif
     252:     return (ip);
     253: }
     254:
     255: /*
     256:  * Convert a pointer to an inode into a reference to an inode.
     257:  *
     258:  * This is basically the internal piece of iget (after the
     259:  * inode pointer is located) but without the test for mounted
     260:  * filesystems.  It is caller's responsibility to check that
     261:  * the inode pointer is valid.
     262:  */
     263: igrab(ip)
     264:     register struct inode *ip;
     265: {
     266:     while ((ip->i_flag&ILOCKED) != 0) {
     267:         ip->i_flag |= IWANT;
     268:         sleep((caddr_t)ip, PINOD);
     269:     }
     270:     if (ip->i_count == 0) {     /* ino on free list */
     271:         register struct inode *iq;
     272:
     273:         if (iq = ip->i_freef)
     274:             iq->i_freeb = ip->i_freeb;
     275:         else
     276:             ifreet = ip->i_freeb;
     277:         *ip->i_freeb = iq;
     278:         ip->i_freef = NULL;
     279:         ip->i_freeb = NULL;
     280:     }
     281:     ip->i_count++;
     282:     ip->i_flag |= ILOCKED;
     283: }
     284:
     285: /*
     286:  * Decrement reference count of
     287:  * an inode structure.
     288:  * On the last reference,
     289:  * write the inode out and if necessary,
     290:  * truncate and deallocate the file.
     291:  */
     292: iput(ip)
     293:     register struct inode *ip;
     294: {
     295:
     296: #ifdef notnow
     297:     /*
     298: 	 * This code requires a lot of workarounds, you have to change
     299: 	 * lots of places to gratuitously lock just so we can unlock it.
     300: 	 * Not worth it.  -- KB
     301: 	 */
     302:     if ((ip->i_flag & ILOCKED) == 0)
     303:         panic("iput");
     304: #endif
     305:     IUNLOCK(ip);
     306:     irele(ip);
     307: }
     308:
     309: irele(ip)
     310:     register struct inode *ip;
     311: {
     312:     if (ip->i_count == 1) {
     313:         ip->i_flag |= ILOCKED;
     314:         if (ip->i_nlink <= 0 && ip->i_fs->fs_ronly == 0) {
     315: #ifdef QUOTA
     316:             QUOTAMAP();
     317:             (void) chkiq(ip->i_dev, ip, ip->i_uid, 0);
     318:             dqrele(ix_dquot[ip - inode]);
     319:             ix_dquot[ip - inode] = NODQUOT;
     320:             QUOTAUNMAP();
     321: #endif
     322:             itrunc(ip, (u_long)0, 0);
     323:             ip->i_mode = 0;
     324:             ip->i_rdev = 0;
     325:             ip->i_flag |= IUPD|ICHG;
     326:             ifree(ip, ip->i_number);
     327:         }
     328:         IUPDAT(ip, &time, &time, 0);
     329:         IUNLOCK(ip);
     330:         ip->i_flag = 0;
     331:         /*
     332: 		 * Put the inode on the end of the free list.
     333: 		 * Possibly in some cases it would be better to
     334: 		 * put the inode at the head of the free list,
     335: 		 * (eg: where i_mode == 0 || i_number == 0)
     336: 		 * but I will think about that later .. kre
     337: 		 * (i_number is rarely 0 - only after an i/o error in iget,
     338: 		 * where i_mode == 0, the inode will probably be wanted
     339: 		 * again soon for an ialloc, so possibly we should keep it)
     340: 		 */
     341:         if (ifreeh) {
     342:             *ifreet = ip;
     343:             ip->i_freeb = ifreet;
     344:         } else {
     345:             ifreeh = ip;
     346:             ip->i_freeb = &ifreeh;
     347:         }
     348:         ip->i_freef = NULL;
     349:         ifreet = &ip->i_freef;
     350:     } else if (!(ip->i_flag & ILOCKED))
     351:         ITIMES(ip, &time, &time);
     352:     ip->i_count--;
     353: }
     354:
     355: /*
     356:  * Check accessed and update flags on
     357:  * an inode structure.
     358:  * If any are on, update the inode
     359:  * with the current time.
     360:  * If waitfor set, then must insure
     361:  * i/o order so wait for the write to complete.
     362:  */
     363: iupdat(ip, ta, tm, waitfor)
     364:     struct inode *ip;
     365:     struct timeval *ta, *tm;
     366:     int waitfor;
     367: {
     368:     register struct buf *bp;
     369:     register struct dinode *dp;
     370: #ifdef EXTERNALITIMES
     371:     struct icommon2 xic2, *xicp2;
     372: #endif
     373:     register struct inode *tip = ip;
     374:
     375:     if ((tip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0)
     376:         return;
     377:     if (tip->i_fs->fs_ronly)
     378:         return;
     379:     bp = bread(tip->i_dev, itod(tip->i_number));
     380:     if (bp->b_flags & B_ERROR) {
     381:         brelse(bp);
     382:         return;
     383:     }
     384: #ifdef EXTERNALITIMES
     385:     mapseg5(xitimes, xitdesc);
     386:     xicp2 = &((struct icommon2 *)SEG5)[ip - inode];
     387:     if (tip->i_flag & IACC)
     388:         xicp2->ic_atime = ta->tv_sec;
     389:     if (tip->i_flag & IUPD)
     390:         xicp2->ic_mtime = tm->tv_sec;
     391:     if (tip->i_flag & ICHG)
     392:         xicp2->ic_ctime = time.tv_sec;
     393:     xic2 = *xicp2;
     394:     normalseg5();
     395: #else
     396:     if (tip->i_flag&IACC)
     397:         tip->i_atime = ta->tv_sec;
     398:     if (tip->i_flag&IUPD)
     399:         tip->i_mtime = tm->tv_sec;
     400:     if (tip->i_flag&ICHG)
     401:         tip->i_ctime = time.tv_sec;
     402: #endif
     403:     tip->i_flag &= ~(IUPD|IACC|ICHG|IMOD);
     404:     dp = (struct dinode *)mapin(bp) + itoo(tip->i_number);
     405:     dp->di_ic1 = tip->i_ic1;
     406:     dp->di_flags = tip->i_flags;
     407: #ifdef EXTERNALITIMES
     408:     dp->di_ic2 = xic2;
     409: #else
     410:     dp->di_ic2 = tip->i_ic2;
     411: #endif
     412:     bcopy(ip->i_addr, dp->di_addr, NADDR * sizeof (daddr_t));
     413:     mapout(bp);
     414:     if (waitfor && ((ip->i_fs->fs_flags & MNT_ASYNC) == 0))
     415:         bwrite(bp);
     416:     else
     417:         bdwrite(bp);
     418: }
     419:
     420: #define SINGLE  0   /* index of single indirect block */
     421: #define DOUBLE  1   /* index of double indirect block */
     422: #define TRIPLE  2   /* index of triple indirect block */
     423: /*
     424:  * Truncate the inode ip to at most
     425:  * length size.  Free affected disk
     426:  * blocks -- the blocks of the file
     427:  * are removed in reverse order.
     428:  *
     429:  * NB: triple indirect blocks are untested.
     430:  */
     431: itrunc(oip,length, ioflags)
     432:     register struct inode *oip;
     433:     u_long length;
     434:     int ioflags;
     435: {
     436:     daddr_t lastblock;
     437:     register int i;
     438:     register struct inode *ip;
     439:     daddr_t bn, lastiblock[NIADDR];
     440:     struct buf *bp;
     441:     int offset, level;
     442:     struct inode tip;
     443:     int aflags;
     444: #ifdef QUOTA
     445:     long bytesreleased;
     446: #endif
     447:
     448:     aflags = B_CLRBUF;
     449:     if (ioflags & IO_SYNC)
     450:         aflags |= B_SYNC;
     451:
     452:     /*
     453: 	 * special hack for pipes, since size for them isn't the size of
     454: 	 * the file, it's the amount currently waiting for transfer.  It's
     455: 	 * unclear that this will work, though, because pipes can (although
     456: 	 * rarely do) get bigger than MAXPIPSIZ.  Don't think it worked
     457: 	 * in V7 either, I don't really understand what's going on.
     458: 	 */
     459:     if (oip->i_flag & IPIPE)
     460:         oip->i_size = MAXPIPSIZ;
     461:     else if (oip->i_size == length)
     462:         goto updret;
     463:
     464:     /*
     465: 	 * Lengthen the size of the file. We must ensure that the
     466: 	 * last byte of the file is allocated. Since the smallest
     467: 	 * value of osize is 0, length will be at least 1.
     468: 	 */
     469:     if (oip->i_size < length) {
     470:         bn = bmap(oip, lblkno(length - 1), B_WRITE, aflags);
     471:         if (u.u_error || bn < 0)
     472:             return;
     473: #ifdef  QUOTA
     474:         bytesreleased = oip->i_size - length;
     475: #endif
     476:         oip->i_size = length;
     477:         goto doquotaupd;
     478:     }
     479:
     480:     /*
     481: 	 * Calculate index into inode's block list of
     482: 	 * last direct and indirect blocks (if any)
     483: 	 * which we want to keep.  Lastblock is -1 when
     484: 	 * the file is truncated to 0.
     485: 	 */
     486:     lastblock = lblkno(length + DEV_BSIZE - 1) - 1;
     487:     lastiblock[SINGLE] = lastblock - NDADDR;
     488:     lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR;
     489:     lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR * NINDIR;
     490:     /*
     491: 	 * Update the size of the file. If the file is not being
     492: 	 * truncated to a block boundry, the contents of the
     493: 	 * partial block following the end of the file must be
     494: 	 * zero'ed in case it ever become accessable again because
     495: 	 * of subsequent file growth.
     496: 	 */
     497:     offset = blkoff(length);
     498:     if (offset) {
     499:         bn = bmap(oip, lblkno(length), B_WRITE, aflags);
     500:         if (u.u_error || bn < 0)
     501:             return;
     502:         bp = bread(oip->i_dev, bn);
     503:         if (bp->b_flags & B_ERROR) {
     504:             u.u_error = EIO;
     505:             brelse(bp);
     506:             return;
     507:         }
     508:         bzero(mapin(bp) + offset, (u_int)(DEV_BSIZE - offset));
     509:         mapout(bp);
     510:         bdwrite(bp);
     511:     }
     512:     /*
     513: 	 * Update file and block pointers
     514: 	 * on disk before we start freeing blocks.
     515: 	 * If we crash before free'ing blocks below,
     516: 	 * the blocks will be returned to the free list.
     517: 	 * lastiblock values are also normalized to -1
     518: 	 * for calls to indirtrunc below.
     519: 	 */
     520:     tip = *oip;
     521: #ifdef QUOTA
     522:     bytesreleased = oip->i_size - length;
     523: #endif
     524:     oip->i_size = length;
     525:     for (level = TRIPLE; level >= SINGLE; level--)
     526:         if (lastiblock[level] < 0) {
     527:             oip->i_ib[level] = 0;
     528:             lastiblock[level] = -1;
     529:         }
     530:     for (i = NDADDR - 1; i > lastblock; i--)
     531:         oip->i_db[i] = 0;
     532:
     533:     /*
     534: 	 * Indirect blocks first.
     535: 	 */
     536:     ip = &tip;
     537:     for (level = TRIPLE; level >= SINGLE; level--) {
     538:         bn = ip->i_ib[level];
     539:         if (bn != 0) {
     540:             indirtrunc(ip, bn, lastiblock[level], level, aflags);
     541:             if (lastiblock[level] < 0) {
     542:                 ip->i_ib[level] = 0;
     543:                 free(ip, bn);
     544:             }
     545:         }
     546:         if (lastiblock[level] >= 0)
     547:             goto done;
     548:     }
     549:
     550:     /*
     551: 	 * All whole direct blocks.
     552: 	 */
     553:     for (i = NDADDR - 1; i > lastblock; i--) {
     554:         bn = ip->i_db[i];
     555:         if (bn == 0)
     556:             continue;
     557:         ip->i_db[i] = 0;
     558:         free(ip, bn);
     559:     }
     560:     if (lastblock < 0)
     561:         goto done;
     562:
     563: done:
     564: #ifdef DIAGNOSTIC
     565: /* BEGIN PARANOIA */
     566:     for (level = SINGLE; level <= TRIPLE; level++)
     567:         if (ip->i_ib[level] != oip->i_ib[level])
     568:             panic("itrunc1");
     569:     for (i = 0; i < NDADDR; i++)
     570:         if (ip->i_db[i] != oip->i_db[i])
     571:             panic("itrunc2");
     572: /* END PARANOIA */
     573: #endif
     574:
     575: doquotaupd:
     576: #ifdef QUOTA
     577:     QUOTAMAP();
     578:     (void)chkdq(oip, -bytesreleased, 0);
     579:     QUOTAUNMAP();
     580: #endif
     581: updret:
     582:     oip->i_flag |= ICHG|IUPD;
     583:     iupdat(oip, &time, &time, 1);
     584: }
     585:
     586: /*
     587:  * Release blocks associated with the inode ip and
     588:  * stored in the indirect block bn.  Blocks are free'd
     589:  * in LIFO order up to (but not including) lastbn.  If
     590:  * level is greater than SINGLE, the block is an indirect
     591:  * block and recursive calls to indirtrunc must be used to
     592:  * cleanse other indirect blocks.
     593:  *
     594:  * NB: triple indirect blocks are untested.
     595:  */
     596: indirtrunc(ip, bn, lastbn, level, aflags)
     597:     struct inode *ip;
     598:     daddr_t bn, lastbn;
     599:     int level;
     600:     int aflags;
     601: {
     602:     register struct buf *bp;
     603:     daddr_t nb, last;
     604:     long factor;
     605:
     606:     /*
     607: 	 * Calculate index in current block of last
     608: 	 * block to be kept.  -1 indicates the entire
     609: 	 * block so we need not calculate the index.
     610: 	 */
     611:     switch(level) {
     612:         case SINGLE:
     613:             factor = 1;
     614:             break;
     615:         case DOUBLE:
     616:             factor = NINDIR;
     617:             break;
     618:         case TRIPLE:
     619:             factor = NINDIR * NINDIR;
     620:             break;
     621:     }
     622:     last = lastbn;
     623:     if (lastbn > 0)
     624:         last = last / factor;
     625:     /*
     626: 	 * Get buffer of block pointers, zero those
     627: 	 * entries corresponding to blocks to be free'd,
     628: 	 * and update on disk copy first.
     629: 	 */
     630:     {
     631:         register daddr_t *bap;
     632:         register struct buf *cpy;
     633:
     634:         bp = bread(ip->i_dev, bn);
     635:         if (bp->b_flags&B_ERROR) {
     636:             brelse(bp);
     637:             return;
     638:         }
     639:         cpy = geteblk();
     640:         copy(bftopaddr(bp), bftopaddr(cpy), btoc(DEV_BSIZE));
     641:         bap = (daddr_t *)mapin(bp);
     642:         bzero((caddr_t)&bap[last + 1],
     643:             (u_int)(NINDIR - (last + 1)) * sizeof(daddr_t));
     644:         mapout(bp);
     645:         if (aflags & B_SYNC)
     646:             bwrite(bp);
     647:         else
     648:             bawrite(bp);
     649:         bp = cpy;
     650:     }
     651:
     652:     /*
     653: 	 * Optimized for single indirect blocks, i.e. until a file is
     654: 	 * greater than 4K + 256K you don't have to do a mapin/mapout
     655: 	 * for every entry.  The mapin/mapout is required since free()
     656: 	 * may have to map an item in.  Have to use another routine
     657: 	 * since it requires 1K of kernel stack to get around the problem
     658: 	 * and that doesn't work well with recursion.
     659: 	 */
     660:     if (level == SINGLE)
     661:         trsingle(ip, bp, last, aflags);
     662:     else {
     663:         register daddr_t *bstart, *bstop;
     664:
     665:         bstart = (daddr_t *)mapin(bp);
     666:         bstop = &bstart[last];
     667:         bstart += NINDIR - 1;
     668:         /*
     669: 		 * Recursively free totally unused blocks.
     670: 		 */
     671:         for (;bstart > bstop;--bstart) {
     672:             nb = *bstart;
     673:             if (nb) {
     674:                 mapout(bp);
     675:                 indirtrunc(ip,nb,(daddr_t)-1, level-1, aflags);
     676:                 free(ip, nb);
     677:                 mapin(bp);
     678:             }
     679:         }
     680:         mapout(bp);
     681:
     682:         /*
     683: 		 * Recursively free last partial block.
     684: 		 */
     685:         if (lastbn >= 0) {
     686:
     687:             mapin(bp);
     688:             nb = *bstop;
     689:             mapout(bp);
     690:             last = lastbn % factor;
     691:             if (nb != 0)
     692:                 indirtrunc(ip, nb, last, level - 1, aflags);
     693:         }
     694:     }
     695:     brelse(bp);
     696: }
     697:
     698: static
     699: trsingle(ip, bp,last, aflags)
     700:     register struct inode *ip;
     701:     caddr_t bp;
     702:     daddr_t last;
     703:     int aflags;
     704: {
     705:     register daddr_t *bstart, *bstop;
     706:     daddr_t blarray[NINDIR];
     707:
     708:     bcopy(mapin(bp),blarray,NINDIR * sizeof(daddr_t));
     709:     mapout(bp);
     710:     bstart = &blarray[NINDIR - 1];
     711:     bstop = &blarray[last];
     712:     for (;bstart > bstop;--bstart)
     713:         if (*bstart)
     714:             free(ip, *bstart);
     715: }
     716:
     717: /*
     718:  * remove any inodes in the inode cache belonging to dev
     719:  *
     720:  * There should not be any active ones, return error if any are found
     721:  * (nb: this is a user error, not a system err)
     722:  *
     723:  * Also, count the references to dev by block devices - this really
     724:  * has nothing to do with the object of the procedure, but as we have
     725:  * to scan the inode table here anyway, we might as well get the
     726:  * extra benefit.
     727:  *
     728:  * this is called from sumount() when dev is being unmounted
     729:  */
     730: #ifdef QUOTA
     731: iflush(dev, iq)
     732:     struct inode *iq;
     733: #else
     734: iflush(dev)
     735: #endif
     736:     dev_t dev;
     737: {
     738:     register struct inode *ip;
     739:     register int open = 0;
     740:
     741:     for (ip = inode; ip < inodeNINODE; ip++) {
     742: #ifdef QUOTA
     743:         if (ip != iq && ip->i_dev == dev)
     744: #else
     745:         if (ip->i_dev == dev)
     746: #endif
     747:             if (ip->i_count)
     748:                 return(-1);
     749:             else {
     750:                 remque(ip);
     751:                 ip->i_forw = ip;
     752:                 ip->i_back = ip;
     753:                 /*
     754: 				 * as i_count == 0, the inode was on the free
     755: 				 * list already, just leave it there, it will
     756: 				 * fall off the bottom eventually. We could
     757: 				 * perhaps move it to the head of the free
     758: 				 * list, but as umounts are done so
     759: 				 * infrequently, we would gain very little,
     760: 				 * while making the code bigger.
     761: 				 */
     762: #ifdef QUOTA
     763:                 QUOTAMAP();
     764:                 dqrele(ix_dquot[ip - inode]);
     765:                 ix_dquot[ip - inode] = NODQUOT;
     766:                 QUOTAUNMAP();
     767: #endif
     768:             }
     769:         else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK &&
     770:             ip->i_rdev == dev)
     771:             open++;
     772:     }
     773:     return (open);
     774: }
     775:
     776: /*
     777:  * Lock an inode. If its already locked, set the WANT bit and sleep.
     778:  */
     779: ilock(ip)
     780:     register struct inode *ip;
     781: {
     782:
     783:     ILOCK(ip);
     784: }
     785:
     786: /*
     787:  * Unlock an inode.  If WANT bit is on, wakeup.
     788:  */
     789: iunlock(ip)
     790:     register struct inode *ip;
     791: {
     792:
     793:     IUNLOCK(ip);
     794: }

#### Defined functions

ifind defined in line 69; used 2 times

- in /usr/src/sys/sys/ufs_alloc.c line 145, 208

iflush defined in line 734; used 3 times

- in /usr/src/sys/sys/ufs_mount.c line 289-291(2), 305

iget defined in line 99; used 9 times

- in /usr/src/sys/h/inode.h line 172
- in /usr/src/sys/sys/init_main.c line 206-208(2)
- in /usr/src/sys/sys/ufs_alloc.c line 163
- in /usr/src/sys/sys/ufs_namei.c line 610, 680, 711, 717, 1192

igrab defined in line 263; used 2 times

- in /usr/src/sys/sys/ufs_namei.c line 304-308(2)

ihinit defined in line 40; used 1 times

- in /usr/src/sys/sys/init_main.c line 98

ilock defined in line 779; used 10 times

- in /usr/src/sys/sys/kern_exit.c line 70-73(2)
- in /usr/src/sys/sys/sys_pipe.c line 278
- in /usr/src/sys/sys/ufs_syscalls.c line 42, 517, 571, 644, 754
- in /usr/src/sys/sys/ufs_syscalls2.c line 256
- in /usr/src/sys/sys/vfs_vnops.c line 162

indirtrunc defined in line 596; used 3 times

- in line 540, 675, 692

iput defined in line 292; used 75 times

- in line 224
- in /usr/src/sys/pdp/net_mac.h line 58-60(2)
- in /usr/src/sys/sys/init_main.c line 432
- in /usr/src/sys/sys/kern_exec.c line 176, 296, 386
- in /usr/src/sys/sys/kern_exit.c line 71-74(2)
- in /usr/src/sys/sys/kern_sig.c line 678
- in /usr/src/sys/sys/sys_kern.c line 112
- in /usr/src/sys/sys/sys_pipe.c line 67, 75, 302
- in /usr/src/sys/sys/ufs_alloc.c line 177
- in /usr/src/sys/sys/ufs_mount.c line 103, 134, 242, 341-345(2)
- in /usr/src/sys/sys/ufs_namei.c line 320, 612, 625, 651, 682, 798, 841, 917, 945, 993, 1054, 1191, 1203
- in /usr/src/sys/sys/ufs_syscalls.c line 99, 234, 255-260(2), 272, 278, 319, 331, 376-377(2), 409, 450, 480, 501, 554, 626, 731, 811-815(2), 830-834(2), 842, 895, 995, 1060-1062(2), 1069-1072(2), 1097, 1132, 1169, 1185, 1257-1258(2), 1283, 1323, 1341-1342(2)
- in /usr/src/sys/sys/ufs_syscalls2.c line 36, 191, 285
- in /usr/src/sys/sys/vfs_vnops.c line 169

irele defined in line 309; used 20 times

- in line 306
- in /usr/src/sys/sys/quota_kern.c line 805
- in /usr/src/sys/sys/sys_kern.c line 86
- in /usr/src/sys/sys/ufs_mount.c line 309
- in /usr/src/sys/sys/ufs_namei.c line 800, 822, 828, 834
- in /usr/src/sys/sys/ufs_syscalls.c line 51, 94, 288, 374, 813, 832, 1063, 1076, 1282
- in /usr/src/sys/sys/vfs_vnops.c line 193, 219
- in /usr/src/sys/sys/vm_text.c line 358

itrunc defined in line 431; used 8 times

- in line 322
- in /usr/src/sys/sys/kern_sig.c line 661
- in /usr/src/sys/sys/sys_inode.c line 309
- in /usr/src/sys/sys/ufs_fio.c line 163
- in /usr/src/sys/sys/ufs_namei.c line 992
- in /usr/src/sys/sys/ufs_syscalls.c line 992, 1337
- in /usr/src/sys/sys/vfs_vnops.c line 140

iunlock defined in line 789; used 14 times

- in /usr/src/sys/sys/init_main.c line 207-209(2)
- in /usr/src/sys/sys/sys_kern.c line 122
- in /usr/src/sys/sys/ufs_syscalls.c line 49, 55, 92, 266, 519, 575, 649, 758, 853
- in /usr/src/sys/sys/ufs_syscalls2.c line 258
- in /usr/src/sys/sys/vfs_vnops.c line 147

iupdat defined in line 363; used 11 times

- in line 583
- in /usr/src/sys/h/inode.h line 284
- in /usr/src/sys/sys/ufs_fio.c line 181
- in /usr/src/sys/sys/ufs_subr.c line 100
- in /usr/src/sys/sys/ufs_syscalls.c line 265, 852, 926, 1123, 1203, 1213
- in /usr/src/sys/sys/ufs_syscalls2.c line 190

trsingle defined in line 698; used 1 times

- in line 661

#### Defined variables

ifreeh defined in line 34; used 8 times

- in line 50-52(2), 160, 171-172(2), 341-346(3)

ifreet defined in line 34; used 9 times

- in line 51, 59-61(3), 150, 276, 342-343(2), 349

ihead defined in line 32; used 3 times

- in line 44, 77, 117

#### Defined union's

ihead defined in line 29; used 8 times

- in line 30(2), 44(2), 75(2), 106(2)

#### Defined macros

DOUBLE defined in line 421; used 2 times

- in line 488-489(2)

INOHASH defined in line 27; used 2 times

- in line 77, 117

INOHSZ defined in line 26; used 3 times

- in line 27-32(2), 46

SINGLE defined in line 420; used 6 times

- in line 487-488(2), 525, 537, 566, 660

TRIPLE defined in line 422; used 4 times

- in line 489, 525, 537, 566

Last modified: 1997-02-07 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1831 |