13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier #include "iotrack.h" 43e12c5d1SDavid du Colombier #include "dat.h" 53e12c5d1SDavid du Colombier #include "fns.h" 63e12c5d1SDavid du Colombier 73e12c5d1SDavid du Colombier #define HIOB 31 /* a prime */ 83e12c5d1SDavid du Colombier #define NIOBUF 80 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier static Iotrack hiob[HIOB+1]; /* hash buckets + lru list */ 113e12c5d1SDavid du Colombier static Iotrack iobuf[NIOBUF]; /* the real ones */ 123e12c5d1SDavid du Colombier 133e12c5d1SDavid du Colombier #define UNLINK(p, nx, pr) ((p)->pr->nx = (p)->nx, (p)->nx->pr = (p)->pr) 143e12c5d1SDavid du Colombier 153e12c5d1SDavid du Colombier #define LINK(h, p, nx, pr) ((p)->nx = (h)->nx, (p)->pr = (h), \ 163e12c5d1SDavid du Colombier (h)->nx->pr = (p), (h)->nx = (p)) 173e12c5d1SDavid du Colombier 183e12c5d1SDavid du Colombier #define HTOFRONT(h, p) ((h)->hnext != (p) ? (UNLINK(p,hnext,hprev), LINK(h,p,hnext,hprev)) : 0) 193e12c5d1SDavid du Colombier 203e12c5d1SDavid du Colombier #define TOFRONT(h, p) ((h)->next != (p) ? (UNLINK(p, next, prev), LINK(h,p, next, prev)) : 0) 213e12c5d1SDavid du Colombier 223e12c5d1SDavid du Colombier Iosect * 233e12c5d1SDavid du Colombier getsect(Xfs *xf, long addr) 243e12c5d1SDavid du Colombier { 253e12c5d1SDavid du Colombier return getiosect(xf, addr, 1); 263e12c5d1SDavid du Colombier } 273e12c5d1SDavid du Colombier 283e12c5d1SDavid du Colombier Iosect * 293e12c5d1SDavid du Colombier getosect(Xfs *xf, long addr) 303e12c5d1SDavid du Colombier { 313e12c5d1SDavid du Colombier return getiosect(xf, addr, 0); 323e12c5d1SDavid du Colombier } 333e12c5d1SDavid du Colombier 343e12c5d1SDavid du Colombier Iosect * 353e12c5d1SDavid du Colombier getiosect(Xfs *xf, long addr, int rflag) 363e12c5d1SDavid du Colombier { 373e12c5d1SDavid du Colombier Iotrack *t; 383e12c5d1SDavid du Colombier long taddr; 393e12c5d1SDavid du Colombier int toff; 403e12c5d1SDavid du Colombier Iosect *p; 413e12c5d1SDavid du Colombier 423e12c5d1SDavid du Colombier toff = addr % Sect2trk; 433e12c5d1SDavid du Colombier taddr = addr - toff; 443e12c5d1SDavid du Colombier t = getiotrack(xf, taddr); 453e12c5d1SDavid du Colombier if(rflag && (t->flags&BSTALE)){ 463e12c5d1SDavid du Colombier if(tread(t) < 0){ 473e12c5d1SDavid du Colombier unlock(&t->lock); 483e12c5d1SDavid du Colombier return 0; 493e12c5d1SDavid du Colombier } 503e12c5d1SDavid du Colombier t->flags &= ~BSTALE; 513e12c5d1SDavid du Colombier } 523e12c5d1SDavid du Colombier t->ref++; 533e12c5d1SDavid du Colombier p = t->tp->p[toff]; 543e12c5d1SDavid du Colombier if(p == 0){ 553e12c5d1SDavid du Colombier p = newsect(); 563e12c5d1SDavid du Colombier t->tp->p[toff] = p; 573e12c5d1SDavid du Colombier p->flags = t->flags&BSTALE; 583e12c5d1SDavid du Colombier p->lock.key = 0; 593e12c5d1SDavid du Colombier p->t = t; 603e12c5d1SDavid du Colombier p->iobuf = t->tp->buf[toff]; 613e12c5d1SDavid du Colombier } 623e12c5d1SDavid du Colombier unlock(&t->lock); 633e12c5d1SDavid du Colombier lock(&p->lock); 643e12c5d1SDavid du Colombier return p; 653e12c5d1SDavid du Colombier } 663e12c5d1SDavid du Colombier 673e12c5d1SDavid du Colombier void 683e12c5d1SDavid du Colombier putsect(Iosect *p) 693e12c5d1SDavid du Colombier { 703e12c5d1SDavid du Colombier Iotrack *t; 713e12c5d1SDavid du Colombier 723e12c5d1SDavid du Colombier if(canlock(&p->lock)) 733e12c5d1SDavid du Colombier panic("putsect"); 743e12c5d1SDavid du Colombier t = p->t; 753e12c5d1SDavid du Colombier lock(&t->lock); 763e12c5d1SDavid du Colombier t->flags |= p->flags; 773e12c5d1SDavid du Colombier p->flags = 0; 783e12c5d1SDavid du Colombier t->ref--; 793e12c5d1SDavid du Colombier if(t->flags & BIMM){ 803e12c5d1SDavid du Colombier if(t->flags & BMOD) 813e12c5d1SDavid du Colombier twrite(t); 823e12c5d1SDavid du Colombier t->flags &= ~(BMOD|BIMM); 833e12c5d1SDavid du Colombier } 843e12c5d1SDavid du Colombier unlock(&t->lock); 853e12c5d1SDavid du Colombier unlock(&p->lock); 863e12c5d1SDavid du Colombier } 873e12c5d1SDavid du Colombier 883e12c5d1SDavid du Colombier Iotrack * 893e12c5d1SDavid du Colombier getiotrack(Xfs *xf, long addr) 903e12c5d1SDavid du Colombier { 913e12c5d1SDavid du Colombier Iotrack *hp, *p; 923e12c5d1SDavid du Colombier Iotrack *mp = &hiob[HIOB]; 933e12c5d1SDavid du Colombier long h; 943e12c5d1SDavid du Colombier /* 953e12c5d1SDavid du Colombier * chat("iotrack %d,%d...", dev, addr); 963e12c5d1SDavid du Colombier */ 973e12c5d1SDavid du Colombier h = (xf->dev<<24) ^ addr; 983e12c5d1SDavid du Colombier if(h < 0) 993e12c5d1SDavid du Colombier h = ~h; 1003e12c5d1SDavid du Colombier h %= HIOB; 1013e12c5d1SDavid du Colombier hp = &hiob[h]; 1023e12c5d1SDavid du Colombier 1033e12c5d1SDavid du Colombier loop: 1043e12c5d1SDavid du Colombier 1053e12c5d1SDavid du Colombier /* 1063e12c5d1SDavid du Colombier * look for it in the active list 1073e12c5d1SDavid du Colombier */ 1083e12c5d1SDavid du Colombier lock(&hp->lock); 1093e12c5d1SDavid du Colombier for(p=hp->hnext; p != hp; p=p->hnext){ 1103e12c5d1SDavid du Colombier if(p->addr != addr || p->xf != xf) 1113e12c5d1SDavid du Colombier continue; 1123e12c5d1SDavid du Colombier unlock(&hp->lock); 1133e12c5d1SDavid du Colombier lock(&p->lock); 1143e12c5d1SDavid du Colombier if(p->addr == addr && p->xf == xf) 1153e12c5d1SDavid du Colombier goto out; 1163e12c5d1SDavid du Colombier unlock(&p->lock); 1173e12c5d1SDavid du Colombier goto loop; 1183e12c5d1SDavid du Colombier } 1193e12c5d1SDavid du Colombier unlock(&hp->lock); 1203e12c5d1SDavid du Colombier /* 1213e12c5d1SDavid du Colombier * not found 1223e12c5d1SDavid du Colombier * take oldest unref'd entry 1233e12c5d1SDavid du Colombier */ 1243e12c5d1SDavid du Colombier lock(&mp->lock); 1253e12c5d1SDavid du Colombier for(p=mp->prev; p != mp; p=p->prev) 1263e12c5d1SDavid du Colombier if(p->ref == 0 && canlock(&p->lock)){ 1273e12c5d1SDavid du Colombier if(p->ref == 0) 1283e12c5d1SDavid du Colombier break; 1293e12c5d1SDavid du Colombier unlock(&p->lock); 1303e12c5d1SDavid du Colombier } 1313e12c5d1SDavid du Colombier unlock(&mp->lock); 1323e12c5d1SDavid du Colombier if(p == mp){ 1333e12c5d1SDavid du Colombier print("iotrack all ref'd\n"); 1343e12c5d1SDavid du Colombier goto loop; 1353e12c5d1SDavid du Colombier } 1363e12c5d1SDavid du Colombier if(p->flags & BMOD){ 1373e12c5d1SDavid du Colombier twrite(p); 1383e12c5d1SDavid du Colombier p->flags &= ~(BMOD|BIMM); 1393e12c5d1SDavid du Colombier unlock(&p->lock); 1403e12c5d1SDavid du Colombier goto loop; 1413e12c5d1SDavid du Colombier } 1423e12c5d1SDavid du Colombier purgetrack(p); 1433e12c5d1SDavid du Colombier p->addr = addr; 1443e12c5d1SDavid du Colombier p->xf = xf; 1453e12c5d1SDavid du Colombier p->flags = BSTALE; 1463e12c5d1SDavid du Colombier out: 1473e12c5d1SDavid du Colombier lock(&hp->lock); HTOFRONT(hp, p); unlock(&hp->lock); 1483e12c5d1SDavid du Colombier lock(&mp->lock); TOFRONT(mp, p); unlock(&mp->lock); 1493e12c5d1SDavid du Colombier return p; 1503e12c5d1SDavid du Colombier } 1513e12c5d1SDavid du Colombier 1523e12c5d1SDavid du Colombier void 1533e12c5d1SDavid du Colombier purgetrack(Iotrack *t) 1543e12c5d1SDavid du Colombier { 1553e12c5d1SDavid du Colombier int i, ref = Sect2trk; 1563e12c5d1SDavid du Colombier Iosect *p; 1573e12c5d1SDavid du Colombier 1583e12c5d1SDavid du Colombier for(i=0; i<Sect2trk; i++){ 1593e12c5d1SDavid du Colombier p = t->tp->p[i]; 1603e12c5d1SDavid du Colombier if(p == 0){ 1613e12c5d1SDavid du Colombier --ref; 1623e12c5d1SDavid du Colombier continue; 1633e12c5d1SDavid du Colombier } 1643e12c5d1SDavid du Colombier if(canlock(&p->lock)){ 1653e12c5d1SDavid du Colombier freesect(p); 1663e12c5d1SDavid du Colombier --ref; 1673e12c5d1SDavid du Colombier t->tp->p[i] = 0; 1683e12c5d1SDavid du Colombier } 1693e12c5d1SDavid du Colombier } 1703e12c5d1SDavid du Colombier if(t->ref != ref) 1713e12c5d1SDavid du Colombier panic("purgetrack"); 1723e12c5d1SDavid du Colombier } 1733e12c5d1SDavid du Colombier 1743e12c5d1SDavid du Colombier int 1753e12c5d1SDavid du Colombier twrite(Iotrack *t) 1763e12c5d1SDavid du Colombier { 1773e12c5d1SDavid du Colombier int i, ref; 1783e12c5d1SDavid du Colombier 1793e12c5d1SDavid du Colombier chat("[twrite %d...", t->addr); 1803e12c5d1SDavid du Colombier if(t->flags & BSTALE){ 1813e12c5d1SDavid du Colombier for(ref=0,i=0; i<Sect2trk; i++) 1823e12c5d1SDavid du Colombier if(t->tp->p[i]) 1833e12c5d1SDavid du Colombier ++ref; 1843e12c5d1SDavid du Colombier if(ref < Sect2trk){ 1853e12c5d1SDavid du Colombier if(tread(t) < 0){ 1863e12c5d1SDavid du Colombier chat("error]"); 1873e12c5d1SDavid du Colombier return -1; 1883e12c5d1SDavid du Colombier } 1893e12c5d1SDavid du Colombier }else 1903e12c5d1SDavid du Colombier t->flags &= ~BSTALE; 1913e12c5d1SDavid du Colombier } 1923e12c5d1SDavid du Colombier if(devwrite(t->xf, t->addr, t->tp->buf, Trksize) < 0){ 1933e12c5d1SDavid du Colombier chat("error]"); 1943e12c5d1SDavid du Colombier return -1; 1953e12c5d1SDavid du Colombier } 1963e12c5d1SDavid du Colombier chat(" done]"); 1973e12c5d1SDavid du Colombier return 0; 1983e12c5d1SDavid du Colombier } 1993e12c5d1SDavid du Colombier 2003e12c5d1SDavid du Colombier int 2013e12c5d1SDavid du Colombier tread(Iotrack *t) 2023e12c5d1SDavid du Colombier { 2033e12c5d1SDavid du Colombier int i, ref = 0; 2043e12c5d1SDavid du Colombier uchar buf[Sect2trk][Sectorsize]; 2053e12c5d1SDavid du Colombier 2063e12c5d1SDavid du Colombier for(i=0; i<Sect2trk; i++) 2073e12c5d1SDavid du Colombier if(t->tp->p[i]) 2083e12c5d1SDavid du Colombier ++ref; 2093e12c5d1SDavid du Colombier chat("[tread %d...", t->addr); 2103e12c5d1SDavid du Colombier if(ref == 0){ 2113e12c5d1SDavid du Colombier if(devread(t->xf, t->addr, t->tp->buf, Trksize) < 0){ 2123e12c5d1SDavid du Colombier chat("error]"); 2133e12c5d1SDavid du Colombier return -1; 2143e12c5d1SDavid du Colombier } 2153e12c5d1SDavid du Colombier chat("done]"); 2163e12c5d1SDavid du Colombier t->flags &= ~BSTALE; 2173e12c5d1SDavid du Colombier return 0; 2183e12c5d1SDavid du Colombier } 2193e12c5d1SDavid du Colombier if(devread(t->xf, t->addr, buf, Trksize) < 0){ 2203e12c5d1SDavid du Colombier chat("error]"); 2213e12c5d1SDavid du Colombier return -1; 2223e12c5d1SDavid du Colombier } 2233e12c5d1SDavid du Colombier for(i=0; i<Sect2trk; i++) 2243e12c5d1SDavid du Colombier if(t->tp->p[i] == 0){ 2253e12c5d1SDavid du Colombier memmove(t->tp->buf[i], buf[i], Sectorsize); 2263e12c5d1SDavid du Colombier chat("%d ", i); 2273e12c5d1SDavid du Colombier } 2283e12c5d1SDavid du Colombier chat("done]"); 2293e12c5d1SDavid du Colombier t->flags &= ~BSTALE; 2303e12c5d1SDavid du Colombier return 0; 2313e12c5d1SDavid du Colombier } 2323e12c5d1SDavid du Colombier 2333e12c5d1SDavid du Colombier void 2343e12c5d1SDavid du Colombier purgebuf(Xfs *xf) 2353e12c5d1SDavid du Colombier { 2363e12c5d1SDavid du Colombier Iotrack *p; 2373e12c5d1SDavid du Colombier 2383e12c5d1SDavid du Colombier for(p=&iobuf[0]; p<&iobuf[NIOBUF]; p++){ 2393e12c5d1SDavid du Colombier if(p->xf != xf) 2403e12c5d1SDavid du Colombier continue; 2413e12c5d1SDavid du Colombier lock(&p->lock); 2423e12c5d1SDavid du Colombier if(p->xf == xf){ 2433e12c5d1SDavid du Colombier if(p->flags & BMOD) 2443e12c5d1SDavid du Colombier twrite(p); 2453e12c5d1SDavid du Colombier p->flags = BSTALE; 2463e12c5d1SDavid du Colombier purgetrack(p); 2473e12c5d1SDavid du Colombier } 2483e12c5d1SDavid du Colombier unlock(&p->lock); 2493e12c5d1SDavid du Colombier } 2503e12c5d1SDavid du Colombier } 2513e12c5d1SDavid du Colombier 2523e12c5d1SDavid du Colombier void 2533e12c5d1SDavid du Colombier sync(void) 2543e12c5d1SDavid du Colombier { 2553e12c5d1SDavid du Colombier Iotrack *p; 2563e12c5d1SDavid du Colombier 2573e12c5d1SDavid du Colombier for(p=&iobuf[0]; p<&iobuf[NIOBUF]; p++){ 2583e12c5d1SDavid du Colombier if(!(p->flags & BMOD)) 2593e12c5d1SDavid du Colombier continue; 2603e12c5d1SDavid du Colombier lock(&p->lock); 2613e12c5d1SDavid du Colombier if(p->flags & BMOD){ 2623e12c5d1SDavid du Colombier twrite(p); 2633e12c5d1SDavid du Colombier p->flags &= ~(BMOD|BIMM); 2643e12c5d1SDavid du Colombier } 2653e12c5d1SDavid du Colombier unlock(&p->lock); 2663e12c5d1SDavid du Colombier } 2673e12c5d1SDavid du Colombier } 2683e12c5d1SDavid du Colombier 2693e12c5d1SDavid du Colombier void 2703e12c5d1SDavid du Colombier iotrack_init(void) 2713e12c5d1SDavid du Colombier { 2723e12c5d1SDavid du Colombier Iotrack *mp, *p; 2733e12c5d1SDavid du Colombier 2743e12c5d1SDavid du Colombier for (mp=&hiob[0]; mp<&hiob[HIOB]; mp++) 2753e12c5d1SDavid du Colombier mp->hprev = mp->hnext = mp; 2763e12c5d1SDavid du Colombier mp->prev = mp->next = mp; 2773e12c5d1SDavid du Colombier 2783e12c5d1SDavid du Colombier for (p=&iobuf[0]; p<&iobuf[NIOBUF]; p++) { 2793e12c5d1SDavid du Colombier p->hprev = p->hnext = p; 2803e12c5d1SDavid du Colombier p->prev = p->next = p; 2813e12c5d1SDavid du Colombier TOFRONT(mp, p); 282*219b2ee8SDavid du Colombier p->tp = sbrk(sizeof(Track)); 2833e12c5d1SDavid du Colombier memset(p->tp->p, 0, sizeof p->tp->p); 2843e12c5d1SDavid du Colombier } 2853e12c5d1SDavid du Colombier } 2863e12c5d1SDavid du Colombier 2873e12c5d1SDavid du Colombier static Lock freelock; 2883e12c5d1SDavid du Colombier static Iosect * freelist; 2893e12c5d1SDavid du Colombier 2903e12c5d1SDavid du Colombier Iosect * 2913e12c5d1SDavid du Colombier newsect(void) 2923e12c5d1SDavid du Colombier { 2933e12c5d1SDavid du Colombier Iosect *p; 2943e12c5d1SDavid du Colombier 2953e12c5d1SDavid du Colombier lock(&freelock); 2963e12c5d1SDavid du Colombier if(p = freelist) /* assign = */ 2973e12c5d1SDavid du Colombier freelist = p->next; 2983e12c5d1SDavid du Colombier else 2993e12c5d1SDavid du Colombier p = malloc(sizeof(Iosect)); 3003e12c5d1SDavid du Colombier unlock(&freelock); 3013e12c5d1SDavid du Colombier p->next = 0; 3023e12c5d1SDavid du Colombier return p; 3033e12c5d1SDavid du Colombier } 3043e12c5d1SDavid du Colombier 3053e12c5d1SDavid du Colombier void 3063e12c5d1SDavid du Colombier freesect(Iosect *p) 3073e12c5d1SDavid du Colombier { 3083e12c5d1SDavid du Colombier lock(&freelock); 3093e12c5d1SDavid du Colombier p->next = freelist; 3103e12c5d1SDavid du Colombier freelist = p; 3113e12c5d1SDavid du Colombier unlock(&freelock); 3123e12c5d1SDavid du Colombier } 313