xref: /plan9/sys/src/cmd/aux/flashfs/request.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1*9a747e4fSDavid du Colombier #include <u.h>
2*9a747e4fSDavid du Colombier #include <libc.h>
3*9a747e4fSDavid du Colombier #include <auth.h>
4*9a747e4fSDavid du Colombier #include <fcall.h>
5*9a747e4fSDavid du Colombier #include <thread.h>
6*9a747e4fSDavid du Colombier #include <9p.h>
7*9a747e4fSDavid du Colombier #include "flashfs.h"
8*9a747e4fSDavid du Colombier 
9*9a747e4fSDavid du Colombier static	Srv	flashsrv;
10*9a747e4fSDavid du Colombier 
11*9a747e4fSDavid du Colombier typedef struct	State	State;
12*9a747e4fSDavid du Colombier 
13*9a747e4fSDavid du Colombier struct State
14*9a747e4fSDavid du Colombier {
15*9a747e4fSDavid du Colombier 	Entry	*e;
16*9a747e4fSDavid du Colombier 	Dirr	*r;
17*9a747e4fSDavid du Colombier };
18*9a747e4fSDavid du Colombier 
19*9a747e4fSDavid du Colombier #define	writeable(e)	((e)->mode & 0222)
20*9a747e4fSDavid du Colombier 
21*9a747e4fSDavid du Colombier static State *
state(Entry * e)22*9a747e4fSDavid du Colombier state(Entry *e)
23*9a747e4fSDavid du Colombier {
24*9a747e4fSDavid du Colombier 	State *s;
25*9a747e4fSDavid du Colombier 
26*9a747e4fSDavid du Colombier 	s = emalloc9p(sizeof(State));
27*9a747e4fSDavid du Colombier 	s->e = e;
28*9a747e4fSDavid du Colombier 	s->r = nil;
29*9a747e4fSDavid du Colombier 	return s;
30*9a747e4fSDavid du Colombier }
31*9a747e4fSDavid du Colombier 
32*9a747e4fSDavid du Colombier static void
destroy(Fid * f)33*9a747e4fSDavid du Colombier destroy(Fid *f)
34*9a747e4fSDavid du Colombier {
35*9a747e4fSDavid du Colombier 	State *s;
36*9a747e4fSDavid du Colombier 
37*9a747e4fSDavid du Colombier 	s = f->aux;
38*9a747e4fSDavid du Colombier 	if(s == nil)		/* Tauth fids have no state */
39*9a747e4fSDavid du Colombier 		return;
40*9a747e4fSDavid du Colombier 
41*9a747e4fSDavid du Colombier 	f->aux = nil;
42*9a747e4fSDavid du Colombier 	if(s->e)
43*9a747e4fSDavid du Colombier 		edestroy(s->e);
44*9a747e4fSDavid du Colombier 	if(s->r)
45*9a747e4fSDavid du Colombier 		edirclose(s->r);
46*9a747e4fSDavid du Colombier 	free(s);
47*9a747e4fSDavid du Colombier }
48*9a747e4fSDavid du Colombier 
49*9a747e4fSDavid du Colombier static void
trace(Req *)50*9a747e4fSDavid du Colombier trace(Req *)
51*9a747e4fSDavid du Colombier {
52*9a747e4fSDavid du Colombier 	edump();
53*9a747e4fSDavid du Colombier }
54*9a747e4fSDavid du Colombier 
55*9a747e4fSDavid du Colombier /** T_ **/
56*9a747e4fSDavid du Colombier 
57*9a747e4fSDavid du Colombier static void
flattach(Req * r)58*9a747e4fSDavid du Colombier flattach(Req *r)
59*9a747e4fSDavid du Colombier {
60*9a747e4fSDavid du Colombier 	root->ref++;
61*9a747e4fSDavid du Colombier 	r->ofcall.qid = eqid(root);
62*9a747e4fSDavid du Colombier 	r->fid->qid = r->ofcall.qid;
63*9a747e4fSDavid du Colombier 	r->fid->aux = state(root);
64*9a747e4fSDavid du Colombier 	respond(r, nil);
65*9a747e4fSDavid du Colombier }
66*9a747e4fSDavid du Colombier 
67*9a747e4fSDavid du Colombier static void
flopen(Req * r)68*9a747e4fSDavid du Colombier flopen(Req *r)
69*9a747e4fSDavid du Colombier {
70*9a747e4fSDavid du Colombier 	Jrec j;
71*9a747e4fSDavid du Colombier 	int m, p;
72*9a747e4fSDavid du Colombier 	Entry *e;
73*9a747e4fSDavid du Colombier 	State *s;
74*9a747e4fSDavid du Colombier 	char *err;
75*9a747e4fSDavid du Colombier 
76*9a747e4fSDavid du Colombier 	s = r->fid->aux;
77*9a747e4fSDavid du Colombier 	e = s->e;
78*9a747e4fSDavid du Colombier 	m = e->mode;
79*9a747e4fSDavid du Colombier 	m = (m | (m >> 3) | (m >> 6)) & 7;
80*9a747e4fSDavid du Colombier 	switch(r->ifcall.mode & 3) {
81*9a747e4fSDavid du Colombier 	case OREAD:
82*9a747e4fSDavid du Colombier 		p = AREAD;
83*9a747e4fSDavid du Colombier 		break;
84*9a747e4fSDavid du Colombier 	case OWRITE:
85*9a747e4fSDavid du Colombier 		p = AWRITE;
86*9a747e4fSDavid du Colombier 		break;
87*9a747e4fSDavid du Colombier 	case ORDWR:
88*9a747e4fSDavid du Colombier 		p = AREAD|AWRITE;
89*9a747e4fSDavid du Colombier 		break;
90*9a747e4fSDavid du Colombier 	case OEXEC:
91*9a747e4fSDavid du Colombier 		p = AEXEC;
92*9a747e4fSDavid du Colombier 		break;
93*9a747e4fSDavid du Colombier 	default:
94*9a747e4fSDavid du Colombier 		p = 0;
95*9a747e4fSDavid du Colombier 		break;
96*9a747e4fSDavid du Colombier 	}
97*9a747e4fSDavid du Colombier 
98*9a747e4fSDavid du Colombier 	if((p & m) != p) {
99*9a747e4fSDavid du Colombier 		respond(r, Eperm);
100*9a747e4fSDavid du Colombier 		return;
101*9a747e4fSDavid du Colombier 	}
102*9a747e4fSDavid du Colombier 
103*9a747e4fSDavid du Colombier 	if(readonly && (p & AWRITE) != 0) {
104*9a747e4fSDavid du Colombier 		respond(r, Erofs);
105*9a747e4fSDavid du Colombier 		return;
106*9a747e4fSDavid du Colombier 	}
107*9a747e4fSDavid du Colombier 
108*9a747e4fSDavid du Colombier 	r->ofcall.qid = eqid(e);
109*9a747e4fSDavid du Colombier 	if(r->ofcall.qid.type & QTDIR) {
110*9a747e4fSDavid du Colombier 		if((p & AWRITE) != 0) {
111*9a747e4fSDavid du Colombier 			respond(r, Eisdir);
112*9a747e4fSDavid du Colombier 			return;
113*9a747e4fSDavid du Colombier 		}
114*9a747e4fSDavid du Colombier 		s->r = ediropen(s->e);
115*9a747e4fSDavid du Colombier 	}
116*9a747e4fSDavid du Colombier 	else if(r->ifcall.mode & OTRUNC) {
117*9a747e4fSDavid du Colombier 		err = need(Ntrunc);
118*9a747e4fSDavid du Colombier 		if(err != nil) {
119*9a747e4fSDavid du Colombier 			respond(r, err);
120*9a747e4fSDavid du Colombier 			return;
121*9a747e4fSDavid du Colombier 		}
122*9a747e4fSDavid du Colombier 		j.type = FT_trunc;
123*9a747e4fSDavid du Colombier 		j.tnum = e->fnum;
124*9a747e4fSDavid du Colombier 		j.mtime = now();
125*9a747e4fSDavid du Colombier 		etrunc(e, 0, j.mtime);
126*9a747e4fSDavid du Colombier 		j.fnum = e->fnum;
127*9a747e4fSDavid du Colombier 		j.parent = e->parent->fnum;
128*9a747e4fSDavid du Colombier 		j.mode = e->mode;
129*9a747e4fSDavid du Colombier 		strcpy(j.name, e->name);
130*9a747e4fSDavid du Colombier 		put(&j, 1);
131*9a747e4fSDavid du Colombier 	}
132*9a747e4fSDavid du Colombier 
133*9a747e4fSDavid du Colombier 	respond(r, nil);
134*9a747e4fSDavid du Colombier }
135*9a747e4fSDavid du Colombier 
136*9a747e4fSDavid du Colombier static void
flcreate(Req * r)137*9a747e4fSDavid du Colombier flcreate(Req *r)
138*9a747e4fSDavid du Colombier {
139*9a747e4fSDavid du Colombier 	Jrec j;
140*9a747e4fSDavid du Colombier 	State *s;
141*9a747e4fSDavid du Colombier 	char *err;
142*9a747e4fSDavid du Colombier 	Entry *e, *f;
143*9a747e4fSDavid du Colombier 
144*9a747e4fSDavid du Colombier 	if(readonly) {
145*9a747e4fSDavid du Colombier 		respond(r, Erofs);
146*9a747e4fSDavid du Colombier 		return;
147*9a747e4fSDavid du Colombier 	}
148*9a747e4fSDavid du Colombier 
149*9a747e4fSDavid du Colombier 	s = r->fid->aux;
150*9a747e4fSDavid du Colombier 	e = s->e;
151*9a747e4fSDavid du Colombier 	if((e->mode & DMDIR) == 0) {
152*9a747e4fSDavid du Colombier 		respond(r, Eisdir);
153*9a747e4fSDavid du Colombier 		return;
154*9a747e4fSDavid du Colombier 	}
155*9a747e4fSDavid du Colombier 
156*9a747e4fSDavid du Colombier 	if(!writeable(e)) {
157*9a747e4fSDavid du Colombier 		respond(r, Eperm);
158*9a747e4fSDavid du Colombier 		return;
159*9a747e4fSDavid du Colombier 	}
160*9a747e4fSDavid du Colombier 
161*9a747e4fSDavid du Colombier 	if(strlen(r->ifcall.name) > MAXNSIZE) {
162*9a747e4fSDavid du Colombier 		respond(r, "filename too long");
163*9a747e4fSDavid du Colombier 		return;
164*9a747e4fSDavid du Colombier 	}
165*9a747e4fSDavid du Colombier 
166*9a747e4fSDavid du Colombier 	err = need(Ncreate);
167*9a747e4fSDavid du Colombier 	if(err != nil) {
168*9a747e4fSDavid du Colombier 		respond(r, err);
169*9a747e4fSDavid du Colombier 		return;
170*9a747e4fSDavid du Colombier 	}
171*9a747e4fSDavid du Colombier 
172*9a747e4fSDavid du Colombier 	j.type = FT_create;
173*9a747e4fSDavid du Colombier 	j.mtime = now();
174*9a747e4fSDavid du Colombier 	j.parent = e->fnum;
175*9a747e4fSDavid du Colombier 	j.mode = r->ifcall.perm;
176*9a747e4fSDavid du Colombier 	strcpy(j.name, r->ifcall.name);
177*9a747e4fSDavid du Colombier 
178*9a747e4fSDavid du Colombier 	f = ecreate(e, r->ifcall.name, 0, r->ifcall.perm, j.mtime, &err);
179*9a747e4fSDavid du Colombier 	if(f == nil) {
180*9a747e4fSDavid du Colombier 		respond(r, err);
181*9a747e4fSDavid du Colombier 		return;
182*9a747e4fSDavid du Colombier 	}
183*9a747e4fSDavid du Colombier 
184*9a747e4fSDavid du Colombier 	j.fnum = f->fnum;
185*9a747e4fSDavid du Colombier 	put(&j, 1);
186*9a747e4fSDavid du Colombier 	s->e = f;
187*9a747e4fSDavid du Colombier 	r->ofcall.qid = eqid(f);
188*9a747e4fSDavid du Colombier 	respond(r, nil);
189*9a747e4fSDavid du Colombier }
190*9a747e4fSDavid du Colombier 
191*9a747e4fSDavid du Colombier static void
flread(Req * r)192*9a747e4fSDavid du Colombier flread(Req *r)
193*9a747e4fSDavid du Colombier {
194*9a747e4fSDavid du Colombier 	Entry *e;
195*9a747e4fSDavid du Colombier 	State *s;
196*9a747e4fSDavid du Colombier 
197*9a747e4fSDavid du Colombier 	s = r->fid->aux;
198*9a747e4fSDavid du Colombier 	e = s->e;
199*9a747e4fSDavid du Colombier 
200*9a747e4fSDavid du Colombier 	if(e->mode & DMDIR)
201*9a747e4fSDavid du Colombier 		r->ofcall.count = edirread(s->r, r->ofcall.data, r->ifcall.count);
202*9a747e4fSDavid du Colombier 	else
203*9a747e4fSDavid du Colombier 		r->ofcall.count = eread(e, eparity, r->ofcall.data, r->ifcall.count, r->ifcall.offset);
204*9a747e4fSDavid du Colombier 
205*9a747e4fSDavid du Colombier 	respond(r, nil);
206*9a747e4fSDavid du Colombier }
207*9a747e4fSDavid du Colombier 
208*9a747e4fSDavid du Colombier static void
flwrite(Req * r)209*9a747e4fSDavid du Colombier flwrite(Req *r)
210*9a747e4fSDavid du Colombier {
211*9a747e4fSDavid du Colombier 	Jrec j;
212*9a747e4fSDavid du Colombier 	uchar *a;
213*9a747e4fSDavid du Colombier 	Entry *e;
214*9a747e4fSDavid du Colombier 	State *s;
215*9a747e4fSDavid du Colombier 	Extent *x;
216*9a747e4fSDavid du Colombier 	char *err;
217*9a747e4fSDavid du Colombier 	ulong c, n, o, mtime;
218*9a747e4fSDavid du Colombier 
219*9a747e4fSDavid du Colombier 	c = r->ifcall.count;
220*9a747e4fSDavid du Colombier 	o = r->ifcall.offset;
221*9a747e4fSDavid du Colombier 	a = (uchar *)r->ifcall.data;
222*9a747e4fSDavid du Colombier 
223*9a747e4fSDavid du Colombier 	if(c == 0) {
224*9a747e4fSDavid du Colombier 		respond(r, nil);
225*9a747e4fSDavid du Colombier 		return;
226*9a747e4fSDavid du Colombier 	}
227*9a747e4fSDavid du Colombier 
228*9a747e4fSDavid du Colombier 	if(o + c >= MAXFSIZE) {
229*9a747e4fSDavid du Colombier 		respond(r, "file too big");
230*9a747e4fSDavid du Colombier 		return;
231*9a747e4fSDavid du Colombier 	}
232*9a747e4fSDavid du Colombier 
233*9a747e4fSDavid du Colombier 	if(used + c > limit) {
234*9a747e4fSDavid du Colombier 		respond(r, "filesystem full");
235*9a747e4fSDavid du Colombier 		return;
236*9a747e4fSDavid du Colombier 	}
237*9a747e4fSDavid du Colombier 
238*9a747e4fSDavid du Colombier 	r->ofcall.count = c;
239*9a747e4fSDavid du Colombier 	s = r->fid->aux;
240*9a747e4fSDavid du Colombier 	e = s->e;
241*9a747e4fSDavid du Colombier 	mtime = now();
242*9a747e4fSDavid du Colombier 
243*9a747e4fSDavid du Colombier 	for(;;) {
244*9a747e4fSDavid du Colombier 		n = c;
245*9a747e4fSDavid du Colombier 		if(n > maxwrite)
246*9a747e4fSDavid du Colombier 			n = maxwrite;
247*9a747e4fSDavid du Colombier 
248*9a747e4fSDavid du Colombier 		err = need(Nwrite + n);
249*9a747e4fSDavid du Colombier 		if(err != nil) {
250*9a747e4fSDavid du Colombier 			respond(r, err);
251*9a747e4fSDavid du Colombier 			return;
252*9a747e4fSDavid du Colombier 		}
253*9a747e4fSDavid du Colombier 
254*9a747e4fSDavid du Colombier 		x = emalloc9p(sizeof(Extent));
255*9a747e4fSDavid du Colombier 		x->size = n;
256*9a747e4fSDavid du Colombier 		x->off = o;
257*9a747e4fSDavid du Colombier 		ewrite(e, x, eparity, mtime);
258*9a747e4fSDavid du Colombier 		j.type = FT_WRITE;
259*9a747e4fSDavid du Colombier 		j.fnum = e->fnum;
260*9a747e4fSDavid du Colombier 		j.size = n;
261*9a747e4fSDavid du Colombier 		j.offset = o;
262*9a747e4fSDavid du Colombier 		j.mtime = mtime;
263*9a747e4fSDavid du Colombier 		putw(&j, 1, x, a);
264*9a747e4fSDavid du Colombier 		c -= n;
265*9a747e4fSDavid du Colombier 
266*9a747e4fSDavid du Colombier 		if(c == 0)
267*9a747e4fSDavid du Colombier 			break;
268*9a747e4fSDavid du Colombier 
269*9a747e4fSDavid du Colombier 		o += n;
270*9a747e4fSDavid du Colombier 		a += n;
271*9a747e4fSDavid du Colombier 	}
272*9a747e4fSDavid du Colombier 
273*9a747e4fSDavid du Colombier 	respond(r, nil);
274*9a747e4fSDavid du Colombier }
275*9a747e4fSDavid du Colombier 
276*9a747e4fSDavid du Colombier static void
flremove(Req * r)277*9a747e4fSDavid du Colombier flremove(Req *r)
278*9a747e4fSDavid du Colombier {
279*9a747e4fSDavid du Colombier 	Jrec j;
280*9a747e4fSDavid du Colombier 	State *s;
281*9a747e4fSDavid du Colombier 	Entry *e;
282*9a747e4fSDavid du Colombier 	char *d, *err;
283*9a747e4fSDavid du Colombier 
284*9a747e4fSDavid du Colombier 	if(readonly) {
285*9a747e4fSDavid du Colombier 		respond(r, Erofs);
286*9a747e4fSDavid du Colombier 		return;
287*9a747e4fSDavid du Colombier 	}
288*9a747e4fSDavid du Colombier 
289*9a747e4fSDavid du Colombier 	s = r->fid->aux;
290*9a747e4fSDavid du Colombier 	e = s->e;
291*9a747e4fSDavid du Colombier 	if(writeable(e->parent)) {
292*9a747e4fSDavid du Colombier 		err = need(Nremove);
293*9a747e4fSDavid du Colombier 		if(err != nil) {
294*9a747e4fSDavid du Colombier 			respond(r, err);
295*9a747e4fSDavid du Colombier 			return;
296*9a747e4fSDavid du Colombier 		}
297*9a747e4fSDavid du Colombier 
298*9a747e4fSDavid du Colombier 		d = eremove(e);
299*9a747e4fSDavid du Colombier 		if(d == nil) {
300*9a747e4fSDavid du Colombier 			j.type = FT_REMOVE;
301*9a747e4fSDavid du Colombier 			j.fnum = e->fnum;
302*9a747e4fSDavid du Colombier 			put(&j, 0);
303*9a747e4fSDavid du Colombier 		}
304*9a747e4fSDavid du Colombier 		respond(r, d);
305*9a747e4fSDavid du Colombier 	}
306*9a747e4fSDavid du Colombier 	else
307*9a747e4fSDavid du Colombier 		respond(r, Eperm);
308*9a747e4fSDavid du Colombier }
309*9a747e4fSDavid du Colombier 
310*9a747e4fSDavid du Colombier static void
flstat(Req * r)311*9a747e4fSDavid du Colombier flstat(Req *r)
312*9a747e4fSDavid du Colombier {
313*9a747e4fSDavid du Colombier 	State *s;
314*9a747e4fSDavid du Colombier 
315*9a747e4fSDavid du Colombier 	s = r->fid->aux;
316*9a747e4fSDavid du Colombier 	estat(s->e, &r->d, 1);
317*9a747e4fSDavid du Colombier 	respond(r, nil);
318*9a747e4fSDavid du Colombier }
319*9a747e4fSDavid du Colombier 
320*9a747e4fSDavid du Colombier static void
flwstat(Req * r)321*9a747e4fSDavid du Colombier flwstat(Req *r)
322*9a747e4fSDavid du Colombier {
323*9a747e4fSDavid du Colombier 	int m;
324*9a747e4fSDavid du Colombier 	Jrec j;
325*9a747e4fSDavid du Colombier 	State *s;
326*9a747e4fSDavid du Colombier 	Entry *e;
327*9a747e4fSDavid du Colombier 	char *err;
328*9a747e4fSDavid du Colombier 
329*9a747e4fSDavid du Colombier 	s = r->fid->aux;
330*9a747e4fSDavid du Colombier 	e = s->e;
331*9a747e4fSDavid du Colombier 
332*9a747e4fSDavid du Colombier 	if(readonly) {
333*9a747e4fSDavid du Colombier 		respond(r, Erofs);
334*9a747e4fSDavid du Colombier 		return;
335*9a747e4fSDavid du Colombier 	}
336*9a747e4fSDavid du Colombier 
337*9a747e4fSDavid du Colombier 	if(e->fnum == 0) {
338*9a747e4fSDavid du Colombier 		respond(r, Eperm);
339*9a747e4fSDavid du Colombier 		return;
340*9a747e4fSDavid du Colombier 	}
341*9a747e4fSDavid du Colombier 
342*9a747e4fSDavid du Colombier 	m = r->d.mode & 0777;
343*9a747e4fSDavid du Colombier 	if(m != (e->mode & 0777)) {
344*9a747e4fSDavid du Colombier 		err = need(Nchmod);
345*9a747e4fSDavid du Colombier 		if(err != nil) {
346*9a747e4fSDavid du Colombier 			respond(r, err);
347*9a747e4fSDavid du Colombier 			return;
348*9a747e4fSDavid du Colombier 		}
349*9a747e4fSDavid du Colombier 
350*9a747e4fSDavid du Colombier 		echmod(e, m, 0);
351*9a747e4fSDavid du Colombier 		j.type = FT_chmod;
352*9a747e4fSDavid du Colombier 		j.mode = m;
353*9a747e4fSDavid du Colombier 		j.fnum = e->fnum;
354*9a747e4fSDavid du Colombier 		j.mnum = e->mnum;
355*9a747e4fSDavid du Colombier 		put(&j, 0);
356*9a747e4fSDavid du Colombier 	}
357*9a747e4fSDavid du Colombier 	respond(r, nil);
358*9a747e4fSDavid du Colombier }
359*9a747e4fSDavid du Colombier 
360*9a747e4fSDavid du Colombier static void
flwalk(Req * r)361*9a747e4fSDavid du Colombier flwalk(Req *r)
362*9a747e4fSDavid du Colombier {
363*9a747e4fSDavid du Colombier 	int i;
364*9a747e4fSDavid du Colombier 	State *s;
365*9a747e4fSDavid du Colombier 	char *err;
366*9a747e4fSDavid du Colombier 	Entry *e, *f;
367*9a747e4fSDavid du Colombier 
368*9a747e4fSDavid du Colombier 	if(r->ifcall.fid != r->ifcall.newfid)
369*9a747e4fSDavid du Colombier 		r->newfid->aux = state(nil);
370*9a747e4fSDavid du Colombier 
371*9a747e4fSDavid du Colombier 	s = r->fid->aux;
372*9a747e4fSDavid du Colombier 	e = s->e;
373*9a747e4fSDavid du Colombier 	f = e;
374*9a747e4fSDavid du Colombier 	e->ref++;
375*9a747e4fSDavid du Colombier 	err = nil;
376*9a747e4fSDavid du Colombier 	for(i = 0; i < r->ifcall.nwname; i++) {
377*9a747e4fSDavid du Colombier 		f = ewalk(e, r->ifcall.wname[i], &err);
378*9a747e4fSDavid du Colombier 		if(f) {
379*9a747e4fSDavid du Colombier 			r->ofcall.wqid[i] = eqid(f);
380*9a747e4fSDavid du Colombier 			e = f;
381*9a747e4fSDavid du Colombier 		}
382*9a747e4fSDavid du Colombier 		else {
383*9a747e4fSDavid du Colombier 			e->ref--;
384*9a747e4fSDavid du Colombier 			break;
385*9a747e4fSDavid du Colombier 		}
386*9a747e4fSDavid du Colombier 	}
387*9a747e4fSDavid du Colombier 	r->ofcall.nwqid = i;
388*9a747e4fSDavid du Colombier 	if (i) err = nil;
389*9a747e4fSDavid du Colombier 
390*9a747e4fSDavid du Colombier 	if(f) {
391*9a747e4fSDavid du Colombier 		if(r->ifcall.fid != r->ifcall.newfid) {
392*9a747e4fSDavid du Colombier 			s = r->newfid->aux;
393*9a747e4fSDavid du Colombier 			s->e = f;
394*9a747e4fSDavid du Colombier 			r->newfid->qid = eqid(f);
395*9a747e4fSDavid du Colombier 		}
396*9a747e4fSDavid du Colombier 		else {
397*9a747e4fSDavid du Colombier 			s = r->fid->aux;
398*9a747e4fSDavid du Colombier 			s->e->ref--;
399*9a747e4fSDavid du Colombier 			s->e = f;
400*9a747e4fSDavid du Colombier 			r->fid->qid = eqid(f);
401*9a747e4fSDavid du Colombier 		}
402*9a747e4fSDavid du Colombier 	}
403*9a747e4fSDavid du Colombier 	respond(r, err);
404*9a747e4fSDavid du Colombier }
405*9a747e4fSDavid du Colombier 
406*9a747e4fSDavid du Colombier void
serve(char * mount)407*9a747e4fSDavid du Colombier serve(char *mount)
408*9a747e4fSDavid du Colombier {
409*9a747e4fSDavid du Colombier 	flashsrv.attach = flattach;
410*9a747e4fSDavid du Colombier 	flashsrv.open = flopen;
411*9a747e4fSDavid du Colombier 	flashsrv.create = flcreate;
412*9a747e4fSDavid du Colombier 	flashsrv.read = flread;
413*9a747e4fSDavid du Colombier 	flashsrv.write = flwrite;
414*9a747e4fSDavid du Colombier 	flashsrv.remove = flremove;
415*9a747e4fSDavid du Colombier 	flashsrv.stat = flstat;
416*9a747e4fSDavid du Colombier 	flashsrv.wstat = flwstat;
417*9a747e4fSDavid du Colombier 	flashsrv.walk = flwalk;
418*9a747e4fSDavid du Colombier 
419*9a747e4fSDavid du Colombier 	flashsrv.destroyfid = destroy;
420*9a747e4fSDavid du Colombier 	flashsrv.destroyreq = trace;
421*9a747e4fSDavid du Colombier 	postmountsrv(&flashsrv, "brzr", mount, MREPL|MCREATE);
422*9a747e4fSDavid du Colombier }
423