All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Boyd <sboyd@codeaurora.org>
To: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Saravana Kannan <skannan@codeaurora.org>,
	Kay Sievers <kay.sievers@vrfy.org>,
	Greg KH <gregkh@linuxfoundation.org>,
	Christian Lamparter <chunkeey@googlemail.com>,
	linux-kernel@vger.kernel.org,
	"Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>,
	alan@lxorguk.ukuu.org.uk,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Linux PM mailing list <linux-pm@vger.kernel.org>
Subject: Re: [PATCH] firmware loader: don't cancel _nowait requests when helper is not yet available
Date: Fri, 16 Mar 2012 19:47:53 -0700	[thread overview]
Message-ID: <4F63FB59.9010104@codeaurora.org> (raw)
In-Reply-To: <201203150111.05724.rjw@sisk.pl>

On 03/14/12 17:11, Rafael J. Wysocki wrote:
> On Thursday, March 15, 2012, Stephen Boyd wrote:
>> On 03/14/12 16:34, Rafael J. Wysocki wrote:
>>> On Thursday, March 15, 2012, Stephen Boyd wrote:
>>>> On 03/14/12 16:13, Rafael J. Wysocki wrote:
>>>>> On Thursday, March 15, 2012, Rafael J. Wysocki wrote:
>>>>>
>>>>>> Which is OK, I think.
>>>>> Moreover, thaw_kernel_threads() is _only_ called by (a) freeze_kernel_threads()
>>>>> on error and (b) user-space hibernate interface in kernel/power/user.c
>>>>> (and please read the comment in there describing what it's there for, which
>>>>> also explains why the schedule() call in there is necessary).
>>>> Exactly. So in case (a) when the error occurs we'll have this call flow:
>>>>
>>>> usermodehelpers_disable()
>>>> suspend_freeze_processes()
>>>>     freeze_processes()
>>>>     freeze_kernel_threads()
>>>>         try_to_freeze_tasks() <-- returns error
>>>>         thaw_kernel_threads()
>>>>             schedule()
>>>>     thaw_processes()
>>>> usermodehelpers_enable()
>>>>
>>>> Shouldn't we schedule only after we thaw all processes (not just tasks)?
>>>> Otherwise we may run a kernel thread before userspace is thawed?
>>> Yes, we may, but that isn't wrong, is it?
>>>
>>> Only a few kernel threads are freezable, so definitely kernel threads
>>> can run while user space is frozen.
>>>
>> Yes but if someone calls request_firmware() from a kthread then they
>> will hit the same problem where the thread runs and requests the
>> firmware and usermodehelpers are still disabled. Currently my code is
>> written with kthreads and that thread makes the request firmware call,
>> so this doesn't seem far fetched (although in my case I can probably fix
>> it).
> So again, please consider using suspend/resume notifiers to synchronize
> your kthread with system power transitions.

Ah. Freezable workqueues and threads are entirely not what I want. I
have to use suspend/resume notifiers so that I don't call
request_firmware() until suspend is over and I have to synchronize that
with a rwsem so that suspend is blocked until my call to
request_firmware() completes (and so request_firmware() is blocked until
suspend completes). Every user of request_firmware() has to do the same
check or be certain that their code won't run during a system-wide
suspend/resume.  Ouch.

Can we fix this in the core firmware loading code somehow? I really want
to have a way to differentiate between tasks that can block suspend from
progressing and tasks that won't. This way everyone who doesn't care
about suspend can still call request_firmware() and go to sleep if we're
in the middle of suspending and the ones who would block suspend get
failed immediately. That would seem to be more in line with why this
patch was made (i.e. don't block suspend/resume from progressing with
request_firmware() calls).

What about this? It basically keeps track of which task is the
suspending task and then only fails that one. I'm not completely sold on
this one but it would work most of the time.

---8<-----

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 6c9387d..5127534 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -533,9 +533,7 @@ static int _request_firmware(const struct firmware **firmware_p,
 		return 0;
 	}
 
-	read_lock_usermodehelper();
-
-	if (WARN_ON(usermodehelper_is_disabled())) {
+	if (is_sleep_task()) {
 		dev_err(device, "firmware: %s will not be loaded\n", name);
 		retval = -EBUSY;
 		goto out;
@@ -550,6 +548,7 @@ static int _request_firmware(const struct firmware **firmware_p,
 		goto out;
 	}
 
+	read_lock_usermodehelper();
 	if (uevent) {
 		if (loading_timeout > 0)
 			mod_timer(&fw_priv->timeout,
@@ -560,6 +559,7 @@ static int _request_firmware(const struct firmware **firmware_p,
 	}
 
 	wait_for_completion(&fw_priv->completion);
+	read_unlock_usermodehelper();
 
 	set_bit(FW_STATUS_DONE, &fw_priv->status);
 	del_timer_sync(&fw_priv->timeout);
@@ -573,7 +573,6 @@ static int _request_firmware(const struct firmware **firmware_p,
 	fw_destroy_instance(fw_priv);
 
 out:
-	read_unlock_usermodehelper();
 
 	if (retval) {
 		release_firmware(firmware);
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 9efeae6..d84da8c 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -115,6 +115,7 @@ extern void usermodehelper_init(void);
 extern int usermodehelper_disable(void);
 extern void usermodehelper_enable(void);
 extern bool usermodehelper_is_disabled(void);
+extern bool is_sleep_task(void);
 extern void read_lock_usermodehelper(void);
 extern void read_unlock_usermodehelper(void);
 
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 9faa560..50fae27 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -368,6 +368,13 @@ void read_unlock_usermodehelper(void)
 }
 EXPORT_SYMBOL_GPL(read_unlock_usermodehelper);
 
+static struct task_struct *system_sleep_task;
+
+bool is_sleep_task(void)
+{
+	return current == system_sleep_task;
+}
+
 /**
  * usermodehelper_disable - prevent new helpers from being started
  */
@@ -375,9 +382,9 @@ int usermodehelper_disable(void)
 {
 	long retval;
 
+	system_sleep_task = current;
 	down_write(&umhelper_sem);
 	usermodehelper_disabled = 1;
-	up_write(&umhelper_sem);
 
 	/*
 	 * From now on call_usermodehelper_exec() won't start any new
@@ -391,9 +398,9 @@ int usermodehelper_disable(void)
 	if (retval)
 		return 0;
 
-	down_write(&umhelper_sem);
 	usermodehelper_disabled = 0;
 	up_write(&umhelper_sem);
+	system_sleep_task = NULL;
 	return -EAGAIN;
 }
 
@@ -402,9 +409,9 @@ int usermodehelper_disable(void)
  */
 void usermodehelper_enable(void)
 {
-	down_write(&umhelper_sem);
 	usermodehelper_disabled = 0;
 	up_write(&umhelper_sem);
+	system_sleep_task = NULL;
 }
 
 /**
-- 


Or maybe we should modify request_firmware_nowait() to have the suspend
notifier checks? Right now if I call request_firmware_nowait() from a
probe it just might happen to fail because the kthread could run before
resume is complete. I didn't call request_firmware(), so I really tried
not to block resume progress but I'm gambling that resume will be over
before my thread runs. I could write notifier rwsem code and then wait
for resume to finish before calling request_firmware_nowat(), but that
would require me to fork a thread/workqueue to run
request_firmware_nowait() which will then fork a thread again. Seems
useless to even use request_firmware_nowait() then.

How about this totally untested patch? We do the rwsem thing for
request_firmware_nowait() at least.
----8<-----

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 6c9387d..f320ccd 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -20,6 +20,8 @@
 #include <linux/highmem.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/suspend.h>
+#include <linux/rwsem.h>
 
 #define to_dev(obj) container_of(obj, struct device, kobj)
 
@@ -629,6 +631,9 @@ struct firmware_work {
 	bool uevent;
 };
 
+/* Synchronize request_firmware_work_func() with suspend */
+static DECLARE_RWSEM(fw_pm_rwsem);
+
 static int request_firmware_work_func(void *arg)
 {
 	struct firmware_work *fw_work = arg;
@@ -640,8 +645,10 @@ static int request_firmware_work_func(void *arg)
 		return 0;
 	}
 
+	down_read(&fw_pm_rwsem);
 	ret = _request_firmware(&fw, fw_work->name, fw_work->device,
 				fw_work->uevent, true);
+	up_read(&fw_pm_rwsem);
 	fw_work->cont(fw, fw_work->context);
 
 	module_put(fw_work->module);
@@ -704,13 +711,33 @@ request_firmware_nowait(
 	return 0;
 }
 
+static int firmware_class_pm_notify(struct notifier_block *block,
+		unsigned long event, void *p)
+{
+	switch (event) {
+	case PM_SUSPEND_PREPARE:
+		down_write(&fw_pm_rwsem);
+		break;
+	case PM_POST_SUSPEND:
+		up_write(&fw_pm_rwsem);
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block firmware_class_pm_notifier = {
+	.notifier_call = firmware_class_pm_notify,
+};
+
 static int __init firmware_class_init(void)
 {
+	register_pm_notifier(&firmware_class_pm_notifier);
 	return class_register(&firmware_class);
 }
 
 static void __exit firmware_class_exit(void)
 {
+	unregister_pm_notifier(&firmware_class_pm_notifier);
 	class_unregister(&firmware_class);
 }
 
-- 


Hmm it seems something similar is going on in the other part of the
thread. I'll work something up in a few hours.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


  parent reply	other threads:[~2012-03-17  2:47 UTC|newest]

Thread overview: 111+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-03 20:22 [RFC] firmware loader: retry _nowait requests when userhelper is not yet available Christian Lamparter
2012-03-03 23:57 ` Alan Cox
2012-03-04  1:50   ` Christian Lamparter
2012-03-05 20:12 ` Srivatsa S. Bhat
2012-03-09 22:30   ` [PATCH] firmware loader: don't cancel _nowait requests when helper " Christian Lamparter
2012-03-09 23:36     ` Greg KH
2012-03-10  0:52       ` Christian Lamparter
2012-03-11 11:56       ` Kay Sievers
2012-03-13  9:37         ` Saravana Kannan
2012-03-13  9:43         ` Saravana Kannan
2012-03-13 20:14           ` Rafael J. Wysocki
2012-03-14 19:21             ` Stephen Boyd
2012-03-14 23:04               ` Rafael J. Wysocki
2012-03-14 23:13                 ` Rafael J. Wysocki
2012-03-14 23:17                   ` Stephen Boyd
2012-03-14 23:34                     ` Rafael J. Wysocki
2012-03-14 23:38                       ` Stephen Boyd
2012-03-15  0:11                         ` Rafael J. Wysocki
2012-03-15 19:50                           ` [PATCH] firmware_class: Move request_firmware_nowait() to workqueues Stephen Boyd
2012-03-15 20:07                             ` Christian Lamparter
2012-03-15 20:12                               ` Stephen Boyd
2012-03-15 22:31                                 ` Rafael J. Wysocki
2012-03-16  1:39                                   ` Stephen Boyd
2012-03-16 20:19                                     ` Rafael J. Wysocki
2012-03-16 20:26                                       ` Stephen Boyd
2012-03-16 21:45                                         ` Rafael J. Wysocki
2012-03-16 22:18                                           ` Christian Lamparter
2012-03-16 22:35                                             ` Rafael J. Wysocki
2012-03-17  2:47                           ` Stephen Boyd [this message]
2012-03-17  5:51                             ` [PATCH] firmware loader: don't cancel _nowait requests when helper is not yet available Linus Torvalds
2012-03-17 20:06                               ` Rafael J. Wysocki
2012-03-18  8:26                               ` Stephen Boyd
2012-03-18 12:01                                 ` Rafael J. Wysocki
2012-03-19  6:32                                   ` Stephen Boyd
2012-03-19 11:24                                     ` Rafael J. Wysocki
2012-03-19 23:00                                       ` Rafael J. Wysocki
2012-03-25 22:00                                         ` [PATCH 0/6] firmware_class: Fix problems with usermodehelper test Rafael J. Wysocki
2012-03-25 22:01                                           ` [PATCH 1/6] firmware_class: Rework usermodehelper check Rafael J. Wysocki
2012-03-25 22:01                                           ` [PATCH 2/6] firmware_class: Split _request_firmware() into three functions Rafael J. Wysocki
2012-03-26 18:15                                             ` Stephen Boyd
2012-03-26 18:21                                               ` Stephen Boyd
2012-03-26 20:12                                                 ` Rafael J. Wysocki
2012-03-26 20:31                                                   ` Stephen Boyd
2012-03-26 20:36                                               ` Rafael J. Wysocki
2012-03-27 21:35                                                 ` Stephen Boyd
2012-03-27 21:51                                                   ` Rafael J. Wysocki
2012-03-25 22:02                                           ` [PATCH 3/6] firmware_class: Do not warn that system is not ready from async loads Rafael J. Wysocki
2012-03-25 22:03                                           ` [PATCH 4/6] PM / Hibernate: Disable usermode helpers right before freezing tasks Rafael J. Wysocki
2012-03-25 22:03                                           ` [PATCH 5/6] PM / Sleep: Move disabling of usermode helpers to the freezer Rafael J. Wysocki
2012-03-25 22:04                                           ` [PATCH 6/6] PM / Sleep: Mitigate race between the freezer and request_firmware() Rafael J. Wysocki
2012-03-26 18:16                                             ` Stephen Boyd
2012-03-26 20:06                                               ` Rafael J. Wysocki
2012-03-27 21:25                                                 ` Stephen Boyd
2012-03-27 21:37                                                   ` Rafael J. Wysocki
2012-03-26 18:42                                           ` [PATCH 0/6] firmware_class: Fix problems with usermodehelper test Greg KH
2012-03-26 20:37                                             ` Rafael J. Wysocki
2012-03-27 21:28                                           ` [PATCH 1/2] firmware_class: Reorganize fw_create_instance() Stephen Boyd
2012-03-27 21:47                                             ` Rafael J. Wysocki
2012-03-27 21:49                                               ` Greg KH
2012-03-27 21:56                                                 ` Rafael J. Wysocki
2012-03-27 21:28                                           ` [PATCH 2/2] firmware_class: Move request_firmware_nowait() to workqueues Stephen Boyd
2012-03-27 21:49                                             ` Rafael J. Wysocki
2012-03-27 22:01                                             ` Tejun Heo
2012-03-27 22:21                                               ` Rafael J. Wysocki
2012-03-27 22:48                                                 ` Tejun Heo
2012-03-27 22:55                                                   ` Rafael J. Wysocki
2012-03-27 23:02                                                     ` Stephen Boyd
2012-03-27 23:05                                                     ` Stephen Boyd
2012-03-28 21:19                                           ` [PATCH v2 0/8] firmware_class: Fix problems with usermodehelper test Rafael J. Wysocki
2012-03-28 21:20                                             ` [PATCH v2 1/8] firmware_class: Rework usermodehelper check Rafael J. Wysocki
2012-03-28 21:21                                             ` [PATCH v2 2/8] firmware_class: Split _request_firmware() into three functions, v2 Rafael J. Wysocki
2012-03-28 21:22                                             ` [PATCH v3 3/8] firmware_class: Do not warn that system is not ready from async loads Rafael J. Wysocki
2012-03-28 21:23                                             ` [PATCH v2 4/8] PM / Hibernate: Disable usermode helpers right before freezing tasks Rafael J. Wysocki
2012-03-28 21:23                                             ` [PATCH v2 5/8] PM / Sleep: Move disabling of usermode helpers to the freezer Rafael J. Wysocki
2012-03-28 21:24                                             ` [PATCH v2 6/8] PM / Sleep: Mitigate race between the freezer and request_firmware() Rafael J. Wysocki
2012-03-28 21:25                                             ` [PATCH v2 7/8] firmware_class: Reorganize fw_create_instance() Rafael J. Wysocki
2012-03-28 21:26                                             ` [PATCH v2 8/8] firmware_class: Move request_firmware_nowait() to workqueues Rafael J. Wysocki
2012-03-14 23:19                 ` [PATCH] firmware loader: don't cancel _nowait requests when helper is not yet available Rafael J. Wysocki
2012-03-13 19:42         ` Rafael J. Wysocki
2012-03-13 23:25           ` Kay Sievers
2012-03-14  0:10             ` Rafael J. Wysocki
2012-03-14  0:14               ` Kay Sievers
2012-03-14  0:54                 ` Linus Torvalds
2012-03-14  1:43                   ` Kay Sievers
2012-03-14  1:51                     ` Linus Torvalds
2012-03-14  1:55                       ` Kay Sievers
2012-03-14  2:00                         ` Kay Sievers
2012-03-14  2:21                         ` Linus Torvalds
2012-03-14 15:07               ` Srivatsa S. Bhat
2012-03-14 22:54                 ` Rafael J. Wysocki
2012-03-16  7:14                   ` Srivatsa S. Bhat
2012-03-16 20:23                     ` Rafael J. Wysocki
2012-03-16 21:14                       ` Christian Lamparter
2012-03-16 21:19                         ` Linus Torvalds
2012-03-19  7:06                         ` Srivatsa S. Bhat
2012-03-16 22:19   ` [RFC] firmware loader: retry _nowait requests when userhelper " Rafael J. Wysocki
2012-03-16 22:25     ` Christian Lamparter
2012-03-16 22:57       ` Rafael J. Wysocki
2012-03-16 23:35         ` Christian Lamparter
2012-03-16 23:37         ` Linus Torvalds
2012-03-17  0:23           ` Rafael J. Wysocki
2012-03-17  0:33             ` Linus Torvalds
2012-03-18  0:29               ` Rafael J. Wysocki
2012-03-18  2:21                 ` Linus Torvalds
2012-03-18 12:21                   ` Rafael J. Wysocki
2012-03-18 12:43                 ` Christian Lamparter
2012-03-18 23:15                   ` [PATCH 0/3] firmware_class: Fix problem with async requests (was: Re: [RFC] firmware loader: retry ...) Rafael J. Wysocki
2012-03-18 23:17                     ` [PATCH 1/3] firmware_class: Rework usermodehelper check Rafael J. Wysocki
2012-03-18 23:18                     ` [PATCH 2/3] firmware_class: Split _request_firmware() into three functions Rafael J. Wysocki
2012-03-18 23:21                     ` [PATCH 3/3] firmware_class: Do not warn that system is not ready for async loads Rafael J. Wysocki
2012-03-19 12:41           ` [RFC] firmware loader: retry _nowait requests when userhelper is not yet available James Courtier-Dutton

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=4F63FB59.9010104@codeaurora.org \
    --to=sboyd@codeaurora.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=chunkeey@googlemail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=kay.sievers@vrfy.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=rjw@sisk.pl \
    --cc=skannan@codeaurora.org \
    --cc=srivatsa.bhat@linux.vnet.ibm.com \
    --cc=torvalds@linux-foundation.org \
    /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.