diff options
Diffstat (limited to 'include/linux/mm.h')
-rw-r--r-- | include/linux/mm.h | 55 |
1 files changed, 50 insertions, 5 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index 60e0e4a592d2..4670ebd1f622 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -267,21 +267,31 @@ static inline int get_page_unless_zero(struct page *page) | |||
267 | return atomic_inc_not_zero(&page->_count); | 267 | return atomic_inc_not_zero(&page->_count); |
268 | } | 268 | } |
269 | 269 | ||
270 | static inline struct page *compound_head(struct page *page) | ||
271 | { | ||
272 | if (unlikely(PageTail(page))) | ||
273 | return page->first_page; | ||
274 | return page; | ||
275 | } | ||
276 | |||
270 | static inline int page_count(struct page *page) | 277 | static inline int page_count(struct page *page) |
271 | { | 278 | { |
272 | if (unlikely(PageCompound(page))) | 279 | return atomic_read(&compound_head(page)->_count); |
273 | page = (struct page *)page_private(page); | ||
274 | return atomic_read(&page->_count); | ||
275 | } | 280 | } |
276 | 281 | ||
277 | static inline void get_page(struct page *page) | 282 | static inline void get_page(struct page *page) |
278 | { | 283 | { |
279 | if (unlikely(PageCompound(page))) | 284 | page = compound_head(page); |
280 | page = (struct page *)page_private(page); | ||
281 | VM_BUG_ON(atomic_read(&page->_count) == 0); | 285 | VM_BUG_ON(atomic_read(&page->_count) == 0); |
282 | atomic_inc(&page->_count); | 286 | atomic_inc(&page->_count); |
283 | } | 287 | } |
284 | 288 | ||
289 | static inline struct page *virt_to_head_page(const void *x) | ||
290 | { | ||
291 | struct page *page = virt_to_page(x); | ||
292 | return compound_head(page); | ||
293 | } | ||
294 | |||
285 | /* | 295 | /* |
286 | * Setup the page count before being freed into the page allocator for | 296 | * Setup the page count before being freed into the page allocator for |
287 | * the first time (boot or memory hotplug) | 297 | * the first time (boot or memory hotplug) |
@@ -314,6 +324,18 @@ static inline compound_page_dtor *get_compound_page_dtor(struct page *page) | |||
314 | return (compound_page_dtor *)page[1].lru.next; | 324 | return (compound_page_dtor *)page[1].lru.next; |
315 | } | 325 | } |
316 | 326 | ||
327 | static inline int compound_order(struct page *page) | ||
328 | { | ||
329 | if (!PageHead(page)) | ||
330 | return 0; | ||
331 | return (unsigned long)page[1].lru.prev; | ||
332 | } | ||
333 | |||
334 | static inline void set_compound_order(struct page *page, unsigned long order) | ||
335 | { | ||
336 | page[1].lru.prev = (void *)order; | ||
337 | } | ||
338 | |||
317 | /* | 339 | /* |
318 | * Multiple processes may "see" the same page. E.g. for untouched | 340 | * Multiple processes may "see" the same page. E.g. for untouched |
319 | * mappings of /dev/null, all processes see the same page full of | 341 | * mappings of /dev/null, all processes see the same page full of |
@@ -850,8 +872,26 @@ static inline int vma_wants_writenotify(struct vm_area_struct *vma) | |||
850 | 872 | ||
851 | extern pte_t *FASTCALL(get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl)); | 873 | extern pte_t *FASTCALL(get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl)); |
852 | 874 | ||
875 | #ifdef __PAGETABLE_PUD_FOLDED | ||
876 | static inline int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, | ||
877 | unsigned long address) | ||
878 | { | ||
879 | return 0; | ||
880 | } | ||
881 | #else | ||
853 | int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address); | 882 | int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address); |
883 | #endif | ||
884 | |||
885 | #ifdef __PAGETABLE_PMD_FOLDED | ||
886 | static inline int __pmd_alloc(struct mm_struct *mm, pud_t *pud, | ||
887 | unsigned long address) | ||
888 | { | ||
889 | return 0; | ||
890 | } | ||
891 | #else | ||
854 | int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address); | 892 | int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address); |
893 | #endif | ||
894 | |||
855 | int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address); | 895 | int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address); |
856 | int __pte_alloc_kernel(pmd_t *pmd, unsigned long address); | 896 | int __pte_alloc_kernel(pmd_t *pmd, unsigned long address); |
857 | 897 | ||
@@ -1130,6 +1170,11 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address, | |||
1130 | #define FOLL_GET 0x04 /* do get_page on page */ | 1170 | #define FOLL_GET 0x04 /* do get_page on page */ |
1131 | #define FOLL_ANON 0x08 /* give ZERO_PAGE if no pgtable */ | 1171 | #define FOLL_ANON 0x08 /* give ZERO_PAGE if no pgtable */ |
1132 | 1172 | ||
1173 | typedef int (*pte_fn_t)(pte_t *pte, struct page *pmd_page, unsigned long addr, | ||
1174 | void *data); | ||
1175 | extern int apply_to_page_range(struct mm_struct *mm, unsigned long address, | ||
1176 | unsigned long size, pte_fn_t fn, void *data); | ||
1177 | |||
1133 | #ifdef CONFIG_PROC_FS | 1178 | #ifdef CONFIG_PROC_FS |
1134 | void vm_stat_account(struct mm_struct *, unsigned long, struct file *, long); | 1179 | void vm_stat_account(struct mm_struct *, unsigned long, struct file *, long); |
1135 | #else | 1180 | #else |