#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/interrupt.h>
+#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/percpu.h>
#include <linux/cryptohash.h>
*/
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;
/*
* This function adds bytes into the entropy "pool". It does not
* update the entropy estimate. The caller should call
- * credit_entropy_store if this is appropriate.
+ * credit_entropy_bits if this is appropriate.
*
* The pool is stirred with a primitive polynomial of the appropriate
* degree, and then twisted. We twist by three bits at a time because
/*
* Credit (or debit) the entropy store with n bits of entropy
*/
-static void credit_entropy_store(struct entropy_store *r, int nbits)
+static void credit_entropy_bits(struct entropy_store *r, int nbits)
{
unsigned long flags;
+ if (!nbits)
+ return;
+
spin_lock_irqsave(&r->lock, flags);
- if (r->entropy_count + nbits < 0) {
- DEBUG_ENT("negative entropy/overflow (%d+%d)\n",
- r->entropy_count, nbits);
+ DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
+ r->entropy_count += nbits;
+ if (r->entropy_count < 0) {
+ DEBUG_ENT("negative entropy/overflow\n");
r->entropy_count = 0;
- } else if (r->entropy_count + nbits > r->poolinfo->POOLBITS) {
+ } else if (r->entropy_count > r->poolinfo->POOLBITS)
r->entropy_count = r->poolinfo->POOLBITS;
- } else {
- r->entropy_count += nbits;
- if (nbits)
- DEBUG_ENT("added %d entropy credits to %s\n",
- nbits, r->name);
- }
/* 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);
}
* Round down by 1 bit on general principles,
* and limit entropy entimate to 12 bits.
*/
- credit_entropy_store(&input_pool,
- min_t(int, fls(delta>>1), 11));
+ credit_entropy_bits(&input_pool,
+ min_t(int, fls(delta>>1), 11));
}
out:
preempt_enable();
bytes = extract_entropy(r->pull, tmp, bytes,
random_read_wakeup_thresh / 8, rsvd);
mix_pool_bytes(r, tmp, bytes);
- credit_entropy_store(r, bytes*8);
+ credit_entropy_bits(r, bytes*8);
}
}
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",
return -EPERM;
if (get_user(ent_count, p))
return -EFAULT;
- credit_entropy_store(&input_pool, ent_count);
+ credit_entropy_bits(&input_pool, ent_count);
return 0;
case RNDADDENTROPY:
if (!capable(CAP_SYS_ADMIN))
size);
if (retval < 0)
return retval;
- credit_entropy_store(&input_pool, ent_count);
+ credit_entropy_bits(&input_pool, ent_count);
return 0;
case RNDZAPENTCNT:
case RNDCLEARPOOL:
}
}
+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,
};
/***************************************************************