xref: /plan9/sys/src/cmd/disk/kfs/iobuf.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
13e12c5d1SDavid du Colombier #include	"all.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier #define	DEBUG	0
43e12c5d1SDavid du Colombier 
53e12c5d1SDavid du Colombier long	niob;
63e12c5d1SDavid du Colombier long	nhiob;
73e12c5d1SDavid du Colombier Hiob	*hiob;
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier Iobuf*
getbuf(Device dev,long addr,int flag)103e12c5d1SDavid du Colombier getbuf(Device dev, long addr, int flag)
113e12c5d1SDavid du Colombier {
123e12c5d1SDavid du Colombier 	Iobuf *p, *s;
133e12c5d1SDavid du Colombier 	Hiob *hp;
143e12c5d1SDavid du Colombier 	long h;
153e12c5d1SDavid du Colombier 
163e12c5d1SDavid du Colombier 	if(DEBUG)
173e12c5d1SDavid du Colombier 		print("getbuf %D(%ld) f=%x\n", dev, addr, flag);
183e12c5d1SDavid du Colombier 	h = addr +
193e12c5d1SDavid du Colombier 		dev.type*1009L +
203e12c5d1SDavid du Colombier 		dev.ctrl*10007L +
213e12c5d1SDavid du Colombier 		dev.unit*100003L +
223e12c5d1SDavid du Colombier 		dev.part*1000003L;
233e12c5d1SDavid du Colombier 	if(h < 0)
243e12c5d1SDavid du Colombier 		h = ~h;
253e12c5d1SDavid du Colombier 	h %= nhiob;
263e12c5d1SDavid du Colombier 	hp = &hiob[h];
273e12c5d1SDavid du Colombier 
283e12c5d1SDavid du Colombier loop:
293e12c5d1SDavid du Colombier 	lock(hp);
303e12c5d1SDavid du Colombier 
313e12c5d1SDavid du Colombier /*
323e12c5d1SDavid du Colombier  * look for it in the active list
333e12c5d1SDavid du Colombier  */
343e12c5d1SDavid du Colombier 	s = hp->link;
353e12c5d1SDavid du Colombier 	for(p=s;;) {
363e12c5d1SDavid du Colombier 		if(p->addr == addr && !devcmp(p->dev, dev)) {
373e12c5d1SDavid du Colombier 			if(p != s) {
383e12c5d1SDavid du Colombier 				p->back->fore = p->fore;
393e12c5d1SDavid du Colombier 				p->fore->back = p->back;
403e12c5d1SDavid du Colombier 				p->fore = s;
413e12c5d1SDavid du Colombier 				p->back = s->back;
423e12c5d1SDavid du Colombier 				s->back = p;
433e12c5d1SDavid du Colombier 				p->back->fore = p;
443e12c5d1SDavid du Colombier 				hp->link = p;
453e12c5d1SDavid du Colombier 			}
463e12c5d1SDavid du Colombier 			unlock(hp);
473e12c5d1SDavid du Colombier 			qlock(p);
483e12c5d1SDavid du Colombier 			if(p->addr != addr || devcmp(p->dev, dev)) {
493e12c5d1SDavid du Colombier 				qunlock(p);
503e12c5d1SDavid du Colombier 				goto loop;
513e12c5d1SDavid du Colombier 			}
523e12c5d1SDavid du Colombier 			p->flags |= flag;
533e12c5d1SDavid du Colombier 			cons.bhit.count++;
543e12c5d1SDavid du Colombier 			p->iobuf = p->xiobuf;
553e12c5d1SDavid du Colombier 			return p;
563e12c5d1SDavid du Colombier 		}
573e12c5d1SDavid du Colombier 		p = p->fore;
583e12c5d1SDavid du Colombier 		if(p == s)
593e12c5d1SDavid du Colombier 			break;
603e12c5d1SDavid du Colombier 	}
613e12c5d1SDavid du Colombier 	if(flag & Bprobe) {
623e12c5d1SDavid du Colombier 		unlock(hp);
633e12c5d1SDavid du Colombier 		return 0;
643e12c5d1SDavid du Colombier 	}
653e12c5d1SDavid du Colombier 
663e12c5d1SDavid du Colombier /*
673e12c5d1SDavid du Colombier  * not found
683e12c5d1SDavid du Colombier  * take oldest unlocked entry in this queue
693e12c5d1SDavid du Colombier  */
703e12c5d1SDavid du Colombier xloop:
713e12c5d1SDavid du Colombier 	p = s->back;
723e12c5d1SDavid du Colombier 	if(!canqlock(p)) {
733e12c5d1SDavid du Colombier 		if(p == hp->link) {
743e12c5d1SDavid du Colombier 			unlock(hp);
753e12c5d1SDavid du Colombier 			print("iobuf all locked\n");
763e12c5d1SDavid du Colombier 			goto loop;
773e12c5d1SDavid du Colombier 		}
783e12c5d1SDavid du Colombier 		s = p;
793e12c5d1SDavid du Colombier 		goto xloop;
803e12c5d1SDavid du Colombier 	}
813e12c5d1SDavid du Colombier 	/*
823e12c5d1SDavid du Colombier 	 * its dangerous to flush the pseudo
833e12c5d1SDavid du Colombier 	 * devices since they recursively call
843e12c5d1SDavid du Colombier 	 * getbuf/putbuf. deadlock!
853e12c5d1SDavid du Colombier 	 */
863e12c5d1SDavid du Colombier 	if(p->flags & Bres) {
873e12c5d1SDavid du Colombier 		qunlock(p);
883e12c5d1SDavid du Colombier 		if(p == hp->link) {
893e12c5d1SDavid du Colombier 			unlock(hp);
903e12c5d1SDavid du Colombier 			print("iobuf all resed\n");
913e12c5d1SDavid du Colombier 			goto loop;
923e12c5d1SDavid du Colombier 		}
933e12c5d1SDavid du Colombier 		s = p;
943e12c5d1SDavid du Colombier 		goto xloop;
953e12c5d1SDavid du Colombier 	}
963e12c5d1SDavid du Colombier 	if(p->flags & Bmod) {
973e12c5d1SDavid du Colombier 		unlock(hp);
983e12c5d1SDavid du Colombier 		if(!devwrite(p->dev, p->addr, p->xiobuf))
993e12c5d1SDavid du Colombier 			p->flags &= ~(Bimm|Bmod);
1003e12c5d1SDavid du Colombier 		qunlock(p);
1013e12c5d1SDavid du Colombier 		goto loop;
1023e12c5d1SDavid du Colombier 	}
1033e12c5d1SDavid du Colombier 	hp->link = p;
1043e12c5d1SDavid du Colombier 	p->addr = addr;
1053e12c5d1SDavid du Colombier 	p->dev = dev;
1063e12c5d1SDavid du Colombier 	p->flags = flag;
1073e12c5d1SDavid du Colombier 	unlock(hp);
1083e12c5d1SDavid du Colombier 	p->iobuf = p->xiobuf;
1093e12c5d1SDavid du Colombier 	if(flag & Bread) {
1103e12c5d1SDavid du Colombier 		if(devread(p->dev, p->addr, p->iobuf)) {
1113e12c5d1SDavid du Colombier 			p->flags = 0;
1123e12c5d1SDavid du Colombier 			p->dev = devnone;
1133e12c5d1SDavid du Colombier 			p->addr = -1;
1143e12c5d1SDavid du Colombier 			p->iobuf = (char*)-1;
1153e12c5d1SDavid du Colombier 			qunlock(p);
1163e12c5d1SDavid du Colombier 			return 0;
1173e12c5d1SDavid du Colombier 		}
1183e12c5d1SDavid du Colombier 		cons.bread.count++;
1193e12c5d1SDavid du Colombier 		return p;
1203e12c5d1SDavid du Colombier 	}
1213e12c5d1SDavid du Colombier 	cons.binit.count++;
1223e12c5d1SDavid du Colombier 	return p;
1233e12c5d1SDavid du Colombier }
1243e12c5d1SDavid du Colombier 
1253e12c5d1SDavid du Colombier /*
1263e12c5d1SDavid du Colombier  * syncblock tries to put out a block per hashline
1273e12c5d1SDavid du Colombier  * returns 0 all done,
1283e12c5d1SDavid du Colombier  * returns 1 if it missed something
1293e12c5d1SDavid du Colombier  */
1303e12c5d1SDavid du Colombier int
syncblock(void)1313e12c5d1SDavid du Colombier syncblock(void)
1323e12c5d1SDavid du Colombier {
1333e12c5d1SDavid du Colombier 	Iobuf *p, *s, *q;
1343e12c5d1SDavid du Colombier 	Hiob *hp;
1353e12c5d1SDavid du Colombier 	long h;
1363e12c5d1SDavid du Colombier 	int flag;
1373e12c5d1SDavid du Colombier 
1383e12c5d1SDavid du Colombier 	flag = 0;
1393e12c5d1SDavid du Colombier 	for(h=0; h<nhiob; h++) {
1403e12c5d1SDavid du Colombier 		q = 0;
1413e12c5d1SDavid du Colombier 		hp = &hiob[h];
1423e12c5d1SDavid du Colombier 		lock(hp);
1433e12c5d1SDavid du Colombier 		s = hp->link;
1443e12c5d1SDavid du Colombier 		for(p=s;;) {
1453e12c5d1SDavid du Colombier 			if(p->flags & Bmod) {
1463e12c5d1SDavid du Colombier 				if(q)
1473e12c5d1SDavid du Colombier 					flag = 1;	/* more than 1 mod/line */
1483e12c5d1SDavid du Colombier 				q = p;
1493e12c5d1SDavid du Colombier 			}
1503e12c5d1SDavid du Colombier 			p = p->fore;
1513e12c5d1SDavid du Colombier 			if(p == s)
1523e12c5d1SDavid du Colombier 				break;
1533e12c5d1SDavid du Colombier 		}
1543e12c5d1SDavid du Colombier 		unlock(hp);
1553e12c5d1SDavid du Colombier 		if(q) {
1563e12c5d1SDavid du Colombier 			if(!canqlock(q)) {
1573e12c5d1SDavid du Colombier 				flag = 1;		/* missed -- was locked */
1583e12c5d1SDavid du Colombier 				continue;
1593e12c5d1SDavid du Colombier 			}
1603e12c5d1SDavid du Colombier 			if(!(q->flags & Bmod)) {
1613e12c5d1SDavid du Colombier 				qunlock(q);
1623e12c5d1SDavid du Colombier 				continue;
1633e12c5d1SDavid du Colombier 			}
1643e12c5d1SDavid du Colombier 			if(!devwrite(q->dev, q->addr, q->xiobuf))
1653e12c5d1SDavid du Colombier 				q->flags &= ~(Bmod|Bimm);
1663e12c5d1SDavid du Colombier 			qunlock(q);
1673e12c5d1SDavid du Colombier 		}
1683e12c5d1SDavid du Colombier 	}
1693e12c5d1SDavid du Colombier 	return flag;
1703e12c5d1SDavid du Colombier }
1713e12c5d1SDavid du Colombier 
1723e12c5d1SDavid du Colombier void
sync(char * reason)1733e12c5d1SDavid du Colombier sync(char *reason)
1743e12c5d1SDavid du Colombier {
1753e12c5d1SDavid du Colombier 	long i;
1763e12c5d1SDavid du Colombier 
1773e12c5d1SDavid du Colombier 	print("sync: %s\n", reason);
1783e12c5d1SDavid du Colombier 	for(i=10*nhiob; i>0; i--)
1793e12c5d1SDavid du Colombier 		if(!syncblock())
1803e12c5d1SDavid du Colombier 			return;
1813e12c5d1SDavid du Colombier 	print("sync shorted\n");
1823e12c5d1SDavid du Colombier }
1833e12c5d1SDavid du Colombier 
1843e12c5d1SDavid du Colombier void
putbuf(Iobuf * p)1853e12c5d1SDavid du Colombier putbuf(Iobuf *p)
1863e12c5d1SDavid du Colombier {
1873e12c5d1SDavid du Colombier 	if(canqlock(p))
1883e12c5d1SDavid du Colombier 		print("buffer not locked %D(%ld)\n", p->dev, p->addr);
1893e12c5d1SDavid du Colombier 	if(p->flags & Bimm) {
1903e12c5d1SDavid du Colombier 		if(!(p->flags & Bmod))
1913e12c5d1SDavid du Colombier 			print("imm and no mod %D(%ld)\n", p->dev, p->addr);
1923e12c5d1SDavid du Colombier 		if(!devwrite(p->dev, p->addr, p->iobuf))
1933e12c5d1SDavid du Colombier 			p->flags &= ~(Bmod|Bimm);
1943e12c5d1SDavid du Colombier 	}
1953e12c5d1SDavid du Colombier 	p->iobuf = (char*)-1;
1963e12c5d1SDavid du Colombier 	qunlock(p);
1973e12c5d1SDavid du Colombier }
1983e12c5d1SDavid du Colombier 
1993e12c5d1SDavid du Colombier int
checktag(Iobuf * p,int tag,long qpath)2003e12c5d1SDavid du Colombier checktag(Iobuf *p, int tag, long qpath)
2013e12c5d1SDavid du Colombier {
2023e12c5d1SDavid du Colombier 	Tag *t;
2033e12c5d1SDavid du Colombier 
2043e12c5d1SDavid du Colombier 	t = (Tag*)(p->iobuf+BUFSIZE);
2053e12c5d1SDavid du Colombier 	if(t->tag != tag) {
2063e12c5d1SDavid du Colombier 		if(1 || CHAT(0))
207*9a747e4fSDavid du Colombier 			print("	tag = %G; expected %G; addr = %lud\n",
208*9a747e4fSDavid du Colombier 				t->tag, tag, p->addr);
2093e12c5d1SDavid du Colombier 		return 2;
2103e12c5d1SDavid du Colombier 	}
2113e12c5d1SDavid du Colombier 	if(qpath != QPNONE) {
2123e12c5d1SDavid du Colombier 		qpath &= ~QPDIR;
2133e12c5d1SDavid du Colombier 		if(qpath != t->path) {
2143e12c5d1SDavid du Colombier 			if(qpath == (t->path&~QPDIR))	/* old bug */
2153e12c5d1SDavid du Colombier 				return 0;
2163e12c5d1SDavid du Colombier 			if(1 || CHAT(0))
2173e12c5d1SDavid du Colombier 				print("	tag/path = %lux; expected %G/%lux\n",
2183e12c5d1SDavid du Colombier 					t->path, tag, qpath);
2193e12c5d1SDavid du Colombier 			return 1;
2203e12c5d1SDavid du Colombier 		}
2213e12c5d1SDavid du Colombier 	}
2223e12c5d1SDavid du Colombier 	return 0;
2233e12c5d1SDavid du Colombier }
2243e12c5d1SDavid du Colombier 
2253e12c5d1SDavid du Colombier void
settag(Iobuf * p,int tag,long qpath)2263e12c5d1SDavid du Colombier settag(Iobuf *p, int tag, long qpath)
2273e12c5d1SDavid du Colombier {
2283e12c5d1SDavid du Colombier 	Tag *t;
2293e12c5d1SDavid du Colombier 
2303e12c5d1SDavid du Colombier 	t = (Tag*)(p->iobuf+BUFSIZE);
2313e12c5d1SDavid du Colombier 	t->tag = tag;
2323e12c5d1SDavid du Colombier 	if(qpath != QPNONE)
2333e12c5d1SDavid du Colombier 		t->path = qpath & ~QPDIR;
2343e12c5d1SDavid du Colombier 	p->flags |= Bmod;
2353e12c5d1SDavid du Colombier }
236