2 * Copyright (c) 2006 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $DragonFly: src/sys/kern/kern_syslink.c,v 1.8 2007/04/16 17:40:13 dillon Exp $
37 * This module implements the syslink() system call and protocol which
38 * is used to glue clusters together as well as to interface userland
39 * devices and filesystems to the kernel.
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/malloc.h>
46 #include <sys/alist.h>
51 #include <sys/thread.h>
53 #include <sys/sysctl.h>
54 #include <sys/sysproto.h>
55 #include <sys/syslink.h>
56 #include <sys/syslink_msg.h>
58 #include <sys/thread2.h>
61 * Red-Black trees organizing the syslink 'router' nodes and connections
67 RB_HEAD(slrouter_rb_tree
, slrouter
);
68 RB_HEAD(sldata_rb_tree
, sldata
);
69 RB_PROTOTYPE2(slrouter_rb_tree
, slrouter
, rbnode
,
70 rb_slrouter_compare
, sysid_t
);
71 RB_PROTOTYPE2(sldata_rb_tree
, sldata
, rbnode
,
72 rb_sldata_compare
, int);
75 RB_ENTRY(slrouter
) rbnode
; /* list of routers */
76 struct sldata_rb_tree sldata_rb_root
; /* connections to router */
77 sysid_t sysid
; /* logical sysid of router */
78 int flags
; /* flags passed on create */
79 int bits
; /* accomodate connections */
80 int count
; /* number of connections */
83 char label
[SYSLINK_LABEL_SIZE
];
87 * fileops interface. slbuf and sldata are also used in conjunction with a
88 * normal file descriptor.
92 int bufsize
; /* must be a power of 2 */
93 int bufmask
; /* (bufsize - 1) */
94 int rindex
; /* tail-chasing FIFO indices */
99 RB_ENTRY(sldata
) rbnode
;
100 struct slrouter
*router
; /* organizing router */
103 struct file
*xfp
; /* external file pointer */
104 struct lock rlock
; /* synchronizing lock */
105 struct lock wlock
; /* synchronizing lock */
106 struct thread
*rthread
; /* xfp -> rbuf & process */
107 struct thread
*wthread
; /* wbuf -> xfp */
108 int flags
; /* connection flags */
112 char label
[SYSLINK_LABEL_SIZE
];
116 * syslink kernel thread support flags
118 #define SLF_RQUIT 0x0001
119 #define SLF_WQUIT 0x0002
120 #define SLF_RDONE 0x0004
121 #define SLF_WDONE 0x0008
122 #define SLF_DESTROYED 0x8000
124 #define SYSLINK_BUFSIZE (128*1024)
126 static int rb_slrouter_compare(struct slrouter
*r1
, struct slrouter
*r2
);
127 static int rb_sldata_compare(struct sldata
*d1
, struct sldata
*d2
);
129 static int syslink_destroy(struct slrouter
*slrouter
);
130 static int syslink_add(struct slrouter
*slrouter
, int fd
,
131 struct syslink_info
*info
, int *result
);
132 static int syslink_rem(struct slrouter
*slrouter
, struct sldata
*sldata
,
133 struct syslink_info
*info
);
135 static int syslink_read(struct file
*fp
, struct uio
*uio
,
136 struct ucred
*cred
, int flags
);
137 static int syslink_write(struct file
*fp
, struct uio
*uio
,
138 struct ucred
*cred
, int flags
);
139 static int syslink_close(struct file
*fp
);
140 static int syslink_stat(struct file
*fp
, struct stat
*sb
, struct ucred
*cred
);
141 static int syslink_shutdown(struct file
*fp
, int how
);
142 static int syslink_ioctl(struct file
*fp
, u_long cmd
, caddr_t data
,
144 static int syslink_poll(struct file
*fp
, int events
, struct ucred
*cred
);
145 static int syslink_kqfilter(struct file
*fp
, struct knote
*kn
);
147 static void syslink_rthread(void *arg
);
148 static void syslink_wthread(void *arg
);
149 static void slbuf_alloc(struct slbuf
*buf
, int bytes
);
150 static void slbuf_free(struct slbuf
*buf
);
151 static void sldata_rels(struct sldata
*sldata
);
152 static void slrouter_rels(struct slrouter
*slrouter
);
153 static int process_syslink_msg(struct sldata
*sldata
, struct syslink_msg
*head
);
154 static int syslink_validate(struct syslink_msg
*head
, int bytes
);
156 RB_GENERATE2(slrouter_rb_tree
, slrouter
, rbnode
,
157 rb_slrouter_compare
, sysid_t
, sysid
);
158 RB_GENERATE2(sldata_rb_tree
, sldata
, rbnode
,
159 rb_sldata_compare
, int, linkid
);
161 static struct fileops syslinkops
= {
162 .fo_read
= syslink_read
,
163 .fo_write
= syslink_write
,
164 .fo_ioctl
= syslink_ioctl
,
165 .fo_poll
= syslink_poll
,
166 .fo_kqfilter
= syslink_kqfilter
,
167 .fo_stat
= syslink_stat
,
168 .fo_close
= syslink_close
,
169 .fo_shutdown
= syslink_shutdown
172 MALLOC_DEFINE(M_SYSLINK
, "syslink", "syslink manager");
174 static int syslink_enabled
;
175 SYSCTL_INT(_kern
, OID_AUTO
, syslink_enabled
,
176 CTLFLAG_RW
, &syslink_enabled
, 0, "Enable SYSLINK");
179 * Support declarations and compare function for our RB trees
181 static struct slrouter_rb_tree slrouter_rb_root
;
184 rb_slrouter_compare(struct slrouter
*r1
, struct slrouter
*r2
)
186 if (r1
->sysid
< r2
->sysid
)
188 if (r1
->sysid
> r2
->sysid
)
194 rb_sldata_compare(struct sldata
*d1
, struct sldata
*d2
)
196 if (d1
->linkid
< d2
->linkid
)
198 if (d1
->linkid
> d2
->linkid
)
204 * Compare and callback functions for first-sysid and first-linkid searches.
207 syslink_cmd_locate_cmp(struct slrouter
*slrouter
, void *data
)
209 struct syslink_info
*info
= data
;
211 if (slrouter
->sysid
< info
->sysid
)
213 if (slrouter
->sysid
> info
->sysid
)
219 syslink_cmd_locate_callback(struct slrouter
*slrouter
, void *data
)
221 struct syslink_info
*info
= data
;
223 info
->flags
= slrouter
->flags
; /* also clears SLIF_ERROR */
224 bcopy(slrouter
->label
, info
->label
, SYSLINK_LABEL_SIZE
);
230 syslink_cmd_find_cmp(struct sldata
*sldata
, void *data
)
232 struct syslink_info
*info
= data
;
234 if (sldata
->linkid
< info
->linkid
)
236 if (sldata
->linkid
> info
->linkid
)
242 syslink_cmd_find_callback(struct sldata
*sldata
, void *data
)
244 struct syslink_info
*info
= data
;
246 info
->linkid
= sldata
->linkid
;
247 info
->flags
= sldata
->flags
; /* also clears SLIF_ERROR */
248 bcopy(sldata
->label
, info
->label
, SYSLINK_LABEL_SIZE
);
254 * Primary system call interface - associate a full-duplex stream
255 * (typically a pipe or a connected socket) with a sysid namespace,
256 * or create a direct link.
258 * syslink(int fd, int cmd, void *info, size_t *infosize)
261 sys_syslink(struct syslink_args
*uap
)
263 struct syslink_info info
;
264 struct slrouter
*slrouter
= NULL
;
265 struct sldata
*sldata
= NULL
;
270 * System call is under construction and disabled by default.
271 * Superuser access is also required.
273 if (syslink_enabled
== 0)
275 error
= suser(curthread
);
280 * Load and validate the info structure. Unloaded bytes are zerod out
282 bzero(&info
, sizeof(info
));
283 if ((unsigned)uap
->bytes
<= sizeof(info
)) {
285 error
= copyin(uap
->info
, &info
, uap
->bytes
);
292 if (info
.label
[sizeof(info
.label
)-1] != 0)
300 case SYSLINK_CMD_CREATE
:
302 * Create a new syslink router node. Set refs to prevent the
303 * router node from being destroyed. One ref is our temporary
304 * reference while the other is the SLIF_DESTROYED-interlocked
307 if (info
.bits
< 2 || info
.bits
> SYSLINK_ROUTER_MAXBITS
)
309 slrouter
= kmalloc(sizeof(struct slrouter
), M_SYSLINK
,
311 if (slrouter_rb_tree_RB_LOOKUP(&slrouter_rb_root
, info
.sysid
)) {
312 kfree(slrouter
, M_SYSLINK
);
316 slrouter
->sysid
= info
.sysid
;
318 slrouter
->bits
= info
.bits
;
319 slrouter
->flags
= info
.flags
& SLIF_USERFLAGS
;
320 slrouter
->bitmap
= alist_create(1 << info
.bits
, M_SYSLINK
);
321 RB_INIT(&slrouter
->sldata_rb_root
);
322 RB_INSERT(slrouter_rb_tree
, &slrouter_rb_root
, slrouter
);
324 case SYSLINK_CMD_DESTROY
:
326 * Destroy a syslink router node. The physical node is
327 * not freed until our temporary reference is removed.
329 slrouter
= slrouter_rb_tree_RB_LOOKUP(&slrouter_rb_root
,
333 if ((slrouter
->flags
& SLIF_DESTROYED
) == 0) {
334 slrouter
->flags
|= SLIF_DESTROYED
;
335 /* SLIF_DESTROYED interlock */
336 slrouter_rels(slrouter
);
337 error
= syslink_destroy(slrouter
);
338 /* still holding our private interlock */
342 case SYSLINK_CMD_LOCATE
:
344 * Locate the first syslink router node >= info.sysid
346 info
.flags
|= SLIF_ERROR
;
347 n
= slrouter_rb_tree_RB_SCAN(
349 syslink_cmd_locate_cmp
, syslink_cmd_locate_callback
,
351 if (info
.flags
& SLIF_ERROR
)
354 case SYSLINK_CMD_ADD
:
355 slrouter
= slrouter_rb_tree_RB_LOOKUP(&slrouter_rb_root
, info
.sysid
);
357 (info
.bits
< 2 || info
.bits
> SYSLINK_ROUTER_MAXBITS
)) {
359 } else if (slrouter
&& (slrouter
->flags
& SLIF_DESTROYED
)) {
361 * Someone is trying to destroy this route node,
362 * no new adds please!
365 } else if (slrouter
) {
367 error
= syslink_add(slrouter
, uap
->fd
, &info
,
368 &uap
->sysmsg_result
);
373 case SYSLINK_CMD_REM
:
374 slrouter
= slrouter_rb_tree_RB_LOOKUP(&slrouter_rb_root
,
378 sldata
= sldata_rb_tree_RB_LOOKUP(&slrouter
->sldata_rb_root
, info
.linkid
);
381 error
= syslink_rem(slrouter
, sldata
, &info
);
389 case SYSLINK_CMD_FIND
:
390 slrouter
= slrouter_rb_tree_RB_LOOKUP(&slrouter_rb_root
, info
.sysid
);
391 info
.flags
|= SLIF_ERROR
;
394 n
= sldata_rb_tree_RB_SCAN(
395 &slrouter
->sldata_rb_root
,
396 syslink_cmd_find_cmp
, syslink_cmd_find_callback
,
398 if (info
.flags
& SLIF_ERROR
)
415 slrouter_rels(slrouter
);
421 syslink_destroy_callback(struct sldata
*sldata
, void *data __unused
)
424 if ((sldata
->flags
& SLF_RQUIT
) == 0) {
425 sldata
->flags
|= SLF_RQUIT
;
426 wakeup(&sldata
->rbuf
);
428 if ((sldata
->flags
& SLF_WQUIT
) == 0) {
429 sldata
->flags
|= SLF_WQUIT
;
430 wakeup(&sldata
->wbuf
);
437 * Shutdown all the connections going into this syslink.
439 * Try to wait for completion, but return after 1 second
444 syslink_destroy(struct slrouter
*slrouter
)
448 while (!RB_EMPTY(&slrouter
->sldata_rb_root
) && retries
) {
449 RB_SCAN(sldata_rb_tree
, &slrouter
->sldata_rb_root
, NULL
,
450 syslink_destroy_callback
, slrouter
);
452 tsleep(&retries
, 0, "syslnk", hz
/ 10);
454 if (RB_EMPTY(&slrouter
->sldata_rb_root
))
462 syslink_add(struct slrouter
*slrouter
, int fd
, struct syslink_info
*info
,
465 struct sldata
*sldata
;
473 maxphys
= 1 << slrouter
->bits
;
474 numphys
= info
->bits
? (1 << info
->bits
) : 1;
477 * Create a connection to the route node and allocate a physical ID.
478 * Physical ID 0 is reserved for the route node itself, and an all-1's
479 * ID is reserved as a broadcast address.
481 sldata
= kmalloc(sizeof(struct sldata
), M_SYSLINK
, M_WAITOK
|M_ZERO
);
483 linkid
= alist_alloc(slrouter
->bitmap
, numphys
);
484 if (linkid
== ALIST_BLOCK_NONE
) {
485 kfree(sldata
, M_SYSLINK
);
490 * Insert the node, initializing enough fields to prevent things from
491 * being ripped out from under us before we have a chance to complete
494 sldata
->linkid
= linkid
;
497 if (sldata_rb_tree_RB_LOOKUP(&slrouter
->sldata_rb_root
, linkid
))
498 panic("syslink_add: free linkid wasn't free!");
499 RB_INSERT(sldata_rb_tree
, &slrouter
->sldata_rb_root
, sldata
);
502 * Complete initialization of the physical route node. Setting
503 * sldata->router activates the node.
505 lockinit(&sldata
->rlock
, "slread", 0, 0);
506 lockinit(&sldata
->wlock
, "slwrite", 0, 0);
510 * We create a direct syslink descriptor. Only the
511 * reader thread is needed.
513 error
= falloc(curproc
, &fp
, &fd
);
515 fp
->f_type
= DTYPE_SYSLINK
;
516 fp
->f_flag
= FREAD
| FWRITE
;
517 fp
->f_ops
= &syslinkops
;
519 slbuf_alloc(&sldata
->rbuf
, SYSLINK_BUFSIZE
);
520 slbuf_alloc(&sldata
->wbuf
, SYSLINK_BUFSIZE
);
521 /* two refs: reader thread and fp descriptor */
523 sldata
->flags
= SLF_WQUIT
| SLF_WDONE
;
524 lwkt_create(syslink_rthread
, sldata
,
525 &sldata
->rthread
, NULL
,
527 fsetfd(curproc
, fp
, fd
);
532 sldata
->xfp
= holdfp(curproc
->p_fd
, fd
, -1);
533 if (sldata
->xfp
!= NULL
) {
534 slbuf_alloc(&sldata
->rbuf
, SYSLINK_BUFSIZE
);
535 slbuf_alloc(&sldata
->wbuf
, SYSLINK_BUFSIZE
);
536 /* two refs: reader thread and writer thread */
538 lwkt_create(syslink_rthread
, sldata
,
539 &sldata
->rthread
, NULL
,
541 lwkt_create(syslink_wthread
, sldata
,
542 &sldata
->wthread
, NULL
,
548 sldata
->router
= slrouter
;
555 syslink_rem(struct slrouter
*slrouter
, struct sldata
*sldata
,
556 struct syslink_info
*info
)
558 int error
= EINPROGRESS
;
560 if ((sldata
->flags
& SLF_RQUIT
) == 0) {
561 sldata
->flags
|= SLF_RQUIT
;
562 wakeup(&sldata
->rbuf
);
565 if ((sldata
->flags
& SLF_WQUIT
) == 0) {
566 sldata
->flags
|= SLF_WQUIT
;
567 wakeup(&sldata
->wbuf
);
574 * This thread reads from an external descriptor into rbuf, then parses and
575 * dispatches syslink messages from rbuf.
579 syslink_rthread(void *arg
)
581 struct sldata
*sldata
= arg
;
582 struct slbuf
*slbuf
= &sldata
->rbuf
;
583 struct syslink_msg
*head
;
584 const int min_msg_size
= SL_MIN_MESSAGE_SIZE
;
586 while ((sldata
->flags
& SLF_RQUIT
) == 0) {
592 * Calculate contiguous space available to read and read as
595 * If the entire buffer is used there's probably a format
596 * error of some sort and we terminate the link.
598 used
= slbuf
->windex
- slbuf
->rindex
;
602 * Read some data, terminate the link if an error occurs or
603 * if EOF is encountered. xfp can be NULL, indicating that
604 * the data was injected by other means.
607 count
= slbuf
->bufsize
-
608 (slbuf
->windex
& slbuf
->bufmask
);
609 if (count
> slbuf
->bufsize
- used
)
610 count
= slbuf
->bufsize
- used
;
613 error
= fp_read(sldata
->xfp
,
615 (slbuf
->windex
& slbuf
->bufmask
),
616 count
, &count
, 0, UIO_SYSSPACE
);
621 slbuf
->windex
+= count
;
624 tsleep(slbuf
, 0, "fiford", 0);
628 * Process as many syslink messages as we can. The record
629 * length must be at least a minimal PAD record (8 bytes).
631 while (slbuf
->windex
- slbuf
->rindex
>= min_msg_size
) {
634 head
= (void *)(slbuf
->buf
+
635 (slbuf
->rindex
& slbuf
->bufmask
));
636 if (head
->sm_bytes
< min_msg_size
) {
640 aligned_reclen
= SLMSG_ALIGN(head
->sm_bytes
);
645 if ((slbuf
->rindex
& slbuf
->bufmask
) >
646 ((slbuf
->rindex
+ aligned_reclen
) & slbuf
->bufmask
)
653 * Insufficient data read
655 if (slbuf
->windex
- slbuf
->rindex
< aligned_reclen
)
659 * Process non-pad messages. Non-pad messages have
660 * to be at least the size of the syslink_msg
663 * A PAD message's sm_cmd field contains 0.
666 if (head
->sm_bytes
< sizeof(*head
)) {
670 error
= process_syslink_msg(sldata
, head
);
675 slbuf
->rindex
+= aligned_reclen
;
682 * Mark us as done and deref sldata. Tell the writer to terminate as
685 sldata
->flags
|= SLF_RDONE
;
686 if ((sldata
->flags
& SLF_WDONE
) == 0) {
687 sldata
->flags
|= SLF_WQUIT
;
688 wakeup(&sldata
->wbuf
);
690 wakeup(&sldata
->rbuf
);
691 wakeup(&sldata
->wbuf
);
696 * This thread takes outgoing syslink messages queued to wbuf and writes them
697 * to the descriptor. PAD is stripped. PAD is also added as required to
698 * conform to the outgoing descriptor's buffering requirements.
702 syslink_wthread(void *arg
)
704 struct sldata
*sldata
= arg
;
705 struct slbuf
*slbuf
= &sldata
->wbuf
;
706 struct syslink_msg
*head
;
709 while ((sldata
->flags
& SLF_WQUIT
) == 0) {
716 used
= slbuf
->windex
- slbuf
->rindex
;
717 if (used
< SL_MIN_MESSAGE_SIZE
)
720 head
= (void *)(slbuf
->buf
+
721 (slbuf
->rindex
& slbuf
->bufmask
));
722 if (head
->sm_bytes
< SL_MIN_MESSAGE_SIZE
) {
726 aligned_reclen
= SLMSG_ALIGN(head
->sm_bytes
);
731 if ((slbuf
->rindex
& slbuf
->bufmask
) >
732 ((slbuf
->rindex
+ aligned_reclen
) & slbuf
->bufmask
)
739 * Insufficient data read
741 if (used
< aligned_reclen
)
745 * Write it out whether it is PAD or not.
746 * XXX re-PAD for output here.
748 error
= fp_write(sldata
->xfp
, head
,
752 if (error
&& error
!= ENOBUFS
)
754 if (count
!= aligned_reclen
) {
758 slbuf
->rindex
+= aligned_reclen
;
762 tsleep(slbuf
, 0, "fifowt", 0);
764 sldata
->flags
|= SLF_WDONE
;
770 slbuf_alloc(struct slbuf
*slbuf
, int bytes
)
772 bzero(slbuf
, sizeof(*slbuf
));
773 slbuf
->buf
= kmalloc(bytes
, M_SYSLINK
, M_WAITOK
);
774 slbuf
->bufsize
= bytes
;
775 slbuf
->bufmask
= bytes
- 1;
780 slbuf_free(struct slbuf
*slbuf
)
782 kfree(slbuf
->buf
, M_SYSLINK
);
788 sldata_rels(struct sldata
*sldata
)
790 struct slrouter
*slrouter
;
792 if (--sldata
->refs
== 0) {
793 slrouter
= sldata
->router
;
794 KKASSERT(slrouter
!= NULL
);
796 RB_REMOVE(sldata_rb_tree
,
797 &sldata
->router
->sldata_rb_root
, sldata
);
798 sldata
->router
= NULL
;
799 slbuf_free(&sldata
->rbuf
);
800 slbuf_free(&sldata
->wbuf
);
801 kfree(sldata
, M_SYSLINK
);
802 slrouter_rels(slrouter
);
808 slrouter_rels(struct slrouter
*slrouter
)
810 if (--slrouter
->refs
== 0 && RB_EMPTY(&slrouter
->sldata_rb_root
)) {
811 KKASSERT(slrouter
->flags
& SLIF_DESTROYED
);
812 RB_REMOVE(slrouter_rb_tree
, &slrouter_rb_root
, slrouter
);
813 alist_destroy(slrouter
->bitmap
, M_SYSLINK
);
814 slrouter
->bitmap
= NULL
;
815 kfree(slrouter
, M_SYSLINK
);
820 * fileops for an established syslink when the kernel is asked to create a
821 * descriptor (verses one being handed to it). No threads are created in
826 * Transfer zero or more messages from the kernel to userland. Only complete
827 * messages are returned. If the uio has insufficient space then EMSGSIZE
828 * is returned. The kernel feeds messages to wbuf so we use wlock (structures
829 * are relative to the kernel).
833 syslink_read(struct file
*fp
, struct uio
*uio
, struct ucred
*cred
, int flags
)
835 struct sldata
*sldata
= fp
->f_data
;
836 struct slbuf
*slbuf
= &sldata
->wbuf
;
837 struct syslink_msg
*head
;
843 if (flags
& O_FBLOCKING
)
845 else if (flags
& O_FNONBLOCKING
)
847 else if (fp
->f_flag
& O_NONBLOCK
)
852 lockmgr(&sldata
->wlock
, LK_EXCLUSIVE
| LK_RETRY
);
855 * Calculate the number of bytes we can transfer in one shot. Transfers
856 * do not wrap the FIFO.
858 contig
= slbuf
->bufsize
- (slbuf
->rindex
& slbuf
->bufmask
);
860 bytes
= slbuf
->windex
- slbuf
->rindex
;
863 if (sldata
->flags
& SLF_RDONE
) {
871 tsleep(slbuf
, 0, "fiford", 0);
877 * The uio must be able to accomodate the transfer.
879 if (uio
->uio_resid
< bytes
) {
885 * Copy the data to userland and update rindex.
887 head
= (void *)(slbuf
->buf
+ (slbuf
->rindex
& slbuf
->bufmask
));
888 error
= uiomove((caddr_t
)head
, bytes
, uio
);
890 slbuf
->rindex
+= bytes
;
896 lockmgr(&sldata
->wlock
, LK_RELEASE
);
901 * Transfer zero or more messages from userland to the kernel. Only complete
902 * messages may be written. The kernel processes from rbuf so that is where
903 * we have to copy the messages.
907 syslink_write (struct file
*fp
, struct uio
*uio
, struct ucred
*cred
, int flags
)
909 struct sldata
*sldata
= fp
->f_data
;
910 struct slbuf
*slbuf
= &sldata
->rbuf
;
911 struct syslink_msg
*head
;
917 if (flags
& O_FBLOCKING
)
919 else if (flags
& O_FNONBLOCKING
)
921 else if (fp
->f_flag
& O_NONBLOCK
)
926 lockmgr(&sldata
->rlock
, LK_EXCLUSIVE
| LK_RETRY
);
929 * Calculate the maximum number of contiguous bytes that may be
930 * available. Caller is required to not wrap our FIFO.
932 contig
= slbuf
->bufsize
- (slbuf
->windex
& slbuf
->bufmask
);
933 if (uio
->uio_resid
> contig
) {
939 * Truncate based on actual unused space available in the FIFO. If
940 * the uio does not fit, block and loop.
943 bytes
= slbuf
->bufsize
- (slbuf
->windex
- slbuf
->rindex
);
946 if (uio
->uio_resid
<= bytes
)
948 if (sldata
->flags
& SLF_RDONE
) {
956 tsleep(slbuf
, 0, "fifowr", 0);
958 bytes
= uio
->uio_resid
;
959 head
= (void *)(slbuf
->buf
+ (slbuf
->windex
& slbuf
->bufmask
));
960 error
= uiomove((caddr_t
)head
, bytes
, uio
);
962 error
= syslink_validate(head
, bytes
);
964 slbuf
->windex
+= bytes
;
968 lockmgr(&sldata
->rlock
, LK_RELEASE
);
974 syslink_close (struct file
*fp
)
976 struct sldata
*sldata
;
979 if ((sldata
->flags
& SLF_RQUIT
) == 0) {
980 sldata
->flags
|= SLF_RQUIT
;
981 wakeup(&sldata
->rbuf
);
983 if ((sldata
->flags
& SLF_WQUIT
) == 0) {
984 sldata
->flags
|= SLF_WQUIT
;
985 wakeup(&sldata
->wbuf
);
994 syslink_stat (struct file
*fp
, struct stat
*sb
, struct ucred
*cred
)
1001 syslink_shutdown (struct file
*fp
, int how
)
1008 syslink_ioctl (struct file
*fp
, u_long cmd
, caddr_t data
, struct ucred
*cred
)
1015 syslink_poll (struct file
*fp
, int events
, struct ucred
*cred
)
1022 syslink_kqfilter(struct file
*fp
, struct knote
*kn
)
1028 * This routine is called from a route node's reader thread to process a
1029 * syslink message once it has been completely read and its size validated.
1033 process_syslink_msg(struct sldata
*sldata
, struct syslink_msg
*head
)
1035 kprintf("process syslink msg %08x\n", head
->sm_cmd
);
1040 * Validate that the syslink message header(s) are correctly sized.
1044 syslink_validate(struct syslink_msg
*head
, int bytes
)
1046 const int min_msg_size
= SL_MIN_MESSAGE_SIZE
;
1051 * Message size and alignment
1053 if (bytes
< min_msg_size
)
1055 if (bytes
& SL_ALIGNMASK
)
1057 if (head
->sm_cmd
&& bytes
< sizeof(struct syslink_msg
))
1061 * Buffer must contain entire record
1063 aligned_reclen
= SLMSG_ALIGN(head
->sm_bytes
);
1064 if (bytes
< aligned_reclen
)
1066 bytes
-= aligned_reclen
;
1067 head
= (void *)((char *)head
+ aligned_reclen
);