xref: /minix3/lib/libpuffs/framebuf.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
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, &notresp) == 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