1*8ccd4a63SDavid du Colombier #include "u.h"
2*8ccd4a63SDavid du Colombier #include "lib.h"
3*8ccd4a63SDavid du Colombier #include "dat.h"
4*8ccd4a63SDavid du Colombier #include "fns.h"
5*8ccd4a63SDavid du Colombier #include "error.h"
6*8ccd4a63SDavid du Colombier
7*8ccd4a63SDavid du Colombier typedef struct Fid Fid;
8*8ccd4a63SDavid du Colombier typedef struct Export Export;
9*8ccd4a63SDavid du Colombier typedef struct Exq Exq;
10*8ccd4a63SDavid du Colombier
11*8ccd4a63SDavid du Colombier #define nil ((void*)0)
12*8ccd4a63SDavid du Colombier
13*8ccd4a63SDavid du Colombier enum
14*8ccd4a63SDavid du Colombier {
15*8ccd4a63SDavid du Colombier Nfidhash = 1,
16*8ccd4a63SDavid du Colombier MAXRPC = MAXMSG+MAXFDATA,
17*8ccd4a63SDavid du Colombier MAXDIRREAD = (MAXFDATA/DIRLEN)*DIRLEN
18*8ccd4a63SDavid du Colombier };
19*8ccd4a63SDavid du Colombier
20*8ccd4a63SDavid du Colombier struct Export
21*8ccd4a63SDavid du Colombier {
22*8ccd4a63SDavid du Colombier Ref r;
23*8ccd4a63SDavid du Colombier Exq* work;
24*8ccd4a63SDavid du Colombier Lock fidlock;
25*8ccd4a63SDavid du Colombier Fid* fid[Nfidhash];
26*8ccd4a63SDavid du Colombier Chan* root;
27*8ccd4a63SDavid du Colombier Chan* io;
28*8ccd4a63SDavid du Colombier Pgrp* pgrp;
29*8ccd4a63SDavid du Colombier int npart;
30*8ccd4a63SDavid du Colombier char part[MAXRPC];
31*8ccd4a63SDavid du Colombier };
32*8ccd4a63SDavid du Colombier
33*8ccd4a63SDavid du Colombier struct Fid
34*8ccd4a63SDavid du Colombier {
35*8ccd4a63SDavid du Colombier Fid* next;
36*8ccd4a63SDavid du Colombier Fid** last;
37*8ccd4a63SDavid du Colombier Chan* chan;
38*8ccd4a63SDavid du Colombier long offset;
39*8ccd4a63SDavid du Colombier int fid;
40*8ccd4a63SDavid du Colombier int ref; /* fcalls using the fid; locked by Export.Lock */
41*8ccd4a63SDavid du Colombier int attached; /* fid attached or cloned but not clunked */
42*8ccd4a63SDavid du Colombier };
43*8ccd4a63SDavid du Colombier
44*8ccd4a63SDavid du Colombier struct Exq
45*8ccd4a63SDavid du Colombier {
46*8ccd4a63SDavid du Colombier Lock lk;
47*8ccd4a63SDavid du Colombier int nointr;
48*8ccd4a63SDavid du Colombier int noresponse; /* don't respond to this one */
49*8ccd4a63SDavid du Colombier Exq* next;
50*8ccd4a63SDavid du Colombier int shut; /* has been noted for shutdown */
51*8ccd4a63SDavid du Colombier Export* export;
52*8ccd4a63SDavid du Colombier void* slave;
53*8ccd4a63SDavid du Colombier Fcall rpc;
54*8ccd4a63SDavid du Colombier char buf[MAXRPC];
55*8ccd4a63SDavid du Colombier };
56*8ccd4a63SDavid du Colombier
57*8ccd4a63SDavid du Colombier struct
58*8ccd4a63SDavid du Colombier {
59*8ccd4a63SDavid du Colombier Lock l;
60*8ccd4a63SDavid du Colombier Qlock qwait;
61*8ccd4a63SDavid du Colombier Rendez rwait;
62*8ccd4a63SDavid du Colombier Exq *head; /* work waiting for a slave */
63*8ccd4a63SDavid du Colombier Exq *tail;
64*8ccd4a63SDavid du Colombier }exq;
65*8ccd4a63SDavid du Colombier
66*8ccd4a63SDavid du Colombier static void exshutdown(Export*);
67*8ccd4a63SDavid du Colombier static void exflush(Export*, int, int);
68*8ccd4a63SDavid du Colombier static void exslave(void*);
69*8ccd4a63SDavid du Colombier static void exfree(Export*);
70*8ccd4a63SDavid du Colombier static void exportproc(Export*);
71*8ccd4a63SDavid du Colombier
72*8ccd4a63SDavid du Colombier static char* Exauth(Export*, Fcall*);
73*8ccd4a63SDavid du Colombier static char* Exattach(Export*, Fcall*);
74*8ccd4a63SDavid du Colombier static char* Exclunk(Export*, Fcall*);
75*8ccd4a63SDavid du Colombier static char* Excreate(Export*, Fcall*);
76*8ccd4a63SDavid du Colombier static char* Exopen(Export*, Fcall*);
77*8ccd4a63SDavid du Colombier static char* Exread(Export*, Fcall*);
78*8ccd4a63SDavid du Colombier static char* Exremove(Export*, Fcall*);
79*8ccd4a63SDavid du Colombier static char* Exstat(Export*, Fcall*);
80*8ccd4a63SDavid du Colombier static char* Exwalk(Export*, Fcall*);
81*8ccd4a63SDavid du Colombier static char* Exwrite(Export*, Fcall*);
82*8ccd4a63SDavid du Colombier static char* Exwstat(Export*, Fcall*);
83*8ccd4a63SDavid du Colombier static char* Exversion(Export*, Fcall*);
84*8ccd4a63SDavid du Colombier
85*8ccd4a63SDavid du Colombier static char *(*fcalls[Tmax])(Export*, Fcall*);
86*8ccd4a63SDavid du Colombier
87*8ccd4a63SDavid du Colombier static char Enofid[] = "no such fid";
88*8ccd4a63SDavid du Colombier static char Eseekdir[] = "can't seek on a directory";
89*8ccd4a63SDavid du Colombier static char Ereaddir[] = "unaligned read of a directory";
90*8ccd4a63SDavid du Colombier static int exdebug = 0;
91*8ccd4a63SDavid du Colombier
92*8ccd4a63SDavid du Colombier int
sysexport(int fd)93*8ccd4a63SDavid du Colombier sysexport(int fd)
94*8ccd4a63SDavid du Colombier {
95*8ccd4a63SDavid du Colombier Chan *c;
96*8ccd4a63SDavid du Colombier Export *fs;
97*8ccd4a63SDavid du Colombier
98*8ccd4a63SDavid du Colombier if(waserror())
99*8ccd4a63SDavid du Colombier return -1;
100*8ccd4a63SDavid du Colombier
101*8ccd4a63SDavid du Colombier c = fdtochan(fd, ORDWR, 1, 1);
102*8ccd4a63SDavid du Colombier poperror();
103*8ccd4a63SDavid du Colombier c->flag |= CMSG;
104*8ccd4a63SDavid du Colombier
105*8ccd4a63SDavid du Colombier fs = mallocz(sizeof(Export));
106*8ccd4a63SDavid du Colombier fs->r.ref = 1;
107*8ccd4a63SDavid du Colombier fs->pgrp = up->pgrp;
108*8ccd4a63SDavid du Colombier refinc(&fs->pgrp->r);
109*8ccd4a63SDavid du Colombier refinc(&up->slash->r);
110*8ccd4a63SDavid du Colombier fs->root = up->slash;
111*8ccd4a63SDavid du Colombier refinc(&fs->root->r);
112*8ccd4a63SDavid du Colombier fs->root = domount(fs->root);
113*8ccd4a63SDavid du Colombier fs->io = c;
114*8ccd4a63SDavid du Colombier
115*8ccd4a63SDavid du Colombier exportproc(fs);
116*8ccd4a63SDavid du Colombier
117*8ccd4a63SDavid du Colombier return 0;
118*8ccd4a63SDavid du Colombier }
119*8ccd4a63SDavid du Colombier
120*8ccd4a63SDavid du Colombier static void
exportinit(void)121*8ccd4a63SDavid du Colombier exportinit(void)
122*8ccd4a63SDavid du Colombier {
123*8ccd4a63SDavid du Colombier lock(&exq.l);
124*8ccd4a63SDavid du Colombier if(fcalls[Tversion] != nil) {
125*8ccd4a63SDavid du Colombier unlock(&exq.l);
126*8ccd4a63SDavid du Colombier return;
127*8ccd4a63SDavid du Colombier }
128*8ccd4a63SDavid du Colombier
129*8ccd4a63SDavid du Colombier fmtinstall('F', fcallfmt);
130*8ccd4a63SDavid du Colombier fmtinstall('D', dirfmt);
131*8ccd4a63SDavid du Colombier fmtinstall('M', dirmodefmt);
132*8ccd4a63SDavid du Colombier fcalls[Tversion] = Exversion;
133*8ccd4a63SDavid du Colombier fcalls[Tauth] = Exauth;
134*8ccd4a63SDavid du Colombier fcalls[Tattach] = Exattach;
135*8ccd4a63SDavid du Colombier fcalls[Twalk] = Exwalk;
136*8ccd4a63SDavid du Colombier fcalls[Topen] = Exopen;
137*8ccd4a63SDavid du Colombier fcalls[Tcreate] = Excreate;
138*8ccd4a63SDavid du Colombier fcalls[Tread] = Exread;
139*8ccd4a63SDavid du Colombier fcalls[Twrite] = Exwrite;
140*8ccd4a63SDavid du Colombier fcalls[Tclunk] = Exclunk;
141*8ccd4a63SDavid du Colombier fcalls[Tremove] = Exremove;
142*8ccd4a63SDavid du Colombier fcalls[Tstat] = Exstat;
143*8ccd4a63SDavid du Colombier fcalls[Twstat] = Exwstat;
144*8ccd4a63SDavid du Colombier unlock(&exq.l);
145*8ccd4a63SDavid du Colombier }
146*8ccd4a63SDavid du Colombier
147*8ccd4a63SDavid du Colombier void
exportproc(Export * fs)148*8ccd4a63SDavid du Colombier exportproc(Export *fs)
149*8ccd4a63SDavid du Colombier {
150*8ccd4a63SDavid du Colombier Exq *q;
151*8ccd4a63SDavid du Colombier char *buf;
152*8ccd4a63SDavid du Colombier int n, cn, len;
153*8ccd4a63SDavid du Colombier
154*8ccd4a63SDavid du Colombier exportinit();
155*8ccd4a63SDavid du Colombier
156*8ccd4a63SDavid du Colombier for(;;){
157*8ccd4a63SDavid du Colombier q = mallocz(sizeof(Exq));
158*8ccd4a63SDavid du Colombier if(q == 0)
159*8ccd4a63SDavid du Colombier panic("no memory");
160*8ccd4a63SDavid du Colombier
161*8ccd4a63SDavid du Colombier q->rpc.data = q->buf + MAXMSG;
162*8ccd4a63SDavid du Colombier
163*8ccd4a63SDavid du Colombier buf = q->buf;
164*8ccd4a63SDavid du Colombier len = MAXRPC;
165*8ccd4a63SDavid du Colombier if(fs->npart) {
166*8ccd4a63SDavid du Colombier memmove(buf, fs->part, fs->npart);
167*8ccd4a63SDavid du Colombier buf += fs->npart;
168*8ccd4a63SDavid du Colombier len -= fs->npart;
169*8ccd4a63SDavid du Colombier goto chk;
170*8ccd4a63SDavid du Colombier }
171*8ccd4a63SDavid du Colombier for(;;) {
172*8ccd4a63SDavid du Colombier if(waserror())
173*8ccd4a63SDavid du Colombier goto bad;
174*8ccd4a63SDavid du Colombier
175*8ccd4a63SDavid du Colombier n = (*devtab[fs->io->type].read)(fs->io, buf, len, 0);
176*8ccd4a63SDavid du Colombier poperror();
177*8ccd4a63SDavid du Colombier
178*8ccd4a63SDavid du Colombier if(n <= 0)
179*8ccd4a63SDavid du Colombier goto bad;
180*8ccd4a63SDavid du Colombier
181*8ccd4a63SDavid du Colombier buf += n;
182*8ccd4a63SDavid du Colombier len -= n;
183*8ccd4a63SDavid du Colombier chk:
184*8ccd4a63SDavid du Colombier n = buf - q->buf;
185*8ccd4a63SDavid du Colombier
186*8ccd4a63SDavid du Colombier /* convM2S returns size of correctly decoded message */
187*8ccd4a63SDavid du Colombier cn = convM2S(q->buf, &q->rpc, n);
188*8ccd4a63SDavid du Colombier if(cn < 0){
189*8ccd4a63SDavid du Colombier iprint("bad message type in devmnt\n");
190*8ccd4a63SDavid du Colombier goto bad;
191*8ccd4a63SDavid du Colombier }
192*8ccd4a63SDavid du Colombier if(cn > 0) {
193*8ccd4a63SDavid du Colombier n -= cn;
194*8ccd4a63SDavid du Colombier if(n < 0){
195*8ccd4a63SDavid du Colombier iprint("negative size in devmnt");
196*8ccd4a63SDavid du Colombier goto bad;
197*8ccd4a63SDavid du Colombier }
198*8ccd4a63SDavid du Colombier fs->npart = n;
199*8ccd4a63SDavid du Colombier if(n != 0)
200*8ccd4a63SDavid du Colombier memmove(fs->part, q->buf+cn, n);
201*8ccd4a63SDavid du Colombier break;
202*8ccd4a63SDavid du Colombier }
203*8ccd4a63SDavid du Colombier }
204*8ccd4a63SDavid du Colombier if(exdebug)
205*8ccd4a63SDavid du Colombier iprint("export %d <- %F\n", getpid(), &q->rpc);
206*8ccd4a63SDavid du Colombier
207*8ccd4a63SDavid du Colombier if(q->rpc.type == Tflush){
208*8ccd4a63SDavid du Colombier exflush(fs, q->rpc.tag, q->rpc.oldtag);
209*8ccd4a63SDavid du Colombier free(q);
210*8ccd4a63SDavid du Colombier continue;
211*8ccd4a63SDavid du Colombier }
212*8ccd4a63SDavid du Colombier
213*8ccd4a63SDavid du Colombier q->export = fs;
214*8ccd4a63SDavid du Colombier refinc(&fs->r);
215*8ccd4a63SDavid du Colombier
216*8ccd4a63SDavid du Colombier lock(&exq.l);
217*8ccd4a63SDavid du Colombier if(exq.head == nil)
218*8ccd4a63SDavid du Colombier exq.head = q;
219*8ccd4a63SDavid du Colombier else
220*8ccd4a63SDavid du Colombier exq.tail->next = q;
221*8ccd4a63SDavid du Colombier q->next = nil;
222*8ccd4a63SDavid du Colombier exq.tail = q;
223*8ccd4a63SDavid du Colombier unlock(&exq.l);
224*8ccd4a63SDavid du Colombier if(exq.qwait.first == nil) {
225*8ccd4a63SDavid du Colombier n = thread("exportfs", exslave, nil);
226*8ccd4a63SDavid du Colombier /* iprint("launch export (pid=%ux)\n", n); */
227*8ccd4a63SDavid du Colombier }
228*8ccd4a63SDavid du Colombier rendwakeup(&exq.rwait);
229*8ccd4a63SDavid du Colombier }
230*8ccd4a63SDavid du Colombier bad:
231*8ccd4a63SDavid du Colombier free(q);
232*8ccd4a63SDavid du Colombier exshutdown(fs);
233*8ccd4a63SDavid du Colombier exfree(fs);
234*8ccd4a63SDavid du Colombier }
235*8ccd4a63SDavid du Colombier
236*8ccd4a63SDavid du Colombier void
exflush(Export * fs,int flushtag,int tag)237*8ccd4a63SDavid du Colombier exflush(Export *fs, int flushtag, int tag)
238*8ccd4a63SDavid du Colombier {
239*8ccd4a63SDavid du Colombier Exq *q, **last;
240*8ccd4a63SDavid du Colombier int n;
241*8ccd4a63SDavid du Colombier Fcall fc;
242*8ccd4a63SDavid du Colombier char buf[MAXMSG];
243*8ccd4a63SDavid du Colombier
244*8ccd4a63SDavid du Colombier /* hasn't been started? */
245*8ccd4a63SDavid du Colombier lock(&exq.l);
246*8ccd4a63SDavid du Colombier last = &exq.head;
247*8ccd4a63SDavid du Colombier for(q = exq.head; q != nil; q = q->next){
248*8ccd4a63SDavid du Colombier if(q->export == fs && q->rpc.tag == tag){
249*8ccd4a63SDavid du Colombier *last = q->next;
250*8ccd4a63SDavid du Colombier unlock(&exq.l);
251*8ccd4a63SDavid du Colombier exfree(fs);
252*8ccd4a63SDavid du Colombier free(q);
253*8ccd4a63SDavid du Colombier goto Respond;
254*8ccd4a63SDavid du Colombier }
255*8ccd4a63SDavid du Colombier last = &q->next;
256*8ccd4a63SDavid du Colombier }
257*8ccd4a63SDavid du Colombier unlock(&exq.l);
258*8ccd4a63SDavid du Colombier
259*8ccd4a63SDavid du Colombier /* in progress? */
260*8ccd4a63SDavid du Colombier lock(&fs->r.l);
261*8ccd4a63SDavid du Colombier for(q = fs->work; q != nil; q = q->next){
262*8ccd4a63SDavid du Colombier if(q->rpc.tag == tag && !q->noresponse){
263*8ccd4a63SDavid du Colombier lock(&q->lk);
264*8ccd4a63SDavid du Colombier q->noresponse = 1;
265*8ccd4a63SDavid du Colombier if(!q->nointr)
266*8ccd4a63SDavid du Colombier intr(q->slave);
267*8ccd4a63SDavid du Colombier unlock(&q->lk);
268*8ccd4a63SDavid du Colombier unlock(&fs->r.l);
269*8ccd4a63SDavid du Colombier goto Respond;
270*8ccd4a63SDavid du Colombier return;
271*8ccd4a63SDavid du Colombier }
272*8ccd4a63SDavid du Colombier }
273*8ccd4a63SDavid du Colombier unlock(&fs->r.l);
274*8ccd4a63SDavid du Colombier
275*8ccd4a63SDavid du Colombier if(exdebug) iprint("exflush: did not find rpc: %d\n", tag);
276*8ccd4a63SDavid du Colombier
277*8ccd4a63SDavid du Colombier Respond:
278*8ccd4a63SDavid du Colombier fc.type = Rflush;
279*8ccd4a63SDavid du Colombier fc.tag = flushtag;
280*8ccd4a63SDavid du Colombier n = convS2M(&fc, buf);
281*8ccd4a63SDavid du Colombier if(exdebug) iprint("exflush -> %F\n", &fc);
282*8ccd4a63SDavid du Colombier if(!waserror()){
283*8ccd4a63SDavid du Colombier (*devtab[fs->io->type].write)(fs->io, buf, n, 0);
284*8ccd4a63SDavid du Colombier poperror();
285*8ccd4a63SDavid du Colombier }
286*8ccd4a63SDavid du Colombier }
287*8ccd4a63SDavid du Colombier
288*8ccd4a63SDavid du Colombier void
exshutdown(Export * fs)289*8ccd4a63SDavid du Colombier exshutdown(Export *fs)
290*8ccd4a63SDavid du Colombier {
291*8ccd4a63SDavid du Colombier Exq *q, **last;
292*8ccd4a63SDavid du Colombier
293*8ccd4a63SDavid du Colombier lock(&exq.l);
294*8ccd4a63SDavid du Colombier last = &exq.head;
295*8ccd4a63SDavid du Colombier for(q = exq.head; q != nil; q = *last){
296*8ccd4a63SDavid du Colombier if(q->export == fs){
297*8ccd4a63SDavid du Colombier *last = q->next;
298*8ccd4a63SDavid du Colombier exfree(fs);
299*8ccd4a63SDavid du Colombier free(q);
300*8ccd4a63SDavid du Colombier continue;
301*8ccd4a63SDavid du Colombier }
302*8ccd4a63SDavid du Colombier last = &q->next;
303*8ccd4a63SDavid du Colombier }
304*8ccd4a63SDavid du Colombier unlock(&exq.l);
305*8ccd4a63SDavid du Colombier
306*8ccd4a63SDavid du Colombier lock(&fs->r.l);
307*8ccd4a63SDavid du Colombier q = fs->work;
308*8ccd4a63SDavid du Colombier while(q != nil){
309*8ccd4a63SDavid du Colombier if(q->shut){
310*8ccd4a63SDavid du Colombier q = q->next;
311*8ccd4a63SDavid du Colombier continue;
312*8ccd4a63SDavid du Colombier }
313*8ccd4a63SDavid du Colombier q->shut = 1;
314*8ccd4a63SDavid du Colombier unlock(&fs->r.l);
315*8ccd4a63SDavid du Colombier /* postnote(q->slave, 1, "interrupted", NUser); */
316*8ccd4a63SDavid du Colombier iprint("postnote 2!\n");
317*8ccd4a63SDavid du Colombier lock(&fs->r.l);
318*8ccd4a63SDavid du Colombier q = fs->work;
319*8ccd4a63SDavid du Colombier }
320*8ccd4a63SDavid du Colombier unlock(&fs->r.l);
321*8ccd4a63SDavid du Colombier }
322*8ccd4a63SDavid du Colombier
323*8ccd4a63SDavid du Colombier void
exfree(Export * fs)324*8ccd4a63SDavid du Colombier exfree(Export *fs)
325*8ccd4a63SDavid du Colombier {
326*8ccd4a63SDavid du Colombier Fid *f, *n;
327*8ccd4a63SDavid du Colombier int i;
328*8ccd4a63SDavid du Colombier
329*8ccd4a63SDavid du Colombier if(refdec(&fs->r) != 0)
330*8ccd4a63SDavid du Colombier return;
331*8ccd4a63SDavid du Colombier closepgrp(fs->pgrp);
332*8ccd4a63SDavid du Colombier cclose(fs->root);
333*8ccd4a63SDavid du Colombier cclose(fs->io);
334*8ccd4a63SDavid du Colombier for(i = 0; i < Nfidhash; i++){
335*8ccd4a63SDavid du Colombier for(f = fs->fid[i]; f != nil; f = n){
336*8ccd4a63SDavid du Colombier if(f->chan != nil)
337*8ccd4a63SDavid du Colombier cclose(f->chan);
338*8ccd4a63SDavid du Colombier n = f->next;
339*8ccd4a63SDavid du Colombier free(f);
340*8ccd4a63SDavid du Colombier }
341*8ccd4a63SDavid du Colombier }
342*8ccd4a63SDavid du Colombier free(fs);
343*8ccd4a63SDavid du Colombier }
344*8ccd4a63SDavid du Colombier
345*8ccd4a63SDavid du Colombier int
exwork(void * a)346*8ccd4a63SDavid du Colombier exwork(void *a)
347*8ccd4a63SDavid du Colombier {
348*8ccd4a63SDavid du Colombier return exq.head != nil;
349*8ccd4a63SDavid du Colombier }
350*8ccd4a63SDavid du Colombier
351*8ccd4a63SDavid du Colombier void
exslave(void * a)352*8ccd4a63SDavid du Colombier exslave(void *a)
353*8ccd4a63SDavid du Colombier {
354*8ccd4a63SDavid du Colombier Export *fs;
355*8ccd4a63SDavid du Colombier Exq *q, *t, **last;
356*8ccd4a63SDavid du Colombier char *err;
357*8ccd4a63SDavid du Colombier int n;
358*8ccd4a63SDavid du Colombier /*
359*8ccd4a63SDavid du Colombier closepgrp(up->pgrp);
360*8ccd4a63SDavid du Colombier up->pgrp = nil;
361*8ccd4a63SDavid du Colombier */
362*8ccd4a63SDavid du Colombier for(;;){
363*8ccd4a63SDavid du Colombier qlock(&exq.qwait);
364*8ccd4a63SDavid du Colombier rendsleep(&exq.rwait, exwork, nil);
365*8ccd4a63SDavid du Colombier
366*8ccd4a63SDavid du Colombier lock(&exq.l);
367*8ccd4a63SDavid du Colombier q = exq.head;
368*8ccd4a63SDavid du Colombier if(q == nil) {
369*8ccd4a63SDavid du Colombier unlock(&exq.l);
370*8ccd4a63SDavid du Colombier qunlock(&exq.qwait);
371*8ccd4a63SDavid du Colombier continue;
372*8ccd4a63SDavid du Colombier }
373*8ccd4a63SDavid du Colombier exq.head = q->next;
374*8ccd4a63SDavid du Colombier q->slave = curthread();
375*8ccd4a63SDavid du Colombier unlock(&exq.l);
376*8ccd4a63SDavid du Colombier
377*8ccd4a63SDavid du Colombier qunlock(&exq.qwait);
378*8ccd4a63SDavid du Colombier
379*8ccd4a63SDavid du Colombier q->noresponse = 0;
380*8ccd4a63SDavid du Colombier q->nointr = 0;
381*8ccd4a63SDavid du Colombier fs = q->export;
382*8ccd4a63SDavid du Colombier lock(&fs->r.l);
383*8ccd4a63SDavid du Colombier q->next = fs->work;
384*8ccd4a63SDavid du Colombier fs->work = q;
385*8ccd4a63SDavid du Colombier unlock(&fs->r.l);
386*8ccd4a63SDavid du Colombier
387*8ccd4a63SDavid du Colombier up->pgrp = q->export->pgrp;
388*8ccd4a63SDavid du Colombier
389*8ccd4a63SDavid du Colombier if(exdebug > 1)
390*8ccd4a63SDavid du Colombier iprint("exslave dispatch %d %F\n", getpid(), &q->rpc);
391*8ccd4a63SDavid du Colombier
392*8ccd4a63SDavid du Colombier if(waserror()){
393*8ccd4a63SDavid du Colombier iprint("exslave err %r\n");
394*8ccd4a63SDavid du Colombier err = up->errstr;
395*8ccd4a63SDavid du Colombier goto Err;
396*8ccd4a63SDavid du Colombier }
397*8ccd4a63SDavid du Colombier if(q->rpc.type >= Tmax || !fcalls[q->rpc.type])
398*8ccd4a63SDavid du Colombier err = "bad fcall type";
399*8ccd4a63SDavid du Colombier else
400*8ccd4a63SDavid du Colombier err = (*fcalls[q->rpc.type])(fs, &q->rpc);
401*8ccd4a63SDavid du Colombier
402*8ccd4a63SDavid du Colombier poperror();
403*8ccd4a63SDavid du Colombier Err:;
404*8ccd4a63SDavid du Colombier q->rpc.type++;
405*8ccd4a63SDavid du Colombier if(err){
406*8ccd4a63SDavid du Colombier q->rpc.type = Rerror;
407*8ccd4a63SDavid du Colombier strncpy(q->rpc.ename, err, ERRLEN);
408*8ccd4a63SDavid du Colombier }
409*8ccd4a63SDavid du Colombier n = convS2M(&q->rpc, q->buf);
410*8ccd4a63SDavid du Colombier
411*8ccd4a63SDavid du Colombier if(exdebug)
412*8ccd4a63SDavid du Colombier iprint("exslve %d -> %F\n", getpid(), &q->rpc);
413*8ccd4a63SDavid du Colombier
414*8ccd4a63SDavid du Colombier lock(&q->lk);
415*8ccd4a63SDavid du Colombier if(q->noresponse == 0){
416*8ccd4a63SDavid du Colombier q->nointr = 1;
417*8ccd4a63SDavid du Colombier clearintr();
418*8ccd4a63SDavid du Colombier if(!waserror()){
419*8ccd4a63SDavid du Colombier (*devtab[fs->io->type].write)(fs->io, q->buf, n, 0);
420*8ccd4a63SDavid du Colombier poperror();
421*8ccd4a63SDavid du Colombier }
422*8ccd4a63SDavid du Colombier }
423*8ccd4a63SDavid du Colombier unlock(&q->lk);
424*8ccd4a63SDavid du Colombier
425*8ccd4a63SDavid du Colombier /*
426*8ccd4a63SDavid du Colombier * exflush might set noresponse at this point, but
427*8ccd4a63SDavid du Colombier * setting noresponse means don't send a response now;
428*8ccd4a63SDavid du Colombier * it's okay that we sent a response already.
429*8ccd4a63SDavid du Colombier */
430*8ccd4a63SDavid du Colombier if(exdebug > 1)
431*8ccd4a63SDavid du Colombier iprint("exslave %d written %d\n", getpid(), q->rpc.tag);
432*8ccd4a63SDavid du Colombier
433*8ccd4a63SDavid du Colombier lock(&fs->r.l);
434*8ccd4a63SDavid du Colombier last = &fs->work;
435*8ccd4a63SDavid du Colombier for(t = fs->work; t != nil; t = t->next){
436*8ccd4a63SDavid du Colombier if(t == q){
437*8ccd4a63SDavid du Colombier *last = q->next;
438*8ccd4a63SDavid du Colombier break;
439*8ccd4a63SDavid du Colombier }
440*8ccd4a63SDavid du Colombier last = &t->next;
441*8ccd4a63SDavid du Colombier }
442*8ccd4a63SDavid du Colombier unlock(&fs->r.l);
443*8ccd4a63SDavid du Colombier
444*8ccd4a63SDavid du Colombier exfree(q->export);
445*8ccd4a63SDavid du Colombier free(q);
446*8ccd4a63SDavid du Colombier }
447*8ccd4a63SDavid du Colombier iprint("exslave shut down");
448*8ccd4a63SDavid du Colombier threadexit();
449*8ccd4a63SDavid du Colombier }
450*8ccd4a63SDavid du Colombier
451*8ccd4a63SDavid du Colombier Fid*
Exmkfid(Export * fs,int fid)452*8ccd4a63SDavid du Colombier Exmkfid(Export *fs, int fid)
453*8ccd4a63SDavid du Colombier {
454*8ccd4a63SDavid du Colombier ulong h;
455*8ccd4a63SDavid du Colombier Fid *f, *nf;
456*8ccd4a63SDavid du Colombier
457*8ccd4a63SDavid du Colombier nf = mallocz(sizeof(Fid));
458*8ccd4a63SDavid du Colombier if(nf == nil)
459*8ccd4a63SDavid du Colombier return nil;
460*8ccd4a63SDavid du Colombier lock(&fs->fidlock);
461*8ccd4a63SDavid du Colombier h = fid % Nfidhash;
462*8ccd4a63SDavid du Colombier for(f = fs->fid[h]; f != nil; f = f->next){
463*8ccd4a63SDavid du Colombier if(f->fid == fid){
464*8ccd4a63SDavid du Colombier unlock(&fs->fidlock);
465*8ccd4a63SDavid du Colombier free(nf);
466*8ccd4a63SDavid du Colombier return nil;
467*8ccd4a63SDavid du Colombier }
468*8ccd4a63SDavid du Colombier }
469*8ccd4a63SDavid du Colombier
470*8ccd4a63SDavid du Colombier nf->next = fs->fid[h];
471*8ccd4a63SDavid du Colombier if(nf->next != nil)
472*8ccd4a63SDavid du Colombier nf->next->last = &nf->next;
473*8ccd4a63SDavid du Colombier nf->last = &fs->fid[h];
474*8ccd4a63SDavid du Colombier fs->fid[h] = nf;
475*8ccd4a63SDavid du Colombier
476*8ccd4a63SDavid du Colombier nf->fid = fid;
477*8ccd4a63SDavid du Colombier nf->ref = 1;
478*8ccd4a63SDavid du Colombier nf->attached = 1;
479*8ccd4a63SDavid du Colombier nf->offset = 0;
480*8ccd4a63SDavid du Colombier nf->chan = nil;
481*8ccd4a63SDavid du Colombier unlock(&fs->fidlock);
482*8ccd4a63SDavid du Colombier return nf;
483*8ccd4a63SDavid du Colombier }
484*8ccd4a63SDavid du Colombier
485*8ccd4a63SDavid du Colombier Fid*
Exgetfid(Export * fs,int fid)486*8ccd4a63SDavid du Colombier Exgetfid(Export *fs, int fid)
487*8ccd4a63SDavid du Colombier {
488*8ccd4a63SDavid du Colombier Fid *f;
489*8ccd4a63SDavid du Colombier ulong h;
490*8ccd4a63SDavid du Colombier
491*8ccd4a63SDavid du Colombier lock(&fs->fidlock);
492*8ccd4a63SDavid du Colombier h = fid % Nfidhash;
493*8ccd4a63SDavid du Colombier for(f = fs->fid[h]; f; f = f->next) {
494*8ccd4a63SDavid du Colombier if(f->fid == fid){
495*8ccd4a63SDavid du Colombier if(f->attached == 0)
496*8ccd4a63SDavid du Colombier break;
497*8ccd4a63SDavid du Colombier f->ref++;
498*8ccd4a63SDavid du Colombier unlock(&fs->fidlock);
499*8ccd4a63SDavid du Colombier return f;
500*8ccd4a63SDavid du Colombier }
501*8ccd4a63SDavid du Colombier }
502*8ccd4a63SDavid du Colombier unlock(&fs->fidlock);
503*8ccd4a63SDavid du Colombier return nil;
504*8ccd4a63SDavid du Colombier }
505*8ccd4a63SDavid du Colombier
506*8ccd4a63SDavid du Colombier void
Exputfid(Export * fs,Fid * f)507*8ccd4a63SDavid du Colombier Exputfid(Export *fs, Fid *f)
508*8ccd4a63SDavid du Colombier {
509*8ccd4a63SDavid du Colombier lock(&fs->fidlock);
510*8ccd4a63SDavid du Colombier f->ref--;
511*8ccd4a63SDavid du Colombier if(f->ref == 0 && f->attached == 0){
512*8ccd4a63SDavid du Colombier if(f->chan != nil)
513*8ccd4a63SDavid du Colombier cclose(f->chan);
514*8ccd4a63SDavid du Colombier f->chan = nil;
515*8ccd4a63SDavid du Colombier *f->last = f->next;
516*8ccd4a63SDavid du Colombier if(f->next != nil)
517*8ccd4a63SDavid du Colombier f->next->last = f->last;
518*8ccd4a63SDavid du Colombier unlock(&fs->fidlock);
519*8ccd4a63SDavid du Colombier free(f);
520*8ccd4a63SDavid du Colombier return;
521*8ccd4a63SDavid du Colombier }
522*8ccd4a63SDavid du Colombier unlock(&fs->fidlock);
523*8ccd4a63SDavid du Colombier }
524*8ccd4a63SDavid du Colombier
525*8ccd4a63SDavid du Colombier char*
Exsession(Export * e,Fcall * rpc)526*8ccd4a63SDavid du Colombier Exsession(Export *e, Fcall *rpc)
527*8ccd4a63SDavid du Colombier {
528*8ccd4a63SDavid du Colombier memset(rpc->authid, 0, sizeof(rpc->authid));
529*8ccd4a63SDavid du Colombier memset(rpc->authdom, 0, sizeof(rpc->authdom));
530*8ccd4a63SDavid du Colombier memset(rpc->chal, 0, sizeof(rpc->chal));
531*8ccd4a63SDavid du Colombier return nil;
532*8ccd4a63SDavid du Colombier }
533*8ccd4a63SDavid du Colombier
534*8ccd4a63SDavid du Colombier char*
Exauth(Export * e,Fcall * f)535*8ccd4a63SDavid du Colombier Exauth(Export *e, Fcall *f)
536*8ccd4a63SDavid du Colombier {
537*8ccd4a63SDavid du Colombier return "authentication not required";
538*8ccd4a63SDavid du Colombier }
539*8ccd4a63SDavid du Colombier
540*8ccd4a63SDavid du Colombier char*
Exattach(Export * fs,Fcall * rpc)541*8ccd4a63SDavid du Colombier Exattach(Export *fs, Fcall *rpc)
542*8ccd4a63SDavid du Colombier {
543*8ccd4a63SDavid du Colombier Fid *f;
544*8ccd4a63SDavid du Colombier
545*8ccd4a63SDavid du Colombier f = Exmkfid(fs, rpc->fid);
546*8ccd4a63SDavid du Colombier if(f == nil)
547*8ccd4a63SDavid du Colombier return Einuse;
548*8ccd4a63SDavid du Colombier if(waserror()){
549*8ccd4a63SDavid du Colombier f->attached = 0;
550*8ccd4a63SDavid du Colombier Exputfid(fs, f);
551*8ccd4a63SDavid du Colombier return up->errstr;
552*8ccd4a63SDavid du Colombier }
553*8ccd4a63SDavid du Colombier f->chan = clone(fs->root, nil);
554*8ccd4a63SDavid du Colombier poperror();
555*8ccd4a63SDavid du Colombier rpc->qid = f->chan->qid;
556*8ccd4a63SDavid du Colombier Exputfid(fs, f);
557*8ccd4a63SDavid du Colombier return nil;
558*8ccd4a63SDavid du Colombier }
559*8ccd4a63SDavid du Colombier
560*8ccd4a63SDavid du Colombier char*
Exclone(Export * fs,Fcall * rpc)561*8ccd4a63SDavid du Colombier Exclone(Export *fs, Fcall *rpc)
562*8ccd4a63SDavid du Colombier {
563*8ccd4a63SDavid du Colombier Fid *f, *nf;
564*8ccd4a63SDavid du Colombier
565*8ccd4a63SDavid du Colombier if(rpc->fid == rpc->newfid)
566*8ccd4a63SDavid du Colombier return Einuse;
567*8ccd4a63SDavid du Colombier f = Exgetfid(fs, rpc->fid);
568*8ccd4a63SDavid du Colombier if(f == nil)
569*8ccd4a63SDavid du Colombier return Enofid;
570*8ccd4a63SDavid du Colombier nf = Exmkfid(fs, rpc->newfid);
571*8ccd4a63SDavid du Colombier if(nf == nil){
572*8ccd4a63SDavid du Colombier Exputfid(fs, f);
573*8ccd4a63SDavid du Colombier return Einuse;
574*8ccd4a63SDavid du Colombier }
575*8ccd4a63SDavid du Colombier if(waserror()){
576*8ccd4a63SDavid du Colombier Exputfid(fs, f);
577*8ccd4a63SDavid du Colombier Exputfid(fs, nf);
578*8ccd4a63SDavid du Colombier return up->errstr;
579*8ccd4a63SDavid du Colombier }
580*8ccd4a63SDavid du Colombier nf->chan = clone(f->chan, nil);
581*8ccd4a63SDavid du Colombier poperror();
582*8ccd4a63SDavid du Colombier Exputfid(fs, f);
583*8ccd4a63SDavid du Colombier Exputfid(fs, nf);
584*8ccd4a63SDavid du Colombier return nil;
585*8ccd4a63SDavid du Colombier }
586*8ccd4a63SDavid du Colombier
587*8ccd4a63SDavid du Colombier char*
Exclunk(Export * fs,Fcall * rpc)588*8ccd4a63SDavid du Colombier Exclunk(Export *fs, Fcall *rpc)
589*8ccd4a63SDavid du Colombier {
590*8ccd4a63SDavid du Colombier Fid *f;
591*8ccd4a63SDavid du Colombier
592*8ccd4a63SDavid du Colombier f = Exgetfid(fs, rpc->fid);
593*8ccd4a63SDavid du Colombier if(f != nil){
594*8ccd4a63SDavid du Colombier f->attached = 0;
595*8ccd4a63SDavid du Colombier Exputfid(fs, f);
596*8ccd4a63SDavid du Colombier }
597*8ccd4a63SDavid du Colombier return nil;
598*8ccd4a63SDavid du Colombier }
599*8ccd4a63SDavid du Colombier
600*8ccd4a63SDavid du Colombier char*
Exwalk(Export * fs,Fcall * rpc)601*8ccd4a63SDavid du Colombier Exwalk(Export *fs, Fcall *rpc)
602*8ccd4a63SDavid du Colombier {
603*8ccd4a63SDavid du Colombier Fid *f;
604*8ccd4a63SDavid du Colombier Chan *c;
605*8ccd4a63SDavid du Colombier
606*8ccd4a63SDavid du Colombier f = Exgetfid(fs, rpc->fid);
607*8ccd4a63SDavid du Colombier if(f == nil)
608*8ccd4a63SDavid du Colombier return Enofid;
609*8ccd4a63SDavid du Colombier if(waserror()){
610*8ccd4a63SDavid du Colombier Exputfid(fs, f);
611*8ccd4a63SDavid du Colombier return up->errstr;
612*8ccd4a63SDavid du Colombier }
613*8ccd4a63SDavid du Colombier c = walk(f->chan, rpc->name, 1);
614*8ccd4a63SDavid du Colombier if(c == nil)
615*8ccd4a63SDavid du Colombier error(Enonexist);
616*8ccd4a63SDavid du Colombier poperror();
617*8ccd4a63SDavid du Colombier
618*8ccd4a63SDavid du Colombier f->chan = c;
619*8ccd4a63SDavid du Colombier rpc->qid = c->qid;
620*8ccd4a63SDavid du Colombier Exputfid(fs, f);
621*8ccd4a63SDavid du Colombier return nil;
622*8ccd4a63SDavid du Colombier }
623*8ccd4a63SDavid du Colombier
624*8ccd4a63SDavid du Colombier char*
Exopen(Export * fs,Fcall * rpc)625*8ccd4a63SDavid du Colombier Exopen(Export *fs, Fcall *rpc)
626*8ccd4a63SDavid du Colombier {
627*8ccd4a63SDavid du Colombier Fid *f;
628*8ccd4a63SDavid du Colombier Chan *c;
629*8ccd4a63SDavid du Colombier
630*8ccd4a63SDavid du Colombier f = Exgetfid(fs, rpc->fid);
631*8ccd4a63SDavid du Colombier if(f == nil)
632*8ccd4a63SDavid du Colombier return Enofid;
633*8ccd4a63SDavid du Colombier if(waserror()){
634*8ccd4a63SDavid du Colombier Exputfid(fs, f);
635*8ccd4a63SDavid du Colombier return up->errstr;
636*8ccd4a63SDavid du Colombier }
637*8ccd4a63SDavid du Colombier c = f->chan;
638*8ccd4a63SDavid du Colombier c = (*devtab[c->type].open)(c, rpc->mode);
639*8ccd4a63SDavid du Colombier poperror();
640*8ccd4a63SDavid du Colombier
641*8ccd4a63SDavid du Colombier f->chan = c;
642*8ccd4a63SDavid du Colombier f->offset = 0;
643*8ccd4a63SDavid du Colombier rpc->qid = f->chan->qid;
644*8ccd4a63SDavid du Colombier Exputfid(fs, f);
645*8ccd4a63SDavid du Colombier return nil;
646*8ccd4a63SDavid du Colombier }
647*8ccd4a63SDavid du Colombier
648*8ccd4a63SDavid du Colombier char*
Excreate(Export * fs,Fcall * rpc)649*8ccd4a63SDavid du Colombier Excreate(Export *fs, Fcall *rpc)
650*8ccd4a63SDavid du Colombier {
651*8ccd4a63SDavid du Colombier Fid *f;
652*8ccd4a63SDavid du Colombier Chan *c;
653*8ccd4a63SDavid du Colombier
654*8ccd4a63SDavid du Colombier f = Exgetfid(fs, rpc->fid);
655*8ccd4a63SDavid du Colombier if(f == nil)
656*8ccd4a63SDavid du Colombier return Enofid;
657*8ccd4a63SDavid du Colombier if(waserror()){
658*8ccd4a63SDavid du Colombier Exputfid(fs, f);
659*8ccd4a63SDavid du Colombier return up->errstr;
660*8ccd4a63SDavid du Colombier }
661*8ccd4a63SDavid du Colombier c = f->chan;
662*8ccd4a63SDavid du Colombier if(c->mnt && !(c->flag&CCREATE))
663*8ccd4a63SDavid du Colombier c = createdir(c);
664*8ccd4a63SDavid du Colombier (*devtab[c->type].create)(c, rpc->name, rpc->mode, rpc->perm);
665*8ccd4a63SDavid du Colombier poperror();
666*8ccd4a63SDavid du Colombier
667*8ccd4a63SDavid du Colombier f->chan = c;
668*8ccd4a63SDavid du Colombier rpc->qid = f->chan->qid;
669*8ccd4a63SDavid du Colombier Exputfid(fs, f);
670*8ccd4a63SDavid du Colombier return nil;
671*8ccd4a63SDavid du Colombier }
672*8ccd4a63SDavid du Colombier
673*8ccd4a63SDavid du Colombier char*
Exread(Export * fs,Fcall * rpc)674*8ccd4a63SDavid du Colombier Exread(Export *fs, Fcall *rpc)
675*8ccd4a63SDavid du Colombier {
676*8ccd4a63SDavid du Colombier Fid *f;
677*8ccd4a63SDavid du Colombier Chan *c;
678*8ccd4a63SDavid du Colombier long off;
679*8ccd4a63SDavid du Colombier int dir, n, seek;
680*8ccd4a63SDavid du Colombier
681*8ccd4a63SDavid du Colombier f = Exgetfid(fs, rpc->fid);
682*8ccd4a63SDavid du Colombier if(f == nil)
683*8ccd4a63SDavid du Colombier return Enofid;
684*8ccd4a63SDavid du Colombier
685*8ccd4a63SDavid du Colombier c = f->chan;
686*8ccd4a63SDavid du Colombier dir = c->qid.path & CHDIR;
687*8ccd4a63SDavid du Colombier if(dir){
688*8ccd4a63SDavid du Colombier rpc->count -= rpc->count%DIRLEN;
689*8ccd4a63SDavid du Colombier if(rpc->offset%DIRLEN || rpc->count==0){
690*8ccd4a63SDavid du Colombier Exputfid(fs, f);
691*8ccd4a63SDavid du Colombier return Ereaddir;
692*8ccd4a63SDavid du Colombier }
693*8ccd4a63SDavid du Colombier if(f->offset > rpc->offset){
694*8ccd4a63SDavid du Colombier Exputfid(fs, f);
695*8ccd4a63SDavid du Colombier return Eseekdir;
696*8ccd4a63SDavid du Colombier }
697*8ccd4a63SDavid du Colombier }
698*8ccd4a63SDavid du Colombier
699*8ccd4a63SDavid du Colombier if(waserror()) {
700*8ccd4a63SDavid du Colombier Exputfid(fs, f);
701*8ccd4a63SDavid du Colombier return up->errstr;
702*8ccd4a63SDavid du Colombier }
703*8ccd4a63SDavid du Colombier
704*8ccd4a63SDavid du Colombier for(;;){
705*8ccd4a63SDavid du Colombier n = rpc->count;
706*8ccd4a63SDavid du Colombier seek = 0;
707*8ccd4a63SDavid du Colombier off = rpc->offset;
708*8ccd4a63SDavid du Colombier if(dir && f->offset != off){
709*8ccd4a63SDavid du Colombier off = f->offset;
710*8ccd4a63SDavid du Colombier n = rpc->offset - off;
711*8ccd4a63SDavid du Colombier if(n > MAXDIRREAD)
712*8ccd4a63SDavid du Colombier n = MAXDIRREAD;
713*8ccd4a63SDavid du Colombier seek = 1;
714*8ccd4a63SDavid du Colombier }
715*8ccd4a63SDavid du Colombier if(dir && c->mnt != nil)
716*8ccd4a63SDavid du Colombier n = unionread(c, rpc->data, n);
717*8ccd4a63SDavid du Colombier else{
718*8ccd4a63SDavid du Colombier c->offset = off;
719*8ccd4a63SDavid du Colombier n = (*devtab[c->type].read)(c, rpc->data, n, off);
720*8ccd4a63SDavid du Colombier }
721*8ccd4a63SDavid du Colombier if(n == 0 || !seek)
722*8ccd4a63SDavid du Colombier break;
723*8ccd4a63SDavid du Colombier f->offset = off + n;
724*8ccd4a63SDavid du Colombier c->offset += n;
725*8ccd4a63SDavid du Colombier }
726*8ccd4a63SDavid du Colombier rpc->count = n;
727*8ccd4a63SDavid du Colombier poperror();
728*8ccd4a63SDavid du Colombier Exputfid(fs, f);
729*8ccd4a63SDavid du Colombier return nil;
730*8ccd4a63SDavid du Colombier }
731*8ccd4a63SDavid du Colombier
732*8ccd4a63SDavid du Colombier char*
Exwrite(Export * fs,Fcall * rpc)733*8ccd4a63SDavid du Colombier Exwrite(Export *fs, Fcall *rpc)
734*8ccd4a63SDavid du Colombier {
735*8ccd4a63SDavid du Colombier Fid *f;
736*8ccd4a63SDavid du Colombier Chan *c;
737*8ccd4a63SDavid du Colombier
738*8ccd4a63SDavid du Colombier f = Exgetfid(fs, rpc->fid);
739*8ccd4a63SDavid du Colombier if(f == nil)
740*8ccd4a63SDavid du Colombier return Enofid;
741*8ccd4a63SDavid du Colombier if(waserror()){
742*8ccd4a63SDavid du Colombier Exputfid(fs, f);
743*8ccd4a63SDavid du Colombier return up->errstr;
744*8ccd4a63SDavid du Colombier }
745*8ccd4a63SDavid du Colombier c = f->chan;
746*8ccd4a63SDavid du Colombier if(c->qid.path & CHDIR)
747*8ccd4a63SDavid du Colombier error(Eisdir);
748*8ccd4a63SDavid du Colombier rpc->count = (*devtab[c->type].write)(c, rpc->data, rpc->count, rpc->offset);
749*8ccd4a63SDavid du Colombier poperror();
750*8ccd4a63SDavid du Colombier Exputfid(fs, f);
751*8ccd4a63SDavid du Colombier return nil;
752*8ccd4a63SDavid du Colombier }
753*8ccd4a63SDavid du Colombier
754*8ccd4a63SDavid du Colombier char*
Exstat(Export * fs,Fcall * rpc)755*8ccd4a63SDavid du Colombier Exstat(Export *fs, Fcall *rpc)
756*8ccd4a63SDavid du Colombier {
757*8ccd4a63SDavid du Colombier Fid *f;
758*8ccd4a63SDavid du Colombier Chan *c;
759*8ccd4a63SDavid du Colombier
760*8ccd4a63SDavid du Colombier f = Exgetfid(fs, rpc->fid);
761*8ccd4a63SDavid du Colombier if(f == nil)
762*8ccd4a63SDavid du Colombier return Enofid;
763*8ccd4a63SDavid du Colombier if(waserror()){
764*8ccd4a63SDavid du Colombier Exputfid(fs, f);
765*8ccd4a63SDavid du Colombier return up->errstr;
766*8ccd4a63SDavid du Colombier }
767*8ccd4a63SDavid du Colombier c = f->chan;
768*8ccd4a63SDavid du Colombier (*devtab[c->type].stat)(c, rpc->stat);
769*8ccd4a63SDavid du Colombier poperror();
770*8ccd4a63SDavid du Colombier Exputfid(fs, f);
771*8ccd4a63SDavid du Colombier return nil;
772*8ccd4a63SDavid du Colombier }
773*8ccd4a63SDavid du Colombier
774*8ccd4a63SDavid du Colombier char*
Exwstat(Export * fs,Fcall * rpc)775*8ccd4a63SDavid du Colombier Exwstat(Export *fs, Fcall *rpc)
776*8ccd4a63SDavid du Colombier {
777*8ccd4a63SDavid du Colombier Fid *f;
778*8ccd4a63SDavid du Colombier Chan *c;
779*8ccd4a63SDavid du Colombier
780*8ccd4a63SDavid du Colombier f = Exgetfid(fs, rpc->fid);
781*8ccd4a63SDavid du Colombier if(f == nil)
782*8ccd4a63SDavid du Colombier return Enofid;
783*8ccd4a63SDavid du Colombier if(waserror()){
784*8ccd4a63SDavid du Colombier Exputfid(fs, f);
785*8ccd4a63SDavid du Colombier return up->errstr;
786*8ccd4a63SDavid du Colombier }
787*8ccd4a63SDavid du Colombier c = f->chan;
788*8ccd4a63SDavid du Colombier (*devtab[c->type].wstat)(c, rpc->stat);
789*8ccd4a63SDavid du Colombier poperror();
790*8ccd4a63SDavid du Colombier Exputfid(fs, f);
791*8ccd4a63SDavid du Colombier return nil;
792*8ccd4a63SDavid du Colombier }
793*8ccd4a63SDavid du Colombier
794*8ccd4a63SDavid du Colombier char*
Exremove(Export * fs,Fcall * rpc)795*8ccd4a63SDavid du Colombier Exremove(Export *fs, Fcall *rpc)
796*8ccd4a63SDavid du Colombier {
797*8ccd4a63SDavid du Colombier Fid *f;
798*8ccd4a63SDavid du Colombier Chan *c;
799*8ccd4a63SDavid du Colombier
800*8ccd4a63SDavid du Colombier f = Exgetfid(fs, rpc->fid);
801*8ccd4a63SDavid du Colombier if(f == nil)
802*8ccd4a63SDavid du Colombier return Enofid;
803*8ccd4a63SDavid du Colombier if(waserror()){
804*8ccd4a63SDavid du Colombier Exputfid(fs, f);
805*8ccd4a63SDavid du Colombier return up->errstr;
806*8ccd4a63SDavid du Colombier }
807*8ccd4a63SDavid du Colombier c = f->chan;
808*8ccd4a63SDavid du Colombier (*devtab[c->type].remove)(c);
809*8ccd4a63SDavid du Colombier poperror();
810*8ccd4a63SDavid du Colombier
811*8ccd4a63SDavid du Colombier /*
812*8ccd4a63SDavid du Colombier * chan is already clunked by remove.
813*8ccd4a63SDavid du Colombier * however, we need to recover the chan,
814*8ccd4a63SDavid du Colombier * and follow sysremove's lead in making to point to root.
815*8ccd4a63SDavid du Colombier */
816*8ccd4a63SDavid du Colombier c->type = 0;
817*8ccd4a63SDavid du Colombier
818*8ccd4a63SDavid du Colombier f->attached = 0;
819*8ccd4a63SDavid du Colombier Exputfid(fs, f);
820*8ccd4a63SDavid du Colombier return nil;
821*8ccd4a63SDavid du Colombier }
822