Subject: Re: struct emul modification
To: None <tech-kern@netbsd.org>
From: Emmanuel Dreyfus <p99dreyf@criens.u-psud.fr>
List: tech-kern
Date: 06/14/2001 21:21:41
Silence before, flame afterwards?
If nobody complain before sunday, I'll commit this...
> Here is the fix I propose to this problem:
> - no more emulation code in sys/kern/uipc_socket2.c
> - fixes both pipes and sockets inconsitencies
> - async I/O state is consistent if the Linux process re-reads it.
>
> The key point is using the socket buffer SB_ASYNC flag in sowakeup() instead
> of using the socket flags SS_ASYNC. It has no bad side effect on my NetBSD
> system, I'd like to be sure it's okay before commiting the code. Is it safe to
> do it like this?
>
> Also, I'd like to do the fix for SunOS emulation, but I need someone to test
> it.
>
> Index: sys_socket.c
> ===================================================================
> RCS file: /cvsroot/syssrc/sys/kern/sys_socket.c,v
> retrieving revision 1.30
> diff -U4 -r1.30 sys_socket.c
> --- sys_socket.c 2001/05/19 17:28:33 1.30
> +++ sys_socket.c 2001/06/11 21:24:21
> @@ -99,14 +99,9 @@
> so->so_state &= ~SS_NBIO;
> return (0);
>
> case FIOASYNC:
> - if (
> -#ifndef __HAVE_MINIMAL_EMUL
> - (!(so->so_state & SS_ISAPIPE) ||
> - (!(p->p_emul->e_flags & EMUL_NO_BSD_ASYNCIO_PIPE))) &&
> -#endif
> - *(int *)data) {
> + if (*(int *)data) {
> so->so_state |= SS_ASYNC;
> so->so_rcv.sb_flags |= SB_ASYNC;
> so->so_snd.sb_flags |= SB_ASYNC;
> } else {
> Index: uipc_socket2.c
> ===================================================================
> RCS file: /cvsroot/syssrc/sys/kern/uipc_socket2.c,v
> retrieving revision 1.38
> diff -U4 -r1.38 uipc_socket2.c
> --- uipc_socket2.c 2001/04/30 03:32:56 1.38
> +++ uipc_socket2.c 2001/06/11 21:24:27
> @@ -289,9 +289,9 @@
>
> /*
> * Wakeup processes waiting on a socket buffer.
> * Do asynchronous notification via SIGIO
> - * if the socket has the SS_ASYNC flag set.
> + * if the socket buffer has the SB_ASYNC flag set.
> */
> void
> sowakeup(struct socket *so, struct sockbuf *sb)
> {
> @@ -302,9 +302,9 @@
> if (sb->sb_flags & SB_WAIT) {
> sb->sb_flags &= ~SB_WAIT;
> wakeup((caddr_t)&sb->sb_cc);
> }
> - if (so->so_state & SS_ASYNC) {
> + if (sb->sb_flags & SB_ASYNC) {
> if (so->so_pgid < 0)
> gsignal(-so->so_pgid, SIGIO);
> else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
> psignal(p, SIGIO);
> Index: proc.h
> ===================================================================
> RCS file: /cvsroot/syssrc/sys/sys/proc.h,v
> retrieving revision 1.130
> diff -U4 -r1.130 proc.h
> --- proc.h 2001/05/19 17:28:33 1.130
> +++ proc.h 2001/06/11 21:26:27
> @@ -122,18 +122,8 @@
> /*
> * Emulation miscelaneous flags
> */
> #define EMUL_HAS_SYS___syscall 0x001 /* Has SYS___syscall */
> -/*
> - * No BSD style async I/O pipes. Aync I/O request through
> - * fcntl() for pipes will be ignored.
> - */
> -#define EMUL_NO_BSD_ASYNCIO_PIPE 0x002
> -/*
> - * No SIGIO fired on read() calls when async I/O is enabled
> - * This is not implemented yet
> - */
> -#define EMUL_NO_SIGIO_ON_READ 0x004
>
> /*
> * Description of a process.
> *
> Index: linux_file.c
> ===================================================================
> RCS file: /cvsroot/syssrc/sys/compat/linux/common/linux_file.c,v
> retrieving revision 1.37
> diff -U4 -r1.37 linux_file.c
> --- linux_file.c 2001/01/22 21:31:37 1.37
> +++ linux_file.c 2001/06/11 21:27:35
> @@ -53,8 +53,9 @@
> #include <sys/mount.h>
> #include <sys/malloc.h>
> #include <sys/vnode.h>
> #include <sys/tty.h>
> +#include <sys/socketvar.h>
> #include <sys/conf.h>
>
> #include <sys/syscallargs.h>
>
> @@ -319,9 +320,61 @@
> val = linux_to_bsd_ioflags((unsigned long)SCARG(uap, arg));
> SCARG(&fca, fd) = fd;
> SCARG(&fca, cmd) = F_SETFL;
> SCARG(&fca, arg) = (caddr_t) val;
> - return sys_fcntl(p, &fca, retval);
> + error = sys_fcntl(p, &fca, retval);
> + /*
> + * Linux does not send a SIGIO to the write end of a socket,
> + * neither it does send any SIGIO for pipes. If async I/O
> + * was requested, we keep the SS_ASYNC iin struct socket flag
> + * set, but we clear SB_ASYNC flags on the sending buffer
> + * (for socket), and on the sending and the receiving buffer
> + * (for pipes).
> + *
> + * Because we do not alter to SS_ASYNC in struct socket,
> + * the Linux process keeps a consistent view of async I/O
> + * status if it attemps to read the async flag (SS_ASYNC)
> + *
> + * This async I/O problem does matters, since some Linux
> + * programs such as the JDK request async I/O on pipes,
> + * but they fail if they happen to get a SIGIO to the write
> + * end of the pipe.
> + */
> + if ((error == 0) && (val & O_ASYNC)) {
> + struct filedesc *fdp;
> + struct file *fp;
> + struct socket *so;
> +
> + fdp = p->p_fd;
> +
> + if ((u_int)fd >= fdp->fd_nfiles ||
> + (fp = fdp->fd_ofiles[fd]) == NULL ||
> + (fp->f_iflags & FIF_WANTCLOSE) != 0)
> + return (EBADF);
> +
> + FILE_USE(fp);
> +
> + if ((fp->f_type == DTYPE_SOCKET) &&
> + (so = (struct socket*)fp->f_data)) {
> + /*
> + * Clear async I/O on sending buffer
> + * This will disable SIGIO for the
> + * write end of sockets and pipes.
> + */
> + so->so_snd.sb_flags &= ~SB_ASYNC;
> + /*
> + * If it's a pipe, also clear
> + * it on the receiving buffer.
> + * This will disable SIGIO for the
> + * read end of pipes.
> + */
> + if (so->so_state & SS_ISAPIPE)
> + so->so_rcv.sb_flags &= ~SB_ASYNC;
> + }
> +
> + FILE_UNUSE(fp, p);
> + }
> + return error;
> case LINUX_F_GETLK:
> sg = stackgap_init(p->p_emul);
> bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
> if ((error = copyin(arg, &lfl, sizeof lfl)))
>
> --
> Emmanuel Dreyfus
> p99dreyf@criens.u-psud.fr
--
Emmanuel Dreyfus
p99dreyf@criens.u-psud.fr