diff options
Diffstat (limited to 'include/linux/mm.h')
-rw-r--r-- | include/linux/mm.h | 142 |
1 files changed, 133 insertions, 9 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index 721f451c3029..f6385fc17ad4 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/mm_types.h> | 14 | #include <linux/mm_types.h> |
15 | #include <linux/range.h> | 15 | #include <linux/range.h> |
16 | #include <linux/pfn.h> | 16 | #include <linux/pfn.h> |
17 | #include <linux/bit_spinlock.h> | ||
17 | 18 | ||
18 | struct mempolicy; | 19 | struct mempolicy; |
19 | struct anon_vma; | 20 | struct anon_vma; |
@@ -82,6 +83,7 @@ extern unsigned int kobjsize(const void *objp); | |||
82 | #define VM_GROWSUP 0x00000200 | 83 | #define VM_GROWSUP 0x00000200 |
83 | #else | 84 | #else |
84 | #define VM_GROWSUP 0x00000000 | 85 | #define VM_GROWSUP 0x00000000 |
86 | #define VM_NOHUGEPAGE 0x00000200 /* MADV_NOHUGEPAGE marked this vma */ | ||
85 | #endif | 87 | #endif |
86 | #define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */ | 88 | #define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */ |
87 | #define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */ | 89 | #define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */ |
@@ -101,7 +103,11 @@ extern unsigned int kobjsize(const void *objp); | |||
101 | #define VM_NORESERVE 0x00200000 /* should the VM suppress accounting */ | 103 | #define VM_NORESERVE 0x00200000 /* should the VM suppress accounting */ |
102 | #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ | 104 | #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ |
103 | #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ | 105 | #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ |
106 | #ifndef CONFIG_TRANSPARENT_HUGEPAGE | ||
104 | #define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */ | 107 | #define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */ |
108 | #else | ||
109 | #define VM_HUGEPAGE 0x01000000 /* MADV_HUGEPAGE marked this vma */ | ||
110 | #endif | ||
105 | #define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */ | 111 | #define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */ |
106 | #define VM_ALWAYSDUMP 0x04000000 /* Always include in core dumps */ | 112 | #define VM_ALWAYSDUMP 0x04000000 /* Always include in core dumps */ |
107 | 113 | ||
@@ -242,6 +248,7 @@ struct inode; | |||
242 | * files which need it (119 of them) | 248 | * files which need it (119 of them) |
243 | */ | 249 | */ |
244 | #include <linux/page-flags.h> | 250 | #include <linux/page-flags.h> |
251 | #include <linux/huge_mm.h> | ||
245 | 252 | ||
246 | /* | 253 | /* |
247 | * Methods to modify the page usage count. | 254 | * Methods to modify the page usage count. |
@@ -305,6 +312,39 @@ static inline int is_vmalloc_or_module_addr(const void *x) | |||
305 | } | 312 | } |
306 | #endif | 313 | #endif |
307 | 314 | ||
315 | static inline void compound_lock(struct page *page) | ||
316 | { | ||
317 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
318 | bit_spin_lock(PG_compound_lock, &page->flags); | ||
319 | #endif | ||
320 | } | ||
321 | |||
322 | static inline void compound_unlock(struct page *page) | ||
323 | { | ||
324 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
325 | bit_spin_unlock(PG_compound_lock, &page->flags); | ||
326 | #endif | ||
327 | } | ||
328 | |||
329 | static inline unsigned long compound_lock_irqsave(struct page *page) | ||
330 | { | ||
331 | unsigned long uninitialized_var(flags); | ||
332 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
333 | local_irq_save(flags); | ||
334 | compound_lock(page); | ||
335 | #endif | ||
336 | return flags; | ||
337 | } | ||
338 | |||
339 | static inline void compound_unlock_irqrestore(struct page *page, | ||
340 | unsigned long flags) | ||
341 | { | ||
342 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
343 | compound_unlock(page); | ||
344 | local_irq_restore(flags); | ||
345 | #endif | ||
346 | } | ||
347 | |||
308 | static inline struct page *compound_head(struct page *page) | 348 | static inline struct page *compound_head(struct page *page) |
309 | { | 349 | { |
310 | if (unlikely(PageTail(page))) | 350 | if (unlikely(PageTail(page))) |
@@ -319,9 +359,29 @@ static inline int page_count(struct page *page) | |||
319 | 359 | ||
320 | static inline void get_page(struct page *page) | 360 | static inline void get_page(struct page *page) |
321 | { | 361 | { |
322 | page = compound_head(page); | 362 | /* |
323 | VM_BUG_ON(atomic_read(&page->_count) == 0); | 363 | * Getting a normal page or the head of a compound page |
364 | * requires to already have an elevated page->_count. Only if | ||
365 | * we're getting a tail page, the elevated page->_count is | ||
366 | * required only in the head page, so for tail pages the | ||
367 | * bugcheck only verifies that the page->_count isn't | ||
368 | * negative. | ||
369 | */ | ||
370 | VM_BUG_ON(atomic_read(&page->_count) < !PageTail(page)); | ||
324 | atomic_inc(&page->_count); | 371 | atomic_inc(&page->_count); |
372 | /* | ||
373 | * Getting a tail page will elevate both the head and tail | ||
374 | * page->_count(s). | ||
375 | */ | ||
376 | if (unlikely(PageTail(page))) { | ||
377 | /* | ||
378 | * This is safe only because | ||
379 | * __split_huge_page_refcount can't run under | ||
380 | * get_page(). | ||
381 | */ | ||
382 | VM_BUG_ON(atomic_read(&page->first_page->_count) <= 0); | ||
383 | atomic_inc(&page->first_page->_count); | ||
384 | } | ||
325 | } | 385 | } |
326 | 386 | ||
327 | static inline struct page *virt_to_head_page(const void *x) | 387 | static inline struct page *virt_to_head_page(const void *x) |
@@ -339,6 +399,27 @@ static inline void init_page_count(struct page *page) | |||
339 | atomic_set(&page->_count, 1); | 399 | atomic_set(&page->_count, 1); |
340 | } | 400 | } |
341 | 401 | ||
402 | /* | ||
403 | * PageBuddy() indicate that the page is free and in the buddy system | ||
404 | * (see mm/page_alloc.c). | ||
405 | */ | ||
406 | static inline int PageBuddy(struct page *page) | ||
407 | { | ||
408 | return atomic_read(&page->_mapcount) == -2; | ||
409 | } | ||
410 | |||
411 | static inline void __SetPageBuddy(struct page *page) | ||
412 | { | ||
413 | VM_BUG_ON(atomic_read(&page->_mapcount) != -1); | ||
414 | atomic_set(&page->_mapcount, -2); | ||
415 | } | ||
416 | |||
417 | static inline void __ClearPageBuddy(struct page *page) | ||
418 | { | ||
419 | VM_BUG_ON(!PageBuddy(page)); | ||
420 | atomic_set(&page->_mapcount, -1); | ||
421 | } | ||
422 | |||
342 | void put_page(struct page *page); | 423 | void put_page(struct page *page); |
343 | void put_pages_list(struct list_head *pages); | 424 | void put_pages_list(struct list_head *pages); |
344 | 425 | ||
@@ -370,11 +451,40 @@ static inline int compound_order(struct page *page) | |||
370 | return (unsigned long)page[1].lru.prev; | 451 | return (unsigned long)page[1].lru.prev; |
371 | } | 452 | } |
372 | 453 | ||
454 | static inline int compound_trans_order(struct page *page) | ||
455 | { | ||
456 | int order; | ||
457 | unsigned long flags; | ||
458 | |||
459 | if (!PageHead(page)) | ||
460 | return 0; | ||
461 | |||
462 | flags = compound_lock_irqsave(page); | ||
463 | order = compound_order(page); | ||
464 | compound_unlock_irqrestore(page, flags); | ||
465 | return order; | ||
466 | } | ||
467 | |||
373 | static inline void set_compound_order(struct page *page, unsigned long order) | 468 | static inline void set_compound_order(struct page *page, unsigned long order) |
374 | { | 469 | { |
375 | page[1].lru.prev = (void *)order; | 470 | page[1].lru.prev = (void *)order; |
376 | } | 471 | } |
377 | 472 | ||
473 | #ifdef CONFIG_MMU | ||
474 | /* | ||
475 | * Do pte_mkwrite, but only if the vma says VM_WRITE. We do this when | ||
476 | * servicing faults for write access. In the normal case, do always want | ||
477 | * pte_mkwrite. But get_user_pages can cause write faults for mappings | ||
478 | * that do not have writing enabled, when used by access_process_vm. | ||
479 | */ | ||
480 | static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma) | ||
481 | { | ||
482 | if (likely(vma->vm_flags & VM_WRITE)) | ||
483 | pte = pte_mkwrite(pte); | ||
484 | return pte; | ||
485 | } | ||
486 | #endif | ||
487 | |||
378 | /* | 488 | /* |
379 | * Multiple processes may "see" the same page. E.g. for untouched | 489 | * Multiple processes may "see" the same page. E.g. for untouched |
380 | * mappings of /dev/null, all processes see the same page full of | 490 | * mappings of /dev/null, all processes see the same page full of |
@@ -657,7 +767,7 @@ static inline struct address_space *page_mapping(struct page *page) | |||
657 | VM_BUG_ON(PageSlab(page)); | 767 | VM_BUG_ON(PageSlab(page)); |
658 | if (unlikely(PageSwapCache(page))) | 768 | if (unlikely(PageSwapCache(page))) |
659 | mapping = &swapper_space; | 769 | mapping = &swapper_space; |
660 | else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON)) | 770 | else if ((unsigned long)mapping & PAGE_MAPPING_ANON) |
661 | mapping = NULL; | 771 | mapping = NULL; |
662 | return mapping; | 772 | return mapping; |
663 | } | 773 | } |
@@ -1064,7 +1174,8 @@ static inline int __pmd_alloc(struct mm_struct *mm, pud_t *pud, | |||
1064 | int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address); | 1174 | int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address); |
1065 | #endif | 1175 | #endif |
1066 | 1176 | ||
1067 | int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address); | 1177 | int __pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, |
1178 | pmd_t *pmd, unsigned long address); | ||
1068 | int __pte_alloc_kernel(pmd_t *pmd, unsigned long address); | 1179 | int __pte_alloc_kernel(pmd_t *pmd, unsigned long address); |
1069 | 1180 | ||
1070 | /* | 1181 | /* |
@@ -1133,16 +1244,18 @@ static inline void pgtable_page_dtor(struct page *page) | |||
1133 | pte_unmap(pte); \ | 1244 | pte_unmap(pte); \ |
1134 | } while (0) | 1245 | } while (0) |
1135 | 1246 | ||
1136 | #define pte_alloc_map(mm, pmd, address) \ | 1247 | #define pte_alloc_map(mm, vma, pmd, address) \ |
1137 | ((unlikely(!pmd_present(*(pmd))) && __pte_alloc(mm, pmd, address))? \ | 1248 | ((unlikely(pmd_none(*(pmd))) && __pte_alloc(mm, vma, \ |
1138 | NULL: pte_offset_map(pmd, address)) | 1249 | pmd, address))? \ |
1250 | NULL: pte_offset_map(pmd, address)) | ||
1139 | 1251 | ||
1140 | #define pte_alloc_map_lock(mm, pmd, address, ptlp) \ | 1252 | #define pte_alloc_map_lock(mm, pmd, address, ptlp) \ |
1141 | ((unlikely(!pmd_present(*(pmd))) && __pte_alloc(mm, pmd, address))? \ | 1253 | ((unlikely(pmd_none(*(pmd))) && __pte_alloc(mm, NULL, \ |
1254 | pmd, address))? \ | ||
1142 | NULL: pte_offset_map_lock(mm, pmd, address, ptlp)) | 1255 | NULL: pte_offset_map_lock(mm, pmd, address, ptlp)) |
1143 | 1256 | ||
1144 | #define pte_alloc_kernel(pmd, address) \ | 1257 | #define pte_alloc_kernel(pmd, address) \ |
1145 | ((unlikely(!pmd_present(*(pmd))) && __pte_alloc_kernel(pmd, address))? \ | 1258 | ((unlikely(pmd_none(*(pmd))) && __pte_alloc_kernel(pmd, address))? \ |
1146 | NULL: pte_offset_kernel(pmd, address)) | 1259 | NULL: pte_offset_kernel(pmd, address)) |
1147 | 1260 | ||
1148 | extern void free_area_init(unsigned long * zones_size); | 1261 | extern void free_area_init(unsigned long * zones_size); |
@@ -1415,6 +1528,8 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address, | |||
1415 | #define FOLL_GET 0x04 /* do get_page on page */ | 1528 | #define FOLL_GET 0x04 /* do get_page on page */ |
1416 | #define FOLL_DUMP 0x08 /* give error on hole if it would be zero */ | 1529 | #define FOLL_DUMP 0x08 /* give error on hole if it would be zero */ |
1417 | #define FOLL_FORCE 0x10 /* get_user_pages read/write w/o permission */ | 1530 | #define FOLL_FORCE 0x10 /* get_user_pages read/write w/o permission */ |
1531 | #define FOLL_MLOCK 0x40 /* mark page as mlocked */ | ||
1532 | #define FOLL_SPLIT 0x80 /* don't return transhuge pages, split them */ | ||
1418 | 1533 | ||
1419 | typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, | 1534 | typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, |
1420 | void *data); | 1535 | void *data); |
@@ -1518,5 +1633,14 @@ static inline int is_hwpoison_address(unsigned long addr) | |||
1518 | 1633 | ||
1519 | extern void dump_page(struct page *page); | 1634 | extern void dump_page(struct page *page); |
1520 | 1635 | ||
1636 | #if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLBFS) | ||
1637 | extern void clear_huge_page(struct page *page, | ||
1638 | unsigned long addr, | ||
1639 | unsigned int pages_per_huge_page); | ||
1640 | extern void copy_user_huge_page(struct page *dst, struct page *src, | ||
1641 | unsigned long addr, struct vm_area_struct *vma, | ||
1642 | unsigned int pages_per_huge_page); | ||
1643 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */ | ||
1644 | |||
1521 | #endif /* __KERNEL__ */ | 1645 | #endif /* __KERNEL__ */ |
1522 | #endif /* _LINUX_MM_H */ | 1646 | #endif /* _LINUX_MM_H */ |