diff --git a/include/linux/module.h b/include/linux/module.h
index a98e188cf37b..be374968cbdb 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -583,6 +583,10 @@ struct module {
 #ifdef CONFIG_DYNAMIC_DEBUG_CORE
 	struct _ddebug_info dyndbg_info;
 #endif
+
+#ifdef CONFIG_PAGE_OWNER
+	atomic_t nr_pages_allocated;
+#endif
 } ____cacheline_aligned __randomize_layout;
 #ifndef MODULE_ARCH_INIT
 #define MODULE_ARCH_INIT {}
diff --git a/kernel/module/Makefile b/kernel/module/Makefile
index a10b2b9a6fdf..b973a3956131 100644
--- a/kernel/module/Makefile
+++ b/kernel/module/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_KGDB_KDB) += kdb.o
 obj-$(CONFIG_MODVERSIONS) += version.o
 obj-$(CONFIG_MODULE_UNLOAD_TAINT_TRACKING) += tracking.o
 obj-$(CONFIG_MODULE_STATS) += stats.o
+obj-$(CONFIG_PAGE_OWNER) += page_owner.o
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 59b1d067e528..e021c7f6dd24 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2888,6 +2888,10 @@ static int load_module(struct load_info *info, const char __user *uargs,
 
 	init_param_lock(mod);
 
+#ifdef CONFIG_PAGE_OWNER
+	atomic_set(&mod->nr_pages_allocated, 0);
+#endif
+
 	/*
 	 * Now we've got everything in the final locations, we can
 	 * find optional sections.
diff --git a/kernel/module/page_owner.c b/kernel/module/page_owner.c
new file mode 100644
index 000000000000..bcf2a15e7ed3
--- /dev/null
+++ b/kernel/module/page_owner.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/module.h>
+#include <linux/oom.h>
+#include "internal.h"
+
+static int po_oom_notify(struct notifier_block *self,
+		unsigned long val, void *data)
+{
+	struct module *mod;
+	int nr;
+	int ret = notifier_from_errno(0);
+
+	preempt_disable();
+	pr_info("Modules state:\n");
+	pr_info("module               nr_page_allocated\n");
+	list_for_each_entry_rcu(mod, &modules, list) {
+		nr = atomic_read(&mod->nr_pages_allocated);
+		if (nr <= 0)
+			continue;
+
+		pr_info("%-20s %d\n", mod->name, nr);
+	}
+	preempt_enable();
+
+	return ret;
+}
+
+static struct notifier_block po_oom_nb = {
+	.notifier_call = po_oom_notify,
+	.priority = 0
+};
+
+void po_register_oom_notifier(void)
+{
+	if (register_oom_notifier(&po_oom_nb))
+		pr_warn("Failed to register pageowner oom notifier\n");
+}
diff --git a/mm/page_owner.c b/mm/page_owner.c
index ef8fe1857d42..bbbf5a518a41 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -139,7 +139,7 @@ static noinline depot_stack_handle_t save_stack(gfp_t flags)
 }
 
 #ifdef CONFIG_MODULES
-static char *find_module_name(depot_stack_handle_t handle)
+static char *find_module_name(depot_stack_handle_t handle, int nr_pages)
 {
 	int i;
 	struct module *mod = NULL;
@@ -158,6 +158,7 @@ static char *find_module_name(depot_stack_handle_t handle)
 		if (!mod)
 			continue;
 
+		atomic_add(nr_pages, &mod->nr_pages_allocated);
 		return mod->name;
 	}
 
@@ -187,8 +188,11 @@ static inline void copy_module_name(struct page_owner *old_page_owner,
 {
 	set_module_name(new_page_owner, old_page_owner->module_name);
 }
+
+void po_register_oom_notifier(void);
 #else
-static inline char *find_module_name(depot_stack_handle_t handle)
+static inline char *find_module_name(depot_stack_handle_t handle,
+		int nr_pages)
 {
 	return NULL;
 }
@@ -208,6 +212,10 @@ static inline void copy_module_name(struct page_owner *old_page_owner,
 		struct page_owner *new_page_owner)
 {
 }
+
+void po_register_oom_notifier(void)
+{
+}
 #endif
 
 void __reset_page_owner(struct page *page, unsigned short order)
@@ -224,7 +232,7 @@ void __reset_page_owner(struct page *page, unsigned short order)
 		return;
 
 	handle = save_stack(GFP_NOWAIT | __GFP_NOWARN);
-	mod_name = find_module_name(handle);
+	mod_name = find_module_name(handle, -(1 << order));
 	for (i = 0; i < (1 << order); i++) {
 		__clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
 		page_owner = get_page_owner(page_ext);
@@ -245,7 +253,7 @@ static inline void __set_page_owner_handle(struct page_ext *page_ext,
 	u64 ts_nsec = local_clock();
 	char *mod_name;
 
-	mod_name = find_module_name(handle);
+	mod_name = find_module_name(handle, 1 << order);
 
 	for (i = 0; i < (1 << order); i++) {
 		page_owner = get_page_owner(page_ext);
@@ -809,6 +817,8 @@ static int __init pageowner_init(void)
 	debugfs_create_file("page_owner", 0400, NULL, NULL,
 			    &proc_page_owner_operations);
 
+	po_register_oom_notifier();
+
 	return 0;
 }
 late_initcall(pageowner_init)
