aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-22 20:40:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-22 20:40:19 -0400
commit88d6ae8dc33af12fe1c7941b1fae2767374046fd (patch)
tree8f17415c0722b0a4d7511ac170cfb4e3802e1ad2 /mm
parentf5c101892fbd3d2f6d2729bc7eb7b3f6c31dbddd (diff)
parent0d4dde1ac9a5af74ac76c6ab90557d1ae7b8f5d8 (diff)
Merge branch 'for-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup updates from Tejun Heo: "cgroup file type addition / removal is updated so that file types are added and removed instead of individual files so that dynamic file type addition / removal can be implemented by cgroup and used by controllers. blkio controller changes which will come through block tree are dependent on this. Other changes include res_counter cleanup and disallowing kthread / PF_THREAD_BOUND threads to be attached to non-root cgroups. There's a reported bug with the file type addition / removal handling which can lead to oops on cgroup umount. The issue is being looked into. It shouldn't cause problems for most setups and isn't a security concern." Fix up trivial conflict in Documentation/feature-removal-schedule.txt * 'for-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: (21 commits) res_counter: Account max_usage when calling res_counter_charge_nofail() res_counter: Merge res_counter_charge and res_counter_charge_nofail cgroups: disallow attaching kthreadd or PF_THREAD_BOUND threads cgroup: remove cgroup_subsys->populate() cgroup: get rid of populate for memcg cgroup: pass struct mem_cgroup instead of struct cgroup to socket memcg cgroup: make css->refcnt clearing on cgroup removal optional cgroup: use negative bias on css->refcnt to block css_tryget() cgroup: implement cgroup_rm_cftypes() cgroup: introduce struct cfent cgroup: relocate __d_cgrp() and __d_cft() cgroup: remove cgroup_add_file[s]() cgroup: convert memcg controller to the new cftype interface memcg: always create memsw files if CONFIG_CGROUP_MEM_RES_CTLR_SWAP cgroup: convert all non-memcg controllers to the new cftype interface cgroup: relocate cftype and cgroup_subsys definitions in controllers cgroup: merge cft_release_agent cftype array into the base files array cgroup: implement cgroup_add_cftypes() and friends cgroup: build list of all cgroups under a given cgroupfs_root cgroup: move cgroup_clear_directory() call out of cgroup_populate_dir() ...
Diffstat (limited to 'mm')
-rw-r--r--mm/memcontrol.c115
1 files changed, 52 insertions, 63 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 7685d4a0b3ce..f342778a0c0a 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3873,14 +3873,21 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
3873 return val << PAGE_SHIFT; 3873 return val << PAGE_SHIFT;
3874} 3874}
3875 3875
3876static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) 3876static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
3877 struct file *file, char __user *buf,
3878 size_t nbytes, loff_t *ppos)
3877{ 3879{
3878 struct mem_cgroup *memcg = mem_cgroup_from_cont(cont); 3880 struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
3881 char str[64];
3879 u64 val; 3882 u64 val;
3880 int type, name; 3883 int type, name, len;
3881 3884
3882 type = MEMFILE_TYPE(cft->private); 3885 type = MEMFILE_TYPE(cft->private);
3883 name = MEMFILE_ATTR(cft->private); 3886 name = MEMFILE_ATTR(cft->private);
3887
3888 if (!do_swap_account && type == _MEMSWAP)
3889 return -EOPNOTSUPP;
3890
3884 switch (type) { 3891 switch (type) {
3885 case _MEM: 3892 case _MEM:
3886 if (name == RES_USAGE) 3893 if (name == RES_USAGE)
@@ -3897,7 +3904,9 @@ static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
3897 default: 3904 default:
3898 BUG(); 3905 BUG();
3899 } 3906 }
3900 return val; 3907
3908 len = scnprintf(str, sizeof(str), "%llu\n", (unsigned long long)val);
3909 return simple_read_from_buffer(buf, nbytes, ppos, str, len);
3901} 3910}
3902/* 3911/*
3903 * The user of this function is... 3912 * The user of this function is...
@@ -3913,6 +3922,10 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
3913 3922
3914 type = MEMFILE_TYPE(cft->private); 3923 type = MEMFILE_TYPE(cft->private);
3915 name = MEMFILE_ATTR(cft->private); 3924 name = MEMFILE_ATTR(cft->private);
3925
3926 if (!do_swap_account && type == _MEMSWAP)
3927 return -EOPNOTSUPP;
3928
3916 switch (name) { 3929 switch (name) {
3917 case RES_LIMIT: 3930 case RES_LIMIT:
3918 if (mem_cgroup_is_root(memcg)) { /* Can't set limit on root */ 3931 if (mem_cgroup_is_root(memcg)) { /* Can't set limit on root */
@@ -3978,12 +3991,15 @@ out:
3978 3991
3979static int mem_cgroup_reset(struct cgroup *cont, unsigned int event) 3992static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
3980{ 3993{
3981 struct mem_cgroup *memcg; 3994 struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
3982 int type, name; 3995 int type, name;
3983 3996
3984 memcg = mem_cgroup_from_cont(cont);
3985 type = MEMFILE_TYPE(event); 3997 type = MEMFILE_TYPE(event);
3986 name = MEMFILE_ATTR(event); 3998 name = MEMFILE_ATTR(event);
3999
4000 if (!do_swap_account && type == _MEMSWAP)
4001 return -EOPNOTSUPP;
4002
3987 switch (name) { 4003 switch (name) {
3988 case RES_MAX_USAGE: 4004 case RES_MAX_USAGE:
3989 if (type == _MEM) 4005 if (type == _MEM)
@@ -4624,29 +4640,22 @@ static int mem_control_numa_stat_open(struct inode *unused, struct file *file)
4624#endif /* CONFIG_NUMA */ 4640#endif /* CONFIG_NUMA */
4625 4641
4626#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM 4642#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
4627static int register_kmem_files(struct cgroup *cont, struct cgroup_subsys *ss) 4643static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
4628{ 4644{
4629 /* 4645 return mem_cgroup_sockets_init(memcg, ss);
4630 * Part of this would be better living in a separate allocation
4631 * function, leaving us with just the cgroup tree population work.
4632 * We, however, depend on state such as network's proto_list that
4633 * is only initialized after cgroup creation. I found the less
4634 * cumbersome way to deal with it to defer it all to populate time
4635 */
4636 return mem_cgroup_sockets_init(cont, ss);
4637}; 4646};
4638 4647
4639static void kmem_cgroup_destroy(struct cgroup *cont) 4648static void kmem_cgroup_destroy(struct mem_cgroup *memcg)
4640{ 4649{
4641 mem_cgroup_sockets_destroy(cont); 4650 mem_cgroup_sockets_destroy(memcg);
4642} 4651}
4643#else 4652#else
4644static int register_kmem_files(struct cgroup *cont, struct cgroup_subsys *ss) 4653static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
4645{ 4654{
4646 return 0; 4655 return 0;
4647} 4656}
4648 4657
4649static void kmem_cgroup_destroy(struct cgroup *cont) 4658static void kmem_cgroup_destroy(struct mem_cgroup *memcg)
4650{ 4659{
4651} 4660}
4652#endif 4661#endif
@@ -4655,7 +4664,7 @@ static struct cftype mem_cgroup_files[] = {
4655 { 4664 {
4656 .name = "usage_in_bytes", 4665 .name = "usage_in_bytes",
4657 .private = MEMFILE_PRIVATE(_MEM, RES_USAGE), 4666 .private = MEMFILE_PRIVATE(_MEM, RES_USAGE),
4658 .read_u64 = mem_cgroup_read, 4667 .read = mem_cgroup_read,
4659 .register_event = mem_cgroup_usage_register_event, 4668 .register_event = mem_cgroup_usage_register_event,
4660 .unregister_event = mem_cgroup_usage_unregister_event, 4669 .unregister_event = mem_cgroup_usage_unregister_event,
4661 }, 4670 },
@@ -4663,25 +4672,25 @@ static struct cftype mem_cgroup_files[] = {
4663 .name = "max_usage_in_bytes", 4672 .name = "max_usage_in_bytes",
4664 .private = MEMFILE_PRIVATE(_MEM, RES_MAX_USAGE), 4673 .private = MEMFILE_PRIVATE(_MEM, RES_MAX_USAGE),
4665 .trigger = mem_cgroup_reset, 4674 .trigger = mem_cgroup_reset,
4666 .read_u64 = mem_cgroup_read, 4675 .read = mem_cgroup_read,
4667 }, 4676 },
4668 { 4677 {
4669 .name = "limit_in_bytes", 4678 .name = "limit_in_bytes",
4670 .private = MEMFILE_PRIVATE(_MEM, RES_LIMIT), 4679 .private = MEMFILE_PRIVATE(_MEM, RES_LIMIT),
4671 .write_string = mem_cgroup_write, 4680 .write_string = mem_cgroup_write,
4672 .read_u64 = mem_cgroup_read, 4681 .read = mem_cgroup_read,
4673 }, 4682 },
4674 { 4683 {
4675 .name = "soft_limit_in_bytes", 4684 .name = "soft_limit_in_bytes",
4676 .private = MEMFILE_PRIVATE(_MEM, RES_SOFT_LIMIT), 4685 .private = MEMFILE_PRIVATE(_MEM, RES_SOFT_LIMIT),
4677 .write_string = mem_cgroup_write, 4686 .write_string = mem_cgroup_write,
4678 .read_u64 = mem_cgroup_read, 4687 .read = mem_cgroup_read,
4679 }, 4688 },
4680 { 4689 {
4681 .name = "failcnt", 4690 .name = "failcnt",
4682 .private = MEMFILE_PRIVATE(_MEM, RES_FAILCNT), 4691 .private = MEMFILE_PRIVATE(_MEM, RES_FAILCNT),
4683 .trigger = mem_cgroup_reset, 4692 .trigger = mem_cgroup_reset,
4684 .read_u64 = mem_cgroup_read, 4693 .read = mem_cgroup_read,
4685 }, 4694 },
4686 { 4695 {
4687 .name = "stat", 4696 .name = "stat",
@@ -4721,14 +4730,11 @@ static struct cftype mem_cgroup_files[] = {
4721 .mode = S_IRUGO, 4730 .mode = S_IRUGO,
4722 }, 4731 },
4723#endif 4732#endif
4724};
4725
4726#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP 4733#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
4727static struct cftype memsw_cgroup_files[] = {
4728 { 4734 {
4729 .name = "memsw.usage_in_bytes", 4735 .name = "memsw.usage_in_bytes",
4730 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE), 4736 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE),
4731 .read_u64 = mem_cgroup_read, 4737 .read = mem_cgroup_read,
4732 .register_event = mem_cgroup_usage_register_event, 4738 .register_event = mem_cgroup_usage_register_event,
4733 .unregister_event = mem_cgroup_usage_unregister_event, 4739 .unregister_event = mem_cgroup_usage_unregister_event,
4734 }, 4740 },
@@ -4736,35 +4742,23 @@ static struct cftype memsw_cgroup_files[] = {
4736 .name = "memsw.max_usage_in_bytes", 4742 .name = "memsw.max_usage_in_bytes",
4737 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_MAX_USAGE), 4743 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_MAX_USAGE),
4738 .trigger = mem_cgroup_reset, 4744 .trigger = mem_cgroup_reset,
4739 .read_u64 = mem_cgroup_read, 4745 .read = mem_cgroup_read,
4740 }, 4746 },
4741 { 4747 {
4742 .name = "memsw.limit_in_bytes", 4748 .name = "memsw.limit_in_bytes",
4743 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_LIMIT), 4749 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_LIMIT),
4744 .write_string = mem_cgroup_write, 4750 .write_string = mem_cgroup_write,
4745 .read_u64 = mem_cgroup_read, 4751 .read = mem_cgroup_read,
4746 }, 4752 },
4747 { 4753 {
4748 .name = "memsw.failcnt", 4754 .name = "memsw.failcnt",
4749 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_FAILCNT), 4755 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_FAILCNT),
4750 .trigger = mem_cgroup_reset, 4756 .trigger = mem_cgroup_reset,
4751 .read_u64 = mem_cgroup_read, 4757 .read = mem_cgroup_read,
4752 }, 4758 },
4753};
4754
4755static int register_memsw_files(struct cgroup *cont, struct cgroup_subsys *ss)
4756{
4757 if (!do_swap_account)
4758 return 0;
4759 return cgroup_add_files(cont, ss, memsw_cgroup_files,
4760 ARRAY_SIZE(memsw_cgroup_files));
4761};
4762#else
4763static int register_memsw_files(struct cgroup *cont, struct cgroup_subsys *ss)
4764{
4765 return 0;
4766}
4767#endif 4759#endif
4760 { }, /* terminate */
4761};
4768 4762
4769static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node) 4763static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
4770{ 4764{
@@ -5016,6 +5010,17 @@ mem_cgroup_create(struct cgroup *cont)
5016 memcg->move_charge_at_immigrate = 0; 5010 memcg->move_charge_at_immigrate = 0;
5017 mutex_init(&memcg->thresholds_lock); 5011 mutex_init(&memcg->thresholds_lock);
5018 spin_lock_init(&memcg->move_lock); 5012 spin_lock_init(&memcg->move_lock);
5013
5014 error = memcg_init_kmem(memcg, &mem_cgroup_subsys);
5015 if (error) {
5016 /*
5017 * We call put now because our (and parent's) refcnts
5018 * are already in place. mem_cgroup_put() will internally
5019 * call __mem_cgroup_free, so return directly
5020 */
5021 mem_cgroup_put(memcg);
5022 return ERR_PTR(error);
5023 }
5019 return &memcg->css; 5024 return &memcg->css;
5020free_out: 5025free_out:
5021 __mem_cgroup_free(memcg); 5026 __mem_cgroup_free(memcg);
@@ -5033,28 +5038,11 @@ static void mem_cgroup_destroy(struct cgroup *cont)
5033{ 5038{
5034 struct mem_cgroup *memcg = mem_cgroup_from_cont(cont); 5039 struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
5035 5040
5036 kmem_cgroup_destroy(cont); 5041 kmem_cgroup_destroy(memcg);
5037 5042
5038 mem_cgroup_put(memcg); 5043 mem_cgroup_put(memcg);
5039} 5044}
5040 5045
5041static int mem_cgroup_populate(struct cgroup_subsys *ss,
5042 struct cgroup *cont)
5043{
5044 int ret;
5045
5046 ret = cgroup_add_files(cont, ss, mem_cgroup_files,
5047 ARRAY_SIZE(mem_cgroup_files));
5048
5049 if (!ret)
5050 ret = register_memsw_files(cont, ss);
5051
5052 if (!ret)
5053 ret = register_kmem_files(cont, ss);
5054
5055 return ret;
5056}
5057
5058#ifdef CONFIG_MMU 5046#ifdef CONFIG_MMU
5059/* Handlers for move charge at task migration. */ 5047/* Handlers for move charge at task migration. */
5060#define PRECHARGE_COUNT_AT_ONCE 256 5048#define PRECHARGE_COUNT_AT_ONCE 256
@@ -5638,12 +5626,13 @@ struct cgroup_subsys mem_cgroup_subsys = {
5638 .create = mem_cgroup_create, 5626 .create = mem_cgroup_create,
5639 .pre_destroy = mem_cgroup_pre_destroy, 5627 .pre_destroy = mem_cgroup_pre_destroy,
5640 .destroy = mem_cgroup_destroy, 5628 .destroy = mem_cgroup_destroy,
5641 .populate = mem_cgroup_populate,
5642 .can_attach = mem_cgroup_can_attach, 5629 .can_attach = mem_cgroup_can_attach,
5643 .cancel_attach = mem_cgroup_cancel_attach, 5630 .cancel_attach = mem_cgroup_cancel_attach,
5644 .attach = mem_cgroup_move_task, 5631 .attach = mem_cgroup_move_task,
5632 .base_cftypes = mem_cgroup_files,
5645 .early_init = 0, 5633 .early_init = 0,
5646 .use_id = 1, 5634 .use_id = 1,
5635 .__DEPRECATED_clear_css_refs = true,
5647}; 5636};
5648 5637
5649#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP 5638#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP