aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2015-09-09 18:38:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-10 16:29:01 -0400
commitbb304a5c6fc63d8506cd9741a3a5f35b73605625 (patch)
tree39d30e22c712abfaa9d4c2912fafb2a7ae6ad8c6
parent90f023030e26ce8f981b3e688cb79329d8d07cc3 (diff)
kmod: handle UMH_WAIT_PROC from system unbound workqueue
The UMH_WAIT_PROC handler runs in its own thread in order to make sure that waiting for the exec kernel thread completion won't block other usermodehelper queued jobs. On older workqueue implementations, worklets couldn't sleep without blocking the rest of the queue. But now the workqueue subsystem handles that. Khelper still had the older limitation due to its singlethread properties but we replaced it to system unbound workqueues. Those are affine to the current node and can block up to some number of instances. They are a good candidate to handle UMH_WAIT_PROC assuming that we have enough system unbound workers to handle lots of parallel usermodehelper jobs. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Rik van Riel <riel@redhat.com> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Cc: Christoph Lameter <cl@linux.com> Cc: Tejun Heo <tj@kernel.org> Cc: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--kernel/kmod.c44
1 files changed, 20 insertions, 24 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c
index d38b2dab99a7..da98d0593de2 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -265,15 +265,9 @@ out:
265 do_exit(0); 265 do_exit(0);
266} 266}
267 267
268/* 268/* Handles UMH_WAIT_PROC. */
269 * Handles UMH_WAIT_PROC. Our parent (unbound workqueue) might not be able to 269static void call_usermodehelper_exec_sync(struct subprocess_info *sub_info)
270 * run enough instances to handle usermodehelper completions without blocking
271 * some other pending requests. That's why we use a kernel thread dedicated for
272 * that purpose.
273 */
274static int call_usermodehelper_exec_sync(void *data)
275{ 270{
276 struct subprocess_info *sub_info = data;
277 pid_t pid; 271 pid_t pid;
278 272
279 /* If SIGCLD is ignored sys_wait4 won't populate the status. */ 273 /* If SIGCLD is ignored sys_wait4 won't populate the status. */
@@ -287,9 +281,9 @@ static int call_usermodehelper_exec_sync(void *data)
287 * Normally it is bogus to call wait4() from in-kernel because 281 * Normally it is bogus to call wait4() from in-kernel because
288 * wait4() wants to write the exit code to a userspace address. 282 * wait4() wants to write the exit code to a userspace address.
289 * But call_usermodehelper_exec_sync() always runs as kernel 283 * But call_usermodehelper_exec_sync() always runs as kernel
290 * thread and put_user() to a kernel address works OK for kernel 284 * thread (workqueue) and put_user() to a kernel address works
291 * threads, due to their having an mm_segment_t which spans the 285 * OK for kernel threads, due to their having an mm_segment_t
292 * entire address space. 286 * which spans the entire address space.
293 * 287 *
294 * Thus the __user pointer cast is valid here. 288 * Thus the __user pointer cast is valid here.
295 */ 289 */
@@ -304,19 +298,21 @@ static int call_usermodehelper_exec_sync(void *data)
304 sub_info->retval = ret; 298 sub_info->retval = ret;
305 } 299 }
306 300
301 /* Restore default kernel sig handler */
302 kernel_sigaction(SIGCHLD, SIG_IGN);
303
307 umh_complete(sub_info); 304 umh_complete(sub_info);
308 do_exit(0);
309} 305}
310 306
311/* 307/*
312 * This function doesn't strictly needs to be called asynchronously. But we 308 * We need to create the usermodehelper kernel thread from a task that is affine
313 * need to create the usermodehelper kernel threads from a task that is affine
314 * to an optimized set of CPUs (or nohz housekeeping ones) such that they 309 * to an optimized set of CPUs (or nohz housekeeping ones) such that they
315 * inherit a widest affinity irrespective of call_usermodehelper() callers with 310 * inherit a widest affinity irrespective of call_usermodehelper() callers with
316 * possibly reduced affinity (eg: per-cpu workqueues). We don't want 311 * possibly reduced affinity (eg: per-cpu workqueues). We don't want
317 * usermodehelper targets to contend a busy CPU. 312 * usermodehelper targets to contend a busy CPU.
318 * 313 *
319 * Unbound workqueues provide such wide affinity. 314 * Unbound workqueues provide such wide affinity and allow to block on
315 * UMH_WAIT_PROC requests without blocking pending request (up to some limit).
320 * 316 *
321 * Besides, workqueues provide the privilege level that caller might not have 317 * Besides, workqueues provide the privilege level that caller might not have
322 * to perform the usermodehelper request. 318 * to perform the usermodehelper request.
@@ -326,18 +322,18 @@ static void call_usermodehelper_exec_work(struct work_struct *work)
326{ 322{
327 struct subprocess_info *sub_info = 323 struct subprocess_info *sub_info =
328 container_of(work, struct subprocess_info, work); 324 container_of(work, struct subprocess_info, work);
329 pid_t pid;
330 325
331 if (sub_info->wait & UMH_WAIT_PROC) 326 if (sub_info->wait & UMH_WAIT_PROC) {
332 pid = kernel_thread(call_usermodehelper_exec_sync, sub_info, 327 call_usermodehelper_exec_sync(sub_info);
333 CLONE_FS | CLONE_FILES | SIGCHLD); 328 } else {
334 else 329 pid_t pid;
330
335 pid = kernel_thread(call_usermodehelper_exec_async, sub_info, 331 pid = kernel_thread(call_usermodehelper_exec_async, sub_info,
336 SIGCHLD); 332 SIGCHLD);
337 333 if (pid < 0) {
338 if (pid < 0) { 334 sub_info->retval = pid;
339 sub_info->retval = pid; 335 umh_complete(sub_info);
340 umh_complete(sub_info); 336 }
341 } 337 }
342} 338}
343 339