From: Luis Chamberlain <mcgrof@kernel.org>
To: Lukas Middendorf <kernel@tuxforce.de>
Cc: linux-btrfs@vger.kernel.org, Antti Palosaari <crope@iki.fi>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
linux-media@vger.kernel.org
Subject: Re: Is request_firmware() really safe to call in resume callback when /usr/lib/firmware is on btrfs?
Date: Fri, 2 Apr 2021 18:02:53 +0000 [thread overview]
Message-ID: <20210402180253.GS4332@42.do-not-panic.com> (raw)
In-Reply-To: <6b61e549-42b8-8e71-ff57-43b7c5b4291f@tuxforce.de>
On Thu, Apr 01, 2021 at 04:59:47PM +0200, Lukas Middendorf wrote:
> Hello Luis,
>
>
> On 18/08/2020 16:37, Luis Chamberlain wrote:
> > On Tue, Aug 18, 2020 at 12:04:51AM +0200, Lukas Middendorf wrote:
> > > On 17/08/2020 17:20, Luis Chamberlain wrote:
> > > > This helps, thanks so much, now we'll have to write a reproducer, thanks
> > > > for the report!!
> > >
> > > Will you do it yourself or do you expect me to do anything for this?
> >
> > I meant to imply that we'd do this, now that we understand the problem. Thanks
> > for your report!
>
> any news on this issue? Did you succeed with reproducing this at your end?
No sorry, I dropped the ball on this but I managed to now spawn up the
virtual guests where I was doing development to reproduce this. Give me
some time and I will zero in on this now.
For now what I have is the following to test this, I next will work
on the userspace part.
diff --git a/lib/test_firmware.c b/lib/test_firmware.c
index 9fee2b93a8d1..f9e67fc4145a 100644
--- a/lib/test_firmware.c
+++ b/lib/test_firmware.c
@@ -18,6 +18,7 @@
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
@@ -33,6 +34,8 @@
static DEFINE_MUTEX(test_fw_mutex);
static const struct firmware *test_firmware;
+static struct platform_device *pdev;
+
struct test_batched_req {
u8 idx;
int rc;
@@ -53,6 +56,9 @@ struct test_batched_req {
* @sync_direct: when the sync trigger is used if this is true
* request_firmware_direct() will be used instead.
* @send_uevent: whether or not to send a uevent for async requests
+ * @enable_resume_test: if @senable_resume is true this will enable a test to
+ * issue a request_firmware() upon resume. This is useful to test resume
+ * after suspend filesystem races.
* @num_requests: number of requests to try per test case. This is trigger
* specific.
* @reqs: stores all requests information
@@ -91,6 +97,7 @@ struct test_config {
bool into_buf;
bool sync_direct;
bool send_uevent;
+ bool enable_resume_test;
u8 num_requests;
u8 read_fw_idx;
@@ -184,6 +191,7 @@ static int __test_firmware_config_init(void)
test_fw_config->send_uevent = true;
test_fw_config->into_buf = false;
test_fw_config->sync_direct = false;
+ test_fw_config->enable_resume_test = false;
test_fw_config->req_firmware = request_firmware;
test_fw_config->test_result = 0;
test_fw_config->reqs = NULL;
@@ -257,6 +265,9 @@ static ssize_t config_show(struct device *dev,
len += scnprintf(buf+len, PAGE_SIZE - len,
"sync_direct:\t\t%s\n",
test_fw_config->sync_direct ? "true" : "false");
+ len += scnprintf(buf+len, PAGE_SIZE - len,
+ "enable_resume_test:\t\t%s\n",
+ test_fw_config->enable_resume_test ? "true" : "false");
len += scnprintf(buf+len, PAGE_SIZE - len,
"read_fw_idx:\t%u\n", test_fw_config->read_fw_idx);
@@ -422,6 +433,22 @@ static ssize_t config_sync_direct_show(struct device *dev,
}
static DEVICE_ATTR_RW(config_sync_direct);
+static ssize_t config_enable_resume_test_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return test_dev_config_update_bool(buf, count,
+ &test_fw_config->enable_resume_test);
+}
+
+static ssize_t config_enable_resume_test_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return test_dev_config_show_bool(buf, test_fw_config->enable_resume_test);
+}
+static DEVICE_ATTR_RW(config_enable_resume_test);
+
static ssize_t config_send_uevent_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@@ -929,6 +956,7 @@ static struct attribute *test_dev_attrs[] = {
TEST_FW_DEV_ATTR(config_into_buf),
TEST_FW_DEV_ATTR(config_sync_direct),
TEST_FW_DEV_ATTR(config_send_uevent),
+ TEST_FW_DEV_ATTR(config_enable_resume_test),
TEST_FW_DEV_ATTR(config_read_fw_idx),
/* These don't use the config at all - they could be ported! */
@@ -958,6 +986,81 @@ static struct miscdevice test_fw_misc_device = {
.groups = test_dev_groups,
};
+static int __maybe_unused test_firmware_suspend(struct device *dev)
+{
+ return 0;
+}
+
+
+static int __maybe_unused test_firmware_resume(struct device *dev)
+{
+ int rc;
+
+ if (!test_fw_config->enable_resume_test)
+ return 0;
+
+ pr_info("resume test, loading '%s'\n", test_fw_config->name);
+
+ mutex_lock(&test_fw_mutex);
+ release_firmware(test_firmware);
+ test_firmware = NULL;
+ rc = request_firmware(&test_firmware, test_fw_config->name, dev);
+ if (rc) {
+ mutex_unlock(&test_fw_mutex);
+ pr_info("load of '%s' failed: %d\n", test_fw_config->name, rc);
+ goto out;
+ }
+
+ pr_info("loaded: %zu\n", test_firmware->size);
+ mutex_unlock(&test_fw_mutex);
+ pr_info("resume test, completed successfully\n");
+out:
+ return rc;
+}
+
+static SIMPLE_DEV_PM_OPS(test_dev_pm_ops, test_firmware_suspend, test_firmware_resume);
+
+static int test_firmware_probe(struct platform_device *dev)
+{
+ int rc;
+
+ rc = misc_register(&test_fw_misc_device);
+ if (rc) {
+ kfree(test_fw_config);
+ pr_err("could not register misc device: %d\n", rc);
+ return rc;
+ }
+
+ pr_info("interface ready\n");
+
+ return 0;
+}
+
+static int test_firmware_remove(struct platform_device *dev)
+{
+ mutex_lock(&test_fw_mutex);
+ release_firmware(test_firmware);
+ misc_deregister(&test_fw_misc_device);
+ mutex_unlock(&test_fw_mutex);
+
+ return 0;
+}
+
+static void test_firmware_shutdown(struct platform_device *dev)
+{
+}
+
+static struct platform_driver test_firmware_driver = {
+ .driver = {
+ .name = "test_firmware",
+ .pm = &test_dev_pm_ops,
+ },
+ .probe = test_firmware_probe,
+ .remove = test_firmware_remove,
+ .shutdown = test_firmware_shutdown,
+};
+
+
static int __init test_firmware_init(void)
{
int rc;
@@ -973,28 +1076,39 @@ static int __init test_firmware_init(void)
return rc;
}
- rc = misc_register(&test_fw_misc_device);
- if (rc) {
- kfree(test_fw_config);
- pr_err("could not register misc device: %d\n", rc);
- return rc;
- }
+ rc = platform_driver_register(&test_firmware_driver);
+ if (rc)
+ goto err_alloc;
- pr_warn("interface ready\n");
+ pdev = platform_device_alloc("test_firmware", -1);
+ if (!pdev)
+ goto err_driver_unregister;
+
+ rc = platform_device_add(pdev);
+ if (rc)
+ goto err_free_device;
return 0;
+
+ err_free_device:
+ platform_device_put(pdev);
+ err_driver_unregister:
+ platform_driver_unregister(&test_firmware_driver);
+ err_alloc:
+ __test_firmware_config_free();
+ kfree(test_fw_config);
+ return rc;
}
module_init(test_firmware_init);
static void __exit test_firmware_exit(void)
{
- mutex_lock(&test_fw_mutex);
- release_firmware(test_firmware);
- misc_deregister(&test_fw_misc_device);
+ platform_device_unregister(pdev);
+ platform_driver_unregister(&test_firmware_driver);
+
__test_firmware_config_free();
kfree(test_fw_config);
- mutex_unlock(&test_fw_mutex);
pr_warn("removed interface\n");
}
Luis
next prev parent reply other threads:[~2021-04-02 18:02 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-09 18:51 Is request_firmware() really safe to call in resume callback when /usr/lib/firmware is on btrfs? Lukas Middendorf
2020-08-13 16:37 ` Luis Chamberlain
2020-08-13 21:53 ` Lukas Middendorf
2020-08-13 22:13 ` Luis Chamberlain
2020-08-14 11:38 ` Lukas Middendorf
2020-08-14 16:37 ` Luis Chamberlain
2020-08-14 21:59 ` Lukas Middendorf
2020-08-17 15:20 ` Luis Chamberlain
2020-08-17 22:04 ` Lukas Middendorf
2020-08-18 14:37 ` Luis Chamberlain
2021-04-01 14:59 ` Lukas Middendorf
2021-04-02 18:02 ` Luis Chamberlain [this message]
2021-04-02 22:19 ` Luis Chamberlain
2021-04-02 22:58 ` Luis Chamberlain
2021-04-03 10:24 ` Lukas Middendorf
2021-04-03 16:07 ` Lukas Middendorf
2021-04-03 20:25 ` Luis Chamberlain
2021-04-03 21:04 ` Luis Chamberlain
2021-04-05 9:52 ` Lukas Middendorf
2021-04-04 0:50 ` Lukas Middendorf
2021-04-08 18:02 ` Luis Chamberlain
2021-04-16 23:17 ` Luis Chamberlain
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=20210402180253.GS4332@42.do-not-panic.com \
--to=mcgrof@kernel.org \
--cc=crope@iki.fi \
--cc=kernel@tuxforce.de \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).