diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-10 14:35:36 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-10 14:35:36 -0500 |
commit | 4ba24fef3eb3b142197135223b90ced2f319cd53 (patch) | |
tree | a20c125b27740ec7b4c761b11d801108e1b316b2 /kernel/irq/proc.c | |
parent | 47c1ffb2b6b630894e9a16442611c056ab21c057 (diff) | |
parent | 98a4a59ee31a12105a2b84f5b8b515ac2cb208ef (diff) |
Merge branch 'next' into for-linus
Prepare first round of input updates for 3.20.
Diffstat (limited to 'kernel/irq/proc.c')
-rw-r--r-- | kernel/irq/proc.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index ac1ba2f11032..9dc9bfd8a678 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c | |||
@@ -15,6 +15,23 @@ | |||
15 | 15 | ||
16 | #include "internals.h" | 16 | #include "internals.h" |
17 | 17 | ||
18 | /* | ||
19 | * Access rules: | ||
20 | * | ||
21 | * procfs protects read/write of /proc/irq/N/ files against a | ||
22 | * concurrent free of the interrupt descriptor. remove_proc_entry() | ||
23 | * immediately prevents new read/writes to happen and waits for | ||
24 | * already running read/write functions to complete. | ||
25 | * | ||
26 | * We remove the proc entries first and then delete the interrupt | ||
27 | * descriptor from the radix tree and free it. So it is guaranteed | ||
28 | * that irq_to_desc(N) is valid as long as the read/writes are | ||
29 | * permitted by procfs. | ||
30 | * | ||
31 | * The read from /proc/interrupts is a different problem because there | ||
32 | * is no protection. So the lookup and the access to irqdesc | ||
33 | * information must be protected by sparse_irq_lock. | ||
34 | */ | ||
18 | static struct proc_dir_entry *root_irq_dir; | 35 | static struct proc_dir_entry *root_irq_dir; |
19 | 36 | ||
20 | #ifdef CONFIG_SMP | 37 | #ifdef CONFIG_SMP |
@@ -437,9 +454,10 @@ int show_interrupts(struct seq_file *p, void *v) | |||
437 | seq_putc(p, '\n'); | 454 | seq_putc(p, '\n'); |
438 | } | 455 | } |
439 | 456 | ||
457 | irq_lock_sparse(); | ||
440 | desc = irq_to_desc(i); | 458 | desc = irq_to_desc(i); |
441 | if (!desc) | 459 | if (!desc) |
442 | return 0; | 460 | goto outsparse; |
443 | 461 | ||
444 | raw_spin_lock_irqsave(&desc->lock, flags); | 462 | raw_spin_lock_irqsave(&desc->lock, flags); |
445 | for_each_online_cpu(j) | 463 | for_each_online_cpu(j) |
@@ -479,6 +497,8 @@ int show_interrupts(struct seq_file *p, void *v) | |||
479 | seq_putc(p, '\n'); | 497 | seq_putc(p, '\n'); |
480 | out: | 498 | out: |
481 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 499 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
500 | outsparse: | ||
501 | irq_unlock_sparse(); | ||
482 | return 0; | 502 | return 0; |
483 | } | 503 | } |
484 | #endif | 504 | #endif |