All of lore.kernel.org
 help / color / mirror / Atom feed
From: Uli Luckas <u.luckas@road.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Subject: Re: [PATCH -mm 2/2] PM: Disable usermode helper before hibernation and suspend
Date: Mon, 18 Jun 2007 20:23:45 +0200	[thread overview]
Message-ID: <200706182023.45984.u.luckas@road.de> (raw)
In-Reply-To: <200706181715.15017.rjw@sisk.pl>

On Monday, 18. June 2007, you wrote:
> On Monday, 18 June 2007 12:51, Uli Luckas wrote:
> > On Sunday, 17. June 2007, you wrote:
> > > On Friday, 15 June 2007 23:36, Rafael J. Wysocki wrote:
> > > > On Friday, 15 June 2007 15:08, Uli Luckas wrote:
> > > > > On Monday, 4. June 2007, Rafael J. Wysocki wrote:
> > > > > > From: Rafael J. Wysocki <rjw@sisk.pl>
> > > > > >
> > > > > > Use a hibernation and suspend notifier to disable the user mode
> > > > > > helper before a hibernation/suspend and enable it after the
> > > > > > operation.
> > > > >
> > > > > Hi Rafael,
> > > > > I have a couple of questions, regarding this patch ...
> > > > >
> > > > > 2) how does your patch prevent wait_for_completion(&done) to hang
> > > > > during freezing if usermodehelper_pm_callback is called _after_ the
> > > > > above check?
> > > >
> > > > It doesn't.  Once the helper is running, we can't distinguish it from
> > > > any other user land process.
> > > >
> > > > Still, it narrows the window quite a bit.
> > >
> > > Okay, I think we can help it a bit.  Please tell me what you think of
> > > the following patch (on top of 2.6.22-rc4-mm2).
> >
> > Hi Rafael,
> > Thanks for your work. I haven't found the time to actually test your
> > patch but in general it looks like a valid aproach.
> > I think there is one problem though. You need to have your wait queue
> > woken up when you update (atomic_dec) running_helpers. Otherwise you end
> > up always waiting the full RUNNING_HELPERS_TIMEOUT.
>
> Yeah, right.  I tend to forget about obvious things. :-(
>
Great. As far as I can see, this patch should now fix the situation except 
under heavy load where it would abort the attempted suspend. I can live with 
that and it is a whole lot better than it was before - Thanks.

> Besides, I think that the _pm_callback need not be compiled if CONFIG_PM is
> unset.  
>
Should work but is probably beneath what you intended to do. I'll comment 
further down...

> If you can, please have a look at the next version of the patch 
> (appended).
>
One more topic to keep in mind for the future. None of the callers of 
call_usermode_helper* expect a return value of EBUSY nor do they handle it 
correctly. If auto loading of a module for example fails, a permanent error 
is usually assumed and no retry attempts are made. 

> Greetings,
> Rafael
>
>
> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> ---
>  kernel/kmod.c |   76
> ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed,
> 66 insertions(+), 10 deletions(-)
>
> Index: linux-2.6.22-rc4-mm2/kernel/kmod.c
> ===================================================================
> --- linux-2.6.22-rc4-mm2.orig/kernel/kmod.c
> +++ linux-2.6.22-rc4-mm2/kernel/kmod.c
> @@ -41,14 +41,6 @@ extern int max_threads;
>
>  static struct workqueue_struct *khelper_wq;
>
> -/*
> - * If set, both call_usermodehelper_keys() and call_usermodehelper_pipe()
> exit - * immediately returning -EBUSY.  Used for preventing user land
> processes from - * being created after the user land has been frozen during
> a system-wide - * hibernation or suspend operation.
> - */
> -static int usermodehelper_disabled;
> -
>  #ifdef CONFIG_KMOD
>
>  /*
> @@ -275,6 +267,30 @@ static void __call_usermodehelper(struct
>  	}
>  }
>
> +#ifdef CONFIG_PM
> +/*
> + * If set and if call_usermodehelper_exec() is supposed to wait, it will
> exit + * immediately returning -EBUSY (used for preventing user land
> processes from + * being created after the user land has been frozen during
> a system-wide + * hibernation or suspend operation).
> + */
> +static int usermodehelper_disabled;
> +
> +/* Number of helpers running */
> +static atomic_t running_helpers = ATOMIC_INIT(0);
> +
> +/*
> + * Wait queue head used by usermodehelper_pm_callback() to wait for all
> running + * helpers to finish.
> + */
> +static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq);
> +
> +/*
> + * Time to wait for running_helpers to become zero before the setting of
> + * usermodehelper_disabled in usermodehelper_pm_callback() fails
> + */
> +#define RUNNING_HELPERS_TIMEOUT	(5 * HZ)
> +
>  static int usermodehelper_pm_callback(struct notifier_block *nfb,
>  					unsigned long action,
>  					void *ignored)
> @@ -283,7 +299,15 @@ static int usermodehelper_pm_callback(st
>  	case PM_HIBERNATION_PREPARE:
>  	case PM_SUSPEND_PREPARE:
>  		usermodehelper_disabled = 1;
> -		return NOTIFY_OK;
> +		wait_event_timeout(running_helpers_waitq,
> +					atomic_read(&running_helpers) == 0,
> +					RUNNING_HELPERS_TIMEOUT);
> +		if (atomic_read(&running_helpers) == 0) {
> +			return NOTIFY_OK;
> +		} else {
> +			usermodehelper_disabled = 0;
> +			return NOTIFY_BAD;
> +		}
>  	case PM_POST_HIBERNATION:
>  	case PM_POST_SUSPEND:
>  		usermodehelper_disabled = 0;
> @@ -293,6 +317,36 @@ static int usermodehelper_pm_callback(st
>  	return NOTIFY_DONE;
>  }
>
> +static void new_helper(void)
> +{
> +	atomic_inc(&running_helpers);
> +}
> +
> +static void helper_finished(void)
> +{
> +	if (atomic_dec_and_test(&running_helpers))
> +		wake_up(&running_helpers_waitq);
> +}
> +
> +#else /* CONFIG_PM */
> +#define usermodehelper_disabled	0
> +
> +static inline int usermodehelper_pm_callback(struct notifier_block *nfb,
          ^^^^^^
This kind of implies, the compiler might optimize this function away. Further 
down you call "pm_notifier(usermodehelper_pm_callback, 0);", thereby passing 
a pointer to usermodehelper_pm_callback which can't be inlined nor optimized 
away. If instead you had an inline function 
register_usermodehelper_pm_callback which called pm_notifier if CONFIG_PM was 
defined and did nothing otherwise...

> +						unsigned long action,
> +						void *ignored)
> +{
> +	return 0;
> +}
> +
> +static inline void new_helper(void)
> +{
> +}
> +
> +static inline void helper_finished(void)
> +{
> +}
> +#endif /* CONFIG_PM */
> +
>  /**
>   * call_usermodehelper_setup - prepare to call a usermode helper
>   * @path - path to usermode executable
> @@ -397,12 +451,13 @@ int call_usermodehelper_exec(struct subp
>  	DECLARE_COMPLETION_ONSTACK(done);
>  	int retval;
>
> +	new_helper();
>  	if (sub_info->path[0] == '\0') {
>  		retval = 0;
>  		goto out;
>  	}
>
> -	if (!khelper_wq || usermodehelper_disabled) {
> +	if (!khelper_wq || (wait != UMH_NO_WAIT && usermodehelper_disabled)) {
>  		retval = -EBUSY;
>  		goto out;
>  	}
> @@ -418,6 +473,7 @@ int call_usermodehelper_exec(struct subp
>
>    out:
>  	call_usermodehelper_freeinfo(sub_info);
> +	helper_finished();
>  	return retval;
>  }
>  EXPORT_SYMBOL(call_usermodehelper_exec);


-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 64 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing directors: Hans-Peter Constien, Hubertus von Streit

      reply	other threads:[~2007-06-18 18:24 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-06-04 21:25 [PATCH -mm 0/2] PM: Hibernation and suspend notifiers Rafael J. Wysocki
2007-06-04 21:27 ` [PATCH -mm 1/2] PM: Introduce hibernation " Rafael J. Wysocki
2007-06-04 21:28 ` [PATCH -mm 2/2] PM: Disable usermode helper before hibernation and suspend Rafael J. Wysocki
2007-06-04 21:33   ` Nigel Cunningham
2007-06-15 13:08   ` Uli Luckas
2007-06-15 21:36     ` Rafael J. Wysocki
2007-06-17 19:24       ` Rafael J. Wysocki
2007-06-18 10:51         ` Uli Luckas
2007-06-18 15:15           ` Rafael J. Wysocki
2007-06-18 18:23             ` Uli Luckas [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200706182023.45984.u.luckas@road.de \
    --to=u.luckas@road.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rjw@sisk.pl \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.