random - add async I/O support
PATCH 1/1 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(-)
drivers/char/random.c +33 -10
@@ -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_stoelse 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, };/***************************************************************
Quoted 1 line · Jeff Dike
Add async notification support to
/dev/random.
This conflicts just about everywhere with my latest code, but I'll fix that up.
Signature · 1 line
Mathematics is the supreme nostalgia of our time.
Quoted 2 lines · Matt Mackall
This conflicts just about everywhere with my latest code, but I'll fix that up.
Great, thanks.
Jeff
Signature · 1 line
Work email - jdike at linux dot intel dot com