aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2015-09-09 18:38:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-10 16:29:01 -0400
commitb639e86bae431db3fbc9fae8d09a9bbf97b74711 (patch)
tree8a0f6c47b7d8d5571b71e7d80f32d09e2261d216
parentd097c0240ae8085dd39aa6ca9bd9960969b2b38e (diff)
kmod: add up-to-date explanations on the purpose of each asynchronous levels
There seem to be quite some confusions on the comments, likely due to changes that came after them. Now since it's very non obvious why we have 3 levels of asynchronous code to implement usermodehelpers, it's important to comment in detail the reason of this layout. 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.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c
index d910b6378fb6..81c67050c5aa 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -225,8 +225,8 @@ static int call_usermodehelper_exec_async(void *data)
225 spin_unlock_irq(&current->sighand->siglock); 225 spin_unlock_irq(&current->sighand->siglock);
226 226
227 /* 227 /*
228 * Our parent is keventd, which runs with elevated scheduling priority. 228 * Our parent is khelper which runs with elevated scheduling
229 * Avoid propagating that into the userspace child. 229 * priority. Avoid propagating that into the userspace child.
230 */ 230 */
231 set_user_nice(current, 0); 231 set_user_nice(current, 0);
232 232
@@ -267,7 +267,11 @@ out:
267 do_exit(0); 267 do_exit(0);
268} 268}
269 269
270/* Keventd can't block, but this (a child) can. */ 270/*
271 * Handles UMH_WAIT_PROC. Our parent khelper can't wait for usermodehelper
272 * completion without blocking every other pending requests. That's why
273 * we use a kernel thread dedicated for that purpose.
274 */
271static int call_usermodehelper_exec_sync(void *data) 275static int call_usermodehelper_exec_sync(void *data)
272{ 276{
273 struct subprocess_info *sub_info = data; 277 struct subprocess_info *sub_info = data;
@@ -283,8 +287,8 @@ static int call_usermodehelper_exec_sync(void *data)
283 /* 287 /*
284 * Normally it is bogus to call wait4() from in-kernel because 288 * Normally it is bogus to call wait4() from in-kernel because
285 * wait4() wants to write the exit code to a userspace address. 289 * wait4() wants to write the exit code to a userspace address.
286 * But call_usermodehelper_exec_sync() always runs as keventd, 290 * But call_usermodehelper_exec_sync() always runs as kernel
287 * and put_user() to a kernel address works OK for kernel 291 * thread and put_user() to a kernel address works OK for kernel
288 * threads, due to their having an mm_segment_t which spans the 292 * threads, due to their having an mm_segment_t which spans the
289 * entire address space. 293 * entire address space.
290 * 294 *
@@ -305,7 +309,19 @@ static int call_usermodehelper_exec_sync(void *data)
305 do_exit(0); 309 do_exit(0);
306} 310}
307 311
308/* This is run by khelper thread */ 312/*
313 * This function doesn't strictly needs to be called asynchronously. But we
314 * need to create the usermodehelper kernel threads from a task that is affine
315 * to all CPUs (or nohz housekeeping ones) such that they inherit a widest
316 * affinity irrespective of call_usermodehelper() callers with possibly reduced
317 * affinity (eg: per-cpu workqueues). We don't want usermodehelper targets to
318 * contend any busy CPU.
319 * Khelper provides such wide affinity.
320 *
321 * Besides, khelper provides the privilege level that caller might not have to
322 * perform the usermodehelper request.
323 *
324 */
309static void call_usermodehelper_exec_work(struct work_struct *work) 325static void call_usermodehelper_exec_work(struct work_struct *work)
310{ 326{
311 struct subprocess_info *sub_info = 327 struct subprocess_info *sub_info =
@@ -533,8 +549,8 @@ EXPORT_SYMBOL(call_usermodehelper_setup);
533 * from interrupt context. 549 * from interrupt context.
534 * 550 *
535 * Runs a user-space application. The application is started 551 * Runs a user-space application. The application is started
536 * asynchronously if wait is not set, and runs as a child of keventd. 552 * asynchronously if wait is not set, and runs as a child of khelper.
537 * (ie. it runs with full root capabilities). 553 * (ie. it runs with full root capabilities and wide affinity).
538 */ 554 */
539int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) 555int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
540{ 556{