home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / sys / dev / bio.c next >
Encoding:
C/C++ Source or Header  |  1998-02-03  |  11.0 KB  |  565 lines

  1. #include "../h/param.h"
  2. #include "../h/systm.h"
  3. #include "../h/dir.h"
  4. #include "../h/user.h"
  5. #include "../h/buf.h"
  6. #include "../h/conf.h"
  7. #include "../h/proc.h"
  8. #include "../h/seg.h"
  9.  
  10. #define    DISKMON    1
  11.  
  12. #ifdef    DISKMON
  13. struct {
  14.     int    nbuf;
  15.     long    nread;
  16.     long    nreada;
  17.     long    ncache;
  18.     long    nwrite;
  19.     long    bufcount[NBUF];
  20. } io_info;
  21. #endif
  22.  
  23. /*
  24.  * swap IO headers.
  25.  * they are filled in to point
  26.  * at the desired IO operation.
  27.  */
  28. struct    buf    swbuf1;
  29. struct    buf    swbuf2;
  30.  
  31. /*
  32.  * The following several routines allocate and free
  33.  * buffers with various side effects.  In general the
  34.  * arguments to an allocate routine are a device and
  35.  * a block number, and the value is a pointer to
  36.  * to the buffer header; the buffer is marked "busy"
  37.  * so that no one else can touch it.  If the block was
  38.  * already in core, no I/O need be done; if it is
  39.  * already busy, the process waits until it becomes free.
  40.  * The following routines allocate a buffer:
  41.  *    getblk
  42.  *    bread
  43.  *    breada
  44.  * Eventually the buffer must be released, possibly with the
  45.  * side effect of writing it out, by using one of
  46.  *    bwrite
  47.  *    bdwrite
  48.  *    bawrite
  49.  *    brelse
  50.  */
  51.  
  52. /*
  53.  * Read in (if necessary) the block and return a buffer pointer.
  54.  */
  55. struct buf *
  56. bread(dev, blkno)
  57. dev_t dev;
  58. daddr_t blkno;
  59. {
  60.     register struct buf *bp;
  61.  
  62.     bp = getblk(dev, blkno);
  63.     if (bp->b_flags&B_DONE) {
  64. #ifdef    DISKMON
  65.         io_info.ncache++;
  66. #endif
  67.         return(bp);
  68.     }
  69.     bp->b_flags |= B_READ;
  70.     bp->b_bcount = BSIZE;
  71.     (*bdevsw[major(dev)].d_strategy)(bp);
  72. #ifdef    DISKMON
  73.     io_info.nread++;
  74. #endif
  75.     iowait(bp);
  76.     return(bp);
  77. }
  78.  
  79. /*
  80.  * Read in the block, like bread, but also start I/O on the
  81.  * read-ahead block (which is not allocated to the caller)
  82.  */
  83. struct buf *
  84. breada(dev, blkno, rablkno)
  85. dev_t dev;
  86. daddr_t blkno, rablkno;
  87. {
  88.     register struct buf *bp, *rabp;
  89.  
  90.     bp = NULL;
  91.     if (!incore(dev, blkno)) {
  92.         bp = getblk(dev, blkno);
  93.         if ((bp->b_flags&B_DONE) == 0) {
  94.             bp->b_flags |= B_READ;
  95.             bp->b_bcount = BSIZE;
  96.             (*bdevsw[major(dev)].d_strategy)(bp);
  97. #ifdef    DISKMON
  98.             io_info.nread++;
  99. #endif
  100.         }
  101.     }
  102.     if (rablkno && !incore(dev, rablkno)) {
  103.         rabp = getblk(dev, rablkno);
  104.         if (rabp->b_flags & B_DONE)
  105.             brelse(rabp);
  106.         else {
  107.             rabp->b_flags |= B_READ|B_ASYNC;
  108.             rabp->b_bcount = BSIZE;
  109.             (*bdevsw[major(dev)].d_strategy)(rabp);
  110. #ifdef    DISKMON
  111.             io_info.nreada++;
  112. #endif
  113.         }
  114.     }
  115.     if(bp == NULL)
  116.         return(bread(dev, blkno));
  117.     iowait(bp);
  118.     return(bp);
  119. }
  120.  
  121. /*
  122.  * Write the buffer, waiting for completion.
  123.  * Then release the buffer.
  124.  */
  125. bwrite(bp)
  126. register struct buf *bp;
  127. {
  128.     register flag;
  129.  
  130.     flag = bp->b_flags;
  131.     bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI | B_AGE);
  132.     bp->b_bcount = BSIZE;
  133. #ifdef    DISKMON
  134.     io_info.nwrite++;
  135. #endif
  136.     (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
  137.     if ((flag&B_ASYNC) == 0) {
  138.         iowait(bp);
  139.         brelse(bp);
  140.     } else if (flag & B_DELWRI)
  141.         bp->b_flags |= B_AGE;
  142.     else
  143.         geterror(bp);
  144. }
  145.  
  146. /*
  147.  * Release the buffer, marking it so that if it is grabbed
  148.  * for another purpose it will be written out before being
  149.  * given up (e.g. when writing a partial block where it is
  150.  * assumed that another write for the same block will soon follow).
  151.  * This can't be done for magtape, since writes must be done
  152.  * in the same order as requested.
  153.  */
  154. bdwrite(bp)
  155. register struct buf *bp;
  156. {
  157.     register struct buf *dp;
  158.  
  159.     dp = bdevsw[major(bp->b_dev)].d_tab;
  160.     if(dp->b_flags & B_TAPE)
  161.         bawrite(bp);
  162.     else {
  163.         bp->b_flags |= B_DELWRI | B_DONE;
  164.         brelse(bp);
  165.     }
  166. }
  167.  
  168. /*
  169.  * Release the buffer, start I/O on it, but don't wait for completion.
  170.  */
  171. bawrite(bp)
  172. register struct buf *bp;
  173. {
  174.  
  175.     bp->b_flags |= B_ASYNC;
  176.     bwrite(bp);
  177. }
  178.  
  179. /*
  180.  * release the buffer, with no I/O implied.
  181.  */
  182. brelse(bp)
  183. register struct buf *bp;
  184. {
  185.     register struct buf **backp;
  186.     register s;
  187.  
  188.     if (bp->b_flags&B_WANTED)
  189.         wakeup((caddr_t)bp);
  190.     if (bfreelist.b_flags&B_WANTED) {
  191.         bfreelist.b_flags &= ~B_WANTED;
  192.         wakeup((caddr_t)&bfreelist);
  193.     }
  194.     if (bp->b_flags&B_ERROR)
  195.         bp->b_dev = NODEV;  /* no assoc. on error */
  196.     s = spl6();
  197.     if(bp->b_flags & B_AGE) {
  198.         backp = &bfreelist.av_forw;
  199.         (*backp)->av_back = bp;
  200.         bp->av_forw = *backp;
  201.         *backp = bp;
  202.         bp->av_back = &bfreelist;
  203.     } else {
  204.         backp = &bfreelist.av_back;
  205.         (*backp)->av_forw = bp;
  206.         bp->av_back = *backp;
  207.         *backp = bp;
  208.         bp->av_forw = &bfreelist;
  209.     }
  210.     bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE);
  211.     splx(s);
  212. }
  213.  
  214. /*
  215.  * See if the block is associated with some buffer
  216.  * (mainly to avoid getting hung up on a wait in breada)
  217.  */
  218. incore(dev, blkno)
  219. dev_t dev;
  220. daddr_t blkno;
  221. {
  222.     register struct buf *bp;
  223.     register struct buf *dp;
  224.  
  225.     dp = bdevsw[major(dev)].d_tab;
  226.     for (bp=dp->b_forw; bp != dp; bp = bp->b_forw)
  227.         if (bp->b_blkno==blkno && bp->b_dev==dev)
  228.             return(1);
  229.     return(0);
  230. }
  231.  
  232. /*
  233.  * Assign a buffer for the given block.  If the appropriate
  234.  * block is already associated, return it; otherwise search
  235.  * for the oldest non-busy buffer and reassign it.
  236.  */
  237. struct buf *
  238. getblk(dev, blkno)
  239. dev_t dev;
  240. daddr_t blkno;
  241. {
  242.     register struct buf *bp;
  243.     register struct buf *dp;
  244. #ifdef    DISKMON
  245.     register i;
  246. #endif
  247.  
  248.     if(major(dev) >= nblkdev)
  249.         panic("blkdev");
  250.  
  251.     loop:
  252.     spl0();
  253.     dp = bdevsw[major(dev)].d_tab;
  254.     if(dp == NULL)
  255.         panic("devtab");
  256.     for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) {
  257.         if (bp->b_blkno!=blkno || bp->b_dev!=dev)
  258.             continue;
  259.         spl6();
  260.         if (bp->b_flags&B_BUSY) {
  261.             bp->b_flags |= B_WANTED;
  262.             sleep((caddr_t)bp, PRIBIO+1);
  263.             goto loop;
  264.         }
  265.         spl0();
  266. #ifdef    DISKMON
  267.         i = 0;
  268.         dp = bp->av_forw;
  269.         while (dp != &bfreelist) {
  270.             i++;
  271.             dp = dp->av_forw;
  272.         }
  273.         if (i<NBUF)
  274.             io_info.bufcount[i]++;
  275. #endif
  276.         notavail(bp);
  277.         return(bp);
  278.     }
  279.     spl6();
  280.     if (bfreelist.av_forw == &bfreelist) {
  281.         bfreelist.b_flags |= B_WANTED;
  282.         sleep((caddr_t)&bfreelist, PRIBIO+1);
  283.         goto loop;
  284.     }
  285.     spl0();
  286.     notavail(bp = bfreelist.av_forw);
  287.     if (bp->b_flags & B_DELWRI) {
  288.         bp->b_flags |= B_ASYNC;
  289.         bwrite(bp);
  290.         goto loop;
  291.     }
  292.     bp->b_flags = B_BUSY;
  293.     bp->b_back->b_forw = bp->b_forw;
  294.     bp->b_forw->b_back = bp->b_back;
  295.     bp->b_forw = dp->b_forw;
  296.     bp->b_back = dp;
  297.     dp->b_forw->b_back = bp;
  298.     dp->b_forw = bp;
  299.     bp->b_dev = dev;
  300.     bp->b_blkno = blkno;
  301.     return(bp);
  302. }
  303.  
  304. /*
  305.  * get an empty block,
  306.  * not assigned to any particular device
  307.  */
  308. struct buf *
  309. geteblk()
  310. {
  311.     register struct buf *bp;
  312.     register struct buf *dp;
  313.  
  314. loop:
  315.     spl6();
  316.     while (bfreelist.av_forw == &bfreelist) {
  317.         bfreelist.b_flags |= B_WANTED;
  318.         sleep((caddr_t)&bfreelist, PRIBIO+1);
  319.     }
  320.     spl0();
  321.     dp = &bfreelist;
  322.     notavail(bp = bfreelist.av_forw);
  323.     if (bp->b_flags & B_DELWRI) {
  324.         bp->b_flags |= B_ASYNC;
  325.         bwrite(bp);
  326.         goto loop;
  327.     }
  328.     bp->b_flags = B_BUSY;
  329.     bp->b_back->b_forw = bp->b_forw;
  330.     bp->b_forw->b_back = bp->b_back;
  331.     bp->b_forw = dp->b_forw;
  332.     bp->b_back = dp;
  333.     dp->b_forw->b_back = bp;
  334.     dp->b_forw = bp;
  335.     bp->b_dev = (dev_t)NODEV;
  336.     return(bp);
  337. }
  338.  
  339. /*
  340.  * Wait for I/O completion on the buffer; return errors
  341.  * to the user.
  342.  */
  343. iowait(bp)
  344. register struct buf *bp;
  345. {
  346.  
  347.     spl6();
  348.     while ((bp->b_flags&B_DONE)==0)
  349.         sleep((caddr_t)bp, PRIBIO);
  350.     spl0();
  351.     geterror(bp);
  352. }
  353.  
  354. /*
  355.  * Unlink a buffer from the available list and mark it busy.
  356.  * (internal interface)
  357.  */
  358. notavail(bp)
  359. register struct buf *bp;
  360. {
  361.     register s;
  362.  
  363.     s = spl6();
  364.     bp->av_back->av_forw = bp->av_forw;
  365.     bp->av_forw->av_back = bp->av_back;
  366.     bp->b_flags |= B_BUSY;
  367.     splx(s);
  368. }
  369.  
  370. /*
  371.  * Mark I/O complete on a buffer, release it if I/O is asynchronous,
  372.  * and wake up anyone waiting for it.
  373.  */
  374. iodone(bp)
  375. register struct buf *bp;
  376. {
  377.  
  378.     if(bp->b_flags&B_MAP)
  379.         mapfree(bp);
  380.     bp->b_flags |= B_DONE;
  381.     if (bp->b_flags&B_ASYNC)
  382.         brelse(bp);
  383.     else {
  384.         bp->b_flags &= ~B_WANTED;
  385.         wakeup((caddr_t)bp);
  386.     }
  387. }
  388.  
  389. /*
  390.  * Zero the core associated with a buffer.
  391.  */
  392. clrbuf(bp)
  393. struct buf *bp;
  394. {
  395.     register *p;
  396.     register c;
  397.  
  398.     p = bp->b_un.b_words;
  399.     c = BSIZE/sizeof(int);
  400.     do
  401.         *p++ = 0;
  402.     while (--c);
  403.     bp->b_resid = 0;
  404. }
  405.  
  406. /*
  407.  * swap I/O
  408.  */
  409. swap(blkno, coreaddr, count, rdflg)
  410. register count;
  411. {
  412.     register struct buf *bp;
  413.     register tcount;
  414.  
  415.     bp = &swbuf1;
  416.     if(bp->b_flags & B_BUSY)
  417.         if((swbuf2.b_flags&B_WANTED) == 0)
  418.             bp = &swbuf2;
  419.     spl6();
  420.     while (bp->b_flags&B_BUSY) {
  421.         bp->b_flags |= B_WANTED;
  422.         sleep((caddr_t)bp, PSWP+1);
  423.     }
  424.     while (count) {
  425.         bp->b_flags = B_BUSY | B_PHYS | rdflg;
  426.         bp->b_dev = swapdev;
  427.         tcount = count;
  428.         if (tcount >= 01700)    /* prevent byte-count wrap */
  429.             tcount = 01700;
  430.         bp->b_bcount = ctob(tcount);
  431.         bp->b_blkno = swplo+blkno;
  432.         bp->b_un.b_addr = (caddr_t)(coreaddr<<6);
  433.         bp->b_xmem = (coreaddr>>10) & 077;
  434.         (*bdevsw[major(swapdev)].d_strategy)(bp);
  435.         spl6();
  436.         while((bp->b_flags&B_DONE)==0)
  437.             sleep((caddr_t)bp, PSWP);
  438.         count -= tcount;
  439.         coreaddr += tcount;
  440.         blkno += ctod(tcount);
  441.     }
  442.     if (bp->b_flags&B_WANTED)
  443.         wakeup((caddr_t)bp);
  444.     spl0();
  445.     bp->b_flags &= ~(B_BUSY|B_WANTED);
  446.     if (bp->b_flags & B_ERROR)
  447.         panic("IO err in swap");
  448. }
  449.  
  450. /*
  451.  * make sure all write-behind blocks
  452.  * on dev (or NODEV for all)
  453.  * are flushed out.
  454.  * (from umount and update)
  455.  */
  456. bflush(dev)
  457. dev_t dev;
  458. {
  459.     register struct buf *bp;
  460.  
  461. loop:
  462.     spl6();
  463.     for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) {
  464.         if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) {
  465.             bp->b_flags |= B_ASYNC;
  466.             notavail(bp);
  467.             bwrite(bp);
  468.             goto loop;
  469.         }
  470.     }
  471.     spl0();
  472. }
  473.  
  474. /*
  475.  * Raw I/O. The arguments are
  476.  *    The strategy routine for the device
  477.  *    A buffer, which will always be a special buffer
  478.  *      header owned exclusively by the device for this purpose
  479.  *    The device number
  480.  *    Read/write flag
  481.  * Essentially all the work is computing physical addresses and
  482.  * validating them.
  483.  */
  484. physio(strat, bp, dev, rw)
  485. register struct buf *bp;
  486. int (*strat)();
  487. {
  488.     register unsigned base;
  489.     register int nb;
  490.     int ts;
  491.  
  492.     base = (unsigned)u.u_base;
  493.     /*
  494.      * Check odd base, odd count, and address wraparound
  495.      */
  496.     if (base&01 || u.u_count&01 || base>=base+u.u_count)
  497.         goto bad;
  498.     ts = (u.u_tsize+127) & ~0177;
  499.     if (u.u_sep)
  500.         ts = 0;
  501.     nb = (base>>6) & 01777;
  502.     /*
  503.      * Check overlap with text. (ts and nb now
  504.      * in 64-byte clicks)
  505.      */
  506.     if (nb < ts)
  507.         goto bad;
  508.     /*
  509.      * Check that transfer is either entirely in the
  510.      * data or in the stack: that is, either
  511.      * the end is in the data or the start is in the stack
  512.      * (remember wraparound was already checked).
  513.      */
  514.     if ((((base+u.u_count)>>6)&01777) >= ts+u.u_dsize
  515.         && nb < 1024-u.u_ssize)
  516.         goto bad;
  517.     spl6();
  518.     while (bp->b_flags&B_BUSY) {
  519.         bp->b_flags |= B_WANTED;
  520.         sleep((caddr_t)bp, PRIBIO+1);
  521.     }
  522.     bp->b_flags = B_BUSY | B_PHYS | rw;
  523.     bp->b_dev = dev;
  524.     /*
  525.      * Compute physical address by simulating
  526.      * the segmentation hardware.
  527.      */
  528.     ts = (u.u_sep? UDSA: UISA)->r[nb>>7] + (nb&0177);
  529.     bp->b_un.b_addr = (caddr_t)((ts<<6) + (base&077));
  530.     bp->b_xmem = (ts>>10) & 077;
  531.     bp->b_blkno = u.u_offset >> BSHIFT;
  532.     bp->b_bcount = u.u_count;
  533.     bp->b_error = 0;
  534.     u.u_procp->p_flag |= SLOCK;
  535.     (*strat)(bp);
  536.     spl6();
  537.     while ((bp->b_flags&B_DONE) == 0)
  538.         sleep((caddr_t)bp, PRIBIO);
  539.     u.u_procp->p_flag &= ~SLOCK;
  540.     if (bp->b_flags&B_WANTED)
  541.         wakeup((caddr_t)bp);
  542.     spl0();
  543.     bp->b_flags &= ~(B_BUSY|B_WANTED);
  544.     u.u_count = bp->b_resid;
  545.     geterror(bp);
  546.     return;
  547.     bad:
  548.     u.u_error = EFAULT;
  549. }
  550.  
  551. /*
  552.  * Pick up the device's error number and pass it to the user;
  553.  * if there is an error but the number is 0 set a generalized
  554.  * code.  Actually the latter is always true because devices
  555.  * don't yet return specific errors.
  556.  */
  557. geterror(bp)
  558. register struct buf *bp;
  559. {
  560.  
  561.     if (bp->b_flags&B_ERROR)
  562.         if ((u.u_error = bp->b_error)==0)
  563.             u.u_error = EIO;
  564. }
  565.