aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-22 23:54:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-22 23:54:20 -0400
commitb1386cedda177b10fac009ca8d3681034f15b5b3 (patch)
treee979766970249b4cf3b1bae41a91ee7430041bd8
parentd15ae814ccb0df179e93d64c4642e7f58ee8398b (diff)
parent368301f2fe4b07e5fb71dba3cc566bc59eb6705f (diff)
Merge branch 'akpm' (patches from Andrew)
Merge misc fixes from Andrew Morton: "Five fixes" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: pps: do not crash when failed to register tools/vm/slabinfo: fix an unintentional printf testing/radix-tree: fix a macro expansion bug radix-tree: fix radix_tree_iter_retry() for tagged iterators. mm: memcontrol: fix cgroup creation failure after many small jobs
-rw-r--r--drivers/pps/clients/pps_parport.c2
-rw-r--r--include/linux/memcontrol.h25
-rw-r--r--include/linux/radix-tree.h1
-rw-r--r--mm/memcontrol.c82
-rw-r--r--mm/slab_common.c4
-rw-r--r--tools/testing/radix-tree/tag_check.c2
-rw-r--r--tools/vm/slabinfo.c3
7 files changed, 92 insertions, 27 deletions
diff --git a/drivers/pps/clients/pps_parport.c b/drivers/pps/clients/pps_parport.c
index 38a8bbe74810..83797d89c30f 100644
--- a/drivers/pps/clients/pps_parport.c
+++ b/drivers/pps/clients/pps_parport.c
@@ -195,7 +195,7 @@ static void parport_detach(struct parport *port)
195 struct pps_client_pp *device; 195 struct pps_client_pp *device;
196 196
197 /* FIXME: oooh, this is ugly! */ 197 /* FIXME: oooh, this is ugly! */
198 if (strcmp(pardev->name, KBUILD_MODNAME)) 198 if (!pardev || strcmp(pardev->name, KBUILD_MODNAME))
199 /* not our port */ 199 /* not our port */
200 return; 200 return;
201 201
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index a805474df4ab..56e6069d2452 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -97,6 +97,11 @@ enum mem_cgroup_events_target {
97#define MEM_CGROUP_ID_SHIFT 16 97#define MEM_CGROUP_ID_SHIFT 16
98#define MEM_CGROUP_ID_MAX USHRT_MAX 98#define MEM_CGROUP_ID_MAX USHRT_MAX
99 99
100struct mem_cgroup_id {
101 int id;
102 atomic_t ref;
103};
104
100struct mem_cgroup_stat_cpu { 105struct mem_cgroup_stat_cpu {
101 long count[MEMCG_NR_STAT]; 106 long count[MEMCG_NR_STAT];
102 unsigned long events[MEMCG_NR_EVENTS]; 107 unsigned long events[MEMCG_NR_EVENTS];
@@ -172,6 +177,9 @@ enum memcg_kmem_state {
172struct mem_cgroup { 177struct mem_cgroup {
173 struct cgroup_subsys_state css; 178 struct cgroup_subsys_state css;
174 179
180 /* Private memcg ID. Used to ID objects that outlive the cgroup */
181 struct mem_cgroup_id id;
182
175 /* Accounted resources */ 183 /* Accounted resources */
176 struct page_counter memory; 184 struct page_counter memory;
177 struct page_counter swap; 185 struct page_counter swap;
@@ -330,22 +338,9 @@ static inline unsigned short mem_cgroup_id(struct mem_cgroup *memcg)
330 if (mem_cgroup_disabled()) 338 if (mem_cgroup_disabled())
331 return 0; 339 return 0;
332 340
333 return memcg->css.id; 341 return memcg->id.id;
334}
335
336/**
337 * mem_cgroup_from_id - look up a memcg from an id
338 * @id: the id to look up
339 *
340 * Caller must hold rcu_read_lock() and use css_tryget() as necessary.
341 */
342static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
343{
344 struct cgroup_subsys_state *css;
345
346 css = css_from_id(id, &memory_cgrp_subsys);
347 return mem_cgroup_from_css(css);
348} 342}
343struct mem_cgroup *mem_cgroup_from_id(unsigned short id);
349 344
350/** 345/**
351 * parent_mem_cgroup - find the accounting parent of a memcg 346 * parent_mem_cgroup - find the accounting parent of a memcg
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index cb4b7e8cee81..eca6f626c16e 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -407,6 +407,7 @@ static inline __must_check
407void **radix_tree_iter_retry(struct radix_tree_iter *iter) 407void **radix_tree_iter_retry(struct radix_tree_iter *iter)
408{ 408{
409 iter->next_index = iter->index; 409 iter->next_index = iter->index;
410 iter->tags = 0;
410 return NULL; 411 return NULL;
411} 412}
412 413
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index ac8664db3823..5339c89dff63 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -4057,6 +4057,60 @@ static struct cftype mem_cgroup_legacy_files[] = {
4057 { }, /* terminate */ 4057 { }, /* terminate */
4058}; 4058};
4059 4059
4060/*
4061 * Private memory cgroup IDR
4062 *
4063 * Swap-out records and page cache shadow entries need to store memcg
4064 * references in constrained space, so we maintain an ID space that is
4065 * limited to 16 bit (MEM_CGROUP_ID_MAX), limiting the total number of
4066 * memory-controlled cgroups to 64k.
4067 *
4068 * However, there usually are many references to the oflline CSS after
4069 * the cgroup has been destroyed, such as page cache or reclaimable
4070 * slab objects, that don't need to hang on to the ID. We want to keep
4071 * those dead CSS from occupying IDs, or we might quickly exhaust the
4072 * relatively small ID space and prevent the creation of new cgroups
4073 * even when there are much fewer than 64k cgroups - possibly none.
4074 *
4075 * Maintain a private 16-bit ID space for memcg, and allow the ID to
4076 * be freed and recycled when it's no longer needed, which is usually
4077 * when the CSS is offlined.
4078 *
4079 * The only exception to that are records of swapped out tmpfs/shmem
4080 * pages that need to be attributed to live ancestors on swapin. But
4081 * those references are manageable from userspace.
4082 */
4083
4084static DEFINE_IDR(mem_cgroup_idr);
4085
4086static void mem_cgroup_id_get(struct mem_cgroup *memcg)
4087{
4088 atomic_inc(&memcg->id.ref);
4089}
4090
4091static void mem_cgroup_id_put(struct mem_cgroup *memcg)
4092{
4093 if (atomic_dec_and_test(&memcg->id.ref)) {
4094 idr_remove(&mem_cgroup_idr, memcg->id.id);
4095 memcg->id.id = 0;
4096
4097 /* Memcg ID pins CSS */
4098 css_put(&memcg->css);
4099 }
4100}
4101
4102/**
4103 * mem_cgroup_from_id - look up a memcg from a memcg id
4104 * @id: the memcg id to look up
4105 *
4106 * Caller must hold rcu_read_lock().
4107 */
4108struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
4109{
4110 WARN_ON_ONCE(!rcu_read_lock_held());
4111 return idr_find(&mem_cgroup_idr, id);
4112}
4113
4060static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node) 4114static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
4061{ 4115{
4062 struct mem_cgroup_per_node *pn; 4116 struct mem_cgroup_per_node *pn;
@@ -4116,6 +4170,12 @@ static struct mem_cgroup *mem_cgroup_alloc(void)
4116 if (!memcg) 4170 if (!memcg)
4117 return NULL; 4171 return NULL;
4118 4172
4173 memcg->id.id = idr_alloc(&mem_cgroup_idr, NULL,
4174 1, MEM_CGROUP_ID_MAX,
4175 GFP_KERNEL);
4176 if (memcg->id.id < 0)
4177 goto fail;
4178
4119 memcg->stat = alloc_percpu(struct mem_cgroup_stat_cpu); 4179 memcg->stat = alloc_percpu(struct mem_cgroup_stat_cpu);
4120 if (!memcg->stat) 4180 if (!memcg->stat)
4121 goto fail; 4181 goto fail;
@@ -4142,8 +4202,11 @@ static struct mem_cgroup *mem_cgroup_alloc(void)
4142#ifdef CONFIG_CGROUP_WRITEBACK 4202#ifdef CONFIG_CGROUP_WRITEBACK
4143 INIT_LIST_HEAD(&memcg->cgwb_list); 4203 INIT_LIST_HEAD(&memcg->cgwb_list);
4144#endif 4204#endif
4205 idr_replace(&mem_cgroup_idr, memcg, memcg->id.id);
4145 return memcg; 4206 return memcg;
4146fail: 4207fail:
4208 if (memcg->id.id > 0)
4209 idr_remove(&mem_cgroup_idr, memcg->id.id);
4147 mem_cgroup_free(memcg); 4210 mem_cgroup_free(memcg);
4148 return NULL; 4211 return NULL;
4149} 4212}
@@ -4206,12 +4269,11 @@ fail:
4206 return ERR_PTR(-ENOMEM); 4269 return ERR_PTR(-ENOMEM);
4207} 4270}
4208 4271
4209static int 4272static int mem_cgroup_css_online(struct cgroup_subsys_state *css)
4210mem_cgroup_css_online(struct cgroup_subsys_state *css)
4211{ 4273{
4212 if (css->id > MEM_CGROUP_ID_MAX) 4274 /* Online state pins memcg ID, memcg ID pins CSS */
4213 return -ENOSPC; 4275 mem_cgroup_id_get(mem_cgroup_from_css(css));
4214 4276 css_get(css);
4215 return 0; 4277 return 0;
4216} 4278}
4217 4279
@@ -4234,6 +4296,8 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
4234 4296
4235 memcg_offline_kmem(memcg); 4297 memcg_offline_kmem(memcg);
4236 wb_memcg_offline(memcg); 4298 wb_memcg_offline(memcg);
4299
4300 mem_cgroup_id_put(memcg);
4237} 4301}
4238 4302
4239static void mem_cgroup_css_released(struct cgroup_subsys_state *css) 4303static void mem_cgroup_css_released(struct cgroup_subsys_state *css)
@@ -5756,6 +5820,7 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
5756 if (!memcg) 5820 if (!memcg)
5757 return; 5821 return;
5758 5822
5823 mem_cgroup_id_get(memcg);
5759 oldid = swap_cgroup_record(entry, mem_cgroup_id(memcg)); 5824 oldid = swap_cgroup_record(entry, mem_cgroup_id(memcg));
5760 VM_BUG_ON_PAGE(oldid, page); 5825 VM_BUG_ON_PAGE(oldid, page);
5761 mem_cgroup_swap_statistics(memcg, true); 5826 mem_cgroup_swap_statistics(memcg, true);
@@ -5774,6 +5839,9 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
5774 VM_BUG_ON(!irqs_disabled()); 5839 VM_BUG_ON(!irqs_disabled());
5775 mem_cgroup_charge_statistics(memcg, page, false, -1); 5840 mem_cgroup_charge_statistics(memcg, page, false, -1);
5776 memcg_check_events(memcg, page); 5841 memcg_check_events(memcg, page);
5842
5843 if (!mem_cgroup_is_root(memcg))
5844 css_put(&memcg->css);
5777} 5845}
5778 5846
5779/* 5847/*
@@ -5804,11 +5872,11 @@ int mem_cgroup_try_charge_swap(struct page *page, swp_entry_t entry)
5804 !page_counter_try_charge(&memcg->swap, 1, &counter)) 5872 !page_counter_try_charge(&memcg->swap, 1, &counter))
5805 return -ENOMEM; 5873 return -ENOMEM;
5806 5874
5875 mem_cgroup_id_get(memcg);
5807 oldid = swap_cgroup_record(entry, mem_cgroup_id(memcg)); 5876 oldid = swap_cgroup_record(entry, mem_cgroup_id(memcg));
5808 VM_BUG_ON_PAGE(oldid, page); 5877 VM_BUG_ON_PAGE(oldid, page);
5809 mem_cgroup_swap_statistics(memcg, true); 5878 mem_cgroup_swap_statistics(memcg, true);
5810 5879
5811 css_get(&memcg->css);
5812 return 0; 5880 return 0;
5813} 5881}
5814 5882
@@ -5837,7 +5905,7 @@ void mem_cgroup_uncharge_swap(swp_entry_t entry)
5837 page_counter_uncharge(&memcg->memsw, 1); 5905 page_counter_uncharge(&memcg->memsw, 1);
5838 } 5906 }
5839 mem_cgroup_swap_statistics(memcg, false); 5907 mem_cgroup_swap_statistics(memcg, false);
5840 css_put(&memcg->css); 5908 mem_cgroup_id_put(memcg);
5841 } 5909 }
5842 rcu_read_unlock(); 5910 rcu_read_unlock();
5843} 5911}
diff --git a/mm/slab_common.c b/mm/slab_common.c
index a65dad7fdcd1..82317abb03ed 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -526,8 +526,8 @@ void memcg_create_kmem_cache(struct mem_cgroup *memcg,
526 goto out_unlock; 526 goto out_unlock;
527 527
528 cgroup_name(css->cgroup, memcg_name_buf, sizeof(memcg_name_buf)); 528 cgroup_name(css->cgroup, memcg_name_buf, sizeof(memcg_name_buf));
529 cache_name = kasprintf(GFP_KERNEL, "%s(%d:%s)", root_cache->name, 529 cache_name = kasprintf(GFP_KERNEL, "%s(%llu:%s)", root_cache->name,
530 css->id, memcg_name_buf); 530 css->serial_nr, memcg_name_buf);
531 if (!cache_name) 531 if (!cache_name)
532 goto out_unlock; 532 goto out_unlock;
533 533
diff --git a/tools/testing/radix-tree/tag_check.c b/tools/testing/radix-tree/tag_check.c
index b7447ceb75e9..b0ac05741750 100644
--- a/tools/testing/radix-tree/tag_check.c
+++ b/tools/testing/radix-tree/tag_check.c
@@ -122,7 +122,7 @@ enum {
122 NODE_TAGGED = 2, 122 NODE_TAGGED = 2,
123}; 123};
124 124
125#define THRASH_SIZE 1000 * 1000 125#define THRASH_SIZE (1000 * 1000)
126#define N 127 126#define N 127
127#define BATCH 33 127#define BATCH 33
128 128
diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c
index 7cf6e1769903..b9d34b37c017 100644
--- a/tools/vm/slabinfo.c
+++ b/tools/vm/slabinfo.c
@@ -510,10 +510,11 @@ static void slab_stats(struct slabinfo *s)
510 s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total); 510 s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total);
511 } 511 }
512 512
513 if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail) 513 if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail) {
514 printf("\nCmpxchg_double Looping\n------------------------\n"); 514 printf("\nCmpxchg_double Looping\n------------------------\n");
515 printf("Locked Cmpxchg Double redos %lu\nUnlocked Cmpxchg Double redos %lu\n", 515 printf("Locked Cmpxchg Double redos %lu\nUnlocked Cmpxchg Double redos %lu\n",
516 s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail); 516 s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail);
517 }
517} 518}
518 519
519static void report(struct slabinfo *s) 520static void report(struct slabinfo *s)