diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/memcontrol.c | 10 | ||||
-rw-r--r-- | mm/slab.c | 44 | ||||
-rw-r--r-- | mm/slab.h | 12 | ||||
-rw-r--r-- | mm/slab_common.c | 7 |
4 files changed, 63 insertions, 10 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index a32d83c2e35..f3009b4bae5 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -3012,7 +3012,8 @@ int memcg_update_cache_size(struct kmem_cache *s, int num_groups) | |||
3012 | return 0; | 3012 | return 0; |
3013 | } | 3013 | } |
3014 | 3014 | ||
3015 | int memcg_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s) | 3015 | int memcg_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s, |
3016 | struct kmem_cache *root_cache) | ||
3016 | { | 3017 | { |
3017 | size_t size = sizeof(struct memcg_cache_params); | 3018 | size_t size = sizeof(struct memcg_cache_params); |
3018 | 3019 | ||
@@ -3026,8 +3027,10 @@ int memcg_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s) | |||
3026 | if (!s->memcg_params) | 3027 | if (!s->memcg_params) |
3027 | return -ENOMEM; | 3028 | return -ENOMEM; |
3028 | 3029 | ||
3029 | if (memcg) | 3030 | if (memcg) { |
3030 | s->memcg_params->memcg = memcg; | 3031 | s->memcg_params->memcg = memcg; |
3032 | s->memcg_params->root_cache = root_cache; | ||
3033 | } | ||
3031 | return 0; | 3034 | return 0; |
3032 | } | 3035 | } |
3033 | 3036 | ||
@@ -3186,7 +3189,7 @@ static struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg, | |||
3186 | return NULL; | 3189 | return NULL; |
3187 | 3190 | ||
3188 | new = kmem_cache_create_memcg(memcg, name, s->object_size, s->align, | 3191 | new = kmem_cache_create_memcg(memcg, name, s->object_size, s->align, |
3189 | (s->flags & ~SLAB_PANIC), s->ctor); | 3192 | (s->flags & ~SLAB_PANIC), s->ctor, s); |
3190 | 3193 | ||
3191 | if (new) | 3194 | if (new) |
3192 | new->allocflags |= __GFP_KMEMCG; | 3195 | new->allocflags |= __GFP_KMEMCG; |
@@ -3226,7 +3229,6 @@ static struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg, | |||
3226 | } | 3229 | } |
3227 | 3230 | ||
3228 | mem_cgroup_get(memcg); | 3231 | mem_cgroup_get(memcg); |
3229 | new_cachep->memcg_params->root_cache = cachep; | ||
3230 | atomic_set(&new_cachep->memcg_params->nr_pages , 0); | 3232 | atomic_set(&new_cachep->memcg_params->nr_pages , 0); |
3231 | 3233 | ||
3232 | cachep->memcg_params->memcg_caches[idx] = new_cachep; | 3234 | cachep->memcg_params->memcg_caches[idx] = new_cachep; |
@@ -4041,7 +4041,7 @@ static void do_ccupdate_local(void *info) | |||
4041 | } | 4041 | } |
4042 | 4042 | ||
4043 | /* Always called with the slab_mutex held */ | 4043 | /* Always called with the slab_mutex held */ |
4044 | static int do_tune_cpucache(struct kmem_cache *cachep, int limit, | 4044 | static int __do_tune_cpucache(struct kmem_cache *cachep, int limit, |
4045 | int batchcount, int shared, gfp_t gfp) | 4045 | int batchcount, int shared, gfp_t gfp) |
4046 | { | 4046 | { |
4047 | struct ccupdate_struct *new; | 4047 | struct ccupdate_struct *new; |
@@ -4084,12 +4084,48 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit, | |||
4084 | return alloc_kmemlist(cachep, gfp); | 4084 | return alloc_kmemlist(cachep, gfp); |
4085 | } | 4085 | } |
4086 | 4086 | ||
4087 | static int do_tune_cpucache(struct kmem_cache *cachep, int limit, | ||
4088 | int batchcount, int shared, gfp_t gfp) | ||
4089 | { | ||
4090 | int ret; | ||
4091 | struct kmem_cache *c = NULL; | ||
4092 | int i = 0; | ||
4093 | |||
4094 | ret = __do_tune_cpucache(cachep, limit, batchcount, shared, gfp); | ||
4095 | |||
4096 | if (slab_state < FULL) | ||
4097 | return ret; | ||
4098 | |||
4099 | if ((ret < 0) || !is_root_cache(cachep)) | ||
4100 | return ret; | ||
4101 | |||
4102 | for_each_memcg_cache_index(i) { | ||
4103 | c = cache_from_memcg(cachep, i); | ||
4104 | if (c) | ||
4105 | /* return value determined by the parent cache only */ | ||
4106 | __do_tune_cpucache(c, limit, batchcount, shared, gfp); | ||
4107 | } | ||
4108 | |||
4109 | return ret; | ||
4110 | } | ||
4111 | |||
4087 | /* Called with slab_mutex held always */ | 4112 | /* Called with slab_mutex held always */ |
4088 | static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) | 4113 | static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) |
4089 | { | 4114 | { |
4090 | int err; | 4115 | int err; |
4091 | int limit, shared; | 4116 | int limit = 0; |
4117 | int shared = 0; | ||
4118 | int batchcount = 0; | ||
4119 | |||
4120 | if (!is_root_cache(cachep)) { | ||
4121 | struct kmem_cache *root = memcg_root_cache(cachep); | ||
4122 | limit = root->limit; | ||
4123 | shared = root->shared; | ||
4124 | batchcount = root->batchcount; | ||
4125 | } | ||
4092 | 4126 | ||
4127 | if (limit && shared && batchcount) | ||
4128 | goto skip_setup; | ||
4093 | /* | 4129 | /* |
4094 | * The head array serves three purposes: | 4130 | * The head array serves three purposes: |
4095 | * - create a LIFO ordering, i.e. return objects that are cache-warm | 4131 | * - create a LIFO ordering, i.e. return objects that are cache-warm |
@@ -4131,7 +4167,9 @@ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) | |||
4131 | if (limit > 32) | 4167 | if (limit > 32) |
4132 | limit = 32; | 4168 | limit = 32; |
4133 | #endif | 4169 | #endif |
4134 | err = do_tune_cpucache(cachep, limit, (limit + 1) / 2, shared, gfp); | 4170 | batchcount = (limit + 1) / 2; |
4171 | skip_setup: | ||
4172 | err = do_tune_cpucache(cachep, limit, batchcount, shared, gfp); | ||
4135 | if (err) | 4173 | if (err) |
4136 | printk(KERN_ERR "enable_cpucache failed for %s, error %d.\n", | 4174 | printk(KERN_ERR "enable_cpucache failed for %s, error %d.\n", |
4137 | cachep->name, -err); | 4175 | cachep->name, -err); |
@@ -155,6 +155,13 @@ static inline struct kmem_cache *cache_from_memcg(struct kmem_cache *s, int idx) | |||
155 | { | 155 | { |
156 | return s->memcg_params->memcg_caches[idx]; | 156 | return s->memcg_params->memcg_caches[idx]; |
157 | } | 157 | } |
158 | |||
159 | static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s) | ||
160 | { | ||
161 | if (is_root_cache(s)) | ||
162 | return s; | ||
163 | return s->memcg_params->root_cache; | ||
164 | } | ||
158 | #else | 165 | #else |
159 | static inline bool is_root_cache(struct kmem_cache *s) | 166 | static inline bool is_root_cache(struct kmem_cache *s) |
160 | { | 167 | { |
@@ -190,6 +197,11 @@ static inline struct kmem_cache *cache_from_memcg(struct kmem_cache *s, int idx) | |||
190 | { | 197 | { |
191 | return NULL; | 198 | return NULL; |
192 | } | 199 | } |
200 | |||
201 | static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s) | ||
202 | { | ||
203 | return s; | ||
204 | } | ||
193 | #endif | 205 | #endif |
194 | 206 | ||
195 | static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x) | 207 | static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x) |
diff --git a/mm/slab_common.c b/mm/slab_common.c index 081f1b8d9a7..3f3cd97d3fd 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c | |||
@@ -164,7 +164,8 @@ unsigned long calculate_alignment(unsigned long flags, | |||
164 | 164 | ||
165 | struct kmem_cache * | 165 | struct kmem_cache * |
166 | kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size, | 166 | kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size, |
167 | size_t align, unsigned long flags, void (*ctor)(void *)) | 167 | size_t align, unsigned long flags, void (*ctor)(void *), |
168 | struct kmem_cache *parent_cache) | ||
168 | { | 169 | { |
169 | struct kmem_cache *s = NULL; | 170 | struct kmem_cache *s = NULL; |
170 | int err = 0; | 171 | int err = 0; |
@@ -193,7 +194,7 @@ kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size, | |||
193 | s->align = calculate_alignment(flags, align, size); | 194 | s->align = calculate_alignment(flags, align, size); |
194 | s->ctor = ctor; | 195 | s->ctor = ctor; |
195 | 196 | ||
196 | if (memcg_register_cache(memcg, s)) { | 197 | if (memcg_register_cache(memcg, s, parent_cache)) { |
197 | kmem_cache_free(kmem_cache, s); | 198 | kmem_cache_free(kmem_cache, s); |
198 | err = -ENOMEM; | 199 | err = -ENOMEM; |
199 | goto out_locked; | 200 | goto out_locked; |
@@ -243,7 +244,7 @@ struct kmem_cache * | |||
243 | kmem_cache_create(const char *name, size_t size, size_t align, | 244 | kmem_cache_create(const char *name, size_t size, size_t align, |
244 | unsigned long flags, void (*ctor)(void *)) | 245 | unsigned long flags, void (*ctor)(void *)) |
245 | { | 246 | { |
246 | return kmem_cache_create_memcg(NULL, name, size, align, flags, ctor); | 247 | return kmem_cache_create_memcg(NULL, name, size, align, flags, ctor, NULL); |
247 | } | 248 | } |
248 | EXPORT_SYMBOL(kmem_cache_create); | 249 | EXPORT_SYMBOL(kmem_cache_create); |
249 | 250 | ||