diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-12 18:44:27 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-12 18:44:27 -0400 |
| commit | ac4de9543aca59f2b763746647577302fbedd57e (patch) | |
| tree | 40407750569ee030de56233c41c9a97f7e89cf67 /include/linux | |
| parent | 26935fb06ee88f1188789807687c03041f3c70d9 (diff) | |
| parent | de32a8177f64bc62e1b19c685dd391af664ab13f (diff) | |
Merge branch 'akpm' (patches from Andrew Morton)
Merge more patches from Andrew Morton:
"The rest of MM. Plus one misc cleanup"
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (35 commits)
mm/Kconfig: add MMU dependency for MIGRATION.
kernel: replace strict_strto*() with kstrto*()
mm, thp: count thp_fault_fallback anytime thp fault fails
thp: consolidate code between handle_mm_fault() and do_huge_pmd_anonymous_page()
thp: do_huge_pmd_anonymous_page() cleanup
thp: move maybe_pmd_mkwrite() out of mk_huge_pmd()
mm: cleanup add_to_page_cache_locked()
thp: account anon transparent huge pages into NR_ANON_PAGES
truncate: drop 'oldsize' truncate_pagecache() parameter
mm: make lru_add_drain_all() selective
memcg: document cgroup dirty/writeback memory statistics
memcg: add per cgroup writeback pages accounting
memcg: check for proper lock held in mem_cgroup_update_page_stat
memcg: remove MEMCG_NR_FILE_MAPPED
memcg: reduce function dereference
memcg: avoid overflow caused by PAGE_ALIGN
memcg: rename RESOURCE_MAX to RES_COUNTER_MAX
memcg: correct RESOURCE_MAX to ULLONG_MAX
mm: memcg: do not trap chargers with full callstack on OOM
mm: memcg: rework and document OOM waiting and wakeup
...
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/huge_mm.h | 3 | ||||
| -rw-r--r-- | include/linux/memcontrol.h | 148 | ||||
| -rw-r--r-- | include/linux/mm.h | 6 | ||||
| -rw-r--r-- | include/linux/res_counter.h | 2 | ||||
| -rw-r--r-- | include/linux/sched.h | 7 | ||||
| -rw-r--r-- | include/linux/swap.h | 2 |
6 files changed, 143 insertions, 25 deletions
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h index b60de92e2edc..3935428c57cf 100644 --- a/include/linux/huge_mm.h +++ b/include/linux/huge_mm.h | |||
| @@ -96,9 +96,6 @@ extern int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
| 96 | pmd_t *dst_pmd, pmd_t *src_pmd, | 96 | pmd_t *dst_pmd, pmd_t *src_pmd, |
| 97 | struct vm_area_struct *vma, | 97 | struct vm_area_struct *vma, |
| 98 | unsigned long addr, unsigned long end); | 98 | unsigned long addr, unsigned long end); |
| 99 | extern int handle_pte_fault(struct mm_struct *mm, | ||
| 100 | struct vm_area_struct *vma, unsigned long address, | ||
| 101 | pte_t *pte, pmd_t *pmd, unsigned int flags); | ||
| 102 | extern int split_huge_page_to_list(struct page *page, struct list_head *list); | 99 | extern int split_huge_page_to_list(struct page *page, struct list_head *list); |
| 103 | static inline int split_huge_page(struct page *page) | 100 | static inline int split_huge_page(struct page *page) |
| 104 | { | 101 | { |
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 6c416092e324..60e95872da29 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h | |||
| @@ -30,9 +30,21 @@ struct page; | |||
| 30 | struct mm_struct; | 30 | struct mm_struct; |
| 31 | struct kmem_cache; | 31 | struct kmem_cache; |
| 32 | 32 | ||
| 33 | /* Stats that can be updated by kernel. */ | 33 | /* |
| 34 | enum mem_cgroup_page_stat_item { | 34 | * The corresponding mem_cgroup_stat_names is defined in mm/memcontrol.c, |
| 35 | MEMCG_NR_FILE_MAPPED, /* # of pages charged as file rss */ | 35 | * These two lists should keep in accord with each other. |
| 36 | */ | ||
| 37 | enum mem_cgroup_stat_index { | ||
| 38 | /* | ||
| 39 | * For MEM_CONTAINER_TYPE_ALL, usage = pagecache + rss. | ||
| 40 | */ | ||
| 41 | MEM_CGROUP_STAT_CACHE, /* # of pages charged as cache */ | ||
| 42 | MEM_CGROUP_STAT_RSS, /* # of pages charged as anon rss */ | ||
| 43 | MEM_CGROUP_STAT_RSS_HUGE, /* # of pages charged as anon huge */ | ||
| 44 | MEM_CGROUP_STAT_FILE_MAPPED, /* # of pages charged as file rss */ | ||
| 45 | MEM_CGROUP_STAT_WRITEBACK, /* # of pages under writeback */ | ||
| 46 | MEM_CGROUP_STAT_SWAP, /* # of pages, swapped out */ | ||
| 47 | MEM_CGROUP_STAT_NSTATS, | ||
| 36 | }; | 48 | }; |
| 37 | 49 | ||
| 38 | struct mem_cgroup_reclaim_cookie { | 50 | struct mem_cgroup_reclaim_cookie { |
| @@ -41,6 +53,23 @@ struct mem_cgroup_reclaim_cookie { | |||
| 41 | unsigned int generation; | 53 | unsigned int generation; |
| 42 | }; | 54 | }; |
| 43 | 55 | ||
| 56 | enum mem_cgroup_filter_t { | ||
| 57 | VISIT, /* visit current node */ | ||
| 58 | SKIP, /* skip the current node and continue traversal */ | ||
| 59 | SKIP_TREE, /* skip the whole subtree and continue traversal */ | ||
| 60 | }; | ||
| 61 | |||
| 62 | /* | ||
| 63 | * mem_cgroup_filter_t predicate might instruct mem_cgroup_iter_cond how to | ||
| 64 | * iterate through the hierarchy tree. Each tree element is checked by the | ||
| 65 | * predicate before it is returned by the iterator. If a filter returns | ||
| 66 | * SKIP or SKIP_TREE then the iterator code continues traversal (with the | ||
| 67 | * next node down the hierarchy or the next node that doesn't belong under the | ||
| 68 | * memcg's subtree). | ||
| 69 | */ | ||
| 70 | typedef enum mem_cgroup_filter_t | ||
| 71 | (*mem_cgroup_iter_filter)(struct mem_cgroup *memcg, struct mem_cgroup *root); | ||
| 72 | |||
| 44 | #ifdef CONFIG_MEMCG | 73 | #ifdef CONFIG_MEMCG |
| 45 | /* | 74 | /* |
| 46 | * All "charge" functions with gfp_mask should use GFP_KERNEL or | 75 | * All "charge" functions with gfp_mask should use GFP_KERNEL or |
| @@ -108,9 +137,18 @@ mem_cgroup_prepare_migration(struct page *page, struct page *newpage, | |||
| 108 | extern void mem_cgroup_end_migration(struct mem_cgroup *memcg, | 137 | extern void mem_cgroup_end_migration(struct mem_cgroup *memcg, |
| 109 | struct page *oldpage, struct page *newpage, bool migration_ok); | 138 | struct page *oldpage, struct page *newpage, bool migration_ok); |
| 110 | 139 | ||
| 111 | struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *, | 140 | struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root, |
| 112 | struct mem_cgroup *, | 141 | struct mem_cgroup *prev, |
| 113 | struct mem_cgroup_reclaim_cookie *); | 142 | struct mem_cgroup_reclaim_cookie *reclaim, |
| 143 | mem_cgroup_iter_filter cond); | ||
| 144 | |||
| 145 | static inline struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root, | ||
| 146 | struct mem_cgroup *prev, | ||
| 147 | struct mem_cgroup_reclaim_cookie *reclaim) | ||
| 148 | { | ||
| 149 | return mem_cgroup_iter_cond(root, prev, reclaim, NULL); | ||
| 150 | } | ||
| 151 | |||
| 114 | void mem_cgroup_iter_break(struct mem_cgroup *, struct mem_cgroup *); | 152 | void mem_cgroup_iter_break(struct mem_cgroup *, struct mem_cgroup *); |
| 115 | 153 | ||
| 116 | /* | 154 | /* |
| @@ -125,6 +163,48 @@ extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, | |||
| 125 | extern void mem_cgroup_replace_page_cache(struct page *oldpage, | 163 | extern void mem_cgroup_replace_page_cache(struct page *oldpage, |
| 126 | struct page *newpage); | 164 | struct page *newpage); |
| 127 | 165 | ||
| 166 | /** | ||
| 167 | * mem_cgroup_toggle_oom - toggle the memcg OOM killer for the current task | ||
| 168 | * @new: true to enable, false to disable | ||
| 169 | * | ||
| 170 | * Toggle whether a failed memcg charge should invoke the OOM killer | ||
| 171 | * or just return -ENOMEM. Returns the previous toggle state. | ||
| 172 | * | ||
| 173 | * NOTE: Any path that enables the OOM killer before charging must | ||
| 174 | * call mem_cgroup_oom_synchronize() afterward to finalize the | ||
| 175 | * OOM handling and clean up. | ||
| 176 | */ | ||
| 177 | static inline bool mem_cgroup_toggle_oom(bool new) | ||
| 178 | { | ||
| 179 | bool old; | ||
| 180 | |||
| 181 | old = current->memcg_oom.may_oom; | ||
| 182 | current->memcg_oom.may_oom = new; | ||
| 183 | |||
| 184 | return old; | ||
| 185 | } | ||
| 186 | |||
| 187 | static inline void mem_cgroup_enable_oom(void) | ||
| 188 | { | ||
| 189 | bool old = mem_cgroup_toggle_oom(true); | ||
| 190 | |||
| 191 | WARN_ON(old == true); | ||
| 192 | } | ||
| 193 | |||
| 194 | static inline void mem_cgroup_disable_oom(void) | ||
| 195 | { | ||
| 196 | bool old = mem_cgroup_toggle_oom(false); | ||
| 197 | |||
| 198 | WARN_ON(old == false); | ||
| 199 | } | ||
| 200 | |||
| 201 | static inline bool task_in_memcg_oom(struct task_struct *p) | ||
| 202 | { | ||
| 203 | return p->memcg_oom.in_memcg_oom; | ||
| 204 | } | ||
| 205 | |||
| 206 | bool mem_cgroup_oom_synchronize(void); | ||
| 207 | |||
| 128 | #ifdef CONFIG_MEMCG_SWAP | 208 | #ifdef CONFIG_MEMCG_SWAP |
| 129 | extern int do_swap_account; | 209 | extern int do_swap_account; |
| 130 | #endif | 210 | #endif |
| @@ -165,24 +245,24 @@ static inline void mem_cgroup_end_update_page_stat(struct page *page, | |||
| 165 | } | 245 | } |
| 166 | 246 | ||
| 167 | void mem_cgroup_update_page_stat(struct page *page, | 247 | void mem_cgroup_update_page_stat(struct page *page, |
| 168 | enum mem_cgroup_page_stat_item idx, | 248 | enum mem_cgroup_stat_index idx, |
| 169 | int val); | 249 | int val); |
| 170 | 250 | ||
| 171 | static inline void mem_cgroup_inc_page_stat(struct page *page, | 251 | static inline void mem_cgroup_inc_page_stat(struct page *page, |
| 172 | enum mem_cgroup_page_stat_item idx) | 252 | enum mem_cgroup_stat_index idx) |
| 173 | { | 253 | { |
| 174 | mem_cgroup_update_page_stat(page, idx, 1); | 254 | mem_cgroup_update_page_stat(page, idx, 1); |
| 175 | } | 255 | } |
| 176 | 256 | ||
| 177 | static inline void mem_cgroup_dec_page_stat(struct page *page, | 257 | static inline void mem_cgroup_dec_page_stat(struct page *page, |
| 178 | enum mem_cgroup_page_stat_item idx) | 258 | enum mem_cgroup_stat_index idx) |
| 179 | { | 259 | { |
| 180 | mem_cgroup_update_page_stat(page, idx, -1); | 260 | mem_cgroup_update_page_stat(page, idx, -1); |
| 181 | } | 261 | } |
| 182 | 262 | ||
| 183 | unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, | 263 | enum mem_cgroup_filter_t |
| 184 | gfp_t gfp_mask, | 264 | mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg, |
| 185 | unsigned long *total_scanned); | 265 | struct mem_cgroup *root); |
| 186 | 266 | ||
| 187 | void __mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx); | 267 | void __mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx); |
| 188 | static inline void mem_cgroup_count_vm_event(struct mm_struct *mm, | 268 | static inline void mem_cgroup_count_vm_event(struct mm_struct *mm, |
| @@ -296,6 +376,15 @@ static inline void mem_cgroup_end_migration(struct mem_cgroup *memcg, | |||
| 296 | struct page *oldpage, struct page *newpage, bool migration_ok) | 376 | struct page *oldpage, struct page *newpage, bool migration_ok) |
| 297 | { | 377 | { |
| 298 | } | 378 | } |
| 379 | static inline struct mem_cgroup * | ||
| 380 | mem_cgroup_iter_cond(struct mem_cgroup *root, | ||
| 381 | struct mem_cgroup *prev, | ||
| 382 | struct mem_cgroup_reclaim_cookie *reclaim, | ||
| 383 | mem_cgroup_iter_filter cond) | ||
| 384 | { | ||
| 385 | /* first call must return non-NULL, second return NULL */ | ||
| 386 | return (struct mem_cgroup *)(unsigned long)!prev; | ||
| 387 | } | ||
| 299 | 388 | ||
| 300 | static inline struct mem_cgroup * | 389 | static inline struct mem_cgroup * |
| 301 | mem_cgroup_iter(struct mem_cgroup *root, | 390 | mem_cgroup_iter(struct mem_cgroup *root, |
| @@ -348,22 +437,45 @@ static inline void mem_cgroup_end_update_page_stat(struct page *page, | |||
| 348 | { | 437 | { |
| 349 | } | 438 | } |
| 350 | 439 | ||
| 440 | static inline bool mem_cgroup_toggle_oom(bool new) | ||
| 441 | { | ||
| 442 | return false; | ||
| 443 | } | ||
| 444 | |||
| 445 | static inline void mem_cgroup_enable_oom(void) | ||
| 446 | { | ||
| 447 | } | ||
| 448 | |||
| 449 | static inline void mem_cgroup_disable_oom(void) | ||
| 450 | { | ||
| 451 | } | ||
| 452 | |||
| 453 | static inline bool task_in_memcg_oom(struct task_struct *p) | ||
| 454 | { | ||
| 455 | return false; | ||
| 456 | } | ||
| 457 | |||
| 458 | static inline bool mem_cgroup_oom_synchronize(void) | ||
| 459 | { | ||
| 460 | return false; | ||
| 461 | } | ||
| 462 | |||
| 351 | static inline void mem_cgroup_inc_page_stat(struct page *page, | 463 | static inline void mem_cgroup_inc_page_stat(struct page *page, |
| 352 | enum mem_cgroup_page_stat_item idx) | 464 | enum mem_cgroup_stat_index idx) |
| 353 | { | 465 | { |
| 354 | } | 466 | } |
| 355 | 467 | ||
| 356 | static inline void mem_cgroup_dec_page_stat(struct page *page, | 468 | static inline void mem_cgroup_dec_page_stat(struct page *page, |
| 357 | enum mem_cgroup_page_stat_item idx) | 469 | enum mem_cgroup_stat_index idx) |
| 358 | { | 470 | { |
| 359 | } | 471 | } |
| 360 | 472 | ||
| 361 | static inline | 473 | static inline |
| 362 | unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, | 474 | enum mem_cgroup_filter_t |
| 363 | gfp_t gfp_mask, | 475 | mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg, |
| 364 | unsigned long *total_scanned) | 476 | struct mem_cgroup *root) |
| 365 | { | 477 | { |
| 366 | return 0; | 478 | return VISIT; |
| 367 | } | 479 | } |
| 368 | 480 | ||
| 369 | static inline void mem_cgroup_split_huge_fixup(struct page *head) | 481 | static inline void mem_cgroup_split_huge_fixup(struct page *head) |
diff --git a/include/linux/mm.h b/include/linux/mm.h index caf543c7eaa7..8b6e55ee8855 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -176,6 +176,7 @@ extern pgprot_t protection_map[16]; | |||
| 176 | #define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */ | 176 | #define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */ |
| 177 | #define FAULT_FLAG_KILLABLE 0x20 /* The fault task is in SIGKILL killable region */ | 177 | #define FAULT_FLAG_KILLABLE 0x20 /* The fault task is in SIGKILL killable region */ |
| 178 | #define FAULT_FLAG_TRIED 0x40 /* second try */ | 178 | #define FAULT_FLAG_TRIED 0x40 /* second try */ |
| 179 | #define FAULT_FLAG_USER 0x80 /* The fault originated in userspace */ | ||
| 179 | 180 | ||
| 180 | /* | 181 | /* |
| 181 | * vm_fault is filled by the the pagefault handler and passed to the vma's | 182 | * vm_fault is filled by the the pagefault handler and passed to the vma's |
| @@ -876,11 +877,12 @@ static inline int page_mapped(struct page *page) | |||
| 876 | #define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */ | 877 | #define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */ |
| 877 | #define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */ | 878 | #define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */ |
| 878 | #define VM_FAULT_RETRY 0x0400 /* ->fault blocked, must retry */ | 879 | #define VM_FAULT_RETRY 0x0400 /* ->fault blocked, must retry */ |
| 880 | #define VM_FAULT_FALLBACK 0x0800 /* huge page fault failed, fall back to small */ | ||
| 879 | 881 | ||
| 880 | #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */ | 882 | #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */ |
| 881 | 883 | ||
| 882 | #define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \ | 884 | #define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \ |
| 883 | VM_FAULT_HWPOISON_LARGE) | 885 | VM_FAULT_FALLBACK | VM_FAULT_HWPOISON_LARGE) |
| 884 | 886 | ||
| 885 | /* Encode hstate index for a hwpoisoned large page */ | 887 | /* Encode hstate index for a hwpoisoned large page */ |
| 886 | #define VM_FAULT_SET_HINDEX(x) ((x) << 12) | 888 | #define VM_FAULT_SET_HINDEX(x) ((x) << 12) |
| @@ -984,7 +986,7 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping, | |||
| 984 | unmap_mapping_range(mapping, holebegin, holelen, 0); | 986 | unmap_mapping_range(mapping, holebegin, holelen, 0); |
| 985 | } | 987 | } |
| 986 | 988 | ||
| 987 | extern void truncate_pagecache(struct inode *inode, loff_t old, loff_t new); | 989 | extern void truncate_pagecache(struct inode *inode, loff_t new); |
| 988 | extern void truncate_setsize(struct inode *inode, loff_t newsize); | 990 | extern void truncate_setsize(struct inode *inode, loff_t newsize); |
| 989 | void truncate_pagecache_range(struct inode *inode, loff_t offset, loff_t end); | 991 | void truncate_pagecache_range(struct inode *inode, loff_t offset, loff_t end); |
| 990 | int truncate_inode_page(struct address_space *mapping, struct page *page); | 992 | int truncate_inode_page(struct address_space *mapping, struct page *page); |
diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h index 96a509b6be04..201a69749659 100644 --- a/include/linux/res_counter.h +++ b/include/linux/res_counter.h | |||
| @@ -54,7 +54,7 @@ struct res_counter { | |||
| 54 | struct res_counter *parent; | 54 | struct res_counter *parent; |
| 55 | }; | 55 | }; |
| 56 | 56 | ||
| 57 | #define RESOURCE_MAX (unsigned long long)LLONG_MAX | 57 | #define RES_COUNTER_MAX ULLONG_MAX |
| 58 | 58 | ||
| 59 | /** | 59 | /** |
| 60 | * Helpers to interact with userspace | 60 | * Helpers to interact with userspace |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 45f254dddafc..6682da36b293 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1393,6 +1393,13 @@ struct task_struct { | |||
| 1393 | unsigned long memsw_nr_pages; /* uncharged mem+swap usage */ | 1393 | unsigned long memsw_nr_pages; /* uncharged mem+swap usage */ |
| 1394 | } memcg_batch; | 1394 | } memcg_batch; |
| 1395 | unsigned int memcg_kmem_skip_account; | 1395 | unsigned int memcg_kmem_skip_account; |
| 1396 | struct memcg_oom_info { | ||
| 1397 | unsigned int may_oom:1; | ||
| 1398 | unsigned int in_memcg_oom:1; | ||
| 1399 | unsigned int oom_locked:1; | ||
| 1400 | int wakeups; | ||
| 1401 | struct mem_cgroup *wait_on_memcg; | ||
| 1402 | } memcg_oom; | ||
| 1396 | #endif | 1403 | #endif |
| 1397 | #ifdef CONFIG_UPROBES | 1404 | #ifdef CONFIG_UPROBES |
| 1398 | struct uprobe_task *utask; | 1405 | struct uprobe_task *utask; |
diff --git a/include/linux/swap.h b/include/linux/swap.h index c03c139219c9..46ba0c6c219f 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
| @@ -280,7 +280,7 @@ extern void activate_page(struct page *); | |||
| 280 | extern void mark_page_accessed(struct page *); | 280 | extern void mark_page_accessed(struct page *); |
| 281 | extern void lru_add_drain(void); | 281 | extern void lru_add_drain(void); |
| 282 | extern void lru_add_drain_cpu(int cpu); | 282 | extern void lru_add_drain_cpu(int cpu); |
| 283 | extern int lru_add_drain_all(void); | 283 | extern void lru_add_drain_all(void); |
| 284 | extern void rotate_reclaimable_page(struct page *page); | 284 | extern void rotate_reclaimable_page(struct page *page); |
| 285 | extern void deactivate_page(struct page *page); | 285 | extern void deactivate_page(struct page *page); |
| 286 | extern void swap_setup(void); | 286 | extern void swap_setup(void); |
