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 |
