mm, page_owner: fix off-by-one error in __set_page_owner_handle()
Patch series "followups to debug_pagealloc improvements through page_owner", v3. These are followups to [1] which made it to Linus meanwhile. Patches 1 and 3 are based on Kirill's review, patch 2 on KASAN request [2]. It would be nice if all of this made it to 5.4 with [1] already there (or at least Patch 1). This patch (of 3): As noted by Kirill, commit7e2f2a0cd1
("mm, page_owner: record page owner for each subpage") has introduced an off-by-one error in __set_page_owner_handle() when looking up page_ext for subpages. As a result, the head page page_owner info is set twice, while for the last tail page, it's not set at all. Fix this and also make the code more efficient by advancing the page_ext pointer we already have, instead of calling lookup_page_ext() for each subpage. Since the full size of struct page_ext is not known at compile time, we can't use a simple page_ext++ statement, so introduce a page_ext_next() inline function for that. Link: http://lkml.kernel.org/r/20190930122916.14969-2-vbabka@suse.cz Fixes:7e2f2a0cd1
("mm, page_owner: record page owner for each subpage") Signed-off-by: Vlastimil Babka <vbabka@suse.cz> Reported-by: Kirill A. Shutemov <kirill@shutemov.name> Reported-by: Miles Chen <miles.chen@mediatek.com> Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Walter Wu <walter-zh.wu@mediatek.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:

committad av
Linus Torvalds

förälder
2abd839aa7
incheckning
5556cfe8d9
@@ -156,10 +156,10 @@ void __reset_page_owner(struct page *page, unsigned int order)
|
||||
handle = save_stack(GFP_NOWAIT | __GFP_NOWARN);
|
||||
#endif
|
||||
|
||||
page_ext = lookup_page_ext(page);
|
||||
if (unlikely(!page_ext))
|
||||
return;
|
||||
for (i = 0; i < (1 << order); i++) {
|
||||
page_ext = lookup_page_ext(page + i);
|
||||
if (unlikely(!page_ext))
|
||||
continue;
|
||||
__clear_bit(PAGE_EXT_OWNER_ACTIVE, &page_ext->flags);
|
||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||
if (debug_pagealloc_enabled()) {
|
||||
@@ -167,6 +167,7 @@ void __reset_page_owner(struct page *page, unsigned int order)
|
||||
page_owner->free_handle = handle;
|
||||
}
|
||||
#endif
|
||||
page_ext = page_ext_next(page_ext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +187,7 @@ static inline void __set_page_owner_handle(struct page *page,
|
||||
__set_bit(PAGE_EXT_OWNER, &page_ext->flags);
|
||||
__set_bit(PAGE_EXT_OWNER_ACTIVE, &page_ext->flags);
|
||||
|
||||
page_ext = lookup_page_ext(page + i);
|
||||
page_ext = page_ext_next(page_ext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,12 +225,10 @@ void __split_page_owner(struct page *page, unsigned int order)
|
||||
if (unlikely(!page_ext))
|
||||
return;
|
||||
|
||||
page_owner = get_page_owner(page_ext);
|
||||
page_owner->order = 0;
|
||||
for (i = 1; i < (1 << order); i++) {
|
||||
page_ext = lookup_page_ext(page + i);
|
||||
for (i = 0; i < (1 << order); i++) {
|
||||
page_owner = get_page_owner(page_ext);
|
||||
page_owner->order = 0;
|
||||
page_ext = page_ext_next(page_ext);
|
||||
}
|
||||
}
|
||||
|
||||
|
Referens i nytt ärende
Block a user