From: David Woodhouse <dwmw2@infradead.org>
To: Kay Sievers <kay.sievers@vrfy.org>, dhowells@redhat.com
Cc: Tomas Winkler <tomasw@gmail.com>, Greg KH <greg@kroah.com>,
Johannes Berg <johannes@sipsolutions.net>,
"Rafael J. Wysocki" <rjw@sisk.pl>,
Emmanuel Grumbach <egrumbach@gmail.com>,
linux-kernel@vger.kernel.org
Subject: Re: request_firmware API exhaust memory
Date: Tue, 27 Apr 2010 13:43:07 +0100 [thread overview]
Message-ID: <1272372187.5484.3981.camel@macbook.infradead.org> (raw)
In-Reply-To: <s2yac3eb2511004270505g4ded10f5k5322850e8b58790f@mail.gmail.com>
On Tue, 2010-04-27 at 14:05 +0200, Kay Sievers wrote:
>
> The patch I posted makes the issue go away. It's still not the right
> fix, because the pages are only get freed when the device id cleaned
> up, not on calling release_firmware. But it should illustrate the
> underlying issue, and that there is no leaked memory anymore.
>
> > I think this needs some more review.
>
> If David does not fix it, it probably just needs to be reverted. And
> instead of implementing our own "memory management", we should rather
> add a vrealloc(), and the firmware loader should use that.
The whole point was to avoid the vrealloc(). We really don't want to be
screwing with page tables, globally, for each page written from
userspace.
This untested patch attempts to put the page array into the 'struct
firmware' so that we can free it from release_firmware().
It would actually be nice if we could make that the _primary_ method of
returning data to drivers, and we could ditch the vmap() requirement
altogether... drivers which really need it to be virtually contiguous
can depend on CONFIG_MMU and do the vmap() for themselves.
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 985da11..cc9a79b 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -162,8 +162,13 @@ static ssize_t firmware_loading_store(struct device *dev,
mutex_unlock(&fw_lock);
break;
}
- vfree(fw_priv->fw->data);
+ vunmap(fw_priv->fw->data);
fw_priv->fw->data = NULL;
+ if (fw_priv->fw->pages) {
+ for (i = 0; i < PFN_UP(fw_priv->fw->size); i++)
+ __free_page(fw_priv->fw->pages[i]);
+ kfree(fw_priv->fw->pages);
+ }
for (i = 0; i < fw_priv->nr_pages; i++)
__free_page(fw_priv->pages[i]);
kfree(fw_priv->pages);
@@ -176,7 +181,7 @@ static ssize_t firmware_loading_store(struct device *dev,
break;
case 0:
if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
- vfree(fw_priv->fw->data);
+ vunmap(fw_priv->fw->data);
fw_priv->fw->data = vmap(fw_priv->pages,
fw_priv->nr_pages,
0, PAGE_KERNEL_RO);
@@ -184,7 +189,9 @@ static ssize_t firmware_loading_store(struct device *dev,
dev_err(dev, "%s: vmap() failed\n", __func__);
goto err;
}
- /* Pages will be freed by vfree() */
+ /* Pages are now owned by 'struct firmware' */
+ fw_priv->fw->pages = fw_priv->pages;
+ fw_priv->pages = NULL;
fw_priv->page_array_size = 0;
fw_priv->nr_pages = 0;
complete(&fw_priv->completion);
@@ -571,6 +578,7 @@ void
release_firmware(const struct firmware *fw)
{
struct builtin_fw *builtin;
+ int i;
if (fw) {
for (builtin = __start_builtin_fw; builtin != __end_builtin_fw;
@@ -578,7 +586,12 @@ release_firmware(const struct firmware *fw)
if (fw->data == builtin->data)
goto free_fw;
}
- vfree(fw->data);
+ vunmap(fw->data);
+ if (fw->pages) {
+ for (i = 0; i < PFN_UP(fw->size); i++)
+ __free_page(fw->pages[i]);
+ kfree(fw->pages);
+ }
free_fw:
kfree(fw);
}
--
dwmw2
next prev parent reply other threads:[~2010-04-27 12:43 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-04-19 12:20 Tomas Winkler
2010-04-19 12:35 ` Kay Sievers
2010-04-19 14:59 ` Greg KH
2010-04-21 22:22 ` Tomas Winkler
2010-04-25 16:37 ` Greg KH
2010-04-25 19:22 ` Tomas Winkler
2010-04-25 19:36 ` Greg KH
2010-04-25 20:09 ` Tomas Winkler
2010-04-26 10:38 ` Kay Sievers
2010-04-26 15:19 ` Kay Sievers
2010-04-26 16:59 ` Tomas Winkler
2010-04-27 4:12 ` Sujith Manoharan
2010-04-27 11:18 ` Tomas Winkler
2010-04-27 11:53 ` Tomas Winkler
2010-04-27 12:05 ` Kay Sievers
2010-04-27 12:43 ` David Woodhouse [this message]
2010-04-27 13:34 ` Kay Sievers
2010-04-28 8:23 ` Kay Sievers
2010-04-28 13:07 ` Tomas Winkler
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=1272372187.5484.3981.camel@macbook.infradead.org \
--to=dwmw2@infradead.org \
--cc=dhowells@redhat.com \
--cc=egrumbach@gmail.com \
--cc=greg@kroah.com \
--cc=johannes@sipsolutions.net \
--cc=kay.sievers@vrfy.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rjw@sisk.pl \
--cc=tomasw@gmail.com \
/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
Powered by JetHome