diff
+#include <linux/hashtable.h>
+
+DEFINE_HASHTABLE(freed_pages, 10);
+
+static inline void mark_page_freed(struct page *page)
+{
+    unsigned long flags;
+    spin_lock_irqsave(&freed_pages_lock, flags);
+    hash_add(freed_pages, &page->freed_node, (unsigned long)page);
+    spin_unlock_irqrestore(&freed_pages_lock, flags);
+}
+
+static inline bool is_page_freed(struct page *page)
+{
+    bool found = false;
+    unsigned long flags;
+    spin_lock_irqsave(&freed_pages_lock, flags);
+    hash_for_each_possible(freed_pages, node, freed_node, (unsigned long)page) {
+        if (node == page) {
+            found = true;
+            break;
+        }
+    }
+    spin_unlock_irqrestore(&freed_pages_lock, flags);
+    return found;
+}

 static inline void free_the_page(struct page *page, unsigned int order)
 {
-    if (pcp_allowed_order(order))        /* Via pcp? */
+    if (pcp_allowed_order(order) && !is_page_freed(page)) {
         free_unref_page(page, order);
+        mark_page_freed(page);
+    }
 }
