From owner-svn-src-all@FreeBSD.ORG Sun Nov 2 23:30:51 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 65BDB4B0; Sun, 2 Nov 2014 23:30:51 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 5196731C; Sun, 2 Nov 2014 23:30:51 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sA2NUp8q004714; Sun, 2 Nov 2014 23:30:51 GMT (envelope-from delphij@FreeBSD.org) Received: (from delphij@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sA2NUpr8004713; Sun, 2 Nov 2014 23:30:51 GMT (envelope-from delphij@FreeBSD.org) Message-Id: <201411022330.sA2NUpr8004713@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: delphij set sender to delphij@FreeBSD.org using -f From: Xin LI Date: Sun, 2 Nov 2014 23:30:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r273997 - head/sys/dev/random X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Nov 2014 23:30:51 -0000 Author: delphij Date: Sun Nov 2 23:30:50 2014 New Revision: 273997 URL: https://svnweb.freebsd.org/changeset/base/273997 Log: - 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 Modified: head/sys/dev/random/random_adaptors.c Modified: head/sys/dev/random/random_adaptors.c ============================================================================== --- head/sys/dev/random/random_adaptors.c Sun Nov 2 23:22:22 2014 (r273996) +++ head/sys/dev/random/random_adaptors.c Sun Nov 2 23:30:50 2014 (r273997) @@ -171,9 +171,8 @@ random_adaptor_register(const char *name sx_xlock(&random_adaptors_lock); LIST_INSERT_HEAD(&random_adaptors_list, rra, rra_entries); random_adaptor_choose(); - sx_xunlock(&random_adaptors_lock); - KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); + sx_xunlock(&random_adaptors_lock); } void @@ -182,9 +181,9 @@ random_adaptor_deregister(const char *na struct random_adaptors *rra; KASSERT(name != NULL, ("invalid input to %s", __func__)); - KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); sx_xlock(&random_adaptors_lock); + KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); LIST_FOREACH(rra, &random_adaptors_list, rra_entries) if (strcmp(rra->rra_name, name) == 0) { LIST_REMOVE(rra, rra_entries); @@ -208,23 +207,28 @@ random_adaptor_read(struct cdev *dev __u printf("random: %s %ld\n", __func__, uio->uio_resid); #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); + KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); + /* Let the entropy source do any pre-read setup. */ (random_adaptor->ra_read)(NULL, 0); /* (Un)Blocking logic */ error = 0; - while (!random_adaptor->ra_seeded()) { + while (!random_adaptor->ra_seeded() && error == 0) { if (flags & O_NONBLOCK) { error = EWOULDBLOCK; break; } /* 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. */ (random_adaptor->ra_read)(NULL, 0); @@ -241,12 +245,10 @@ random_adaptor_read(struct cdev *dev __u mtx_unlock(&random_read_rate_mtx); - if (!error) { + if (error == 0) { + nbytes = uio->uio_resid; /* The actual read */ - - random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK); - while (uio->uio_resid && !error) { c = MIN(uio->uio_resid, PAGE_SIZE); (random_adaptor->ra_read)(random_buf, c); @@ -256,11 +258,15 @@ random_adaptor_read(struct cdev *dev __u /* Let the entropy source do any post-read cleanup. */ (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); + free(random_buf, M_ENTROPY); + return (error); } @@ -269,6 +275,8 @@ random_adaptor_read_rate(void) { int ret; + sx_assert(&random_adaptors_lock, SA_LOCKED); + KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); mtx_lock(&random_read_rate_mtx); @@ -287,18 +295,20 @@ random_adaptor_write(struct cdev *dev __ { int c, error = 0; void *random_buf; + ssize_t nbytes; #ifdef RANDOM_DEBUG printf("random: %s %zd\n", __func__, uio->uio_resid); #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); - 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); error = uiomove(random_buf, c, uio); if (error) @@ -306,13 +316,20 @@ random_adaptor_write(struct cdev *dev __ (random_adaptor->ra_write)(random_buf, c); /* 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); + if (nbytes != uio->uio_resid && (error == ERESTART || + error == EINTR) ) + error = 0; /* Partial write, not error. */ + + free(random_buf, M_ENTROPY); + return (error); } @@ -325,10 +342,10 @@ random_adaptor_poll(struct cdev *dev __u printf("random: %s\n", __func__); #endif - KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); - sx_slock(&random_adaptors_lock); + KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); + if (events & (POLLIN | POLLRDNORM)) { if (random_adaptor->ra_seeded()) events &= (POLLIN | POLLRDNORM); @@ -382,9 +399,9 @@ random_sysctl_active_adaptor_handler(SYS struct sbuf sbuf; int error; + sx_slock(&random_adaptors_lock); KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); - sx_slock(&random_adaptors_lock); sbuf_new_for_sysctl(&sbuf, NULL, 16, req); LIST_FOREACH(rra, &random_adaptors_list, rra_entries) if (rra->rra_ra == random_adaptor) { @@ -454,9 +471,9 @@ static void random_adaptors_seed(void *unused __unused) { + sx_slock(&random_adaptors_lock); KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); - sx_slock(&random_adaptors_lock); random_adaptor->ra_reseed(); sx_sunlock(&random_adaptors_lock);