|
@@ -4041,7 +4041,7 @@ static void do_ccupdate_local(void *info)
|
|
|
}
|
|
|
|
|
|
/* Always called with the slab_mutex held */
|
|
|
-static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
|
|
|
+static int __do_tune_cpucache(struct kmem_cache *cachep, int limit,
|
|
|
int batchcount, int shared, gfp_t gfp)
|
|
|
{
|
|
|
struct ccupdate_struct *new;
|
|
@@ -4084,12 +4084,48 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
|
|
|
return alloc_kmemlist(cachep, gfp);
|
|
|
}
|
|
|
|
|
|
+static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
|
|
|
+ int batchcount, int shared, gfp_t gfp)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ struct kmem_cache *c = NULL;
|
|
|
+ int i = 0;
|
|
|
+
|
|
|
+ ret = __do_tune_cpucache(cachep, limit, batchcount, shared, gfp);
|
|
|
+
|
|
|
+ if (slab_state < FULL)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ if ((ret < 0) || !is_root_cache(cachep))
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ for_each_memcg_cache_index(i) {
|
|
|
+ c = cache_from_memcg(cachep, i);
|
|
|
+ if (c)
|
|
|
+ /* return value determined by the parent cache only */
|
|
|
+ __do_tune_cpucache(c, limit, batchcount, shared, gfp);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/* Called with slab_mutex held always */
|
|
|
static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp)
|
|
|
{
|
|
|
int err;
|
|
|
- int limit, shared;
|
|
|
+ int limit = 0;
|
|
|
+ int shared = 0;
|
|
|
+ int batchcount = 0;
|
|
|
+
|
|
|
+ if (!is_root_cache(cachep)) {
|
|
|
+ struct kmem_cache *root = memcg_root_cache(cachep);
|
|
|
+ limit = root->limit;
|
|
|
+ shared = root->shared;
|
|
|
+ batchcount = root->batchcount;
|
|
|
+ }
|
|
|
|
|
|
+ if (limit && shared && batchcount)
|
|
|
+ goto skip_setup;
|
|
|
/*
|
|
|
* The head array serves three purposes:
|
|
|
* - 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)
|
|
|
if (limit > 32)
|
|
|
limit = 32;
|
|
|
#endif
|
|
|
- err = do_tune_cpucache(cachep, limit, (limit + 1) / 2, shared, gfp);
|
|
|
+ batchcount = (limit + 1) / 2;
|
|
|
+skip_setup:
|
|
|
+ err = do_tune_cpucache(cachep, limit, batchcount, shared, gfp);
|
|
|
if (err)
|
|
|
printk(KERN_ERR "enable_cpucache failed for %s, error %d.\n",
|
|
|
cachep->name, -err);
|