1 /* 2 * Buffered I/O on block devices. 3 * Write buffering ignores offset. 4 */ 5 6 #include <u.h> 7 #include <libc.h> 8 #include <disk.h> 9 #include "dat.h" 10 #include "fns.h" 11 12 Buf* 13 bopen(long (*fn)(Buf*, void*, long, long), int omode, int bs, int nblock) 14 { 15 Buf *b; 16 17 assert(omode == OREAD || OWRITE); 18 assert(bs > 0 && nblock > 0); 19 assert(fn != nil); 20 21 b = emalloc(sizeof(*b)); 22 b->data = emalloc(bs*nblock); 23 b->ndata = 0; 24 b->nblock = nblock; 25 b->bs = bs; 26 b->omode = omode; 27 b->fn = fn; 28 29 return b; 30 } 31 32 long 33 bread(Buf *b, void *v, long n, long off) 34 { 35 long m, noff; 36 37 assert(b->omode == OREAD); 38 39 /* Refill buffer */ 40 if(b->off > off || off >= b->off+b->ndata) { 41 noff = off - off % b->bs; 42 if(vflag) 43 fprint(2, "try refill at %ld\n", noff); 44 if((m = b->fn(b, b->data, Nblock, noff/b->bs)) <= 0) 45 return m; 46 b->ndata = b->bs * m; 47 b->off = noff; 48 if(vflag) 49 fprint(2, "refill %ld at %ld\n", b->ndata, b->off); 50 } 51 52 // fprint(2, "read %ld at %ld\n", n, off); 53 /* Satisfy request from buffer */ 54 off -= b->off; 55 if(n > b->ndata - off) 56 n = b->ndata - off; 57 memmove(v, b->data+off, n); 58 return n; 59 } 60 61 long 62 bwrite(Buf *b, void *v, long n) 63 { 64 long on, m, mdata; 65 uchar *p; 66 67 p = v; 68 on = n; 69 70 /* Fill buffer */ 71 mdata = b->bs*b->nblock; 72 m = mdata - b->ndata; 73 if(m > n) 74 m = n; 75 memmove(b->data+b->ndata, p, m); 76 p += m; 77 n -= m; 78 b->ndata += m; 79 80 /* Flush buffer */ 81 if(b->ndata == mdata) { 82 if(b->fn(b, b->data, b->nblock, 0) < 0) { 83 if(vflag) 84 fprint(2, "write fails: %r\n"); 85 return -1; 86 } 87 b->ndata = 0; 88 } 89 90 /* For now, don't worry about big writes; 9P only does 8k */ 91 assert(n < mdata); 92 93 /* Add remainder to buffer */ 94 if(n) { 95 memmove(b->data, p, n); 96 b->ndata = n; 97 } 98 99 return on; 100 } 101 102 void 103 bterm(Buf *b) 104 { 105 if(b->omode == OWRITE && b->ndata) 106 b->fn(b, b->data, (b->ndata+b->bs-1)/b->bs, b->off); 107 108 free(b->data); 109 free(b); 110 } 111