|
@@ -258,8 +258,8 @@ struct mem_cgroup {
|
|
|
*/
|
|
|
struct rcu_head rcu_freeing;
|
|
|
/*
|
|
|
- * But when using vfree(), that cannot be done at
|
|
|
- * interrupt time, so we must then queue the work.
|
|
|
+ * We also need some space for a worker in deferred freeing.
|
|
|
+ * By the time we call it, rcu_freeing is no longer in use.
|
|
|
*/
|
|
|
struct work_struct work_freeing;
|
|
|
};
|
|
@@ -4702,23 +4702,28 @@ out_free:
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Helpers for freeing a vzalloc()ed mem_cgroup by RCU,
|
|
|
+ * Helpers for freeing a kmalloc()ed/vzalloc()ed mem_cgroup by RCU,
|
|
|
* but in process context. The work_freeing structure is overlaid
|
|
|
* on the rcu_freeing structure, which itself is overlaid on memsw.
|
|
|
*/
|
|
|
-static void vfree_work(struct work_struct *work)
|
|
|
+static void free_work(struct work_struct *work)
|
|
|
{
|
|
|
struct mem_cgroup *memcg;
|
|
|
+ int size = sizeof(struct mem_cgroup);
|
|
|
|
|
|
memcg = container_of(work, struct mem_cgroup, work_freeing);
|
|
|
- vfree(memcg);
|
|
|
+ if (size < PAGE_SIZE)
|
|
|
+ kfree(memcg);
|
|
|
+ else
|
|
|
+ vfree(memcg);
|
|
|
}
|
|
|
-static void vfree_rcu(struct rcu_head *rcu_head)
|
|
|
+
|
|
|
+static void free_rcu(struct rcu_head *rcu_head)
|
|
|
{
|
|
|
struct mem_cgroup *memcg;
|
|
|
|
|
|
memcg = container_of(rcu_head, struct mem_cgroup, rcu_freeing);
|
|
|
- INIT_WORK(&memcg->work_freeing, vfree_work);
|
|
|
+ INIT_WORK(&memcg->work_freeing, free_work);
|
|
|
schedule_work(&memcg->work_freeing);
|
|
|
}
|
|
|
|
|
@@ -4744,10 +4749,7 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
|
|
|
free_mem_cgroup_per_zone_info(memcg, node);
|
|
|
|
|
|
free_percpu(memcg->stat);
|
|
|
- if (sizeof(struct mem_cgroup) < PAGE_SIZE)
|
|
|
- kfree_rcu(memcg, rcu_freeing);
|
|
|
- else
|
|
|
- call_rcu(&memcg->rcu_freeing, vfree_rcu);
|
|
|
+ call_rcu(&memcg->rcu_freeing, free_rcu);
|
|
|
}
|
|
|
|
|
|
static void mem_cgroup_get(struct mem_cgroup *memcg)
|