Rafael J. Wysocki wrote:
>
>  static int usermodehelper_pm_callback(struct notifier_block *nfb,
>                                       unsigned long action,
>                                       void *ignored)
>  {
> +     long retval;
> +
>       switch (action) {
>       case PM_HIBERNATION_PREPARE:
>       case PM_SUSPEND_PREPARE:
>               usermodehelper_disabled = 1;
> -             return NOTIFY_OK;
> +             /*
> +              * From now on call_usermodehelper_exec() won't start any new
> +              * helpers, so it is sufficient if running_helpers turns out to
> +              * be zero at one point (it may be increased later, but that
> +              * doesn't matter).
> +              */
> +             retval = wait_event_timeout(running_helpers_waitq,
> +                                     atomic_read(&running_helpers) == 0,
> +                                     RUNNING_HELPERS_TIMEOUT);
> +             if (retval) {
> +                     return NOTIFY_OK;
> +             } else {
> +                     usermodehelper_disabled = 0;
> +                     return NOTIFY_BAD;

I think this is racy. First, this needs smp_mb() between 
"usermodehelper_disabled = 1"
and wait_event_timeout().

Second, call_usermodehelper's path should first increment the counter, and only
then check usermodehelper_disabled, and it needs an mb() in between too. 
Otherwise,
the helper can see usermodehelper_disabled == 0, then PM_SUSPEND_PREPARE comes 
and
returns NOTIFY_OK, then the helper increments the counter and starts 
application.

Sadly, you can't use srcu/qrcu because it doesn't handle timeouts.      

Oleg.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to