Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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, ulong), 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;		/* function to read or write bs-byte blocks */
28
 
29
	return b;
30
}
31
 
32
long
33
bread(Buf *b, void *v, long n, vlong off)
34
{
35
	long m;
36
	vlong noff;
37
 
38
	assert(b->omode == OREAD);
39
 
40
	/* Refill buffer */
41
	if(b->off > off || off >= b->off+b->ndata) {
42
		noff = off - off % b->bs;
43
		if(vflag > 1)
44
			fprint(2, "try refill at %lld...", noff);
45
		if((m = b->fn(b, b->data, b->nblock, noff/b->bs)) <= 0) {
46
			if (vflag)
47
				fprint(2, "read failed: %r\n");
48
			return m;
49
		}
50
		b->ndata = b->bs * m;
51
		b->off = noff;
52
		if(vflag > 1)
53
			fprint(2, "got %ld\n", b->ndata);
54
	}
55
 
56
//	fprint(2, "read %ld at %ld\n", n, off);
57
	/* Satisfy request from buffer */
58
	off -= b->off;
59
	if(n > b->ndata - off)
60
		n = b->ndata - off;
61
	memmove(v, b->data+off, n);
62
	return n;
63
}
64
 
65
long
66
bwrite(Buf *b, void *v, long n)
67
{
68
	long on, m, mdata;
69
	uchar *p;
70
 
71
	p = v;
72
	on = n;
73
 
74
	/* Fill buffer */
75
	mdata = b->bs*b->nblock;
76
	m = mdata - b->ndata;
77
	if(m > n)
78
		m = n;
79
	memmove(b->data+b->ndata, p, m);
80
	p += m;
81
	n -= m;
82
	b->ndata += m;
83
 
84
	/* Flush buffer */
85
	if(b->ndata == mdata) {
86
		if(b->fn(b, b->data, b->nblock, 0) < 0) {
87
			if(vflag)
88
				fprint(2, "write fails: %r\n");
89
			return -1;
90
		}
91
		b->ndata = 0;
92
	}
93
 
94
	/* For now, don't worry about big writes; 9P only does 8k */
95
	assert(n < mdata);
96
 
97
	/* Add remainder to buffer */
98
	if(n) {
99
		memmove(b->data, p, n);
100
		b->ndata = n;
101
	}
102
 
103
	return on;
104
}
105
 
106
void
107
bterm(Buf *b)
108
{
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); 
112
 
113
	free(b->data);
114
	free(b);
115
}