1 /* $NetBSD: framebuf.c,v 1.32 2012/06/25 22:32:47 abs Exp $ */
4 * Copyright (c) 2007 Antti Kantee. All Rights Reserved.
6 * Development of this software was supported by the
7 * Finnish Cultural Foundation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * The event portion of this code is a twisty maze of pointers,
33 * flags, yields and continues. Sincere aplogies.
36 #include <sys/cdefs.h>
38 __RCSID("$NetBSD: framebuf.c,v 1.32 2012/06/25 22:32:47 abs Exp $");
41 #include <sys/types.h>
42 #include <sys/queue.h>
52 #include "puffs_priv.h"
54 struct puffs_framebuf
{
55 struct puffs_cc
*pcc
; /* pcc to continue with */
57 puffs_framev_cb fcb
; /* non-blocking callback */
58 void *fcb_arg
; /* argument for previous */
60 uint8_t *buf
; /* buffer base */
61 size_t len
; /* total length */
63 size_t offset
; /* cursor, telloff() */
64 size_t maxoff
; /* maximum offset for data, tellsize() */
66 volatile int rv
; /* errno value */
70 TAILQ_ENTRY(puffs_framebuf
) pfb_entries
;
72 #define ISTAT_NODESTROY 0x01 /* indestructible by framebuf_destroy() */
73 #define ISTAT_INTERNAL 0x02 /* never leaves library */
74 #define ISTAT_NOREPLY 0x04 /* nuke after sending */
75 #define ISTAT_DIRECT 0x08 /* receive directly, no moveinfo */
77 #define ISTAT_ONQUEUE ISTAT_NODESTROY /* alias */
79 #define PUFBUF_INCRALLOC 4096
80 #define PUFBUF_REMAIN(p) (p->len - p->offset)
83 struct puffs_fbevent
{
88 LIST_ENTRY(puffs_fbevent
) pfe_entries
;
91 static struct puffs_fctrl_io
*
92 getfiobyfd(struct puffs_usermount
*pu
, int fd
)
94 struct puffs_fctrl_io
*fio
;
96 LIST_FOREACH(fio
, &pu
->pu_ios
, fio_entries
)
102 struct puffs_framebuf
*
103 puffs_framebuf_make(void)
105 struct puffs_framebuf
*pufbuf
;
107 pufbuf
= malloc(sizeof(struct puffs_framebuf
));
110 memset(pufbuf
, 0, sizeof(struct puffs_framebuf
));
112 pufbuf
->buf
= malloc(PUFBUF_INCRALLOC
);
113 if (pufbuf
->buf
== NULL
) {
117 pufbuf
->len
= PUFBUF_INCRALLOC
;
119 puffs_framebuf_recycle(pufbuf
);
124 puffs_framebuf_destroy(struct puffs_framebuf
*pufbuf
)
127 assert((pufbuf
->istat
& ISTAT_NODESTROY
) == 0);
134 puffs_framebuf_recycle(struct puffs_framebuf
*pufbuf
)
137 assert((pufbuf
->istat
& ISTAT_NODESTROY
) == 0);
145 reservespace(struct puffs_framebuf
*pufbuf
, size_t off
, size_t wantsize
)
150 if (off
<= pufbuf
->len
&& pufbuf
->len
- off
>= wantsize
)
153 for (incr
= PUFBUF_INCRALLOC
;
154 pufbuf
->len
+ incr
< off
+ wantsize
;
155 incr
+= PUFBUF_INCRALLOC
)
158 nd
= realloc(pufbuf
->buf
, pufbuf
->len
+ incr
);
169 puffs_framebuf_dup(struct puffs_framebuf
*pb
, struct puffs_framebuf
**pbp
)
171 struct puffs_framebuf
*newpb
;
173 newpb
= puffs_framebuf_make();
178 memcpy(newpb
, pb
, sizeof(struct puffs_framebuf
));
182 if (reservespace(newpb
, 0, pb
->maxoff
) == -1) {
183 puffs_framebuf_destroy(newpb
);
187 memcpy(newpb
->buf
, pb
->buf
, pb
->maxoff
);
195 puffs_framebuf_reserve_space(struct puffs_framebuf
*pufbuf
, size_t wantsize
)
198 return reservespace(pufbuf
, pufbuf
->offset
, wantsize
);
202 puffs_framebuf_putdata(struct puffs_framebuf
*pufbuf
,
203 const void *data
, size_t dlen
)
206 if (PUFBUF_REMAIN(pufbuf
) < dlen
)
207 if (puffs_framebuf_reserve_space(pufbuf
, dlen
) == -1)
210 memcpy(pufbuf
->buf
+ pufbuf
->offset
, data
, dlen
);
211 pufbuf
->offset
+= dlen
;
213 if (pufbuf
->offset
> pufbuf
->maxoff
)
214 pufbuf
->maxoff
= pufbuf
->offset
;
220 puffs_framebuf_putdata_atoff(struct puffs_framebuf
*pufbuf
, size_t offset
,
221 const void *data
, size_t dlen
)
224 if (reservespace(pufbuf
, offset
, dlen
) == -1)
227 memcpy(pufbuf
->buf
+ offset
, data
, dlen
);
229 if (offset
+ dlen
> pufbuf
->maxoff
)
230 pufbuf
->maxoff
= offset
+ dlen
;
236 puffs_framebuf_getdata(struct puffs_framebuf
*pufbuf
, void *data
, size_t dlen
)
239 if (pufbuf
->maxoff
< pufbuf
->offset
+ dlen
) {
244 memcpy(data
, pufbuf
->buf
+ pufbuf
->offset
, dlen
);
245 pufbuf
->offset
+= dlen
;
251 puffs_framebuf_getdata_atoff(struct puffs_framebuf
*pufbuf
, size_t offset
,
252 void *data
, size_t dlen
)
255 if (pufbuf
->maxoff
< offset
+ dlen
) {
260 memcpy(data
, pufbuf
->buf
+ offset
, dlen
);
265 puffs_framebuf_telloff(struct puffs_framebuf
*pufbuf
)
268 return pufbuf
->offset
;
272 puffs_framebuf_tellsize(struct puffs_framebuf
*pufbuf
)
275 return pufbuf
->maxoff
;
279 puffs_framebuf_remaining(struct puffs_framebuf
*pufbuf
)
282 return puffs_framebuf_tellsize(pufbuf
) - puffs_framebuf_telloff(pufbuf
);
286 puffs_framebuf_seekset(struct puffs_framebuf
*pufbuf
, size_t newoff
)
289 if (reservespace(pufbuf
, newoff
, 0) == -1)
292 pufbuf
->offset
= newoff
;
297 puffs_framebuf_getwindow(struct puffs_framebuf
*pufbuf
, size_t winoff
,
298 void **data
, size_t *dlen
)
303 winlen
= MIN(*dlen
, 32);
308 if (reservespace(pufbuf
, winoff
, winlen
) == -1)
311 *data
= pufbuf
->buf
+ winoff
;
312 if (pufbuf
->maxoff
< winoff
+ winlen
)
313 pufbuf
->maxoff
= winoff
+ winlen
;
319 puffs__framebuf_getdataptr(struct puffs_framebuf
*pufbuf
)
326 errnotify(struct puffs_usermount
*pu
, struct puffs_framebuf
*pufbuf
, int error
)
331 puffs__goto(pufbuf
->pcc
);
332 } else if (pufbuf
->fcb
) {
333 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
334 pufbuf
->fcb(pu
, pufbuf
, pufbuf
->fcb_arg
, error
);
336 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
337 puffs_framebuf_destroy(pufbuf
);
343 fio = getfiobyfd(pu, fd); \
348 if (fio->stat & FIO_WRGONE) { \
352 } while (/*CONSTCOND*/0)
355 puffs_framev_enqueue_cc(struct puffs_cc
*pcc
, int fd
,
356 struct puffs_framebuf
*pufbuf
, int flags
)
358 struct puffs_usermount
*pu
= pcc
->pcc_pu
;
359 struct puffs_fctrl_io
*fio
;
362 * Technically we shouldn't allow this if RDGONE, but it's
363 * difficult to trap write close without allowing writes.
364 * And besides, there's probably a disconnect sequence in
365 * the protocol, so unexpectedly getting a closed fd is
366 * most likely an error condition.
372 pufbuf
->fcb_arg
= NULL
;
375 pufbuf
->istat
|= ISTAT_NODESTROY
;
377 if (flags
& PUFFS_FBQUEUE_URGENT
)
378 TAILQ_INSERT_HEAD(&fio
->snd_qing
, pufbuf
, pfb_entries
);
380 TAILQ_INSERT_TAIL(&fio
->snd_qing
, pufbuf
, pfb_entries
);
384 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
393 puffs_framev_enqueue_cb(struct puffs_usermount
*pu
, int fd
,
394 struct puffs_framebuf
*pufbuf
, puffs_framev_cb fcb
, void *arg
,
397 struct puffs_fctrl_io
*fio
;
404 pufbuf
->fcb_arg
= arg
;
407 pufbuf
->istat
|= ISTAT_NODESTROY
;
409 if (flags
& PUFFS_FBQUEUE_URGENT
)
410 TAILQ_INSERT_HEAD(&fio
->snd_qing
, pufbuf
, pfb_entries
);
412 TAILQ_INSERT_TAIL(&fio
->snd_qing
, pufbuf
, pfb_entries
);
418 puffs_framev_enqueue_justsend(struct puffs_usermount
*pu
, int fd
,
419 struct puffs_framebuf
*pufbuf
, int reply
, int flags
)
421 struct puffs_fctrl_io
*fio
;
423 assert((pufbuf
->istat
& ISTAT_INTERNAL
) == 0);
429 pufbuf
->fcb_arg
= NULL
;
432 pufbuf
->istat
|= ISTAT_NODESTROY
;
434 pufbuf
->istat
|= ISTAT_NOREPLY
;
436 if (flags
& PUFFS_FBQUEUE_URGENT
)
437 TAILQ_INSERT_HEAD(&fio
->snd_qing
, pufbuf
, pfb_entries
);
439 TAILQ_INSERT_TAIL(&fio
->snd_qing
, pufbuf
, pfb_entries
);
446 puffs_framev_enqueue_directreceive(struct puffs_cc
*pcc
, int fd
,
447 struct puffs_framebuf
*pufbuf
, int flags
/* used in the future */)
449 struct puffs_usermount
*pu
= pcc
->pcc_pu
;
450 struct puffs_fctrl_io
*fio
;
452 assert((pufbuf
->istat
& ISTAT_INTERNAL
) == 0);
454 fio
= getfiobyfd(pu
, fd
);
460 /* XXX: should have cur_in queue */
461 assert(fio
->cur_in
== NULL
);
462 fio
->cur_in
= pufbuf
;
466 pufbuf
->fcb_arg
= NULL
;
469 pufbuf
->istat
|= ISTAT_NODESTROY
| ISTAT_DIRECT
;
472 pufbuf
->istat
&= ~ISTAT_NODESTROY
; /* XXX: not the right place */
482 puffs_framev_enqueue_directsend(struct puffs_cc
*pcc
, int fd
,
483 struct puffs_framebuf
*pufbuf
, int flags
)
485 struct puffs_usermount
*pu
= pcc
->pcc_pu
;
486 struct puffs_fctrl_io
*fio
;
488 assert((pufbuf
->istat
& ISTAT_INTERNAL
) == 0);
490 if (flags
& PUFFS_FBQUEUE_URGENT
)
491 abort(); /* EOPNOTSUPP for now */
497 pufbuf
->fcb_arg
= NULL
;
500 pufbuf
->istat
|= ISTAT_NODESTROY
| ISTAT_DIRECT
;
502 TAILQ_INSERT_TAIL(&fio
->snd_qing
, pufbuf
, pfb_entries
);
506 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
515 puffs_framev_framebuf_ccpromote(struct puffs_framebuf
*pufbuf
,
516 struct puffs_cc
*pcc
)
519 if ((pufbuf
->istat
& ISTAT_ONQUEUE
) == 0) {
526 pufbuf
->fcb_arg
= NULL
;
527 pufbuf
->istat
&= ~ISTAT_NOREPLY
;
535 puffs_framev_enqueue_waitevent(struct puffs_cc
*pcc
, int fd
, int *what
)
537 struct puffs_usermount
*pu
= pcc
->pcc_pu
;
538 struct puffs_fctrl_io
*fio
;
539 struct puffs_fbevent feb
;
550 fio
= getfiobyfd(pu
, fd
);
557 feb
.what
= *what
& (PUFFS_FBIO_READ
|PUFFS_FBIO_WRITE
|PUFFS_FBIO_ERROR
);
559 if (*what
& PUFFS_FBIO_READ
)
560 if ((fio
->stat
& FIO_ENABLE_R
) == 0)
561 EV_SET(&kev
, fd
, EVFILT_READ
, EV_ENABLE
,
562 0, 0, (uintptr_t)fio
);
564 if (kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
) == -1)
567 if (*what
& PUFFS_FBIO_READ
)
569 if (*what
& PUFFS_FBIO_WRITE
)
572 LIST_INSERT_HEAD(&fio
->ev_qing
, &feb
, pfe_entries
);
575 assert(svwhat
== *what
);
577 if (*what
& PUFFS_FBIO_READ
) {
579 if (fio
->rwait
== 0 && (fio
->stat
& FIO_ENABLE_R
) == 0) {
580 EV_SET(&kev
, fd
, EVFILT_READ
, EV_DISABLE
,
581 0, 0, (uintptr_t)fio
);
582 rv
= kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
589 if (*what
& PUFFS_FBIO_WRITE
)
596 *what
= PUFFS_FBIO_ERROR
;
605 puffs__framev_notify(struct puffs_fctrl_io
*fio
, int what
)
607 struct puffs_fbevent
*fbevp
;
610 LIST_FOREACH(fbevp
, &fio
->ev_qing
, pfe_entries
) {
611 if (fbevp
->what
& what
) {
614 LIST_REMOVE(fbevp
, pfe_entries
);
615 puffs_cc_continue(fbevp
->pcc
);
621 static struct puffs_framebuf
*
622 findbuf(struct puffs_usermount
*pu
, struct puffs_framectrl
*fctrl
,
623 struct puffs_fctrl_io
*fio
, struct puffs_framebuf
*findme
)
625 struct puffs_framebuf
*cand
;
628 TAILQ_FOREACH(cand
, &fio
->res_qing
, pfb_entries
)
629 if (fctrl
->cmpfb(pu
, findme
, cand
, ¬resp
) == 0 || notresp
)
632 assert(!(notresp
&& cand
== NULL
));
633 if (notresp
|| cand
== NULL
)
636 TAILQ_REMOVE(&fio
->res_qing
, cand
, pfb_entries
);
641 puffs__framebuf_moveinfo(struct puffs_framebuf
*from
, struct puffs_framebuf
*to
)
644 assert(from
->istat
& ISTAT_INTERNAL
);
650 /* migrate buffer info */
652 to
->offset
= from
->offset
;
653 to
->maxoff
= from
->maxoff
;
660 puffs__framev_input(struct puffs_usermount
*pu
, struct puffs_framectrl
*fctrl
,
661 struct puffs_fctrl_io
*fio
)
663 struct puffs_framebuf
*pufbuf
, *appbuf
;
666 while ((fio
->stat
& FIO_DEAD
) == 0 && (fio
->stat
& FIO_ENABLE_R
)) {
667 if ((pufbuf
= fio
->cur_in
) == NULL
) {
668 pufbuf
= puffs_framebuf_make();
671 pufbuf
->istat
|= ISTAT_INTERNAL
;
672 fio
->cur_in
= pufbuf
;
676 rv
= fctrl
->rfb(pu
, pufbuf
, fio
->io_fd
, &complete
);
680 puffs__framev_readclose(pu
, fio
, rv
);
685 /* partial read, come back to fight another day */
689 /* else: full read, process */
691 if ((pufbuf
->istat
& ISTAT_DIRECT
) == 0) {
692 appbuf
= findbuf(pu
, fctrl
, fio
, pufbuf
);
695 * No request for this frame? If fs implements
696 * gotfb, give frame to that. Otherwise drop it.
698 if (appbuf
== NULL
) {
700 pufbuf
->istat
&= ~ISTAT_INTERNAL
;
701 fctrl
->gotfb(pu
, pufbuf
);
703 puffs_framebuf_destroy(pufbuf
);
708 puffs__framebuf_moveinfo(pufbuf
, appbuf
);
709 puffs_framebuf_destroy(pufbuf
);
713 appbuf
->istat
&= ~ISTAT_NODESTROY
;
716 puffs__cc_cont(appbuf
->pcc
);
717 } else if (appbuf
->fcb
) {
718 appbuf
->fcb(pu
, appbuf
, appbuf
->fcb_arg
, 0);
720 puffs_framebuf_destroy(appbuf
);
723 /* hopeless romantics, here we go again */
728 puffs__framev_output(struct puffs_usermount
*pu
, struct puffs_framectrl
*fctrl
,
729 struct puffs_fctrl_io
*fio
)
731 struct puffs_framebuf
*pufbuf
;
732 int rv
, complete
, done
;
734 if (fio
->stat
& FIO_DEAD
)
737 for (pufbuf
= TAILQ_FIRST(&fio
->snd_qing
), done
= 0;
738 pufbuf
&& (fio
->stat
& FIO_DEAD
) == 0 && fio
->stat
& FIO_ENABLE_W
;
739 pufbuf
= TAILQ_FIRST(&fio
->snd_qing
)) {
741 rv
= fctrl
->wfb(pu
, pufbuf
, fio
->io_fd
, &complete
);
744 puffs__framev_writeclose(pu
, fio
, rv
);
753 /* else, complete write */
754 TAILQ_REMOVE(&fio
->snd_qing
, pufbuf
, pfb_entries
);
756 /* can't wait for result if we can't read */
757 if (fio
->stat
& FIO_RDGONE
) {
758 errnotify(pu
, pufbuf
, ENXIO
);
760 } else if ((pufbuf
->istat
& ISTAT_DIRECT
)) {
761 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
763 puffs__cc_cont(pufbuf
->pcc
);
764 } else if ((pufbuf
->istat
& ISTAT_NOREPLY
) == 0) {
765 TAILQ_INSERT_TAIL(&fio
->res_qing
, pufbuf
,
768 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
769 puffs_framebuf_destroy(pufbuf
);
779 puffs__framev_addfd_ctrl(struct puffs_usermount
*pu
, int fd
, int what
,
780 struct puffs_framectrl
*pfctrl
)
782 struct puffs_fctrl_io
*fio
;
783 struct kevent
*newevs
;
784 struct kevent kev
[2];
788 nevs
= pu
->pu_nevs
+2;
789 newevs
= realloc(pu
->pu_evs
, nevs
*sizeof(struct kevent
));
794 fio
= malloc(sizeof(struct puffs_fctrl_io
));
797 memset(fio
, 0, sizeof(struct puffs_fctrl_io
));
801 TAILQ_INIT(&fio
->snd_qing
);
802 TAILQ_INIT(&fio
->res_qing
);
803 LIST_INIT(&fio
->ev_qing
);
806 if ((what
& PUFFS_FBIO_READ
) == 0)
807 readenable
= EV_DISABLE
;
809 if (pu
->pu_state
& PU_INLOOP
) {
810 EV_SET(&kev
[0], fd
, EVFILT_READ
,
811 EV_ADD
|readenable
, 0, 0, (intptr_t)fio
);
812 EV_SET(&kev
[1], fd
, EVFILT_WRITE
,
813 EV_ADD
|EV_DISABLE
, 0, 0, (intptr_t)fio
);
814 rv
= kevent(pu
->pu_kq
, kev
, 2, NULL
, 0, NULL
);
820 if (what
& PUFFS_FBIO_READ
)
821 fio
->stat
|= FIO_ENABLE_R
;
822 if (what
& PUFFS_FBIO_WRITE
)
823 fio
->stat
|= FIO_ENABLE_W
;
825 LIST_INSERT_HEAD(&pu
->pu_ios
, fio
, fio_entries
);
832 puffs_framev_addfd(struct puffs_usermount
*pu
, int fd
, int what
)
835 return puffs__framev_addfd_ctrl(pu
, fd
, what
,
836 &pu
->pu_framectrl
[PU_FRAMECTRL_USER
]);
840 * XXX: the following en/disable should be coalesced and executed
841 * only during the actual kevent call. So feel free to fix if
842 * threatened by mindblowing boredom.
846 puffs_framev_enablefd(struct puffs_usermount
*pu
, int fd
, int what
)
849 struct puffs_fctrl_io
*fio
;
852 assert((what
& (PUFFS_FBIO_READ
| PUFFS_FBIO_WRITE
)) != 0);
854 fio
= getfiobyfd(pu
, fd
);
860 /* write is enabled in the event loop if there is output */
861 if (what
& PUFFS_FBIO_READ
&& fio
->rwait
== 0) {
862 EV_SET(&kev
, fd
, EVFILT_READ
, EV_ENABLE
, 0, 0, (uintptr_t)fio
);
863 rv
= kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
867 if (what
& PUFFS_FBIO_READ
)
868 fio
->stat
|= FIO_ENABLE_R
;
869 if (what
& PUFFS_FBIO_WRITE
)
870 fio
->stat
|= FIO_ENABLE_W
;
877 puffs_framev_disablefd(struct puffs_usermount
*pu
, int fd
, int what
)
879 struct kevent kev
[2];
880 struct puffs_fctrl_io
*fio
;
884 assert((what
& (PUFFS_FBIO_READ
| PUFFS_FBIO_WRITE
)) != 0);
886 fio
= getfiobyfd(pu
, fd
);
893 if (what
& PUFFS_FBIO_READ
&& fio
->rwait
== 0) {
895 EVFILT_READ
, EV_DISABLE
, 0, 0, (uintptr_t)fio
);
898 if (what
& PUFFS_FBIO_WRITE
&& fio
->stat
& FIO_WR
&& fio
->wwait
== 0) {
900 EVFILT_WRITE
, EV_DISABLE
, 0, 0, (uintptr_t)fio
);
904 rv
= kevent(pu
->pu_kq
, kev
, i
, NULL
, 0, NULL
);
909 if (what
& PUFFS_FBIO_READ
)
910 fio
->stat
&= ~FIO_ENABLE_R
;
911 if (what
& PUFFS_FBIO_WRITE
)
912 fio
->stat
&= ~FIO_ENABLE_W
;
919 puffs__framev_readclose(struct puffs_usermount
*pu
,
920 struct puffs_fctrl_io
*fio
, int error
)
922 struct puffs_framebuf
*pufbuf
;
926 if (fio
->stat
& FIO_RDGONE
|| fio
->stat
& FIO_DEAD
)
928 fio
->stat
|= FIO_RDGONE
;
931 if ((fio
->cur_in
->istat
& ISTAT_DIRECT
) == 0) {
932 puffs_framebuf_destroy(fio
->cur_in
);
935 errnotify(pu
, fio
->cur_in
, error
);
939 while ((pufbuf
= TAILQ_FIRST(&fio
->res_qing
)) != NULL
) {
940 TAILQ_REMOVE(&fio
->res_qing
, pufbuf
, pfb_entries
);
941 errnotify(pu
, pufbuf
, error
);
944 EV_SET(&kev
, fio
->io_fd
, EVFILT_READ
, EV_DELETE
, 0, 0, 0);
945 (void) kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
947 notflag
= PUFFS_FBIO_READ
;
948 if (fio
->stat
& FIO_WRGONE
)
949 notflag
|= PUFFS_FBIO_WRITE
;
951 if (fio
->fctrl
->fdnotfn
)
952 fio
->fctrl
->fdnotfn(pu
, fio
->io_fd
, notflag
);
956 puffs__framev_writeclose(struct puffs_usermount
*pu
,
957 struct puffs_fctrl_io
*fio
, int error
)
959 struct puffs_framebuf
*pufbuf
;
963 if (fio
->stat
& FIO_WRGONE
|| fio
->stat
& FIO_DEAD
)
965 fio
->stat
|= FIO_WRGONE
;
967 while ((pufbuf
= TAILQ_FIRST(&fio
->snd_qing
)) != NULL
) {
968 TAILQ_REMOVE(&fio
->snd_qing
, pufbuf
, pfb_entries
);
969 errnotify(pu
, pufbuf
, error
);
972 EV_SET(&kev
, fio
->io_fd
, EVFILT_WRITE
, EV_DELETE
, 0, 0, 0);
973 (void) kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
975 notflag
= PUFFS_FBIO_WRITE
;
976 if (fio
->stat
& FIO_RDGONE
)
977 notflag
|= PUFFS_FBIO_READ
;
979 if (fio
->fctrl
->fdnotfn
)
980 fio
->fctrl
->fdnotfn(pu
, fio
->io_fd
, notflag
);
984 removefio(struct puffs_usermount
*pu
, struct puffs_fctrl_io
*fio
, int error
)
986 struct puffs_fbevent
*fbevp
;
988 LIST_REMOVE(fio
, fio_entries
);
989 if (pu
->pu_state
& PU_INLOOP
) {
990 puffs__framev_readclose(pu
, fio
, error
);
991 puffs__framev_writeclose(pu
, fio
, error
);
994 while ((fbevp
= LIST_FIRST(&fio
->ev_qing
)) != NULL
) {
996 LIST_REMOVE(fbevp
, pfe_entries
);
997 puffs__goto(fbevp
->pcc
);
1000 /* don't bother with realloc */
1003 /* don't free us yet, might have some references in event arrays */
1004 fio
->stat
|= FIO_DEAD
;
1005 LIST_INSERT_HEAD(&pu
->pu_ios_rmlist
, fio
, fio_entries
);
1012 puffs_framev_removefd(struct puffs_usermount
*pu
, int fd
, int error
)
1014 struct puffs_fctrl_io
*fio
;
1016 fio
= getfiobyfd(pu
, fd
);
1022 return removefio(pu
, fio
, error
? error
: ECONNRESET
);
1026 puffs_framev_removeonclose(struct puffs_usermount
*pu
, int fd
, int what
)
1029 if (what
== (PUFFS_FBIO_READ
| PUFFS_FBIO_WRITE
))
1030 (void) puffs_framev_removefd(pu
, fd
, ECONNRESET
);
1034 puffs_framev_unmountonclose(struct puffs_usermount
*pu
, int fd
, int what
)
1037 /* XXX & X: unmount is non-sensible */
1038 puffs_framev_removeonclose(pu
, fd
, what
);
1039 if (what
== (PUFFS_FBIO_READ
| PUFFS_FBIO_WRITE
))
1040 PU_SETSTATE(pu
, PUFFS_STATE_UNMOUNTED
);
1044 puffs_framev_init(struct puffs_usermount
*pu
,
1045 puffs_framev_readframe_fn rfb
, puffs_framev_writeframe_fn wfb
,
1046 puffs_framev_cmpframe_fn cmpfb
, puffs_framev_gotframe_fn gotfb
,
1047 puffs_framev_fdnotify_fn fdnotfn
)
1049 struct puffs_framectrl
*pfctrl
;
1051 pfctrl
= &pu
->pu_framectrl
[PU_FRAMECTRL_USER
];
1054 pfctrl
->cmpfb
= cmpfb
;
1055 pfctrl
->gotfb
= gotfb
;
1056 pfctrl
->fdnotfn
= fdnotfn
;
1060 puffs__framev_exit(struct puffs_usermount
*pu
)
1062 struct puffs_fctrl_io
*fio
;
1064 while ((fio
= LIST_FIRST(&pu
->pu_ios
)) != NULL
)
1065 removefio(pu
, fio
, ENXIO
);
1068 /* closing pu->pu_kq takes care of puffsfd */