summaryrefslogtreecommitdiff
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/filemap.c1
-rw-r--r--mm/khugepaged.c1
-rw-r--r--mm/memory-failure.c21
-rw-r--r--mm/page_alloc.c7
-rw-r--r--mm/shmem.c1
-rw-r--r--mm/swapfile.c1
6 files changed, 28 insertions, 4 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index c8dafe70d4cc..ea49677c6338 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -45,6 +45,7 @@
#include <linux/migrate.h>
#include <linux/pipe_fs_i.h>
#include <linux/splice.h>
+#include <linux/rcupdate_wait.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include "internal.h"
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 3defe6713ef1..2b219acb528e 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -17,6 +17,7 @@
#include <linux/userfaultfd_k.h>
#include <linux/page_idle.h>
#include <linux/page_table_check.h>
+#include <linux/rcupdate_wait.h>
#include <linux/swapops.h>
#include <linux/shmem_fs.h>
#include <linux/ksm.h>
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index a0d9b4ac7d54..4f9b61f4a668 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -678,7 +678,7 @@ static void add_to_kill_fsdax(struct task_struct *tsk, struct page *p,
*/
static void collect_procs_fsdax(struct page *page,
struct address_space *mapping, pgoff_t pgoff,
- struct list_head *to_kill)
+ struct list_head *to_kill, bool pre_remove)
{
struct vm_area_struct *vma;
struct task_struct *tsk;
@@ -686,8 +686,15 @@ static void collect_procs_fsdax(struct page *page,
i_mmap_lock_read(mapping);
rcu_read_lock();
for_each_process(tsk) {
- struct task_struct *t = task_early_kill(tsk, true);
+ struct task_struct *t = tsk;
+ /*
+ * Search for all tasks while MF_MEM_PRE_REMOVE is set, because
+ * the current may not be the one accessing the fsdax page.
+ * Otherwise, search for the current task.
+ */
+ if (!pre_remove)
+ t = task_early_kill(tsk, true);
if (!t)
continue;
vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) {
@@ -1793,6 +1800,7 @@ int mf_dax_kill_procs(struct address_space *mapping, pgoff_t index,
dax_entry_t cookie;
struct page *page;
size_t end = index + count;
+ bool pre_remove = mf_flags & MF_MEM_PRE_REMOVE;
mf_flags |= MF_ACTION_REQUIRED | MF_MUST_KILL;
@@ -1804,9 +1812,14 @@ int mf_dax_kill_procs(struct address_space *mapping, pgoff_t index,
if (!page)
goto unlock;
- SetPageHWPoison(page);
+ if (!pre_remove)
+ SetPageHWPoison(page);
- collect_procs_fsdax(page, mapping, index, &to_kill);
+ /*
+ * The pre_remove case is revoking access, the memory is still
+ * good and could theoretically be put back into service.
+ */
+ collect_procs_fsdax(page, mapping, index, &to_kill, pre_remove);
unmap_and_kill(&to_kill, page_to_pfn(page), mapping,
index, mf_flags);
unlock:
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index a01baf0454f8..150d4f23b010 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -916,6 +916,9 @@ static inline bool page_expected_state(struct page *page,
#ifdef CONFIG_MEMCG
page->memcg_data |
#endif
+#ifdef CONFIG_PAGE_POOL
+ ((page->pp_magic & ~0x3UL) == PP_SIGNATURE) |
+#endif
(page->flags & check_flags)))
return false;
@@ -942,6 +945,10 @@ static const char *page_bad_reason(struct page *page, unsigned long flags)
if (unlikely(page->memcg_data))
bad_reason = "page still charged to cgroup";
#endif
+#ifdef CONFIG_PAGE_POOL
+ if (unlikely((page->pp_magic & ~0x3UL) == PP_SIGNATURE))
+ bad_reason = "page_pool leak";
+#endif
return bad_reason;
}
diff --git a/mm/shmem.c b/mm/shmem.c
index 928aa2304932..d7c84ff62186 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -79,6 +79,7 @@ static struct vfsmount *shm_mnt __ro_after_init;
#include <linux/rmap.h>
#include <linux/uuid.h>
#include <linux/quotaops.h>
+#include <linux/rcupdate_wait.h>
#include <linux/uaccess.h>
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 3eec686484ef..556ff7347d5f 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -42,6 +42,7 @@
#include <linux/completion.h>
#include <linux/suspend.h>
#include <linux/zswap.h>
+#include <linux/plist.h>
#include <asm/tlbflush.h>
#include <linux/swapops.h>