diff options
Diffstat (limited to 'include/linux/huge_mm.h')
-rw-r--r-- | include/linux/huge_mm.h | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h index 91672e2deec3..db512014e061 100644 --- a/include/linux/huge_mm.h +++ b/include/linux/huge_mm.h | |||
@@ -157,6 +157,26 @@ static inline int hpage_nr_pages(struct page *page) | |||
157 | return HPAGE_PMD_NR; | 157 | return HPAGE_PMD_NR; |
158 | return 1; | 158 | return 1; |
159 | } | 159 | } |
160 | /* | ||
161 | * compound_trans_head() should be used instead of compound_head(), | ||
162 | * whenever the "page" passed as parameter could be the tail of a | ||
163 | * transparent hugepage that could be undergoing a | ||
164 | * __split_huge_page_refcount(). The page structure layout often | ||
165 | * changes across releases and it makes extensive use of unions. So if | ||
166 | * the page structure layout will change in a way that | ||
167 | * page->first_page gets clobbered by __split_huge_page_refcount, the | ||
168 | * implementation making use of smp_rmb() will be required. | ||
169 | * | ||
170 | * Currently we define compound_trans_head as compound_head, because | ||
171 | * page->private is in the same union with page->first_page, and | ||
172 | * page->private isn't clobbered. However this also means we're | ||
173 | * currently leaving dirt into the page->private field of anonymous | ||
174 | * pages resulting from a THP split, instead of setting page->private | ||
175 | * to zero like for every other page that has PG_private not set. But | ||
176 | * anonymous pages don't use page->private so this is not a problem. | ||
177 | */ | ||
178 | #if 0 | ||
179 | /* This will be needed if page->private will be clobbered in split_huge_page */ | ||
160 | static inline struct page *compound_trans_head(struct page *page) | 180 | static inline struct page *compound_trans_head(struct page *page) |
161 | { | 181 | { |
162 | if (PageTail(page)) { | 182 | if (PageTail(page)) { |
@@ -174,6 +194,9 @@ static inline struct page *compound_trans_head(struct page *page) | |||
174 | } | 194 | } |
175 | return page; | 195 | return page; |
176 | } | 196 | } |
197 | #else | ||
198 | #define compound_trans_head(page) compound_head(page) | ||
199 | #endif | ||
177 | 200 | ||
178 | extern int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, | 201 | extern int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, |
179 | unsigned long addr, pmd_t pmd, pmd_t *pmdp); | 202 | unsigned long addr, pmd_t pmd, pmd_t *pmdp); |