diff -urN linux-2.6.15.6-bs3-tls/arch/um/drivers/mconsole_kern.c linux-2.6.15.6-bs3-tls-stream/arch/um/drivers/mconsole_kern.c --- linux-2.6.15.6-bs3-tls/arch/um/drivers/mconsole_kern.c 2006-04-25 20:26:57.000000000 -0700 +++ linux-2.6.15.6-bs3-tls-stream/arch/um/drivers/mconsole_kern.c 2006-04-25 20:51:21.000000000 -0700 @@ -72,16 +72,30 @@ DECLARE_WORK(mconsole_work, mc_work_proc, NULL); +static int mconsole_listen_sock = 0; +static char *notify_socket = NULL; + static irqreturn_t mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) { /* long to avoid size mismatch warnings from gcc */ long fd; + int err; struct mconsole_entry *new; struct mc_request req; fd = (long) dev_id; - while (mconsole_get_request(fd, &req)){ + while ((err = mconsole_get_request(fd, &req)) >= 0) { + /* if we got back and end-of-file, close off this client */ + if (err == 0) { + free_irq_later(MCONSOLE_CLIENT_IRQ, (void *)fd); + close(fd); + return(IRQ_HANDLED); + } + + /* if there is no valid command, don't chase it down */ + if (! req.cmd) continue; + if(req.cmd->context == MCONSOLE_INTR) (*req.cmd->handler)(&req); else { @@ -96,7 +110,37 @@ } if(!list_empty(&mc_requests)) schedule_work(&mconsole_work); - reactivate_fd(fd, MCONSOLE_IRQ); + reactivate_fd(fd, MCONSOLE_CLIENT_IRQ); + return(IRQ_HANDLED); +} + +void mconsole_accept_task_proc(void *unused) +{ + int fd; + unsigned long flags; + + local_save_flags(flags); + + while ((fd = os_accept_unix_stream_socket(mconsole_listen_sock)) >= 0) { + if (um_request_irq(MCONSOLE_CLIENT_IRQ, fd, IRQ_READ, mconsole_interrupt, + SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, + "mconsole", (void *)fd)) { + printk(KERN_ERR "mconsole_accept_task_proc: failed to get IRQ for client %d\n",fd); + local_irq_restore(flags); + return; + } + } + + reactivate_fd(mconsole_listen_sock, MCONSOLE_IRQ); + + local_irq_restore(flags); +} + +DECLARE_WORK(mconsole_accept_task, mconsole_accept_task_proc, NULL); + +static irqreturn_t mconsole_accept_interrupt(int irq, void *data, struct pt_regs *regs) +{ + schedule_work(&mconsole_accept_task); return(IRQ_HANDLED); } @@ -563,29 +607,34 @@ /* Changed by mconsole_setup, which is __setup, and called before SMP is * active. */ -static char *notify_socket = NULL; +//static char *notify_socket = NULL; int mconsole_init(void) { /* long to avoid size mismatch warnings from gcc */ - long sock; +// long sock; int err; char file[256]; if(umid_file_name("mconsole", file, sizeof(file))) return(-1); snprintf(mconsole_socket_name, sizeof(file), "%s", file); - sock = os_create_unix_socket(file, sizeof(file), 1); - if (sock < 0){ +// sock = os_create_unix_socket(file, sizeof(file), 1); +// if (sock < 0){ + mconsole_listen_sock = os_create_unix_stream_socket(file, sizeof(file), 1); + if (mconsole_listen_sock < 0){ printk("Failed to initialize management console\n"); return(1); } register_reboot_notifier(&reboot_notifier); - err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, +// err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, +// SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, +// "mconsole", (void *)sock); + err = um_request_irq(MCONSOLE_IRQ, mconsole_listen_sock, IRQ_READ, mconsole_accept_interrupt, SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, - "mconsole", (void *)sock); + "mconsole", (void *)mconsole_listen_sock); if (err){ printk("Failed to get IRQ for management console\n"); return(1); diff -urN linux-2.6.15.6-bs3-tls/arch/um/drivers/mconsole_user.c linux-2.6.15.6-bs3-tls-stream/arch/um/drivers/mconsole_user.c --- linux-2.6.15.6-bs3-tls/arch/um/drivers/mconsole_user.c 2006-04-25 20:26:57.000000000 -0700 +++ linux-2.6.15.6-bs3-tls-stream/arch/um/drivers/mconsole_user.c 2006-04-25 20:28:30.000000000 -0700 @@ -84,10 +84,14 @@ int len; req->originlen = sizeof(req->origin); - req->len = recvfrom(fd, &req->request, sizeof(req->request), 0, - (struct sockaddr *) req->origin, &req->originlen); - if (req->len < 0) +// req->len = recvfrom(fd, &req->request, sizeof(req->request), 0, +// (struct sockaddr *) req->origin, &req->originlen); + req->len = read(fd, &req->request, sizeof(req->request)); + + if (req->len == 0) return 0; + else if (req->len < 0) + return -1; req->originating_fd = fd; @@ -151,8 +155,9 @@ len = sizeof(reply) + reply.len - sizeof(reply.data); - n = sendto(req->originating_fd, &reply, len, 0, - (struct sockaddr *) req->origin, req->originlen); +// n = sendto(req->originating_fd, &reply, len, 0, +// (struct sockaddr *) req->origin, req->originlen); + n = write(req->originating_fd, &reply, len); if(n < 0) return(-errno); } while(total > 0); diff -urN linux-2.6.15.6-bs3-tls/arch/um/include/os.h linux-2.6.15.6-bs3-tls-stream/arch/um/include/os.h --- linux-2.6.15.6-bs3-tls/arch/um/include/os.h 2006-04-25 20:26:57.000000000 -0700 +++ linux-2.6.15.6-bs3-tls-stream/arch/um/include/os.h 2006-04-25 20:28:30.000000000 -0700 @@ -146,6 +146,8 @@ extern int os_set_fd_block(int fd, int blocking); extern int os_accept_connection(int fd); extern int os_create_unix_socket(char *file, int len, int close_on_exec); +extern int os_create_unix_stream_socket(char *file, int len, int close_on_exec); +extern int os_accept_unix_stream_socket(int fd); extern int os_shutdown_socket(int fd, int r, int w); extern void os_close_file(int fd); extern int os_rcv_fd(int fd, int *helper_pid_out); diff -urN linux-2.6.15.6-bs3-tls/arch/um/os-Linux/file.c linux-2.6.15.6-bs3-tls-stream/arch/um/os-Linux/file.c --- linux-2.6.15.6-bs3-tls/arch/um/os-Linux/file.c 2006-01-02 19:21:10.000000000 -0800 +++ linux-2.6.15.6-bs3-tls-stream/arch/um/os-Linux/file.c 2006-04-25 20:28:30.000000000 -0700 @@ -617,6 +617,55 @@ return(sock); } +int os_create_unix_stream_socket(char *file, int len, int close_on_exec) +{ + struct sockaddr_un addr; + int sock, err; + + sock = socket(PF_UNIX, SOCK_STREAM, 0); + if (sock < 0){ + printk("create_unix_socket - socket failed, errno = %d\n", + errno); + return(-errno); + } + + if(close_on_exec) { + err = os_set_exec_close(sock, 1); + if(err < 0) + printk("create_unix_socket : close_on_exec failed, " + "err = %d", -err); + } + + addr.sun_family = AF_UNIX; + + /* XXX Be more careful about overflow */ + snprintf(addr.sun_path, len, "%s", file); + + err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); + if (err < 0){ + printk("create_listening_socket at '%s' - bind failed, " + "errno = %d\n", file, errno); + return(-errno); + } + + listen(sock, 1); + + return(sock); +} + +int os_accept_unix_stream_socket(int fd) +{ + int newfd; + + /* accept the new client */ + newfd = accept(fd,NULL,NULL); + + /* we have to make it non-blocking here */ + fcntl(newfd,F_SETFL,O_NONBLOCK); + + return newfd; +} + void os_flush_stdout(void) { fflush(stdout); diff -urN linux-2.6.15.6-bs3-tls/include/asm-um/irq.h linux-2.6.15.6-bs3-tls-stream/include/asm-um/irq.h --- linux-2.6.15.6-bs3-tls/include/asm-um/irq.h 2006-01-02 19:21:10.000000000 -0800 +++ linux-2.6.15.6-bs3-tls-stream/include/asm-um/irq.h 2006-04-25 20:28:30.000000000 -0700 @@ -15,8 +15,9 @@ #define SIGIO_WRITE_IRQ 11 #define TELNETD_IRQ 12 #define XTERM_IRQ 13 +#define MCONSOLE_CLIENT_IRQ 14 -#define LAST_IRQ XTERM_IRQ +#define LAST_IRQ MCONSOLE_CLIENT_IRQ #define NR_IRQS (LAST_IRQ + 1) #endif