diff options
author | Jérôme Glisse <jglisse@redhat.com> | 2017-03-06 19:49:54 -0500 |
---|---|---|
committer | Jérôme Glisse <jglisse@redhat.com> | 2017-04-24 14:10:38 -0400 |
commit | e84778e9db0672e371eb6599dfcb812512118842 (patch) | |
tree | 79faed11bb15b1db4904600248e2ed4ad5827bcb | |
parent | 870f897792678dbe39374916ab1c7c8e6b025f6e (diff) |
mm/put_page: move ZONE_DEVICE page reference decrement v2
Move page reference decrement of ZONE_DEVICE from put_page()
to put_zone_device_page() this does not affect non ZONE_DEVICE
page.
Doing this allow to catch when a ZONE_DEVICE page refcount reach
1 which means the device is no longer reference by any one (unlike
page from other zone, ZONE_DEVICE page refcount never reach 0).
This patch is just a preparatory patch for HMM.
Changes since v1:
- commit message
Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
-rw-r--r-- | include/linux/mm.h | 14 | ||||
-rw-r--r-- | kernel/memremap.c | 6 |
2 files changed, 17 insertions, 3 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index c82e8dbc81ea..022423ca4aa8 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -821,11 +821,19 @@ static inline void put_page(struct page *page) { page = compound_head(page); + /* + * ZONE_DEVICE pages should never have their refcount reach 0 (this + * would be a bug), so call page_ref_dec() in put_zone_device_page() + * to decrement page refcount and skip __put_page() here, as this + * would worsen things if a ZONE_DEVICE had a refcount bug. + */ + if (unlikely(is_zone_device_page(page))) { + put_zone_device_page(page); + return; + } + if (put_page_testzero(page)) __put_page(page); - - if (unlikely(is_zone_device_page(page))) - put_zone_device_page(page); } #if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP) diff --git a/kernel/memremap.c b/kernel/memremap.c index ea714eee029c..97ef6767bb5a 100644 --- a/kernel/memremap.c +++ b/kernel/memremap.c @@ -190,6 +190,12 @@ EXPORT_SYMBOL(get_zone_device_page); void put_zone_device_page(struct page *page) { + /* + * ZONE_DEVICE page refcount should never reach 0 and never be freed + * to kernel memory allocator. + */ + page_ref_dec(page); + put_dev_pagemap(page->pgmap); } EXPORT_SYMBOL(put_zone_device_page); |