1 /* $NetBSD: framebuf.c,v 1.28 2008/01/29 10:07:29 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/cdefs.h>
38 __RCSID("$NetBSD: framebuf.c,v 1.28 2008/01/29 10:07:29 pooka 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()
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 rv
= kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
568 if (*what
& PUFFS_FBIO_READ
)
570 if (*what
& PUFFS_FBIO_WRITE
)
573 LIST_INSERT_HEAD(&fio
->ev_qing
, &feb
, pfe_entries
);
576 assert(svwhat
== *what
);
578 if (*what
& PUFFS_FBIO_READ
) {
580 if (fio
->rwait
== 0 && (fio
->stat
& FIO_ENABLE_R
) == 0) {
581 EV_SET(&kev
, fd
, EVFILT_READ
, EV_DISABLE
,
582 0, 0, (uintptr_t)fio
);
583 rv
= kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
590 if (*what
& PUFFS_FBIO_WRITE
)
597 *what
= PUFFS_FBIO_ERROR
;
606 puffs__framev_notify(struct puffs_fctrl_io
*fio
, int what
)
608 struct puffs_fbevent
*fbevp
;
611 LIST_FOREACH(fbevp
, &fio
->ev_qing
, pfe_entries
) {
612 if (fbevp
->what
& what
) {
615 LIST_REMOVE(fbevp
, pfe_entries
);
616 puffs_cc_continue(fbevp
->pcc
);
622 static struct puffs_framebuf
*
623 findbuf(struct puffs_usermount
*pu
, struct puffs_framectrl
*fctrl
,
624 struct puffs_fctrl_io
*fio
, struct puffs_framebuf
*findme
)
626 struct puffs_framebuf
*cand
;
629 TAILQ_FOREACH(cand
, &fio
->res_qing
, pfb_entries
)
630 if (fctrl
->cmpfb(pu
, findme
, cand
, ¬resp
) == 0 || notresp
)
633 assert(!(notresp
&& cand
== NULL
));
634 if (notresp
|| cand
== NULL
)
637 TAILQ_REMOVE(&fio
->res_qing
, cand
, pfb_entries
);
642 puffs__framebuf_moveinfo(struct puffs_framebuf
*from
, struct puffs_framebuf
*to
)
645 assert(from
->istat
& ISTAT_INTERNAL
);
651 /* migrate buffer info */
653 to
->offset
= from
->offset
;
654 to
->maxoff
= from
->maxoff
;
661 puffs__framev_input(struct puffs_usermount
*pu
, struct puffs_framectrl
*fctrl
,
662 struct puffs_fctrl_io
*fio
)
664 struct puffs_framebuf
*pufbuf
, *appbuf
;
667 while ((fio
->stat
& FIO_DEAD
) == 0 && (fio
->stat
& FIO_ENABLE_R
)) {
668 if ((pufbuf
= fio
->cur_in
) == NULL
) {
669 pufbuf
= puffs_framebuf_make();
672 pufbuf
->istat
|= ISTAT_INTERNAL
;
673 fio
->cur_in
= pufbuf
;
677 rv
= fctrl
->rfb(pu
, pufbuf
, fio
->io_fd
, &complete
);
681 puffs__framev_readclose(pu
, fio
, rv
);
686 /* partial read, come back to fight another day */
690 /* else: full read, process */
692 if ((pufbuf
->istat
& ISTAT_DIRECT
) == 0) {
693 appbuf
= findbuf(pu
, fctrl
, fio
, pufbuf
);
696 * No request for this frame? If fs implements
697 * gotfb, give frame to that. Otherwise drop it.
699 if (appbuf
== NULL
) {
701 pufbuf
->istat
&= ~ISTAT_INTERNAL
;
702 fctrl
->gotfb(pu
, pufbuf
);
704 puffs_framebuf_destroy(pufbuf
);
709 puffs__framebuf_moveinfo(pufbuf
, appbuf
);
710 puffs_framebuf_destroy(pufbuf
);
714 appbuf
->istat
&= ~ISTAT_NODESTROY
;
717 puffs__cc_cont(appbuf
->pcc
);
718 } else if (appbuf
->fcb
) {
719 appbuf
->fcb(pu
, appbuf
, appbuf
->fcb_arg
, 0);
721 puffs_framebuf_destroy(appbuf
);
724 /* hopeless romantics, here we go again */
729 puffs__framev_output(struct puffs_usermount
*pu
, struct puffs_framectrl
*fctrl
,
730 struct puffs_fctrl_io
*fio
)
732 struct puffs_framebuf
*pufbuf
;
733 int rv
, complete
, done
;
735 if (fio
->stat
& FIO_DEAD
)
738 for (pufbuf
= TAILQ_FIRST(&fio
->snd_qing
), done
= 0;
739 pufbuf
&& (fio
->stat
& FIO_DEAD
) == 0 && fio
->stat
& FIO_ENABLE_W
;
740 pufbuf
= TAILQ_FIRST(&fio
->snd_qing
)) {
742 rv
= fctrl
->wfb(pu
, pufbuf
, fio
->io_fd
, &complete
);
745 puffs__framev_writeclose(pu
, fio
, rv
);
754 /* else, complete write */
755 TAILQ_REMOVE(&fio
->snd_qing
, pufbuf
, pfb_entries
);
757 /* can't wait for result if we can't read */
758 if (fio
->stat
& FIO_RDGONE
) {
759 errnotify(pu
, pufbuf
, ENXIO
);
761 } else if ((pufbuf
->istat
& ISTAT_DIRECT
)) {
762 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
764 puffs__cc_cont(pufbuf
->pcc
);
765 } else if ((pufbuf
->istat
& ISTAT_NOREPLY
) == 0) {
766 TAILQ_INSERT_TAIL(&fio
->res_qing
, pufbuf
,
769 pufbuf
->istat
&= ~ISTAT_NODESTROY
;
770 puffs_framebuf_destroy(pufbuf
);
780 puffs__framev_addfd_ctrl(struct puffs_usermount
*pu
, int fd
, int what
,
781 struct puffs_framectrl
*pfctrl
)
783 struct puffs_fctrl_io
*fio
;
784 struct kevent
*newevs
;
785 struct kevent kev
[2];
789 nfds
= pu
->pu_nfds
+1;
790 newevs
= realloc(pu
->pu_evs
, (2*nfds
) * sizeof(struct kevent
));
795 fio
= malloc(sizeof(struct puffs_fctrl_io
));
798 memset(fio
, 0, sizeof(struct puffs_fctrl_io
));
802 TAILQ_INIT(&fio
->snd_qing
);
803 TAILQ_INIT(&fio
->res_qing
);
804 LIST_INIT(&fio
->ev_qing
);
807 if ((what
& PUFFS_FBIO_READ
) == 0)
808 readenable
= EV_DISABLE
;
810 if (pu
->pu_state
& PU_INLOOP
) {
811 EV_SET(&kev
[0], fd
, EVFILT_READ
,
812 EV_ADD
|readenable
, 0, 0, (intptr_t)fio
);
813 EV_SET(&kev
[1], fd
, EVFILT_WRITE
,
814 EV_ADD
|EV_DISABLE
, 0, 0, (intptr_t)fio
);
815 rv
= kevent(pu
->pu_kq
, kev
, 2, NULL
, 0, NULL
);
821 if (what
& PUFFS_FBIO_READ
)
822 fio
->stat
|= FIO_ENABLE_R
;
823 if (what
& PUFFS_FBIO_WRITE
)
824 fio
->stat
|= FIO_ENABLE_W
;
826 LIST_INSERT_HEAD(&pu
->pu_ios
, fio
, fio_entries
);
833 puffs_framev_addfd(struct puffs_usermount
*pu
, int fd
, int what
)
836 return puffs__framev_addfd_ctrl(pu
, fd
, what
,
837 &pu
->pu_framectrl
[PU_FRAMECTRL_USER
]);
841 * XXX: the following en/disable should be coalesced and executed
842 * only during the actual kevent call. So feel free to fix if
843 * threatened by mindblowing boredom.
847 puffs_framev_enablefd(struct puffs_usermount
*pu
, int fd
, int what
)
850 struct puffs_fctrl_io
*fio
;
853 assert((what
& (PUFFS_FBIO_READ
| PUFFS_FBIO_WRITE
)) != 0);
855 fio
= getfiobyfd(pu
, fd
);
861 /* write is enabled in the event loop if there is output */
862 if (what
& PUFFS_FBIO_READ
&& fio
->rwait
== 0) {
863 EV_SET(&kev
, fd
, EVFILT_READ
, EV_ENABLE
, 0, 0, (uintptr_t)fio
);
864 rv
= kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
868 if (what
& PUFFS_FBIO_READ
)
869 fio
->stat
|= FIO_ENABLE_R
;
870 if (what
& PUFFS_FBIO_WRITE
)
871 fio
->stat
|= FIO_ENABLE_W
;
878 puffs_framev_disablefd(struct puffs_usermount
*pu
, int fd
, int what
)
880 struct kevent kev
[2];
881 struct puffs_fctrl_io
*fio
;
885 assert((what
& (PUFFS_FBIO_READ
| PUFFS_FBIO_WRITE
)) != 0);
887 fio
= getfiobyfd(pu
, fd
);
894 if (what
& PUFFS_FBIO_READ
&& fio
->rwait
== 0) {
896 EVFILT_READ
, EV_DISABLE
, 0, 0, (uintptr_t)fio
);
899 if (what
& PUFFS_FBIO_WRITE
&& fio
->stat
& FIO_WR
&& fio
->wwait
== 0) {
901 EVFILT_WRITE
, EV_DISABLE
, 0, 0, (uintptr_t)fio
);
905 rv
= kevent(pu
->pu_kq
, kev
, i
, NULL
, 0, NULL
);
910 if (what
& PUFFS_FBIO_READ
)
911 fio
->stat
&= ~FIO_ENABLE_R
;
912 if (what
& PUFFS_FBIO_WRITE
)
913 fio
->stat
&= ~FIO_ENABLE_W
;
920 puffs__framev_readclose(struct puffs_usermount
*pu
,
921 struct puffs_fctrl_io
*fio
, int error
)
923 struct puffs_framebuf
*pufbuf
;
927 if (fio
->stat
& FIO_RDGONE
|| fio
->stat
& FIO_DEAD
)
929 fio
->stat
|= FIO_RDGONE
;
932 if ((fio
->cur_in
->istat
& ISTAT_DIRECT
) == 0) {
933 puffs_framebuf_destroy(fio
->cur_in
);
936 errnotify(pu
, fio
->cur_in
, error
);
940 while ((pufbuf
= TAILQ_FIRST(&fio
->res_qing
)) != NULL
) {
941 TAILQ_REMOVE(&fio
->res_qing
, pufbuf
, pfb_entries
);
942 errnotify(pu
, pufbuf
, error
);
945 EV_SET(&kev
, fio
->io_fd
, EVFILT_READ
, EV_DELETE
, 0, 0, 0);
946 (void) kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
948 notflag
= PUFFS_FBIO_READ
;
949 if (fio
->stat
& FIO_WRGONE
)
950 notflag
|= PUFFS_FBIO_WRITE
;
952 if (fio
->fctrl
->fdnotfn
)
953 fio
->fctrl
->fdnotfn(pu
, fio
->io_fd
, notflag
);
957 puffs__framev_writeclose(struct puffs_usermount
*pu
,
958 struct puffs_fctrl_io
*fio
, int error
)
960 struct puffs_framebuf
*pufbuf
;
964 if (fio
->stat
& FIO_WRGONE
|| fio
->stat
& FIO_DEAD
)
966 fio
->stat
|= FIO_WRGONE
;
968 while ((pufbuf
= TAILQ_FIRST(&fio
->snd_qing
)) != NULL
) {
969 TAILQ_REMOVE(&fio
->snd_qing
, pufbuf
, pfb_entries
);
970 errnotify(pu
, pufbuf
, error
);
973 EV_SET(&kev
, fio
->io_fd
, EVFILT_WRITE
, EV_DELETE
, 0, 0, 0);
974 (void) kevent(pu
->pu_kq
, &kev
, 1, NULL
, 0, NULL
);
976 notflag
= PUFFS_FBIO_WRITE
;
977 if (fio
->stat
& FIO_RDGONE
)
978 notflag
|= PUFFS_FBIO_READ
;
980 if (fio
->fctrl
->fdnotfn
)
981 fio
->fctrl
->fdnotfn(pu
, fio
->io_fd
, notflag
);
985 removefio(struct puffs_usermount
*pu
, struct puffs_fctrl_io
*fio
, int error
)
987 struct puffs_fbevent
*fbevp
;
989 LIST_REMOVE(fio
, fio_entries
);
990 if (pu
->pu_state
& PU_INLOOP
) {
991 puffs__framev_readclose(pu
, fio
, error
);
992 puffs__framev_writeclose(pu
, fio
, error
);
995 while ((fbevp
= LIST_FIRST(&fio
->ev_qing
)) != NULL
) {
997 LIST_REMOVE(fbevp
, pfe_entries
);
998 puffs__goto(fbevp
->pcc
);
1001 /* don't bother with realloc */
1004 /* don't free us yet, might have some references in event arrays */
1005 fio
->stat
|= FIO_DEAD
;
1006 LIST_INSERT_HEAD(&pu
->pu_ios_rmlist
, fio
, fio_entries
);
1013 puffs_framev_removefd(struct puffs_usermount
*pu
, int fd
, int error
)
1015 struct puffs_fctrl_io
*fio
;
1017 fio
= getfiobyfd(pu
, fd
);
1023 return removefio(pu
, fio
, error
? error
: ECONNRESET
);
1027 puffs_framev_removeonclose(struct puffs_usermount
*pu
, int fd
, int what
)
1030 if (what
== (PUFFS_FBIO_READ
| PUFFS_FBIO_WRITE
))
1031 (void) puffs_framev_removefd(pu
, fd
, ECONNRESET
);
1035 puffs_framev_unmountonclose(struct puffs_usermount
*pu
, int fd
, int what
)
1038 /* XXX & X: unmount is non-sensible */
1039 puffs_framev_removeonclose(pu
, fd
, what
);
1040 if (what
== (PUFFS_FBIO_READ
| PUFFS_FBIO_WRITE
))
1041 PU_SETSTATE(pu
, PUFFS_STATE_UNMOUNTED
);
1045 puffs_framev_init(struct puffs_usermount
*pu
,
1046 puffs_framev_readframe_fn rfb
, puffs_framev_writeframe_fn wfb
,
1047 puffs_framev_cmpframe_fn cmpfb
, puffs_framev_gotframe_fn gotfb
,
1048 puffs_framev_fdnotify_fn fdnotfn
)
1050 struct puffs_framectrl
*pfctrl
;
1052 pfctrl
= &pu
->pu_framectrl
[PU_FRAMECTRL_USER
];
1055 pfctrl
->cmpfb
= cmpfb
;
1056 pfctrl
->gotfb
= gotfb
;
1057 pfctrl
->fdnotfn
= fdnotfn
;
1061 puffs__framev_exit(struct puffs_usermount
*pu
)
1063 struct puffs_fctrl_io
*fio
;
1065 while ((fio
= LIST_FIRST(&pu
->pu_ios
)) != NULL
)
1066 removefio(pu
, fio
, ENXIO
);
1069 /* closing pu->pu_kq takes care of puffsfd */