diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/capability.c | 24 | ||||
-rw-r--r-- | kernel/exit.c | 2 | ||||
-rw-r--r-- | kernel/lockdep.c | 17 | ||||
-rw-r--r-- | kernel/pid_namespace.c | 3 | ||||
-rw-r--r-- | kernel/printk.c | 80 | ||||
-rw-r--r-- | kernel/sys.c | 60 | ||||
-rw-r--r-- | kernel/time/tick-broadcast.c | 3 | ||||
-rw-r--r-- | kernel/user.c | 2 | ||||
-rw-r--r-- | kernel/user_namespace.c | 11 | ||||
-rw-r--r-- | kernel/workqueue.c | 44 |
10 files changed, 149 insertions, 97 deletions
diff --git a/kernel/capability.c b/kernel/capability.c index 493d97259484..f6c2ce5701e1 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
@@ -393,6 +393,30 @@ bool ns_capable(struct user_namespace *ns, int cap) | |||
393 | EXPORT_SYMBOL(ns_capable); | 393 | EXPORT_SYMBOL(ns_capable); |
394 | 394 | ||
395 | /** | 395 | /** |
396 | * file_ns_capable - Determine if the file's opener had a capability in effect | ||
397 | * @file: The file we want to check | ||
398 | * @ns: The usernamespace we want the capability in | ||
399 | * @cap: The capability to be tested for | ||
400 | * | ||
401 | * Return true if task that opened the file had a capability in effect | ||
402 | * when the file was opened. | ||
403 | * | ||
404 | * This does not set PF_SUPERPRIV because the caller may not | ||
405 | * actually be privileged. | ||
406 | */ | ||
407 | bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap) | ||
408 | { | ||
409 | if (WARN_ON_ONCE(!cap_valid(cap))) | ||
410 | return false; | ||
411 | |||
412 | if (security_capable(file->f_cred, ns, cap) == 0) | ||
413 | return true; | ||
414 | |||
415 | return false; | ||
416 | } | ||
417 | EXPORT_SYMBOL(file_ns_capable); | ||
418 | |||
419 | /** | ||
396 | * capable - Determine if the current task has a superior capability in effect | 420 | * capable - Determine if the current task has a superior capability in effect |
397 | * @cap: The capability to be tested for | 421 | * @cap: The capability to be tested for |
398 | * | 422 | * |
diff --git a/kernel/exit.c b/kernel/exit.c index 51e485ca9935..60bc027c61c3 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -835,7 +835,7 @@ void do_exit(long code) | |||
835 | /* | 835 | /* |
836 | * Make sure we are holding no locks: | 836 | * Make sure we are holding no locks: |
837 | */ | 837 | */ |
838 | debug_check_no_locks_held(); | 838 | debug_check_no_locks_held(tsk); |
839 | /* | 839 | /* |
840 | * We can do this unlocked here. The futex code uses this flag | 840 | * We can do this unlocked here. The futex code uses this flag |
841 | * just to verify whether the pi state cleanup has been done | 841 | * just to verify whether the pi state cleanup has been done |
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 259db207b5d9..8a0efac4f99d 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -4088,7 +4088,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) | |||
4088 | } | 4088 | } |
4089 | EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); | 4089 | EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); |
4090 | 4090 | ||
4091 | static void print_held_locks_bug(void) | 4091 | static void print_held_locks_bug(struct task_struct *curr) |
4092 | { | 4092 | { |
4093 | if (!debug_locks_off()) | 4093 | if (!debug_locks_off()) |
4094 | return; | 4094 | return; |
@@ -4097,21 +4097,22 @@ static void print_held_locks_bug(void) | |||
4097 | 4097 | ||
4098 | printk("\n"); | 4098 | printk("\n"); |
4099 | printk("=====================================\n"); | 4099 | printk("=====================================\n"); |
4100 | printk("[ BUG: %s/%d still has locks held! ]\n", | 4100 | printk("[ BUG: lock held at task exit time! ]\n"); |
4101 | current->comm, task_pid_nr(current)); | ||
4102 | print_kernel_ident(); | 4101 | print_kernel_ident(); |
4103 | printk("-------------------------------------\n"); | 4102 | printk("-------------------------------------\n"); |
4104 | lockdep_print_held_locks(current); | 4103 | printk("%s/%d is exiting with locks still held!\n", |
4104 | curr->comm, task_pid_nr(curr)); | ||
4105 | lockdep_print_held_locks(curr); | ||
4106 | |||
4105 | printk("\nstack backtrace:\n"); | 4107 | printk("\nstack backtrace:\n"); |
4106 | dump_stack(); | 4108 | dump_stack(); |
4107 | } | 4109 | } |
4108 | 4110 | ||
4109 | void debug_check_no_locks_held(void) | 4111 | void debug_check_no_locks_held(struct task_struct *task) |
4110 | { | 4112 | { |
4111 | if (unlikely(current->lockdep_depth > 0)) | 4113 | if (unlikely(task->lockdep_depth > 0)) |
4112 | print_held_locks_bug(); | 4114 | print_held_locks_bug(task); |
4113 | } | 4115 | } |
4114 | EXPORT_SYMBOL_GPL(debug_check_no_locks_held); | ||
4115 | 4116 | ||
4116 | void debug_show_all_locks(void) | 4117 | void debug_show_all_locks(void) |
4117 | { | 4118 | { |
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index c1c3dc1c6023..bea15bdf82b0 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c | |||
@@ -181,6 +181,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns) | |||
181 | int nr; | 181 | int nr; |
182 | int rc; | 182 | int rc; |
183 | struct task_struct *task, *me = current; | 183 | struct task_struct *task, *me = current; |
184 | int init_pids = thread_group_leader(me) ? 1 : 2; | ||
184 | 185 | ||
185 | /* Don't allow any more processes into the pid namespace */ | 186 | /* Don't allow any more processes into the pid namespace */ |
186 | disable_pid_allocation(pid_ns); | 187 | disable_pid_allocation(pid_ns); |
@@ -230,7 +231,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns) | |||
230 | */ | 231 | */ |
231 | for (;;) { | 232 | for (;;) { |
232 | set_current_state(TASK_UNINTERRUPTIBLE); | 233 | set_current_state(TASK_UNINTERRUPTIBLE); |
233 | if (pid_ns->nr_hashed == 1) | 234 | if (pid_ns->nr_hashed == init_pids) |
234 | break; | 235 | break; |
235 | schedule(); | 236 | schedule(); |
236 | } | 237 | } |
diff --git a/kernel/printk.c b/kernel/printk.c index 0b31715f335a..abbdd9e2ac82 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -63,8 +63,6 @@ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...) | |||
63 | #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ | 63 | #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ |
64 | #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */ | 64 | #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */ |
65 | 65 | ||
66 | DECLARE_WAIT_QUEUE_HEAD(log_wait); | ||
67 | |||
68 | int console_printk[4] = { | 66 | int console_printk[4] = { |
69 | DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */ | 67 | DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */ |
70 | DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */ | 68 | DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */ |
@@ -224,6 +222,7 @@ struct log { | |||
224 | static DEFINE_RAW_SPINLOCK(logbuf_lock); | 222 | static DEFINE_RAW_SPINLOCK(logbuf_lock); |
225 | 223 | ||
226 | #ifdef CONFIG_PRINTK | 224 | #ifdef CONFIG_PRINTK |
225 | DECLARE_WAIT_QUEUE_HEAD(log_wait); | ||
227 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ | 226 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ |
228 | static u64 syslog_seq; | 227 | static u64 syslog_seq; |
229 | static u32 syslog_idx; | 228 | static u32 syslog_idx; |
@@ -1957,45 +1956,6 @@ int is_console_locked(void) | |||
1957 | return console_locked; | 1956 | return console_locked; |
1958 | } | 1957 | } |
1959 | 1958 | ||
1960 | /* | ||
1961 | * Delayed printk version, for scheduler-internal messages: | ||
1962 | */ | ||
1963 | #define PRINTK_BUF_SIZE 512 | ||
1964 | |||
1965 | #define PRINTK_PENDING_WAKEUP 0x01 | ||
1966 | #define PRINTK_PENDING_SCHED 0x02 | ||
1967 | |||
1968 | static DEFINE_PER_CPU(int, printk_pending); | ||
1969 | static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); | ||
1970 | |||
1971 | static void wake_up_klogd_work_func(struct irq_work *irq_work) | ||
1972 | { | ||
1973 | int pending = __this_cpu_xchg(printk_pending, 0); | ||
1974 | |||
1975 | if (pending & PRINTK_PENDING_SCHED) { | ||
1976 | char *buf = __get_cpu_var(printk_sched_buf); | ||
1977 | printk(KERN_WARNING "[sched_delayed] %s", buf); | ||
1978 | } | ||
1979 | |||
1980 | if (pending & PRINTK_PENDING_WAKEUP) | ||
1981 | wake_up_interruptible(&log_wait); | ||
1982 | } | ||
1983 | |||
1984 | static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = { | ||
1985 | .func = wake_up_klogd_work_func, | ||
1986 | .flags = IRQ_WORK_LAZY, | ||
1987 | }; | ||
1988 | |||
1989 | void wake_up_klogd(void) | ||
1990 | { | ||
1991 | preempt_disable(); | ||
1992 | if (waitqueue_active(&log_wait)) { | ||
1993 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); | ||
1994 | irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); | ||
1995 | } | ||
1996 | preempt_enable(); | ||
1997 | } | ||
1998 | |||
1999 | static void console_cont_flush(char *text, size_t size) | 1959 | static void console_cont_flush(char *text, size_t size) |
2000 | { | 1960 | { |
2001 | unsigned long flags; | 1961 | unsigned long flags; |
@@ -2458,6 +2418,44 @@ static int __init printk_late_init(void) | |||
2458 | late_initcall(printk_late_init); | 2418 | late_initcall(printk_late_init); |
2459 | 2419 | ||
2460 | #if defined CONFIG_PRINTK | 2420 | #if defined CONFIG_PRINTK |
2421 | /* | ||
2422 | * Delayed printk version, for scheduler-internal messages: | ||
2423 | */ | ||
2424 | #define PRINTK_BUF_SIZE 512 | ||
2425 | |||
2426 | #define PRINTK_PENDING_WAKEUP 0x01 | ||
2427 | #define PRINTK_PENDING_SCHED 0x02 | ||
2428 | |||
2429 | static DEFINE_PER_CPU(int, printk_pending); | ||
2430 | static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); | ||
2431 | |||
2432 | static void wake_up_klogd_work_func(struct irq_work *irq_work) | ||
2433 | { | ||
2434 | int pending = __this_cpu_xchg(printk_pending, 0); | ||
2435 | |||
2436 | if (pending & PRINTK_PENDING_SCHED) { | ||
2437 | char *buf = __get_cpu_var(printk_sched_buf); | ||
2438 | printk(KERN_WARNING "[sched_delayed] %s", buf); | ||
2439 | } | ||
2440 | |||
2441 | if (pending & PRINTK_PENDING_WAKEUP) | ||
2442 | wake_up_interruptible(&log_wait); | ||
2443 | } | ||
2444 | |||
2445 | static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = { | ||
2446 | .func = wake_up_klogd_work_func, | ||
2447 | .flags = IRQ_WORK_LAZY, | ||
2448 | }; | ||
2449 | |||
2450 | void wake_up_klogd(void) | ||
2451 | { | ||
2452 | preempt_disable(); | ||
2453 | if (waitqueue_active(&log_wait)) { | ||
2454 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); | ||
2455 | irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); | ||
2456 | } | ||
2457 | preempt_enable(); | ||
2458 | } | ||
2461 | 2459 | ||
2462 | int printk_sched(const char *fmt, ...) | 2460 | int printk_sched(const char *fmt, ...) |
2463 | { | 2461 | { |
diff --git a/kernel/sys.c b/kernel/sys.c index 81f56445fba9..0da73cf73e60 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -324,7 +324,6 @@ void kernel_restart_prepare(char *cmd) | |||
324 | system_state = SYSTEM_RESTART; | 324 | system_state = SYSTEM_RESTART; |
325 | usermodehelper_disable(); | 325 | usermodehelper_disable(); |
326 | device_shutdown(); | 326 | device_shutdown(); |
327 | syscore_shutdown(); | ||
328 | } | 327 | } |
329 | 328 | ||
330 | /** | 329 | /** |
@@ -370,6 +369,7 @@ void kernel_restart(char *cmd) | |||
370 | { | 369 | { |
371 | kernel_restart_prepare(cmd); | 370 | kernel_restart_prepare(cmd); |
372 | disable_nonboot_cpus(); | 371 | disable_nonboot_cpus(); |
372 | syscore_shutdown(); | ||
373 | if (!cmd) | 373 | if (!cmd) |
374 | printk(KERN_EMERG "Restarting system.\n"); | 374 | printk(KERN_EMERG "Restarting system.\n"); |
375 | else | 375 | else |
@@ -395,6 +395,7 @@ static void kernel_shutdown_prepare(enum system_states state) | |||
395 | void kernel_halt(void) | 395 | void kernel_halt(void) |
396 | { | 396 | { |
397 | kernel_shutdown_prepare(SYSTEM_HALT); | 397 | kernel_shutdown_prepare(SYSTEM_HALT); |
398 | disable_nonboot_cpus(); | ||
398 | syscore_shutdown(); | 399 | syscore_shutdown(); |
399 | printk(KERN_EMERG "System halted.\n"); | 400 | printk(KERN_EMERG "System halted.\n"); |
400 | kmsg_dump(KMSG_DUMP_HALT); | 401 | kmsg_dump(KMSG_DUMP_HALT); |
@@ -2185,9 +2186,8 @@ SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep, | |||
2185 | 2186 | ||
2186 | char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff"; | 2187 | char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff"; |
2187 | 2188 | ||
2188 | static int __orderly_poweroff(void) | 2189 | static int __orderly_poweroff(bool force) |
2189 | { | 2190 | { |
2190 | int argc; | ||
2191 | char **argv; | 2191 | char **argv; |
2192 | static char *envp[] = { | 2192 | static char *envp[] = { |
2193 | "HOME=/", | 2193 | "HOME=/", |
@@ -2196,20 +2196,40 @@ static int __orderly_poweroff(void) | |||
2196 | }; | 2196 | }; |
2197 | int ret; | 2197 | int ret; |
2198 | 2198 | ||
2199 | argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc); | 2199 | argv = argv_split(GFP_KERNEL, poweroff_cmd, NULL); |
2200 | if (argv == NULL) { | 2200 | if (argv) { |
2201 | ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); | ||
2202 | argv_free(argv); | ||
2203 | } else { | ||
2201 | printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", | 2204 | printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", |
2202 | __func__, poweroff_cmd); | 2205 | __func__, poweroff_cmd); |
2203 | return -ENOMEM; | 2206 | ret = -ENOMEM; |
2204 | } | 2207 | } |
2205 | 2208 | ||
2206 | ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_WAIT_EXEC, | 2209 | if (ret && force) { |
2207 | NULL, NULL, NULL); | 2210 | printk(KERN_WARNING "Failed to start orderly shutdown: " |
2208 | argv_free(argv); | 2211 | "forcing the issue\n"); |
2212 | /* | ||
2213 | * I guess this should try to kick off some daemon to sync and | ||
2214 | * poweroff asap. Or not even bother syncing if we're doing an | ||
2215 | * emergency shutdown? | ||
2216 | */ | ||
2217 | emergency_sync(); | ||
2218 | kernel_power_off(); | ||
2219 | } | ||
2209 | 2220 | ||
2210 | return ret; | 2221 | return ret; |
2211 | } | 2222 | } |
2212 | 2223 | ||
2224 | static bool poweroff_force; | ||
2225 | |||
2226 | static void poweroff_work_func(struct work_struct *work) | ||
2227 | { | ||
2228 | __orderly_poweroff(poweroff_force); | ||
2229 | } | ||
2230 | |||
2231 | static DECLARE_WORK(poweroff_work, poweroff_work_func); | ||
2232 | |||
2213 | /** | 2233 | /** |
2214 | * orderly_poweroff - Trigger an orderly system poweroff | 2234 | * orderly_poweroff - Trigger an orderly system poweroff |
2215 | * @force: force poweroff if command execution fails | 2235 | * @force: force poweroff if command execution fails |
@@ -2219,21 +2239,9 @@ static int __orderly_poweroff(void) | |||
2219 | */ | 2239 | */ |
2220 | int orderly_poweroff(bool force) | 2240 | int orderly_poweroff(bool force) |
2221 | { | 2241 | { |
2222 | int ret = __orderly_poweroff(); | 2242 | if (force) /* do not override the pending "true" */ |
2223 | 2243 | poweroff_force = true; | |
2224 | if (ret && force) { | 2244 | schedule_work(&poweroff_work); |
2225 | printk(KERN_WARNING "Failed to start orderly shutdown: " | 2245 | return 0; |
2226 | "forcing the issue\n"); | ||
2227 | |||
2228 | /* | ||
2229 | * I guess this should try to kick off some daemon to sync and | ||
2230 | * poweroff asap. Or not even bother syncing if we're doing an | ||
2231 | * emergency shutdown? | ||
2232 | */ | ||
2233 | emergency_sync(); | ||
2234 | kernel_power_off(); | ||
2235 | } | ||
2236 | |||
2237 | return ret; | ||
2238 | } | 2246 | } |
2239 | EXPORT_SYMBOL_GPL(orderly_poweroff); | 2247 | EXPORT_SYMBOL_GPL(orderly_poweroff); |
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 2fb8cb88df8d..7f32fe0e52cd 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c | |||
@@ -67,7 +67,8 @@ static void tick_broadcast_start_periodic(struct clock_event_device *bc) | |||
67 | */ | 67 | */ |
68 | int tick_check_broadcast_device(struct clock_event_device *dev) | 68 | int tick_check_broadcast_device(struct clock_event_device *dev) |
69 | { | 69 | { |
70 | if ((tick_broadcast_device.evtdev && | 70 | if ((dev->features & CLOCK_EVT_FEAT_DUMMY) || |
71 | (tick_broadcast_device.evtdev && | ||
71 | tick_broadcast_device.evtdev->rating >= dev->rating) || | 72 | tick_broadcast_device.evtdev->rating >= dev->rating) || |
72 | (dev->features & CLOCK_EVT_FEAT_C3STOP)) | 73 | (dev->features & CLOCK_EVT_FEAT_C3STOP)) |
73 | return 0; | 74 | return 0; |
diff --git a/kernel/user.c b/kernel/user.c index e81978e8c03b..8e635a18ab52 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
@@ -51,6 +51,8 @@ struct user_namespace init_user_ns = { | |||
51 | .owner = GLOBAL_ROOT_UID, | 51 | .owner = GLOBAL_ROOT_UID, |
52 | .group = GLOBAL_ROOT_GID, | 52 | .group = GLOBAL_ROOT_GID, |
53 | .proc_inum = PROC_USER_INIT_INO, | 53 | .proc_inum = PROC_USER_INIT_INO, |
54 | .may_mount_sysfs = true, | ||
55 | .may_mount_proc = true, | ||
54 | }; | 56 | }; |
55 | EXPORT_SYMBOL_GPL(init_user_ns); | 57 | EXPORT_SYMBOL_GPL(init_user_ns); |
56 | 58 | ||
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index b14f4d342043..a54f26f82eb2 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c | |||
@@ -61,6 +61,15 @@ int create_user_ns(struct cred *new) | |||
61 | kgid_t group = new->egid; | 61 | kgid_t group = new->egid; |
62 | int ret; | 62 | int ret; |
63 | 63 | ||
64 | /* | ||
65 | * Verify that we can not violate the policy of which files | ||
66 | * may be accessed that is specified by the root directory, | ||
67 | * by verifing that the root directory is at the root of the | ||
68 | * mount namespace which allows all files to be accessed. | ||
69 | */ | ||
70 | if (current_chrooted()) | ||
71 | return -EPERM; | ||
72 | |||
64 | /* The creator needs a mapping in the parent user namespace | 73 | /* The creator needs a mapping in the parent user namespace |
65 | * or else we won't be able to reasonably tell userspace who | 74 | * or else we won't be able to reasonably tell userspace who |
66 | * created a user_namespace. | 75 | * created a user_namespace. |
@@ -87,6 +96,8 @@ int create_user_ns(struct cred *new) | |||
87 | 96 | ||
88 | set_cred_user_ns(new, ns); | 97 | set_cred_user_ns(new, ns); |
89 | 98 | ||
99 | update_mnt_policy(ns); | ||
100 | |||
90 | return 0; | 101 | return 0; |
91 | } | 102 | } |
92 | 103 | ||
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 55fac5b991b7..b48cd597145d 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -3447,28 +3447,34 @@ static void wq_unbind_fn(struct work_struct *work) | |||
3447 | 3447 | ||
3448 | spin_unlock_irq(&pool->lock); | 3448 | spin_unlock_irq(&pool->lock); |
3449 | mutex_unlock(&pool->assoc_mutex); | 3449 | mutex_unlock(&pool->assoc_mutex); |
3450 | } | ||
3451 | 3450 | ||
3452 | /* | 3451 | /* |
3453 | * Call schedule() so that we cross rq->lock and thus can guarantee | 3452 | * Call schedule() so that we cross rq->lock and thus can |
3454 | * sched callbacks see the %WORKER_UNBOUND flag. This is necessary | 3453 | * guarantee sched callbacks see the %WORKER_UNBOUND flag. |
3455 | * as scheduler callbacks may be invoked from other cpus. | 3454 | * This is necessary as scheduler callbacks may be invoked |
3456 | */ | 3455 | * from other cpus. |
3457 | schedule(); | 3456 | */ |
3457 | schedule(); | ||
3458 | 3458 | ||
3459 | /* | 3459 | /* |
3460 | * Sched callbacks are disabled now. Zap nr_running. After this, | 3460 | * Sched callbacks are disabled now. Zap nr_running. |
3461 | * nr_running stays zero and need_more_worker() and keep_working() | 3461 | * After this, nr_running stays zero and need_more_worker() |
3462 | * are always true as long as the worklist is not empty. Pools on | 3462 | * and keep_working() are always true as long as the |
3463 | * @cpu now behave as unbound (in terms of concurrency management) | 3463 | * worklist is not empty. This pool now behaves as an |
3464 | * pools which are served by workers tied to the CPU. | 3464 | * unbound (in terms of concurrency management) pool which |
3465 | * | 3465 | * are served by workers tied to the pool. |
3466 | * On return from this function, the current worker would trigger | 3466 | */ |
3467 | * unbound chain execution of pending work items if other workers | ||
3468 | * didn't already. | ||
3469 | */ | ||
3470 | for_each_std_worker_pool(pool, cpu) | ||
3471 | atomic_set(&pool->nr_running, 0); | 3467 | atomic_set(&pool->nr_running, 0); |
3468 | |||
3469 | /* | ||
3470 | * With concurrency management just turned off, a busy | ||
3471 | * worker blocking could lead to lengthy stalls. Kick off | ||
3472 | * unbound chain execution of currently pending work items. | ||
3473 | */ | ||
3474 | spin_lock_irq(&pool->lock); | ||
3475 | wake_up_worker(pool); | ||
3476 | spin_unlock_irq(&pool->lock); | ||
3477 | } | ||
3472 | } | 3478 | } |
3473 | 3479 | ||
3474 | /* | 3480 | /* |