2008-01-21 18:19:50

by Jeff Dike

[permalink] [raw]
Subject: [PATCH] random - add async I/O support

Add async notification support to /dev/random.

A little test case is below. Without this patch, you get:

$ ./async-random
Drained the pool
Found more randomness

With it, you get:

$ ./async-random
Drained the pool
SIGIO
Found more randomness

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>

static void handler(int sig)
{
printf("SIGIO\n");
}

int main(int argc, char **argv)
{
int fd, n, err, flags;

if(signal(SIGIO, handler) < 0){
perror("setting SIGIO handler");
exit(1);
}

fd = open("/dev/random", O_RDONLY);
if(fd < 0){
perror("open");
exit(1);
}

flags = fcntl(fd, F_GETFL);
if (flags < 0){
perror("getting flags");
exit(1);
}

flags |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, flags) < 0){
perror("setting flags");
exit(1);
}

while((err = read(fd, &n, sizeof(n))) > 0) ;

if(err == 0){
printf("random returned 0\n");
exit(1);
}
else if(errno != EAGAIN){
perror("read");
exit(1);
}

flags |= O_ASYNC;
if (fcntl(fd, F_SETFL, flags) < 0){
perror("setting flags");
exit(1);
}

if (fcntl(fd, F_SETOWN, getpid()) < 0) {
perror("Setting SIGIO");
exit(1);
}

printf("Drained the pool\n");
read(fd, &n, sizeof(n));
printf("Found more randomness\n");

return(0);
}

Signed-off-by: Jeff Dike <[email protected]>
---
drivers/char/random.c | 43 +++++++++++++++++++++++++++++++++----------
1 file changed, 33 insertions(+), 10 deletions(-)

Index: linux-2.6.22/drivers/char/random.c
===================================================================
--- linux-2.6.22.orig/drivers/char/random.c 2008-01-17 12:51:07.000000000 -0500
+++ linux-2.6.22/drivers/char/random.c 2008-01-21 13:02:02.000000000 -0500
@@ -371,6 +371,8 @@ static struct poolinfo {
static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);

+static struct fasync_struct *fasync;
+
#if 0
static int debug = 0;
module_param(debug, bool, 0644);
@@ -751,8 +753,10 @@ static size_t account(struct entropy_sto
else
r->entropy_count = reserved;

- if (r->entropy_count < random_write_wakeup_thresh)
+ if (r->entropy_count < random_write_wakeup_thresh) {
wake_up_interruptible(&random_write_wait);
+ kill_fasync(&fasync, SIGIO, POLL_OUT);
+ }
}

DEBUG_ENT("debiting %d entropy credits from %s%s\n",
@@ -1090,8 +1094,11 @@ random_ioctl(struct inode * inode, struc
* Wake up waiting processes if we have enough
* entropy.
*/
- if (input_pool.entropy_count >= random_read_wakeup_thresh)
+ if (input_pool.entropy_count >= random_read_wakeup_thresh) {
wake_up_interruptible(&random_read_wait);
+ kill_fasync(&fasync, SIGIO, POLL_IN);
+ }
+
return 0;
case RNDADDENTROPY:
if (!capable(CAP_SYS_ADMIN))
@@ -1111,8 +1118,10 @@ random_ioctl(struct inode * inode, struc
* Wake up waiting processes if we have enough
* entropy.
*/
- if (input_pool.entropy_count >= random_read_wakeup_thresh)
+ if (input_pool.entropy_count >= random_read_wakeup_thresh) {
wake_up_interruptible(&random_read_wait);
+ kill_fasync(&fasync, SIGIO, POLL_IN);
+ }
return 0;
case RNDZAPENTCNT:
case RNDCLEARPOOL:
@@ -1128,17 +1137,31 @@ random_ioctl(struct inode * inode, struc
}
}

+static int random_fasync(int fd, struct file *filp, int on)
+{
+ return fasync_helper(fd, filp, on, &fasync);
+}
+
+static int random_release(struct inode *inode, struct file *filp)
+{
+ return fasync_helper(-1, filp, 0, &fasync);
+}
+
const struct file_operations random_fops = {
- .read = random_read,
- .write = random_write,
- .poll = random_poll,
- .ioctl = random_ioctl,
+ .read = random_read,
+ .write = random_write,
+ .poll = random_poll,
+ .ioctl = random_ioctl,
+ .fasync = random_fasync,
+ .release = random_release,
};

const struct file_operations urandom_fops = {
- .read = urandom_read,
- .write = random_write,
- .ioctl = random_ioctl,
+ .read = urandom_read,
+ .write = random_write,
+ .ioctl = random_ioctl,
+ .fasync = random_fasync,
+ .release = random_release,
};

/***************************************************************


2008-01-21 18:44:17

by Matt Mackall

[permalink] [raw]
Subject: Re: [PATCH] random - add async I/O support


On Mon, 2008-01-21 at 13:18 -0500, Jeff Dike wrote:
> Add async notification support to /dev/random.

This conflicts just about everywhere with my latest code, but I'll fix
that up.

--
Mathematics is the supreme nostalgia of our time.

2008-01-21 18:57:01

by Jeff Dike

[permalink] [raw]
Subject: Re: [PATCH] random - add async I/O support

On Mon, Jan 21, 2008 at 12:43:25PM -0600, Matt Mackall wrote:
> This conflicts just about everywhere with my latest code, but I'll fix
> that up.

Great, thanks.

Jeff

--
Work email - jdike at linux dot intel dot com