13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 3219b2ee8SDavid du Colombier #include <auth.h> 43e12c5d1SDavid du Colombier #include <fcall.h> 53e12c5d1SDavid du Colombier 63e12c5d1SDavid du Colombier #include "cformat.h" 73e12c5d1SDavid du Colombier #include "lru.h" 83e12c5d1SDavid du Colombier #include "bcache.h" 93e12c5d1SDavid du Colombier #include "disk.h" 103e12c5d1SDavid du Colombier #include "inode.h" 113e12c5d1SDavid du Colombier #include "file.h" 123e12c5d1SDavid du Colombier 133e12c5d1SDavid du Colombier enum 143e12c5d1SDavid du Colombier { 15*7dd7cddfSDavid du Colombier Nfid= 10240, 163e12c5d1SDavid du Colombier }; 173e12c5d1SDavid du Colombier 183e12c5d1SDavid du Colombier 193e12c5d1SDavid du Colombier typedef struct Mfile Mfile; 203e12c5d1SDavid du Colombier typedef struct Ram Ram; 213e12c5d1SDavid du Colombier typedef struct P9fs P9fs; 223e12c5d1SDavid du Colombier 233e12c5d1SDavid du Colombier struct Mfile 243e12c5d1SDavid du Colombier { 253e12c5d1SDavid du Colombier Qid qid; 26*7dd7cddfSDavid du Colombier Mfile *dp; /* someone needing a clone from us */ 27*7dd7cddfSDavid du Colombier Mfile *nextdp; /* next dependent */ 28*7dd7cddfSDavid du Colombier Mfile *parent; /* fid we need a clone from */ 293e12c5d1SDavid du Colombier char busy; 303e12c5d1SDavid du Colombier }; 313e12c5d1SDavid du Colombier 323e12c5d1SDavid du Colombier Mfile mfile[Nfid]; 333e12c5d1SDavid du Colombier char user[NAMELEN]; 343e12c5d1SDavid du Colombier Icache ic; 353e12c5d1SDavid du Colombier int debug; 363e12c5d1SDavid du Colombier 373e12c5d1SDavid du Colombier struct P9fs 383e12c5d1SDavid du Colombier { 393e12c5d1SDavid du Colombier int fd[2]; 403e12c5d1SDavid du Colombier Fcall rhdr; 413e12c5d1SDavid du Colombier Fcall thdr; 423e12c5d1SDavid du Colombier long len; 433e12c5d1SDavid du Colombier char *name; 443e12c5d1SDavid du Colombier }; 453e12c5d1SDavid du Colombier 463e12c5d1SDavid du Colombier P9fs c; /* client conversation */ 473e12c5d1SDavid du Colombier P9fs s; /* server conversation */ 483e12c5d1SDavid du Colombier 493e12c5d1SDavid du Colombier char datasnd[MAXFDATA + MAXMSG]; 503e12c5d1SDavid du Colombier char datarcv[MAXFDATA + MAXMSG]; 513e12c5d1SDavid du Colombier 52219b2ee8SDavid du Colombier void rsession(void); 533e12c5d1SDavid du Colombier void rflush(void); 543e12c5d1SDavid du Colombier void rattach(Mfile*); 553e12c5d1SDavid du Colombier void rclone(Mfile*); 563e12c5d1SDavid du Colombier void rwalk(Mfile*); 573e12c5d1SDavid du Colombier void rclwalk(Mfile*); 583e12c5d1SDavid du Colombier void ropen(Mfile*); 593e12c5d1SDavid du Colombier void rcreate(Mfile*); 603e12c5d1SDavid du Colombier void rread(Mfile*); 613e12c5d1SDavid du Colombier void rwrite(Mfile*); 623e12c5d1SDavid du Colombier void rclunk(Mfile*); 633e12c5d1SDavid du Colombier void rremove(Mfile*); 643e12c5d1SDavid du Colombier void rstat(Mfile*); 653e12c5d1SDavid du Colombier void rwstat(Mfile*); 663e12c5d1SDavid du Colombier void error(char*); 673e12c5d1SDavid du Colombier void warning(char*); 683e12c5d1SDavid du Colombier void mountinit(char*, char*); 693e12c5d1SDavid du Colombier void io(void); 703e12c5d1SDavid du Colombier void sendreply(char*); 713e12c5d1SDavid du Colombier void sendmsg(P9fs*, Fcall*); 723e12c5d1SDavid du Colombier void rcvmsg(P9fs*, Fcall*); 733e12c5d1SDavid du Colombier int delegate(void); 743e12c5d1SDavid du Colombier int askserver(void); 753e12c5d1SDavid du Colombier void cachesetup(int, char*); 763e12c5d1SDavid du Colombier int doclone(Mfile*); 773e12c5d1SDavid du Colombier void doclwalk(Mfile*, char*); 783e12c5d1SDavid du Colombier 79*7dd7cddfSDavid du Colombier #define PREFACE(m) if(preface(m) < 0) return 803e12c5d1SDavid du Colombier 813e12c5d1SDavid du Colombier char *mname[]={ 823e12c5d1SDavid du Colombier [Tnop] "Tnop", 833e12c5d1SDavid du Colombier [Tsession] "Tsession", 843e12c5d1SDavid du Colombier [Tflush] "Tflush", 853e12c5d1SDavid du Colombier [Tattach] "Tattach", 863e12c5d1SDavid du Colombier [Tclone] "Tclone", 873e12c5d1SDavid du Colombier [Twalk] "Twalk", 883e12c5d1SDavid du Colombier [Topen] "Topen", 893e12c5d1SDavid du Colombier [Tcreate] "Tcreate", 903e12c5d1SDavid du Colombier [Tclunk] "Tclunk", 913e12c5d1SDavid du Colombier [Tread] "Tread", 923e12c5d1SDavid du Colombier [Twrite] "Twrite", 933e12c5d1SDavid du Colombier [Tremove] "Tremove", 943e12c5d1SDavid du Colombier [Tstat] "Tstat", 953e12c5d1SDavid du Colombier [Twstat] "Twstat", 963e12c5d1SDavid du Colombier [Tclwalk] "Tclwalk", 973e12c5d1SDavid du Colombier [Rnop] "Rnop", 983e12c5d1SDavid du Colombier [Rsession] "Rsession", 993e12c5d1SDavid du Colombier [Rerror] "Rerror", 1003e12c5d1SDavid du Colombier [Rflush] "Rflush", 1013e12c5d1SDavid du Colombier [Rattach] "Rattach", 1023e12c5d1SDavid du Colombier [Rclone] "Rclone", 1033e12c5d1SDavid du Colombier [Rwalk] "Rwalk", 1043e12c5d1SDavid du Colombier [Ropen] "Ropen", 1053e12c5d1SDavid du Colombier [Rcreate] "Rcreate", 1063e12c5d1SDavid du Colombier [Rclunk] "Rclunk", 1073e12c5d1SDavid du Colombier [Rread] "Rread", 1083e12c5d1SDavid du Colombier [Rwrite] "Rwrite", 1093e12c5d1SDavid du Colombier [Rremove] "Rremove", 1103e12c5d1SDavid du Colombier [Rstat] "Rstat", 1113e12c5d1SDavid du Colombier [Rwstat] "Rwstat", 1123e12c5d1SDavid du Colombier [Rclwalk] "Rclwalk", 1133e12c5d1SDavid du Colombier [Rauth] "Rauth", 1143e12c5d1SDavid du Colombier 0, 1153e12c5d1SDavid du Colombier }; 1163e12c5d1SDavid du Colombier 1173e12c5d1SDavid du Colombier void 1183e12c5d1SDavid du Colombier usage(void) 1193e12c5d1SDavid du Colombier { 1203e12c5d1SDavid du Colombier fprint(2, "usage:\tcfs -s [-rd] [-f partition]"); 1213e12c5d1SDavid du Colombier fprint(2, "\tcfs [-rd] [-f partition] [-a netaddr] [mt-pt]\n"); 1223e12c5d1SDavid du Colombier } 1233e12c5d1SDavid du Colombier 1243e12c5d1SDavid du Colombier void 1253e12c5d1SDavid du Colombier main(int argc, char *argv[]) 1263e12c5d1SDavid du Colombier { 1273e12c5d1SDavid du Colombier int std; 1283e12c5d1SDavid du Colombier int format; 1293e12c5d1SDavid du Colombier char *part; 1303e12c5d1SDavid du Colombier char *server; 1313e12c5d1SDavid du Colombier char *mtpt; 1323e12c5d1SDavid du Colombier 1333e12c5d1SDavid du Colombier std = 0; 1343e12c5d1SDavid du Colombier format = 0; 135*7dd7cddfSDavid du Colombier part = "/dev/sdC0/cache"; 136*7dd7cddfSDavid du Colombier server = "il!emelie"; 1373e12c5d1SDavid du Colombier mtpt = "/tmp"; 1383e12c5d1SDavid du Colombier 1393e12c5d1SDavid du Colombier ARGBEGIN{ 1403e12c5d1SDavid du Colombier case 'a': 1413e12c5d1SDavid du Colombier server = ARGF(); 1423e12c5d1SDavid du Colombier if(server == 0) 1433e12c5d1SDavid du Colombier usage(); 1443e12c5d1SDavid du Colombier break; 1453e12c5d1SDavid du Colombier case 's': 1463e12c5d1SDavid du Colombier std = 1; 1473e12c5d1SDavid du Colombier break; 1483e12c5d1SDavid du Colombier case 'r': 1493e12c5d1SDavid du Colombier format = 1; 1503e12c5d1SDavid du Colombier break; 1513e12c5d1SDavid du Colombier case 'f': 1523e12c5d1SDavid du Colombier part = ARGF(); 1533e12c5d1SDavid du Colombier if(part == 0) 1543e12c5d1SDavid du Colombier usage(); 1553e12c5d1SDavid du Colombier break; 1563e12c5d1SDavid du Colombier case 'd': 1573e12c5d1SDavid du Colombier debug = 1; 1583e12c5d1SDavid du Colombier break; 1593e12c5d1SDavid du Colombier default: 1603e12c5d1SDavid du Colombier usage(); 1613e12c5d1SDavid du Colombier }ARGEND 1623e12c5d1SDavid du Colombier if(argc && *argv) 1633e12c5d1SDavid du Colombier mtpt = *argv; 1643e12c5d1SDavid du Colombier 165*7dd7cddfSDavid du Colombier if(debug) 166*7dd7cddfSDavid du Colombier fmtinstall('F', fcallconv); 167*7dd7cddfSDavid du Colombier 1683e12c5d1SDavid du Colombier cachesetup(format, part); 1693e12c5d1SDavid du Colombier 1703e12c5d1SDavid du Colombier c.name = "client"; 1713e12c5d1SDavid du Colombier s.name = "server"; 1723e12c5d1SDavid du Colombier if(std){ 1733e12c5d1SDavid du Colombier c.fd[0] = c.fd[1] = 1; 1743e12c5d1SDavid du Colombier s.fd[0] = s.fd[1] = 0; 1753e12c5d1SDavid du Colombier }else 1763e12c5d1SDavid du Colombier mountinit(server, mtpt); 1773e12c5d1SDavid du Colombier 1783e12c5d1SDavid du Colombier switch(fork()){ 1793e12c5d1SDavid du Colombier case 0: 1803e12c5d1SDavid du Colombier io(); 1813e12c5d1SDavid du Colombier exits(""); 1823e12c5d1SDavid du Colombier case -1: 1833e12c5d1SDavid du Colombier error("fork"); 1843e12c5d1SDavid du Colombier default: 1853e12c5d1SDavid du Colombier exits(""); 1863e12c5d1SDavid du Colombier } 1873e12c5d1SDavid du Colombier } 1883e12c5d1SDavid du Colombier 1893e12c5d1SDavid du Colombier void 1903e12c5d1SDavid du Colombier cachesetup(int format, char *partition) 1913e12c5d1SDavid du Colombier { 1923e12c5d1SDavid du Colombier int f; 1933e12c5d1SDavid du Colombier int secsize; 1943e12c5d1SDavid du Colombier int inodes; 1953e12c5d1SDavid du Colombier int blocksize; 1963e12c5d1SDavid du Colombier 1973e12c5d1SDavid du Colombier secsize = 512; 1983e12c5d1SDavid du Colombier inodes = 1024; 1993e12c5d1SDavid du Colombier blocksize = 4*1024; 2003e12c5d1SDavid du Colombier 2013e12c5d1SDavid du Colombier f = open(partition, ORDWR); 2023e12c5d1SDavid du Colombier if(f < 0) 2033e12c5d1SDavid du Colombier error("opening partition"); 2043e12c5d1SDavid du Colombier 2053e12c5d1SDavid du Colombier if(format || iinit(&ic, f, secsize)<0){ 2063e12c5d1SDavid du Colombier if(iformat(&ic, f, inodes, "bootes", blocksize, secsize) < 0) 2073e12c5d1SDavid du Colombier error("formatting failed"); 2083e12c5d1SDavid du Colombier } 2093e12c5d1SDavid du Colombier } 2103e12c5d1SDavid du Colombier 2113e12c5d1SDavid du Colombier void 2123e12c5d1SDavid du Colombier mountinit(char *server, char *mountpoint) 2133e12c5d1SDavid du Colombier { 2143e12c5d1SDavid du Colombier int p[2]; 2153e12c5d1SDavid du Colombier 2163e12c5d1SDavid du Colombier /* 2173e12c5d1SDavid du Colombier * grab a channel and call up the file server 2183e12c5d1SDavid du Colombier */ 219*7dd7cddfSDavid du Colombier s.fd[0] = s.fd[1] = dial(netmkaddr(server, 0, "9fs"), 0, 0, 0); 2203e12c5d1SDavid du Colombier if(s.fd[0] < 0) 2213e12c5d1SDavid du Colombier error("opening data"); 2223e12c5d1SDavid du Colombier 2233e12c5d1SDavid du Colombier /* 2243e12c5d1SDavid du Colombier * mount onto name space 2253e12c5d1SDavid du Colombier */ 2263e12c5d1SDavid du Colombier if(pipe(p) < 0) 2273e12c5d1SDavid du Colombier error("pipe failed"); 2283e12c5d1SDavid du Colombier switch(fork()){ 2293e12c5d1SDavid du Colombier case 0: 230219b2ee8SDavid du Colombier break; 231219b2ee8SDavid du Colombier default: 232219b2ee8SDavid du Colombier if(amount(p[1], mountpoint, MREPL|MCREATE, "") < 0) 2333e12c5d1SDavid du Colombier error("mount failed"); 2343e12c5d1SDavid du Colombier exits(0); 2353e12c5d1SDavid du Colombier case -1: 2363e12c5d1SDavid du Colombier error("fork failed\n"); 2373e12c5d1SDavid du Colombier /*BUG: no wait!*/ 2383e12c5d1SDavid du Colombier } 2393e12c5d1SDavid du Colombier c.fd[0] = c.fd[1] = p[0]; 2403e12c5d1SDavid du Colombier } 2413e12c5d1SDavid du Colombier 2423e12c5d1SDavid du Colombier void 2433e12c5d1SDavid du Colombier io(void) 2443e12c5d1SDavid du Colombier { 2453e12c5d1SDavid du Colombier Mfile *mf; 2463e12c5d1SDavid du Colombier loop: 2473e12c5d1SDavid du Colombier rcvmsg(&c, &c.thdr); 2483e12c5d1SDavid du Colombier mf = &mfile[c.thdr.fid]; 2493e12c5d1SDavid du Colombier switch(c.thdr.type){ 2503e12c5d1SDavid du Colombier default: 2513e12c5d1SDavid du Colombier error("type"); 2523e12c5d1SDavid du Colombier break; 2533e12c5d1SDavid du Colombier case Tsession: 254219b2ee8SDavid du Colombier rsession(); 2553e12c5d1SDavid du Colombier break; 2563e12c5d1SDavid du Colombier case Tnop: 2573e12c5d1SDavid du Colombier rflush(); 2583e12c5d1SDavid du Colombier break; 2593e12c5d1SDavid du Colombier case Tflush: 2603e12c5d1SDavid du Colombier rflush(); 2613e12c5d1SDavid du Colombier break; 2623e12c5d1SDavid du Colombier case Tattach: 2633e12c5d1SDavid du Colombier rattach(mf); 2643e12c5d1SDavid du Colombier break; 2653e12c5d1SDavid du Colombier case Tclone: 2663e12c5d1SDavid du Colombier rclone(mf); 2673e12c5d1SDavid du Colombier break; 2683e12c5d1SDavid du Colombier case Twalk: 2693e12c5d1SDavid du Colombier rwalk(mf); 2703e12c5d1SDavid du Colombier break; 2713e12c5d1SDavid du Colombier case Topen: 2723e12c5d1SDavid du Colombier ropen(mf); 2733e12c5d1SDavid du Colombier break; 2743e12c5d1SDavid du Colombier case Tcreate: 2753e12c5d1SDavid du Colombier rcreate(mf); 2763e12c5d1SDavid du Colombier break; 2773e12c5d1SDavid du Colombier case Tread: 2783e12c5d1SDavid du Colombier rread(mf); 2793e12c5d1SDavid du Colombier break; 2803e12c5d1SDavid du Colombier case Twrite: 2813e12c5d1SDavid du Colombier rwrite(mf); 2823e12c5d1SDavid du Colombier break; 2833e12c5d1SDavid du Colombier case Tclunk: 2843e12c5d1SDavid du Colombier rclunk(mf); 2853e12c5d1SDavid du Colombier break; 2863e12c5d1SDavid du Colombier case Tremove: 2873e12c5d1SDavid du Colombier rremove(mf); 2883e12c5d1SDavid du Colombier break; 2893e12c5d1SDavid du Colombier case Tstat: 2903e12c5d1SDavid du Colombier rstat(mf); 2913e12c5d1SDavid du Colombier break; 2923e12c5d1SDavid du Colombier case Twstat: 2933e12c5d1SDavid du Colombier rwstat(mf); 2943e12c5d1SDavid du Colombier break; 2953e12c5d1SDavid du Colombier } 2963e12c5d1SDavid du Colombier goto loop; 2973e12c5d1SDavid du Colombier } 2983e12c5d1SDavid du Colombier 2993e12c5d1SDavid du Colombier void 300219b2ee8SDavid du Colombier rsession(void) 301219b2ee8SDavid du Colombier { 302219b2ee8SDavid du Colombier delegate(); 303219b2ee8SDavid du Colombier } 304219b2ee8SDavid du Colombier 305219b2ee8SDavid du Colombier void 3063e12c5d1SDavid du Colombier rflush(void) /* synchronous so easy */ 3073e12c5d1SDavid du Colombier { 3083e12c5d1SDavid du Colombier sendreply(0); 3093e12c5d1SDavid du Colombier } 3103e12c5d1SDavid du Colombier 3113e12c5d1SDavid du Colombier void 3123e12c5d1SDavid du Colombier rattach(Mfile *mf) 3133e12c5d1SDavid du Colombier { 3143e12c5d1SDavid du Colombier if(delegate() == 0){ 3153e12c5d1SDavid du Colombier mf->qid = s.rhdr.qid; 3163e12c5d1SDavid du Colombier mf->busy = 1; 317*7dd7cddfSDavid du Colombier mf->parent = 0; 318*7dd7cddfSDavid du Colombier mf->dp = 0; 319*7dd7cddfSDavid du Colombier mf->nextdp = 0; 3203e12c5d1SDavid du Colombier } 3213e12c5d1SDavid du Colombier } 3223e12c5d1SDavid du Colombier 323*7dd7cddfSDavid du Colombier void 324*7dd7cddfSDavid du Colombier removedep(Mfile *dep) 325*7dd7cddfSDavid du Colombier { 326*7dd7cddfSDavid du Colombier Mfile **l; 327*7dd7cddfSDavid du Colombier 328*7dd7cddfSDavid du Colombier for(l = &dep->parent->dp; *l; l = &(*l)->nextdp){ 329*7dd7cddfSDavid du Colombier if(*l == dep){ 330*7dd7cddfSDavid du Colombier *l = dep->nextdp; 331*7dd7cddfSDavid du Colombier break; 332*7dd7cddfSDavid du Colombier } 333*7dd7cddfSDavid du Colombier } 334*7dd7cddfSDavid du Colombier dep->nextdp = 0; 335*7dd7cddfSDavid du Colombier dep->parent = 0; 336*7dd7cddfSDavid du Colombier } 337*7dd7cddfSDavid du Colombier 3383e12c5d1SDavid du Colombier /* 3393e12c5d1SDavid du Colombier * check consistency and perform a delayed clone 3403e12c5d1SDavid du Colombier */ 3413e12c5d1SDavid du Colombier int 3423e12c5d1SDavid du Colombier doclone(Mfile *mf) 3433e12c5d1SDavid du Colombier { 3443e12c5d1SDavid du Colombier Mfile *omf; 3453e12c5d1SDavid du Colombier 346*7dd7cddfSDavid du Colombier if(!mf->busy){ 347*7dd7cddfSDavid du Colombier DPRINT(2, "doclone fid %ld\n", mf-mfile); 348*7dd7cddfSDavid du Colombier sendreply("delayed clone failure"); 349*7dd7cddfSDavid du Colombier return -1; 350*7dd7cddfSDavid du Colombier } 351*7dd7cddfSDavid du Colombier 352*7dd7cddfSDavid du Colombier /* clone this file if it needs it */ 353*7dd7cddfSDavid du Colombier if(mf->parent){ 354*7dd7cddfSDavid du Colombier /* recurse */ 355*7dd7cddfSDavid du Colombier omf = mf->parent; 356*7dd7cddfSDavid du Colombier if(!omf->busy){ 357*7dd7cddfSDavid du Colombier DPRINT(2, "doclone fid %ld\n", omf-mfile); 358*7dd7cddfSDavid du Colombier sendreply("delayed clone failure2"); 359*7dd7cddfSDavid du Colombier return -1; 360*7dd7cddfSDavid du Colombier } 361*7dd7cddfSDavid du Colombier 362*7dd7cddfSDavid du Colombier if(omf->parent){ 363*7dd7cddfSDavid du Colombier DPRINT(2, "doclone recursing\n"); 364*7dd7cddfSDavid du Colombier if(doclone(omf) < 0) 365*7dd7cddfSDavid du Colombier return -1; 366*7dd7cddfSDavid du Colombier } 367*7dd7cddfSDavid du Colombier 368*7dd7cddfSDavid du Colombier removedep(mf); 3693e12c5d1SDavid du Colombier 3703e12c5d1SDavid du Colombier s.thdr.type = Tclone; 371*7dd7cddfSDavid du Colombier s.thdr.fid = omf - mfile; 3723e12c5d1SDavid du Colombier s.thdr.newfid = mf - mfile; 373*7dd7cddfSDavid du Colombier 3743e12c5d1SDavid du Colombier if(askserver() == 0) 3753e12c5d1SDavid du Colombier return 0; 3763e12c5d1SDavid du Colombier sendreply(s.rhdr.ename); 3773e12c5d1SDavid du Colombier return -1; 3783e12c5d1SDavid du Colombier } 3793e12c5d1SDavid du Colombier 380*7dd7cddfSDavid du Colombier return 0; 381*7dd7cddfSDavid du Colombier } 382*7dd7cddfSDavid du Colombier 383*7dd7cddfSDavid du Colombier /* 384*7dd7cddfSDavid du Colombier * clone any files that depend on this one 385*7dd7cddfSDavid du Colombier */ 386*7dd7cddfSDavid du Colombier void 387*7dd7cddfSDavid du Colombier fixdepend(Mfile *mf) 388*7dd7cddfSDavid du Colombier { 389*7dd7cddfSDavid du Colombier Mfile *dep, *next; 390*7dd7cddfSDavid du Colombier 391*7dd7cddfSDavid du Colombier /* clone any files that depend on this one */ 392*7dd7cddfSDavid du Colombier for(dep = mf->dp; dep; dep = next){ 393*7dd7cddfSDavid du Colombier next = dep->nextdp; 394*7dd7cddfSDavid du Colombier if(dep->parent != mf){ 395*7dd7cddfSDavid du Colombier DPRINT(2, "bad dep %ld -> %ld\n", mf-mfile, dep-mfile); 396*7dd7cddfSDavid du Colombier error("bad dependent"); 397*7dd7cddfSDavid du Colombier } 398*7dd7cddfSDavid du Colombier doclone(dep); 399*7dd7cddfSDavid du Colombier } 400*7dd7cddfSDavid du Colombier } 401*7dd7cddfSDavid du Colombier 402*7dd7cddfSDavid du Colombier int 403*7dd7cddfSDavid du Colombier preface(Mfile *mf) 404*7dd7cddfSDavid du Colombier { 405*7dd7cddfSDavid du Colombier /* clone this fid from parent if need be */ 406*7dd7cddfSDavid du Colombier if(doclone(mf) < 0) 407*7dd7cddfSDavid du Colombier return -1; 408*7dd7cddfSDavid du Colombier 409*7dd7cddfSDavid du Colombier /* clone any children that depend on this fid */ 410*7dd7cddfSDavid du Colombier fixdepend(mf); 411*7dd7cddfSDavid du Colombier return 0; 412*7dd7cddfSDavid du Colombier } 413*7dd7cddfSDavid du Colombier 4143e12c5d1SDavid du Colombier /* 4153e12c5d1SDavid du Colombier * don't send clone to server, just reply to client 4163e12c5d1SDavid du Colombier */ 4173e12c5d1SDavid du Colombier void 4183e12c5d1SDavid du Colombier rclone(Mfile *mf) 4193e12c5d1SDavid du Colombier { 4203e12c5d1SDavid du Colombier Mfile *nmf; 4213e12c5d1SDavid du Colombier 4223e12c5d1SDavid du Colombier if(c.thdr.newfid<0 || Nfid<=c.thdr.newfid) 4233e12c5d1SDavid du Colombier error("clone nfid out of range"); 424*7dd7cddfSDavid du Colombier PREFACE(mf); 4253e12c5d1SDavid du Colombier nmf = &mfile[c.thdr.newfid]; 4263e12c5d1SDavid du Colombier if(nmf->busy) 4273e12c5d1SDavid du Colombier error("clone to used channel"); 4283e12c5d1SDavid du Colombier nmf = &mfile[c.thdr.newfid]; 4293e12c5d1SDavid du Colombier nmf->qid = mf->qid; 430*7dd7cddfSDavid du Colombier nmf->parent = mf; 431*7dd7cddfSDavid du Colombier nmf->nextdp = mf->dp; 432*7dd7cddfSDavid du Colombier mf->dp = nmf; 4333e12c5d1SDavid du Colombier nmf->busy = 1; 4343e12c5d1SDavid du Colombier sendreply(0); 4353e12c5d1SDavid du Colombier } 4363e12c5d1SDavid du Colombier 4373e12c5d1SDavid du Colombier /* 4383e12c5d1SDavid du Colombier * do a combined clone and walk. An error implies a clunk. A reply with 4393e12c5d1SDavid du Colombier * the wrong fid implies a "directory entry not found". 4403e12c5d1SDavid du Colombier */ 4413e12c5d1SDavid du Colombier void 4423e12c5d1SDavid du Colombier doclwalk(Mfile *mf, char *name) 4433e12c5d1SDavid du Colombier { 4443e12c5d1SDavid du Colombier s.thdr.type = Tclwalk; 445*7dd7cddfSDavid du Colombier s.thdr.fid = mf->parent - mfile; 4463e12c5d1SDavid du Colombier s.thdr.newfid = mf - mfile; 4473e12c5d1SDavid du Colombier memmove(s.thdr.name, name, sizeof s.thdr.name); 4483e12c5d1SDavid du Colombier if(askserver() == 0){ 4493e12c5d1SDavid du Colombier if(s.rhdr.fid == s.thdr.fid){ 4503e12c5d1SDavid du Colombier /* 4513e12c5d1SDavid du Colombier * this is really a short form of 4523e12c5d1SDavid du Colombier * Terror "directory entry not found" 4533e12c5d1SDavid du Colombier */ 4543e12c5d1SDavid du Colombier sendreply("directory entry not found"); 455*7dd7cddfSDavid du Colombier removedep(mf); 456*7dd7cddfSDavid du Colombier mf->busy = 0; /* this is an implicit clunk in fs/port/fs.c */ 4573e12c5d1SDavid du Colombier return; 4583e12c5d1SDavid du Colombier } 4593e12c5d1SDavid du Colombier mf->qid = s.rhdr.qid; 4603e12c5d1SDavid du Colombier c.rhdr.qid = s.rhdr.qid; 461*7dd7cddfSDavid du Colombier removedep(mf); 4623e12c5d1SDavid du Colombier sendreply(0); 4633e12c5d1SDavid du Colombier } else { 4643e12c5d1SDavid du Colombier sendreply(s.rhdr.ename); 465*7dd7cddfSDavid du Colombier removedep(mf); 466*7dd7cddfSDavid du Colombier mf->busy = 0; /* this is an implicit clunk in fs/port/fs.c */ 4673e12c5d1SDavid du Colombier } 4683e12c5d1SDavid du Colombier } 4693e12c5d1SDavid du Colombier 4703e12c5d1SDavid du Colombier void 4713e12c5d1SDavid du Colombier rwalk(Mfile *mf) 4723e12c5d1SDavid du Colombier { 473*7dd7cddfSDavid du Colombier if(mf->dp){ 474*7dd7cddfSDavid du Colombier /* can't clwalk if we have any dependents */ 475*7dd7cddfSDavid du Colombier doclone(mf); 476*7dd7cddfSDavid du Colombier fixdepend(mf); 477*7dd7cddfSDavid du Colombier } 478*7dd7cddfSDavid du Colombier if(mf->parent){ 4793e12c5d1SDavid du Colombier doclwalk(mf, c.thdr.name); 4803e12c5d1SDavid du Colombier return; 4813e12c5d1SDavid du Colombier } 4823e12c5d1SDavid du Colombier if(delegate() == 0) 4833e12c5d1SDavid du Colombier mf->qid = s.rhdr.qid; 4843e12c5d1SDavid du Colombier } 4853e12c5d1SDavid du Colombier 4863e12c5d1SDavid du Colombier void 4873e12c5d1SDavid du Colombier rclwalk(Mfile *mf) 4883e12c5d1SDavid du Colombier { 489*7dd7cddfSDavid du Colombier PREFACE(mf); 4903e12c5d1SDavid du Colombier if(delegate() == 0) 4913e12c5d1SDavid du Colombier mf->qid = s.rhdr.qid; 4923e12c5d1SDavid du Colombier } 4933e12c5d1SDavid du Colombier 4943e12c5d1SDavid du Colombier void 4953e12c5d1SDavid du Colombier ropen(Mfile *mf) 4963e12c5d1SDavid du Colombier { 4973e12c5d1SDavid du Colombier PREFACE(mf); 4983e12c5d1SDavid du Colombier if(delegate() == 0){ 4993e12c5d1SDavid du Colombier mf->qid = s.rhdr.qid; 500*7dd7cddfSDavid du Colombier if(c.thdr.mode & OTRUNC) 5013e12c5d1SDavid du Colombier iget(&ic, mf->qid); 5023e12c5d1SDavid du Colombier } 5033e12c5d1SDavid du Colombier } 5043e12c5d1SDavid du Colombier 5053e12c5d1SDavid du Colombier void 5063e12c5d1SDavid du Colombier rcreate(Mfile *mf) 5073e12c5d1SDavid du Colombier { 5083e12c5d1SDavid du Colombier PREFACE(mf); 5093e12c5d1SDavid du Colombier if(delegate() == 0){ 5103e12c5d1SDavid du Colombier mf->qid = s.rhdr.qid; 5113e12c5d1SDavid du Colombier mf->qid.vers++; 5123e12c5d1SDavid du Colombier } 5133e12c5d1SDavid du Colombier } 5143e12c5d1SDavid du Colombier 5153e12c5d1SDavid du Colombier void 5163e12c5d1SDavid du Colombier rclunk(Mfile *mf) 5173e12c5d1SDavid du Colombier { 5183e12c5d1SDavid du Colombier if(!mf->busy){ 5193e12c5d1SDavid du Colombier sendreply(0); 5203e12c5d1SDavid du Colombier return; 5213e12c5d1SDavid du Colombier } 522*7dd7cddfSDavid du Colombier PREFACE(mf); 5233e12c5d1SDavid du Colombier mf->busy = 0; 5243e12c5d1SDavid du Colombier delegate(); 5253e12c5d1SDavid du Colombier } 5263e12c5d1SDavid du Colombier 5273e12c5d1SDavid du Colombier void 5283e12c5d1SDavid du Colombier rremove(Mfile *mf) 5293e12c5d1SDavid du Colombier { 5303e12c5d1SDavid du Colombier PREFACE(mf); 5313e12c5d1SDavid du Colombier mf->busy = 0; 5323e12c5d1SDavid du Colombier delegate(); 5333e12c5d1SDavid du Colombier } 5343e12c5d1SDavid du Colombier 5353e12c5d1SDavid du Colombier void 5363e12c5d1SDavid du Colombier rread(Mfile *mf) 5373e12c5d1SDavid du Colombier { 5383e12c5d1SDavid du Colombier int cnt; 5393e12c5d1SDavid du Colombier long off, first; 5403e12c5d1SDavid du Colombier char *cp; 5413e12c5d1SDavid du Colombier Ibuf *b; 5423e12c5d1SDavid du Colombier long n; 5433e12c5d1SDavid du Colombier char data[MAXFDATA]; 5443e12c5d1SDavid du Colombier int done; 5453e12c5d1SDavid du Colombier 5463e12c5d1SDavid du Colombier PREFACE(mf); 5473e12c5d1SDavid du Colombier first = off = c.thdr.offset; 5483e12c5d1SDavid du Colombier cnt = c.thdr.count; 5493e12c5d1SDavid du Colombier 5503e12c5d1SDavid du Colombier if(mf->qid.path & CHDIR){ 5513e12c5d1SDavid du Colombier delegate(); 5523e12c5d1SDavid du Colombier return; 5533e12c5d1SDavid du Colombier } 5543e12c5d1SDavid du Colombier 5553e12c5d1SDavid du Colombier b = iget(&ic, mf->qid); 5563e12c5d1SDavid du Colombier if(b == 0){ 5573e12c5d1SDavid du Colombier delegate(); 5583e12c5d1SDavid du Colombier return; 5593e12c5d1SDavid du Colombier } 5603e12c5d1SDavid du Colombier 5613e12c5d1SDavid du Colombier cp = data; 5623e12c5d1SDavid du Colombier done = 0; 5633e12c5d1SDavid du Colombier while(cnt>0 && !done){ 5643e12c5d1SDavid du Colombier n = fread(&ic, b, cp, off, cnt); 5653e12c5d1SDavid du Colombier if(n <= 0){ 5663e12c5d1SDavid du Colombier n = -n; 5673e12c5d1SDavid du Colombier if(n==0 || n>cnt) 5683e12c5d1SDavid du Colombier n = cnt; 5693e12c5d1SDavid du Colombier s.thdr.type = c.thdr.type; 5703e12c5d1SDavid du Colombier s.thdr.fid = c.thdr.fid; 5713e12c5d1SDavid du Colombier s.thdr.tag = c.thdr.tag; 5723e12c5d1SDavid du Colombier s.thdr.offset = off; 5733e12c5d1SDavid du Colombier s.thdr.count = n; 5743e12c5d1SDavid du Colombier if(askserver() < 0) 5753e12c5d1SDavid du Colombier sendreply(s.rhdr.ename); 5763e12c5d1SDavid du Colombier if(s.rhdr.count != n) 5773e12c5d1SDavid du Colombier done = 1; 5783e12c5d1SDavid du Colombier n = s.rhdr.count; 5793e12c5d1SDavid du Colombier memmove(cp, s.rhdr.data, n); 5803e12c5d1SDavid du Colombier fwrite(&ic, b, cp, off, n); 5813e12c5d1SDavid du Colombier } 5823e12c5d1SDavid du Colombier cnt -= n; 5833e12c5d1SDavid du Colombier off += n; 5843e12c5d1SDavid du Colombier cp += n; 5853e12c5d1SDavid du Colombier } 5863e12c5d1SDavid du Colombier c.rhdr.data = data; 5873e12c5d1SDavid du Colombier c.rhdr.count = off - first; 5883e12c5d1SDavid du Colombier sendreply(0); 5893e12c5d1SDavid du Colombier } 5903e12c5d1SDavid du Colombier 5913e12c5d1SDavid du Colombier void 5923e12c5d1SDavid du Colombier rwrite(Mfile *mf) 5933e12c5d1SDavid du Colombier { 5943e12c5d1SDavid du Colombier Ibuf *b; 5953e12c5d1SDavid du Colombier char buf[MAXFDATA]; 5963e12c5d1SDavid du Colombier 5973e12c5d1SDavid du Colombier PREFACE(mf); 5983e12c5d1SDavid du Colombier if(mf->qid.path & CHDIR){ 5993e12c5d1SDavid du Colombier delegate(); 6003e12c5d1SDavid du Colombier return; 6013e12c5d1SDavid du Colombier } 6023e12c5d1SDavid du Colombier 6033e12c5d1SDavid du Colombier memmove(buf, c.thdr.data, c.thdr.count); 6043e12c5d1SDavid du Colombier if(delegate() < 0) 6053e12c5d1SDavid du Colombier return; 6063e12c5d1SDavid du Colombier 6073e12c5d1SDavid du Colombier b = iget(&ic, mf->qid); 6083e12c5d1SDavid du Colombier if(b == 0) 6093e12c5d1SDavid du Colombier return; 6103e12c5d1SDavid du Colombier mf->qid.vers++; 6113e12c5d1SDavid du Colombier if(fwrite(&ic, b, buf, c.thdr.offset, c.thdr.count) == c.thdr.count) 6123e12c5d1SDavid du Colombier iinc(&ic, b); 6133e12c5d1SDavid du Colombier } 6143e12c5d1SDavid du Colombier 6153e12c5d1SDavid du Colombier void 6163e12c5d1SDavid du Colombier rstat(Mfile *mf) 6173e12c5d1SDavid du Colombier { 6183e12c5d1SDavid du Colombier PREFACE(mf); 6193e12c5d1SDavid du Colombier delegate(); 6203e12c5d1SDavid du Colombier } 6213e12c5d1SDavid du Colombier 6223e12c5d1SDavid du Colombier void 6233e12c5d1SDavid du Colombier rwstat(Mfile *mf) 6243e12c5d1SDavid du Colombier { 6253e12c5d1SDavid du Colombier PREFACE(mf); 6263e12c5d1SDavid du Colombier delegate(); 6273e12c5d1SDavid du Colombier } 6283e12c5d1SDavid du Colombier 6293e12c5d1SDavid du Colombier void 6303e12c5d1SDavid du Colombier error(char *s) 6313e12c5d1SDavid du Colombier { 632*7dd7cddfSDavid du Colombier fprint(2, "cfs: %s", s); 6333e12c5d1SDavid du Colombier perror(""); 6343e12c5d1SDavid du Colombier exits(s); 6353e12c5d1SDavid du Colombier } 6363e12c5d1SDavid du Colombier 6373e12c5d1SDavid du Colombier void 6383e12c5d1SDavid du Colombier warning(char *s) 6393e12c5d1SDavid du Colombier { 640*7dd7cddfSDavid du Colombier fprint(2, "cfs: %s: %r\n", s); 6413e12c5d1SDavid du Colombier } 6423e12c5d1SDavid du Colombier 6433e12c5d1SDavid du Colombier /* 6443e12c5d1SDavid du Colombier * send a reply to the client 6453e12c5d1SDavid du Colombier */ 6463e12c5d1SDavid du Colombier void 6473e12c5d1SDavid du Colombier sendreply(char *err) 6483e12c5d1SDavid du Colombier { 6493e12c5d1SDavid du Colombier 6503e12c5d1SDavid du Colombier if(err){ 6513e12c5d1SDavid du Colombier c.rhdr.type = Rerror; 6523e12c5d1SDavid du Colombier strncpy(c.rhdr.ename, err, ERRLEN); 6533e12c5d1SDavid du Colombier }else{ 6543e12c5d1SDavid du Colombier c.rhdr.type = c.thdr.type+1; 6553e12c5d1SDavid du Colombier c.rhdr.fid = c.thdr.fid; 6563e12c5d1SDavid du Colombier } 6573e12c5d1SDavid du Colombier c.rhdr.tag = c.thdr.tag; 6583e12c5d1SDavid du Colombier sendmsg(&c, &c.rhdr); 6593e12c5d1SDavid du Colombier } 6603e12c5d1SDavid du Colombier 6613e12c5d1SDavid du Colombier /* 6623e12c5d1SDavid du Colombier * send a request to the server, get the reply, and send that to 6633e12c5d1SDavid du Colombier * the client 6643e12c5d1SDavid du Colombier */ 6653e12c5d1SDavid du Colombier int 6663e12c5d1SDavid du Colombier delegate(void) 6673e12c5d1SDavid du Colombier { 6683e12c5d1SDavid du Colombier sendmsg(&s, &c.thdr); 6693e12c5d1SDavid du Colombier rcvmsg(&s, &s.rhdr); 6703e12c5d1SDavid du Colombier sendmsg(&c, &s.rhdr); 6713e12c5d1SDavid du Colombier return c.thdr.type+1 == s.rhdr.type ? 0 : -1; 6723e12c5d1SDavid du Colombier } 6733e12c5d1SDavid du Colombier 6743e12c5d1SDavid du Colombier /* 6753e12c5d1SDavid du Colombier * send a request to the server and get a reply 6763e12c5d1SDavid du Colombier */ 6773e12c5d1SDavid du Colombier int 6783e12c5d1SDavid du Colombier askserver(void) 6793e12c5d1SDavid du Colombier { 6803e12c5d1SDavid du Colombier s.thdr.tag = c.thdr.tag; 6813e12c5d1SDavid du Colombier sendmsg(&s, &s.thdr); 6823e12c5d1SDavid du Colombier rcvmsg(&s, &s.rhdr); 6833e12c5d1SDavid du Colombier return s.thdr.type+1 == s.rhdr.type ? 0 : -1; 6843e12c5d1SDavid du Colombier } 6853e12c5d1SDavid du Colombier 6863e12c5d1SDavid du Colombier /* 6873e12c5d1SDavid du Colombier * send/receive messages with logging 6883e12c5d1SDavid du Colombier */ 6893e12c5d1SDavid du Colombier void 6903e12c5d1SDavid du Colombier sendmsg(P9fs *p, Fcall *f) 6913e12c5d1SDavid du Colombier { 692*7dd7cddfSDavid du Colombier DPRINT(2, "->%s: %F\n", p->name, f); 6933e12c5d1SDavid du Colombier 6943e12c5d1SDavid du Colombier p->len = convS2M(f, datasnd); 695219b2ee8SDavid du Colombier if(write9p(p->fd[1], datasnd, p->len)!=p->len) 6963e12c5d1SDavid du Colombier error("smdmsg"); 6973e12c5d1SDavid du Colombier } 6983e12c5d1SDavid du Colombier 6993e12c5d1SDavid du Colombier void 7003e12c5d1SDavid du Colombier dump(uchar *p, int len) 7013e12c5d1SDavid du Colombier { 7023e12c5d1SDavid du Colombier fprint(2, "%d bytes", len); 7033e12c5d1SDavid du Colombier while(len > 0){ 7043e12c5d1SDavid du Colombier fprint(2, " %.2ux", *p++); 7053e12c5d1SDavid du Colombier len--; 7063e12c5d1SDavid du Colombier } 7073e12c5d1SDavid du Colombier fprint(2, "\n"); 7083e12c5d1SDavid du Colombier } 7093e12c5d1SDavid du Colombier 7103e12c5d1SDavid du Colombier void 7113e12c5d1SDavid du Colombier rcvmsg(P9fs *p, Fcall *f) 7123e12c5d1SDavid du Colombier { 7133e12c5d1SDavid du Colombier int olen; 714*7dd7cddfSDavid du Colombier char buf[128]; 7153e12c5d1SDavid du Colombier 7163e12c5d1SDavid du Colombier olen = p->len; 7173e12c5d1SDavid du Colombier retry: 718219b2ee8SDavid du Colombier p->len = read9p(p->fd[0], datarcv, sizeof(datarcv)); 719*7dd7cddfSDavid du Colombier if(p->len <= 0){ 720*7dd7cddfSDavid du Colombier sprint(buf, "read9p(%d)->%ld: %r", p->fd[0], p->len); 721*7dd7cddfSDavid du Colombier error(buf); 722*7dd7cddfSDavid du Colombier } 7233e12c5d1SDavid du Colombier if(p->len==2 && datarcv[0]=='O' && datarcv[1]=='K') 7243e12c5d1SDavid du Colombier goto retry; 7253e12c5d1SDavid du Colombier if(convM2S(datarcv, f, p->len) == 0) 7263e12c5d1SDavid du Colombier error("rcvmsg format error"); 7273e12c5d1SDavid du Colombier if(f->type != Rauth && (f->fid<0 || Nfid<=f->fid)){ 7283e12c5d1SDavid du Colombier fprint(2, "<-%s: %d %s on %d\n", p->name, f->type, 7293e12c5d1SDavid du Colombier mname[f->type]? mname[f->type] : "mystery", 7303e12c5d1SDavid du Colombier f->fid); 7313e12c5d1SDavid du Colombier dump((uchar*)datasnd, olen); 7323e12c5d1SDavid du Colombier dump((uchar*)datarcv, p->len); 7333e12c5d1SDavid du Colombier error("rcvmsg fid out of range"); 7343e12c5d1SDavid du Colombier } 735*7dd7cddfSDavid du Colombier DPRINT(2, "<-%s: %F\n", p->name, f); 7363e12c5d1SDavid du Colombier } 737