From: "Luke Yang" <luke.adi@gmail.com>
To: linux-kernel@vger.kernel.org, "Andrew Morton" <akpm@osdl.org>,
"Nick Piggin" <npiggin@suse.de>
Subject: [PATCH] nommu page refcount bug fixing
Date: Thu, 30 Mar 2006 11:05:18 +0800 [thread overview]
Message-ID: <489ecd0c0603291905m7ebffff2j83809cc3c93595f1@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 2769 bytes --]
Hi all,
The previous "nommu use compound pages" patch has a problem: when
the pages allocated is not compound page (eg: slab allocator), the
refcount value of every page still need to be set, otherwise the
get/put_page() would free a single page improperly, such as in
access_process_vm().
Signed-off-by: Luke Yang <luke.adi@gmail.com>
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b7f14a4..fc8b544 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -436,6 +436,14 @@ static void __free_pages_ok(struct page
mutex_debug_check_no_locks_freed(page_address(page),
PAGE_SIZE<<order);
+#ifndef CONFIG_MMU
+ if (!PageCompound(page)) {
+ for (i = 1 ; i < (1 << order) ; ++i) {
+ __put_page(page + i);
+ }
+ }
+#endif
+
for (i = 0 ; i < (1 << order) ; ++i)
reserved += free_pages_check(page + i);
if (reserved)
@@ -453,6 +461,8 @@ static void __free_pages_ok(struct page
*/
void fastcall __init __free_pages_bootmem(struct page *page, unsigned
int order)
{
+ int i;
+
if (order == 0) {
__ClearPageReserved(page);
set_page_count(page, 0);
@@ -472,6 +482,11 @@ void fastcall __init __free_pages_bootme
}
set_page_refcounted(page);
+
+#ifndef CONFIG_MMU
+ for (i = 1; i < (1 << order); i++)
+ set_page_refcounted(page + i);
+#endif
__free_pages(page, order);
}
}
@@ -512,6 +527,8 @@ static inline void expand(struct zone *z
*/
static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
{
+ int i;
+
if (unlikely(page_mapcount(page) |
(page->mapping != NULL) |
(page_count(page) != 0) |
@@ -539,7 +556,21 @@ static int prep_new_page(struct page *pa
1 << PG_referenced | 1 << PG_arch_1 |
1 << PG_checked | 1 << PG_mappedtodisk);
set_page_private(page, 0);
+
set_page_refcounted(page);
+
+#ifndef CONFIG_MMU
+ if (!(gfp_flags & __GFP_COMP)) {
+ /*
+ * Reference all the pages for this order, otherwise if
+ * anyone accesses one of the pages with (get/put) it
+ * will be freed. - eg: access_process_vm()
+ */
+ for (i = 1; i < (1 << order); i++)
+ set_page_refcounted(page + i);
+ }
+#endif
+
kernel_map_pages(page, 1 << order, 1);
if (gfp_flags & __GFP_ZERO)
--
Best regards,
Luke Yang
luke.adi@gmail.com
[-- Attachment #2: nommu_page_count_fix.patch --]
[-- Type: text/x-patch, Size: 1833 bytes --]
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b7f14a4..fc8b544 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -436,6 +436,14 @@ static void __free_pages_ok(struct page
mutex_debug_check_no_locks_freed(page_address(page),
PAGE_SIZE<<order);
+#ifndef CONFIG_MMU
+ if (!PageCompound(page)) {
+ for (i = 1 ; i < (1 << order) ; ++i) {
+ __put_page(page + i);
+ }
+ }
+#endif
+
for (i = 0 ; i < (1 << order) ; ++i)
reserved += free_pages_check(page + i);
if (reserved)
@@ -453,6 +461,8 @@ static void __free_pages_ok(struct page
*/
void fastcall __init __free_pages_bootmem(struct page *page, unsigned int order)
{
+ int i;
+
if (order == 0) {
__ClearPageReserved(page);
set_page_count(page, 0);
@@ -472,6 +482,11 @@ void fastcall __init __free_pages_bootme
}
set_page_refcounted(page);
+
+#ifndef CONFIG_MMU
+ for (i = 1; i < (1 << order); i++)
+ set_page_refcounted(page + i);
+#endif
__free_pages(page, order);
}
}
@@ -512,6 +527,8 @@ static inline void expand(struct zone *z
*/
static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
{
+ int i;
+
if (unlikely(page_mapcount(page) |
(page->mapping != NULL) |
(page_count(page) != 0) |
@@ -539,7 +556,21 @@ static int prep_new_page(struct page *pa
1 << PG_referenced | 1 << PG_arch_1 |
1 << PG_checked | 1 << PG_mappedtodisk);
set_page_private(page, 0);
+
set_page_refcounted(page);
+
+#ifndef CONFIG_MMU
+ if (!(gfp_flags & __GFP_COMP)) {
+ /*
+ * Reference all the pages for this order, otherwise if
+ * anyone accesses one of the pages with (get/put) it
+ * will be freed. - eg: access_process_vm()
+ */
+ for (i = 1; i < (1 << order); i++)
+ set_page_refcounted(page + i);
+ }
+#endif
+
kernel_map_pages(page, 1 << order, 1);
if (gfp_flags & __GFP_ZERO)
next reply other threads:[~2006-03-30 3:05 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-03-30 3:05 Luke Yang [this message]
2006-03-30 3:22 ` Nick Piggin
2006-03-30 8:56 ` Luke Yang
2006-03-30 9:00 ` Luke Yang
2006-03-30 9:07 ` Nick Piggin
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=489ecd0c0603291905m7ebffff2j83809cc3c93595f1@mail.gmail.com \
--to=luke.adi@gmail.com \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=npiggin@suse.de \
/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
all inboxes | Powered by JetHome®