1*84d9c625SLionel Sambuc /* $NetBSD: framebuf.c,v 1.32 2012/06/25 22:32:47 abs Exp $ */
2*84d9c625SLionel Sambuc
3*84d9c625SLionel Sambuc /*
4*84d9c625SLionel Sambuc * Copyright (c) 2007 Antti Kantee. All Rights Reserved.
5*84d9c625SLionel Sambuc *
6*84d9c625SLionel Sambuc * Development of this software was supported by the
7*84d9c625SLionel Sambuc * Finnish Cultural Foundation.
8*84d9c625SLionel Sambuc *
9*84d9c625SLionel Sambuc * Redistribution and use in source and binary forms, with or without
10*84d9c625SLionel Sambuc * modification, are permitted provided that the following conditions
11*84d9c625SLionel Sambuc * are met:
12*84d9c625SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
13*84d9c625SLionel Sambuc * notice, this list of conditions and the following disclaimer.
14*84d9c625SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
15*84d9c625SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
16*84d9c625SLionel Sambuc * documentation and/or other materials provided with the distribution.
17*84d9c625SLionel Sambuc *
18*84d9c625SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19*84d9c625SLionel Sambuc * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20*84d9c625SLionel Sambuc * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21*84d9c625SLionel Sambuc * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22*84d9c625SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*84d9c625SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24*84d9c625SLionel Sambuc * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*84d9c625SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*84d9c625SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*84d9c625SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*84d9c625SLionel Sambuc * SUCH DAMAGE.
29*84d9c625SLionel Sambuc */
30*84d9c625SLionel Sambuc
31*84d9c625SLionel Sambuc /*
32*84d9c625SLionel Sambuc * The event portion of this code is a twisty maze of pointers,
33*84d9c625SLionel Sambuc * flags, yields and continues. Sincere aplogies.
34*84d9c625SLionel Sambuc */
35*84d9c625SLionel Sambuc
36*84d9c625SLionel Sambuc #include <sys/cdefs.h>
37*84d9c625SLionel Sambuc #if !defined(lint)
38*84d9c625SLionel Sambuc __RCSID("$NetBSD: framebuf.c,v 1.32 2012/06/25 22:32:47 abs Exp $");
39*84d9c625SLionel Sambuc #endif /* !lint */
40*84d9c625SLionel Sambuc
41*84d9c625SLionel Sambuc #include <sys/types.h>
42*84d9c625SLionel Sambuc #include <sys/queue.h>
43*84d9c625SLionel Sambuc
44*84d9c625SLionel Sambuc #include <assert.h>
45*84d9c625SLionel Sambuc #include <errno.h>
46*84d9c625SLionel Sambuc #include <poll.h>
47*84d9c625SLionel Sambuc #include <puffs.h>
48*84d9c625SLionel Sambuc #include <stdio.h>
49*84d9c625SLionel Sambuc #include <stdlib.h>
50*84d9c625SLionel Sambuc #include <unistd.h>
51*84d9c625SLionel Sambuc
52*84d9c625SLionel Sambuc #include "puffs_priv.h"
53*84d9c625SLionel Sambuc
54*84d9c625SLionel Sambuc struct puffs_framebuf {
55*84d9c625SLionel Sambuc struct puffs_cc *pcc; /* pcc to continue with */
56*84d9c625SLionel Sambuc /* OR */
57*84d9c625SLionel Sambuc puffs_framev_cb fcb; /* non-blocking callback */
58*84d9c625SLionel Sambuc void *fcb_arg; /* argument for previous */
59*84d9c625SLionel Sambuc
60*84d9c625SLionel Sambuc uint8_t *buf; /* buffer base */
61*84d9c625SLionel Sambuc size_t len; /* total length */
62*84d9c625SLionel Sambuc
63*84d9c625SLionel Sambuc size_t offset; /* cursor, telloff() */
64*84d9c625SLionel Sambuc size_t maxoff; /* maximum offset for data, tellsize() */
65*84d9c625SLionel Sambuc
66*84d9c625SLionel Sambuc volatile int rv; /* errno value */
67*84d9c625SLionel Sambuc
68*84d9c625SLionel Sambuc int istat;
69*84d9c625SLionel Sambuc
70*84d9c625SLionel Sambuc TAILQ_ENTRY(puffs_framebuf) pfb_entries;
71*84d9c625SLionel Sambuc };
72*84d9c625SLionel Sambuc #define ISTAT_NODESTROY 0x01 /* indestructible by framebuf_destroy() */
73*84d9c625SLionel Sambuc #define ISTAT_INTERNAL 0x02 /* never leaves library */
74*84d9c625SLionel Sambuc #define ISTAT_NOREPLY 0x04 /* nuke after sending */
75*84d9c625SLionel Sambuc #define ISTAT_DIRECT 0x08 /* receive directly, no moveinfo */
76*84d9c625SLionel Sambuc
77*84d9c625SLionel Sambuc #define ISTAT_ONQUEUE ISTAT_NODESTROY /* alias */
78*84d9c625SLionel Sambuc
79*84d9c625SLionel Sambuc #define PUFBUF_INCRALLOC 4096
80*84d9c625SLionel Sambuc #define PUFBUF_REMAIN(p) (p->len - p->offset)
81*84d9c625SLionel Sambuc
82*84d9c625SLionel Sambuc /* for poll/kqueue */
83*84d9c625SLionel Sambuc struct puffs_fbevent {
84*84d9c625SLionel Sambuc struct puffs_cc *pcc;
85*84d9c625SLionel Sambuc int what;
86*84d9c625SLionel Sambuc volatile int rv;
87*84d9c625SLionel Sambuc
88*84d9c625SLionel Sambuc LIST_ENTRY(puffs_fbevent) pfe_entries;
89*84d9c625SLionel Sambuc };
90*84d9c625SLionel Sambuc
91*84d9c625SLionel Sambuc static struct puffs_fctrl_io *
getfiobyfd(struct puffs_usermount * pu,int fd)92*84d9c625SLionel Sambuc getfiobyfd(struct puffs_usermount *pu, int fd)
93*84d9c625SLionel Sambuc {
94*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio;
95*84d9c625SLionel Sambuc
96*84d9c625SLionel Sambuc LIST_FOREACH(fio, &pu->pu_ios, fio_entries)
97*84d9c625SLionel Sambuc if (fio->io_fd == fd)
98*84d9c625SLionel Sambuc return fio;
99*84d9c625SLionel Sambuc return NULL;
100*84d9c625SLionel Sambuc }
101*84d9c625SLionel Sambuc
102*84d9c625SLionel Sambuc struct puffs_framebuf *
puffs_framebuf_make(void)103*84d9c625SLionel Sambuc puffs_framebuf_make(void)
104*84d9c625SLionel Sambuc {
105*84d9c625SLionel Sambuc struct puffs_framebuf *pufbuf;
106*84d9c625SLionel Sambuc
107*84d9c625SLionel Sambuc pufbuf = malloc(sizeof(struct puffs_framebuf));
108*84d9c625SLionel Sambuc if (pufbuf == NULL)
109*84d9c625SLionel Sambuc return NULL;
110*84d9c625SLionel Sambuc memset(pufbuf, 0, sizeof(struct puffs_framebuf));
111*84d9c625SLionel Sambuc
112*84d9c625SLionel Sambuc pufbuf->buf = malloc(PUFBUF_INCRALLOC);
113*84d9c625SLionel Sambuc if (pufbuf->buf == NULL) {
114*84d9c625SLionel Sambuc free(pufbuf);
115*84d9c625SLionel Sambuc return NULL;
116*84d9c625SLionel Sambuc }
117*84d9c625SLionel Sambuc pufbuf->len = PUFBUF_INCRALLOC;
118*84d9c625SLionel Sambuc
119*84d9c625SLionel Sambuc puffs_framebuf_recycle(pufbuf);
120*84d9c625SLionel Sambuc return pufbuf;
121*84d9c625SLionel Sambuc }
122*84d9c625SLionel Sambuc
123*84d9c625SLionel Sambuc void
puffs_framebuf_destroy(struct puffs_framebuf * pufbuf)124*84d9c625SLionel Sambuc puffs_framebuf_destroy(struct puffs_framebuf *pufbuf)
125*84d9c625SLionel Sambuc {
126*84d9c625SLionel Sambuc
127*84d9c625SLionel Sambuc assert((pufbuf->istat & ISTAT_NODESTROY) == 0);
128*84d9c625SLionel Sambuc
129*84d9c625SLionel Sambuc free(pufbuf->buf);
130*84d9c625SLionel Sambuc free(pufbuf);
131*84d9c625SLionel Sambuc }
132*84d9c625SLionel Sambuc
133*84d9c625SLionel Sambuc void
puffs_framebuf_recycle(struct puffs_framebuf * pufbuf)134*84d9c625SLionel Sambuc puffs_framebuf_recycle(struct puffs_framebuf *pufbuf)
135*84d9c625SLionel Sambuc {
136*84d9c625SLionel Sambuc
137*84d9c625SLionel Sambuc assert((pufbuf->istat & ISTAT_NODESTROY) == 0);
138*84d9c625SLionel Sambuc
139*84d9c625SLionel Sambuc pufbuf->offset = 0;
140*84d9c625SLionel Sambuc pufbuf->maxoff = 0;
141*84d9c625SLionel Sambuc pufbuf->istat = 0;
142*84d9c625SLionel Sambuc }
143*84d9c625SLionel Sambuc
144*84d9c625SLionel Sambuc static int
reservespace(struct puffs_framebuf * pufbuf,size_t off,size_t wantsize)145*84d9c625SLionel Sambuc reservespace(struct puffs_framebuf *pufbuf, size_t off, size_t wantsize)
146*84d9c625SLionel Sambuc {
147*84d9c625SLionel Sambuc size_t incr;
148*84d9c625SLionel Sambuc void *nd;
149*84d9c625SLionel Sambuc
150*84d9c625SLionel Sambuc if (off <= pufbuf->len && pufbuf->len - off >= wantsize)
151*84d9c625SLionel Sambuc return 0;
152*84d9c625SLionel Sambuc
153*84d9c625SLionel Sambuc for (incr = PUFBUF_INCRALLOC;
154*84d9c625SLionel Sambuc pufbuf->len + incr < off + wantsize;
155*84d9c625SLionel Sambuc incr += PUFBUF_INCRALLOC)
156*84d9c625SLionel Sambuc continue;
157*84d9c625SLionel Sambuc
158*84d9c625SLionel Sambuc nd = realloc(pufbuf->buf, pufbuf->len + incr);
159*84d9c625SLionel Sambuc if (nd == NULL)
160*84d9c625SLionel Sambuc return -1;
161*84d9c625SLionel Sambuc
162*84d9c625SLionel Sambuc pufbuf->buf = nd;
163*84d9c625SLionel Sambuc pufbuf->len += incr;
164*84d9c625SLionel Sambuc
165*84d9c625SLionel Sambuc return 0;
166*84d9c625SLionel Sambuc }
167*84d9c625SLionel Sambuc
168*84d9c625SLionel Sambuc int
puffs_framebuf_dup(struct puffs_framebuf * pb,struct puffs_framebuf ** pbp)169*84d9c625SLionel Sambuc puffs_framebuf_dup(struct puffs_framebuf *pb, struct puffs_framebuf **pbp)
170*84d9c625SLionel Sambuc {
171*84d9c625SLionel Sambuc struct puffs_framebuf *newpb;
172*84d9c625SLionel Sambuc
173*84d9c625SLionel Sambuc newpb = puffs_framebuf_make();
174*84d9c625SLionel Sambuc if (newpb == NULL) {
175*84d9c625SLionel Sambuc errno = ENOMEM;
176*84d9c625SLionel Sambuc return -1;
177*84d9c625SLionel Sambuc }
178*84d9c625SLionel Sambuc memcpy(newpb, pb, sizeof(struct puffs_framebuf));
179*84d9c625SLionel Sambuc
180*84d9c625SLionel Sambuc newpb->buf = NULL;
181*84d9c625SLionel Sambuc newpb->len = 0;
182*84d9c625SLionel Sambuc if (reservespace(newpb, 0, pb->maxoff) == -1) {
183*84d9c625SLionel Sambuc puffs_framebuf_destroy(newpb);
184*84d9c625SLionel Sambuc return -1;
185*84d9c625SLionel Sambuc }
186*84d9c625SLionel Sambuc
187*84d9c625SLionel Sambuc memcpy(newpb->buf, pb->buf, pb->maxoff);
188*84d9c625SLionel Sambuc newpb->istat = 0;
189*84d9c625SLionel Sambuc *pbp = newpb;
190*84d9c625SLionel Sambuc
191*84d9c625SLionel Sambuc return 0;
192*84d9c625SLionel Sambuc }
193*84d9c625SLionel Sambuc
194*84d9c625SLionel Sambuc int
puffs_framebuf_reserve_space(struct puffs_framebuf * pufbuf,size_t wantsize)195*84d9c625SLionel Sambuc puffs_framebuf_reserve_space(struct puffs_framebuf *pufbuf, size_t wantsize)
196*84d9c625SLionel Sambuc {
197*84d9c625SLionel Sambuc
198*84d9c625SLionel Sambuc return reservespace(pufbuf, pufbuf->offset, wantsize);
199*84d9c625SLionel Sambuc }
200*84d9c625SLionel Sambuc
201*84d9c625SLionel Sambuc int
puffs_framebuf_putdata(struct puffs_framebuf * pufbuf,const void * data,size_t dlen)202*84d9c625SLionel Sambuc puffs_framebuf_putdata(struct puffs_framebuf *pufbuf,
203*84d9c625SLionel Sambuc const void *data, size_t dlen)
204*84d9c625SLionel Sambuc {
205*84d9c625SLionel Sambuc
206*84d9c625SLionel Sambuc if (PUFBUF_REMAIN(pufbuf) < dlen)
207*84d9c625SLionel Sambuc if (puffs_framebuf_reserve_space(pufbuf, dlen) == -1)
208*84d9c625SLionel Sambuc return -1;
209*84d9c625SLionel Sambuc
210*84d9c625SLionel Sambuc memcpy(pufbuf->buf + pufbuf->offset, data, dlen);
211*84d9c625SLionel Sambuc pufbuf->offset += dlen;
212*84d9c625SLionel Sambuc
213*84d9c625SLionel Sambuc if (pufbuf->offset > pufbuf->maxoff)
214*84d9c625SLionel Sambuc pufbuf->maxoff = pufbuf->offset;
215*84d9c625SLionel Sambuc
216*84d9c625SLionel Sambuc return 0;
217*84d9c625SLionel Sambuc }
218*84d9c625SLionel Sambuc
219*84d9c625SLionel Sambuc int
puffs_framebuf_putdata_atoff(struct puffs_framebuf * pufbuf,size_t offset,const void * data,size_t dlen)220*84d9c625SLionel Sambuc puffs_framebuf_putdata_atoff(struct puffs_framebuf *pufbuf, size_t offset,
221*84d9c625SLionel Sambuc const void *data, size_t dlen)
222*84d9c625SLionel Sambuc {
223*84d9c625SLionel Sambuc
224*84d9c625SLionel Sambuc if (reservespace(pufbuf, offset, dlen) == -1)
225*84d9c625SLionel Sambuc return -1;
226*84d9c625SLionel Sambuc
227*84d9c625SLionel Sambuc memcpy(pufbuf->buf + offset, data, dlen);
228*84d9c625SLionel Sambuc
229*84d9c625SLionel Sambuc if (offset + dlen > pufbuf->maxoff)
230*84d9c625SLionel Sambuc pufbuf->maxoff = offset + dlen;
231*84d9c625SLionel Sambuc
232*84d9c625SLionel Sambuc return 0;
233*84d9c625SLionel Sambuc }
234*84d9c625SLionel Sambuc
235*84d9c625SLionel Sambuc int
puffs_framebuf_getdata(struct puffs_framebuf * pufbuf,void * data,size_t dlen)236*84d9c625SLionel Sambuc puffs_framebuf_getdata(struct puffs_framebuf *pufbuf, void *data, size_t dlen)
237*84d9c625SLionel Sambuc {
238*84d9c625SLionel Sambuc
239*84d9c625SLionel Sambuc if (pufbuf->maxoff < pufbuf->offset + dlen) {
240*84d9c625SLionel Sambuc errno = ENOBUFS;
241*84d9c625SLionel Sambuc return -1;
242*84d9c625SLionel Sambuc }
243*84d9c625SLionel Sambuc
244*84d9c625SLionel Sambuc memcpy(data, pufbuf->buf + pufbuf->offset, dlen);
245*84d9c625SLionel Sambuc pufbuf->offset += dlen;
246*84d9c625SLionel Sambuc
247*84d9c625SLionel Sambuc return 0;
248*84d9c625SLionel Sambuc }
249*84d9c625SLionel Sambuc
250*84d9c625SLionel Sambuc int
puffs_framebuf_getdata_atoff(struct puffs_framebuf * pufbuf,size_t offset,void * data,size_t dlen)251*84d9c625SLionel Sambuc puffs_framebuf_getdata_atoff(struct puffs_framebuf *pufbuf, size_t offset,
252*84d9c625SLionel Sambuc void *data, size_t dlen)
253*84d9c625SLionel Sambuc {
254*84d9c625SLionel Sambuc
255*84d9c625SLionel Sambuc if (pufbuf->maxoff < offset + dlen) {
256*84d9c625SLionel Sambuc errno = ENOBUFS;
257*84d9c625SLionel Sambuc return -1;
258*84d9c625SLionel Sambuc }
259*84d9c625SLionel Sambuc
260*84d9c625SLionel Sambuc memcpy(data, pufbuf->buf + offset, dlen);
261*84d9c625SLionel Sambuc return 0;
262*84d9c625SLionel Sambuc }
263*84d9c625SLionel Sambuc
264*84d9c625SLionel Sambuc size_t
puffs_framebuf_telloff(struct puffs_framebuf * pufbuf)265*84d9c625SLionel Sambuc puffs_framebuf_telloff(struct puffs_framebuf *pufbuf)
266*84d9c625SLionel Sambuc {
267*84d9c625SLionel Sambuc
268*84d9c625SLionel Sambuc return pufbuf->offset;
269*84d9c625SLionel Sambuc }
270*84d9c625SLionel Sambuc
271*84d9c625SLionel Sambuc size_t
puffs_framebuf_tellsize(struct puffs_framebuf * pufbuf)272*84d9c625SLionel Sambuc puffs_framebuf_tellsize(struct puffs_framebuf *pufbuf)
273*84d9c625SLionel Sambuc {
274*84d9c625SLionel Sambuc
275*84d9c625SLionel Sambuc return pufbuf->maxoff;
276*84d9c625SLionel Sambuc }
277*84d9c625SLionel Sambuc
278*84d9c625SLionel Sambuc size_t
puffs_framebuf_remaining(struct puffs_framebuf * pufbuf)279*84d9c625SLionel Sambuc puffs_framebuf_remaining(struct puffs_framebuf *pufbuf)
280*84d9c625SLionel Sambuc {
281*84d9c625SLionel Sambuc
282*84d9c625SLionel Sambuc return puffs_framebuf_tellsize(pufbuf) - puffs_framebuf_telloff(pufbuf);
283*84d9c625SLionel Sambuc }
284*84d9c625SLionel Sambuc
285*84d9c625SLionel Sambuc int
puffs_framebuf_seekset(struct puffs_framebuf * pufbuf,size_t newoff)286*84d9c625SLionel Sambuc puffs_framebuf_seekset(struct puffs_framebuf *pufbuf, size_t newoff)
287*84d9c625SLionel Sambuc {
288*84d9c625SLionel Sambuc
289*84d9c625SLionel Sambuc if (reservespace(pufbuf, newoff, 0) == -1)
290*84d9c625SLionel Sambuc return -1;
291*84d9c625SLionel Sambuc
292*84d9c625SLionel Sambuc pufbuf->offset = newoff;
293*84d9c625SLionel Sambuc return 0;
294*84d9c625SLionel Sambuc }
295*84d9c625SLionel Sambuc
296*84d9c625SLionel Sambuc int
puffs_framebuf_getwindow(struct puffs_framebuf * pufbuf,size_t winoff,void ** data,size_t * dlen)297*84d9c625SLionel Sambuc puffs_framebuf_getwindow(struct puffs_framebuf *pufbuf, size_t winoff,
298*84d9c625SLionel Sambuc void **data, size_t *dlen)
299*84d9c625SLionel Sambuc {
300*84d9c625SLionel Sambuc size_t winlen;
301*84d9c625SLionel Sambuc
302*84d9c625SLionel Sambuc #ifdef WINTESTING
303*84d9c625SLionel Sambuc winlen = MIN(*dlen, 32);
304*84d9c625SLionel Sambuc #else
305*84d9c625SLionel Sambuc winlen = *dlen;
306*84d9c625SLionel Sambuc #endif
307*84d9c625SLionel Sambuc
308*84d9c625SLionel Sambuc if (reservespace(pufbuf, winoff, winlen) == -1)
309*84d9c625SLionel Sambuc return -1;
310*84d9c625SLionel Sambuc
311*84d9c625SLionel Sambuc *data = pufbuf->buf + winoff;
312*84d9c625SLionel Sambuc if (pufbuf->maxoff < winoff + winlen)
313*84d9c625SLionel Sambuc pufbuf->maxoff = winoff + winlen;
314*84d9c625SLionel Sambuc
315*84d9c625SLionel Sambuc return 0;
316*84d9c625SLionel Sambuc }
317*84d9c625SLionel Sambuc
318*84d9c625SLionel Sambuc void *
puffs__framebuf_getdataptr(struct puffs_framebuf * pufbuf)319*84d9c625SLionel Sambuc puffs__framebuf_getdataptr(struct puffs_framebuf *pufbuf)
320*84d9c625SLionel Sambuc {
321*84d9c625SLionel Sambuc
322*84d9c625SLionel Sambuc return pufbuf->buf;
323*84d9c625SLionel Sambuc }
324*84d9c625SLionel Sambuc
325*84d9c625SLionel Sambuc static void
errnotify(struct puffs_usermount * pu,struct puffs_framebuf * pufbuf,int error)326*84d9c625SLionel Sambuc errnotify(struct puffs_usermount *pu, struct puffs_framebuf *pufbuf, int error)
327*84d9c625SLionel Sambuc {
328*84d9c625SLionel Sambuc
329*84d9c625SLionel Sambuc pufbuf->rv = error;
330*84d9c625SLionel Sambuc if (pufbuf->pcc) {
331*84d9c625SLionel Sambuc puffs__goto(pufbuf->pcc);
332*84d9c625SLionel Sambuc } else if (pufbuf->fcb) {
333*84d9c625SLionel Sambuc pufbuf->istat &= ~ISTAT_NODESTROY;
334*84d9c625SLionel Sambuc pufbuf->fcb(pu, pufbuf, pufbuf->fcb_arg, error);
335*84d9c625SLionel Sambuc } else {
336*84d9c625SLionel Sambuc pufbuf->istat &= ~ISTAT_NODESTROY;
337*84d9c625SLionel Sambuc puffs_framebuf_destroy(pufbuf);
338*84d9c625SLionel Sambuc }
339*84d9c625SLionel Sambuc }
340*84d9c625SLionel Sambuc
341*84d9c625SLionel Sambuc #define GETFIO(fd) \
342*84d9c625SLionel Sambuc do { \
343*84d9c625SLionel Sambuc fio = getfiobyfd(pu, fd); \
344*84d9c625SLionel Sambuc if (fio == NULL) { \
345*84d9c625SLionel Sambuc errno = EINVAL; \
346*84d9c625SLionel Sambuc return -1; \
347*84d9c625SLionel Sambuc } \
348*84d9c625SLionel Sambuc if (fio->stat & FIO_WRGONE) { \
349*84d9c625SLionel Sambuc errno = ESHUTDOWN; \
350*84d9c625SLionel Sambuc return -1; \
351*84d9c625SLionel Sambuc } \
352*84d9c625SLionel Sambuc } while (/*CONSTCOND*/0)
353*84d9c625SLionel Sambuc
354*84d9c625SLionel Sambuc int
puffs_framev_enqueue_cc(struct puffs_cc * pcc,int fd,struct puffs_framebuf * pufbuf,int flags)355*84d9c625SLionel Sambuc puffs_framev_enqueue_cc(struct puffs_cc *pcc, int fd,
356*84d9c625SLionel Sambuc struct puffs_framebuf *pufbuf, int flags)
357*84d9c625SLionel Sambuc {
358*84d9c625SLionel Sambuc struct puffs_usermount *pu = pcc->pcc_pu;
359*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio;
360*84d9c625SLionel Sambuc
361*84d9c625SLionel Sambuc /*
362*84d9c625SLionel Sambuc * Technically we shouldn't allow this if RDGONE, but it's
363*84d9c625SLionel Sambuc * difficult to trap write close without allowing writes.
364*84d9c625SLionel Sambuc * And besides, there's probably a disconnect sequence in
365*84d9c625SLionel Sambuc * the protocol, so unexpectedly getting a closed fd is
366*84d9c625SLionel Sambuc * most likely an error condition.
367*84d9c625SLionel Sambuc */
368*84d9c625SLionel Sambuc GETFIO(fd);
369*84d9c625SLionel Sambuc
370*84d9c625SLionel Sambuc pufbuf->pcc = pcc;
371*84d9c625SLionel Sambuc pufbuf->fcb = NULL;
372*84d9c625SLionel Sambuc pufbuf->fcb_arg = NULL;
373*84d9c625SLionel Sambuc
374*84d9c625SLionel Sambuc pufbuf->offset = 0;
375*84d9c625SLionel Sambuc pufbuf->istat |= ISTAT_NODESTROY;
376*84d9c625SLionel Sambuc
377*84d9c625SLionel Sambuc if (flags & PUFFS_FBQUEUE_URGENT)
378*84d9c625SLionel Sambuc TAILQ_INSERT_HEAD(&fio->snd_qing, pufbuf, pfb_entries);
379*84d9c625SLionel Sambuc else
380*84d9c625SLionel Sambuc TAILQ_INSERT_TAIL(&fio->snd_qing, pufbuf, pfb_entries);
381*84d9c625SLionel Sambuc
382*84d9c625SLionel Sambuc puffs_cc_yield(pcc);
383*84d9c625SLionel Sambuc if (pufbuf->rv) {
384*84d9c625SLionel Sambuc pufbuf->istat &= ~ISTAT_NODESTROY;
385*84d9c625SLionel Sambuc errno = pufbuf->rv;
386*84d9c625SLionel Sambuc return -1;
387*84d9c625SLionel Sambuc }
388*84d9c625SLionel Sambuc
389*84d9c625SLionel Sambuc return 0;
390*84d9c625SLionel Sambuc }
391*84d9c625SLionel Sambuc
392*84d9c625SLionel Sambuc int
puffs_framev_enqueue_cb(struct puffs_usermount * pu,int fd,struct puffs_framebuf * pufbuf,puffs_framev_cb fcb,void * arg,int flags)393*84d9c625SLionel Sambuc puffs_framev_enqueue_cb(struct puffs_usermount *pu, int fd,
394*84d9c625SLionel Sambuc struct puffs_framebuf *pufbuf, puffs_framev_cb fcb, void *arg,
395*84d9c625SLionel Sambuc int flags)
396*84d9c625SLionel Sambuc {
397*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio;
398*84d9c625SLionel Sambuc
399*84d9c625SLionel Sambuc /* see enqueue_cc */
400*84d9c625SLionel Sambuc GETFIO(fd);
401*84d9c625SLionel Sambuc
402*84d9c625SLionel Sambuc pufbuf->pcc = NULL;
403*84d9c625SLionel Sambuc pufbuf->fcb = fcb;
404*84d9c625SLionel Sambuc pufbuf->fcb_arg = arg;
405*84d9c625SLionel Sambuc
406*84d9c625SLionel Sambuc pufbuf->offset = 0;
407*84d9c625SLionel Sambuc pufbuf->istat |= ISTAT_NODESTROY;
408*84d9c625SLionel Sambuc
409*84d9c625SLionel Sambuc if (flags & PUFFS_FBQUEUE_URGENT)
410*84d9c625SLionel Sambuc TAILQ_INSERT_HEAD(&fio->snd_qing, pufbuf, pfb_entries);
411*84d9c625SLionel Sambuc else
412*84d9c625SLionel Sambuc TAILQ_INSERT_TAIL(&fio->snd_qing, pufbuf, pfb_entries);
413*84d9c625SLionel Sambuc
414*84d9c625SLionel Sambuc return 0;
415*84d9c625SLionel Sambuc }
416*84d9c625SLionel Sambuc
417*84d9c625SLionel Sambuc int
puffs_framev_enqueue_justsend(struct puffs_usermount * pu,int fd,struct puffs_framebuf * pufbuf,int reply,int flags)418*84d9c625SLionel Sambuc puffs_framev_enqueue_justsend(struct puffs_usermount *pu, int fd,
419*84d9c625SLionel Sambuc struct puffs_framebuf *pufbuf, int reply, int flags)
420*84d9c625SLionel Sambuc {
421*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio;
422*84d9c625SLionel Sambuc
423*84d9c625SLionel Sambuc assert((pufbuf->istat & ISTAT_INTERNAL) == 0);
424*84d9c625SLionel Sambuc
425*84d9c625SLionel Sambuc GETFIO(fd);
426*84d9c625SLionel Sambuc
427*84d9c625SLionel Sambuc pufbuf->pcc = NULL;
428*84d9c625SLionel Sambuc pufbuf->fcb = NULL;
429*84d9c625SLionel Sambuc pufbuf->fcb_arg = NULL;
430*84d9c625SLionel Sambuc
431*84d9c625SLionel Sambuc pufbuf->offset = 0;
432*84d9c625SLionel Sambuc pufbuf->istat |= ISTAT_NODESTROY;
433*84d9c625SLionel Sambuc if (!reply)
434*84d9c625SLionel Sambuc pufbuf->istat |= ISTAT_NOREPLY;
435*84d9c625SLionel Sambuc
436*84d9c625SLionel Sambuc if (flags & PUFFS_FBQUEUE_URGENT)
437*84d9c625SLionel Sambuc TAILQ_INSERT_HEAD(&fio->snd_qing, pufbuf, pfb_entries);
438*84d9c625SLionel Sambuc else
439*84d9c625SLionel Sambuc TAILQ_INSERT_TAIL(&fio->snd_qing, pufbuf, pfb_entries);
440*84d9c625SLionel Sambuc
441*84d9c625SLionel Sambuc return 0;
442*84d9c625SLionel Sambuc }
443*84d9c625SLionel Sambuc
444*84d9c625SLionel Sambuc /* ARGSUSED */
445*84d9c625SLionel Sambuc int
puffs_framev_enqueue_directreceive(struct puffs_cc * pcc,int fd,struct puffs_framebuf * pufbuf,int flags)446*84d9c625SLionel Sambuc puffs_framev_enqueue_directreceive(struct puffs_cc *pcc, int fd,
447*84d9c625SLionel Sambuc struct puffs_framebuf *pufbuf, int flags /* used in the future */)
448*84d9c625SLionel Sambuc {
449*84d9c625SLionel Sambuc struct puffs_usermount *pu = pcc->pcc_pu;
450*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio;
451*84d9c625SLionel Sambuc
452*84d9c625SLionel Sambuc assert((pufbuf->istat & ISTAT_INTERNAL) == 0);
453*84d9c625SLionel Sambuc
454*84d9c625SLionel Sambuc fio = getfiobyfd(pu, fd);
455*84d9c625SLionel Sambuc if (fio == NULL) {
456*84d9c625SLionel Sambuc errno = EINVAL;
457*84d9c625SLionel Sambuc return -1;
458*84d9c625SLionel Sambuc }
459*84d9c625SLionel Sambuc
460*84d9c625SLionel Sambuc /* XXX: should have cur_in queue */
461*84d9c625SLionel Sambuc assert(fio->cur_in == NULL);
462*84d9c625SLionel Sambuc fio->cur_in = pufbuf;
463*84d9c625SLionel Sambuc
464*84d9c625SLionel Sambuc pufbuf->pcc = pcc;
465*84d9c625SLionel Sambuc pufbuf->fcb = NULL;
466*84d9c625SLionel Sambuc pufbuf->fcb_arg = NULL;
467*84d9c625SLionel Sambuc
468*84d9c625SLionel Sambuc pufbuf->offset = 0;
469*84d9c625SLionel Sambuc pufbuf->istat |= ISTAT_NODESTROY | ISTAT_DIRECT;
470*84d9c625SLionel Sambuc
471*84d9c625SLionel Sambuc puffs_cc_yield(pcc);
472*84d9c625SLionel Sambuc pufbuf->istat &= ~ISTAT_NODESTROY; /* XXX: not the right place */
473*84d9c625SLionel Sambuc if (pufbuf->rv) {
474*84d9c625SLionel Sambuc errno = pufbuf->rv;
475*84d9c625SLionel Sambuc return -1;
476*84d9c625SLionel Sambuc }
477*84d9c625SLionel Sambuc
478*84d9c625SLionel Sambuc return 0;
479*84d9c625SLionel Sambuc }
480*84d9c625SLionel Sambuc
481*84d9c625SLionel Sambuc int
puffs_framev_enqueue_directsend(struct puffs_cc * pcc,int fd,struct puffs_framebuf * pufbuf,int flags)482*84d9c625SLionel Sambuc puffs_framev_enqueue_directsend(struct puffs_cc *pcc, int fd,
483*84d9c625SLionel Sambuc struct puffs_framebuf *pufbuf, int flags)
484*84d9c625SLionel Sambuc {
485*84d9c625SLionel Sambuc struct puffs_usermount *pu = pcc->pcc_pu;
486*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio;
487*84d9c625SLionel Sambuc
488*84d9c625SLionel Sambuc assert((pufbuf->istat & ISTAT_INTERNAL) == 0);
489*84d9c625SLionel Sambuc
490*84d9c625SLionel Sambuc if (flags & PUFFS_FBQUEUE_URGENT)
491*84d9c625SLionel Sambuc abort(); /* EOPNOTSUPP for now */
492*84d9c625SLionel Sambuc
493*84d9c625SLionel Sambuc GETFIO(fd);
494*84d9c625SLionel Sambuc
495*84d9c625SLionel Sambuc pufbuf->pcc = pcc;
496*84d9c625SLionel Sambuc pufbuf->fcb = NULL;
497*84d9c625SLionel Sambuc pufbuf->fcb_arg = NULL;
498*84d9c625SLionel Sambuc
499*84d9c625SLionel Sambuc pufbuf->offset = 0;
500*84d9c625SLionel Sambuc pufbuf->istat |= ISTAT_NODESTROY | ISTAT_DIRECT;
501*84d9c625SLionel Sambuc
502*84d9c625SLionel Sambuc TAILQ_INSERT_TAIL(&fio->snd_qing, pufbuf, pfb_entries);
503*84d9c625SLionel Sambuc
504*84d9c625SLionel Sambuc puffs_cc_yield(pcc);
505*84d9c625SLionel Sambuc if (pufbuf->rv) {
506*84d9c625SLionel Sambuc pufbuf->istat &= ~ISTAT_NODESTROY;
507*84d9c625SLionel Sambuc errno = pufbuf->rv;
508*84d9c625SLionel Sambuc return -1;
509*84d9c625SLionel Sambuc }
510*84d9c625SLionel Sambuc
511*84d9c625SLionel Sambuc return 0;
512*84d9c625SLionel Sambuc }
513*84d9c625SLionel Sambuc
514*84d9c625SLionel Sambuc int
puffs_framev_framebuf_ccpromote(struct puffs_framebuf * pufbuf,struct puffs_cc * pcc)515*84d9c625SLionel Sambuc puffs_framev_framebuf_ccpromote(struct puffs_framebuf *pufbuf,
516*84d9c625SLionel Sambuc struct puffs_cc *pcc)
517*84d9c625SLionel Sambuc {
518*84d9c625SLionel Sambuc
519*84d9c625SLionel Sambuc if ((pufbuf->istat & ISTAT_ONQUEUE) == 0) {
520*84d9c625SLionel Sambuc errno = EBUSY;
521*84d9c625SLionel Sambuc return -1;
522*84d9c625SLionel Sambuc }
523*84d9c625SLionel Sambuc
524*84d9c625SLionel Sambuc pufbuf->pcc = pcc;
525*84d9c625SLionel Sambuc pufbuf->fcb = NULL;
526*84d9c625SLionel Sambuc pufbuf->fcb_arg = NULL;
527*84d9c625SLionel Sambuc pufbuf->istat &= ~ISTAT_NOREPLY;
528*84d9c625SLionel Sambuc
529*84d9c625SLionel Sambuc puffs_cc_yield(pcc);
530*84d9c625SLionel Sambuc
531*84d9c625SLionel Sambuc return 0;
532*84d9c625SLionel Sambuc }
533*84d9c625SLionel Sambuc
534*84d9c625SLionel Sambuc int
puffs_framev_enqueue_waitevent(struct puffs_cc * pcc,int fd,int * what)535*84d9c625SLionel Sambuc puffs_framev_enqueue_waitevent(struct puffs_cc *pcc, int fd, int *what)
536*84d9c625SLionel Sambuc {
537*84d9c625SLionel Sambuc struct puffs_usermount *pu = pcc->pcc_pu;
538*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio;
539*84d9c625SLionel Sambuc struct puffs_fbevent feb;
540*84d9c625SLionel Sambuc struct kevent kev;
541*84d9c625SLionel Sambuc int rv, svwhat;
542*84d9c625SLionel Sambuc
543*84d9c625SLionel Sambuc svwhat = *what;
544*84d9c625SLionel Sambuc
545*84d9c625SLionel Sambuc if (*what == 0) {
546*84d9c625SLionel Sambuc errno = EINVAL;
547*84d9c625SLionel Sambuc return -1;
548*84d9c625SLionel Sambuc }
549*84d9c625SLionel Sambuc
550*84d9c625SLionel Sambuc fio = getfiobyfd(pu, fd);
551*84d9c625SLionel Sambuc if (fio == NULL) {
552*84d9c625SLionel Sambuc errno = EINVAL;
553*84d9c625SLionel Sambuc return -1;
554*84d9c625SLionel Sambuc }
555*84d9c625SLionel Sambuc
556*84d9c625SLionel Sambuc feb.pcc = pcc;
557*84d9c625SLionel Sambuc feb.what = *what & (PUFFS_FBIO_READ|PUFFS_FBIO_WRITE|PUFFS_FBIO_ERROR);
558*84d9c625SLionel Sambuc
559*84d9c625SLionel Sambuc if (*what & PUFFS_FBIO_READ)
560*84d9c625SLionel Sambuc if ((fio->stat & FIO_ENABLE_R) == 0)
561*84d9c625SLionel Sambuc EV_SET(&kev, fd, EVFILT_READ, EV_ENABLE,
562*84d9c625SLionel Sambuc 0, 0, (uintptr_t)fio);
563*84d9c625SLionel Sambuc
564*84d9c625SLionel Sambuc if (kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL) == -1)
565*84d9c625SLionel Sambuc return -1;
566*84d9c625SLionel Sambuc
567*84d9c625SLionel Sambuc if (*what & PUFFS_FBIO_READ)
568*84d9c625SLionel Sambuc fio->rwait++;
569*84d9c625SLionel Sambuc if (*what & PUFFS_FBIO_WRITE)
570*84d9c625SLionel Sambuc fio->wwait++;
571*84d9c625SLionel Sambuc
572*84d9c625SLionel Sambuc LIST_INSERT_HEAD(&fio->ev_qing, &feb, pfe_entries);
573*84d9c625SLionel Sambuc puffs_cc_yield(pcc);
574*84d9c625SLionel Sambuc
575*84d9c625SLionel Sambuc assert(svwhat == *what);
576*84d9c625SLionel Sambuc
577*84d9c625SLionel Sambuc if (*what & PUFFS_FBIO_READ) {
578*84d9c625SLionel Sambuc fio->rwait--;
579*84d9c625SLionel Sambuc if (fio->rwait == 0 && (fio->stat & FIO_ENABLE_R) == 0) {
580*84d9c625SLionel Sambuc EV_SET(&kev, fd, EVFILT_READ, EV_DISABLE,
581*84d9c625SLionel Sambuc 0, 0, (uintptr_t)fio);
582*84d9c625SLionel Sambuc rv = kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL);
583*84d9c625SLionel Sambuc #if 0
584*84d9c625SLionel Sambuc if (rv != 0)
585*84d9c625SLionel Sambuc /* XXXXX oh dear */;
586*84d9c625SLionel Sambuc #endif
587*84d9c625SLionel Sambuc }
588*84d9c625SLionel Sambuc }
589*84d9c625SLionel Sambuc if (*what & PUFFS_FBIO_WRITE)
590*84d9c625SLionel Sambuc fio->wwait--;
591*84d9c625SLionel Sambuc
592*84d9c625SLionel Sambuc if (feb.rv == 0) {
593*84d9c625SLionel Sambuc *what = feb.what;
594*84d9c625SLionel Sambuc rv = 0;
595*84d9c625SLionel Sambuc } else {
596*84d9c625SLionel Sambuc *what = PUFFS_FBIO_ERROR;
597*84d9c625SLionel Sambuc errno = feb.rv;
598*84d9c625SLionel Sambuc rv = -1;
599*84d9c625SLionel Sambuc }
600*84d9c625SLionel Sambuc
601*84d9c625SLionel Sambuc return rv;
602*84d9c625SLionel Sambuc }
603*84d9c625SLionel Sambuc
604*84d9c625SLionel Sambuc void
puffs__framev_notify(struct puffs_fctrl_io * fio,int what)605*84d9c625SLionel Sambuc puffs__framev_notify(struct puffs_fctrl_io *fio, int what)
606*84d9c625SLionel Sambuc {
607*84d9c625SLionel Sambuc struct puffs_fbevent *fbevp;
608*84d9c625SLionel Sambuc
609*84d9c625SLionel Sambuc restart:
610*84d9c625SLionel Sambuc LIST_FOREACH(fbevp, &fio->ev_qing, pfe_entries) {
611*84d9c625SLionel Sambuc if (fbevp->what & what) {
612*84d9c625SLionel Sambuc fbevp->what = what;
613*84d9c625SLionel Sambuc fbevp->rv = 0;
614*84d9c625SLionel Sambuc LIST_REMOVE(fbevp, pfe_entries);
615*84d9c625SLionel Sambuc puffs_cc_continue(fbevp->pcc);
616*84d9c625SLionel Sambuc goto restart;
617*84d9c625SLionel Sambuc }
618*84d9c625SLionel Sambuc }
619*84d9c625SLionel Sambuc }
620*84d9c625SLionel Sambuc
621*84d9c625SLionel Sambuc static struct puffs_framebuf *
findbuf(struct puffs_usermount * pu,struct puffs_framectrl * fctrl,struct puffs_fctrl_io * fio,struct puffs_framebuf * findme)622*84d9c625SLionel Sambuc findbuf(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
623*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio, struct puffs_framebuf *findme)
624*84d9c625SLionel Sambuc {
625*84d9c625SLionel Sambuc struct puffs_framebuf *cand;
626*84d9c625SLionel Sambuc int notresp = 0;
627*84d9c625SLionel Sambuc
628*84d9c625SLionel Sambuc TAILQ_FOREACH(cand, &fio->res_qing, pfb_entries)
629*84d9c625SLionel Sambuc if (fctrl->cmpfb(pu, findme, cand, ¬resp) == 0 || notresp)
630*84d9c625SLionel Sambuc break;
631*84d9c625SLionel Sambuc
632*84d9c625SLionel Sambuc assert(!(notresp && cand == NULL));
633*84d9c625SLionel Sambuc if (notresp || cand == NULL)
634*84d9c625SLionel Sambuc return NULL;
635*84d9c625SLionel Sambuc
636*84d9c625SLionel Sambuc TAILQ_REMOVE(&fio->res_qing, cand, pfb_entries);
637*84d9c625SLionel Sambuc return cand;
638*84d9c625SLionel Sambuc }
639*84d9c625SLionel Sambuc
640*84d9c625SLionel Sambuc void
puffs__framebuf_moveinfo(struct puffs_framebuf * from,struct puffs_framebuf * to)641*84d9c625SLionel Sambuc puffs__framebuf_moveinfo(struct puffs_framebuf *from, struct puffs_framebuf *to)
642*84d9c625SLionel Sambuc {
643*84d9c625SLionel Sambuc
644*84d9c625SLionel Sambuc assert(from->istat & ISTAT_INTERNAL);
645*84d9c625SLionel Sambuc
646*84d9c625SLionel Sambuc /* migrate buffer */
647*84d9c625SLionel Sambuc free(to->buf);
648*84d9c625SLionel Sambuc to->buf = from->buf;
649*84d9c625SLionel Sambuc
650*84d9c625SLionel Sambuc /* migrate buffer info */
651*84d9c625SLionel Sambuc to->len = from->len;
652*84d9c625SLionel Sambuc to->offset = from->offset;
653*84d9c625SLionel Sambuc to->maxoff = from->maxoff;
654*84d9c625SLionel Sambuc
655*84d9c625SLionel Sambuc from->buf = NULL;
656*84d9c625SLionel Sambuc from->len = 0;
657*84d9c625SLionel Sambuc }
658*84d9c625SLionel Sambuc
659*84d9c625SLionel Sambuc void
puffs__framev_input(struct puffs_usermount * pu,struct puffs_framectrl * fctrl,struct puffs_fctrl_io * fio)660*84d9c625SLionel Sambuc puffs__framev_input(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
661*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio)
662*84d9c625SLionel Sambuc {
663*84d9c625SLionel Sambuc struct puffs_framebuf *pufbuf, *appbuf;
664*84d9c625SLionel Sambuc int rv, complete;
665*84d9c625SLionel Sambuc
666*84d9c625SLionel Sambuc while ((fio->stat & FIO_DEAD) == 0 && (fio->stat & FIO_ENABLE_R)) {
667*84d9c625SLionel Sambuc if ((pufbuf = fio->cur_in) == NULL) {
668*84d9c625SLionel Sambuc pufbuf = puffs_framebuf_make();
669*84d9c625SLionel Sambuc if (pufbuf == NULL)
670*84d9c625SLionel Sambuc return;
671*84d9c625SLionel Sambuc pufbuf->istat |= ISTAT_INTERNAL;
672*84d9c625SLionel Sambuc fio->cur_in = pufbuf;
673*84d9c625SLionel Sambuc }
674*84d9c625SLionel Sambuc
675*84d9c625SLionel Sambuc complete = 0;
676*84d9c625SLionel Sambuc rv = fctrl->rfb(pu, pufbuf, fio->io_fd, &complete);
677*84d9c625SLionel Sambuc
678*84d9c625SLionel Sambuc /* error */
679*84d9c625SLionel Sambuc if (rv) {
680*84d9c625SLionel Sambuc puffs__framev_readclose(pu, fio, rv);
681*84d9c625SLionel Sambuc fio->cur_in = NULL;
682*84d9c625SLionel Sambuc return;
683*84d9c625SLionel Sambuc }
684*84d9c625SLionel Sambuc
685*84d9c625SLionel Sambuc /* partial read, come back to fight another day */
686*84d9c625SLionel Sambuc if (complete == 0)
687*84d9c625SLionel Sambuc break;
688*84d9c625SLionel Sambuc
689*84d9c625SLionel Sambuc /* else: full read, process */
690*84d9c625SLionel Sambuc fio->cur_in = NULL;
691*84d9c625SLionel Sambuc if ((pufbuf->istat & ISTAT_DIRECT) == 0) {
692*84d9c625SLionel Sambuc appbuf = findbuf(pu, fctrl, fio, pufbuf);
693*84d9c625SLionel Sambuc
694*84d9c625SLionel Sambuc /*
695*84d9c625SLionel Sambuc * No request for this frame? If fs implements
696*84d9c625SLionel Sambuc * gotfb, give frame to that. Otherwise drop it.
697*84d9c625SLionel Sambuc */
698*84d9c625SLionel Sambuc if (appbuf == NULL) {
699*84d9c625SLionel Sambuc if (fctrl->gotfb) {
700*84d9c625SLionel Sambuc pufbuf->istat &= ~ISTAT_INTERNAL;
701*84d9c625SLionel Sambuc fctrl->gotfb(pu, pufbuf);
702*84d9c625SLionel Sambuc } else {
703*84d9c625SLionel Sambuc puffs_framebuf_destroy(pufbuf);
704*84d9c625SLionel Sambuc }
705*84d9c625SLionel Sambuc continue;
706*84d9c625SLionel Sambuc }
707*84d9c625SLionel Sambuc
708*84d9c625SLionel Sambuc puffs__framebuf_moveinfo(pufbuf, appbuf);
709*84d9c625SLionel Sambuc puffs_framebuf_destroy(pufbuf);
710*84d9c625SLionel Sambuc } else {
711*84d9c625SLionel Sambuc appbuf = pufbuf;
712*84d9c625SLionel Sambuc }
713*84d9c625SLionel Sambuc appbuf->istat &= ~ISTAT_NODESTROY;
714*84d9c625SLionel Sambuc
715*84d9c625SLionel Sambuc if (appbuf->pcc) {
716*84d9c625SLionel Sambuc puffs__cc_cont(appbuf->pcc);
717*84d9c625SLionel Sambuc } else if (appbuf->fcb) {
718*84d9c625SLionel Sambuc appbuf->fcb(pu, appbuf, appbuf->fcb_arg, 0);
719*84d9c625SLionel Sambuc } else {
720*84d9c625SLionel Sambuc puffs_framebuf_destroy(appbuf);
721*84d9c625SLionel Sambuc }
722*84d9c625SLionel Sambuc
723*84d9c625SLionel Sambuc /* hopeless romantics, here we go again */
724*84d9c625SLionel Sambuc }
725*84d9c625SLionel Sambuc }
726*84d9c625SLionel Sambuc
727*84d9c625SLionel Sambuc int
puffs__framev_output(struct puffs_usermount * pu,struct puffs_framectrl * fctrl,struct puffs_fctrl_io * fio)728*84d9c625SLionel Sambuc puffs__framev_output(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
729*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio)
730*84d9c625SLionel Sambuc {
731*84d9c625SLionel Sambuc struct puffs_framebuf *pufbuf;
732*84d9c625SLionel Sambuc int rv, complete, done;
733*84d9c625SLionel Sambuc
734*84d9c625SLionel Sambuc if (fio->stat & FIO_DEAD)
735*84d9c625SLionel Sambuc return 0;
736*84d9c625SLionel Sambuc
737*84d9c625SLionel Sambuc for (pufbuf = TAILQ_FIRST(&fio->snd_qing), done = 0;
738*84d9c625SLionel Sambuc pufbuf && (fio->stat & FIO_DEAD) == 0 && fio->stat & FIO_ENABLE_W;
739*84d9c625SLionel Sambuc pufbuf = TAILQ_FIRST(&fio->snd_qing)) {
740*84d9c625SLionel Sambuc complete = 0;
741*84d9c625SLionel Sambuc rv = fctrl->wfb(pu, pufbuf, fio->io_fd, &complete);
742*84d9c625SLionel Sambuc
743*84d9c625SLionel Sambuc if (rv) {
744*84d9c625SLionel Sambuc puffs__framev_writeclose(pu, fio, rv);
745*84d9c625SLionel Sambuc done = 1;
746*84d9c625SLionel Sambuc break;
747*84d9c625SLionel Sambuc }
748*84d9c625SLionel Sambuc
749*84d9c625SLionel Sambuc /* partial write */
750*84d9c625SLionel Sambuc if (complete == 0)
751*84d9c625SLionel Sambuc return done;
752*84d9c625SLionel Sambuc
753*84d9c625SLionel Sambuc /* else, complete write */
754*84d9c625SLionel Sambuc TAILQ_REMOVE(&fio->snd_qing, pufbuf, pfb_entries);
755*84d9c625SLionel Sambuc
756*84d9c625SLionel Sambuc /* can't wait for result if we can't read */
757*84d9c625SLionel Sambuc if (fio->stat & FIO_RDGONE) {
758*84d9c625SLionel Sambuc errnotify(pu, pufbuf, ENXIO);
759*84d9c625SLionel Sambuc done = 1;
760*84d9c625SLionel Sambuc } else if ((pufbuf->istat & ISTAT_DIRECT)) {
761*84d9c625SLionel Sambuc pufbuf->istat &= ~ISTAT_NODESTROY;
762*84d9c625SLionel Sambuc done = 1;
763*84d9c625SLionel Sambuc puffs__cc_cont(pufbuf->pcc);
764*84d9c625SLionel Sambuc } else if ((pufbuf->istat & ISTAT_NOREPLY) == 0) {
765*84d9c625SLionel Sambuc TAILQ_INSERT_TAIL(&fio->res_qing, pufbuf,
766*84d9c625SLionel Sambuc pfb_entries);
767*84d9c625SLionel Sambuc } else {
768*84d9c625SLionel Sambuc pufbuf->istat &= ~ISTAT_NODESTROY;
769*84d9c625SLionel Sambuc puffs_framebuf_destroy(pufbuf);
770*84d9c625SLionel Sambuc }
771*84d9c625SLionel Sambuc
772*84d9c625SLionel Sambuc /* omstart! */
773*84d9c625SLionel Sambuc }
774*84d9c625SLionel Sambuc
775*84d9c625SLionel Sambuc return done;
776*84d9c625SLionel Sambuc }
777*84d9c625SLionel Sambuc
778*84d9c625SLionel Sambuc int
puffs__framev_addfd_ctrl(struct puffs_usermount * pu,int fd,int what,struct puffs_framectrl * pfctrl)779*84d9c625SLionel Sambuc puffs__framev_addfd_ctrl(struct puffs_usermount *pu, int fd, int what,
780*84d9c625SLionel Sambuc struct puffs_framectrl *pfctrl)
781*84d9c625SLionel Sambuc {
782*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio;
783*84d9c625SLionel Sambuc struct kevent *newevs;
784*84d9c625SLionel Sambuc struct kevent kev[2];
785*84d9c625SLionel Sambuc size_t nevs;
786*84d9c625SLionel Sambuc int rv, readenable;
787*84d9c625SLionel Sambuc
788*84d9c625SLionel Sambuc nevs = pu->pu_nevs+2;
789*84d9c625SLionel Sambuc newevs = realloc(pu->pu_evs, nevs*sizeof(struct kevent));
790*84d9c625SLionel Sambuc if (newevs == NULL)
791*84d9c625SLionel Sambuc return -1;
792*84d9c625SLionel Sambuc pu->pu_evs = newevs;
793*84d9c625SLionel Sambuc
794*84d9c625SLionel Sambuc fio = malloc(sizeof(struct puffs_fctrl_io));
795*84d9c625SLionel Sambuc if (fio == NULL)
796*84d9c625SLionel Sambuc return -1;
797*84d9c625SLionel Sambuc memset(fio, 0, sizeof(struct puffs_fctrl_io));
798*84d9c625SLionel Sambuc fio->io_fd = fd;
799*84d9c625SLionel Sambuc fio->cur_in = NULL;
800*84d9c625SLionel Sambuc fio->fctrl = pfctrl;
801*84d9c625SLionel Sambuc TAILQ_INIT(&fio->snd_qing);
802*84d9c625SLionel Sambuc TAILQ_INIT(&fio->res_qing);
803*84d9c625SLionel Sambuc LIST_INIT(&fio->ev_qing);
804*84d9c625SLionel Sambuc
805*84d9c625SLionel Sambuc readenable = 0;
806*84d9c625SLionel Sambuc if ((what & PUFFS_FBIO_READ) == 0)
807*84d9c625SLionel Sambuc readenable = EV_DISABLE;
808*84d9c625SLionel Sambuc
809*84d9c625SLionel Sambuc if (pu->pu_state & PU_INLOOP) {
810*84d9c625SLionel Sambuc EV_SET(&kev[0], fd, EVFILT_READ,
811*84d9c625SLionel Sambuc EV_ADD|readenable, 0, 0, (intptr_t)fio);
812*84d9c625SLionel Sambuc EV_SET(&kev[1], fd, EVFILT_WRITE,
813*84d9c625SLionel Sambuc EV_ADD|EV_DISABLE, 0, 0, (intptr_t)fio);
814*84d9c625SLionel Sambuc rv = kevent(pu->pu_kq, kev, 2, NULL, 0, NULL);
815*84d9c625SLionel Sambuc if (rv == -1) {
816*84d9c625SLionel Sambuc free(fio);
817*84d9c625SLionel Sambuc return -1;
818*84d9c625SLionel Sambuc }
819*84d9c625SLionel Sambuc }
820*84d9c625SLionel Sambuc if (what & PUFFS_FBIO_READ)
821*84d9c625SLionel Sambuc fio->stat |= FIO_ENABLE_R;
822*84d9c625SLionel Sambuc if (what & PUFFS_FBIO_WRITE)
823*84d9c625SLionel Sambuc fio->stat |= FIO_ENABLE_W;
824*84d9c625SLionel Sambuc
825*84d9c625SLionel Sambuc LIST_INSERT_HEAD(&pu->pu_ios, fio, fio_entries);
826*84d9c625SLionel Sambuc pu->pu_nevs = nevs;
827*84d9c625SLionel Sambuc
828*84d9c625SLionel Sambuc return 0;
829*84d9c625SLionel Sambuc }
830*84d9c625SLionel Sambuc
831*84d9c625SLionel Sambuc int
puffs_framev_addfd(struct puffs_usermount * pu,int fd,int what)832*84d9c625SLionel Sambuc puffs_framev_addfd(struct puffs_usermount *pu, int fd, int what)
833*84d9c625SLionel Sambuc {
834*84d9c625SLionel Sambuc
835*84d9c625SLionel Sambuc return puffs__framev_addfd_ctrl(pu, fd, what,
836*84d9c625SLionel Sambuc &pu->pu_framectrl[PU_FRAMECTRL_USER]);
837*84d9c625SLionel Sambuc }
838*84d9c625SLionel Sambuc
839*84d9c625SLionel Sambuc /*
840*84d9c625SLionel Sambuc * XXX: the following en/disable should be coalesced and executed
841*84d9c625SLionel Sambuc * only during the actual kevent call. So feel free to fix if
842*84d9c625SLionel Sambuc * threatened by mindblowing boredom.
843*84d9c625SLionel Sambuc */
844*84d9c625SLionel Sambuc
845*84d9c625SLionel Sambuc int
puffs_framev_enablefd(struct puffs_usermount * pu,int fd,int what)846*84d9c625SLionel Sambuc puffs_framev_enablefd(struct puffs_usermount *pu, int fd, int what)
847*84d9c625SLionel Sambuc {
848*84d9c625SLionel Sambuc struct kevent kev;
849*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio;
850*84d9c625SLionel Sambuc int rv = 0;
851*84d9c625SLionel Sambuc
852*84d9c625SLionel Sambuc assert((what & (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) != 0);
853*84d9c625SLionel Sambuc
854*84d9c625SLionel Sambuc fio = getfiobyfd(pu, fd);
855*84d9c625SLionel Sambuc if (fio == NULL) {
856*84d9c625SLionel Sambuc errno = ENXIO;
857*84d9c625SLionel Sambuc return -1;
858*84d9c625SLionel Sambuc }
859*84d9c625SLionel Sambuc
860*84d9c625SLionel Sambuc /* write is enabled in the event loop if there is output */
861*84d9c625SLionel Sambuc if (what & PUFFS_FBIO_READ && fio->rwait == 0) {
862*84d9c625SLionel Sambuc EV_SET(&kev, fd, EVFILT_READ, EV_ENABLE, 0, 0, (uintptr_t)fio);
863*84d9c625SLionel Sambuc rv = kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL);
864*84d9c625SLionel Sambuc }
865*84d9c625SLionel Sambuc
866*84d9c625SLionel Sambuc if (rv == 0) {
867*84d9c625SLionel Sambuc if (what & PUFFS_FBIO_READ)
868*84d9c625SLionel Sambuc fio->stat |= FIO_ENABLE_R;
869*84d9c625SLionel Sambuc if (what & PUFFS_FBIO_WRITE)
870*84d9c625SLionel Sambuc fio->stat |= FIO_ENABLE_W;
871*84d9c625SLionel Sambuc }
872*84d9c625SLionel Sambuc
873*84d9c625SLionel Sambuc return rv;
874*84d9c625SLionel Sambuc }
875*84d9c625SLionel Sambuc
876*84d9c625SLionel Sambuc int
puffs_framev_disablefd(struct puffs_usermount * pu,int fd,int what)877*84d9c625SLionel Sambuc puffs_framev_disablefd(struct puffs_usermount *pu, int fd, int what)
878*84d9c625SLionel Sambuc {
879*84d9c625SLionel Sambuc struct kevent kev[2];
880*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio;
881*84d9c625SLionel Sambuc size_t i;
882*84d9c625SLionel Sambuc int rv;
883*84d9c625SLionel Sambuc
884*84d9c625SLionel Sambuc assert((what & (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) != 0);
885*84d9c625SLionel Sambuc
886*84d9c625SLionel Sambuc fio = getfiobyfd(pu, fd);
887*84d9c625SLionel Sambuc if (fio == NULL) {
888*84d9c625SLionel Sambuc errno = ENXIO;
889*84d9c625SLionel Sambuc return -1;
890*84d9c625SLionel Sambuc }
891*84d9c625SLionel Sambuc
892*84d9c625SLionel Sambuc i = 0;
893*84d9c625SLionel Sambuc if (what & PUFFS_FBIO_READ && fio->rwait == 0) {
894*84d9c625SLionel Sambuc EV_SET(&kev[0], fd,
895*84d9c625SLionel Sambuc EVFILT_READ, EV_DISABLE, 0, 0, (uintptr_t)fio);
896*84d9c625SLionel Sambuc i++;
897*84d9c625SLionel Sambuc }
898*84d9c625SLionel Sambuc if (what & PUFFS_FBIO_WRITE && fio->stat & FIO_WR && fio->wwait == 0) {
899*84d9c625SLionel Sambuc EV_SET(&kev[1], fd,
900*84d9c625SLionel Sambuc EVFILT_WRITE, EV_DISABLE, 0, 0, (uintptr_t)fio);
901*84d9c625SLionel Sambuc i++;
902*84d9c625SLionel Sambuc }
903*84d9c625SLionel Sambuc if (i)
904*84d9c625SLionel Sambuc rv = kevent(pu->pu_kq, kev, i, NULL, 0, NULL);
905*84d9c625SLionel Sambuc else
906*84d9c625SLionel Sambuc rv = 0;
907*84d9c625SLionel Sambuc
908*84d9c625SLionel Sambuc if (rv == 0) {
909*84d9c625SLionel Sambuc if (what & PUFFS_FBIO_READ)
910*84d9c625SLionel Sambuc fio->stat &= ~FIO_ENABLE_R;
911*84d9c625SLionel Sambuc if (what & PUFFS_FBIO_WRITE)
912*84d9c625SLionel Sambuc fio->stat &= ~FIO_ENABLE_W;
913*84d9c625SLionel Sambuc }
914*84d9c625SLionel Sambuc
915*84d9c625SLionel Sambuc return rv;
916*84d9c625SLionel Sambuc }
917*84d9c625SLionel Sambuc
918*84d9c625SLionel Sambuc void
puffs__framev_readclose(struct puffs_usermount * pu,struct puffs_fctrl_io * fio,int error)919*84d9c625SLionel Sambuc puffs__framev_readclose(struct puffs_usermount *pu,
920*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio, int error)
921*84d9c625SLionel Sambuc {
922*84d9c625SLionel Sambuc struct puffs_framebuf *pufbuf;
923*84d9c625SLionel Sambuc struct kevent kev;
924*84d9c625SLionel Sambuc int notflag;
925*84d9c625SLionel Sambuc
926*84d9c625SLionel Sambuc if (fio->stat & FIO_RDGONE || fio->stat & FIO_DEAD)
927*84d9c625SLionel Sambuc return;
928*84d9c625SLionel Sambuc fio->stat |= FIO_RDGONE;
929*84d9c625SLionel Sambuc
930*84d9c625SLionel Sambuc if (fio->cur_in) {
931*84d9c625SLionel Sambuc if ((fio->cur_in->istat & ISTAT_DIRECT) == 0) {
932*84d9c625SLionel Sambuc puffs_framebuf_destroy(fio->cur_in);
933*84d9c625SLionel Sambuc fio->cur_in = NULL;
934*84d9c625SLionel Sambuc } else {
935*84d9c625SLionel Sambuc errnotify(pu, fio->cur_in, error);
936*84d9c625SLionel Sambuc }
937*84d9c625SLionel Sambuc }
938*84d9c625SLionel Sambuc
939*84d9c625SLionel Sambuc while ((pufbuf = TAILQ_FIRST(&fio->res_qing)) != NULL) {
940*84d9c625SLionel Sambuc TAILQ_REMOVE(&fio->res_qing, pufbuf, pfb_entries);
941*84d9c625SLionel Sambuc errnotify(pu, pufbuf, error);
942*84d9c625SLionel Sambuc }
943*84d9c625SLionel Sambuc
944*84d9c625SLionel Sambuc EV_SET(&kev, fio->io_fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
945*84d9c625SLionel Sambuc (void) kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL);
946*84d9c625SLionel Sambuc
947*84d9c625SLionel Sambuc notflag = PUFFS_FBIO_READ;
948*84d9c625SLionel Sambuc if (fio->stat & FIO_WRGONE)
949*84d9c625SLionel Sambuc notflag |= PUFFS_FBIO_WRITE;
950*84d9c625SLionel Sambuc
951*84d9c625SLionel Sambuc if (fio->fctrl->fdnotfn)
952*84d9c625SLionel Sambuc fio->fctrl->fdnotfn(pu, fio->io_fd, notflag);
953*84d9c625SLionel Sambuc }
954*84d9c625SLionel Sambuc
955*84d9c625SLionel Sambuc void
puffs__framev_writeclose(struct puffs_usermount * pu,struct puffs_fctrl_io * fio,int error)956*84d9c625SLionel Sambuc puffs__framev_writeclose(struct puffs_usermount *pu,
957*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio, int error)
958*84d9c625SLionel Sambuc {
959*84d9c625SLionel Sambuc struct puffs_framebuf *pufbuf;
960*84d9c625SLionel Sambuc struct kevent kev;
961*84d9c625SLionel Sambuc int notflag;
962*84d9c625SLionel Sambuc
963*84d9c625SLionel Sambuc if (fio->stat & FIO_WRGONE || fio->stat & FIO_DEAD)
964*84d9c625SLionel Sambuc return;
965*84d9c625SLionel Sambuc fio->stat |= FIO_WRGONE;
966*84d9c625SLionel Sambuc
967*84d9c625SLionel Sambuc while ((pufbuf = TAILQ_FIRST(&fio->snd_qing)) != NULL) {
968*84d9c625SLionel Sambuc TAILQ_REMOVE(&fio->snd_qing, pufbuf, pfb_entries);
969*84d9c625SLionel Sambuc errnotify(pu, pufbuf, error);
970*84d9c625SLionel Sambuc }
971*84d9c625SLionel Sambuc
972*84d9c625SLionel Sambuc EV_SET(&kev, fio->io_fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
973*84d9c625SLionel Sambuc (void) kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL);
974*84d9c625SLionel Sambuc
975*84d9c625SLionel Sambuc notflag = PUFFS_FBIO_WRITE;
976*84d9c625SLionel Sambuc if (fio->stat & FIO_RDGONE)
977*84d9c625SLionel Sambuc notflag |= PUFFS_FBIO_READ;
978*84d9c625SLionel Sambuc
979*84d9c625SLionel Sambuc if (fio->fctrl->fdnotfn)
980*84d9c625SLionel Sambuc fio->fctrl->fdnotfn(pu, fio->io_fd, notflag);
981*84d9c625SLionel Sambuc }
982*84d9c625SLionel Sambuc
983*84d9c625SLionel Sambuc static int
removefio(struct puffs_usermount * pu,struct puffs_fctrl_io * fio,int error)984*84d9c625SLionel Sambuc removefio(struct puffs_usermount *pu, struct puffs_fctrl_io *fio, int error)
985*84d9c625SLionel Sambuc {
986*84d9c625SLionel Sambuc struct puffs_fbevent *fbevp;
987*84d9c625SLionel Sambuc
988*84d9c625SLionel Sambuc LIST_REMOVE(fio, fio_entries);
989*84d9c625SLionel Sambuc if (pu->pu_state & PU_INLOOP) {
990*84d9c625SLionel Sambuc puffs__framev_readclose(pu, fio, error);
991*84d9c625SLionel Sambuc puffs__framev_writeclose(pu, fio, error);
992*84d9c625SLionel Sambuc }
993*84d9c625SLionel Sambuc
994*84d9c625SLionel Sambuc while ((fbevp = LIST_FIRST(&fio->ev_qing)) != NULL) {
995*84d9c625SLionel Sambuc fbevp->rv = error;
996*84d9c625SLionel Sambuc LIST_REMOVE(fbevp, pfe_entries);
997*84d9c625SLionel Sambuc puffs__goto(fbevp->pcc);
998*84d9c625SLionel Sambuc }
999*84d9c625SLionel Sambuc
1000*84d9c625SLionel Sambuc /* don't bother with realloc */
1001*84d9c625SLionel Sambuc pu->pu_nevs -= 2;
1002*84d9c625SLionel Sambuc
1003*84d9c625SLionel Sambuc /* don't free us yet, might have some references in event arrays */
1004*84d9c625SLionel Sambuc fio->stat |= FIO_DEAD;
1005*84d9c625SLionel Sambuc LIST_INSERT_HEAD(&pu->pu_ios_rmlist, fio, fio_entries);
1006*84d9c625SLionel Sambuc
1007*84d9c625SLionel Sambuc return 0;
1008*84d9c625SLionel Sambuc
1009*84d9c625SLionel Sambuc }
1010*84d9c625SLionel Sambuc
1011*84d9c625SLionel Sambuc int
puffs_framev_removefd(struct puffs_usermount * pu,int fd,int error)1012*84d9c625SLionel Sambuc puffs_framev_removefd(struct puffs_usermount *pu, int fd, int error)
1013*84d9c625SLionel Sambuc {
1014*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio;
1015*84d9c625SLionel Sambuc
1016*84d9c625SLionel Sambuc fio = getfiobyfd(pu, fd);
1017*84d9c625SLionel Sambuc if (fio == NULL) {
1018*84d9c625SLionel Sambuc errno = ENXIO;
1019*84d9c625SLionel Sambuc return -1;
1020*84d9c625SLionel Sambuc }
1021*84d9c625SLionel Sambuc
1022*84d9c625SLionel Sambuc return removefio(pu, fio, error ? error : ECONNRESET);
1023*84d9c625SLionel Sambuc }
1024*84d9c625SLionel Sambuc
1025*84d9c625SLionel Sambuc void
puffs_framev_removeonclose(struct puffs_usermount * pu,int fd,int what)1026*84d9c625SLionel Sambuc puffs_framev_removeonclose(struct puffs_usermount *pu, int fd, int what)
1027*84d9c625SLionel Sambuc {
1028*84d9c625SLionel Sambuc
1029*84d9c625SLionel Sambuc if (what == (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE))
1030*84d9c625SLionel Sambuc (void) puffs_framev_removefd(pu, fd, ECONNRESET);
1031*84d9c625SLionel Sambuc }
1032*84d9c625SLionel Sambuc
1033*84d9c625SLionel Sambuc void
puffs_framev_unmountonclose(struct puffs_usermount * pu,int fd,int what)1034*84d9c625SLionel Sambuc puffs_framev_unmountonclose(struct puffs_usermount *pu, int fd, int what)
1035*84d9c625SLionel Sambuc {
1036*84d9c625SLionel Sambuc
1037*84d9c625SLionel Sambuc /* XXX & X: unmount is non-sensible */
1038*84d9c625SLionel Sambuc puffs_framev_removeonclose(pu, fd, what);
1039*84d9c625SLionel Sambuc if (what == (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE))
1040*84d9c625SLionel Sambuc PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED);
1041*84d9c625SLionel Sambuc }
1042*84d9c625SLionel Sambuc
1043*84d9c625SLionel Sambuc void
puffs_framev_init(struct puffs_usermount * pu,puffs_framev_readframe_fn rfb,puffs_framev_writeframe_fn wfb,puffs_framev_cmpframe_fn cmpfb,puffs_framev_gotframe_fn gotfb,puffs_framev_fdnotify_fn fdnotfn)1044*84d9c625SLionel Sambuc puffs_framev_init(struct puffs_usermount *pu,
1045*84d9c625SLionel Sambuc puffs_framev_readframe_fn rfb, puffs_framev_writeframe_fn wfb,
1046*84d9c625SLionel Sambuc puffs_framev_cmpframe_fn cmpfb, puffs_framev_gotframe_fn gotfb,
1047*84d9c625SLionel Sambuc puffs_framev_fdnotify_fn fdnotfn)
1048*84d9c625SLionel Sambuc {
1049*84d9c625SLionel Sambuc struct puffs_framectrl *pfctrl;
1050*84d9c625SLionel Sambuc
1051*84d9c625SLionel Sambuc pfctrl = &pu->pu_framectrl[PU_FRAMECTRL_USER];
1052*84d9c625SLionel Sambuc pfctrl->rfb = rfb;
1053*84d9c625SLionel Sambuc pfctrl->wfb = wfb;
1054*84d9c625SLionel Sambuc pfctrl->cmpfb = cmpfb;
1055*84d9c625SLionel Sambuc pfctrl->gotfb = gotfb;
1056*84d9c625SLionel Sambuc pfctrl->fdnotfn = fdnotfn;
1057*84d9c625SLionel Sambuc }
1058*84d9c625SLionel Sambuc
1059*84d9c625SLionel Sambuc void
puffs__framev_exit(struct puffs_usermount * pu)1060*84d9c625SLionel Sambuc puffs__framev_exit(struct puffs_usermount *pu)
1061*84d9c625SLionel Sambuc {
1062*84d9c625SLionel Sambuc struct puffs_fctrl_io *fio;
1063*84d9c625SLionel Sambuc
1064*84d9c625SLionel Sambuc while ((fio = LIST_FIRST(&pu->pu_ios)) != NULL)
1065*84d9c625SLionel Sambuc removefio(pu, fio, ENXIO);
1066*84d9c625SLionel Sambuc free(pu->pu_evs);
1067*84d9c625SLionel Sambuc
1068*84d9c625SLionel Sambuc /* closing pu->pu_kq takes care of puffsfd */
1069*84d9c625SLionel Sambuc }
1070