05650 #include "../h/param.h" 05651 #include "../h/systm.h" 05652 #include "../h/dir.h" 05653 #include "../h/user.h" 05654 #include "../h/buf.h" 05655 #include "../h/conf.h" 05656 #include "../h/proc.h" 05657 #include "../h/seg.h" 05658 05659 #define DISKMON 1 05660 05661 #ifdef DISKMON 05662 struct { 05663 int nbuf; 05664 long nread; 05665 long nreada; 05666 long ncache; 05667 long nwrite; 05668 long bufcount[NBUF]; 05669 } io_info; 05670 #endif 05671 05672 /* 05673 * swap IO headers. 05674 * they are filled in to point 05675 * at the desired IO operation. 05676 */ 05677 struct buf swbuf1; 05678 struct buf swbuf2; 05679 05680 /* 05681 * The following several routines allocate and free 05682 * buffers with various side effects. In general the 05683 * arguments to an allocate routine are a device and 05684 * a block number, and the value is a pointer to 05685 * to the buffer header; the buffer is marked "busy" 05686 * so that no one else can touch it. If the block was 05687 * already in core, no I/O need be done; if it is 05688 * already busy, the process waits until it becomes free. 05689 * The following routines allocate a buffer: 05690 * getblk 05691 * bread 05692 * breada 05693 * Eventually the buffer must be released, possibly with the 05694 * side effect of writing it out, by using one of 05695 * bwrite 05696 * bdwrite 05697 * bawrite 05698 * brelse 05699 */ 05700 05701 /* 05702 * Read in (if necessary) the block and return a buffer pointer. 05703 */ 05704 struct buf * 05705 bread(dev, blkno) 05706 dev_t dev; 05707 daddr_t blkno; 05708 { 05709 register struct buf *bp; 05710 05711 bp = getblk(dev, blkno); 05712 if (bp->b_flags&B_DONE) { 05713 #ifdef DISKMON 05714 io_info.ncache++; 05715 #endif 05716 return(bp); 05717 } 05718 bp->b_flags |= B_READ; 05719 bp->b_bcount = BSIZE; 05720 (*bdevsw[major(dev)].d_strategy)(bp); 05721 #ifdef DISKMON 05722 io_info.nread++; 05723 #endif 05724 iowait(bp); 05725 return(bp); 05726 } 05727 05728 /* 05729 * Read in the block, like bread, but also start I/O on the 05730 * read-ahead block (which is not allocated to the caller) 05731 */ 05732 struct buf * 05733 breada(dev, blkno, rablkno) 05734 dev_t dev; 05735 daddr_t blkno, rablkno; 05736 { 05737 register struct buf *bp, *rabp; 05738 05739 bp = NULL; 05740 if (!incore(dev, blkno)) { 05741 bp = getblk(dev, blkno); 05742 if ((bp->b_flags&B_DONE) == 0) { 05743 bp->b_flags |= B_READ; 05744 bp->b_bcount = BSIZE; 05745 (*bdevsw[major(dev)].d_strategy)(bp); 05746 #ifdef DISKMON 05747 io_info.nread++; 05748 #endif 05749 } 05750 } 05751 if (rablkno && !incore(dev, rablkno)) { 05752 rabp = getblk(dev, rablkno); 05753 if (rabp->b_flags & B_DONE) 05754 brelse(rabp); 05755 else { 05756 rabp->b_flags |= B_READ|B_ASYNC; 05757 rabp->b_bcount = BSIZE; 05758 (*bdevsw[major(dev)].d_strategy)(rabp); 05759 #ifdef DISKMON 05760 io_info.nreada++; 05761 #endif 05762 } 05763 } 05764 if(bp == NULL) 05765 return(bread(dev, blkno)); 05766 iowait(bp); 05767 return(bp); 05768 } 05769 05770 /* 05771 * Write the buffer, waiting for completion. 05772 * Then release the buffer. 05773 */ 05774 bwrite(bp) 05775 register struct buf *bp; 05776 { 05777 register flag; 05778 05779 flag = bp->b_flags; 05780 bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI | B_AGE); 05781 bp->b_bcount = BSIZE; 05782 #ifdef DISKMON 05783 io_info.nwrite++; 05784 #endif 05785 (*bdevsw[major(bp->b_dev)].d_strategy)(bp); 05786 if ((flag&B_ASYNC) == 0) { 05787 iowait(bp); 05788 brelse(bp); 05789 } else if (flag & B_DELWRI) 05790 bp->b_flags |= B_AGE; 05791 else 05792 geterror(bp); 05793 } 05794 05795 /* 05796 * Release the buffer, marking it so that if it is grabbed 05797 * for another purpose it will be written out before being 05798 * given up (e.g. when writing a partial block where it is 05799 * assumed that another write for the same block will soon follow). 05800 * This can't be done for magtape, since writes must be done 05801 * in the same order as requested. 05802 */ 05803 bdwrite(bp) 05804 register struct buf *bp; 05805 { 05806 register struct buf *dp; 05807 05808 dp = bdevsw[major(bp->b_dev)].d_tab; 05809 if(dp->b_flags & B_TAPE) 05810 bawrite(bp); 05811 else { 05812 bp->b_flags |= B_DELWRI | B_DONE; 05813 brelse(bp); 05814 } 05815 } 05816 05817 /* 05818 * Release the buffer, start I/O on it, but don't wait for completion. 05819 */ 05820 bawrite(bp) 05821 register struct buf *bp; 05822 { 05823 05824 bp->b_flags |= B_ASYNC; 05825 bwrite(bp); 05826 } 05827 05828 /* 05829 * release the buffer, with no I/O implied. 05830 */ 05831 brelse(bp) 05832 register struct buf *bp; 05833 { 05834 register struct buf **backp; 05835 register s; 05836 05837 if (bp->b_flags&B_WANTED) 05838 wakeup((caddr_t)bp); 05839 if (bfreelist.b_flags&B_WANTED) { 05840 bfreelist.b_flags &= ~B_WANTED; 05841 wakeup((caddr_t)&bfreelist); 05842 } 05843 if (bp->b_flags&B_ERROR) 05844 bp->b_dev = NODEV; /* no assoc. on error */ 05845 s = spl6(); 05846 if(bp->b_flags & B_AGE) { 05847 backp = &bfreelist.av_forw; 05848 (*backp)->av_back = bp; 05849 bp->av_forw = *backp; 05850 *backp = bp; 05851 bp->av_back = &bfreelist; 05852 } else { 05853 backp = &bfreelist.av_back; 05854 (*backp)->av_forw = bp; 05855 bp->av_back = *backp; 05856 *backp = bp; 05857 bp->av_forw = &bfreelist; 05858 } 05859 bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE); 05860 splx(s); 05861 } 05862 05863 /* 05864 * See if the block is associated with some buffer 05865 * (mainly to avoid getting hung up on a wait in breada) 05866 */ 05867 incore(dev, blkno) 05868 dev_t dev; 05869 daddr_t blkno; 05870 { 05871 register struct buf *bp; 05872 register struct buf *dp; 05873 05874 dp = bdevsw[major(dev)].d_tab; 05875 for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) 05876 if (bp->b_blkno==blkno && bp->b_dev==dev) 05877 return(1); 05878 return(0); 05879 } 05880 05881 /* 05882 * Assign a buffer for the given block. If the appropriate 05883 * block is already associated, return it; otherwise search 05884 * for the oldest non-busy buffer and reassign it. 05885 */ 05886 struct buf * 05887 getblk(dev, blkno) 05888 dev_t dev; 05889 daddr_t blkno; 05890 { 05891 register struct buf *bp; 05892 register struct buf *dp; 05893 #ifdef DISKMON 05894 register i; 05895 #endif 05896 05897 if(major(dev) >= nblkdev) 05898 panic("blkdev"); 05899 05900 loop: 05901 spl0(); 05902 dp = bdevsw[major(dev)].d_tab; 05903 if(dp == NULL) 05904 panic("devtab"); 05905 for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) { 05906 if (bp->b_blkno!=blkno || bp->b_dev!=dev) 05907 continue; 05908 spl6(); 05909 if (bp->b_flags&B_BUSY) { 05910 bp->b_flags |= B_WANTED; 05911 sleep((caddr_t)bp, PRIBIO+1); 05912 goto loop; 05913 } 05914 spl0(); 05915 #ifdef DISKMON 05916 i = 0; 05917 dp = bp->av_forw; 05918 while (dp != &bfreelist) { 05919 i++; 05920 dp = dp->av_forw; 05921 } 05922 if (i05923 io_info.bufcount[i]++; 05924 #endif 05925 notavail(bp); 05926 return(bp); 05927 } 05928 spl6(); 05929 if (bfreelist.av_forw == &bfreelist) { 05930 bfreelist.b_flags |= B_WANTED; 05931 sleep((caddr_t)&bfreelist, PRIBIO+1); 05932 goto loop; 05933 } 05934 spl0(); 05935 notavail(bp = bfreelist.av_forw); 05936 if (bp->b_flags & B_DELWRI) { 05937 bp->b_flags |= B_ASYNC; 05938 bwrite(bp); 05939 goto loop; 05940 } 05941 bp->b_flags = B_BUSY; 05942 bp->b_back->b_forw = bp->b_forw; 05943 bp->b_forw->b_back = bp->b_back; 05944 bp->b_forw = dp->b_forw; 05945 bp->b_back = dp; 05946 dp->b_forw->b_back = bp; 05947 dp->b_forw = bp; 05948 bp->b_dev = dev; 05949 bp->b_blkno = blkno; 05950 return(bp); 05951 } 05952 05953 /* 05954 * get an empty block, 05955 * not assigned to any particular device 05956 */ 05957 struct buf * 05958 geteblk() 05959 { 05960 register struct buf *bp; 05961 register struct buf *dp; 05962 05963 loop: 05964 spl6(); 05965 while (bfreelist.av_forw == &bfreelist) { 05966 bfreelist.b_flags |= B_WANTED; 05967 sleep((caddr_t)&bfreelist, PRIBIO+1); 05968 } 05969 spl0(); 05970 dp = &bfreelist; 05971 notavail(bp = bfreelist.av_forw); 05972 if (bp->b_flags & B_DELWRI) { 05973 bp->b_flags |= B_ASYNC; 05974 bwrite(bp); 05975 goto loop; 05976 } 05977 bp->b_flags = B_BUSY; 05978 bp->b_back->b_forw = bp->b_forw; 05979 bp->b_forw->b_back = bp->b_back; 05980 bp->b_forw = dp->b_forw; 05981 bp->b_back = dp; 05982 dp->b_forw->b_back = bp; 05983 dp->b_forw = bp; 05984 bp->b_dev = (dev_t)NODEV; 05985 return(bp); 05986 } 05987 05988 /* 05989 * Wait for I/O completion on the buffer; return errors 05990 * to the user. 05991 */ 05992 iowait(bp) 05993 register struct buf *bp; 05994 { 05995 05996 spl6(); 05997 while ((bp->b_flags&B_DONE)==0) 05998 sleep((caddr_t)bp, PRIBIO); 05999 spl0(); 06000 geterror(bp); 06001 } 06002 06003 /* 06004 * Unlink a buffer from the available list and mark it busy. 06005 * (internal interface) 06006 */ 06007 notavail(bp) 06008 register struct buf *bp; 06009 { 06010 register s; 06011 06012 s = spl6(); 06013 bp->av_back->av_forw = bp->av_forw; 06014 bp->av_forw->av_back = bp->av_back; 06015 bp->b_flags |= B_BUSY; 06016 splx(s); 06017 } 06018 06019 /* 06020 * Mark I/O complete on a buffer, release it if I/O is asynchronous, 06021 * and wake up anyone waiting for it. 06022 */ 06023 iodone(bp) 06024 register struct buf *bp; 06025 { 06026 06027 if(bp->b_flags&B_MAP) 06028 mapfree(bp); 06029 bp->b_flags |= B_DONE; 06030 if (bp->b_flags&B_ASYNC) 06031 brelse(bp); 06032 else { 06033 bp->b_flags &= ~B_WANTED; 06034 wakeup((caddr_t)bp); 06035 } 06036 } 06037 06038 /* 06039 * Zero the core associated with a buffer. 06040 */ 06041 clrbuf(bp) 06042 struct buf *bp; 06043 { 06044 register *p; 06045 register c; 06046 06047 p = bp->b_un.b_words; 06048 c = BSIZE/sizeof(int); 06049 do 06050 *p++ = 0; 06051 while (--c); 06052 bp->b_resid = 0; 06053 } 06054 06055 /* 06056 * swap I/O 06057 */ 06058 swap(blkno, coreaddr, count, rdflg) 06059 register count; 06060 { 06061 register struct buf *bp; 06062 register tcount; 06063 06064 bp = &swbuf1; 06065 if(bp->b_flags & B_BUSY) 06066 if((swbuf2.b_flags&B_WANTED) == 0) 06067 bp = &swbuf2; 06068 spl6(); 06069 while (bp->b_flags&B_BUSY) { 06070 bp->b_flags |= B_WANTED; 06071 sleep((caddr_t)bp, PSWP+1); 06072 } 06073 while (count) { 06074 bp->b_flags = B_BUSY | B_PHYS | rdflg; 06075 bp->b_dev = swapdev; 06076 tcount = count; 06077 if (tcount >= 01700) /* prevent byte-count wrap */ 06078 tcount = 01700; 06079 bp->b_bcount = ctob(tcount); 06080 bp->b_blkno = swplo+blkno; 06081 bp->b_un.b_addr = (caddr_t)(coreaddr<<6); 06082 bp->b_xmem = (coreaddr>>10) & 077; 06083 (*bdevsw[major(swapdev)].d_strategy)(bp); 06084 spl6(); 06085 while((bp->b_flags&B_DONE)==0) 06086 sleep((caddr_t)bp, PSWP); 06087 count -= tcount; 06088 coreaddr += tcount; 06089 blkno += ctod(tcount); 06090 } 06091 if (bp->b_flags&B_WANTED) 06092 wakeup((caddr_t)bp); 06093 spl0(); 06094 bp->b_flags &= ~(B_BUSY|B_WANTED); 06095 if (bp->b_flags & B_ERROR) 06096 panic("IO err in swap"); 06097 } 06098 06099 /* 06100 * make sure all write-behind blocks 06101 * on dev (or NODEV for all) 06102 * are flushed out. 06103 * (from umount and update) 06104 */ 06105 bflush(dev) 06106 dev_t dev; 06107 { 06108 register struct buf *bp; 06109 06110 loop: 06111 spl6(); 06112 for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) { 06113 if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) { 06114 bp->b_flags |= B_ASYNC; 06115 notavail(bp); 06116 bwrite(bp); 06117 goto loop; 06118 } 06119 } 06120 spl0(); 06121 } 06122 06123 /* 06124 * Raw I/O. The arguments are 06125 * The strategy routine for the device 06126 * A buffer, which will always be a special buffer 06127 * header owned exclusively by the device for this purpose 06128 * The device number 06129 * Read/write flag 06130 * Essentially all the work is computing physical addresses and 06131 * validating them. 06132 */ 06133 physio(strat, bp, dev, rw) 06134 register struct buf *bp; 06135 int (*strat)(); 06136 { 06137 register unsigned base; 06138 register int nb; 06139 int ts; 06140 06141 base = (unsigned)u.u_base; 06142 /* 06143 * Check odd base, odd count, and address wraparound 06144 */ 06145 if (base&01 || u.u_count&01 || base>=base+u.u_count) 06146 goto bad; 06147 ts = (u.u_tsize+127) & ~0177; 06148 if (u.u_sep) 06149 ts = 0; 06150 nb = (base>>6) & 01777; 06151 /* 06152 * Check overlap with text. (ts and nb now 06153 * in 64-byte clicks) 06154 */ 06155 if (nb < ts) 06156 goto bad; 06157 /* 06158 * Check that transfer is either entirely in the 06159 * data or in the stack: that is, either 06160 * the end is in the data or the start is in the stack 06161 * (remember wraparound was already checked). 06162 */ 06163 if ((((base+u.u_count)>>6)&01777) >= ts+u.u_dsize 06164 && nb < 1024-u.u_ssize) 06165 goto bad; 06166 spl6(); 06167 while (bp->b_flags&B_BUSY) { 06168 bp->b_flags |= B_WANTED; 06169 sleep((caddr_t)bp, PRIBIO+1); 06170 } 06171 bp->b_flags = B_BUSY | B_PHYS | rw; 06172 bp->b_dev = dev; 06173 /* 06174 * Compute physical address by simulating 06175 * the segmentation hardware. 06176 */ 06177 ts = (u.u_sep? UDSA: UISA)->r[nb>>7] + (nb&0177); 06178 bp->b_un.b_addr = (caddr_t)((ts<<6) + (base&077)); 06179 bp->b_xmem = (ts>>10) & 077; 06180 bp->b_blkno = u.u_offset >> BSHIFT; 06181 bp->b_bcount = u.u_count; 06182 bp->b_error = 0; 06183 u.u_procp->p_flag |= SLOCK; 06184 (*strat)(bp); 06185 spl6(); 06186 while ((bp->b_flags&B_DONE) == 0) 06187 sleep((caddr_t)bp, PRIBIO); 06188 u.u_procp->p_flag &= ~SLOCK; 06189 if (bp->b_flags&B_WANTED) 06190 wakeup((caddr_t)bp); 06191 spl0(); 06192 bp->b_flags &= ~(B_BUSY|B_WANTED); 06193 u.u_count = bp->b_resid; 06194 geterror(bp); 06195 return; 06196 bad: 06197 u.u_error = EFAULT; 06198 } 06199 06200 /* 06201 * Pick up the device's error number and pass it to the user; 06202 * if there is an error but the number is 0 set a generalized 06203 * code. Actually the latter is always true because devices 06204 * don't yet return specific errors. 06205 */ 06206 geterror(bp) 06207 register struct buf *bp; 06208 { 06209 06210 if (bp->b_flags&B_ERROR) 06211 if ((u.u_error = bp->b_error)==0) 06212 u.u_error = EIO; 06213 } 06214 06215 06216 06217 06218 06219 06220 06221 06222 06223 06224 06225 06226 06227 06228 06229 06230 06231 06232 06233 06234 06235 06236 06237 06238 06239 06240 06241 06242 06243 06244 06245 06246 06247 06248 06249