2 * Buffered I/O on block devices.
3 * Write buffering ignores offset.
13 bopen(long (*fn)(Buf*, void*, long, ulong), int omode, int bs, int nblock)
17 assert(omode == OREAD || OWRITE);
18 assert(bs > 0 && nblock > 0);
21 b = emalloc(sizeof(*b));
22 b->data = emalloc(bs*nblock);
27 b->fn = fn; /* function to read or write bs-byte blocks */
33 bread(Buf *b, void *v, long n, vlong off)
38 assert(b->omode == OREAD);
41 if(b->off > off || off >= b->off+b->ndata) {
42 noff = off - off % b->bs;
44 fprint(2, "try refill at %lld...", noff);
45 if((m = b->fn(b, b->data, b->nblock, noff/b->bs)) <= 0) {
47 fprint(2, "failed\n");
53 fprint(2, "got %ld\n", b->ndata);
56 // fprint(2, "read %ld at %ld\n", n, off);
57 /* Satisfy request from buffer */
59 if(n > b->ndata - off)
61 memmove(v, b->data+off, n);
66 bwrite(Buf *b, void *v, long n)
75 mdata = b->bs*b->nblock;
79 memmove(b->data+b->ndata, p, m);
85 if(b->ndata == mdata) {
86 if(b->fn(b, b->data, b->nblock, 0) < 0) {
88 fprint(2, "write fails: %r\n");
94 /* For now, don't worry about big writes; 9P only does 8k */
97 /* Add remainder to buffer */
99 memmove(b->data, p, n);
109 /* DVD & BD prefer full ecc blocks (tracks), but can cope with less */
110 if(b->omode == OWRITE && b->ndata)
111 b->fn(b, b->data, (b->ndata + b->bs - 1)/b->bs, 0);