diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/Makefile | 2 | ||||
-rw-r--r-- | mm/maccess.c | 55 | ||||
-rw-r--r-- | mm/oom_kill.c | 4 | ||||
-rw-r--r-- | mm/slub.c | 97 | ||||
-rw-r--r-- | mm/sparse.c | 10 | ||||
-rw-r--r-- | mm/vmstat.c | 1 |
6 files changed, 133 insertions, 36 deletions
diff --git a/mm/Makefile b/mm/Makefile index a5b0dd93427a..18c143b3c46c 100644 --- a/mm/Makefile +++ b/mm/Makefile | |||
@@ -8,7 +8,7 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \ | |||
8 | vmalloc.o | 8 | vmalloc.o |
9 | 9 | ||
10 | obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ | 10 | obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ |
11 | page_alloc.o page-writeback.o pdflush.o \ | 11 | maccess.o page_alloc.o page-writeback.o pdflush.o \ |
12 | readahead.o swap.o truncate.o vmscan.o \ | 12 | readahead.o swap.o truncate.o vmscan.o \ |
13 | prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ | 13 | prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ |
14 | page_isolation.o $(mmu-y) | 14 | page_isolation.o $(mmu-y) |
diff --git a/mm/maccess.c b/mm/maccess.c new file mode 100644 index 000000000000..ac40796cfb15 --- /dev/null +++ b/mm/maccess.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Access kernel memory without faulting. | ||
3 | */ | ||
4 | #include <linux/uaccess.h> | ||
5 | #include <linux/module.h> | ||
6 | #include <linux/mm.h> | ||
7 | |||
8 | /** | ||
9 | * probe_kernel_read(): safely attempt to read from a location | ||
10 | * @dst: pointer to the buffer that shall take the data | ||
11 | * @src: address to read from | ||
12 | * @size: size of the data chunk | ||
13 | * | ||
14 | * Safely read from address @src to the buffer at @dst. If a kernel fault | ||
15 | * happens, handle that and return -EFAULT. | ||
16 | */ | ||
17 | long probe_kernel_read(void *dst, void *src, size_t size) | ||
18 | { | ||
19 | long ret; | ||
20 | mm_segment_t old_fs = get_fs(); | ||
21 | |||
22 | set_fs(KERNEL_DS); | ||
23 | pagefault_disable(); | ||
24 | ret = __copy_from_user_inatomic(dst, | ||
25 | (__force const void __user *)src, size); | ||
26 | pagefault_enable(); | ||
27 | set_fs(old_fs); | ||
28 | |||
29 | return ret ? -EFAULT : 0; | ||
30 | } | ||
31 | EXPORT_SYMBOL_GPL(probe_kernel_read); | ||
32 | |||
33 | /** | ||
34 | * probe_kernel_write(): safely attempt to write to a location | ||
35 | * @dst: address to write to | ||
36 | * @src: pointer to the data that shall be written | ||
37 | * @size: size of the data chunk | ||
38 | * | ||
39 | * Safely write to address @dst from the buffer at @src. If a kernel fault | ||
40 | * happens, handle that and return -EFAULT. | ||
41 | */ | ||
42 | long probe_kernel_write(void *dst, void *src, size_t size) | ||
43 | { | ||
44 | long ret; | ||
45 | mm_segment_t old_fs = get_fs(); | ||
46 | |||
47 | set_fs(KERNEL_DS); | ||
48 | pagefault_disable(); | ||
49 | ret = __copy_to_user_inatomic((__force void __user *)dst, src, size); | ||
50 | pagefault_enable(); | ||
51 | set_fs(old_fs); | ||
52 | |||
53 | return ret ? -EFAULT : 0; | ||
54 | } | ||
55 | EXPORT_SYMBOL_GPL(probe_kernel_write); | ||
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index f255eda693b0..beb592fe9389 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -423,7 +423,7 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask) | |||
423 | struct task_struct *p; | 423 | struct task_struct *p; |
424 | 424 | ||
425 | cgroup_lock(); | 425 | cgroup_lock(); |
426 | rcu_read_lock(); | 426 | read_lock(&tasklist_lock); |
427 | retry: | 427 | retry: |
428 | p = select_bad_process(&points, mem); | 428 | p = select_bad_process(&points, mem); |
429 | if (PTR_ERR(p) == -1UL) | 429 | if (PTR_ERR(p) == -1UL) |
@@ -436,7 +436,7 @@ retry: | |||
436 | "Memory cgroup out of memory")) | 436 | "Memory cgroup out of memory")) |
437 | goto retry; | 437 | goto retry; |
438 | out: | 438 | out: |
439 | rcu_read_unlock(); | 439 | read_unlock(&tasklist_lock); |
440 | cgroup_unlock(); | 440 | cgroup_unlock(); |
441 | } | 441 | } |
442 | #endif | 442 | #endif |
@@ -837,6 +837,35 @@ static void remove_full(struct kmem_cache *s, struct page *page) | |||
837 | spin_unlock(&n->list_lock); | 837 | spin_unlock(&n->list_lock); |
838 | } | 838 | } |
839 | 839 | ||
840 | /* Tracking of the number of slabs for debugging purposes */ | ||
841 | static inline unsigned long slabs_node(struct kmem_cache *s, int node) | ||
842 | { | ||
843 | struct kmem_cache_node *n = get_node(s, node); | ||
844 | |||
845 | return atomic_long_read(&n->nr_slabs); | ||
846 | } | ||
847 | |||
848 | static inline void inc_slabs_node(struct kmem_cache *s, int node) | ||
849 | { | ||
850 | struct kmem_cache_node *n = get_node(s, node); | ||
851 | |||
852 | /* | ||
853 | * May be called early in order to allocate a slab for the | ||
854 | * kmem_cache_node structure. Solve the chicken-egg | ||
855 | * dilemma by deferring the increment of the count during | ||
856 | * bootstrap (see early_kmem_cache_node_alloc). | ||
857 | */ | ||
858 | if (!NUMA_BUILD || n) | ||
859 | atomic_long_inc(&n->nr_slabs); | ||
860 | } | ||
861 | static inline void dec_slabs_node(struct kmem_cache *s, int node) | ||
862 | { | ||
863 | struct kmem_cache_node *n = get_node(s, node); | ||
864 | |||
865 | atomic_long_dec(&n->nr_slabs); | ||
866 | } | ||
867 | |||
868 | /* Object debug checks for alloc/free paths */ | ||
840 | static void setup_object_debug(struct kmem_cache *s, struct page *page, | 869 | static void setup_object_debug(struct kmem_cache *s, struct page *page, |
841 | void *object) | 870 | void *object) |
842 | { | 871 | { |
@@ -1028,6 +1057,11 @@ static inline unsigned long kmem_cache_flags(unsigned long objsize, | |||
1028 | return flags; | 1057 | return flags; |
1029 | } | 1058 | } |
1030 | #define slub_debug 0 | 1059 | #define slub_debug 0 |
1060 | |||
1061 | static inline unsigned long slabs_node(struct kmem_cache *s, int node) | ||
1062 | { return 0; } | ||
1063 | static inline void inc_slabs_node(struct kmem_cache *s, int node) {} | ||
1064 | static inline void dec_slabs_node(struct kmem_cache *s, int node) {} | ||
1031 | #endif | 1065 | #endif |
1032 | /* | 1066 | /* |
1033 | * Slab allocation and freeing | 1067 | * Slab allocation and freeing |
@@ -1066,7 +1100,6 @@ static void setup_object(struct kmem_cache *s, struct page *page, | |||
1066 | static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) | 1100 | static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) |
1067 | { | 1101 | { |
1068 | struct page *page; | 1102 | struct page *page; |
1069 | struct kmem_cache_node *n; | ||
1070 | void *start; | 1103 | void *start; |
1071 | void *last; | 1104 | void *last; |
1072 | void *p; | 1105 | void *p; |
@@ -1078,9 +1111,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) | |||
1078 | if (!page) | 1111 | if (!page) |
1079 | goto out; | 1112 | goto out; |
1080 | 1113 | ||
1081 | n = get_node(s, page_to_nid(page)); | 1114 | inc_slabs_node(s, page_to_nid(page)); |
1082 | if (n) | ||
1083 | atomic_long_inc(&n->nr_slabs); | ||
1084 | page->slab = s; | 1115 | page->slab = s; |
1085 | page->flags |= 1 << PG_slab; | 1116 | page->flags |= 1 << PG_slab; |
1086 | if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON | | 1117 | if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON | |
@@ -1125,6 +1156,8 @@ static void __free_slab(struct kmem_cache *s, struct page *page) | |||
1125 | NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE, | 1156 | NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE, |
1126 | -pages); | 1157 | -pages); |
1127 | 1158 | ||
1159 | __ClearPageSlab(page); | ||
1160 | reset_page_mapcount(page); | ||
1128 | __free_pages(page, s->order); | 1161 | __free_pages(page, s->order); |
1129 | } | 1162 | } |
1130 | 1163 | ||
@@ -1151,11 +1184,7 @@ static void free_slab(struct kmem_cache *s, struct page *page) | |||
1151 | 1184 | ||
1152 | static void discard_slab(struct kmem_cache *s, struct page *page) | 1185 | static void discard_slab(struct kmem_cache *s, struct page *page) |
1153 | { | 1186 | { |
1154 | struct kmem_cache_node *n = get_node(s, page_to_nid(page)); | 1187 | dec_slabs_node(s, page_to_nid(page)); |
1155 | |||
1156 | atomic_long_dec(&n->nr_slabs); | ||
1157 | reset_page_mapcount(page); | ||
1158 | __ClearPageSlab(page); | ||
1159 | free_slab(s, page); | 1188 | free_slab(s, page); |
1160 | } | 1189 | } |
1161 | 1190 | ||
@@ -1886,15 +1915,18 @@ static void init_kmem_cache_cpu(struct kmem_cache *s, | |||
1886 | c->node = 0; | 1915 | c->node = 0; |
1887 | c->offset = s->offset / sizeof(void *); | 1916 | c->offset = s->offset / sizeof(void *); |
1888 | c->objsize = s->objsize; | 1917 | c->objsize = s->objsize; |
1918 | #ifdef CONFIG_SLUB_STATS | ||
1919 | memset(c->stat, 0, NR_SLUB_STAT_ITEMS * sizeof(unsigned)); | ||
1920 | #endif | ||
1889 | } | 1921 | } |
1890 | 1922 | ||
1891 | static void init_kmem_cache_node(struct kmem_cache_node *n) | 1923 | static void init_kmem_cache_node(struct kmem_cache_node *n) |
1892 | { | 1924 | { |
1893 | n->nr_partial = 0; | 1925 | n->nr_partial = 0; |
1894 | atomic_long_set(&n->nr_slabs, 0); | ||
1895 | spin_lock_init(&n->list_lock); | 1926 | spin_lock_init(&n->list_lock); |
1896 | INIT_LIST_HEAD(&n->partial); | 1927 | INIT_LIST_HEAD(&n->partial); |
1897 | #ifdef CONFIG_SLUB_DEBUG | 1928 | #ifdef CONFIG_SLUB_DEBUG |
1929 | atomic_long_set(&n->nr_slabs, 0); | ||
1898 | INIT_LIST_HEAD(&n->full); | 1930 | INIT_LIST_HEAD(&n->full); |
1899 | #endif | 1931 | #endif |
1900 | } | 1932 | } |
@@ -2063,7 +2095,7 @@ static struct kmem_cache_node *early_kmem_cache_node_alloc(gfp_t gfpflags, | |||
2063 | init_tracking(kmalloc_caches, n); | 2095 | init_tracking(kmalloc_caches, n); |
2064 | #endif | 2096 | #endif |
2065 | init_kmem_cache_node(n); | 2097 | init_kmem_cache_node(n); |
2066 | atomic_long_inc(&n->nr_slabs); | 2098 | inc_slabs_node(kmalloc_caches, node); |
2067 | 2099 | ||
2068 | /* | 2100 | /* |
2069 | * lockdep requires consistent irq usage for each lock | 2101 | * lockdep requires consistent irq usage for each lock |
@@ -2376,7 +2408,7 @@ static inline int kmem_cache_close(struct kmem_cache *s) | |||
2376 | struct kmem_cache_node *n = get_node(s, node); | 2408 | struct kmem_cache_node *n = get_node(s, node); |
2377 | 2409 | ||
2378 | n->nr_partial -= free_list(s, n, &n->partial); | 2410 | n->nr_partial -= free_list(s, n, &n->partial); |
2379 | if (atomic_long_read(&n->nr_slabs)) | 2411 | if (slabs_node(s, node)) |
2380 | return 1; | 2412 | return 1; |
2381 | } | 2413 | } |
2382 | free_kmem_cache_nodes(s); | 2414 | free_kmem_cache_nodes(s); |
@@ -2409,10 +2441,6 @@ EXPORT_SYMBOL(kmem_cache_destroy); | |||
2409 | struct kmem_cache kmalloc_caches[PAGE_SHIFT + 1] __cacheline_aligned; | 2441 | struct kmem_cache kmalloc_caches[PAGE_SHIFT + 1] __cacheline_aligned; |
2410 | EXPORT_SYMBOL(kmalloc_caches); | 2442 | EXPORT_SYMBOL(kmalloc_caches); |
2411 | 2443 | ||
2412 | #ifdef CONFIG_ZONE_DMA | ||
2413 | static struct kmem_cache *kmalloc_caches_dma[PAGE_SHIFT + 1]; | ||
2414 | #endif | ||
2415 | |||
2416 | static int __init setup_slub_min_order(char *str) | 2444 | static int __init setup_slub_min_order(char *str) |
2417 | { | 2445 | { |
2418 | get_option(&str, &slub_min_order); | 2446 | get_option(&str, &slub_min_order); |
@@ -2472,6 +2500,7 @@ panic: | |||
2472 | } | 2500 | } |
2473 | 2501 | ||
2474 | #ifdef CONFIG_ZONE_DMA | 2502 | #ifdef CONFIG_ZONE_DMA |
2503 | static struct kmem_cache *kmalloc_caches_dma[PAGE_SHIFT + 1]; | ||
2475 | 2504 | ||
2476 | static void sysfs_add_func(struct work_struct *w) | 2505 | static void sysfs_add_func(struct work_struct *w) |
2477 | { | 2506 | { |
@@ -2688,21 +2717,6 @@ void kfree(const void *x) | |||
2688 | } | 2717 | } |
2689 | EXPORT_SYMBOL(kfree); | 2718 | EXPORT_SYMBOL(kfree); |
2690 | 2719 | ||
2691 | #if defined(CONFIG_SLUB_DEBUG) || defined(CONFIG_SLABINFO) | ||
2692 | static unsigned long count_partial(struct kmem_cache_node *n) | ||
2693 | { | ||
2694 | unsigned long flags; | ||
2695 | unsigned long x = 0; | ||
2696 | struct page *page; | ||
2697 | |||
2698 | spin_lock_irqsave(&n->list_lock, flags); | ||
2699 | list_for_each_entry(page, &n->partial, lru) | ||
2700 | x += page->inuse; | ||
2701 | spin_unlock_irqrestore(&n->list_lock, flags); | ||
2702 | return x; | ||
2703 | } | ||
2704 | #endif | ||
2705 | |||
2706 | /* | 2720 | /* |
2707 | * kmem_cache_shrink removes empty slabs from the partial lists and sorts | 2721 | * kmem_cache_shrink removes empty slabs from the partial lists and sorts |
2708 | * the remaining slabs by the number of items in use. The slabs with the | 2722 | * the remaining slabs by the number of items in use. The slabs with the |
@@ -2816,7 +2830,7 @@ static void slab_mem_offline_callback(void *arg) | |||
2816 | * and offline_pages() function shoudn't call this | 2830 | * and offline_pages() function shoudn't call this |
2817 | * callback. So, we must fail. | 2831 | * callback. So, we must fail. |
2818 | */ | 2832 | */ |
2819 | BUG_ON(atomic_long_read(&n->nr_slabs)); | 2833 | BUG_ON(slabs_node(s, offline_node)); |
2820 | 2834 | ||
2821 | s->node[offline_node] = NULL; | 2835 | s->node[offline_node] = NULL; |
2822 | kmem_cache_free(kmalloc_caches, n); | 2836 | kmem_cache_free(kmalloc_caches, n); |
@@ -3181,6 +3195,21 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, | |||
3181 | return slab_alloc(s, gfpflags, node, caller); | 3195 | return slab_alloc(s, gfpflags, node, caller); |
3182 | } | 3196 | } |
3183 | 3197 | ||
3198 | #if (defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)) || defined(CONFIG_SLABINFO) | ||
3199 | static unsigned long count_partial(struct kmem_cache_node *n) | ||
3200 | { | ||
3201 | unsigned long flags; | ||
3202 | unsigned long x = 0; | ||
3203 | struct page *page; | ||
3204 | |||
3205 | spin_lock_irqsave(&n->list_lock, flags); | ||
3206 | list_for_each_entry(page, &n->partial, lru) | ||
3207 | x += page->inuse; | ||
3208 | spin_unlock_irqrestore(&n->list_lock, flags); | ||
3209 | return x; | ||
3210 | } | ||
3211 | #endif | ||
3212 | |||
3184 | #if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG) | 3213 | #if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG) |
3185 | static int validate_slab(struct kmem_cache *s, struct page *page, | 3214 | static int validate_slab(struct kmem_cache *s, struct page *page, |
3186 | unsigned long *map) | 3215 | unsigned long *map) |
@@ -3979,10 +4008,12 @@ static int show_stat(struct kmem_cache *s, char *buf, enum stat_item si) | |||
3979 | 4008 | ||
3980 | len = sprintf(buf, "%lu", sum); | 4009 | len = sprintf(buf, "%lu", sum); |
3981 | 4010 | ||
4011 | #ifdef CONFIG_SMP | ||
3982 | for_each_online_cpu(cpu) { | 4012 | for_each_online_cpu(cpu) { |
3983 | if (data[cpu] && len < PAGE_SIZE - 20) | 4013 | if (data[cpu] && len < PAGE_SIZE - 20) |
3984 | len += sprintf(buf + len, " c%d=%u", cpu, data[cpu]); | 4014 | len += sprintf(buf + len, " C%d=%u", cpu, data[cpu]); |
3985 | } | 4015 | } |
4016 | #endif | ||
3986 | kfree(data); | 4017 | kfree(data); |
3987 | return len + sprintf(buf + len, "\n"); | 4018 | return len + sprintf(buf + len, "\n"); |
3988 | } | 4019 | } |
diff --git a/mm/sparse.c b/mm/sparse.c index f6a43c09c322..98d6b39c3472 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
@@ -149,8 +149,18 @@ static inline int sparse_early_nid(struct mem_section *section) | |||
149 | /* Record a memory area against a node. */ | 149 | /* Record a memory area against a node. */ |
150 | void __init memory_present(int nid, unsigned long start, unsigned long end) | 150 | void __init memory_present(int nid, unsigned long start, unsigned long end) |
151 | { | 151 | { |
152 | unsigned long max_arch_pfn = 1UL << (MAX_PHYSMEM_BITS-PAGE_SHIFT); | ||
152 | unsigned long pfn; | 153 | unsigned long pfn; |
153 | 154 | ||
155 | /* | ||
156 | * Sanity checks - do not allow an architecture to pass | ||
157 | * in larger pfns than the maximum scope of sparsemem: | ||
158 | */ | ||
159 | if (start >= max_arch_pfn) | ||
160 | return; | ||
161 | if (end >= max_arch_pfn) | ||
162 | end = max_arch_pfn; | ||
163 | |||
154 | start &= PAGE_SECTION_MASK; | 164 | start &= PAGE_SECTION_MASK; |
155 | for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) { | 165 | for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) { |
156 | unsigned long section = pfn_to_section_nr(pfn); | 166 | unsigned long section = pfn_to_section_nr(pfn); |
diff --git a/mm/vmstat.c b/mm/vmstat.c index 422d960ffcd8..7c7286e9506d 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -388,6 +388,7 @@ static char * const migratetype_names[MIGRATE_TYPES] = { | |||
388 | "Reclaimable", | 388 | "Reclaimable", |
389 | "Movable", | 389 | "Movable", |
390 | "Reserve", | 390 | "Reserve", |
391 | "Isolate", | ||
391 | }; | 392 | }; |
392 | 393 | ||
393 | static void *frag_start(struct seq_file *m, loff_t *pos) | 394 | static void *frag_start(struct seq_file *m, loff_t *pos) |