summaryrefslogtreecommitdiff
path: root/sys/src/cmd/dossrv/iotrack.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/dossrv/iotrack.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/dossrv/iotrack.c')
-rwxr-xr-xsys/src/cmd/dossrv/iotrack.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/sys/src/cmd/dossrv/iotrack.c b/sys/src/cmd/dossrv/iotrack.c
new file mode 100755
index 000000000..2815fa8c7
--- /dev/null
+++ b/sys/src/cmd/dossrv/iotrack.c
@@ -0,0 +1,316 @@
+#include <u.h>
+#include <libc.h>
+#include "iotrack.h"
+#include "dat.h"
+#include "fns.h"
+
+#define HIOB 31 /* a prime */
+#define NIOBUF 80
+
+static Iotrack hiob[HIOB+1]; /* hash buckets + lru list */
+static Iotrack iobuf[NIOBUF]; /* the real ones */
+
+#define UNLINK(p, nx, pr) ((p)->pr->nx = (p)->nx, (p)->nx->pr = (p)->pr)
+
+#define LINK(h, p, nx, pr) ((p)->nx = (h)->nx, (p)->pr = (h), \
+ (h)->nx->pr = (p), (h)->nx = (p))
+
+#define HTOFRONT(h, p) ((h)->hnext != (p) && (UNLINK(p,hnext,hprev), LINK(h,p,hnext,hprev)))
+
+#define TOFRONT(h, p) ((h)->next != (p) && (UNLINK(p, next, prev), LINK(h,p, next, prev)))
+
+Iosect *
+getsect(Xfs *xf, long addr)
+{
+ return getiosect(xf, addr, 1);
+}
+
+Iosect *
+getosect(Xfs *xf, long addr)
+{
+ return getiosect(xf, addr, 0);
+}
+
+Iosect *
+getiosect(Xfs *xf, long addr, int rflag)
+{
+ Iotrack *t;
+ long taddr;
+ int toff;
+ Iosect *p;
+
+ toff = addr % Sect2trk;
+ taddr = addr - toff;
+ t = getiotrack(xf, taddr);
+ if(rflag && (t->flags&BSTALE)){
+ if(tread(t) < 0){
+ unmlock(&t->lock);
+ return 0;
+ }
+ t->flags &= ~BSTALE;
+ }
+ t->ref++;
+ p = t->tp->p[toff];
+ if(p == 0){
+ p = newsect();
+ t->tp->p[toff] = p;
+ p->flags = t->flags&BSTALE;
+ p->lock.key = 0;
+ p->t = t;
+ p->iobuf = t->tp->buf[toff];
+ }
+ unmlock(&t->lock);
+ mlock(&p->lock);
+ return p;
+}
+
+void
+putsect(Iosect *p)
+{
+ Iotrack *t;
+
+ if(canmlock(&p->lock))
+ panic("putsect");
+ t = p->t;
+ mlock(&t->lock);
+ t->flags |= p->flags;
+ p->flags = 0;
+ t->ref--;
+ if(t->flags & BIMM){
+ if(t->flags & BMOD)
+ twrite(t);
+ t->flags &= ~(BMOD|BIMM);
+ }
+ unmlock(&t->lock);
+ unmlock(&p->lock);
+}
+
+Iotrack *
+getiotrack(Xfs *xf, long addr)
+{
+ Iotrack *hp, *p;
+ Iotrack *mp = &hiob[HIOB];
+ long h;
+/*
+ * chat("iotrack %d,%d...", dev, addr);
+ */
+ h = (xf->dev<<24) ^ addr;
+ if(h < 0)
+ h = ~h;
+ h %= HIOB;
+ hp = &hiob[h];
+
+loop:
+
+/*
+ * look for it in the active list
+ */
+ mlock(&hp->lock);
+ for(p=hp->hnext; p != hp; p=p->hnext){
+ if(p->addr != addr || p->xf != xf)
+ continue;
+ unmlock(&hp->lock);
+ mlock(&p->lock);
+ if(p->addr == addr && p->xf == xf)
+ goto out;
+ unmlock(&p->lock);
+ goto loop;
+ }
+ unmlock(&hp->lock);
+/*
+ * not found
+ * take oldest unref'd entry
+ */
+ mlock(&mp->lock);
+ for(p=mp->prev; p != mp; p=p->prev)
+ if(p->ref == 0 && canmlock(&p->lock)){
+ if(p->ref == 0)
+ break;
+ unmlock(&p->lock);
+ }
+ unmlock(&mp->lock);
+ if(p == mp){
+ print("iotrack all ref'd\n");
+ goto loop;
+ }
+ if(p->flags & BMOD){
+ twrite(p);
+ p->flags &= ~(BMOD|BIMM);
+ unmlock(&p->lock);
+ goto loop;
+ }
+ purgetrack(p);
+ p->addr = addr;
+ p->xf = xf;
+ p->flags = BSTALE;
+out:
+ mlock(&hp->lock);
+ HTOFRONT(hp, p);
+ unmlock(&hp->lock);
+ mlock(&mp->lock);
+ TOFRONT(mp, p);
+ unmlock(&mp->lock);
+ return p;
+}
+
+void
+purgetrack(Iotrack *t)
+{
+ int i, ref = Sect2trk;
+ Iosect *p;
+
+ for(i=0; i<Sect2trk; i++){
+ p = t->tp->p[i];
+ if(p == 0){
+ --ref;
+ continue;
+ }
+ if(canmlock(&p->lock)){
+ freesect(p);
+ --ref;
+ t->tp->p[i] = 0;
+ }
+ }
+ if(t->ref != ref)
+ panic("purgetrack");
+}
+
+int
+twrite(Iotrack *t)
+{
+ int i, ref;
+
+ chat("[twrite %ld...", t->addr);
+ if(t->flags & BSTALE){
+ for(ref=0,i=0; i<Sect2trk; i++)
+ if(t->tp->p[i])
+ ++ref;
+ if(ref < Sect2trk){
+ if(tread(t) < 0){
+ chat("error]");
+ return -1;
+ }
+ }else
+ t->flags &= ~BSTALE;
+ }
+ if(devwrite(t->xf, t->addr, t->tp->buf, Trksize) < 0){
+ chat("error]");
+ return -1;
+ }
+ chat(" done]");
+ return 0;
+}
+
+int
+tread(Iotrack *t)
+{
+ int i, ref = 0;
+ uchar buf[Sect2trk][Sectorsize];
+
+ for(i=0; i<Sect2trk; i++)
+ if(t->tp->p[i])
+ ++ref;
+ chat("[tread %ld+%ld...", t->addr, t->xf->offset);
+ if(ref == 0){
+ if(devread(t->xf, t->addr, t->tp->buf, Trksize) < 0){
+ chat("error]");
+ return -1;
+ }
+ chat("done]");
+ t->flags &= ~BSTALE;
+ return 0;
+ }
+ if(devread(t->xf, t->addr, buf, Trksize) < 0){
+ chat("error]");
+ return -1;
+ }
+ for(i=0; i<Sect2trk; i++)
+ if(t->tp->p[i] == 0){
+ memmove(t->tp->buf[i], buf[i], Sectorsize);
+ chat("%d ", i);
+ }
+ chat("done]");
+ t->flags &= ~BSTALE;
+ return 0;
+}
+
+void
+purgebuf(Xfs *xf)
+{
+ Iotrack *p;
+
+ for(p=&iobuf[0]; p<&iobuf[NIOBUF]; p++){
+ if(p->xf != xf)
+ continue;
+ mlock(&p->lock);
+ if(p->xf == xf){
+ if(p->flags & BMOD)
+ twrite(p);
+ p->flags = BSTALE;
+ purgetrack(p);
+ }
+ unmlock(&p->lock);
+ }
+}
+
+void
+sync(void)
+{
+ Iotrack *p;
+
+ for(p=&iobuf[0]; p<&iobuf[NIOBUF]; p++){
+ if(!(p->flags & BMOD))
+ continue;
+ mlock(&p->lock);
+ if(p->flags & BMOD){
+ twrite(p);
+ p->flags &= ~(BMOD|BIMM);
+ }
+ unmlock(&p->lock);
+ }
+}
+
+void
+iotrack_init(void)
+{
+ Iotrack *mp, *p;
+
+ for (mp=&hiob[0]; mp<&hiob[HIOB]; mp++)
+ mp->hprev = mp->hnext = mp;
+ mp->prev = mp->next = mp;
+
+ for (p=&iobuf[0]; p<&iobuf[NIOBUF]; p++) {
+ p->hprev = p->hnext = p;
+ p->prev = p->next = p;
+ TOFRONT(mp, p);
+ p->tp = sbrk(sizeof(Track));
+ memset(p->tp->p, 0, sizeof p->tp->p);
+ }
+}
+
+static MLock freelock;
+static Iosect * freelist;
+
+Iosect *
+newsect(void)
+{
+ Iosect *p;
+
+ mlock(&freelock);
+ if(p = freelist) /* assign = */
+ freelist = p->next;
+ else
+ p = malloc(sizeof(Iosect));
+ unmlock(&freelock);
+ p->next = 0;
+ return p;
+}
+
+void
+freesect(Iosect *p)
+{
+ mlock(&freelock);
+ p->next = freelist;
+ freelist = p;
+ unmlock(&freelock);
+}