@@ -9,6 +9,7 @@
#include <linux/vmstat.h>
#include <linux/highmem.h>
#include <linux/swap.h>
+#include <linux/pagemap.h>
#include <asm/pgtable.h>
@@ -95,10 +96,23 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
}
VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
page = pte_page(pte);
- if (unlikely(!try_get_page(page))) {
+
+ if (WARN_ON_ONCE(page_ref_count(page) < 0)) {
+ pte_unmap(ptep);
+ return 0;
+ }
+
+ if (!page_cache_get_speculative(page)) {
pte_unmap(ptep);
return 0;
}
+
+ if (unlikely(pte_val(pte) != pte_val(*ptep))) {
+ put_page(page);
+ pte_unmap(ptep);
+ return 0;
+ }
+
SetPageReferenced(page);
pages[*nr] = page;
(*nr)++;