diff options
Diffstat (limited to 'kernel/kmod.c')
-rw-r--r-- | kernel/kmod.c | 58 |
1 files changed, 45 insertions, 13 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c index 4079ac1d5e79..da7fcca279f9 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
@@ -334,6 +334,12 @@ static atomic_t running_helpers = ATOMIC_INIT(0); | |||
334 | static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq); | 334 | static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq); |
335 | 335 | ||
336 | /* | 336 | /* |
337 | * Used by usermodehelper_read_lock_wait() to wait for usermodehelper_disabled | ||
338 | * to become 'false'. | ||
339 | */ | ||
340 | static DECLARE_WAIT_QUEUE_HEAD(usermodehelper_disabled_waitq); | ||
341 | |||
342 | /* | ||
337 | * Time to wait for running_helpers to become zero before the setting of | 343 | * Time to wait for running_helpers to become zero before the setting of |
338 | * usermodehelper_disabled in usermodehelper_disable() fails | 344 | * usermodehelper_disabled in usermodehelper_disable() fails |
339 | */ | 345 | */ |
@@ -352,6 +358,33 @@ int usermodehelper_read_trylock(void) | |||
352 | } | 358 | } |
353 | EXPORT_SYMBOL_GPL(usermodehelper_read_trylock); | 359 | EXPORT_SYMBOL_GPL(usermodehelper_read_trylock); |
354 | 360 | ||
361 | long usermodehelper_read_lock_wait(long timeout) | ||
362 | { | ||
363 | DEFINE_WAIT(wait); | ||
364 | |||
365 | if (timeout < 0) | ||
366 | return -EINVAL; | ||
367 | |||
368 | down_read(&umhelper_sem); | ||
369 | for (;;) { | ||
370 | prepare_to_wait(&usermodehelper_disabled_waitq, &wait, | ||
371 | TASK_UNINTERRUPTIBLE); | ||
372 | if (!usermodehelper_disabled) | ||
373 | break; | ||
374 | |||
375 | up_read(&umhelper_sem); | ||
376 | |||
377 | timeout = schedule_timeout(timeout); | ||
378 | if (!timeout) | ||
379 | break; | ||
380 | |||
381 | down_read(&umhelper_sem); | ||
382 | } | ||
383 | finish_wait(&usermodehelper_disabled_waitq, &wait); | ||
384 | return timeout; | ||
385 | } | ||
386 | EXPORT_SYMBOL_GPL(usermodehelper_read_lock_wait); | ||
387 | |||
355 | void usermodehelper_read_unlock(void) | 388 | void usermodehelper_read_unlock(void) |
356 | { | 389 | { |
357 | up_read(&umhelper_sem); | 390 | up_read(&umhelper_sem); |
@@ -359,6 +392,17 @@ void usermodehelper_read_unlock(void) | |||
359 | EXPORT_SYMBOL_GPL(usermodehelper_read_unlock); | 392 | EXPORT_SYMBOL_GPL(usermodehelper_read_unlock); |
360 | 393 | ||
361 | /** | 394 | /** |
395 | * usermodehelper_enable - allow new helpers to be started again | ||
396 | */ | ||
397 | void usermodehelper_enable(void) | ||
398 | { | ||
399 | down_write(&umhelper_sem); | ||
400 | usermodehelper_disabled = 0; | ||
401 | wake_up(&usermodehelper_disabled_waitq); | ||
402 | up_write(&umhelper_sem); | ||
403 | } | ||
404 | |||
405 | /** | ||
362 | * usermodehelper_disable - prevent new helpers from being started | 406 | * usermodehelper_disable - prevent new helpers from being started |
363 | */ | 407 | */ |
364 | int usermodehelper_disable(void) | 408 | int usermodehelper_disable(void) |
@@ -381,22 +425,10 @@ int usermodehelper_disable(void) | |||
381 | if (retval) | 425 | if (retval) |
382 | return 0; | 426 | return 0; |
383 | 427 | ||
384 | down_write(&umhelper_sem); | 428 | usermodehelper_enable(); |
385 | usermodehelper_disabled = 0; | ||
386 | up_write(&umhelper_sem); | ||
387 | return -EAGAIN; | 429 | return -EAGAIN; |
388 | } | 430 | } |
389 | 431 | ||
390 | /** | ||
391 | * usermodehelper_enable - allow new helpers to be started again | ||
392 | */ | ||
393 | void usermodehelper_enable(void) | ||
394 | { | ||
395 | down_write(&umhelper_sem); | ||
396 | usermodehelper_disabled = 0; | ||
397 | up_write(&umhelper_sem); | ||
398 | } | ||
399 | |||
400 | static void helper_lock(void) | 432 | static void helper_lock(void) |
401 | { | 433 | { |
402 | atomic_inc(&running_helpers); | 434 | atomic_inc(&running_helpers); |