mm: thp: turn compound_head() into BUG_ON(!PageTail) in get_huge_page_tail()
[platform/adaptation/renesas_rcar/renesas_kernel.git] / include / linux / mm.h
index 3552717..58202c2 100644 (file)
@@ -414,15 +414,44 @@ static inline int page_count(struct page *page)
        return atomic_read(&compound_head(page)->_count);
 }
 
+#ifdef CONFIG_HUGETLB_PAGE
+extern int PageHeadHuge(struct page *page_head);
+#else /* CONFIG_HUGETLB_PAGE */
+static inline int PageHeadHuge(struct page *page_head)
+{
+       return 0;
+}
+#endif /* CONFIG_HUGETLB_PAGE */
+
+static inline bool __compound_tail_refcounted(struct page *page)
+{
+       return !PageSlab(page) && !PageHeadHuge(page);
+}
+
+/*
+ * This takes a head page as parameter and tells if the
+ * tail page reference counting can be skipped.
+ *
+ * For this to be safe, PageSlab and PageHeadHuge must remain true on
+ * any given page where they return true here, until all tail pins
+ * have been released.
+ */
+static inline bool compound_tail_refcounted(struct page *page)
+{
+       VM_BUG_ON(!PageHead(page));
+       return __compound_tail_refcounted(page);
+}
+
 static inline void get_huge_page_tail(struct page *page)
 {
        /*
-        * __split_huge_page_refcount() cannot run
-        * from under us.
+        * __split_huge_page_refcount() cannot run from under us.
         */
+       VM_BUG_ON(!PageTail(page));
        VM_BUG_ON(page_mapcount(page) < 0);
        VM_BUG_ON(atomic_read(&page->_count) != 0);
-       atomic_inc(&page->_mapcount);
+       if (compound_tail_refcounted(page->first_page))
+               atomic_inc(&page->_mapcount);
 }
 
 extern bool __get_page_tail(struct page *page);
@@ -846,11 +875,14 @@ static __always_inline void *lowmem_page_address(const struct page *page)
 #endif
 
 #if defined(WANT_PAGE_VIRTUAL)
-#define page_address(page) ((page)->virtual)
-#define set_page_address(page, address)                        \
-       do {                                            \
-               (page)->virtual = (address);            \
-       } while(0)
+static inline void *page_address(const struct page *page)
+{
+       return page->virtual;
+}
+static inline void set_page_address(struct page *page, void *address)
+{
+       page->virtual = address;
+}
 #define page_address_init()  do { } while(0)
 #endif