home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V6 / usr / sys / ken / alloc.c next >
Encoding:
C/C++ Source or Header  |  1975-07-17  |  5.9 KB  |  315 lines

  1. #
  2. /*
  3.  */
  4.  
  5. #include "../param.h"
  6. #include "../systm.h"
  7. #include "../filsys.h"
  8. #include "../conf.h"
  9. #include "../buf.h"
  10. #include "../inode.h"
  11. #include "../user.h"
  12.  
  13. /*
  14.  * iinit is called once (from main)
  15.  * very early in initialization.
  16.  * It reads the root's super block
  17.  * and initializes the current date
  18.  * from the last modified date.
  19.  *
  20.  * panic: iinit -- cannot read the super
  21.  * block. Usually because of an IO error.
  22.  */
  23. iinit()
  24. {
  25.     register *cp, *bp;
  26.  
  27.     (*bdevsw[rootdev.d_major].d_open)(rootdev, 1);
  28.     bp = bread(rootdev, 1);
  29.     cp = getblk(NODEV);
  30.     if(u.u_error)
  31.         panic("iinit");
  32.     bcopy(bp->b_addr, cp->b_addr, 256);
  33.     brelse(bp);
  34.     mount[0].m_bufp = cp;
  35.     mount[0].m_dev = rootdev;
  36.     cp = cp->b_addr;
  37.     cp->s_flock = 0;
  38.     cp->s_ilock = 0;
  39.     cp->s_ronly = 0;
  40.     time[0] = cp->s_time[0];
  41.     time[1] = cp->s_time[1];
  42. }
  43.  
  44. /*
  45.  * alloc will obtain the next available
  46.  * free disk block from the free list of
  47.  * the specified device.
  48.  * The super block has up to 100 remembered
  49.  * free blocks; the last of these is read to
  50.  * obtain 100 more . . .
  51.  *
  52.  * no space on dev x/y -- when
  53.  * the free list is exhausted.
  54.  */
  55. alloc(dev)
  56. {
  57.     int bno;
  58.     register *bp, *ip, *fp;
  59.  
  60.     fp = getfs(dev);
  61.     while(fp->s_flock)
  62.         sleep(&fp->s_flock, PINOD);
  63.     do {
  64.         if(fp->s_nfree <= 0)
  65.             goto nospace;
  66.         bno = fp->s_free[--fp->s_nfree];
  67.         if(bno == 0)
  68.             goto nospace;
  69.     } while (badblock(fp, bno, dev));
  70.     if(fp->s_nfree <= 0) {
  71.         fp->s_flock++;
  72.         bp = bread(dev, bno);
  73.         ip = bp->b_addr;
  74.         fp->s_nfree = *ip++;
  75.         bcopy(ip, fp->s_free, 100);
  76.         brelse(bp);
  77.         fp->s_flock = 0;
  78.         wakeup(&fp->s_flock);
  79.     }
  80.     bp = getblk(dev, bno);
  81.     clrbuf(bp);
  82.     fp->s_fmod = 1;
  83.     return(bp);
  84.  
  85. nospace:
  86.     fp->s_nfree = 0;
  87.     prdev("no space", dev);
  88.     u.u_error = ENOSPC;
  89.     return(NULL);
  90. }
  91.  
  92. /*
  93.  * place the specified disk block
  94.  * back on the free list of the
  95.  * specified device.
  96.  */
  97. free(dev, bno)
  98. {
  99.     register *fp, *bp, *ip;
  100.  
  101.     fp = getfs(dev);
  102.     fp->s_fmod = 1;
  103.     while(fp->s_flock)
  104.         sleep(&fp->s_flock, PINOD);
  105.     if (badblock(fp, bno, dev))
  106.         return;
  107.     if(fp->s_nfree <= 0) {
  108.         fp->s_nfree = 1;
  109.         fp->s_free[0] = 0;
  110.     }
  111.     if(fp->s_nfree >= 100) {
  112.         fp->s_flock++;
  113.         bp = getblk(dev, bno);
  114.         ip = bp->b_addr;
  115.         *ip++ = fp->s_nfree;
  116.         bcopy(fp->s_free, ip, 100);
  117.         fp->s_nfree = 0;
  118.         bwrite(bp);
  119.         fp->s_flock = 0;
  120.         wakeup(&fp->s_flock);
  121.     }
  122.     fp->s_free[fp->s_nfree++] = bno;
  123.     fp->s_fmod = 1;
  124. }
  125.  
  126. /*
  127.  * Check that a block number is in the
  128.  * range between the I list and the size
  129.  * of the device.
  130.  * This is used mainly to check that a
  131.  * garbage file system has not been mounted.
  132.  *
  133.  * bad block on dev x/y -- not in range
  134.  */
  135. badblock(afp, abn, dev)
  136. {
  137.     register struct filsys *fp;
  138.     register char *bn;
  139.  
  140.     fp = afp;
  141.     bn = abn;
  142.     if (bn < fp->s_isize+2 || bn >= fp->s_fsize) {
  143.         prdev("bad block", dev);
  144.         return(1);
  145.     }
  146.     return(0);
  147. }
  148.  
  149. /*
  150.  * Allocate an unused I node
  151.  * on the specified device.
  152.  * Used with file creation.
  153.  * The algorithm keeps up to
  154.  * 100 spare I nodes in the
  155.  * super block. When this runs out,
  156.  * a linear search through the
  157.  * I list is instituted to pick
  158.  * up 100 more.
  159.  */
  160. ialloc(dev)
  161. {
  162.     register *fp, *bp, *ip;
  163.     int i, j, k, ino;
  164.  
  165.     fp = getfs(dev);
  166.     while(fp->s_ilock)
  167.         sleep(&fp->s_ilock, PINOD);
  168. loop:
  169.     if(fp->s_ninode > 0) {
  170.         ino = fp->s_inode[--fp->s_ninode];
  171.         ip = iget(dev, ino);
  172.         if (ip==NULL)
  173.             return(NULL);
  174.         if(ip->i_mode == 0) {
  175.             for(bp = &ip->i_mode; bp < &ip->i_addr[8];)
  176.                 *bp++ = 0;
  177.             fp->s_fmod = 1;
  178.             return(ip);
  179.         }
  180.         /*
  181.          * Inode was allocated after all.
  182.          * Look some more.
  183.          */
  184.         iput(ip);
  185.         goto loop;
  186.     }
  187.     fp->s_ilock++;
  188.     ino = 0;
  189.     for(i=0; i<fp->s_isize; i++) {
  190.         bp = bread(dev, i+2);
  191.         ip = bp->b_addr;
  192.         for(j=0; j<256; j=+16) {
  193.             ino++;
  194.             if(ip[j] != 0)
  195.                 continue;
  196.             for(k=0; k<NINODE; k++)
  197.             if(dev==inode[k].i_dev && ino==inode[k].i_number)
  198.                 goto cont;
  199.             fp->s_inode[fp->s_ninode++] = ino;
  200.             if(fp->s_ninode >= 100)
  201.                 break;
  202.         cont:;
  203.         }
  204.         brelse(bp);
  205.         if(fp->s_ninode >= 100)
  206.             break;
  207.     }
  208.     fp->s_ilock = 0;
  209.     wakeup(&fp->s_ilock);
  210.     if (fp->s_ninode > 0)
  211.         goto loop;
  212.     prdev("Out of inodes", dev);
  213.     u.u_error = ENOSPC;
  214.     return(NULL);
  215. }
  216.  
  217. /*
  218.  * Free the specified I node
  219.  * on the specified device.
  220.  * The algorithm stores up
  221.  * to 100 I nodes in the super
  222.  * block and throws away any more.
  223.  */
  224. ifree(dev, ino)
  225. {
  226.     register *fp;
  227.  
  228.     fp = getfs(dev);
  229.     if(fp->s_ilock)
  230.         return;
  231.     if(fp->s_ninode >= 100)
  232.         return;
  233.     fp->s_inode[fp->s_ninode++] = ino;
  234.     fp->s_fmod = 1;
  235. }
  236.  
  237. /*
  238.  * getfs maps a device number into
  239.  * a pointer to the incore super
  240.  * block.
  241.  * The algorithm is a linear
  242.  * search through the mount table.
  243.  * A consistency check of the
  244.  * in core free-block and i-node
  245.  * counts.
  246.  *
  247.  * bad count on dev x/y -- the count
  248.  *    check failed. At this point, all
  249.  *    the counts are zeroed which will
  250.  *    almost certainly lead to "no space"
  251.  *    diagnostic
  252.  * panic: no fs -- the device is not mounted.
  253.  *    this "cannot happen"
  254.  */
  255. getfs(dev)
  256. {
  257.     register struct mount *p;
  258.     register char *n1, *n2;
  259.  
  260.     for(p = &mount[0]; p < &mount[NMOUNT]; p++)
  261.     if(p->m_bufp != NULL && p->m_dev == dev) {
  262.         p = p->m_bufp->b_addr;
  263.         n1 = p->s_nfree;
  264.         n2 = p->s_ninode;
  265.         if(n1 > 100 || n2 > 100) {
  266.             prdev("bad count", dev);
  267.             p->s_nfree = 0;
  268.             p->s_ninode = 0;
  269.         }
  270.         return(p);
  271.     }
  272.     panic("no fs");
  273. }
  274.  
  275. /*
  276.  * update is the internal name of
  277.  * 'sync'. It goes through the disk
  278.  * queues to initiate sandbagged IO;
  279.  * goes through the I nodes to write
  280.  * modified nodes; and it goes through
  281.  * the mount table to initiate modified
  282.  * super blocks.
  283.  */
  284. update()
  285. {
  286.     register struct inode *ip;
  287.     register struct mount *mp;
  288.     register *bp;
  289.  
  290.     if(updlock)
  291.         return;
  292.     updlock++;
  293.     for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
  294.         if(mp->m_bufp != NULL) {
  295.             ip = mp->m_bufp->b_addr;
  296.             if(ip->s_fmod==0 || ip->s_ilock!=0 ||
  297.                ip->s_flock!=0 || ip->s_ronly!=0)
  298.                 continue;
  299.             bp = getblk(mp->m_dev, 1);
  300.             ip->s_fmod = 0;
  301.             ip->s_time[0] = time[0];
  302.             ip->s_time[1] = time[1];
  303.             bcopy(ip, bp->b_addr, 256);
  304.             bwrite(bp);
  305.         }
  306.     for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
  307.         if((ip->i_flag&ILOCK) == 0) {
  308.             ip->i_flag =| ILOCK;
  309.             iupdat(ip, time);
  310.             prele(ip);
  311.         }
  312.     updlock = 0;
  313.     bflush(NODEV);
  314. }
  315.