diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cpuset.c | 24 | ||||
-rw-r--r-- | kernel/irq/handle.c | 2 | ||||
-rw-r--r-- | kernel/module.c | 6 | ||||
-rw-r--r-- | kernel/sched.c | 2 | ||||
-rw-r--r-- | kernel/signal.c | 11 | ||||
-rw-r--r-- | kernel/spinlock.c | 8 |
6 files changed, 40 insertions, 13 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 961d74044deb..00e8f2575512 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -166,9 +166,8 @@ static struct super_block *cpuset_sb = NULL; | |||
166 | * The hooks from fork and exit, cpuset_fork() and cpuset_exit(), don't | 166 | * The hooks from fork and exit, cpuset_fork() and cpuset_exit(), don't |
167 | * (usually) grab cpuset_sem. These are the two most performance | 167 | * (usually) grab cpuset_sem. These are the two most performance |
168 | * critical pieces of code here. The exception occurs on exit(), | 168 | * critical pieces of code here. The exception occurs on exit(), |
169 | * if the last task using a cpuset exits, and the cpuset was marked | 169 | * when a task in a notify_on_release cpuset exits. Then cpuset_sem |
170 | * notify_on_release. In that case, the cpuset_sem is taken, the | 170 | * is taken, and if the cpuset count is zero, a usermode call made |
171 | * path to the released cpuset calculated, and a usermode call made | ||
172 | * to /sbin/cpuset_release_agent with the name of the cpuset (path | 171 | * to /sbin/cpuset_release_agent with the name of the cpuset (path |
173 | * relative to the root of cpuset file system) as the argument. | 172 | * relative to the root of cpuset file system) as the argument. |
174 | * | 173 | * |
@@ -1404,6 +1403,18 @@ void cpuset_fork(struct task_struct *tsk) | |||
1404 | * | 1403 | * |
1405 | * Description: Detach cpuset from @tsk and release it. | 1404 | * Description: Detach cpuset from @tsk and release it. |
1406 | * | 1405 | * |
1406 | * Note that cpusets marked notify_on_release force every task | ||
1407 | * in them to take the global cpuset_sem semaphore when exiting. | ||
1408 | * This could impact scaling on very large systems. Be reluctant | ||
1409 | * to use notify_on_release cpusets where very high task exit | ||
1410 | * scaling is required on large systems. | ||
1411 | * | ||
1412 | * Don't even think about derefencing 'cs' after the cpuset use | ||
1413 | * count goes to zero, except inside a critical section guarded | ||
1414 | * by the cpuset_sem semaphore. If you don't hold cpuset_sem, | ||
1415 | * then a zero cpuset use count is a license to any other task to | ||
1416 | * nuke the cpuset immediately. | ||
1417 | * | ||
1407 | **/ | 1418 | **/ |
1408 | 1419 | ||
1409 | void cpuset_exit(struct task_struct *tsk) | 1420 | void cpuset_exit(struct task_struct *tsk) |
@@ -1415,10 +1426,13 @@ void cpuset_exit(struct task_struct *tsk) | |||
1415 | tsk->cpuset = NULL; | 1426 | tsk->cpuset = NULL; |
1416 | task_unlock(tsk); | 1427 | task_unlock(tsk); |
1417 | 1428 | ||
1418 | if (atomic_dec_and_test(&cs->count)) { | 1429 | if (notify_on_release(cs)) { |
1419 | down(&cpuset_sem); | 1430 | down(&cpuset_sem); |
1420 | check_for_release(cs); | 1431 | if (atomic_dec_and_test(&cs->count)) |
1432 | check_for_release(cs); | ||
1421 | up(&cpuset_sem); | 1433 | up(&cpuset_sem); |
1434 | } else { | ||
1435 | atomic_dec(&cs->count); | ||
1422 | } | 1436 | } |
1423 | } | 1437 | } |
1424 | 1438 | ||
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 06b5a6323998..436c7d93c00a 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -119,8 +119,6 @@ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs) | |||
119 | */ | 119 | */ |
120 | desc->handler->ack(irq); | 120 | desc->handler->ack(irq); |
121 | action_ret = handle_IRQ_event(irq, regs, desc->action); | 121 | action_ret = handle_IRQ_event(irq, regs, desc->action); |
122 | if (!noirqdebug) | ||
123 | note_interrupt(irq, desc, action_ret); | ||
124 | desc->handler->end(irq); | 122 | desc->handler->end(irq); |
125 | return 1; | 123 | return 1; |
126 | } | 124 | } |
diff --git a/kernel/module.c b/kernel/module.c index 5734ab09d3f9..83b3d376708c 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -1758,6 +1758,7 @@ sys_init_module(void __user *umod, | |||
1758 | const char __user *uargs) | 1758 | const char __user *uargs) |
1759 | { | 1759 | { |
1760 | struct module *mod; | 1760 | struct module *mod; |
1761 | mm_segment_t old_fs = get_fs(); | ||
1761 | int ret = 0; | 1762 | int ret = 0; |
1762 | 1763 | ||
1763 | /* Must have permission */ | 1764 | /* Must have permission */ |
@@ -1775,6 +1776,9 @@ sys_init_module(void __user *umod, | |||
1775 | return PTR_ERR(mod); | 1776 | return PTR_ERR(mod); |
1776 | } | 1777 | } |
1777 | 1778 | ||
1779 | /* flush the icache in correct context */ | ||
1780 | set_fs(KERNEL_DS); | ||
1781 | |||
1778 | /* Flush the instruction cache, since we've played with text */ | 1782 | /* Flush the instruction cache, since we've played with text */ |
1779 | if (mod->module_init) | 1783 | if (mod->module_init) |
1780 | flush_icache_range((unsigned long)mod->module_init, | 1784 | flush_icache_range((unsigned long)mod->module_init, |
@@ -1783,6 +1787,8 @@ sys_init_module(void __user *umod, | |||
1783 | flush_icache_range((unsigned long)mod->module_core, | 1787 | flush_icache_range((unsigned long)mod->module_core, |
1784 | (unsigned long)mod->module_core + mod->core_size); | 1788 | (unsigned long)mod->module_core + mod->core_size); |
1785 | 1789 | ||
1790 | set_fs(old_fs); | ||
1791 | |||
1786 | /* Now sew it into the lists. They won't access us, since | 1792 | /* Now sew it into the lists. They won't access us, since |
1787 | strong_try_module_get() will fail. */ | 1793 | strong_try_module_get() will fail. */ |
1788 | stop_machine_run(__link_module, mod, NR_CPUS); | 1794 | stop_machine_run(__link_module, mod, NR_CPUS); |
diff --git a/kernel/sched.c b/kernel/sched.c index 0dc3158667a2..66b2ed784822 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -4243,7 +4243,7 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *tsk) | |||
4243 | 4243 | ||
4244 | /* No more Mr. Nice Guy. */ | 4244 | /* No more Mr. Nice Guy. */ |
4245 | if (dest_cpu == NR_CPUS) { | 4245 | if (dest_cpu == NR_CPUS) { |
4246 | tsk->cpus_allowed = cpuset_cpus_allowed(tsk); | 4246 | cpus_setall(tsk->cpus_allowed); |
4247 | dest_cpu = any_online_cpu(tsk->cpus_allowed); | 4247 | dest_cpu = any_online_cpu(tsk->cpus_allowed); |
4248 | 4248 | ||
4249 | /* | 4249 | /* |
diff --git a/kernel/signal.c b/kernel/signal.c index 293e189d8bc3..c89821b69ae3 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -523,7 +523,16 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, | |||
523 | { | 523 | { |
524 | int sig = 0; | 524 | int sig = 0; |
525 | 525 | ||
526 | sig = next_signal(pending, mask); | 526 | /* SIGKILL must have priority, otherwise it is quite easy |
527 | * to create an unkillable process, sending sig < SIGKILL | ||
528 | * to self */ | ||
529 | if (unlikely(sigismember(&pending->signal, SIGKILL))) { | ||
530 | if (!sigismember(mask, SIGKILL)) | ||
531 | sig = SIGKILL; | ||
532 | } | ||
533 | |||
534 | if (likely(!sig)) | ||
535 | sig = next_signal(pending, mask); | ||
527 | if (sig) { | 536 | if (sig) { |
528 | if (current->notifier) { | 537 | if (current->notifier) { |
529 | if (sigismember(current->notifier_mask, sig)) { | 538 | if (sigismember(current->notifier_mask, sig)) { |
diff --git a/kernel/spinlock.c b/kernel/spinlock.c index e15ed17863f1..0c3f9d8bbe17 100644 --- a/kernel/spinlock.c +++ b/kernel/spinlock.c | |||
@@ -294,7 +294,7 @@ EXPORT_SYMBOL(_spin_unlock_irq); | |||
294 | void __lockfunc _spin_unlock_bh(spinlock_t *lock) | 294 | void __lockfunc _spin_unlock_bh(spinlock_t *lock) |
295 | { | 295 | { |
296 | _raw_spin_unlock(lock); | 296 | _raw_spin_unlock(lock); |
297 | preempt_enable(); | 297 | preempt_enable_no_resched(); |
298 | local_bh_enable(); | 298 | local_bh_enable(); |
299 | } | 299 | } |
300 | EXPORT_SYMBOL(_spin_unlock_bh); | 300 | EXPORT_SYMBOL(_spin_unlock_bh); |
@@ -318,7 +318,7 @@ EXPORT_SYMBOL(_read_unlock_irq); | |||
318 | void __lockfunc _read_unlock_bh(rwlock_t *lock) | 318 | void __lockfunc _read_unlock_bh(rwlock_t *lock) |
319 | { | 319 | { |
320 | _raw_read_unlock(lock); | 320 | _raw_read_unlock(lock); |
321 | preempt_enable(); | 321 | preempt_enable_no_resched(); |
322 | local_bh_enable(); | 322 | local_bh_enable(); |
323 | } | 323 | } |
324 | EXPORT_SYMBOL(_read_unlock_bh); | 324 | EXPORT_SYMBOL(_read_unlock_bh); |
@@ -342,7 +342,7 @@ EXPORT_SYMBOL(_write_unlock_irq); | |||
342 | void __lockfunc _write_unlock_bh(rwlock_t *lock) | 342 | void __lockfunc _write_unlock_bh(rwlock_t *lock) |
343 | { | 343 | { |
344 | _raw_write_unlock(lock); | 344 | _raw_write_unlock(lock); |
345 | preempt_enable(); | 345 | preempt_enable_no_resched(); |
346 | local_bh_enable(); | 346 | local_bh_enable(); |
347 | } | 347 | } |
348 | EXPORT_SYMBOL(_write_unlock_bh); | 348 | EXPORT_SYMBOL(_write_unlock_bh); |
@@ -354,7 +354,7 @@ int __lockfunc _spin_trylock_bh(spinlock_t *lock) | |||
354 | if (_raw_spin_trylock(lock)) | 354 | if (_raw_spin_trylock(lock)) |
355 | return 1; | 355 | return 1; |
356 | 356 | ||
357 | preempt_enable(); | 357 | preempt_enable_no_resched(); |
358 | local_bh_enable(); | 358 | local_bh_enable(); |
359 | return 0; | 359 | return 0; |
360 | } | 360 | } |