- Make sure random_adaptor accesses happen only when
random_adaptors_lock is held. - Use sx_sleep instead of tsleep in read and write path to allow another thread that registers a new random adapter when waiting. Assert that random_adaptor is not NULL after reacquiring the lock. - Capture EINTR/ERESTART from sx_sleep to allow the blocking cycle be stopped when user requests so, while there also make short read/write's return 0. - Move M_WAITOK allocations out of lock scope. In collobration with: kib, markm, ian, jilles Reviewed by: kib, markm Approved by: so
This commit is contained in:
parent
824fc46089
commit
57cd52ca4c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=273997
@ -171,9 +171,8 @@ random_adaptor_register(const char *name, struct random_adaptor *ra)
|
|||||||
sx_xlock(&random_adaptors_lock);
|
sx_xlock(&random_adaptors_lock);
|
||||||
LIST_INSERT_HEAD(&random_adaptors_list, rra, rra_entries);
|
LIST_INSERT_HEAD(&random_adaptors_list, rra, rra_entries);
|
||||||
random_adaptor_choose();
|
random_adaptor_choose();
|
||||||
sx_xunlock(&random_adaptors_lock);
|
|
||||||
|
|
||||||
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
||||||
|
sx_xunlock(&random_adaptors_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -182,9 +181,9 @@ random_adaptor_deregister(const char *name)
|
|||||||
struct random_adaptors *rra;
|
struct random_adaptors *rra;
|
||||||
|
|
||||||
KASSERT(name != NULL, ("invalid input to %s", __func__));
|
KASSERT(name != NULL, ("invalid input to %s", __func__));
|
||||||
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
|
||||||
|
|
||||||
sx_xlock(&random_adaptors_lock);
|
sx_xlock(&random_adaptors_lock);
|
||||||
|
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
||||||
LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
|
LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
|
||||||
if (strcmp(rra->rra_name, name) == 0) {
|
if (strcmp(rra->rra_name, name) == 0) {
|
||||||
LIST_REMOVE(rra, rra_entries);
|
LIST_REMOVE(rra, rra_entries);
|
||||||
@ -208,23 +207,28 @@ random_adaptor_read(struct cdev *dev __unused, struct uio *uio, int flags)
|
|||||||
printf("random: %s %ld\n", __func__, uio->uio_resid);
|
printf("random: %s %ld\n", __func__, uio->uio_resid);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
|
||||||
|
|
||||||
sx_slock(&random_adaptors_lock);
|
sx_slock(&random_adaptors_lock);
|
||||||
|
|
||||||
|
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
||||||
|
|
||||||
/* Let the entropy source do any pre-read setup. */
|
/* Let the entropy source do any pre-read setup. */
|
||||||
(random_adaptor->ra_read)(NULL, 0);
|
(random_adaptor->ra_read)(NULL, 0);
|
||||||
|
|
||||||
/* (Un)Blocking logic */
|
/* (Un)Blocking logic */
|
||||||
error = 0;
|
error = 0;
|
||||||
while (!random_adaptor->ra_seeded()) {
|
while (!random_adaptor->ra_seeded() && error == 0) {
|
||||||
if (flags & O_NONBLOCK) {
|
if (flags & O_NONBLOCK) {
|
||||||
error = EWOULDBLOCK;
|
error = EWOULDBLOCK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sleep instead of going into a spin-frenzy */
|
/* Sleep instead of going into a spin-frenzy */
|
||||||
tsleep(&random_adaptor, PUSER | PCATCH, "block", hz/10);
|
error = sx_sleep(&random_adaptor, &random_adaptors_lock,
|
||||||
|
PUSER | PCATCH, "randrd", hz/10);
|
||||||
|
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s",
|
||||||
|
__func__));
|
||||||
|
|
||||||
/* keep tapping away at the pre-read until we seed/unblock. */
|
/* keep tapping away at the pre-read until we seed/unblock. */
|
||||||
(random_adaptor->ra_read)(NULL, 0);
|
(random_adaptor->ra_read)(NULL, 0);
|
||||||
@ -241,12 +245,10 @@ random_adaptor_read(struct cdev *dev __unused, struct uio *uio, int flags)
|
|||||||
|
|
||||||
mtx_unlock(&random_read_rate_mtx);
|
mtx_unlock(&random_read_rate_mtx);
|
||||||
|
|
||||||
if (!error) {
|
if (error == 0) {
|
||||||
|
nbytes = uio->uio_resid;
|
||||||
|
|
||||||
/* The actual read */
|
/* The actual read */
|
||||||
|
|
||||||
random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
|
|
||||||
|
|
||||||
while (uio->uio_resid && !error) {
|
while (uio->uio_resid && !error) {
|
||||||
c = MIN(uio->uio_resid, PAGE_SIZE);
|
c = MIN(uio->uio_resid, PAGE_SIZE);
|
||||||
(random_adaptor->ra_read)(random_buf, c);
|
(random_adaptor->ra_read)(random_buf, c);
|
||||||
@ -256,11 +258,15 @@ random_adaptor_read(struct cdev *dev __unused, struct uio *uio, int flags)
|
|||||||
/* Let the entropy source do any post-read cleanup. */
|
/* Let the entropy source do any post-read cleanup. */
|
||||||
(random_adaptor->ra_read)(NULL, 1);
|
(random_adaptor->ra_read)(NULL, 1);
|
||||||
|
|
||||||
free(random_buf, M_ENTROPY);
|
if (nbytes != uio->uio_resid && (error == ERESTART ||
|
||||||
}
|
error == EINTR) )
|
||||||
|
error = 0; /* Return partial read, not error. */
|
||||||
|
|
||||||
|
}
|
||||||
sx_sunlock(&random_adaptors_lock);
|
sx_sunlock(&random_adaptors_lock);
|
||||||
|
|
||||||
|
free(random_buf, M_ENTROPY);
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,6 +275,8 @@ random_adaptor_read_rate(void)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
sx_assert(&random_adaptors_lock, SA_LOCKED);
|
||||||
|
|
||||||
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
||||||
|
|
||||||
mtx_lock(&random_read_rate_mtx);
|
mtx_lock(&random_read_rate_mtx);
|
||||||
@ -287,18 +295,20 @@ random_adaptor_write(struct cdev *dev __unused, struct uio *uio, int flags __unu
|
|||||||
{
|
{
|
||||||
int c, error = 0;
|
int c, error = 0;
|
||||||
void *random_buf;
|
void *random_buf;
|
||||||
|
ssize_t nbytes;
|
||||||
|
|
||||||
#ifdef RANDOM_DEBUG
|
#ifdef RANDOM_DEBUG
|
||||||
printf("random: %s %zd\n", __func__, uio->uio_resid);
|
printf("random: %s %zd\n", __func__, uio->uio_resid);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
|
||||||
|
|
||||||
sx_slock(&random_adaptors_lock);
|
sx_slock(&random_adaptors_lock);
|
||||||
|
|
||||||
random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
|
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
||||||
|
|
||||||
while (uio->uio_resid > 0) {
|
nbytes = uio->uio_resid;
|
||||||
|
while (uio->uio_resid > 0 && error == 0) {
|
||||||
c = MIN(uio->uio_resid, PAGE_SIZE);
|
c = MIN(uio->uio_resid, PAGE_SIZE);
|
||||||
error = uiomove(random_buf, c, uio);
|
error = uiomove(random_buf, c, uio);
|
||||||
if (error)
|
if (error)
|
||||||
@ -306,13 +316,20 @@ random_adaptor_write(struct cdev *dev __unused, struct uio *uio, int flags __unu
|
|||||||
(random_adaptor->ra_write)(random_buf, c);
|
(random_adaptor->ra_write)(random_buf, c);
|
||||||
|
|
||||||
/* Introduce an annoying delay to stop swamping */
|
/* Introduce an annoying delay to stop swamping */
|
||||||
tsleep(&random_adaptor, PUSER | PCATCH, "block", hz/10);
|
error = sx_sleep(&random_adaptor, &random_adaptors_lock,
|
||||||
|
PUSER | PCATCH, "randwr", hz/10);
|
||||||
|
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s",
|
||||||
|
__func__));
|
||||||
}
|
}
|
||||||
|
|
||||||
free(random_buf, M_ENTROPY);
|
|
||||||
|
|
||||||
sx_sunlock(&random_adaptors_lock);
|
sx_sunlock(&random_adaptors_lock);
|
||||||
|
|
||||||
|
if (nbytes != uio->uio_resid && (error == ERESTART ||
|
||||||
|
error == EINTR) )
|
||||||
|
error = 0; /* Partial write, not error. */
|
||||||
|
|
||||||
|
free(random_buf, M_ENTROPY);
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,10 +342,10 @@ random_adaptor_poll(struct cdev *dev __unused, int events, struct thread *td __u
|
|||||||
printf("random: %s\n", __func__);
|
printf("random: %s\n", __func__);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
|
||||||
|
|
||||||
sx_slock(&random_adaptors_lock);
|
sx_slock(&random_adaptors_lock);
|
||||||
|
|
||||||
|
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
||||||
|
|
||||||
if (events & (POLLIN | POLLRDNORM)) {
|
if (events & (POLLIN | POLLRDNORM)) {
|
||||||
if (random_adaptor->ra_seeded())
|
if (random_adaptor->ra_seeded())
|
||||||
events &= (POLLIN | POLLRDNORM);
|
events &= (POLLIN | POLLRDNORM);
|
||||||
@ -382,9 +399,9 @@ random_sysctl_active_adaptor_handler(SYSCTL_HANDLER_ARGS)
|
|||||||
struct sbuf sbuf;
|
struct sbuf sbuf;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
sx_slock(&random_adaptors_lock);
|
||||||
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
||||||
|
|
||||||
sx_slock(&random_adaptors_lock);
|
|
||||||
sbuf_new_for_sysctl(&sbuf, NULL, 16, req);
|
sbuf_new_for_sysctl(&sbuf, NULL, 16, req);
|
||||||
LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
|
LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
|
||||||
if (rra->rra_ra == random_adaptor) {
|
if (rra->rra_ra == random_adaptor) {
|
||||||
@ -454,9 +471,9 @@ static void
|
|||||||
random_adaptors_seed(void *unused __unused)
|
random_adaptors_seed(void *unused __unused)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
sx_slock(&random_adaptors_lock);
|
||||||
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
|
||||||
|
|
||||||
sx_slock(&random_adaptors_lock);
|
|
||||||
random_adaptor->ra_reseed();
|
random_adaptor->ra_reseed();
|
||||||
sx_sunlock(&random_adaptors_lock);
|
sx_sunlock(&random_adaptors_lock);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user