diff options
Diffstat (limited to 'kernel/kmod.c')
-rw-r--r-- | kernel/kmod.c | 47 |
1 files changed, 37 insertions, 10 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c index da7fcca279f9..05698a7415fe 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
@@ -322,7 +322,7 @@ static void __call_usermodehelper(struct work_struct *work) | |||
322 | * land has been frozen during a system-wide hibernation or suspend operation). | 322 | * land has been frozen during a system-wide hibernation or suspend operation). |
323 | * Should always be manipulated under umhelper_sem acquired for write. | 323 | * Should always be manipulated under umhelper_sem acquired for write. |
324 | */ | 324 | */ |
325 | static int usermodehelper_disabled = 1; | 325 | static enum umh_disable_depth usermodehelper_disabled = UMH_DISABLED; |
326 | 326 | ||
327 | /* Number of helpers running */ | 327 | /* Number of helpers running */ |
328 | static atomic_t running_helpers = ATOMIC_INIT(0); | 328 | static atomic_t running_helpers = ATOMIC_INIT(0); |
@@ -347,13 +347,30 @@ static DECLARE_WAIT_QUEUE_HEAD(usermodehelper_disabled_waitq); | |||
347 | 347 | ||
348 | int usermodehelper_read_trylock(void) | 348 | int usermodehelper_read_trylock(void) |
349 | { | 349 | { |
350 | DEFINE_WAIT(wait); | ||
350 | int ret = 0; | 351 | int ret = 0; |
351 | 352 | ||
352 | down_read(&umhelper_sem); | 353 | down_read(&umhelper_sem); |
353 | if (usermodehelper_disabled) { | 354 | for (;;) { |
355 | prepare_to_wait(&usermodehelper_disabled_waitq, &wait, | ||
356 | TASK_INTERRUPTIBLE); | ||
357 | if (!usermodehelper_disabled) | ||
358 | break; | ||
359 | |||
360 | if (usermodehelper_disabled == UMH_DISABLED) | ||
361 | ret = -EAGAIN; | ||
362 | |||
354 | up_read(&umhelper_sem); | 363 | up_read(&umhelper_sem); |
355 | ret = -EAGAIN; | 364 | |
365 | if (ret) | ||
366 | break; | ||
367 | |||
368 | schedule(); | ||
369 | try_to_freeze(); | ||
370 | |||
371 | down_read(&umhelper_sem); | ||
356 | } | 372 | } |
373 | finish_wait(&usermodehelper_disabled_waitq, &wait); | ||
357 | return ret; | 374 | return ret; |
358 | } | 375 | } |
359 | EXPORT_SYMBOL_GPL(usermodehelper_read_trylock); | 376 | EXPORT_SYMBOL_GPL(usermodehelper_read_trylock); |
@@ -392,25 +409,35 @@ void usermodehelper_read_unlock(void) | |||
392 | EXPORT_SYMBOL_GPL(usermodehelper_read_unlock); | 409 | EXPORT_SYMBOL_GPL(usermodehelper_read_unlock); |
393 | 410 | ||
394 | /** | 411 | /** |
395 | * usermodehelper_enable - allow new helpers to be started again | 412 | * __usermodehelper_set_disable_depth - Modify usermodehelper_disabled. |
413 | * depth: New value to assign to usermodehelper_disabled. | ||
414 | * | ||
415 | * Change the value of usermodehelper_disabled (under umhelper_sem locked for | ||
416 | * writing) and wakeup tasks waiting for it to change. | ||
396 | */ | 417 | */ |
397 | void usermodehelper_enable(void) | 418 | void __usermodehelper_set_disable_depth(enum umh_disable_depth depth) |
398 | { | 419 | { |
399 | down_write(&umhelper_sem); | 420 | down_write(&umhelper_sem); |
400 | usermodehelper_disabled = 0; | 421 | usermodehelper_disabled = depth; |
401 | wake_up(&usermodehelper_disabled_waitq); | 422 | wake_up(&usermodehelper_disabled_waitq); |
402 | up_write(&umhelper_sem); | 423 | up_write(&umhelper_sem); |
403 | } | 424 | } |
404 | 425 | ||
405 | /** | 426 | /** |
406 | * usermodehelper_disable - prevent new helpers from being started | 427 | * __usermodehelper_disable - Prevent new helpers from being started. |
428 | * @depth: New value to assign to usermodehelper_disabled. | ||
429 | * | ||
430 | * Set usermodehelper_disabled to @depth and wait for running helpers to exit. | ||
407 | */ | 431 | */ |
408 | int usermodehelper_disable(void) | 432 | int __usermodehelper_disable(enum umh_disable_depth depth) |
409 | { | 433 | { |
410 | long retval; | 434 | long retval; |
411 | 435 | ||
436 | if (!depth) | ||
437 | return -EINVAL; | ||
438 | |||
412 | down_write(&umhelper_sem); | 439 | down_write(&umhelper_sem); |
413 | usermodehelper_disabled = 1; | 440 | usermodehelper_disabled = depth; |
414 | up_write(&umhelper_sem); | 441 | up_write(&umhelper_sem); |
415 | 442 | ||
416 | /* | 443 | /* |
@@ -425,7 +452,7 @@ int usermodehelper_disable(void) | |||
425 | if (retval) | 452 | if (retval) |
426 | return 0; | 453 | return 0; |
427 | 454 | ||
428 | usermodehelper_enable(); | 455 | __usermodehelper_set_disable_depth(UMH_ENABLED); |
429 | return -EAGAIN; | 456 | return -EAGAIN; |
430 | } | 457 | } |
431 | 458 | ||