|
@@ -50,6 +50,8 @@
|
|
|
#include <linux/cpu.h>
|
|
|
#include <linux/oom.h>
|
|
|
#include "internal.h"
|
|
|
+#include <net/sock.h>
|
|
|
+#include <net/tcp_memcontrol.h>
|
|
|
|
|
|
#include <asm/uaccess.h>
|
|
|
|
|
@@ -295,6 +297,10 @@ struct mem_cgroup {
|
|
|
*/
|
|
|
struct mem_cgroup_stat_cpu nocpu_base;
|
|
|
spinlock_t pcp_counter_lock;
|
|
|
+
|
|
|
+#ifdef CONFIG_INET
|
|
|
+ struct tcp_memcontrol tcp_mem;
|
|
|
+#endif
|
|
|
};
|
|
|
|
|
|
/* Stuffs for move charges at task migration. */
|
|
@@ -384,6 +390,7 @@ static void mem_cgroup_put(struct mem_cgroup *memcg);
|
|
|
#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
|
|
|
#ifdef CONFIG_INET
|
|
|
#include <net/sock.h>
|
|
|
+#include <net/ip.h>
|
|
|
|
|
|
static bool mem_cgroup_is_root(struct mem_cgroup *memcg);
|
|
|
void sock_update_memcg(struct sock *sk)
|
|
@@ -418,6 +425,15 @@ void sock_release_memcg(struct sock *sk)
|
|
|
mem_cgroup_put(memcg);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg)
|
|
|
+{
|
|
|
+ if (!memcg || mem_cgroup_is_root(memcg))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ return &memcg->tcp_mem.cg_proto;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(tcp_proto_cgroup);
|
|
|
#endif /* CONFIG_INET */
|
|
|
#endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */
|
|
|
|
|
@@ -800,7 +816,7 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page)
|
|
|
preempt_enable();
|
|
|
}
|
|
|
|
|
|
-static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont)
|
|
|
+struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont)
|
|
|
{
|
|
|
return container_of(cgroup_subsys_state(cont,
|
|
|
mem_cgroup_subsys_id), struct mem_cgroup,
|
|
@@ -4732,14 +4748,34 @@ static int register_kmem_files(struct cgroup *cont, struct cgroup_subsys *ss)
|
|
|
|
|
|
ret = cgroup_add_files(cont, ss, kmem_cgroup_files,
|
|
|
ARRAY_SIZE(kmem_cgroup_files));
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Part of this would be better living in a separate allocation
|
|
|
+ * function, leaving us with just the cgroup tree population work.
|
|
|
+ * We, however, depend on state such as network's proto_list that
|
|
|
+ * is only initialized after cgroup creation. I found the less
|
|
|
+ * cumbersome way to deal with it to defer it all to populate time
|
|
|
+ */
|
|
|
+ if (!ret)
|
|
|
+ ret = mem_cgroup_sockets_init(cont, ss);
|
|
|
return ret;
|
|
|
};
|
|
|
|
|
|
+static void kmem_cgroup_destroy(struct cgroup_subsys *ss,
|
|
|
+ struct cgroup *cont)
|
|
|
+{
|
|
|
+ mem_cgroup_sockets_destroy(cont, ss);
|
|
|
+}
|
|
|
#else
|
|
|
static int register_kmem_files(struct cgroup *cont, struct cgroup_subsys *ss)
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+static void kmem_cgroup_destroy(struct cgroup_subsys *ss,
|
|
|
+ struct cgroup *cont)
|
|
|
+{
|
|
|
+}
|
|
|
#endif
|
|
|
|
|
|
static struct cftype mem_cgroup_files[] = {
|
|
@@ -5098,6 +5134,8 @@ static void mem_cgroup_destroy(struct cgroup_subsys *ss,
|
|
|
{
|
|
|
struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
|
|
|
|
|
|
+ kmem_cgroup_destroy(ss, cont);
|
|
|
+
|
|
|
mem_cgroup_put(memcg);
|
|
|
}
|
|
|
|