From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Greg KH <gregkh@linuxfoundation.org>,
torvalds@linux-foundation.org, akpm@linux-foundation.org,
alan@lxorguk.ukuu.org.uk, "Theodore Tso" <tytso@mit.edu>
Subject: [ 31/65] random: use lockless techniques in the interrupt path
Date: Mon, 13 Aug 2012 15:14:15 -0700 [thread overview]
Message-ID: <20120813221417.702230387@linuxfoundation.org> (raw)
In-Reply-To: <20120813221414.965154048@linuxfoundation.org>
From: Greg KH <gregkh@linuxfoundation.org>
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <tytso@mit.edu>
commit 902c098a3663de3fa18639efbb71b6080f0bcd3c upstream.
The real-time Linux folks don't like add_interrupt_randomness() taking
a spinlock since it is called in the low-level interrupt routine.
This also allows us to reduce the overhead in the fast path, for the
random driver, which is the interrupt collection path.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/char/random.c | 78 +++++++++++++++++++++++++-------------------------
1 file changed, 39 insertions(+), 39 deletions(-)
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -418,9 +418,9 @@ struct entropy_store {
/* read-write data: */
spinlock_t lock;
unsigned add_ptr;
+ unsigned input_rotate;
int entropy_count;
int entropy_total;
- int input_rotate;
unsigned int initialized:1;
__u8 last_data[EXTRACT_SIZE];
};
@@ -468,26 +468,24 @@ static __u32 const twist_table[8] = {
* it's cheap to do so and helps slightly in the expected case where
* the entropy is concentrated in the low-order bits.
*/
-static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
- int nbytes, __u8 out[64])
+static void __mix_pool_bytes(struct entropy_store *r, const void *in,
+ int nbytes, __u8 out[64])
{
unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
int input_rotate;
int wordmask = r->poolinfo->poolwords - 1;
const char *bytes = in;
__u32 w;
- unsigned long flags;
- /* Taps are constant, so we can load them without holding r->lock. */
tap1 = r->poolinfo->tap1;
tap2 = r->poolinfo->tap2;
tap3 = r->poolinfo->tap3;
tap4 = r->poolinfo->tap4;
tap5 = r->poolinfo->tap5;
- spin_lock_irqsave(&r->lock, flags);
- input_rotate = r->input_rotate;
- i = r->add_ptr;
+ smp_rmb();
+ input_rotate = ACCESS_ONCE(r->input_rotate);
+ i = ACCESS_ONCE(r->add_ptr);
/* mix one byte at a time to simplify size handling and churn faster */
while (nbytes--) {
@@ -514,19 +512,23 @@ static void mix_pool_bytes_extract(struc
input_rotate += i ? 7 : 14;
}
- r->input_rotate = input_rotate;
- r->add_ptr = i;
+ ACCESS_ONCE(r->input_rotate) = input_rotate;
+ ACCESS_ONCE(r->add_ptr) = i;
+ smp_wmb();
if (out)
for (j = 0; j < 16; j++)
((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
-
- spin_unlock_irqrestore(&r->lock, flags);
}
-static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
+static void mix_pool_bytes(struct entropy_store *r, const void *in,
+ int nbytes, __u8 out[64])
{
- mix_pool_bytes_extract(r, in, bytes, NULL);
+ unsigned long flags;
+
+ spin_lock_irqsave(&r->lock, flags);
+ __mix_pool_bytes(r, in, nbytes, out);
+ spin_unlock_irqrestore(&r->lock, flags);
}
struct fast_pool {
@@ -564,23 +566,22 @@ static void fast_mix(struct fast_pool *f
*/
static void credit_entropy_bits(struct entropy_store *r, int nbits)
{
- unsigned long flags;
- int entropy_count;
+ int entropy_count, orig;
if (!nbits)
return;
- spin_lock_irqsave(&r->lock, flags);
-
DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
- entropy_count = r->entropy_count;
+retry:
+ entropy_count = orig = ACCESS_ONCE(r->entropy_count);
entropy_count += nbits;
if (entropy_count < 0) {
DEBUG_ENT("negative entropy/overflow\n");
entropy_count = 0;
} else if (entropy_count > r->poolinfo->POOLBITS)
entropy_count = r->poolinfo->POOLBITS;
- r->entropy_count = entropy_count;
+ if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+ goto retry;
if (!r->initialized && nbits > 0) {
r->entropy_total += nbits;
@@ -593,7 +594,6 @@ static void credit_entropy_bits(struct e
wake_up_interruptible(&random_read_wait);
kill_fasync(&fasync, SIGIO, POLL_IN);
}
- spin_unlock_irqrestore(&r->lock, flags);
}
/*********************************************************************
@@ -680,7 +680,7 @@ static void add_timer_randomness(struct
sample.cycles = get_cycles();
sample.num = num;
- mix_pool_bytes(&input_pool, &sample, sizeof(sample));
+ mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
/*
* Calculate number of bits of randomness we probably added.
@@ -764,7 +764,7 @@ void add_interrupt_randomness(int irq, i
fast_pool->last = now;
r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
- mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
+ __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
/*
* If we don't have a valid cycle counter, and we see
* back-to-back timer interrupts, then skip giving credit for
@@ -829,7 +829,7 @@ static void xfer_secondary_pool(struct e
bytes = extract_entropy(r->pull, tmp, bytes,
random_read_wakeup_thresh / 8, rsvd);
- mix_pool_bytes(r, tmp, bytes);
+ mix_pool_bytes(r, tmp, bytes, NULL);
credit_entropy_bits(r, bytes*8);
}
}
@@ -890,9 +890,11 @@ static void extract_buf(struct entropy_s
int i;
__u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
__u8 extract[64];
+ unsigned long flags;
/* Generate a hash across the pool, 16 words (512 bits) at a time */
sha_init(hash);
+ spin_lock_irqsave(&r->lock, flags);
for (i = 0; i < r->poolinfo->poolwords; i += 16)
sha_transform(hash, (__u8 *)(r->pool + i), workspace);
@@ -905,7 +907,8 @@ static void extract_buf(struct entropy_s
* brute-forcing the feedback as hard as brute-forcing the
* hash.
*/
- mix_pool_bytes_extract(r, hash, sizeof(hash), extract);
+ __mix_pool_bytes(r, hash, sizeof(hash), extract);
+ spin_unlock_irqrestore(&r->lock, flags);
/*
* To avoid duplicates, we atomically extract a portion of the
@@ -928,11 +931,10 @@ static void extract_buf(struct entropy_s
}
static ssize_t extract_entropy(struct entropy_store *r, void *buf,
- size_t nbytes, int min, int reserved)
+ size_t nbytes, int min, int reserved)
{
ssize_t ret = 0, i;
__u8 tmp[EXTRACT_SIZE];
- unsigned long flags;
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, min, reserved);
@@ -941,6 +943,8 @@ static ssize_t extract_entropy(struct en
extract_buf(r, tmp);
if (fips_enabled) {
+ unsigned long flags;
+
spin_lock_irqsave(&r->lock, flags);
if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
panic("Hardware RNG duplicated output!\n");
@@ -1034,22 +1038,18 @@ EXPORT_SYMBOL(get_random_bytes);
static void init_std_data(struct entropy_store *r)
{
int i;
- ktime_t now;
- unsigned long flags;
+ ktime_t now = ktime_get_real();
+ unsigned long rv;
- spin_lock_irqsave(&r->lock, flags);
r->entropy_count = 0;
r->entropy_total = 0;
- spin_unlock_irqrestore(&r->lock, flags);
-
- now = ktime_get_real();
- mix_pool_bytes(r, &now, sizeof(now));
- for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) {
- if (!arch_get_random_long(&flags))
+ mix_pool_bytes(r, &now, sizeof(now), NULL);
+ for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) {
+ if (!arch_get_random_long(&rv))
break;
- mix_pool_bytes(r, &flags, sizeof(flags));
+ mix_pool_bytes(r, &rv, sizeof(rv), NULL);
}
- mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
+ mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL);
}
static int rand_initialize(void)
@@ -1186,7 +1186,7 @@ write_pool(struct entropy_store *r, cons
count -= bytes;
p += bytes;
- mix_pool_bytes(r, buf, bytes);
+ mix_pool_bytes(r, buf, bytes, NULL);
cond_resched();
}
next prev parent reply other threads:[~2012-08-13 22:27 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-13 22:13 [ 00/65] 3.4.9-stable review Greg Kroah-Hartman
2012-08-13 22:13 ` [ 01/65] [IA64] Redefine ATOMIC_INIT and ATOMIC64_INIT to drop the casts Greg Kroah-Hartman
2012-08-13 22:13 ` [ 02/65] asus-wmi: use ASUS_WMI_METHODID_DSTS2 as default DSTS ID Greg Kroah-Hartman
2012-08-13 22:13 ` [ 03/65] sunrpc: clnt: Add missing braces Greg Kroah-Hartman
2012-08-13 22:13 ` [ 04/65] SUNRPC: return negative value in case rpcbind client creation error Greg Kroah-Hartman
2012-08-13 22:13 ` [ 05/65] nilfs2: fix deadlock issue between chcp and thaw ioctls Greg Kroah-Hartman
2012-08-13 22:13 ` [ 06/65] media: ene_ir: Fix driver initialisation Greg Kroah-Hartman
2012-08-13 22:13 ` [ 07/65] pcdp: use early_ioremap/early_iounmap to access pcdp table Greg Kroah-Hartman
2012-08-13 22:13 ` [ 08/65] mm: fix wrong argument of migrate_huge_pages() in soft_offline_huge_page() Greg Kroah-Hartman
2012-08-13 22:13 ` [ 09/65] ARM: 7466/1: disable interrupt before spinning endlessly Greg Kroah-Hartman
2012-08-13 22:13 ` [ 10/65] ARM: 7467/1: mutex: use generic xchg-based implementation for ARMv6+ Greg Kroah-Hartman
2012-08-15 4:29 ` Ben Hutchings
2012-08-15 9:10 ` Will Deacon
2012-08-13 22:13 ` [ 11/65] ARM: 7476/1: vfp: only clear vfp state for current cpu in vfp_pm_suspend Greg Kroah-Hartman
2012-08-13 22:13 ` [ 12/65] ARM: 7477/1: vfp: Always save VFP state in vfp_pm_suspend on UP Greg Kroah-Hartman
2012-08-13 22:13 ` [ 13/65] ARM: 7478/1: errata: extend workaround for erratum #720789 Greg Kroah-Hartman
2012-08-13 22:13 ` [ 14/65] ARM: 7479/1: mm: avoid NULL dereference when flushing gate_vma with VIVT caches Greg Kroah-Hartman
2012-08-13 22:13 ` [ 15/65] ARM: 7480/1: only call smp_send_stop() on SMP Greg Kroah-Hartman
2012-08-13 22:14 ` [ 16/65] ARM: Fix undefined instruction exception handling Greg Kroah-Hartman
2012-08-13 22:14 ` [ 17/65] ALSA: hda - add dock support for Thinkpad T430s Greg Kroah-Hartman
2012-08-13 22:14 ` [ 18/65] ALSA: hda - add dock support for Thinkpad X230 Greg Kroah-Hartman
2012-08-13 22:14 ` [ 19/65] ALSA: hda - remove quirk for Dell Vostro 1015 Greg Kroah-Hartman
2012-08-13 22:14 ` [ 20/65] ALSA: hda - Fix double quirk for Quanta FL1 / Lenovo Ideapad Greg Kroah-Hartman
2012-08-13 22:14 ` [ 21/65] mm: mmu_notifier: fix freed page still mapped in secondary MMU Greg Kroah-Hartman
2012-08-13 22:14 ` [ 22/65] md/raid1: dont abort a resync on the first badblock Greg Kroah-Hartman
2012-08-13 22:14 ` [ 23/65] video/smscufx: fix line counting in fb_write Greg Kroah-Hartman
2012-08-13 22:14 ` [ 24/65] ore: Fix out-of-bounds access in _ios_obj() Greg Kroah-Hartman
2012-08-13 22:14 ` [ 25/65] ACPI processor: Fix tick_broadcast_mask online/offline regression Greg Kroah-Hartman
2012-08-13 22:14 ` [ 26/65] mac80211: cancel mesh path timer Greg Kroah-Hartman
2012-08-13 22:14 ` [ 27/65] ath9k: Add PID/VID support for AR1111 Greg Kroah-Hartman
2012-08-13 22:14 ` [ 28/65] wireless: reg: restore previous behaviour of chan->max_power calculations Greg Kroah-Hartman
2012-08-13 22:14 ` [ 29/65] x86, nops: Missing break resulting in incorrect selection on Intel Greg Kroah-Hartman
2012-08-13 22:14 ` [ 30/65] random: make add_interrupt_randomness() do something sane Greg Kroah-Hartman
2012-08-13 22:14 ` Greg Kroah-Hartman [this message]
2012-08-13 22:14 ` [ 32/65] random: create add_device_randomness() interface Greg Kroah-Hartman
2012-08-13 22:14 ` [ 33/65] usb: feed USB device information to the /dev/random driver Greg Kroah-Hartman
2012-08-13 22:14 ` [ 34/65] net: feed /dev/random with the MAC address when registering a device Greg Kroah-Hartman
2012-08-13 22:14 ` [ 35/65] random: use the arch-specific rng in xfer_secondary_pool Greg Kroah-Hartman
2012-08-13 22:14 ` [ 36/65] random: add new get_random_bytes_arch() function Greg Kroah-Hartman
2012-08-13 22:14 ` [ 37/65] random: add tracepoints for easier debugging and verification Greg Kroah-Hartman
2012-08-13 22:14 ` [ 38/65] MAINTAINERS: Theodore Tso is taking over the random driver Greg Kroah-Hartman
2012-08-13 22:14 ` [ 39/65] rtc: wm831x: Feed the write counter into device_add_randomness() Greg Kroah-Hartman
2012-08-13 22:14 ` [ 40/65] mfd: wm831x: Feed the device UUID " Greg Kroah-Hartman
2012-08-13 22:14 ` [ 41/65] random: remove rand_initialize_irq() Greg Kroah-Hartman
2012-08-13 22:14 ` [ 42/65] random: Add comment to random_initialize() Greg Kroah-Hartman
2012-08-13 22:14 ` [ 43/65] dmi: Feed DMI table to /dev/random driver Greg Kroah-Hartman
2012-08-13 22:14 ` [ 44/65] random: mix in architectural randomness in extract_buf() Greg Kroah-Hartman
2012-08-13 22:14 ` [ 45/65] HID: multitouch: add support for Novatek touchscreen Greg Kroah-Hartman
2012-08-13 22:14 ` [ 46/65] HID: add support for Cypress barcode scanner 04B4:ED81 Greg Kroah-Hartman
2012-08-13 22:14 ` [ 47/65] HID: add ASUS AIO keyboard model AK1D Greg Kroah-Hartman
2012-08-13 22:14 ` [ 48/65] x86, microcode: microcode_core.c simple_strtoul cleanup Greg Kroah-Hartman
2012-08-13 22:14 ` [ 49/65] x86, microcode: Sanitize per-cpu microcode reloading interface Greg Kroah-Hartman
2012-08-13 22:14 ` [ 50/65] mm: hugetlbfs: close race during teardown of hugetlbfs shared page tables Greg Kroah-Hartman
2012-08-13 22:14 ` [ 51/65] target: Add range checking to UNMAP emulation Greg Kroah-Hartman
2012-08-13 22:14 ` [ 52/65] target: Fix reading of data length fields for UNMAP commands Greg Kroah-Hartman
2012-08-13 22:14 ` [ 53/65] target: Fix possible integer underflow in UNMAP emulation Greg Kroah-Hartman
2012-08-13 22:14 ` [ 54/65] target: Check number of unmap descriptors against our limit Greg Kroah-Hartman
2012-08-13 22:14 ` [ 55/65] ARM: mxs: Remove MMAP_MIN_ADDR setting from mxs_defconfig Greg Kroah-Hartman
2012-08-13 22:14 ` [ 56/65] ARM: dts: imx53-ard: add regulators for lan9220 Greg Kroah-Hartman
2012-08-13 22:14 ` [ 57/65] ARM: pxa: remove irq_to_gpio from ezx-pcap driver Greg Kroah-Hartman
2012-08-13 22:14 ` [ 58/65] cfg80211: process pending events when unregistering net device Greg Kroah-Hartman
2012-08-13 22:14 ` [ 59/65] cfg80211: fix interface combinations check for ADHOC(IBSS) Greg Kroah-Hartman
2012-08-13 22:14 ` [ 60/65] tun: dont zeroize sock->file on detach Greg Kroah-Hartman
2012-08-13 22:14 ` [ 61/65] iwlwifi: disable greenfield transmissions as a workaround Greg Kroah-Hartman
2012-08-13 22:14 ` [ 62/65] e1000e: NIC goes up and immediately goes down Greg Kroah-Hartman
2012-08-13 22:14 ` [ 63/65] Input: eeti_ts: pass gpio value instead of IRQ Greg Kroah-Hartman
2012-08-13 22:14 ` [ 64/65] Input: wacom - Bamboo One 1024 pressure fix Greg Kroah-Hartman
2012-08-13 22:14 ` [ 65/65] rt61pci: fix NULL pointer dereference in config_lna_gain Greg Kroah-Hartman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120813221417.702230387@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).