diff options
| author | Jeff Dike <jdike@addtoit.com> | 2008-04-29 01:03:08 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-29 08:06:25 -0700 | 
| commit | 9a6f70bbed4e8b72dd340812d7c606bfd5e00b47 (patch) | |
| tree | 55158b087275b1848b5f0ad4e58eb2a2d47016c8 /drivers/char/random.c | |
| parent | adc782dae6c4c0f6fb679a48a544cfbcd79ae3dc (diff) | |
| download | olio-linux-3.10-9a6f70bbed4e8b72dd340812d7c606bfd5e00b47.tar.xz olio-linux-3.10-9a6f70bbed4e8b72dd340812d7c606bfd5e00b47.zip  | |
random: add async notification support to /dev/random
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 <jdike@linux.intel.com>
Signed-off-by: Matt Mackall <mpm@selenic.com>
Cc: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/random.c')
| -rw-r--r-- | drivers/char/random.c | 24 | 
1 files changed, 22 insertions, 2 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index 2faeef28c20..0cf98bd4f2d 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -370,6 +370,7 @@ 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; @@ -533,8 +534,11 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)  		r->entropy_count = r->poolinfo->POOLBITS;  	/* should we wake readers? */ -	if (r == &input_pool && r->entropy_count >= random_read_wakeup_thresh) +	if (r == &input_pool && +	    r->entropy_count >= random_read_wakeup_thresh) {  		wake_up_interruptible(&random_read_wait); +		kill_fasync(&fasync, SIGIO, POLL_IN); +	}  	spin_unlock_irqrestore(&r->lock, flags);  } @@ -742,8 +746,10 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,  		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", @@ -1100,17 +1106,31 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)  	}  } +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,  	.unlocked_ioctl = random_ioctl, +	.fasync = random_fasync, +	.release = random_release,  };  const struct file_operations urandom_fops = {  	.read  = urandom_read,  	.write = random_write,  	.unlocked_ioctl = random_ioctl, +	.fasync = random_fasync, +	.release = random_release,  };  /***************************************************************  |