1*3ff48bf5SDavid du Colombier #include <u.h> 2*3ff48bf5SDavid du Colombier #include <libc.h> 3*3ff48bf5SDavid du Colombier #include <auth.h> 4*3ff48bf5SDavid du Colombier #include <fcall.h> 5*3ff48bf5SDavid du Colombier #include <thread.h> 6*3ff48bf5SDavid du Colombier #include <9p.h> 7*3ff48bf5SDavid du Colombier 8*3ff48bf5SDavid du Colombier typedef struct Part Part; 9*3ff48bf5SDavid du Colombier typedef struct Trip Trip; 10*3ff48bf5SDavid du Colombier typedef struct Dbl Dbl; 11*3ff48bf5SDavid du Colombier typedef struct Ind Ind; 12*3ff48bf5SDavid du Colombier 13*3ff48bf5SDavid du Colombier /* 14*3ff48bf5SDavid du Colombier * with 8192-byte blocks and 4-byte pointers, 15*3ff48bf5SDavid du Colombier * double-indirect gets us 34 GB. 16*3ff48bf5SDavid du Colombier * triple-indirect gets us 70,368 GB. 17*3ff48bf5SDavid du Colombier */ 18*3ff48bf5SDavid du Colombier 19*3ff48bf5SDavid du Colombier enum 20*3ff48bf5SDavid du Colombier { 21*3ff48bf5SDavid du Colombier LOGBLKSZ = 13, 22*3ff48bf5SDavid du Colombier BLKSZ = 1<<LOGBLKSZ, /* 8192 */ 23*3ff48bf5SDavid du Colombier LOGNPTR = LOGBLKSZ-2, /* assume sizeof(void*) == 4 */ 24*3ff48bf5SDavid du Colombier NPTR = 1<<LOGNPTR, 25*3ff48bf5SDavid du Colombier }; 26*3ff48bf5SDavid du Colombier 27*3ff48bf5SDavid du Colombier struct Trip 28*3ff48bf5SDavid du Colombier { 29*3ff48bf5SDavid du Colombier Dbl *dbl[NPTR]; 30*3ff48bf5SDavid du Colombier }; 31*3ff48bf5SDavid du Colombier 32*3ff48bf5SDavid du Colombier struct Dbl 33*3ff48bf5SDavid du Colombier { 34*3ff48bf5SDavid du Colombier Ind *ind[NPTR]; 35*3ff48bf5SDavid du Colombier }; 36*3ff48bf5SDavid du Colombier 37*3ff48bf5SDavid du Colombier struct Ind 38*3ff48bf5SDavid du Colombier { 39*3ff48bf5SDavid du Colombier uchar *blk[NPTR]; 40*3ff48bf5SDavid du Colombier }; 41*3ff48bf5SDavid du Colombier 42*3ff48bf5SDavid du Colombier Trip trip; 43*3ff48bf5SDavid du Colombier 44*3ff48bf5SDavid du Colombier struct Part 45*3ff48bf5SDavid du Colombier { 46*3ff48bf5SDavid du Colombier int inuse; 47*3ff48bf5SDavid du Colombier int vers; 48*3ff48bf5SDavid du Colombier ulong mode; 49*3ff48bf5SDavid du Colombier char *name; 50*3ff48bf5SDavid du Colombier vlong offset; /* in sectors */ 51*3ff48bf5SDavid du Colombier vlong length; /* in sectors */ 52*3ff48bf5SDavid du Colombier }; 53*3ff48bf5SDavid du Colombier 54*3ff48bf5SDavid du Colombier enum 55*3ff48bf5SDavid du Colombier { 56*3ff48bf5SDavid du Colombier Qroot = 0, 57*3ff48bf5SDavid du Colombier Qdir, 58*3ff48bf5SDavid du Colombier Qctl, 59*3ff48bf5SDavid du Colombier Qpart, 60*3ff48bf5SDavid du Colombier }; 61*3ff48bf5SDavid du Colombier 62*3ff48bf5SDavid du Colombier Part tab[64]; 63*3ff48bf5SDavid du Colombier 64*3ff48bf5SDavid du Colombier char *sdname = "sdXX"; 65*3ff48bf5SDavid du Colombier ulong ctlmode = 0666; 66*3ff48bf5SDavid du Colombier char *inquiry = "aux/disksim hard drive"; 67*3ff48bf5SDavid du Colombier vlong nsect, sectsize, c, h, s; 68*3ff48bf5SDavid du Colombier ulong time0; 69*3ff48bf5SDavid du Colombier 70*3ff48bf5SDavid du Colombier char* 71*3ff48bf5SDavid du Colombier ctlstring(void) 72*3ff48bf5SDavid du Colombier { 73*3ff48bf5SDavid du Colombier int i; 74*3ff48bf5SDavid du Colombier Fmt fmt; 75*3ff48bf5SDavid du Colombier 76*3ff48bf5SDavid du Colombier fmtstrinit(&fmt); 77*3ff48bf5SDavid du Colombier fmtprint(&fmt, "inquiry %s\n", inquiry); 78*3ff48bf5SDavid du Colombier fmtprint(&fmt, "geometry %lld %lld %lld %lld %lld\n", nsect, sectsize, c, h, s); 79*3ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++) 80*3ff48bf5SDavid du Colombier if(tab[i].inuse) 81*3ff48bf5SDavid du Colombier fmtprint(&fmt, "part %s %lld %lld\n", tab[i].name, tab[i].offset, tab[i].length); 82*3ff48bf5SDavid du Colombier return fmtstrflush(&fmt); 83*3ff48bf5SDavid du Colombier } 84*3ff48bf5SDavid du Colombier 85*3ff48bf5SDavid du Colombier int 86*3ff48bf5SDavid du Colombier addpart(char *name, vlong start, vlong end) 87*3ff48bf5SDavid du Colombier { 88*3ff48bf5SDavid du Colombier int i; 89*3ff48bf5SDavid du Colombier 90*3ff48bf5SDavid du Colombier if(start < 0 || start > end || end > nsect){ 91*3ff48bf5SDavid du Colombier werrstr("bad partition boundaries"); 92*3ff48bf5SDavid du Colombier return -1; 93*3ff48bf5SDavid du Colombier } 94*3ff48bf5SDavid du Colombier 95*3ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++) 96*3ff48bf5SDavid du Colombier if(tab[i].inuse == 0) 97*3ff48bf5SDavid du Colombier break; 98*3ff48bf5SDavid du Colombier if(i == nelem(tab)){ 99*3ff48bf5SDavid du Colombier werrstr("no free partition slots"); 100*3ff48bf5SDavid du Colombier return -1; 101*3ff48bf5SDavid du Colombier } 102*3ff48bf5SDavid du Colombier 103*3ff48bf5SDavid du Colombier free(tab[i].name); 104*3ff48bf5SDavid du Colombier tab[i].inuse = 1; 105*3ff48bf5SDavid du Colombier tab[i].name = estrdup9p(name); 106*3ff48bf5SDavid du Colombier tab[i].offset = start; 107*3ff48bf5SDavid du Colombier tab[i].length = end - start; 108*3ff48bf5SDavid du Colombier tab[i].mode = ctlmode; 109*3ff48bf5SDavid du Colombier tab[i].vers++; 110*3ff48bf5SDavid du Colombier 111*3ff48bf5SDavid du Colombier return 0; 112*3ff48bf5SDavid du Colombier } 113*3ff48bf5SDavid du Colombier 114*3ff48bf5SDavid du Colombier int 115*3ff48bf5SDavid du Colombier delpart(char *s) 116*3ff48bf5SDavid du Colombier { 117*3ff48bf5SDavid du Colombier int i; 118*3ff48bf5SDavid du Colombier 119*3ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++) 120*3ff48bf5SDavid du Colombier if(tab[i].inuse && strcmp(tab[i].name, s) == 0) 121*3ff48bf5SDavid du Colombier break; 122*3ff48bf5SDavid du Colombier if(i==nelem(tab)){ 123*3ff48bf5SDavid du Colombier werrstr("partition not found"); 124*3ff48bf5SDavid du Colombier return -1; 125*3ff48bf5SDavid du Colombier } 126*3ff48bf5SDavid du Colombier 127*3ff48bf5SDavid du Colombier tab[i].inuse = 0; 128*3ff48bf5SDavid du Colombier free(tab[i].name); 129*3ff48bf5SDavid du Colombier tab[i].name = 0; 130*3ff48bf5SDavid du Colombier return 0; 131*3ff48bf5SDavid du Colombier } 132*3ff48bf5SDavid du Colombier 133*3ff48bf5SDavid du Colombier void 134*3ff48bf5SDavid du Colombier ctlwrite(Req *r) 135*3ff48bf5SDavid du Colombier { 136*3ff48bf5SDavid du Colombier int i; 137*3ff48bf5SDavid du Colombier Cmdbuf *cb; 138*3ff48bf5SDavid du Colombier vlong start, end; 139*3ff48bf5SDavid du Colombier 140*3ff48bf5SDavid du Colombier r->ofcall.count = r->ifcall.count; 141*3ff48bf5SDavid du Colombier cb = parsecmd(r->ifcall.data, r->ifcall.count); 142*3ff48bf5SDavid du Colombier if(cb->nf < 1){ 143*3ff48bf5SDavid du Colombier respond(r, "empty control message"); 144*3ff48bf5SDavid du Colombier free(cb); 145*3ff48bf5SDavid du Colombier return; 146*3ff48bf5SDavid du Colombier } 147*3ff48bf5SDavid du Colombier 148*3ff48bf5SDavid du Colombier if(strcmp(cb->f[0], "part") == 0){ 149*3ff48bf5SDavid du Colombier if(cb->nf != 4){ 150*3ff48bf5SDavid du Colombier respondcmderror(r, cb, "part takes 3 args"); 151*3ff48bf5SDavid du Colombier free(cb); 152*3ff48bf5SDavid du Colombier return; 153*3ff48bf5SDavid du Colombier } 154*3ff48bf5SDavid du Colombier start = strtoll(cb->f[2], 0, 0); 155*3ff48bf5SDavid du Colombier end = strtoll(cb->f[3], 0, 0); 156*3ff48bf5SDavid du Colombier if(addpart(cb->f[1], start, end) < 0){ 157*3ff48bf5SDavid du Colombier respondcmderror(r, cb, "%r"); 158*3ff48bf5SDavid du Colombier free(cb); 159*3ff48bf5SDavid du Colombier return; 160*3ff48bf5SDavid du Colombier } 161*3ff48bf5SDavid du Colombier } 162*3ff48bf5SDavid du Colombier else if(strcmp(cb->f[0], "delpart") == 0){ 163*3ff48bf5SDavid du Colombier if(cb->nf != 2){ 164*3ff48bf5SDavid du Colombier respondcmderror(r, cb, "delpart takes 1 arg"); 165*3ff48bf5SDavid du Colombier free(cb); 166*3ff48bf5SDavid du Colombier return; 167*3ff48bf5SDavid du Colombier } 168*3ff48bf5SDavid du Colombier if(delpart(cb->f[1]) < 0){ 169*3ff48bf5SDavid du Colombier respondcmderror(r, cb, "%r"); 170*3ff48bf5SDavid du Colombier free(cb); 171*3ff48bf5SDavid du Colombier return; 172*3ff48bf5SDavid du Colombier } 173*3ff48bf5SDavid du Colombier } 174*3ff48bf5SDavid du Colombier else if(strcmp(cb->f[0], "inquiry") == 0){ 175*3ff48bf5SDavid du Colombier if(cb->nf != 2){ 176*3ff48bf5SDavid du Colombier respondcmderror(r, cb, "inquiry takes 1 arg"); 177*3ff48bf5SDavid du Colombier free(cb); 178*3ff48bf5SDavid du Colombier return; 179*3ff48bf5SDavid du Colombier } 180*3ff48bf5SDavid du Colombier free(inquiry); 181*3ff48bf5SDavid du Colombier inquiry = estrdup9p(cb->f[1]); 182*3ff48bf5SDavid du Colombier } 183*3ff48bf5SDavid du Colombier else if(strcmp(cb->f[0], "geometry") == 0){ 184*3ff48bf5SDavid du Colombier if(cb->nf != 6){ 185*3ff48bf5SDavid du Colombier respondcmderror(r, cb, "geometry takes 5 args"); 186*3ff48bf5SDavid du Colombier free(cb); 187*3ff48bf5SDavid du Colombier return; 188*3ff48bf5SDavid du Colombier } 189*3ff48bf5SDavid du Colombier nsect = strtoll(cb->f[1], 0, 0); 190*3ff48bf5SDavid du Colombier sectsize = strtoll(cb->f[2], 0, 0); 191*3ff48bf5SDavid du Colombier c = strtoll(cb->f[3], 0, 0); 192*3ff48bf5SDavid du Colombier h = strtoll(cb->f[4], 0, 0); 193*3ff48bf5SDavid du Colombier s = strtoll(cb->f[5], 0, 0); 194*3ff48bf5SDavid du Colombier if(tab[0].inuse && strcmp(tab[0].name, "data") == 0 && tab[0].vers == 0){ 195*3ff48bf5SDavid du Colombier tab[0].offset = 0; 196*3ff48bf5SDavid du Colombier tab[0].length = nsect; 197*3ff48bf5SDavid du Colombier } 198*3ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++){ 199*3ff48bf5SDavid du Colombier if(tab[i].inuse && tab[i].offset+tab[i].length > nsect){ 200*3ff48bf5SDavid du Colombier tab[i].inuse = 0; 201*3ff48bf5SDavid du Colombier free(tab[i].name); 202*3ff48bf5SDavid du Colombier tab[i].name = 0; 203*3ff48bf5SDavid du Colombier } 204*3ff48bf5SDavid du Colombier } 205*3ff48bf5SDavid du Colombier } 206*3ff48bf5SDavid du Colombier else{ 207*3ff48bf5SDavid du Colombier respondcmderror(r, cb, "unknown control message"); 208*3ff48bf5SDavid du Colombier free(cb); 209*3ff48bf5SDavid du Colombier return; 210*3ff48bf5SDavid du Colombier } 211*3ff48bf5SDavid du Colombier 212*3ff48bf5SDavid du Colombier free(cb); 213*3ff48bf5SDavid du Colombier respond(r, nil); 214*3ff48bf5SDavid du Colombier } 215*3ff48bf5SDavid du Colombier 216*3ff48bf5SDavid du Colombier void* 217*3ff48bf5SDavid du Colombier allocblk(void) 218*3ff48bf5SDavid du Colombier { 219*3ff48bf5SDavid du Colombier uchar *op; 220*3ff48bf5SDavid du Colombier static uchar *p; 221*3ff48bf5SDavid du Colombier static ulong n; 222*3ff48bf5SDavid du Colombier 223*3ff48bf5SDavid du Colombier if(n == 0){ 224*3ff48bf5SDavid du Colombier p = malloc(4*1024*1024); 225*3ff48bf5SDavid du Colombier if(p == 0) 226*3ff48bf5SDavid du Colombier sysfatal("out of memory"); 227*3ff48bf5SDavid du Colombier n = 4*1024*1024; 228*3ff48bf5SDavid du Colombier } 229*3ff48bf5SDavid du Colombier op = p; 230*3ff48bf5SDavid du Colombier p += BLKSZ; 231*3ff48bf5SDavid du Colombier n -= BLKSZ; 232*3ff48bf5SDavid du Colombier memset(op, 0, BLKSZ); 233*3ff48bf5SDavid du Colombier return op; 234*3ff48bf5SDavid du Colombier } 235*3ff48bf5SDavid du Colombier 236*3ff48bf5SDavid du Colombier uchar* 237*3ff48bf5SDavid du Colombier getblock(vlong addr, int alloc) 238*3ff48bf5SDavid du Colombier { 239*3ff48bf5SDavid du Colombier static uchar zero[BLKSZ]; 240*3ff48bf5SDavid du Colombier Dbl *p2; 241*3ff48bf5SDavid du Colombier Ind *p1; 242*3ff48bf5SDavid du Colombier uchar *p0; 243*3ff48bf5SDavid du Colombier uint i0, i1, i2; 244*3ff48bf5SDavid du Colombier 245*3ff48bf5SDavid du Colombier addr >>= LOGBLKSZ; 246*3ff48bf5SDavid du Colombier i0 = addr & (NPTR-1); 247*3ff48bf5SDavid du Colombier addr >>= LOGNPTR; 248*3ff48bf5SDavid du Colombier i1 = addr & (NPTR-1); 249*3ff48bf5SDavid du Colombier addr >>= LOGNPTR; 250*3ff48bf5SDavid du Colombier i2 = addr & (NPTR-1); 251*3ff48bf5SDavid du Colombier addr >>= LOGNPTR; 252*3ff48bf5SDavid du Colombier assert(addr == 0); 253*3ff48bf5SDavid du Colombier 254*3ff48bf5SDavid du Colombier if((p2 = trip.dbl[i2]) == 0){ 255*3ff48bf5SDavid du Colombier if(!alloc) 256*3ff48bf5SDavid du Colombier return zero; 257*3ff48bf5SDavid du Colombier trip.dbl[i2] = p2 = allocblk(); 258*3ff48bf5SDavid du Colombier } 259*3ff48bf5SDavid du Colombier 260*3ff48bf5SDavid du Colombier if((p1 = p2->ind[i1]) == 0){ 261*3ff48bf5SDavid du Colombier if(!alloc) 262*3ff48bf5SDavid du Colombier return zero; 263*3ff48bf5SDavid du Colombier p2->ind[i1] = p1 = allocblk(); 264*3ff48bf5SDavid du Colombier } 265*3ff48bf5SDavid du Colombier 266*3ff48bf5SDavid du Colombier if((p0 = p1->blk[i0]) == 0){ 267*3ff48bf5SDavid du Colombier if(!alloc) 268*3ff48bf5SDavid du Colombier return zero; 269*3ff48bf5SDavid du Colombier p1->blk[i0] = p0 = allocblk(); 270*3ff48bf5SDavid du Colombier } 271*3ff48bf5SDavid du Colombier return p0; 272*3ff48bf5SDavid du Colombier } 273*3ff48bf5SDavid du Colombier 274*3ff48bf5SDavid du Colombier int 275*3ff48bf5SDavid du Colombier rootgen(int off, Dir *d, void*) 276*3ff48bf5SDavid du Colombier { 277*3ff48bf5SDavid du Colombier memset(d, 0, sizeof *d); 278*3ff48bf5SDavid du Colombier d->atime = time0; 279*3ff48bf5SDavid du Colombier d->mtime = time0; 280*3ff48bf5SDavid du Colombier if(off == 0){ 281*3ff48bf5SDavid du Colombier d->name = estrdup9p(sdname); 282*3ff48bf5SDavid du Colombier d->mode = DMDIR|0777; 283*3ff48bf5SDavid du Colombier d->qid.path = Qdir; 284*3ff48bf5SDavid du Colombier d->qid.type = QTDIR; 285*3ff48bf5SDavid du Colombier d->uid = estrdup9p("disksim"); 286*3ff48bf5SDavid du Colombier d->gid = estrdup9p("disksim"); 287*3ff48bf5SDavid du Colombier d->muid = estrdup9p(""); 288*3ff48bf5SDavid du Colombier return 0; 289*3ff48bf5SDavid du Colombier } 290*3ff48bf5SDavid du Colombier return -1; 291*3ff48bf5SDavid du Colombier } 292*3ff48bf5SDavid du Colombier 293*3ff48bf5SDavid du Colombier int 294*3ff48bf5SDavid du Colombier dirgen(int off, Dir *d, void*) 295*3ff48bf5SDavid du Colombier { 296*3ff48bf5SDavid du Colombier int n, j; 297*3ff48bf5SDavid du Colombier 298*3ff48bf5SDavid du Colombier memset(d, 0, sizeof *d); 299*3ff48bf5SDavid du Colombier d->atime = time0; 300*3ff48bf5SDavid du Colombier d->mtime = time0; 301*3ff48bf5SDavid du Colombier if(off == 0){ 302*3ff48bf5SDavid du Colombier d->name = estrdup9p("ctl"); 303*3ff48bf5SDavid du Colombier d->mode = ctlmode; 304*3ff48bf5SDavid du Colombier d->qid.path = Qctl; 305*3ff48bf5SDavid du Colombier goto Have; 306*3ff48bf5SDavid du Colombier } 307*3ff48bf5SDavid du Colombier 308*3ff48bf5SDavid du Colombier off--; 309*3ff48bf5SDavid du Colombier n = 0; 310*3ff48bf5SDavid du Colombier for(j=0; j<nelem(tab); j++){ 311*3ff48bf5SDavid du Colombier if(tab[j].inuse==0) 312*3ff48bf5SDavid du Colombier continue; 313*3ff48bf5SDavid du Colombier if(n == off){ 314*3ff48bf5SDavid du Colombier d->name = estrdup9p(tab[j].name); 315*3ff48bf5SDavid du Colombier d->length = tab[j].length; 316*3ff48bf5SDavid du Colombier d->mode = tab[j].mode; 317*3ff48bf5SDavid du Colombier d->qid.path = Qpart+j; 318*3ff48bf5SDavid du Colombier d->qid.vers = tab[j].vers; 319*3ff48bf5SDavid du Colombier goto Have; 320*3ff48bf5SDavid du Colombier } 321*3ff48bf5SDavid du Colombier n++; 322*3ff48bf5SDavid du Colombier } 323*3ff48bf5SDavid du Colombier return -1; 324*3ff48bf5SDavid du Colombier 325*3ff48bf5SDavid du Colombier Have: 326*3ff48bf5SDavid du Colombier d->uid = estrdup9p("disksim"); 327*3ff48bf5SDavid du Colombier d->gid = estrdup9p("disksim"); 328*3ff48bf5SDavid du Colombier d->muid = estrdup9p(""); 329*3ff48bf5SDavid du Colombier return 0; 330*3ff48bf5SDavid du Colombier } 331*3ff48bf5SDavid du Colombier 332*3ff48bf5SDavid du Colombier void* 333*3ff48bf5SDavid du Colombier evommem(void *a, void *b, ulong n) 334*3ff48bf5SDavid du Colombier { 335*3ff48bf5SDavid du Colombier return memmove(b, a, n); 336*3ff48bf5SDavid du Colombier } 337*3ff48bf5SDavid du Colombier 338*3ff48bf5SDavid du Colombier int 339*3ff48bf5SDavid du Colombier rdwrpart(Req *r) 340*3ff48bf5SDavid du Colombier { 341*3ff48bf5SDavid du Colombier int q; 342*3ff48bf5SDavid du Colombier Part *p; 343*3ff48bf5SDavid du Colombier vlong offset; 344*3ff48bf5SDavid du Colombier long count, tot, n, o; 345*3ff48bf5SDavid du Colombier uchar *blk, *dat; 346*3ff48bf5SDavid du Colombier void *(*move)(void*, void*, ulong); 347*3ff48bf5SDavid du Colombier 348*3ff48bf5SDavid du Colombier q = r->fid->qid.path-Qpart; 349*3ff48bf5SDavid du Colombier if(q < 0 || q > nelem(tab) || !tab[q].inuse || tab[q].vers != r->fid->qid.vers){ 350*3ff48bf5SDavid du Colombier respond(r, "unknown partition"); 351*3ff48bf5SDavid du Colombier return -1; 352*3ff48bf5SDavid du Colombier } 353*3ff48bf5SDavid du Colombier 354*3ff48bf5SDavid du Colombier p = &tab[q]; 355*3ff48bf5SDavid du Colombier offset = r->ifcall.offset; 356*3ff48bf5SDavid du Colombier count = r->ifcall.count; 357*3ff48bf5SDavid du Colombier if(offset < 0){ 358*3ff48bf5SDavid du Colombier respond(r, "negative offset"); 359*3ff48bf5SDavid du Colombier return -1; 360*3ff48bf5SDavid du Colombier } 361*3ff48bf5SDavid du Colombier if(count < 0){ 362*3ff48bf5SDavid du Colombier respond(r, "negative count"); 363*3ff48bf5SDavid du Colombier return -1; 364*3ff48bf5SDavid du Colombier } 365*3ff48bf5SDavid du Colombier if(offset > p->length*sectsize){ 366*3ff48bf5SDavid du Colombier respond(r, "offset past end of partition"); 367*3ff48bf5SDavid du Colombier return -1; 368*3ff48bf5SDavid du Colombier } 369*3ff48bf5SDavid du Colombier if(offset+count > p->length*sectsize) 370*3ff48bf5SDavid du Colombier count = p->length*sectsize - offset; 371*3ff48bf5SDavid du Colombier offset += p->offset*sectsize; 372*3ff48bf5SDavid du Colombier 373*3ff48bf5SDavid du Colombier if(r->ifcall.type == Tread) 374*3ff48bf5SDavid du Colombier move = memmove; 375*3ff48bf5SDavid du Colombier else 376*3ff48bf5SDavid du Colombier move = evommem; 377*3ff48bf5SDavid du Colombier 378*3ff48bf5SDavid du Colombier tot = 0; 379*3ff48bf5SDavid du Colombier if(r->ifcall.type == Tread) 380*3ff48bf5SDavid du Colombier dat = (uchar*)r->ofcall.data; 381*3ff48bf5SDavid du Colombier else 382*3ff48bf5SDavid du Colombier dat = (uchar*)r->ifcall.data; 383*3ff48bf5SDavid du Colombier o = offset & (BLKSZ-1); 384*3ff48bf5SDavid du Colombier 385*3ff48bf5SDavid du Colombier /* left fringe block */ 386*3ff48bf5SDavid du Colombier if(o && count){ 387*3ff48bf5SDavid du Colombier blk = getblock(offset, r->ifcall.type==Twrite); 388*3ff48bf5SDavid du Colombier if(blk == nil) 389*3ff48bf5SDavid du Colombier abort(); 390*3ff48bf5SDavid du Colombier n = BLKSZ - o; 391*3ff48bf5SDavid du Colombier if(n > count) 392*3ff48bf5SDavid du Colombier n = count; 393*3ff48bf5SDavid du Colombier (*move)(dat, blk+o, n); 394*3ff48bf5SDavid du Colombier tot += n; 395*3ff48bf5SDavid du Colombier } 396*3ff48bf5SDavid du Colombier /* full and right fringe blocks */ 397*3ff48bf5SDavid du Colombier while(tot < count){ 398*3ff48bf5SDavid du Colombier blk = getblock(offset+tot, r->ifcall.type==Twrite); 399*3ff48bf5SDavid du Colombier if(blk == nil) 400*3ff48bf5SDavid du Colombier abort(); 401*3ff48bf5SDavid du Colombier n = BLKSZ; 402*3ff48bf5SDavid du Colombier if(n > count) 403*3ff48bf5SDavid du Colombier n = count; 404*3ff48bf5SDavid du Colombier (*move)(dat+tot, blk, n); 405*3ff48bf5SDavid du Colombier tot += n; 406*3ff48bf5SDavid du Colombier } 407*3ff48bf5SDavid du Colombier r->ofcall.count = tot; 408*3ff48bf5SDavid du Colombier respond(r, nil); 409*3ff48bf5SDavid du Colombier return 0; 410*3ff48bf5SDavid du Colombier } 411*3ff48bf5SDavid du Colombier 412*3ff48bf5SDavid du Colombier void 413*3ff48bf5SDavid du Colombier fsread(Req *r) 414*3ff48bf5SDavid du Colombier { 415*3ff48bf5SDavid du Colombier char *s; 416*3ff48bf5SDavid du Colombier 417*3ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){ 418*3ff48bf5SDavid du Colombier case Qroot: 419*3ff48bf5SDavid du Colombier dirread9p(r, rootgen, nil); 420*3ff48bf5SDavid du Colombier respond(r, nil); 421*3ff48bf5SDavid du Colombier break; 422*3ff48bf5SDavid du Colombier 423*3ff48bf5SDavid du Colombier case Qdir: 424*3ff48bf5SDavid du Colombier dirread9p(r, dirgen, nil); 425*3ff48bf5SDavid du Colombier respond(r, nil); 426*3ff48bf5SDavid du Colombier break; 427*3ff48bf5SDavid du Colombier 428*3ff48bf5SDavid du Colombier case Qctl: 429*3ff48bf5SDavid du Colombier s = ctlstring(); 430*3ff48bf5SDavid du Colombier readstr(r, s); 431*3ff48bf5SDavid du Colombier free(s); 432*3ff48bf5SDavid du Colombier respond(r, nil); 433*3ff48bf5SDavid du Colombier break; 434*3ff48bf5SDavid du Colombier 435*3ff48bf5SDavid du Colombier default: 436*3ff48bf5SDavid du Colombier rdwrpart(r); 437*3ff48bf5SDavid du Colombier break; 438*3ff48bf5SDavid du Colombier } 439*3ff48bf5SDavid du Colombier } 440*3ff48bf5SDavid du Colombier 441*3ff48bf5SDavid du Colombier void 442*3ff48bf5SDavid du Colombier fswrite(Req *r) 443*3ff48bf5SDavid du Colombier { 444*3ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){ 445*3ff48bf5SDavid du Colombier case Qroot: 446*3ff48bf5SDavid du Colombier case Qdir: 447*3ff48bf5SDavid du Colombier respond(r, "write to a directory?"); 448*3ff48bf5SDavid du Colombier break; 449*3ff48bf5SDavid du Colombier 450*3ff48bf5SDavid du Colombier case Qctl: 451*3ff48bf5SDavid du Colombier ctlwrite(r); 452*3ff48bf5SDavid du Colombier break; 453*3ff48bf5SDavid du Colombier 454*3ff48bf5SDavid du Colombier default: 455*3ff48bf5SDavid du Colombier rdwrpart(r); 456*3ff48bf5SDavid du Colombier break; 457*3ff48bf5SDavid du Colombier } 458*3ff48bf5SDavid du Colombier } 459*3ff48bf5SDavid du Colombier 460*3ff48bf5SDavid du Colombier void 461*3ff48bf5SDavid du Colombier fsopen(Req *r) 462*3ff48bf5SDavid du Colombier { 463*3ff48bf5SDavid du Colombier if(r->ifcall.mode&ORCLOSE) 464*3ff48bf5SDavid du Colombier respond(r, "cannot open ORCLOSE"); 465*3ff48bf5SDavid du Colombier 466*3ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){ 467*3ff48bf5SDavid du Colombier case Qroot: 468*3ff48bf5SDavid du Colombier case Qdir: 469*3ff48bf5SDavid du Colombier if(r->ifcall.mode != OREAD){ 470*3ff48bf5SDavid du Colombier respond(r, "bad mode for directory open"); 471*3ff48bf5SDavid du Colombier return; 472*3ff48bf5SDavid du Colombier } 473*3ff48bf5SDavid du Colombier } 474*3ff48bf5SDavid du Colombier 475*3ff48bf5SDavid du Colombier respond(r, nil); 476*3ff48bf5SDavid du Colombier } 477*3ff48bf5SDavid du Colombier 478*3ff48bf5SDavid du Colombier void 479*3ff48bf5SDavid du Colombier fsstat(Req *r) 480*3ff48bf5SDavid du Colombier { 481*3ff48bf5SDavid du Colombier int q; 482*3ff48bf5SDavid du Colombier Dir *d; 483*3ff48bf5SDavid du Colombier Part *p; 484*3ff48bf5SDavid du Colombier 485*3ff48bf5SDavid du Colombier d = &r->d; 486*3ff48bf5SDavid du Colombier memset(d, 0, sizeof *d); 487*3ff48bf5SDavid du Colombier d->qid = r->fid->qid; 488*3ff48bf5SDavid du Colombier d->atime = d->mtime = time0; 489*3ff48bf5SDavid du Colombier q = r->fid->qid.path; 490*3ff48bf5SDavid du Colombier switch(q){ 491*3ff48bf5SDavid du Colombier case Qroot: 492*3ff48bf5SDavid du Colombier d->name = estrdup9p("/"); 493*3ff48bf5SDavid du Colombier d->mode = DMDIR|0777; 494*3ff48bf5SDavid du Colombier break; 495*3ff48bf5SDavid du Colombier 496*3ff48bf5SDavid du Colombier case Qdir: 497*3ff48bf5SDavid du Colombier d->name = estrdup9p(sdname); 498*3ff48bf5SDavid du Colombier d->mode = DMDIR|0777; 499*3ff48bf5SDavid du Colombier break; 500*3ff48bf5SDavid du Colombier 501*3ff48bf5SDavid du Colombier default: 502*3ff48bf5SDavid du Colombier q -= Qpart; 503*3ff48bf5SDavid du Colombier if(q < 0 || q > nelem(tab) || tab[q].inuse==0 || r->fid->qid.vers != tab[q].vers){ 504*3ff48bf5SDavid du Colombier respond(r, "partition no longer exists"); 505*3ff48bf5SDavid du Colombier return; 506*3ff48bf5SDavid du Colombier } 507*3ff48bf5SDavid du Colombier p = &tab[q]; 508*3ff48bf5SDavid du Colombier d->name = estrdup9p(p->name); 509*3ff48bf5SDavid du Colombier d->length = p->length * sectsize; 510*3ff48bf5SDavid du Colombier d->mode = p->mode; 511*3ff48bf5SDavid du Colombier break; 512*3ff48bf5SDavid du Colombier } 513*3ff48bf5SDavid du Colombier 514*3ff48bf5SDavid du Colombier d->uid = estrdup9p("disksim"); 515*3ff48bf5SDavid du Colombier d->gid = estrdup9p("disksim"); 516*3ff48bf5SDavid du Colombier d->muid = estrdup9p(""); 517*3ff48bf5SDavid du Colombier respond(r, nil); 518*3ff48bf5SDavid du Colombier } 519*3ff48bf5SDavid du Colombier 520*3ff48bf5SDavid du Colombier void 521*3ff48bf5SDavid du Colombier fsattach(Req *r) 522*3ff48bf5SDavid du Colombier { 523*3ff48bf5SDavid du Colombier char *spec; 524*3ff48bf5SDavid du Colombier 525*3ff48bf5SDavid du Colombier spec = r->ifcall.aname; 526*3ff48bf5SDavid du Colombier if(spec && spec[0]){ 527*3ff48bf5SDavid du Colombier respond(r, "invalid attach specifier"); 528*3ff48bf5SDavid du Colombier return; 529*3ff48bf5SDavid du Colombier } 530*3ff48bf5SDavid du Colombier r->ofcall.qid = (Qid){Qroot, 0, QTDIR}; 531*3ff48bf5SDavid du Colombier r->fid->qid = r->ofcall.qid; 532*3ff48bf5SDavid du Colombier respond(r, nil); 533*3ff48bf5SDavid du Colombier } 534*3ff48bf5SDavid du Colombier 535*3ff48bf5SDavid du Colombier char* 536*3ff48bf5SDavid du Colombier fswalk1(Fid *fid, char *name, Qid *qid) 537*3ff48bf5SDavid du Colombier { 538*3ff48bf5SDavid du Colombier int i; 539*3ff48bf5SDavid du Colombier switch((int)fid->qid.path){ 540*3ff48bf5SDavid du Colombier case Qroot: 541*3ff48bf5SDavid du Colombier if(strcmp(name, sdname) == 0){ 542*3ff48bf5SDavid du Colombier fid->qid.path = Qdir; 543*3ff48bf5SDavid du Colombier fid->qid.type = QTDIR; 544*3ff48bf5SDavid du Colombier *qid = fid->qid; 545*3ff48bf5SDavid du Colombier return nil; 546*3ff48bf5SDavid du Colombier } 547*3ff48bf5SDavid du Colombier break; 548*3ff48bf5SDavid du Colombier case Qdir: 549*3ff48bf5SDavid du Colombier if(strcmp(name, "ctl") == 0){ 550*3ff48bf5SDavid du Colombier fid->qid.path = Qctl; 551*3ff48bf5SDavid du Colombier fid->qid.vers = 0; 552*3ff48bf5SDavid du Colombier fid->qid.type = 0; 553*3ff48bf5SDavid du Colombier *qid = fid->qid; 554*3ff48bf5SDavid du Colombier return nil; 555*3ff48bf5SDavid du Colombier } 556*3ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++){ 557*3ff48bf5SDavid du Colombier if(tab[i].inuse && strcmp(tab[i].name, name) == 0){ 558*3ff48bf5SDavid du Colombier fid->qid.path = i+Qpart; 559*3ff48bf5SDavid du Colombier fid->qid.vers = tab[i].vers; 560*3ff48bf5SDavid du Colombier fid->qid.type = 0; 561*3ff48bf5SDavid du Colombier *qid = fid->qid; 562*3ff48bf5SDavid du Colombier return nil; 563*3ff48bf5SDavid du Colombier } 564*3ff48bf5SDavid du Colombier } 565*3ff48bf5SDavid du Colombier break; 566*3ff48bf5SDavid du Colombier } 567*3ff48bf5SDavid du Colombier return "file not found"; 568*3ff48bf5SDavid du Colombier } 569*3ff48bf5SDavid du Colombier 570*3ff48bf5SDavid du Colombier Srv fs = { 571*3ff48bf5SDavid du Colombier .attach= fsattach, 572*3ff48bf5SDavid du Colombier .open= fsopen, 573*3ff48bf5SDavid du Colombier .read= fsread, 574*3ff48bf5SDavid du Colombier .write= fswrite, 575*3ff48bf5SDavid du Colombier .stat= fsstat, 576*3ff48bf5SDavid du Colombier .walk1= fswalk1, 577*3ff48bf5SDavid du Colombier }; 578*3ff48bf5SDavid du Colombier 579*3ff48bf5SDavid du Colombier char *mtpt = "/dev"; 580*3ff48bf5SDavid du Colombier char *srvname; 581*3ff48bf5SDavid du Colombier 582*3ff48bf5SDavid du Colombier void 583*3ff48bf5SDavid du Colombier usage(void) 584*3ff48bf5SDavid du Colombier { 585*3ff48bf5SDavid du Colombier fprint(2, "usage: aux/disksim [-D] [-s srvname] [-m mtpt] [sdXX]\n"); 586*3ff48bf5SDavid du Colombier fprint(2, "\tdefault mtpt is /dev\n"); 587*3ff48bf5SDavid du Colombier exits("usage"); 588*3ff48bf5SDavid du Colombier } 589*3ff48bf5SDavid du Colombier 590*3ff48bf5SDavid du Colombier void 591*3ff48bf5SDavid du Colombier main(int argc, char **argv) 592*3ff48bf5SDavid du Colombier { 593*3ff48bf5SDavid du Colombier quotefmtinstall(); 594*3ff48bf5SDavid du Colombier time0 = time(0); 595*3ff48bf5SDavid du Colombier if(NPTR != BLKSZ/sizeof(void*)) 596*3ff48bf5SDavid du Colombier sysfatal("unexpected pointer size"); 597*3ff48bf5SDavid du Colombier 598*3ff48bf5SDavid du Colombier ARGBEGIN{ 599*3ff48bf5SDavid du Colombier case 'D': 600*3ff48bf5SDavid du Colombier chatty9p++; 601*3ff48bf5SDavid du Colombier break; 602*3ff48bf5SDavid du Colombier case 's': 603*3ff48bf5SDavid du Colombier srvname = EARGF(usage()); 604*3ff48bf5SDavid du Colombier break; 605*3ff48bf5SDavid du Colombier case 'm': 606*3ff48bf5SDavid du Colombier mtpt = EARGF(usage()); 607*3ff48bf5SDavid du Colombier break; 608*3ff48bf5SDavid du Colombier default: 609*3ff48bf5SDavid du Colombier usage(); 610*3ff48bf5SDavid du Colombier }ARGEND 611*3ff48bf5SDavid du Colombier 612*3ff48bf5SDavid du Colombier if(argc > 1) 613*3ff48bf5SDavid du Colombier usage(); 614*3ff48bf5SDavid du Colombier if(argc == 1) 615*3ff48bf5SDavid du Colombier sdname = argv[0]; 616*3ff48bf5SDavid du Colombier 617*3ff48bf5SDavid du Colombier inquiry = estrdup9p(inquiry); 618*3ff48bf5SDavid du Colombier tab[0].name = estrdup9p("data"); 619*3ff48bf5SDavid du Colombier tab[0].inuse = 1; 620*3ff48bf5SDavid du Colombier tab[0].mode = 0666; 621*3ff48bf5SDavid du Colombier 622*3ff48bf5SDavid du Colombier postmountsrv(&fs, srvname, mtpt, MBEFORE); 623*3ff48bf5SDavid du Colombier exits(nil); 624*3ff48bf5SDavid du Colombier } 625