summaryrefslogtreecommitdiff
path: root/sys/compat/linux/common
diff options
context:
space:
mode:
authorjdolecek <jdolecek@NetBSD.org>2001-09-04 20:27:29 +0000
committerjdolecek <jdolecek@NetBSD.org>2001-09-04 20:27:29 +0000
commita065626465b2d062d85d8ffcd52bafcba12bd0b5 (patch)
tree17dbb0084859c04acefd7cc4363754bbf3ca5b1d /sys/compat/linux/common
parent9f971c1da2bb55ed42fa78d063761ac530cebcde (diff)
change LINUX_F_SETFL so that SIGIO handling for sockets
matches more closely add support for NEW_PIPE to the SIGIO hack
Diffstat (limited to 'sys/compat/linux/common')
-rw-r--r--sys/compat/linux/common/linux_file.c89
1 files changed, 43 insertions, 46 deletions
diff --git a/sys/compat/linux/common/linux_file.c b/sys/compat/linux/common/linux_file.c
index 157f51bc1c8..3c336f97d16 100644
--- a/sys/compat/linux/common/linux_file.c
+++ b/sys/compat/linux/common/linux_file.c
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_file.c,v 1.40 2001/07/22 13:34:09 wiz Exp $ */
+/* $NetBSD: linux_file.c,v 1.41 2001/09/04 20:27:29 jdolecek Exp $ */
/*-
* Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
@@ -56,6 +56,7 @@
#include <sys/tty.h>
#include <sys/socketvar.h>
#include <sys/conf.h>
+#include <sys/pipe.h>
#include <sys/syscallargs.h>
@@ -318,63 +319,59 @@ linux_sys_fcntl(p, v, retval)
return error;
retval[0] = bsd_to_linux_ioflags(retval[0]);
return 0;
- case LINUX_F_SETFL:
+ case LINUX_F_SETFL: {
+ struct file *fp = NULL;
+
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;
- 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 in 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)
+ * Linux seems to have same semantics for sending SIGIO to the
+ * read side of socket, but slighly different semantics
+ * for SIGIO to the write side. Rather than sending the SIGIO
+ * every time it's possible to write (directly) more data, it
+ * only sends SIGIO if last write(2) failed due to insufficient
+ * memory to hold the data. This is compatible enough
+ * with NetBSD semantics to not do anything about the
+ * difference.
*
- * 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.
+ * Linux does NOT send SIGIO for pipes. Deal with socketpair
+ * ones and DTYPE_PIPE ones. For these, we don't set
+ * the underlying flags (we don't pass O_ASYNC flag down
+ * to sys_fcntl()), but set the FASYNC flag for file descriptor,
+ * so that F_GETFL would report the ASYNC i/o is on.
*/
- if ((error == 0) && (val & O_ASYNC)) {
- struct filedesc *fdp;
- struct file *fp;
- struct socket *so;
-
- fdp = p->p_fd;
-
- if (((fp = fd_getfile(fdp, fd)) == NULL) ||
- (fp->f_iflags & FIF_WANTCLOSE) != 0)
+ if (val & O_ASYNC) {
+ if (((fp = fd_getfile(p->p_fd, fd)) == NULL))
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;
+ if (((fp->f_type == DTYPE_SOCKET) && fp->f_data
+ && ((struct socket *)fp->f_data)->so_state & SS_ISAPIPE)
+ || (fp->f_type == DTYPE_PIPE))
+ val &= ~O_ASYNC;
+ else {
+ /* not a pipe, do not modify anything */
+ FILE_UNUSE(fp, p);
+ fp = NULL;
}
+ }
+
+ SCARG(&fca, fd) = fd;
+ SCARG(&fca, cmd) = F_SETFL;
+ SCARG(&fca, arg) = (caddr_t) val;
+ error = sys_fcntl(p, &fca, retval);
+
+ /* Now set the FASYNC flag for pipes */
+ if (fp) {
+ if (!error)
+ fp->f_flag |= FASYNC;
FILE_UNUSE(fp, p);
}
- return error;
+
+ return (error);
+ }
case LINUX_F_GETLK:
sg = stackgap_init(p->p_emul);
bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);