xref: /plan9/sys/src/cmd/cdfs/buf.c (revision 144145943e440fe30c4e4512a0856f5e3d5ca4be)
17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier  * Buffered I/O on block devices.
37dd7cddfSDavid du Colombier  * Write buffering ignores offset.
47dd7cddfSDavid du Colombier  */
57dd7cddfSDavid du Colombier 
67dd7cddfSDavid du Colombier #include <u.h>
77dd7cddfSDavid du Colombier #include <libc.h>
87dd7cddfSDavid du Colombier #include <disk.h>
97dd7cddfSDavid du Colombier #include "dat.h"
107dd7cddfSDavid du Colombier #include "fns.h"
117dd7cddfSDavid du Colombier 
127dd7cddfSDavid du Colombier Buf*
137dd7cddfSDavid du Colombier bopen(long (*fn)(Buf*, void*, long, long), int omode, int bs, int nblock)
147dd7cddfSDavid du Colombier {
157dd7cddfSDavid du Colombier 	Buf *b;
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier 	assert(omode == OREAD || OWRITE);
187dd7cddfSDavid du Colombier 	assert(bs > 0 && nblock > 0);
197dd7cddfSDavid du Colombier 	assert(fn != nil);
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier 	b = emalloc(sizeof(*b));
227dd7cddfSDavid du Colombier 	b->data = emalloc(bs*nblock);
237dd7cddfSDavid du Colombier 	b->ndata = 0;
247dd7cddfSDavid du Colombier 	b->nblock = nblock;
257dd7cddfSDavid du Colombier 	b->bs = bs;
267dd7cddfSDavid du Colombier 	b->omode = omode;
277dd7cddfSDavid du Colombier 	b->fn = fn;
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier 	return b;
307dd7cddfSDavid du Colombier }
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier long
337dd7cddfSDavid du Colombier bread(Buf *b, void *v, long n, long off)
347dd7cddfSDavid du Colombier {
357dd7cddfSDavid du Colombier 	long m, noff;
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier 	assert(b->omode == OREAD);
387dd7cddfSDavid du Colombier 
397dd7cddfSDavid du Colombier 	/* Refill buffer */
407dd7cddfSDavid du Colombier 	if(b->off > off || off >= b->off+b->ndata) {
417dd7cddfSDavid du Colombier 		noff = off - off % b->bs;
427dd7cddfSDavid du Colombier 		if(vflag)
437dd7cddfSDavid du Colombier 			fprint(2, "try refill at %ld\n", noff);
447dd7cddfSDavid du Colombier 		if((m = b->fn(b, b->data, Nblock, noff/b->bs)) <= 0)
457dd7cddfSDavid du Colombier 			return -1;
467dd7cddfSDavid du Colombier 		b->ndata = b->bs * m;
477dd7cddfSDavid du Colombier 		b->off = noff;
487dd7cddfSDavid du Colombier 		if(vflag)
497dd7cddfSDavid du Colombier 			fprint(2, "refill %ld at %ld\n", b->ndata, b->off);
507dd7cddfSDavid du Colombier 	}
517dd7cddfSDavid du Colombier 
52*14414594SDavid du Colombier //	fprint(2, "read %ld at %ld\n", n, off);
537dd7cddfSDavid du Colombier 	/* Satisfy request from buffer */
547dd7cddfSDavid du Colombier 	off -= b->off;
557dd7cddfSDavid du Colombier 	if(n > b->ndata - off)
567dd7cddfSDavid du Colombier 		n = b->ndata - off;
577dd7cddfSDavid du Colombier 	memmove(v, b->data+off, n);
587dd7cddfSDavid du Colombier 	return n;
597dd7cddfSDavid du Colombier }
607dd7cddfSDavid du Colombier 
617dd7cddfSDavid du Colombier long
627dd7cddfSDavid du Colombier bwrite(Buf *b, void *v, long n)
637dd7cddfSDavid du Colombier {
647dd7cddfSDavid du Colombier 	long on, m, mdata;
657dd7cddfSDavid du Colombier 	uchar *p;
667dd7cddfSDavid du Colombier 
677dd7cddfSDavid du Colombier 	p = v;
687dd7cddfSDavid du Colombier 	on = n;
697dd7cddfSDavid du Colombier 
707dd7cddfSDavid du Colombier 	/* Fill buffer */
717dd7cddfSDavid du Colombier 	mdata = b->bs*b->nblock;
727dd7cddfSDavid du Colombier 	m = mdata - b->ndata;
737dd7cddfSDavid du Colombier 	if(m > n)
747dd7cddfSDavid du Colombier 		m = n;
757dd7cddfSDavid du Colombier 	memmove(b->data+b->ndata, p, m);
767dd7cddfSDavid du Colombier 	p += m;
777dd7cddfSDavid du Colombier 	n -= m;
787dd7cddfSDavid du Colombier 	b->ndata += m;
797dd7cddfSDavid du Colombier 
807dd7cddfSDavid du Colombier 	/* Flush buffer */
817dd7cddfSDavid du Colombier 	if(b->ndata == mdata) {
827dd7cddfSDavid du Colombier 		if(b->fn(b, b->data, b->nblock, 0) < 0) {
837dd7cddfSDavid du Colombier 			if(vflag)
847dd7cddfSDavid du Colombier 				fprint(2, "write fails: %r\n");
857dd7cddfSDavid du Colombier 			return -1;
867dd7cddfSDavid du Colombier 		}
877dd7cddfSDavid du Colombier 		b->ndata = 0;
887dd7cddfSDavid du Colombier 	}
897dd7cddfSDavid du Colombier 
907dd7cddfSDavid du Colombier 	/* For now, don't worry about big writes; 9P only does 8k */
917dd7cddfSDavid du Colombier 	assert(n < mdata);
927dd7cddfSDavid du Colombier 
937dd7cddfSDavid du Colombier 	/* Add remainder to buffer */
947dd7cddfSDavid du Colombier 	if(n) {
957dd7cddfSDavid du Colombier 		memmove(b->data, p, n);
967dd7cddfSDavid du Colombier 		b->ndata = n;
977dd7cddfSDavid du Colombier 	}
987dd7cddfSDavid du Colombier 
997dd7cddfSDavid du Colombier 	return on;
1007dd7cddfSDavid du Colombier }
1017dd7cddfSDavid du Colombier 
1027dd7cddfSDavid du Colombier void
1037dd7cddfSDavid du Colombier bterm(Buf *b)
1047dd7cddfSDavid du Colombier {
1057dd7cddfSDavid du Colombier 	if(b->omode == OWRITE && b->ndata)
1067dd7cddfSDavid du Colombier 		b->fn(b, b->data, (b->ndata+b->bs-1)/b->bs, b->off);
1077dd7cddfSDavid du Colombier 
1087dd7cddfSDavid du Colombier 	free(b->data);
1097dd7cddfSDavid du Colombier 	free(b);
1107dd7cddfSDavid du Colombier }
111