xref: /plan9/sys/src/cmd/ext2srv/iobuf.c (revision ec46fab06dcae3e636b775c4eaa679036316e1d8)
1dc5a79c1SDavid du Colombier #include <u.h>
2dc5a79c1SDavid du Colombier #include <libc.h>
3dc5a79c1SDavid du Colombier #include <fcall.h>
4dc5a79c1SDavid du Colombier #include <thread.h>
5dc5a79c1SDavid du Colombier #include <9p.h>
6dc5a79c1SDavid du Colombier #include "dat.h"
7dc5a79c1SDavid du Colombier #include "fns.h"
8dc5a79c1SDavid du Colombier 
9dc5a79c1SDavid du Colombier #define	NIOBUF		100
10dc5a79c1SDavid du Colombier #define	HIOB		(NIOBUF/3)
11dc5a79c1SDavid du Colombier 
12dc5a79c1SDavid du Colombier static Iobuf*	hiob[HIOB];		/* hash buckets */
13dc5a79c1SDavid du Colombier static Iobuf	iobuf[NIOBUF];		/* buffer headers */
14dc5a79c1SDavid du Colombier static Iobuf*	iohead;
15dc5a79c1SDavid du Colombier static Iobuf*	iotail;
16dc5a79c1SDavid du Colombier 
17dc5a79c1SDavid du Colombier Iobuf*
getbuf(Xfs * dev,long addr)18dc5a79c1SDavid du Colombier getbuf(Xfs *dev, long addr)
19dc5a79c1SDavid du Colombier {
20dc5a79c1SDavid du Colombier 	Iobuf *p, *h, **l, **f;
21dc5a79c1SDavid du Colombier 
22dc5a79c1SDavid du Colombier 	l = &hiob[addr%HIOB];
23dc5a79c1SDavid du Colombier 	for(p = *l; p; p = p->hash) {
24dc5a79c1SDavid du Colombier 		if(p->addr == addr && p->dev == dev) {
25dc5a79c1SDavid du Colombier 			p->busy++;
26dc5a79c1SDavid du Colombier 			return p;
27dc5a79c1SDavid du Colombier 		}
28dc5a79c1SDavid du Colombier 	}
29dc5a79c1SDavid du Colombier 	/* Find a non-busy buffer from the tail */
30dc5a79c1SDavid du Colombier 	for(p = iotail; p && (p->busy > 0); p = p->prev)
31dc5a79c1SDavid du Colombier 		;
32dc5a79c1SDavid du Colombier 	if(!p)
33dc5a79c1SDavid du Colombier 		panic("all buffers busy");
34dc5a79c1SDavid du Colombier 	if(p->dirty){
35dc5a79c1SDavid du Colombier 		xwrite(p);
36dc5a79c1SDavid du Colombier 		p->dirty = 0;
37dc5a79c1SDavid du Colombier 	}
38dc5a79c1SDavid du Colombier 
39dc5a79c1SDavid du Colombier 	if( xread(dev, p, addr) < 0)
40dc5a79c1SDavid du Colombier 		return 0;
41dc5a79c1SDavid du Colombier 	/* Delete from hash chain */
42dc5a79c1SDavid du Colombier 	f = &hiob[p->addr%HIOB];
43dc5a79c1SDavid du Colombier 	if( *f == p )
44dc5a79c1SDavid du Colombier 		*f = p->hash;
45dc5a79c1SDavid du Colombier 	else {
46dc5a79c1SDavid du Colombier 		for(h = *f; h ; h = h->hash)
47dc5a79c1SDavid du Colombier 			if( h->hash == p ){
48dc5a79c1SDavid du Colombier 				h->hash = p->hash;
49dc5a79c1SDavid du Colombier 				break;
50dc5a79c1SDavid du Colombier 			}
51dc5a79c1SDavid du Colombier 	}
52dc5a79c1SDavid du Colombier 	/* Fill and hash */
53dc5a79c1SDavid du Colombier 	p->hash = *l;
54dc5a79c1SDavid du Colombier 	*l = p;
55dc5a79c1SDavid du Colombier 	p->addr = addr;
56dc5a79c1SDavid du Colombier 	p->dev = dev;
57dc5a79c1SDavid du Colombier 	p->busy=1;
58dc5a79c1SDavid du Colombier 
59dc5a79c1SDavid du Colombier 	return p;
60dc5a79c1SDavid du Colombier }
61dc5a79c1SDavid du Colombier void
putbuf(Iobuf * p)62dc5a79c1SDavid du Colombier putbuf(Iobuf *p)
63dc5a79c1SDavid du Colombier {
64dc5a79c1SDavid du Colombier 	if(p->busy <= 0)
65dc5a79c1SDavid du Colombier 		panic("putbuf");
66dc5a79c1SDavid du Colombier 	p->busy--;
67dc5a79c1SDavid du Colombier 
68dc5a79c1SDavid du Colombier 	/* Link onto head for lru */
69dc5a79c1SDavid du Colombier 	if(p == iohead)
70dc5a79c1SDavid du Colombier 		return;
71dc5a79c1SDavid du Colombier 	if( p == iotail ){
72dc5a79c1SDavid du Colombier 		p->prev->next = 0;
73dc5a79c1SDavid du Colombier 		iotail = p->prev;
74dc5a79c1SDavid du Colombier 	}else{
75dc5a79c1SDavid du Colombier 		p->prev->next = p->next;
76dc5a79c1SDavid du Colombier 		p->next->prev = p->prev;
77dc5a79c1SDavid du Colombier 	}
78dc5a79c1SDavid du Colombier 
79dc5a79c1SDavid du Colombier 	p->prev = 0;
80dc5a79c1SDavid du Colombier 	p->next = iohead;
81dc5a79c1SDavid du Colombier 	iohead->prev = p;
82dc5a79c1SDavid du Colombier 	iohead = p;
83dc5a79c1SDavid du Colombier }
84dc5a79c1SDavid du Colombier void
dirtybuf(Iobuf * p)85dc5a79c1SDavid du Colombier dirtybuf(Iobuf *p)
86dc5a79c1SDavid du Colombier {
87dc5a79c1SDavid du Colombier 	if(p->busy <=0)
88dc5a79c1SDavid du Colombier 		panic("dirtybuf");
89dc5a79c1SDavid du Colombier 	p->dirty = 1;
90dc5a79c1SDavid du Colombier }
91dc5a79c1SDavid du Colombier void
syncbuf(void)92dc5a79c1SDavid du Colombier syncbuf(void)
93dc5a79c1SDavid du Colombier {
94dc5a79c1SDavid du Colombier 	Iobuf *p;
95dc5a79c1SDavid du Colombier 
96dc5a79c1SDavid du Colombier 	for(p=&iobuf[0] ; p<&iobuf[NIOBUF]; p++)
97dc5a79c1SDavid du Colombier 		if( p->dirty ){
98dc5a79c1SDavid du Colombier 			xwrite(p);
99dc5a79c1SDavid du Colombier 			p->dirty = 0;
100dc5a79c1SDavid du Colombier 		}
101dc5a79c1SDavid du Colombier }
102dc5a79c1SDavid du Colombier void
purgebuf(Xfs * dev)103dc5a79c1SDavid du Colombier purgebuf(Xfs *dev)
104dc5a79c1SDavid du Colombier {
105dc5a79c1SDavid du Colombier 	Iobuf *p;
106dc5a79c1SDavid du Colombier 
107dc5a79c1SDavid du Colombier 	for(p=&iobuf[0]; p<&iobuf[NIOBUF]; p++)
108dc5a79c1SDavid du Colombier 		if(p->dev == dev)
109dc5a79c1SDavid du Colombier 			p->busy = 0;
110dc5a79c1SDavid du Colombier 
111dc5a79c1SDavid du Colombier 	/* Blow hash chains */
112dc5a79c1SDavid du Colombier 	memset(hiob, 0, sizeof(hiob));
113dc5a79c1SDavid du Colombier }
114dc5a79c1SDavid du Colombier void
iobuf_init(void)115dc5a79c1SDavid du Colombier iobuf_init(void)
116dc5a79c1SDavid du Colombier {
117dc5a79c1SDavid du Colombier 	Iobuf *p;
118dc5a79c1SDavid du Colombier 
119dc5a79c1SDavid du Colombier 	iohead = iobuf;
120dc5a79c1SDavid du Colombier 	iotail = iobuf+NIOBUF-1;
121dc5a79c1SDavid du Colombier 
122dc5a79c1SDavid du Colombier 	for(p = iobuf; p <= iotail; p++) {
123dc5a79c1SDavid du Colombier 		p->next = p+1;
124dc5a79c1SDavid du Colombier 		p->prev = p-1;
125dc5a79c1SDavid du Colombier 
126dc5a79c1SDavid du Colombier 		p->iobuf = (char *)malloc(EXT2_MAX_BLOCK_SIZE);
127dc5a79c1SDavid du Colombier 		if(p->iobuf == 0)
128dc5a79c1SDavid du Colombier 			panic("iobuf_init");
129dc5a79c1SDavid du Colombier 	}
130dc5a79c1SDavid du Colombier 
131dc5a79c1SDavid du Colombier 	iohead->prev = 0;
132dc5a79c1SDavid du Colombier 	iotail->next = 0;
133dc5a79c1SDavid du Colombier }
134dc5a79c1SDavid du Colombier int
xread(Xfs * dev,Iobuf * p,long addr)135dc5a79c1SDavid du Colombier xread(Xfs *dev, Iobuf *p, long addr)
136dc5a79c1SDavid du Colombier {
137dc5a79c1SDavid du Colombier 	/*chat("xread %d,%d...", dev->dev, addr);*/
138dc5a79c1SDavid du Colombier 
139dc5a79c1SDavid du Colombier 	seek(dev->dev, (vlong)addr*dev->block_size, 0);
140dc5a79c1SDavid du Colombier 	if(read(dev->dev, p->iobuf, dev->block_size) != dev->block_size){
141dc5a79c1SDavid du Colombier 		chat("xread %d, block=%d failed ...", dev->dev, addr);
142dc5a79c1SDavid du Colombier 		errno = Eio;
143dc5a79c1SDavid du Colombier 		return -1;
144dc5a79c1SDavid du Colombier 	}
145dc5a79c1SDavid du Colombier 	/*chat("xread ok...");*/
146*ec46fab0SDavid du Colombier 	return 0;
147dc5a79c1SDavid du Colombier }
148dc5a79c1SDavid du Colombier void
xwrite(Iobuf * p)149dc5a79c1SDavid du Colombier xwrite(Iobuf *p)
150dc5a79c1SDavid du Colombier {
151dc5a79c1SDavid du Colombier 	Xfs *dev;
152dc5a79c1SDavid du Colombier 	long addr;
153dc5a79c1SDavid du Colombier 
154dc5a79c1SDavid du Colombier 	dev = p->dev;
155dc5a79c1SDavid du Colombier 	addr = p->addr;
156dc5a79c1SDavid du Colombier 	/*chat("xwrite %d,%d...", dev->dev, addr);*/
157dc5a79c1SDavid du Colombier 
158dc5a79c1SDavid du Colombier 	seek(dev->dev, (vlong)addr*dev->block_size, 0);
159dc5a79c1SDavid du Colombier 	if(write(dev->dev, p->iobuf, dev->block_size) != dev->block_size){
160dc5a79c1SDavid du Colombier 		chat("xwrite %d, block=%d failed ...", dev->dev, addr);
161dc5a79c1SDavid du Colombier 		errno = Eio;
162dc5a79c1SDavid du Colombier 		return;
163dc5a79c1SDavid du Colombier 	}
164dc5a79c1SDavid du Colombier 	/*chat("xwrite ok...");*/
165dc5a79c1SDavid du Colombier }
166dc5a79c1SDavid du Colombier void
dumpbuf(void)167dc5a79c1SDavid du Colombier dumpbuf(void)
168dc5a79c1SDavid du Colombier {
169dc5a79c1SDavid du Colombier 	Iobuf *p;
170dc5a79c1SDavid du Colombier 
171dc5a79c1SDavid du Colombier 	for(p = iotail; p ; p = p->prev)
172dc5a79c1SDavid du Colombier 		if( p->busy )
173dc5a79c1SDavid du Colombier 			mchat("\nHi ERROR buf(%x, %d, %d)\n", p, p->addr, p->busy);
174dc5a79c1SDavid du Colombier }
175