1 /* $NetBSD: framebuf.c,v 1.30 2010/01/12 18:42:38 pooka 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/types.h>
37 #include <sys/event.h>
38 #include <sys/queue.h>
48 #include "puffs_priv.h"
50 struct puffs_framebuf
{
51 struct puffs_cc
*pcc
; /* pcc to continue with */
53 puffs_framev_cb fcb
; /* non-blocking callback */
54 void *fcb_arg
; /* argument for previous */
56 uint8_t *buf
; /* buffer base */
57 size_t len
; /* total length */
59 size_t offset
; /* cursor, telloff() */
60 size_t maxoff
; /* maximum offset for data, tellsize() */
62 volatile int rv
; /* errno value */
66 TAILQ_ENTRY(puffs_framebuf
) pfb_entries
;
68 #define ISTAT_NODESTROY 0x01 /* indestructible by framebuf_destroy() */
69 #define ISTAT_INTERNAL 0x02 /* never leaves library */
70 #define ISTAT_NOREPLY 0x04 /* nuke after sending */
71 #define ISTAT_DIRECT 0x08 /* receive directly, no moveinfo */
73 #define ISTAT_ONQUEUE ISTAT_NODESTROY /* alias */
75 #define PUFBUF_INCRALLOC 4096
76 #define PUFBUF_REMAIN(p) (p->len - p->offset)
79 struct puffs_fbevent
{
84 LIST_ENTRY(puffs_fbevent
) pfe_entries
;
87 static struct puffs_fctrl_io
*
88 getfiobyfd(struct puffs_usermount
*pu
, int fd
)
90 struct puffs_fctrl_io
*fio
;
92 LIST_FOREACH(fio
, &pu
->pu_ios
, fio_entries
)
98 struct puffs_framebuf
*
99 puffs_framebuf_make(void)
101 struct puffs_framebuf
*pufbuf
;
103 pufbuf
= malloc(sizeof(struct puffs_framebuf
));
106 memset(pufbuf
, 0, sizeof(struct puffs_framebuf
));
108 pufbuf
->buf
= malloc(PUFBUF_INCRALLOC
);
109 if (pufbuf
->buf
== NULL
) {
113 pufbuf
->len
= PUFBUF_INCRALLOC
;
115 puffs_framebuf_recycle(pufbuf
);
120 puffs_framebuf_destroy(struct puffs_framebuf
*pufbuf
)
123 assert((pufbuf
->istat
& ISTAT_NODESTROY
) == 0);
130 puffs_framebuf_recycle(struct puffs_framebuf
*pufbuf
)
133 assert((pufbuf
->istat
& ISTAT_NODESTROY
) == 0);
141 reservespace(struct puffs_framebuf
*pufbuf
, size_t off
, size_t wantsize
)
146 if (off
<= pufbuf
->len
&& pufbuf
->len
- off
>= wantsize
)
149 for (incr
= PUFBUF_INCRALLOC
;
150 pufbuf
->len
+ incr
< off
+ wantsize
;
151 incr
+= PUFBUF_INCRALLOC
)
154 nd
= realloc(pufbuf
->buf
, pufbuf
->len
+ incr
);
165 puffs_framebuf_dup(struct puffs_framebuf
*pb
, struct puffs_framebuf
**pbp
)
167 struct puffs_framebuf
*newpb
;
169 newpb
= puffs_framebuf_make();
174 memcpy(newpb
, pb
, sizeof(struct puffs_framebuf
));
178 if (reservespace(newpb
, 0, pb
->maxoff
) == -1) {
179 puffs_framebuf_destroy(newpb
);
183 memcpy(newpb
->buf
, pb
->buf
, pb
->maxoff
);
191 puffs_framebuf_reserve_space(struct puffs_framebuf
*pufbuf
, size_t wantsize
)
194 return reservespace(pufbuf
, pufbuf
->offset
, wantsize
);
198 puffs_framebuf_putdata(struct puffs_framebuf
*pufbuf
,
199 const void *data
, size_t dlen
)
202 if (PUFBUF_REMAIN(pufbuf
) < dlen
)
203 if (puffs_framebuf_reserve_space(pufbuf
, dlen
) == -1)
206 memcpy(pufbuf
->buf
+ pufbuf
->offset
, data
, dlen
);
207 pufbuf
->offset
+= dlen
;
209 if (pufbuf
->offset
> pufbuf
->maxoff
)
210 pufbuf
->maxoff
= pufbuf
->offset
;
216 puffs_framebuf_putdata_atoff(struct puffs_framebuf
*pufbuf
, size_t offset
,
217 const void *data
, size_t dlen
)
220 if (reservespace(pufbuf
, offset
, dlen
) == -1)
223 memcpy(pufbuf
->buf
+ offset
, data
, dlen
);
225 if (offset
+ dlen
> pufbuf
->maxoff
)
226 pufbuf
->maxoff
= offset
+ dlen
;
232 puffs_framebuf_getdata(struct puffs_framebuf
*pufbuf
, void *data
, size_t dlen
)
235 if (pufbuf
->maxoff
< pufbuf
->offset
+ dlen
) {
240 memcpy(data
, pufbuf
->buf
+ pufbuf
->offset
, dlen
);
241 pufbuf
->offset
+= dlen
;
247 puffs_framebuf_getdata_atoff(struct puffs_framebuf
*pufbuf
, size_t offset
,
248 void *data
, size_t dlen
)
251 if (pufbuf
->maxoff
< offset
+ dlen
) {
256 memcpy(data
, pufbuf
->buf
+ offset
, dlen
);
261 puffs_framebuf_telloff(struct puffs_framebuf
*pufbuf
)
264 return pufbuf
->offset
;
268 puffs_framebuf_tellsize(struct puffs_framebuf
*pufbuf
)
271 return pufbuf
->maxoff
;
275 puffs_framebuf_remaining(struct puffs_framebuf
*pufbuf
)
278 return puffs_framebuf_tellsize(pufbuf
) - puffs_framebuf_telloff(pufbuf
);
282 puffs_framebuf_seekset(struct puffs_framebuf
*pufbuf
, size_t newoff
)
285 if (reservespace(pufbuf
, newoff
, 0) == -1)
288 pufbuf
->offset
= newoff
;
293 puffs_framebuf_getwindow(struct puffs_framebuf
*pufbuf
, size_t winoff
,
294 void **data
, size_t *dlen
)
299 winlen
= MIN(*dlen
, 32);
304 if (reservespace(pufbuf
, winoff
, winlen
) == -1)
307 *data
= pufbuf
->buf
+ winoff
;
308 if (pufbuf
->maxoff
< winoff
+ winlen
)
309 pufbuf
->maxoff
= winoff
+ winlen
;
315 puffs__framebuf_getdataptr(struct puffs_framebuf
*pufbuf
)
322 errnotify(struct puffs_usermount
*pu
, struct puffs_framebuf
*pufbuf
, int error
)
327 puffs__goto(pufbuf
->pcc
);
328 } else if (pufbuf
->fcb
) {
329 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
330 pufbuf
->fcb(pu
, pufbuf
, pufbuf
->fcb_arg
, error
);
332 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
333 puffs_framebuf_destroy(pufbuf
);
339 fio = getfiobyfd(pu, fd); \
344 if (fio->stat & FIO_WRGONE) { \
348 } while (/*CONSTCOND*/0)
351 puffs_framev_enqueue_cc(struct puffs_cc
*pcc
, int fd
,
352 struct puffs_framebuf
*pufbuf
, int flags
)
354 struct puffs_usermount
*pu
= pcc
->pcc_pu
;
355 struct puffs_fctrl_io
*fio
;
358 * Technically we shouldn't allow this if RDGONE, but it's
359 * difficult to trap write close without allowing writes.
360 * And besides, there's probably a disconnect sequence in
361 * the protocol, so unexpectedly getting a closed fd is
362 * most likely an error condition.
368 pufbuf
->fcb_arg
= NULL
;
371 pufbuf
->istat
|= ISTAT_NODESTROY
;
373 if (flags
& PUFFS_FBQUEUE_URGENT
)
374 TAILQ_INSERT_HEAD(&fio
->snd_qing
, pufbuf
, pfb_entries
);
376 TAILQ_INSERT_TAIL(&fio
->snd_qing
, pufbuf
, pfb_entries
);
380 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
389 puffs_framev_enqueue_cb(struct puffs_usermount
*pu
, int fd
,
390 struct puffs_framebuf
*pufbuf
, puffs_framev_cb fcb
, void *arg
,
393 struct puffs_fctrl_io
*fio
;
400 pufbuf
->fcb_arg
= arg
;
403 pufbuf
->istat
|= ISTAT_NODESTROY
;
405 if (flags
& PUFFS_FBQUEUE_URGENT
)
406 TAILQ_INSERT_HEAD(&fio
->snd_qing
, pufbuf
, pfb_entries
);
408 TAILQ_INSERT_TAIL(&fio
->snd_qing
, pufbuf
, pfb_entries
);
414 puffs_framev_enqueue_justsend(struct puffs_usermount
*pu
, int fd
,
415 struct puffs_framebuf
*pufbuf
, int reply
, int flags
)
417 struct puffs_fctrl_io
*fio
;
419 assert((pufbuf
->istat
& ISTAT_INTERNAL
) == 0);
425 pufbuf
->fcb_arg
= NULL
;
428 pufbuf
->istat
|= ISTAT_NODESTROY
;
430 pufbuf
->istat
|= ISTAT_NOREPLY
;
432 if (flags
& PUFFS_FBQUEUE_URGENT
)
433 TAILQ_INSERT_HEAD(&fio
->snd_qing
, pufbuf
, pfb_entries
);
435 TAILQ_INSERT_TAIL(&fio
->snd_qing
, pufbuf
, pfb_entries
);
442 puffs_framev_enqueue_directreceive(struct puffs_cc
*pcc
, int fd
,
443 struct puffs_framebuf
*pufbuf
, int flags
/* used in the future */)
445 struct puffs_usermount
*pu
= pcc
->pcc_pu
;
446 struct puffs_fctrl_io
*fio
;
448 assert((pufbuf
->istat
& ISTAT_INTERNAL
) == 0);
450 fio
= getfiobyfd(pu
, fd
);
456 /* XXX: should have cur_in queue */
457 assert(fio
->cur_in
== NULL
);
458 fio
->cur_in
= pufbuf
;
462 pufbuf
->fcb_arg
= NULL
;
465 pufbuf
->istat
|= ISTAT_NODESTROY
| ISTAT_DIRECT
;
468 pufbuf
->istat
&= ~ISTAT_NODESTROY
; /* XXX: not the right place */
478 puffs_framev_enqueue_directsend(struct puffs_cc
*pcc
, int fd
,
479 struct puffs_framebuf
*pufbuf
, int flags
)
481 struct puffs_usermount
*pu
= pcc
->pcc_pu
;
482 struct puffs_fctrl_io
*fio
;
484 assert((pufbuf
->istat
& ISTAT_INTERNAL
) == 0);
486 if (flags
& PUFFS_FBQUEUE_URGENT
)
487 abort(); /* EOPNOTSUPP for now */
493 pufbuf
->fcb_arg
= NULL
;
496 pufbuf
->istat
|= ISTAT_NODESTROY
| ISTAT_DIRECT
;
498 TAILQ_INSERT_TAIL(&fio
->snd_qing
, pufbuf
, pfb_entries
);
502 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
511 puffs_framev_framebuf_ccpromote(struct puffs_framebuf
*pufbuf
,
512 struct puffs_cc
*pcc
)
515 if ((pufbuf
->istat
& ISTAT_ONQUEUE
) == 0) {
522 pufbuf
->fcb_arg
= NULL
;
523 pufbuf
->istat
&= ~ISTAT_NOREPLY
;
531 puffs_framev_enqueue_waitevent(struct puffs_cc
*pcc
, int fd
, int *what
)
533 struct puffs_usermount
*pu
= pcc
->pcc_pu
;
534 struct puffs_fctrl_io
*fio
;
535 struct puffs_fbevent feb
;
546 fio
= getfiobyfd(pu
, fd
);
553 feb
.what
= *what
& (PUFFS_FBIO_READ
|PUFFS_FBIO_WRITE
|PUFFS_FBIO_ERROR
);
555 if (*what
& PUFFS_FBIO_READ
)
556 if ((fio
->stat
& FIO_ENABLE_R
) == 0)
557 EV_SET(&kev
, fd
, EVFILT_READ
, EV_ENABLE
,
560 rv
= kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
564 if (*what
& PUFFS_FBIO_READ
)
566 if (*what
& PUFFS_FBIO_WRITE
)
569 LIST_INSERT_HEAD(&fio
->ev_qing
, &feb
, pfe_entries
);
572 assert(svwhat
== *what
);
574 if (*what
& PUFFS_FBIO_READ
) {
576 if (fio
->rwait
== 0 && (fio
->stat
& FIO_ENABLE_R
) == 0) {
577 EV_SET(&kev
, fd
, EVFILT_READ
, EV_DISABLE
,
579 rv
= kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
586 if (*what
& PUFFS_FBIO_WRITE
)
593 *what
= PUFFS_FBIO_ERROR
;
602 puffs__framev_notify(struct puffs_fctrl_io
*fio
, int what
)
604 struct puffs_fbevent
*fbevp
;
607 LIST_FOREACH(fbevp
, &fio
->ev_qing
, pfe_entries
) {
608 if (fbevp
->what
& what
) {
611 LIST_REMOVE(fbevp
, pfe_entries
);
612 puffs_cc_continue(fbevp
->pcc
);
618 static struct puffs_framebuf
*
619 findbuf(struct puffs_usermount
*pu
, struct puffs_framectrl
*fctrl
,
620 struct puffs_fctrl_io
*fio
, struct puffs_framebuf
*findme
)
622 struct puffs_framebuf
*cand
;
625 TAILQ_FOREACH(cand
, &fio
->res_qing
, pfb_entries
)
626 if (fctrl
->cmpfb(pu
, findme
, cand
, ¬resp
) == 0 || notresp
)
629 assert(!(notresp
&& cand
== NULL
));
630 if (notresp
|| cand
== NULL
)
633 TAILQ_REMOVE(&fio
->res_qing
, cand
, pfb_entries
);
638 puffs__framebuf_moveinfo(struct puffs_framebuf
*from
, struct puffs_framebuf
*to
)
641 assert(from
->istat
& ISTAT_INTERNAL
);
647 /* migrate buffer info */
649 to
->offset
= from
->offset
;
650 to
->maxoff
= from
->maxoff
;
657 puffs__framev_input(struct puffs_usermount
*pu
, struct puffs_framectrl
*fctrl
,
658 struct puffs_fctrl_io
*fio
)
660 struct puffs_framebuf
*pufbuf
, *appbuf
;
663 while ((fio
->stat
& FIO_DEAD
) == 0 && (fio
->stat
& FIO_ENABLE_R
)) {
664 if ((pufbuf
= fio
->cur_in
) == NULL
) {
665 pufbuf
= puffs_framebuf_make();
668 pufbuf
->istat
|= ISTAT_INTERNAL
;
669 fio
->cur_in
= pufbuf
;
673 rv
= fctrl
->rfb(pu
, pufbuf
, fio
->io_fd
, &complete
);
677 puffs__framev_readclose(pu
, fio
, rv
);
682 /* partial read, come back to fight another day */
686 /* else: full read, process */
688 if ((pufbuf
->istat
& ISTAT_DIRECT
) == 0) {
689 appbuf
= findbuf(pu
, fctrl
, fio
, pufbuf
);
692 * No request for this frame? If fs implements
693 * gotfb, give frame to that. Otherwise drop it.
695 if (appbuf
== NULL
) {
697 pufbuf
->istat
&= ~ISTAT_INTERNAL
;
698 fctrl
->gotfb(pu
, pufbuf
);
700 puffs_framebuf_destroy(pufbuf
);
705 puffs__framebuf_moveinfo(pufbuf
, appbuf
);
706 puffs_framebuf_destroy(pufbuf
);
710 appbuf
->istat
&= ~ISTAT_NODESTROY
;
713 puffs__cc_cont(appbuf
->pcc
);
714 } else if (appbuf
->fcb
) {
715 appbuf
->fcb(pu
, appbuf
, appbuf
->fcb_arg
, 0);
717 puffs_framebuf_destroy(appbuf
);
720 /* hopeless romantics, here we go again */
725 puffs__framev_output(struct puffs_usermount
*pu
, struct puffs_framectrl
*fctrl
,
726 struct puffs_fctrl_io
*fio
)
728 struct puffs_framebuf
*pufbuf
;
729 int rv
, complete
, done
;
731 if (fio
->stat
& FIO_DEAD
)
734 for (pufbuf
= TAILQ_FIRST(&fio
->snd_qing
), done
= 0;
735 pufbuf
&& (fio
->stat
& FIO_DEAD
) == 0 && fio
->stat
& FIO_ENABLE_W
;
736 pufbuf
= TAILQ_FIRST(&fio
->snd_qing
)) {
738 rv
= fctrl
->wfb(pu
, pufbuf
, fio
->io_fd
, &complete
);
741 puffs__framev_writeclose(pu
, fio
, rv
);
750 /* else, complete write */
751 TAILQ_REMOVE(&fio
->snd_qing
, pufbuf
, pfb_entries
);
753 /* can't wait for result if we can't read */
754 if (fio
->stat
& FIO_RDGONE
) {
755 errnotify(pu
, pufbuf
, ENXIO
);
757 } else if ((pufbuf
->istat
& ISTAT_DIRECT
)) {
758 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
760 puffs__cc_cont(pufbuf
->pcc
);
761 } else if ((pufbuf
->istat
& ISTAT_NOREPLY
) == 0) {
762 TAILQ_INSERT_TAIL(&fio
->res_qing
, pufbuf
,
765 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
766 puffs_framebuf_destroy(pufbuf
);
776 puffs__framev_addfd_ctrl(struct puffs_usermount
*pu
, int fd
, int what
,
777 struct puffs_framectrl
*pfctrl
)
779 struct puffs_fctrl_io
*fio
;
780 struct kevent
*newevs
;
781 struct kevent kev
[2];
785 nevs
= pu
->pu_nevs
+2;
786 newevs
= realloc(pu
->pu_evs
, nevs
*sizeof(struct kevent
));
791 fio
= malloc(sizeof(struct puffs_fctrl_io
));
794 memset(fio
, 0, sizeof(struct puffs_fctrl_io
));
798 TAILQ_INIT(&fio
->snd_qing
);
799 TAILQ_INIT(&fio
->res_qing
);
800 LIST_INIT(&fio
->ev_qing
);
803 if ((what
& PUFFS_FBIO_READ
) == 0)
804 readenable
= EV_DISABLE
;
806 if (pu
->pu_state
& PU_INLOOP
) {
807 EV_SET(&kev
[0], fd
, EVFILT_READ
,
808 EV_ADD
|readenable
, 0, 0, fio
);
809 EV_SET(&kev
[1], fd
, EVFILT_WRITE
,
810 EV_ADD
|EV_DISABLE
, 0, 0, fio
);
811 rv
= kevent(pu
->pu_kq
, kev
, 2, NULL
, 0, NULL
);
817 if (what
& PUFFS_FBIO_READ
)
818 fio
->stat
|= FIO_ENABLE_R
;
819 if (what
& PUFFS_FBIO_WRITE
)
820 fio
->stat
|= FIO_ENABLE_W
;
822 LIST_INSERT_HEAD(&pu
->pu_ios
, fio
, fio_entries
);
829 puffs_framev_addfd(struct puffs_usermount
*pu
, int fd
, int what
)
832 return puffs__framev_addfd_ctrl(pu
, fd
, what
,
833 &pu
->pu_framectrl
[PU_FRAMECTRL_USER
]);
837 * XXX: the following en/disable should be coalesced and executed
838 * only during the actual kevent call. So feel free to fix if
839 * threatened by mindblowing boredom.
843 puffs_framev_enablefd(struct puffs_usermount
*pu
, int fd
, int what
)
846 struct puffs_fctrl_io
*fio
;
849 assert((what
& (PUFFS_FBIO_READ
| PUFFS_FBIO_WRITE
)) != 0);
851 fio
= getfiobyfd(pu
, fd
);
857 /* write is enabled in the event loop if there is output */
858 if (what
& PUFFS_FBIO_READ
&& fio
->rwait
== 0) {
859 EV_SET(&kev
, fd
, EVFILT_READ
, EV_ENABLE
, 0, 0, fio
);
860 rv
= kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
864 if (what
& PUFFS_FBIO_READ
)
865 fio
->stat
|= FIO_ENABLE_R
;
866 if (what
& PUFFS_FBIO_WRITE
)
867 fio
->stat
|= FIO_ENABLE_W
;
874 puffs_framev_disablefd(struct puffs_usermount
*pu
, int fd
, int what
)
876 struct kevent kev
[2];
877 struct puffs_fctrl_io
*fio
;
881 assert((what
& (PUFFS_FBIO_READ
| PUFFS_FBIO_WRITE
)) != 0);
883 fio
= getfiobyfd(pu
, fd
);
890 if (what
& PUFFS_FBIO_READ
&& fio
->rwait
== 0) {
892 EVFILT_READ
, EV_DISABLE
, 0, 0, fio
);
895 if (what
& PUFFS_FBIO_WRITE
&& fio
->stat
& FIO_WR
&& fio
->wwait
== 0) {
897 EVFILT_WRITE
, EV_DISABLE
, 0, 0, fio
);
901 rv
= kevent(pu
->pu_kq
, kev
, i
, NULL
, 0, NULL
);
906 if (what
& PUFFS_FBIO_READ
)
907 fio
->stat
&= ~FIO_ENABLE_R
;
908 if (what
& PUFFS_FBIO_WRITE
)
909 fio
->stat
&= ~FIO_ENABLE_W
;
916 puffs__framev_readclose(struct puffs_usermount
*pu
,
917 struct puffs_fctrl_io
*fio
, int error
)
919 struct puffs_framebuf
*pufbuf
;
923 if (fio
->stat
& FIO_RDGONE
|| fio
->stat
& FIO_DEAD
)
925 fio
->stat
|= FIO_RDGONE
;
928 if ((fio
->cur_in
->istat
& ISTAT_DIRECT
) == 0) {
929 puffs_framebuf_destroy(fio
->cur_in
);
932 errnotify(pu
, fio
->cur_in
, error
);
936 while ((pufbuf
= TAILQ_FIRST(&fio
->res_qing
)) != NULL
) {
937 TAILQ_REMOVE(&fio
->res_qing
, pufbuf
, pfb_entries
);
938 errnotify(pu
, pufbuf
, error
);
941 EV_SET(&kev
, fio
->io_fd
, EVFILT_READ
, EV_DELETE
, 0, 0, 0);
942 (void) kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
944 notflag
= PUFFS_FBIO_READ
;
945 if (fio
->stat
& FIO_WRGONE
)
946 notflag
|= PUFFS_FBIO_WRITE
;
948 if (fio
->fctrl
->fdnotfn
)
949 fio
->fctrl
->fdnotfn(pu
, fio
->io_fd
, notflag
);
953 puffs__framev_writeclose(struct puffs_usermount
*pu
,
954 struct puffs_fctrl_io
*fio
, int error
)
956 struct puffs_framebuf
*pufbuf
;
960 if (fio
->stat
& FIO_WRGONE
|| fio
->stat
& FIO_DEAD
)
962 fio
->stat
|= FIO_WRGONE
;
964 while ((pufbuf
= TAILQ_FIRST(&fio
->snd_qing
)) != NULL
) {
965 TAILQ_REMOVE(&fio
->snd_qing
, pufbuf
, pfb_entries
);
966 errnotify(pu
, pufbuf
, error
);
969 EV_SET(&kev
, fio
->io_fd
, EVFILT_WRITE
, EV_DELETE
, 0, 0, 0);
970 (void) kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
972 notflag
= PUFFS_FBIO_WRITE
;
973 if (fio
->stat
& FIO_RDGONE
)
974 notflag
|= PUFFS_FBIO_READ
;
976 if (fio
->fctrl
->fdnotfn
)
977 fio
->fctrl
->fdnotfn(pu
, fio
->io_fd
, notflag
);
981 removefio(struct puffs_usermount
*pu
, struct puffs_fctrl_io
*fio
, int error
)
983 struct puffs_fbevent
*fbevp
;
985 LIST_REMOVE(fio
, fio_entries
);
986 if (pu
->pu_state
& PU_INLOOP
) {
987 puffs__framev_readclose(pu
, fio
, error
);
988 puffs__framev_writeclose(pu
, fio
, error
);
991 while ((fbevp
= LIST_FIRST(&fio
->ev_qing
)) != NULL
) {
993 LIST_REMOVE(fbevp
, pfe_entries
);
994 puffs__goto(fbevp
->pcc
);
997 /* don't bother with realloc */
1000 /* don't free us yet, might have some references in event arrays */
1001 fio
->stat
|= FIO_DEAD
;
1002 LIST_INSERT_HEAD(&pu
->pu_ios_rmlist
, fio
, fio_entries
);
1009 puffs_framev_removefd(struct puffs_usermount
*pu
, int fd
, int error
)
1011 struct puffs_fctrl_io
*fio
;
1013 fio
= getfiobyfd(pu
, fd
);
1019 return removefio(pu
, fio
, error
? error
: ECONNRESET
);
1023 puffs_framev_removeonclose(struct puffs_usermount
*pu
, int fd
, int what
)
1026 if (what
== (PUFFS_FBIO_READ
| PUFFS_FBIO_WRITE
))
1027 (void) puffs_framev_removefd(pu
, fd
, ECONNRESET
);
1031 puffs_framev_unmountonclose(struct puffs_usermount
*pu
, int fd
, int what
)
1034 /* XXX & X: unmount is non-sensible */
1035 puffs_framev_removeonclose(pu
, fd
, what
);
1036 if (what
== (PUFFS_FBIO_READ
| PUFFS_FBIO_WRITE
))
1037 PU_SETSTATE(pu
, PUFFS_STATE_UNMOUNTED
);
1041 puffs_framev_init(struct puffs_usermount
*pu
,
1042 puffs_framev_readframe_fn rfb
, puffs_framev_writeframe_fn wfb
,
1043 puffs_framev_cmpframe_fn cmpfb
, puffs_framev_gotframe_fn gotfb
,
1044 puffs_framev_fdnotify_fn fdnotfn
)
1046 struct puffs_framectrl
*pfctrl
;
1048 pfctrl
= &pu
->pu_framectrl
[PU_FRAMECTRL_USER
];
1051 pfctrl
->cmpfb
= cmpfb
;
1052 pfctrl
->gotfb
= gotfb
;
1053 pfctrl
->fdnotfn
= fdnotfn
;
1057 puffs__framev_exit(struct puffs_usermount
*pu
)
1059 struct puffs_fctrl_io
*fio
;
1061 while ((fio
= LIST_FIRST(&pu
->pu_ios
)) != NULL
)
1062 removefio(pu
, fio
, ENXIO
);
1065 /* closing pu->pu_kq takes care of puffsfd */