2006-03-27 17:14:32 +08:00
|
|
|
/*
|
uml: random driver fixes
The random driver would essentially hang if the host's /dev/random returned
-EAGAIN. There was a test of need_resched followed by a schedule inside the
loop, but that didn't help and it's the wrong way to work anyway.
The right way is to ask for an interrupt when there is input available from
the host and handle it then rather than polling.
Now, when the host's /dev/random returns -EAGAIN, the driver asks for a wakeup
when there's randomness available again and sleeps. The interrupt routine
just wakes up whatever processes are sleeping on host_read_wait.
There is an atomic_t, host_sleep_count, which counts the number of processes
waiting for randomness. When this reaches zero, the interrupt is disabled.
An added complication is that async I/O notification was only recently added
to /dev/random (by me), so essentially all hosts will lack it. So, we use the
sigio workaround here, which is to have a separate thread poll on the
descriptor and send an interrupt when there is input on it. This mechanism is
activated when a process gets -EAGAIN (activating this multiple times is
harmless, if a bit wasteful) and deactivated by the last process still
waiting.
The module name was changed from "random" to "hw_random" in order for udev to
recognize it.
The sigio workaround needed some changes. sigio_broken was added for cases
when we know that async notification doesn't work. This is now called from
maybe_sigio_broken, which deals with pts devices.
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-05-13 05:01:58 +08:00
|
|
|
* Copyright (C) 2002 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
2005-04-17 06:20:36 +08:00
|
|
|
* Licensed under the GPL
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <unistd.h>
|
2008-02-05 14:31:02 +08:00
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <poll.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <pty.h>
|
2008-02-05 14:31:02 +08:00
|
|
|
#include <sched.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <signal.h>
|
|
|
|
#include <string.h>
|
2008-02-05 14:31:02 +08:00
|
|
|
#include "kern_constants.h"
|
2005-04-17 06:20:36 +08:00
|
|
|
#include "kern_util.h"
|
2008-02-05 14:31:02 +08:00
|
|
|
#include "init.h"
|
2005-04-17 06:20:36 +08:00
|
|
|
#include "os.h"
|
uml: random driver fixes
The random driver would essentially hang if the host's /dev/random returned
-EAGAIN. There was a test of need_resched followed by a schedule inside the
loop, but that didn't help and it's the wrong way to work anyway.
The right way is to ask for an interrupt when there is input available from
the host and handle it then rather than polling.
Now, when the host's /dev/random returns -EAGAIN, the driver asks for a wakeup
when there's randomness available again and sleeps. The interrupt routine
just wakes up whatever processes are sleeping on host_read_wait.
There is an atomic_t, host_sleep_count, which counts the number of processes
waiting for randomness. When this reaches zero, the interrupt is disabled.
An added complication is that async I/O notification was only recently added
to /dev/random (by me), so essentially all hosts will lack it. So, we use the
sigio workaround here, which is to have a separate thread poll on the
descriptor and send an interrupt when there is input on it. This mechanism is
activated when a process gets -EAGAIN (activating this multiple times is
harmless, if a bit wasteful) and deactivated by the last process still
waiting.
The module name was changed from "random" to "hw_random" in order for udev to
recognize it.
The sigio workaround needed some changes. sigio_broken was added for cases
when we know that async notification doesn't work. This is now called from
maybe_sigio_broken, which deals with pts devices.
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-05-13 05:01:58 +08:00
|
|
|
#include "process.h"
|
2008-02-05 14:31:02 +08:00
|
|
|
#include "sigio.h"
|
2006-10-20 14:28:20 +08:00
|
|
|
#include "um_malloc.h"
|
2008-02-05 14:31:02 +08:00
|
|
|
#include "user.h"
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
/*
|
|
|
|
* Protected by sigio_lock(), also used by sigio_cleanup, which is an
|
2005-04-17 06:20:36 +08:00
|
|
|
* exitcall.
|
|
|
|
*/
|
|
|
|
static int write_sigio_pid = -1;
|
2007-07-16 14:38:56 +08:00
|
|
|
static unsigned long write_sigio_stack;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
/*
|
|
|
|
* These arrays are initialized before the sigio thread is started, and
|
2005-04-17 06:20:36 +08:00
|
|
|
* the descriptors closed after it is killed. So, it can't see them change.
|
|
|
|
* On the UML side, they are changed under the sigio_lock.
|
|
|
|
*/
|
2006-03-27 17:14:40 +08:00
|
|
|
#define SIGIO_FDS_INIT {-1, -1}
|
|
|
|
|
|
|
|
static int write_sigio_fds[2] = SIGIO_FDS_INIT;
|
|
|
|
static int sigio_private[2] = SIGIO_FDS_INIT;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
struct pollfds {
|
|
|
|
struct pollfd *poll;
|
|
|
|
int size;
|
|
|
|
int used;
|
|
|
|
};
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
/*
|
|
|
|
* Protected by sigio_lock(). Used by the sigio thread, but the UML thread
|
2005-04-17 06:20:36 +08:00
|
|
|
* synchronizes with it.
|
|
|
|
*/
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
static struct pollfds current_poll;
|
|
|
|
static struct pollfds next_poll;
|
|
|
|
static struct pollfds all_sigio_fds;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
static int write_sigio_thread(void *unused)
|
|
|
|
{
|
|
|
|
struct pollfds *fds, tmp;
|
|
|
|
struct pollfd *p;
|
|
|
|
int i, n, respond_fd;
|
|
|
|
char c;
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
signal(SIGWINCH, SIG_IGN);
|
2005-04-17 06:20:36 +08:00
|
|
|
fds = ¤t_poll;
|
2008-02-05 14:31:02 +08:00
|
|
|
while (1) {
|
2005-04-17 06:20:36 +08:00
|
|
|
n = poll(fds->poll, fds->used, -1);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (n < 0) {
|
|
|
|
if (errno == EINTR)
|
|
|
|
continue;
|
|
|
|
printk(UM_KERN_ERR "write_sigio_thread : poll returned "
|
|
|
|
"%d, errno = %d\n", n, errno);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2008-02-05 14:31:02 +08:00
|
|
|
for (i = 0; i < fds->used; i++) {
|
2005-04-17 06:20:36 +08:00
|
|
|
p = &fds->poll[i];
|
2008-02-05 14:31:02 +08:00
|
|
|
if (p->revents == 0)
|
|
|
|
continue;
|
|
|
|
if (p->fd == sigio_private[1]) {
|
2007-05-07 05:51:35 +08:00
|
|
|
CATCH_EINTR(n = read(sigio_private[1], &c,
|
|
|
|
sizeof(c)));
|
2008-02-05 14:31:02 +08:00
|
|
|
if (n != sizeof(c))
|
|
|
|
printk(UM_KERN_ERR
|
|
|
|
"write_sigio_thread : "
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
"read on socket failed, "
|
2007-05-07 05:51:35 +08:00
|
|
|
"err = %d\n", errno);
|
2005-04-17 06:20:36 +08:00
|
|
|
tmp = current_poll;
|
|
|
|
current_poll = next_poll;
|
|
|
|
next_poll = tmp;
|
|
|
|
respond_fd = sigio_private[1];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
respond_fd = write_sigio_fds[1];
|
|
|
|
fds->used--;
|
|
|
|
memmove(&fds->poll[i], &fds->poll[i + 1],
|
|
|
|
(fds->used - i) * sizeof(*fds->poll));
|
|
|
|
}
|
|
|
|
|
2007-05-07 05:51:35 +08:00
|
|
|
CATCH_EINTR(n = write(respond_fd, &c, sizeof(c)));
|
2008-02-05 14:31:02 +08:00
|
|
|
if (n != sizeof(c))
|
|
|
|
printk(UM_KERN_ERR "write_sigio_thread : "
|
|
|
|
"write on socket failed, err = %d\n",
|
|
|
|
errno);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
2006-01-06 16:18:49 +08:00
|
|
|
|
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
static int need_poll(struct pollfds *polls, int n)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
[PATCH] uml: fix 2.6.20 hang
A previous cleanup misused need_poll, which had a fairly broken interface.
It implemented a growable array, changing the used elements count itself,
but leaving it up to the caller to fill in the actual elements, including
the entire array if the array had to be reallocated. This worked because
the previous users were switching between two such structures, and the
elements were copied from the inactive array to the active array after
making sure the active array had enough room.
maybe_sigio_broken was made to use need_poll, but it was operating on a
single array, so when the buffer was reallocated, the previous contents
were lost.
This patch makes need_poll implement more sane semantics. It merely
assures that the array is of the proper size and that the contents are
preserved. It is up to the caller to adjust the used elements count and to
ensure that the proper elements are resent.
This manifested itself as a hang in 2.6.20 as the uninitialized buffer
convinced UML that one of its own file descriptors didn't support SIGIO and
needed to be watched by poll in a separate thread. The result was an
interrupt flood as control traffic over this descriptor sparked interrupts,
which resulted in more control traffic, ad nauseum.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-02-16 17:27:21 +08:00
|
|
|
struct pollfd *new;
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
if (n <= polls->size)
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
return 0;
|
[PATCH] uml: fix 2.6.20 hang
A previous cleanup misused need_poll, which had a fairly broken interface.
It implemented a growable array, changing the used elements count itself,
but leaving it up to the caller to fill in the actual elements, including
the entire array if the array had to be reallocated. This worked because
the previous users were switching between two such structures, and the
elements were copied from the inactive array to the active array after
making sure the active array had enough room.
maybe_sigio_broken was made to use need_poll, but it was operating on a
single array, so when the buffer was reallocated, the previous contents
were lost.
This patch makes need_poll implement more sane semantics. It merely
assures that the array is of the proper size and that the contents are
preserved. It is up to the caller to adjust the used elements count and to
ensure that the proper elements are resent.
This manifested itself as a hang in 2.6.20 as the uninitialized buffer
convinced UML that one of its own file descriptors didn't support SIGIO and
needed to be watched by poll in a separate thread. The result was an
interrupt flood as control traffic over this descriptor sparked interrupts,
which resulted in more control traffic, ad nauseum.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-02-16 17:27:21 +08:00
|
|
|
|
2008-05-13 05:01:52 +08:00
|
|
|
new = uml_kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (new == NULL) {
|
|
|
|
printk(UM_KERN_ERR "need_poll : failed to allocate new "
|
|
|
|
"pollfds\n");
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
return -ENOMEM;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
[PATCH] uml: fix 2.6.20 hang
A previous cleanup misused need_poll, which had a fairly broken interface.
It implemented a growable array, changing the used elements count itself,
but leaving it up to the caller to fill in the actual elements, including
the entire array if the array had to be reallocated. This worked because
the previous users were switching between two such structures, and the
elements were copied from the inactive array to the active array after
making sure the active array had enough room.
maybe_sigio_broken was made to use need_poll, but it was operating on a
single array, so when the buffer was reallocated, the previous contents
were lost.
This patch makes need_poll implement more sane semantics. It merely
assures that the array is of the proper size and that the contents are
preserved. It is up to the caller to adjust the used elements count and to
ensure that the proper elements are resent.
This manifested itself as a hang in 2.6.20 as the uninitialized buffer
convinced UML that one of its own file descriptors didn't support SIGIO and
needed to be watched by poll in a separate thread. The result was an
interrupt flood as control traffic over this descriptor sparked interrupts,
which resulted in more control traffic, ad nauseum.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-02-16 17:27:21 +08:00
|
|
|
|
|
|
|
memcpy(new, polls->poll, polls->used * sizeof(struct pollfd));
|
|
|
|
kfree(polls->poll);
|
|
|
|
|
|
|
|
polls->poll = new;
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
polls->size = n;
|
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
/*
|
|
|
|
* Must be called with sigio_lock held, because it's needed by the marked
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
* critical section.
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
static void update_thread(void)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
int n;
|
|
|
|
char c;
|
|
|
|
|
|
|
|
flags = set_signals(0);
|
2008-02-05 14:31:02 +08:00
|
|
|
CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c)));
|
|
|
|
if (n != sizeof(c)) {
|
|
|
|
printk(UM_KERN_ERR "update_thread : write failed, err = %d\n",
|
|
|
|
errno);
|
2005-04-17 06:20:36 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2007-05-07 05:51:35 +08:00
|
|
|
CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c)));
|
2008-02-05 14:31:02 +08:00
|
|
|
if (n != sizeof(c)) {
|
|
|
|
printk(UM_KERN_ERR "update_thread : read failed, err = %d\n",
|
|
|
|
errno);
|
2005-04-17 06:20:36 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_signals(flags);
|
|
|
|
return;
|
|
|
|
fail:
|
|
|
|
/* Critical section start */
|
2007-07-16 14:38:56 +08:00
|
|
|
if (write_sigio_pid != -1) {
|
2005-04-17 06:20:36 +08:00
|
|
|
os_kill_process(write_sigio_pid, 1);
|
2007-07-16 14:38:56 +08:00
|
|
|
free_stack(write_sigio_stack, 0);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
write_sigio_pid = -1;
|
2006-03-27 17:14:32 +08:00
|
|
|
close(sigio_private[0]);
|
|
|
|
close(sigio_private[1]);
|
|
|
|
close(write_sigio_fds[0]);
|
|
|
|
close(write_sigio_fds[1]);
|
2005-04-17 06:20:36 +08:00
|
|
|
/* Critical section end */
|
|
|
|
set_signals(flags);
|
|
|
|
}
|
|
|
|
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
int add_sigio_fd(int fd)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
struct pollfd *p;
|
|
|
|
int err = 0, i, n;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
sigio_lock();
|
2008-02-05 14:31:02 +08:00
|
|
|
for (i = 0; i < all_sigio_fds.used; i++) {
|
|
|
|
if (all_sigio_fds.poll[i].fd == fd)
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
break;
|
|
|
|
}
|
2008-02-05 14:31:02 +08:00
|
|
|
if (i == all_sigio_fds.used)
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
p = &all_sigio_fds.poll[i];
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
for (i = 0; i < current_poll.used; i++) {
|
|
|
|
if (current_poll.poll[i].fd == fd)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
[PATCH] uml: fix 2.6.20 hang
A previous cleanup misused need_poll, which had a fairly broken interface.
It implemented a growable array, changing the used elements count itself,
but leaving it up to the caller to fill in the actual elements, including
the entire array if the array had to be reallocated. This worked because
the previous users were switching between two such structures, and the
elements were copied from the inactive array to the active array after
making sure the active array had enough room.
maybe_sigio_broken was made to use need_poll, but it was operating on a
single array, so when the buffer was reallocated, the previous contents
were lost.
This patch makes need_poll implement more sane semantics. It merely
assures that the array is of the proper size and that the contents are
preserved. It is up to the caller to adjust the used elements count and to
ensure that the proper elements are resent.
This manifested itself as a hang in 2.6.20 as the uninitialized buffer
convinced UML that one of its own file descriptors didn't support SIGIO and
needed to be watched by poll in a separate thread. The result was an
interrupt flood as control traffic over this descriptor sparked interrupts,
which resulted in more control traffic, ad nauseum.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-02-16 17:27:21 +08:00
|
|
|
n = current_poll.used;
|
|
|
|
err = need_poll(&next_poll, n + 1);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (err)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out;
|
|
|
|
|
[PATCH] uml: fix 2.6.20 hang
A previous cleanup misused need_poll, which had a fairly broken interface.
It implemented a growable array, changing the used elements count itself,
but leaving it up to the caller to fill in the actual elements, including
the entire array if the array had to be reallocated. This worked because
the previous users were switching between two such structures, and the
elements were copied from the inactive array to the active array after
making sure the active array had enough room.
maybe_sigio_broken was made to use need_poll, but it was operating on a
single array, so when the buffer was reallocated, the previous contents
were lost.
This patch makes need_poll implement more sane semantics. It merely
assures that the array is of the proper size and that the contents are
preserved. It is up to the caller to adjust the used elements count and to
ensure that the proper elements are resent.
This manifested itself as a hang in 2.6.20 as the uninitialized buffer
convinced UML that one of its own file descriptors didn't support SIGIO and
needed to be watched by poll in a separate thread. The result was an
interrupt flood as control traffic over this descriptor sparked interrupts,
which resulted in more control traffic, ad nauseum.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-02-16 17:27:21 +08:00
|
|
|
memcpy(next_poll.poll, current_poll.poll,
|
|
|
|
current_poll.used * sizeof(struct pollfd));
|
|
|
|
next_poll.poll[n] = *p;
|
|
|
|
next_poll.used = n + 1;
|
2005-04-17 06:20:36 +08:00
|
|
|
update_thread();
|
|
|
|
out:
|
|
|
|
sigio_unlock();
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
return err;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int ignore_sigio_fd(int fd)
|
|
|
|
{
|
|
|
|
struct pollfd *p;
|
|
|
|
int err = 0, i, n = 0;
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
/*
|
|
|
|
* This is called from exitcalls elsewhere in UML - if
|
2006-07-10 19:45:11 +08:00
|
|
|
* sigio_cleanup has already run, then update_thread will hang
|
|
|
|
* or fail because the thread is no longer running.
|
|
|
|
*/
|
2008-02-05 14:31:02 +08:00
|
|
|
if (write_sigio_pid == -1)
|
2006-07-10 19:45:11 +08:00
|
|
|
return -EIO;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
sigio_lock();
|
2008-02-05 14:31:02 +08:00
|
|
|
for (i = 0; i < current_poll.used; i++) {
|
|
|
|
if (current_poll.poll[i].fd == fd)
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2008-02-05 14:31:02 +08:00
|
|
|
if (i == current_poll.used)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out;
|
2006-03-27 17:14:33 +08:00
|
|
|
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
err = need_poll(&next_poll, current_poll.used - 1);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (err)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out;
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
for (i = 0; i < current_poll.used; i++) {
|
2005-04-17 06:20:36 +08:00
|
|
|
p = ¤t_poll.poll[i];
|
2008-02-05 14:31:02 +08:00
|
|
|
if (p->fd != fd)
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
next_poll.poll[n++] = *p;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
[PATCH] uml: fix 2.6.20 hang
A previous cleanup misused need_poll, which had a fairly broken interface.
It implemented a growable array, changing the used elements count itself,
but leaving it up to the caller to fill in the actual elements, including
the entire array if the array had to be reallocated. This worked because
the previous users were switching between two such structures, and the
elements were copied from the inactive array to the active array after
making sure the active array had enough room.
maybe_sigio_broken was made to use need_poll, but it was operating on a
single array, so when the buffer was reallocated, the previous contents
were lost.
This patch makes need_poll implement more sane semantics. It merely
assures that the array is of the proper size and that the contents are
preserved. It is up to the caller to adjust the used elements count and to
ensure that the proper elements are resent.
This manifested itself as a hang in 2.6.20 as the uninitialized buffer
convinced UML that one of its own file descriptors didn't support SIGIO and
needed to be watched by poll in a separate thread. The result was an
interrupt flood as control traffic over this descriptor sparked interrupts,
which resulted in more control traffic, ad nauseum.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-02-16 17:27:21 +08:00
|
|
|
next_poll.used = current_poll.used - 1;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
update_thread();
|
|
|
|
out:
|
|
|
|
sigio_unlock();
|
2006-07-10 19:45:11 +08:00
|
|
|
return err;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-27 17:14:33 +08:00
|
|
|
static struct pollfd *setup_initial_poll(int fd)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct pollfd *p;
|
|
|
|
|
2008-05-13 05:01:52 +08:00
|
|
|
p = uml_kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL);
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
if (p == NULL) {
|
2008-02-05 14:31:02 +08:00
|
|
|
printk(UM_KERN_ERR "setup_initial_poll : failed to allocate "
|
|
|
|
"poll\n");
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
return NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
*p = ((struct pollfd) { .fd = fd,
|
2005-04-17 06:20:36 +08:00
|
|
|
.events = POLLIN,
|
|
|
|
.revents = 0 });
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
return p;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-07-10 19:45:11 +08:00
|
|
|
static void write_sigio_workaround(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
struct pollfd *p;
|
2005-04-17 06:20:36 +08:00
|
|
|
int err;
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
int l_write_sigio_fds[2];
|
|
|
|
int l_sigio_private[2];
|
|
|
|
int l_write_sigio_pid;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
/* We call this *tons* of times - and most ones we must just fail. */
|
2005-04-17 06:20:36 +08:00
|
|
|
sigio_lock();
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
l_write_sigio_pid = write_sigio_pid;
|
|
|
|
sigio_unlock();
|
2005-04-17 06:20:36 +08:00
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
if (l_write_sigio_pid != -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
err = os_pipe(l_write_sigio_fds, 1, 1);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (err < 0) {
|
|
|
|
printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 1 failed, "
|
2005-04-17 06:20:36 +08:00
|
|
|
"err = %d\n", -err);
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
err = os_pipe(l_sigio_private, 1, 1);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (err < 0) {
|
|
|
|
printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 2 failed, "
|
2005-04-17 06:20:36 +08:00
|
|
|
"err = %d\n", -err);
|
|
|
|
goto out_close1;
|
|
|
|
}
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
|
|
|
|
p = setup_initial_poll(l_sigio_private[1]);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (!p)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out_close2;
|
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
sigio_lock();
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
/*
|
|
|
|
* Did we race? Don't try to optimize this, please, it's not so likely
|
|
|
|
* to happen, and no more than once at the boot.
|
|
|
|
*/
|
|
|
|
if (write_sigio_pid != -1)
|
2006-03-27 17:14:40 +08:00
|
|
|
goto out_free;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-27 17:14:40 +08:00
|
|
|
current_poll = ((struct pollfds) { .poll = p,
|
|
|
|
.used = 1,
|
|
|
|
.size = 1 });
|
2005-04-17 06:20:36 +08:00
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
if (write_sigio_irq(l_write_sigio_fds[0]))
|
2006-03-27 17:14:40 +08:00
|
|
|
goto out_clear_poll;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
|
|
|
|
memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
|
|
|
|
|
2006-03-27 17:14:40 +08:00
|
|
|
write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
|
2007-07-16 14:38:56 +08:00
|
|
|
CLONE_FILES | CLONE_VM,
|
|
|
|
&write_sigio_stack);
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
|
2006-03-27 17:14:40 +08:00
|
|
|
if (write_sigio_pid < 0)
|
|
|
|
goto out_clear;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
sigio_unlock();
|
2006-03-27 17:14:40 +08:00
|
|
|
return;
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
|
2006-03-27 17:14:40 +08:00
|
|
|
out_clear:
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
write_sigio_pid = -1;
|
2006-03-27 17:14:40 +08:00
|
|
|
write_sigio_fds[0] = -1;
|
|
|
|
write_sigio_fds[1] = -1;
|
|
|
|
sigio_private[0] = -1;
|
|
|
|
sigio_private[1] = -1;
|
|
|
|
out_clear_poll:
|
|
|
|
current_poll = ((struct pollfds) { .poll = NULL,
|
|
|
|
.size = 0,
|
|
|
|
.used = 0 });
|
|
|
|
out_free:
|
|
|
|
sigio_unlock();
|
2006-04-11 13:53:36 +08:00
|
|
|
kfree(p);
|
2006-03-27 17:14:40 +08:00
|
|
|
out_close2:
|
2006-03-27 17:14:32 +08:00
|
|
|
close(l_sigio_private[0]);
|
|
|
|
close(l_sigio_private[1]);
|
2006-03-27 17:14:40 +08:00
|
|
|
out_close1:
|
2006-03-27 17:14:32 +08:00
|
|
|
close(l_write_sigio_fds[0]);
|
|
|
|
close(l_write_sigio_fds[1]);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
uml: random driver fixes
The random driver would essentially hang if the host's /dev/random returned
-EAGAIN. There was a test of need_resched followed by a schedule inside the
loop, but that didn't help and it's the wrong way to work anyway.
The right way is to ask for an interrupt when there is input available from
the host and handle it then rather than polling.
Now, when the host's /dev/random returns -EAGAIN, the driver asks for a wakeup
when there's randomness available again and sleeps. The interrupt routine
just wakes up whatever processes are sleeping on host_read_wait.
There is an atomic_t, host_sleep_count, which counts the number of processes
waiting for randomness. When this reaches zero, the interrupt is disabled.
An added complication is that async I/O notification was only recently added
to /dev/random (by me), so essentially all hosts will lack it. So, we use the
sigio workaround here, which is to have a separate thread poll on the
descriptor and send an interrupt when there is input on it. This mechanism is
activated when a process gets -EAGAIN (activating this multiple times is
harmless, if a bit wasteful) and deactivated by the last process still
waiting.
The module name was changed from "random" to "hw_random" in order for udev to
recognize it.
The sigio workaround needed some changes. sigio_broken was added for cases
when we know that async notification doesn't work. This is now called from
maybe_sigio_broken, which deals with pts devices.
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-05-13 05:01:58 +08:00
|
|
|
void sigio_broken(int fd, int read)
|
2006-07-10 19:45:11 +08:00
|
|
|
{
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
int err;
|
|
|
|
|
2006-07-10 19:45:11 +08:00
|
|
|
write_sigio_workaround();
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
|
|
|
|
sigio_lock();
|
|
|
|
err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (err) {
|
|
|
|
printk(UM_KERN_ERR "maybe_sigio_broken - failed to add pollfd "
|
|
|
|
"for descriptor %d\n", fd);
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
goto out;
|
2007-03-01 12:13:11 +08:00
|
|
|
}
|
[PATCH] uml: fix 2.6.20 hang
A previous cleanup misused need_poll, which had a fairly broken interface.
It implemented a growable array, changing the used elements count itself,
but leaving it up to the caller to fill in the actual elements, including
the entire array if the array had to be reallocated. This worked because
the previous users were switching between two such structures, and the
elements were copied from the inactive array to the active array after
making sure the active array had enough room.
maybe_sigio_broken was made to use need_poll, but it was operating on a
single array, so when the buffer was reallocated, the previous contents
were lost.
This patch makes need_poll implement more sane semantics. It merely
assures that the array is of the proper size and that the contents are
preserved. It is up to the caller to adjust the used elements count and to
ensure that the proper elements are resent.
This manifested itself as a hang in 2.6.20 as the uninitialized buffer
convinced UML that one of its own file descriptors didn't support SIGIO and
needed to be watched by poll in a separate thread. The result was an
interrupt flood as control traffic over this descriptor sparked interrupts,
which resulted in more control traffic, ad nauseum.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-02-16 17:27:21 +08:00
|
|
|
|
[PATCH] uml: SIGIO cleanups
- Various cleanups in the sigio code.
- Removed explicit zero-initializations of a few structures.
- Improved some error messages.
- An API change - there was an asymmetry between reactivate_fd calling
maybe_sigio_broken, which goes through all the machinery of figuring out if
a file descriptor supports SIGIO and applying the workaround to it if not,
and deactivate_fd, which just turns off the descriptor.
This is changed so that only activate_fd calls maybe_sigio_broken, when
the descriptor is first seen. reactivate_fd now calls add_sigio_fd, which
is symmetric with ignore_sigio_fd.
This removes a recursion which makes a critical section look more critical
than it really was, obsoleting a big comment to that effect. This requires
keeping track of all descriptors which are getting the SIGIO treatment, not
just the ones being polled at any given moment, so that reactivate_fd,
through add_sigio_fd, doesn't try to tell the SIGIO thread about descriptors
it doesn't care about.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-26 14:33:04 +08:00
|
|
|
all_sigio_fds.poll[all_sigio_fds.used++] =
|
|
|
|
((struct pollfd) { .fd = fd,
|
|
|
|
.events = read ? POLLIN : POLLOUT,
|
|
|
|
.revents = 0 });
|
|
|
|
out:
|
|
|
|
sigio_unlock();
|
2006-07-10 19:45:11 +08:00
|
|
|
}
|
|
|
|
|
uml: random driver fixes
The random driver would essentially hang if the host's /dev/random returned
-EAGAIN. There was a test of need_resched followed by a schedule inside the
loop, but that didn't help and it's the wrong way to work anyway.
The right way is to ask for an interrupt when there is input available from
the host and handle it then rather than polling.
Now, when the host's /dev/random returns -EAGAIN, the driver asks for a wakeup
when there's randomness available again and sleeps. The interrupt routine
just wakes up whatever processes are sleeping on host_read_wait.
There is an atomic_t, host_sleep_count, which counts the number of processes
waiting for randomness. When this reaches zero, the interrupt is disabled.
An added complication is that async I/O notification was only recently added
to /dev/random (by me), so essentially all hosts will lack it. So, we use the
sigio workaround here, which is to have a separate thread poll on the
descriptor and send an interrupt when there is input on it. This mechanism is
activated when a process gets -EAGAIN (activating this multiple times is
harmless, if a bit wasteful) and deactivated by the last process still
waiting.
The module name was changed from "random" to "hw_random" in order for udev to
recognize it.
The sigio workaround needed some changes. sigio_broken was added for cases
when we know that async notification doesn't work. This is now called from
maybe_sigio_broken, which deals with pts devices.
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-05-13 05:01:58 +08:00
|
|
|
/* Changed during early boot */
|
|
|
|
static int pty_output_sigio;
|
|
|
|
static int pty_close_sigio;
|
|
|
|
|
|
|
|
void maybe_sigio_broken(int fd, int read)
|
|
|
|
{
|
|
|
|
if (!isatty(fd))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((read || pty_output_sigio) && (!read || pty_close_sigio))
|
|
|
|
return;
|
|
|
|
|
|
|
|
sigio_broken(fd, read);
|
|
|
|
}
|
|
|
|
|
2006-07-10 19:45:12 +08:00
|
|
|
static void sigio_cleanup(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2007-07-16 14:38:56 +08:00
|
|
|
if (write_sigio_pid == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
os_kill_process(write_sigio_pid, 1);
|
|
|
|
free_stack(write_sigio_stack, 0);
|
|
|
|
write_sigio_pid = -1;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2006-07-10 19:45:12 +08:00
|
|
|
|
|
|
|
__uml_exitcall(sigio_cleanup);
|
2007-05-07 05:51:06 +08:00
|
|
|
|
|
|
|
/* Used as a flag during SIGIO testing early in boot */
|
uml: random driver fixes
The random driver would essentially hang if the host's /dev/random returned
-EAGAIN. There was a test of need_resched followed by a schedule inside the
loop, but that didn't help and it's the wrong way to work anyway.
The right way is to ask for an interrupt when there is input available from
the host and handle it then rather than polling.
Now, when the host's /dev/random returns -EAGAIN, the driver asks for a wakeup
when there's randomness available again and sleeps. The interrupt routine
just wakes up whatever processes are sleeping on host_read_wait.
There is an atomic_t, host_sleep_count, which counts the number of processes
waiting for randomness. When this reaches zero, the interrupt is disabled.
An added complication is that async I/O notification was only recently added
to /dev/random (by me), so essentially all hosts will lack it. So, we use the
sigio workaround here, which is to have a separate thread poll on the
descriptor and send an interrupt when there is input on it. This mechanism is
activated when a process gets -EAGAIN (activating this multiple times is
harmless, if a bit wasteful) and deactivated by the last process still
waiting.
The module name was changed from "random" to "hw_random" in order for udev to
recognize it.
The sigio workaround needed some changes. sigio_broken was added for cases
when we know that async notification doesn't work. This is now called from
maybe_sigio_broken, which deals with pts devices.
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-05-13 05:01:58 +08:00
|
|
|
static int got_sigio;
|
2007-05-07 05:51:06 +08:00
|
|
|
|
|
|
|
static void __init handler(int sig)
|
|
|
|
{
|
|
|
|
got_sigio = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct openpty_arg {
|
|
|
|
int master;
|
|
|
|
int slave;
|
|
|
|
int err;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void openpty_cb(void *arg)
|
|
|
|
{
|
|
|
|
struct openpty_arg *info = arg;
|
|
|
|
|
|
|
|
info->err = 0;
|
2008-02-05 14:31:02 +08:00
|
|
|
if (openpty(&info->master, &info->slave, NULL, NULL, NULL))
|
2007-05-07 05:51:06 +08:00
|
|
|
info->err = -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int async_pty(int master, int slave)
|
|
|
|
{
|
|
|
|
int flags;
|
|
|
|
|
|
|
|
flags = fcntl(master, F_GETFL);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (flags < 0)
|
2007-05-07 05:51:06 +08:00
|
|
|
return -errno;
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
if ((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
|
|
|
|
(fcntl(master, F_SETOWN, os_getpid()) < 0))
|
2007-05-07 05:51:06 +08:00
|
|
|
return -errno;
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
if ((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
|
2007-05-07 05:51:06 +08:00
|
|
|
return -errno;
|
|
|
|
|
2008-02-05 14:30:41 +08:00
|
|
|
return 0;
|
2007-05-07 05:51:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __init check_one_sigio(void (*proc)(int, int))
|
|
|
|
{
|
|
|
|
struct sigaction old, new;
|
|
|
|
struct openpty_arg pty = { .master = -1, .slave = -1 };
|
|
|
|
int master, slave, err;
|
|
|
|
|
|
|
|
initial_thread_cb(openpty_cb, &pty);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (pty.err) {
|
|
|
|
printk(UM_KERN_ERR "check_one_sigio failed, errno = %d\n",
|
|
|
|
-pty.err);
|
2007-05-07 05:51:06 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
master = pty.master;
|
|
|
|
slave = pty.slave;
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
if ((master == -1) || (slave == -1)) {
|
|
|
|
printk(UM_KERN_ERR "check_one_sigio failed to allocate a "
|
|
|
|
"pty\n");
|
2007-05-07 05:51:06 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not now, but complain so we now where we failed. */
|
|
|
|
err = raw(master);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (err < 0) {
|
|
|
|
printk(UM_KERN_ERR "check_one_sigio : raw failed, errno = %d\n",
|
|
|
|
-err);
|
|
|
|
return;
|
|
|
|
}
|
2007-05-07 05:51:06 +08:00
|
|
|
|
|
|
|
err = async_pty(master, slave);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (err < 0) {
|
|
|
|
printk(UM_KERN_ERR "check_one_sigio : sigio_async failed, "
|
|
|
|
"err = %d\n", -err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sigaction(SIGIO, NULL, &old) < 0) {
|
|
|
|
printk(UM_KERN_ERR "check_one_sigio : sigaction 1 failed, "
|
|
|
|
"errno = %d\n", errno);
|
|
|
|
return;
|
|
|
|
}
|
2007-05-07 05:51:06 +08:00
|
|
|
|
|
|
|
new = old;
|
|
|
|
new.sa_handler = handler;
|
2008-02-05 14:31:02 +08:00
|
|
|
if (sigaction(SIGIO, &new, NULL) < 0) {
|
|
|
|
printk(UM_KERN_ERR "check_one_sigio : sigaction 2 failed, "
|
|
|
|
"errno = %d\n", errno);
|
|
|
|
return;
|
|
|
|
}
|
2007-05-07 05:51:06 +08:00
|
|
|
|
|
|
|
got_sigio = 0;
|
|
|
|
(*proc)(master, slave);
|
|
|
|
|
|
|
|
close(master);
|
|
|
|
close(slave);
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
if (sigaction(SIGIO, &old, NULL) < 0)
|
|
|
|
printk(UM_KERN_ERR "check_one_sigio : sigaction 3 failed, "
|
|
|
|
"errno = %d\n", errno);
|
2007-05-07 05:51:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tty_output(int master, int slave)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
char buf[512];
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
printk(UM_KERN_INFO "Checking that host ptys support output SIGIO...");
|
2007-05-07 05:51:06 +08:00
|
|
|
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
while (write(master, buf, sizeof(buf)) > 0) ;
|
|
|
|
if (errno != EAGAIN)
|
|
|
|
printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n",
|
|
|
|
errno);
|
uml: random driver fixes
The random driver would essentially hang if the host's /dev/random returned
-EAGAIN. There was a test of need_resched followed by a schedule inside the
loop, but that didn't help and it's the wrong way to work anyway.
The right way is to ask for an interrupt when there is input available from
the host and handle it then rather than polling.
Now, when the host's /dev/random returns -EAGAIN, the driver asks for a wakeup
when there's randomness available again and sleeps. The interrupt routine
just wakes up whatever processes are sleeping on host_read_wait.
There is an atomic_t, host_sleep_count, which counts the number of processes
waiting for randomness. When this reaches zero, the interrupt is disabled.
An added complication is that async I/O notification was only recently added
to /dev/random (by me), so essentially all hosts will lack it. So, we use the
sigio workaround here, which is to have a separate thread poll on the
descriptor and send an interrupt when there is input on it. This mechanism is
activated when a process gets -EAGAIN (activating this multiple times is
harmless, if a bit wasteful) and deactivated by the last process still
waiting.
The module name was changed from "random" to "hw_random" in order for udev to
recognize it.
The sigio workaround needed some changes. sigio_broken was added for cases
when we know that async notification doesn't work. This is now called from
maybe_sigio_broken, which deals with pts devices.
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-05-13 05:01:58 +08:00
|
|
|
while (((n = read(slave, buf, sizeof(buf))) > 0) &&
|
|
|
|
!({ barrier(); got_sigio; }))
|
2008-02-05 14:31:02 +08:00
|
|
|
;
|
2007-05-07 05:51:06 +08:00
|
|
|
|
2008-02-05 14:31:02 +08:00
|
|
|
if (got_sigio) {
|
|
|
|
printk(UM_KERN_CONT "Yes\n");
|
2007-05-07 05:51:06 +08:00
|
|
|
pty_output_sigio = 1;
|
2008-02-05 14:31:02 +08:00
|
|
|
} else if (n == -EAGAIN)
|
|
|
|
printk(UM_KERN_CONT "No, enabling workaround\n");
|
|
|
|
else
|
|
|
|
printk(UM_KERN_CONT "tty_output : read failed, err = %d\n", n);
|
2007-05-07 05:51:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tty_close(int master, int slave)
|
|
|
|
{
|
2008-02-05 14:31:02 +08:00
|
|
|
printk(UM_KERN_INFO "Checking that host ptys support SIGIO on "
|
|
|
|
"close...");
|
2007-05-07 05:51:06 +08:00
|
|
|
|
|
|
|
close(slave);
|
2008-02-05 14:31:02 +08:00
|
|
|
if (got_sigio) {
|
|
|
|
printk(UM_KERN_CONT "Yes\n");
|
2007-05-07 05:51:06 +08:00
|
|
|
pty_close_sigio = 1;
|
2008-02-05 14:31:02 +08:00
|
|
|
} else
|
|
|
|
printk(UM_KERN_CONT "No, enabling workaround\n");
|
2007-05-07 05:51:06 +08:00
|
|
|
}
|
|
|
|
|
2008-07-24 12:28:49 +08:00
|
|
|
static void __init check_sigio(void)
|
2007-05-07 05:51:06 +08:00
|
|
|
{
|
2008-02-05 14:31:02 +08:00
|
|
|
if ((access("/dev/ptmx", R_OK) < 0) &&
|
|
|
|
(access("/dev/ptyp0", R_OK) < 0)) {
|
|
|
|
printk(UM_KERN_WARNING "No pseudo-terminals available - "
|
|
|
|
"skipping pty SIGIO check\n");
|
2007-05-07 05:51:06 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
check_one_sigio(tty_output);
|
|
|
|
check_one_sigio(tty_close);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Here because it only does the SIGIO testing for now */
|
|
|
|
void __init os_check_bugs(void)
|
|
|
|
{
|
|
|
|
check_sigio();
|
|
|
|
}
|