18ccd4a63SDavid du Colombier #include <u.h>
28ccd4a63SDavid du Colombier #include <libc.h>
38ccd4a63SDavid du Colombier #include <fcall.h>
48ccd4a63SDavid du Colombier #define Extern extern
58ccd4a63SDavid du Colombier #include "exportfs.h"
68ccd4a63SDavid du Colombier
78ccd4a63SDavid du Colombier char Ebadfid[] = "Bad fid";
88ccd4a63SDavid du Colombier char Enotdir[] = "Not a directory";
98ccd4a63SDavid du Colombier char Edupfid[] = "Fid already in use";
108ccd4a63SDavid du Colombier char Eopen[] = "Fid already opened";
118ccd4a63SDavid du Colombier char Exmnt[] = "Cannot .. past mount point";
128ccd4a63SDavid du Colombier char Emip[] = "Mount in progress";
138ccd4a63SDavid du Colombier char Enopsmt[] = "Out of pseudo mount points";
148ccd4a63SDavid du Colombier char Enomem[] = "No memory";
158ccd4a63SDavid du Colombier char Eversion[] = "Bad 9P2000 version";
168ccd4a63SDavid du Colombier
iounit(int x)178ccd4a63SDavid du Colombier int iounit(int x)
188ccd4a63SDavid du Colombier {
19*58da3067SDavid du Colombier return 8*8192+IOHDRSZ;
208ccd4a63SDavid du Colombier }
218ccd4a63SDavid du Colombier
228ccd4a63SDavid du Colombier void*
emallocz(ulong n)238ccd4a63SDavid du Colombier emallocz(ulong n)
248ccd4a63SDavid du Colombier {
258ccd4a63SDavid du Colombier void *v;
268ccd4a63SDavid du Colombier
278ccd4a63SDavid du Colombier v = mallocz(n, 1);
288ccd4a63SDavid du Colombier if(v == nil)
298ccd4a63SDavid du Colombier panic("out of memory");
308ccd4a63SDavid du Colombier return v;
318ccd4a63SDavid du Colombier }
328ccd4a63SDavid du Colombier
338ccd4a63SDavid du Colombier
348ccd4a63SDavid du Colombier void
Xversion(Fsrpc * t)358ccd4a63SDavid du Colombier Xversion(Fsrpc *t)
368ccd4a63SDavid du Colombier {
378ccd4a63SDavid du Colombier Fcall rhdr;
388ccd4a63SDavid du Colombier
398ccd4a63SDavid du Colombier if(t->work.msize > messagesize)
408ccd4a63SDavid du Colombier t->work.msize = messagesize;
418ccd4a63SDavid du Colombier messagesize = t->work.msize;
428ccd4a63SDavid du Colombier if(strncmp(t->work.version, "9P2000", 6) != 0){
438ccd4a63SDavid du Colombier reply(&t->work, &rhdr, Eversion);
448ccd4a63SDavid du Colombier return;
458ccd4a63SDavid du Colombier }
468ccd4a63SDavid du Colombier rhdr.version = "9P2000";
478ccd4a63SDavid du Colombier rhdr.msize = t->work.msize;
488ccd4a63SDavid du Colombier reply(&t->work, &rhdr, 0);
498ccd4a63SDavid du Colombier t->busy = 0;
508ccd4a63SDavid du Colombier }
518ccd4a63SDavid du Colombier
528ccd4a63SDavid du Colombier void
Xauth(Fsrpc * t)538ccd4a63SDavid du Colombier Xauth(Fsrpc *t)
548ccd4a63SDavid du Colombier {
558ccd4a63SDavid du Colombier Fcall rhdr;
568ccd4a63SDavid du Colombier
578ccd4a63SDavid du Colombier reply(&t->work, &rhdr, "exportfs: authentication not required");
588ccd4a63SDavid du Colombier t->busy = 0;
598ccd4a63SDavid du Colombier }
608ccd4a63SDavid du Colombier
618ccd4a63SDavid du Colombier void
Xflush(Fsrpc * t)628ccd4a63SDavid du Colombier Xflush(Fsrpc *t)
638ccd4a63SDavid du Colombier {
648ccd4a63SDavid du Colombier Fsrpc *w, *e;
658ccd4a63SDavid du Colombier Fcall rhdr;
668ccd4a63SDavid du Colombier
678ccd4a63SDavid du Colombier e = &Workq[Nr_workbufs];
688ccd4a63SDavid du Colombier
698ccd4a63SDavid du Colombier for(w = Workq; w < e; w++) {
708ccd4a63SDavid du Colombier if(w->work.tag == t->work.oldtag) {
718ccd4a63SDavid du Colombier DEBUG(DFD, "\tQ busy %d pid %d can %d\n", w->busy, w->pid, w->canint);
728ccd4a63SDavid du Colombier if(w->busy && w->pid) {
738ccd4a63SDavid du Colombier w->flushtag = t->work.tag;
748ccd4a63SDavid du Colombier DEBUG(DFD, "\tset flushtag %d\n", t->work.tag);
758ccd4a63SDavid du Colombier // if(w->canint)
768ccd4a63SDavid du Colombier // postnote(PNPROC, w->pid, "flush");
778ccd4a63SDavid du Colombier t->busy = 0;
788ccd4a63SDavid du Colombier return;
798ccd4a63SDavid du Colombier }
808ccd4a63SDavid du Colombier }
818ccd4a63SDavid du Colombier }
828ccd4a63SDavid du Colombier
838ccd4a63SDavid du Colombier reply(&t->work, &rhdr, 0);
848ccd4a63SDavid du Colombier DEBUG(DFD, "\tflush reply\n");
858ccd4a63SDavid du Colombier t->busy = 0;
868ccd4a63SDavid du Colombier }
878ccd4a63SDavid du Colombier
888ccd4a63SDavid du Colombier void
Xattach(Fsrpc * t)898ccd4a63SDavid du Colombier Xattach(Fsrpc *t)
908ccd4a63SDavid du Colombier {
918ccd4a63SDavid du Colombier Fcall rhdr;
928ccd4a63SDavid du Colombier Fid *f;
938ccd4a63SDavid du Colombier
948ccd4a63SDavid du Colombier f = newfid(t->work.fid);
958ccd4a63SDavid du Colombier if(f == 0) {
968ccd4a63SDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
978ccd4a63SDavid du Colombier t->busy = 0;
988ccd4a63SDavid du Colombier return;
998ccd4a63SDavid du Colombier }
1008ccd4a63SDavid du Colombier
1018ccd4a63SDavid du Colombier if(srvfd >= 0){
1028ccd4a63SDavid du Colombier /*
1038ccd4a63SDavid du Colombier if(psmpt == 0){
1048ccd4a63SDavid du Colombier Nomount:
1058ccd4a63SDavid du Colombier reply(&t->work, &rhdr, Enopsmt);
1068ccd4a63SDavid du Colombier t->busy = 0;
1078ccd4a63SDavid du Colombier freefid(t->work.fid);
1088ccd4a63SDavid du Colombier return;
1098ccd4a63SDavid du Colombier }
1108ccd4a63SDavid du Colombier for(i=0; i<Npsmpt; i++)
1118ccd4a63SDavid du Colombier if(psmap[i] == 0)
1128ccd4a63SDavid du Colombier break;
1138ccd4a63SDavid du Colombier if(i >= Npsmpt)
1148ccd4a63SDavid du Colombier goto Nomount;
1158ccd4a63SDavid du Colombier sprint(buf, "%d", i);
1168ccd4a63SDavid du Colombier f->f = file(psmpt, buf);
1178ccd4a63SDavid du Colombier if(f->f == nil)
1188ccd4a63SDavid du Colombier goto Nomount;
1198ccd4a63SDavid du Colombier sprint(buf, "/mnt/exportfs/%d", i);
1208ccd4a63SDavid du Colombier nfd = dup(srvfd, -1);
1218ccd4a63SDavid du Colombier if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){
1228ccd4a63SDavid du Colombier errstr(buf, sizeof buf);
1238ccd4a63SDavid du Colombier reply(&t->work, &rhdr, buf);
1248ccd4a63SDavid du Colombier t->busy = 0;
1258ccd4a63SDavid du Colombier freefid(t->work.fid);
1268ccd4a63SDavid du Colombier close(nfd);
1278ccd4a63SDavid du Colombier return;
1288ccd4a63SDavid du Colombier }
1298ccd4a63SDavid du Colombier psmap[i] = 1;
1308ccd4a63SDavid du Colombier f->mid = i;
1318ccd4a63SDavid du Colombier */
1328ccd4a63SDavid du Colombier }else{
1338ccd4a63SDavid du Colombier f->f = root;
1348ccd4a63SDavid du Colombier f->f->ref++;
1358ccd4a63SDavid du Colombier }
1368ccd4a63SDavid du Colombier
1378ccd4a63SDavid du Colombier rhdr.qid = f->f->qid;
1388ccd4a63SDavid du Colombier reply(&t->work, &rhdr, 0);
1398ccd4a63SDavid du Colombier t->busy = 0;
1408ccd4a63SDavid du Colombier }
1418ccd4a63SDavid du Colombier
1428ccd4a63SDavid du Colombier Fid*
clonefid(Fid * f,int new)1438ccd4a63SDavid du Colombier clonefid(Fid *f, int new)
1448ccd4a63SDavid du Colombier {
1458ccd4a63SDavid du Colombier Fid *n;
1468ccd4a63SDavid du Colombier
1478ccd4a63SDavid du Colombier n = newfid(new);
1488ccd4a63SDavid du Colombier if(n == 0) {
1498ccd4a63SDavid du Colombier n = getfid(new);
1508ccd4a63SDavid du Colombier if(n == 0)
1518ccd4a63SDavid du Colombier fatal("inconsistent fids");
1528ccd4a63SDavid du Colombier if(n->fid >= 0)
1538ccd4a63SDavid du Colombier close(n->fid);
1548ccd4a63SDavid du Colombier freefid(new);
1558ccd4a63SDavid du Colombier n = newfid(new);
1568ccd4a63SDavid du Colombier if(n == 0)
1578ccd4a63SDavid du Colombier fatal("inconsistent fids2");
1588ccd4a63SDavid du Colombier }
1598ccd4a63SDavid du Colombier n->f = f->f;
1608ccd4a63SDavid du Colombier n->f->ref++;
1618ccd4a63SDavid du Colombier return n;
1628ccd4a63SDavid du Colombier }
1638ccd4a63SDavid du Colombier
1648ccd4a63SDavid du Colombier void
Xwalk(Fsrpc * t)1658ccd4a63SDavid du Colombier Xwalk(Fsrpc *t)
1668ccd4a63SDavid du Colombier {
1678ccd4a63SDavid du Colombier char err[ERRMAX], *e;
1688ccd4a63SDavid du Colombier Fcall rhdr;
1698ccd4a63SDavid du Colombier Fid *f, *nf;
1708ccd4a63SDavid du Colombier File *wf;
1718ccd4a63SDavid du Colombier int i;
1728ccd4a63SDavid du Colombier
1738ccd4a63SDavid du Colombier f = getfid(t->work.fid);
1748ccd4a63SDavid du Colombier if(f == 0) {
1758ccd4a63SDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
1768ccd4a63SDavid du Colombier t->busy = 0;
1778ccd4a63SDavid du Colombier return;
1788ccd4a63SDavid du Colombier }
1798ccd4a63SDavid du Colombier
1808ccd4a63SDavid du Colombier nf = nil;
1818ccd4a63SDavid du Colombier if(t->work.newfid != t->work.fid){
1828ccd4a63SDavid du Colombier nf = clonefid(f, t->work.newfid);
1838ccd4a63SDavid du Colombier f = nf;
1848ccd4a63SDavid du Colombier }
1858ccd4a63SDavid du Colombier
1868ccd4a63SDavid du Colombier rhdr.nwqid = 0;
1878ccd4a63SDavid du Colombier e = nil;
1888ccd4a63SDavid du Colombier for(i=0; i<t->work.nwname; i++){
1898ccd4a63SDavid du Colombier if(i == MAXWELEM){
1908ccd4a63SDavid du Colombier e = "Too many path elements";
1918ccd4a63SDavid du Colombier break;
1928ccd4a63SDavid du Colombier }
1938ccd4a63SDavid du Colombier
1948ccd4a63SDavid du Colombier if(strcmp(t->work.wname[i], "..") == 0) {
1958ccd4a63SDavid du Colombier if(f->f->parent == nil) {
1968ccd4a63SDavid du Colombier e = Exmnt;
1978ccd4a63SDavid du Colombier break;
1988ccd4a63SDavid du Colombier }
1998ccd4a63SDavid du Colombier wf = f->f->parent;
2008ccd4a63SDavid du Colombier wf->ref++;
2018ccd4a63SDavid du Colombier goto Accept;
2028ccd4a63SDavid du Colombier }
2038ccd4a63SDavid du Colombier
2048ccd4a63SDavid du Colombier wf = file(f->f, t->work.wname[i]);
2058ccd4a63SDavid du Colombier if(wf == 0){
2068ccd4a63SDavid du Colombier errstr(err, sizeof err);
2078ccd4a63SDavid du Colombier e = err;
2088ccd4a63SDavid du Colombier break;
2098ccd4a63SDavid du Colombier }
2108ccd4a63SDavid du Colombier Accept:
2118ccd4a63SDavid du Colombier freefile(f->f);
2128ccd4a63SDavid du Colombier rhdr.wqid[rhdr.nwqid++] = wf->qid;
2138ccd4a63SDavid du Colombier f->f = wf;
2148ccd4a63SDavid du Colombier continue;
2158ccd4a63SDavid du Colombier }
2168ccd4a63SDavid du Colombier
2178ccd4a63SDavid du Colombier if(nf!=nil && (e!=nil || rhdr.nwqid!=t->work.nwname))
2188ccd4a63SDavid du Colombier freefid(t->work.newfid);
2198ccd4a63SDavid du Colombier if(rhdr.nwqid > 0)
2208ccd4a63SDavid du Colombier e = nil;
2218ccd4a63SDavid du Colombier reply(&t->work, &rhdr, e);
2228ccd4a63SDavid du Colombier t->busy = 0;
2238ccd4a63SDavid du Colombier }
2248ccd4a63SDavid du Colombier
2258ccd4a63SDavid du Colombier void
Xclunk(Fsrpc * t)2268ccd4a63SDavid du Colombier Xclunk(Fsrpc *t)
2278ccd4a63SDavid du Colombier {
2288ccd4a63SDavid du Colombier Fcall rhdr;
2298ccd4a63SDavid du Colombier Fid *f;
2308ccd4a63SDavid du Colombier
2318ccd4a63SDavid du Colombier f = getfid(t->work.fid);
2328ccd4a63SDavid du Colombier if(f == 0) {
2338ccd4a63SDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
2348ccd4a63SDavid du Colombier t->busy = 0;
2358ccd4a63SDavid du Colombier return;
2368ccd4a63SDavid du Colombier }
2378ccd4a63SDavid du Colombier
2388ccd4a63SDavid du Colombier if(f->fid >= 0)
2398ccd4a63SDavid du Colombier close(f->fid);
2408ccd4a63SDavid du Colombier
2418ccd4a63SDavid du Colombier freefid(t->work.fid);
2428ccd4a63SDavid du Colombier reply(&t->work, &rhdr, 0);
2438ccd4a63SDavid du Colombier t->busy = 0;
2448ccd4a63SDavid du Colombier }
2458ccd4a63SDavid du Colombier
2468ccd4a63SDavid du Colombier void
Xstat(Fsrpc * t)2478ccd4a63SDavid du Colombier Xstat(Fsrpc *t)
2488ccd4a63SDavid du Colombier {
2498ccd4a63SDavid du Colombier char err[ERRMAX], *path;
2508ccd4a63SDavid du Colombier Fcall rhdr;
2518ccd4a63SDavid du Colombier Fid *f;
2528ccd4a63SDavid du Colombier Dir *d;
2538ccd4a63SDavid du Colombier int s;
2548ccd4a63SDavid du Colombier uchar *statbuf;
2558ccd4a63SDavid du Colombier
2568ccd4a63SDavid du Colombier f = getfid(t->work.fid);
2578ccd4a63SDavid du Colombier if(f == 0) {
2588ccd4a63SDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
2598ccd4a63SDavid du Colombier t->busy = 0;
2608ccd4a63SDavid du Colombier return;
2618ccd4a63SDavid du Colombier }
2628ccd4a63SDavid du Colombier if(f->fid >= 0)
2638ccd4a63SDavid du Colombier d = dirfstat(f->fid);
2648ccd4a63SDavid du Colombier else {
2658ccd4a63SDavid du Colombier path = makepath(f->f, "");
2668ccd4a63SDavid du Colombier d = dirstat(path);
2678ccd4a63SDavid du Colombier free(path);
2688ccd4a63SDavid du Colombier }
2698ccd4a63SDavid du Colombier
2708ccd4a63SDavid du Colombier if(d == nil) {
2718ccd4a63SDavid du Colombier errstr(err, sizeof err);
2728ccd4a63SDavid du Colombier reply(&t->work, &rhdr, err);
2738ccd4a63SDavid du Colombier t->busy = 0;
2748ccd4a63SDavid du Colombier return;
2758ccd4a63SDavid du Colombier }
2768ccd4a63SDavid du Colombier
2778ccd4a63SDavid du Colombier d->qid.path = f->f->qidt->uniqpath;
2788ccd4a63SDavid du Colombier s = sizeD2M(d);
2798ccd4a63SDavid du Colombier statbuf = emallocz(s);
2808ccd4a63SDavid du Colombier s = convD2M(d, statbuf, s);
2818ccd4a63SDavid du Colombier free(d);
2828ccd4a63SDavid du Colombier rhdr.nstat = s;
2838ccd4a63SDavid du Colombier rhdr.stat = statbuf;
2848ccd4a63SDavid du Colombier reply(&t->work, &rhdr, 0);
2858ccd4a63SDavid du Colombier free(statbuf);
2868ccd4a63SDavid du Colombier t->busy = 0;
2878ccd4a63SDavid du Colombier }
2888ccd4a63SDavid du Colombier
2898ccd4a63SDavid du Colombier static int
getiounit(int fd)2908ccd4a63SDavid du Colombier getiounit(int fd)
2918ccd4a63SDavid du Colombier {
2928ccd4a63SDavid du Colombier int n;
2938ccd4a63SDavid du Colombier
2948ccd4a63SDavid du Colombier n = iounit(fd);
2958ccd4a63SDavid du Colombier if(n > messagesize-IOHDRSZ)
2968ccd4a63SDavid du Colombier n = messagesize-IOHDRSZ;
2978ccd4a63SDavid du Colombier return n;
2988ccd4a63SDavid du Colombier }
2998ccd4a63SDavid du Colombier
3008ccd4a63SDavid du Colombier void
Xcreate(Fsrpc * t)3018ccd4a63SDavid du Colombier Xcreate(Fsrpc *t)
3028ccd4a63SDavid du Colombier {
3038ccd4a63SDavid du Colombier char err[ERRMAX], *path;
3048ccd4a63SDavid du Colombier Fcall rhdr;
3058ccd4a63SDavid du Colombier Fid *f;
3068ccd4a63SDavid du Colombier File *nf;
3078ccd4a63SDavid du Colombier
3088ccd4a63SDavid du Colombier f = getfid(t->work.fid);
3098ccd4a63SDavid du Colombier if(f == 0) {
3108ccd4a63SDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
3118ccd4a63SDavid du Colombier t->busy = 0;
3128ccd4a63SDavid du Colombier return;
3138ccd4a63SDavid du Colombier }
3148ccd4a63SDavid du Colombier
3158ccd4a63SDavid du Colombier
3168ccd4a63SDavid du Colombier path = makepath(f->f, t->work.name);
3178ccd4a63SDavid du Colombier f->fid = create(path, t->work.mode, t->work.perm);
3188ccd4a63SDavid du Colombier free(path);
3198ccd4a63SDavid du Colombier if(f->fid < 0) {
3208ccd4a63SDavid du Colombier errstr(err, sizeof err);
3218ccd4a63SDavid du Colombier reply(&t->work, &rhdr, err);
3228ccd4a63SDavid du Colombier t->busy = 0;
3238ccd4a63SDavid du Colombier return;
3248ccd4a63SDavid du Colombier }
3258ccd4a63SDavid du Colombier
3268ccd4a63SDavid du Colombier nf = file(f->f, t->work.name);
3278ccd4a63SDavid du Colombier if(nf == 0) {
3288ccd4a63SDavid du Colombier errstr(err, sizeof err);
3298ccd4a63SDavid du Colombier reply(&t->work, &rhdr, err);
3308ccd4a63SDavid du Colombier t->busy = 0;
3318ccd4a63SDavid du Colombier return;
3328ccd4a63SDavid du Colombier }
3338ccd4a63SDavid du Colombier
3348ccd4a63SDavid du Colombier f->mode = t->work.mode;
3358ccd4a63SDavid du Colombier freefile(f->f);
3368ccd4a63SDavid du Colombier f->f = nf;
3378ccd4a63SDavid du Colombier rhdr.qid = f->f->qid;
3388ccd4a63SDavid du Colombier rhdr.iounit = getiounit(f->fid);
3398ccd4a63SDavid du Colombier reply(&t->work, &rhdr, 0);
3408ccd4a63SDavid du Colombier t->busy = 0;
3418ccd4a63SDavid du Colombier }
3428ccd4a63SDavid du Colombier
3438ccd4a63SDavid du Colombier void
Xremove(Fsrpc * t)3448ccd4a63SDavid du Colombier Xremove(Fsrpc *t)
3458ccd4a63SDavid du Colombier {
3468ccd4a63SDavid du Colombier char err[ERRMAX], *path;
3478ccd4a63SDavid du Colombier Fcall rhdr;
3488ccd4a63SDavid du Colombier Fid *f;
3498ccd4a63SDavid du Colombier
3508ccd4a63SDavid du Colombier f = getfid(t->work.fid);
3518ccd4a63SDavid du Colombier if(f == 0) {
3528ccd4a63SDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
3538ccd4a63SDavid du Colombier t->busy = 0;
3548ccd4a63SDavid du Colombier return;
3558ccd4a63SDavid du Colombier }
3568ccd4a63SDavid du Colombier
3578ccd4a63SDavid du Colombier path = makepath(f->f, "");
3588ccd4a63SDavid du Colombier DEBUG(DFD, "\tremove: %s\n", path);
3598ccd4a63SDavid du Colombier if(remove(path) < 0) {
3608ccd4a63SDavid du Colombier free(path);
3618ccd4a63SDavid du Colombier errstr(err, sizeof err);
3628ccd4a63SDavid du Colombier reply(&t->work, &rhdr, err);
3638ccd4a63SDavid du Colombier t->busy = 0;
3648ccd4a63SDavid du Colombier return;
3658ccd4a63SDavid du Colombier }
3668ccd4a63SDavid du Colombier free(path);
3678ccd4a63SDavid du Colombier
3688ccd4a63SDavid du Colombier f->f->inval = 1;
3698ccd4a63SDavid du Colombier if(f->fid >= 0)
3708ccd4a63SDavid du Colombier close(f->fid);
3718ccd4a63SDavid du Colombier freefid(t->work.fid);
3728ccd4a63SDavid du Colombier
3738ccd4a63SDavid du Colombier reply(&t->work, &rhdr, 0);
3748ccd4a63SDavid du Colombier t->busy = 0;
3758ccd4a63SDavid du Colombier }
3768ccd4a63SDavid du Colombier
3778ccd4a63SDavid du Colombier void
Xwstat(Fsrpc * t)3788ccd4a63SDavid du Colombier Xwstat(Fsrpc *t)
3798ccd4a63SDavid du Colombier {
3808ccd4a63SDavid du Colombier char err[ERRMAX], *path;
3818ccd4a63SDavid du Colombier Fcall rhdr;
3828ccd4a63SDavid du Colombier Fid *f;
3838ccd4a63SDavid du Colombier int s;
3848ccd4a63SDavid du Colombier char *strings;
3858ccd4a63SDavid du Colombier Dir d;
3868ccd4a63SDavid du Colombier
3878ccd4a63SDavid du Colombier f = getfid(t->work.fid);
3888ccd4a63SDavid du Colombier if(f == 0) {
3898ccd4a63SDavid du Colombier reply(&t->work, &rhdr, Ebadfid);
3908ccd4a63SDavid du Colombier t->busy = 0;
3918ccd4a63SDavid du Colombier return;
3928ccd4a63SDavid du Colombier }
3938ccd4a63SDavid du Colombier strings = emallocz(t->work.nstat); /* ample */
3948ccd4a63SDavid du Colombier if(convM2D(t->work.stat, t->work.nstat, &d, strings) <= BIT16SZ){
3958ccd4a63SDavid du Colombier rerrstr(err, sizeof err);
3968ccd4a63SDavid du Colombier reply(&t->work, &rhdr, err);
3978ccd4a63SDavid du Colombier t->busy = 0;
3988ccd4a63SDavid du Colombier free(strings);
3998ccd4a63SDavid du Colombier return;
4008ccd4a63SDavid du Colombier }
4018ccd4a63SDavid du Colombier
4028ccd4a63SDavid du Colombier if(f->fid >= 0)
4038ccd4a63SDavid du Colombier s = dirfwstat(f->fid, &d);
4048ccd4a63SDavid du Colombier else {
4058ccd4a63SDavid du Colombier path = makepath(f->f, "");
4068ccd4a63SDavid du Colombier s = dirwstat(path, &d);
4078ccd4a63SDavid du Colombier free(path);
4088ccd4a63SDavid du Colombier }
4098ccd4a63SDavid du Colombier if(s < 0) {
4108ccd4a63SDavid du Colombier rerrstr(err, sizeof err);
4118ccd4a63SDavid du Colombier reply(&t->work, &rhdr, err);
4128ccd4a63SDavid du Colombier }
4138ccd4a63SDavid du Colombier else {
4148ccd4a63SDavid du Colombier /* wstat may really be rename */
4158ccd4a63SDavid du Colombier if(strcmp(d.name, f->f->name)!=0 && strcmp(d.name, "")!=0){
4168ccd4a63SDavid du Colombier free(f->f->name);
4178ccd4a63SDavid du Colombier f->f->name = estrdup(d.name);
4188ccd4a63SDavid du Colombier }
4198ccd4a63SDavid du Colombier reply(&t->work, &rhdr, 0);
4208ccd4a63SDavid du Colombier }
4218ccd4a63SDavid du Colombier free(strings);
4228ccd4a63SDavid du Colombier t->busy = 0;
4238ccd4a63SDavid du Colombier }
4248ccd4a63SDavid du Colombier
4258ccd4a63SDavid du Colombier void
slave(Fsrpc * f)4268ccd4a63SDavid du Colombier slave(Fsrpc *f)
4278ccd4a63SDavid du Colombier {
4288ccd4a63SDavid du Colombier Proc *p;
4298ccd4a63SDavid du Colombier int pid;
4308ccd4a63SDavid du Colombier static int nproc;
4318ccd4a63SDavid du Colombier
4328ccd4a63SDavid du Colombier for(;;) {
4338ccd4a63SDavid du Colombier for(p = Proclist; p; p = p->next) {
4348ccd4a63SDavid du Colombier if(p->busy == 0) {
4358ccd4a63SDavid du Colombier f->pid = p->pid;
4368ccd4a63SDavid du Colombier p->busy = 1;
437ec59a3ddSDavid du Colombier pid = (uintptr)rendezvous((void*)(uintptr)p->pid, f);
4388ccd4a63SDavid du Colombier if(pid != p->pid)
4398ccd4a63SDavid du Colombier fatal("rendezvous sync fail");
4408ccd4a63SDavid du Colombier return;
4418ccd4a63SDavid du Colombier }
4428ccd4a63SDavid du Colombier }
4438ccd4a63SDavid du Colombier
4448ccd4a63SDavid du Colombier if(++nproc > MAXPROC)
4458ccd4a63SDavid du Colombier fatal("too many procs");
4468ccd4a63SDavid du Colombier
4478ccd4a63SDavid du Colombier pid = kproc("slave", blockingslave, nil);
4488ccd4a63SDavid du Colombier DEBUG(DFD, "slave pid %d\n", pid);
4498ccd4a63SDavid du Colombier if(pid == -1)
4508ccd4a63SDavid du Colombier fatal("kproc");
4518ccd4a63SDavid du Colombier
4528ccd4a63SDavid du Colombier p = malloc(sizeof(Proc));
4538ccd4a63SDavid du Colombier if(p == 0)
4548ccd4a63SDavid du Colombier fatal("out of memory");
4558ccd4a63SDavid du Colombier
4568ccd4a63SDavid du Colombier p->busy = 0;
4578ccd4a63SDavid du Colombier p->pid = pid;
4588ccd4a63SDavid du Colombier p->next = Proclist;
4598ccd4a63SDavid du Colombier Proclist = p;
4608ccd4a63SDavid du Colombier
4618ccd4a63SDavid du Colombier DEBUG(DFD, "parent %d rendez\n", pid);
462ec59a3ddSDavid du Colombier rendezvous((void*)(uintptr)pid, p);
4638ccd4a63SDavid du Colombier DEBUG(DFD, "parent %d went\n", pid);
4648ccd4a63SDavid du Colombier }
4658ccd4a63SDavid du Colombier }
4668ccd4a63SDavid du Colombier
4678ccd4a63SDavid du Colombier void
blockingslave(void * x)4688ccd4a63SDavid du Colombier blockingslave(void *x)
4698ccd4a63SDavid du Colombier {
4708ccd4a63SDavid du Colombier Fsrpc *p;
4718ccd4a63SDavid du Colombier Fcall rhdr;
4728ccd4a63SDavid du Colombier Proc *m;
4738ccd4a63SDavid du Colombier int pid;
4748ccd4a63SDavid du Colombier
4758ccd4a63SDavid du Colombier USED(x);
4768ccd4a63SDavid du Colombier
4778ccd4a63SDavid du Colombier notify(flushaction);
4788ccd4a63SDavid du Colombier
4798ccd4a63SDavid du Colombier pid = getpid();
4808ccd4a63SDavid du Colombier
4818ccd4a63SDavid du Colombier DEBUG(DFD, "blockingslave %d rendez\n", pid);
482ec59a3ddSDavid du Colombier m = (Proc*)rendezvous((void*)(uintptr)pid, 0);
4838ccd4a63SDavid du Colombier DEBUG(DFD, "blockingslave %d rendez got %p\n", pid, m);
4848ccd4a63SDavid du Colombier
4858ccd4a63SDavid du Colombier for(;;) {
486ec59a3ddSDavid du Colombier p = rendezvous((void*)(uintptr)pid, (void*)(uintptr)pid);
487ec59a3ddSDavid du Colombier if((uintptr)p == ~(uintptr)0) /* Interrupted */
4888ccd4a63SDavid du Colombier continue;
4898ccd4a63SDavid du Colombier
4908ccd4a63SDavid du Colombier DEBUG(DFD, "\tslave: %d %F b %d p %d\n", pid, &p->work, p->busy, p->pid);
4918ccd4a63SDavid du Colombier if(p->flushtag != NOTAG)
4928ccd4a63SDavid du Colombier goto flushme;
4938ccd4a63SDavid du Colombier
4948ccd4a63SDavid du Colombier switch(p->work.type) {
4958ccd4a63SDavid du Colombier case Tread:
4968ccd4a63SDavid du Colombier slaveread(p);
4978ccd4a63SDavid du Colombier break;
4988ccd4a63SDavid du Colombier
4998ccd4a63SDavid du Colombier case Twrite:
5008ccd4a63SDavid du Colombier slavewrite(p);
5018ccd4a63SDavid du Colombier break;
5028ccd4a63SDavid du Colombier
5038ccd4a63SDavid du Colombier case Topen:
5048ccd4a63SDavid du Colombier slaveopen(p);
5058ccd4a63SDavid du Colombier break;
5068ccd4a63SDavid du Colombier
5078ccd4a63SDavid du Colombier default:
5088ccd4a63SDavid du Colombier reply(&p->work, &rhdr, "exportfs: slave type error");
5098ccd4a63SDavid du Colombier }
5108ccd4a63SDavid du Colombier if(p->flushtag != NOTAG) {
5118ccd4a63SDavid du Colombier flushme:
5128ccd4a63SDavid du Colombier p->work.type = Tflush;
5138ccd4a63SDavid du Colombier p->work.tag = p->flushtag;
5148ccd4a63SDavid du Colombier reply(&p->work, &rhdr, 0);
5158ccd4a63SDavid du Colombier }
5168ccd4a63SDavid du Colombier p->busy = 0;
5178ccd4a63SDavid du Colombier m->busy = 0;
5188ccd4a63SDavid du Colombier }
5198ccd4a63SDavid du Colombier }
5208ccd4a63SDavid du Colombier
5218ccd4a63SDavid du Colombier int
openmount(int sfd)5228ccd4a63SDavid du Colombier openmount(int sfd)
5238ccd4a63SDavid du Colombier {
5248ccd4a63SDavid du Colombier werrstr("openmount not implemented");
5258ccd4a63SDavid du Colombier return -1;
5268ccd4a63SDavid du Colombier }
5278ccd4a63SDavid du Colombier
5288ccd4a63SDavid du Colombier void
slaveopen(Fsrpc * p)5298ccd4a63SDavid du Colombier slaveopen(Fsrpc *p)
5308ccd4a63SDavid du Colombier {
5318ccd4a63SDavid du Colombier char err[ERRMAX], *path;
5328ccd4a63SDavid du Colombier Fcall *work, rhdr;
5338ccd4a63SDavid du Colombier Fid *f;
5348ccd4a63SDavid du Colombier Dir *d;
5358ccd4a63SDavid du Colombier
5368ccd4a63SDavid du Colombier work = &p->work;
5378ccd4a63SDavid du Colombier
5388ccd4a63SDavid du Colombier f = getfid(work->fid);
5398ccd4a63SDavid du Colombier if(f == 0) {
5408ccd4a63SDavid du Colombier reply(work, &rhdr, Ebadfid);
5418ccd4a63SDavid du Colombier return;
5428ccd4a63SDavid du Colombier }
5438ccd4a63SDavid du Colombier if(f->fid >= 0) {
5448ccd4a63SDavid du Colombier close(f->fid);
5458ccd4a63SDavid du Colombier f->fid = -1;
5468ccd4a63SDavid du Colombier }
5478ccd4a63SDavid du Colombier
5488ccd4a63SDavid du Colombier path = makepath(f->f, "");
5498ccd4a63SDavid du Colombier DEBUG(DFD, "\topen: %s %d\n", path, work->mode);
5508ccd4a63SDavid du Colombier
5518ccd4a63SDavid du Colombier p->canint = 1;
5528ccd4a63SDavid du Colombier if(p->flushtag != NOTAG){
5538ccd4a63SDavid du Colombier free(path);
5548ccd4a63SDavid du Colombier return;
5558ccd4a63SDavid du Colombier }
5568ccd4a63SDavid du Colombier /* There is a race here I ignore because there are no locks */
5578ccd4a63SDavid du Colombier f->fid = open(path, work->mode);
5588ccd4a63SDavid du Colombier free(path);
5598ccd4a63SDavid du Colombier p->canint = 0;
5608ccd4a63SDavid du Colombier if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) {
5618ccd4a63SDavid du Colombier Error:
5628ccd4a63SDavid du Colombier errstr(err, sizeof err);
5638ccd4a63SDavid du Colombier reply(work, &rhdr, err);
5648ccd4a63SDavid du Colombier return;
5658ccd4a63SDavid du Colombier }
5668ccd4a63SDavid du Colombier f->f->qid = d->qid;
5678ccd4a63SDavid du Colombier free(d);
5688ccd4a63SDavid du Colombier if(f->f->qid.type & QTMOUNT){ /* fork new exportfs for this */
5698ccd4a63SDavid du Colombier f->fid = openmount(f->fid);
5708ccd4a63SDavid du Colombier if(f->fid < 0)
5718ccd4a63SDavid du Colombier goto Error;
5728ccd4a63SDavid du Colombier }
5738ccd4a63SDavid du Colombier
5748ccd4a63SDavid du Colombier DEBUG(DFD, "\topen: fd %d\n", f->fid);
5758ccd4a63SDavid du Colombier f->mode = work->mode;
5768ccd4a63SDavid du Colombier rhdr.iounit = getiounit(f->fid);
5778ccd4a63SDavid du Colombier rhdr.qid = f->f->qid;
5788ccd4a63SDavid du Colombier reply(work, &rhdr, 0);
5798ccd4a63SDavid du Colombier }
5808ccd4a63SDavid du Colombier
5818ccd4a63SDavid du Colombier void
slaveread(Fsrpc * p)5828ccd4a63SDavid du Colombier slaveread(Fsrpc *p)
5838ccd4a63SDavid du Colombier {
5848ccd4a63SDavid du Colombier Fid *f;
5858ccd4a63SDavid du Colombier int n, r;
5868ccd4a63SDavid du Colombier Fcall *work, rhdr;
5878ccd4a63SDavid du Colombier char *data, err[ERRMAX];
5888ccd4a63SDavid du Colombier
5898ccd4a63SDavid du Colombier work = &p->work;
5908ccd4a63SDavid du Colombier
5918ccd4a63SDavid du Colombier f = getfid(work->fid);
5928ccd4a63SDavid du Colombier if(f == 0) {
5938ccd4a63SDavid du Colombier reply(work, &rhdr, Ebadfid);
5948ccd4a63SDavid du Colombier return;
5958ccd4a63SDavid du Colombier }
5968ccd4a63SDavid du Colombier
5978ccd4a63SDavid du Colombier n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
5988ccd4a63SDavid du Colombier p->canint = 1;
5998ccd4a63SDavid du Colombier if(p->flushtag != NOTAG)
6008ccd4a63SDavid du Colombier return;
6018ccd4a63SDavid du Colombier data = malloc(n);
6028ccd4a63SDavid du Colombier if(data == nil)
6038ccd4a63SDavid du Colombier fatal(Enomem);
6048ccd4a63SDavid du Colombier
6058ccd4a63SDavid du Colombier /* can't just call pread, since directories must update the offset */
6068ccd4a63SDavid du Colombier r = pread(f->fid, data, n, work->offset);
6078ccd4a63SDavid du Colombier p->canint = 0;
6088ccd4a63SDavid du Colombier if(r < 0) {
6098ccd4a63SDavid du Colombier free(data);
6108ccd4a63SDavid du Colombier errstr(err, sizeof err);
6118ccd4a63SDavid du Colombier reply(work, &rhdr, err);
6128ccd4a63SDavid du Colombier return;
6138ccd4a63SDavid du Colombier }
6148ccd4a63SDavid du Colombier
6158ccd4a63SDavid du Colombier DEBUG(DFD, "\tread: fd=%d %d bytes\n", f->fid, r);
6168ccd4a63SDavid du Colombier
6178ccd4a63SDavid du Colombier rhdr.data = data;
6188ccd4a63SDavid du Colombier rhdr.count = r;
6198ccd4a63SDavid du Colombier reply(work, &rhdr, 0);
6208ccd4a63SDavid du Colombier free(data);
6218ccd4a63SDavid du Colombier }
6228ccd4a63SDavid du Colombier
6238ccd4a63SDavid du Colombier void
slavewrite(Fsrpc * p)6248ccd4a63SDavid du Colombier slavewrite(Fsrpc *p)
6258ccd4a63SDavid du Colombier {
6268ccd4a63SDavid du Colombier char err[ERRMAX];
6278ccd4a63SDavid du Colombier Fcall *work, rhdr;
6288ccd4a63SDavid du Colombier Fid *f;
6298ccd4a63SDavid du Colombier int n;
6308ccd4a63SDavid du Colombier
6318ccd4a63SDavid du Colombier work = &p->work;
6328ccd4a63SDavid du Colombier
6338ccd4a63SDavid du Colombier f = getfid(work->fid);
6348ccd4a63SDavid du Colombier if(f == 0) {
6358ccd4a63SDavid du Colombier reply(work, &rhdr, Ebadfid);
6368ccd4a63SDavid du Colombier return;
6378ccd4a63SDavid du Colombier }
6388ccd4a63SDavid du Colombier
6398ccd4a63SDavid du Colombier n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
6408ccd4a63SDavid du Colombier p->canint = 1;
6418ccd4a63SDavid du Colombier if(p->flushtag != NOTAG)
6428ccd4a63SDavid du Colombier return;
6438ccd4a63SDavid du Colombier n = pwrite(f->fid, work->data, n, work->offset);
6448ccd4a63SDavid du Colombier p->canint = 0;
6458ccd4a63SDavid du Colombier if(n < 0) {
6468ccd4a63SDavid du Colombier errstr(err, sizeof err);
6478ccd4a63SDavid du Colombier reply(work, &rhdr, err);
6488ccd4a63SDavid du Colombier return;
6498ccd4a63SDavid du Colombier }
6508ccd4a63SDavid du Colombier
6518ccd4a63SDavid du Colombier DEBUG(DFD, "\twrite: %d bytes fd=%d\n", n, f->fid);
6528ccd4a63SDavid du Colombier
6538ccd4a63SDavid du Colombier rhdr.count = n;
6548ccd4a63SDavid du Colombier reply(work, &rhdr, 0);
6558ccd4a63SDavid du Colombier }
6568ccd4a63SDavid du Colombier
6578ccd4a63SDavid du Colombier void
reopen(Fid * f)6588ccd4a63SDavid du Colombier reopen(Fid *f)
6598ccd4a63SDavid du Colombier {
6608ccd4a63SDavid du Colombier USED(f);
6618ccd4a63SDavid du Colombier fatal("reopen");
6628ccd4a63SDavid du Colombier }
6638ccd4a63SDavid du Colombier
6648ccd4a63SDavid du Colombier void
flushaction(void * a,char * cause)6658ccd4a63SDavid du Colombier flushaction(void *a, char *cause)
6668ccd4a63SDavid du Colombier {
6678ccd4a63SDavid du Colombier USED(a);
6688ccd4a63SDavid du Colombier if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) {
6698ccd4a63SDavid du Colombier fprint(2, "exportsrv: note: %s\n", cause);
6708ccd4a63SDavid du Colombier exits("noted");
6718ccd4a63SDavid du Colombier }
6728ccd4a63SDavid du Colombier if(strncmp(cause, "kill", 4) == 0)
6738ccd4a63SDavid du Colombier noted(NDFLT);
6748ccd4a63SDavid du Colombier
6758ccd4a63SDavid du Colombier noted(NCONT);
6768ccd4a63SDavid du Colombier }
677