aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/memcontrol.h6
-rw-r--r--mm/memcontrol.c91
2 files changed, 18 insertions, 79 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index d87090eb14c0..9815951ec995 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -38,6 +38,7 @@ extern struct page_cgroup *page_get_page_cgroup(struct page *page);
38extern int mem_cgroup_charge(struct page *page, struct mm_struct *mm, 38extern int mem_cgroup_charge(struct page *page, struct mm_struct *mm,
39 gfp_t gfp_mask); 39 gfp_t gfp_mask);
40extern void mem_cgroup_uncharge(struct page_cgroup *pc); 40extern void mem_cgroup_uncharge(struct page_cgroup *pc);
41extern void mem_cgroup_uncharge_page(struct page *page);
41extern void mem_cgroup_move_lists(struct page_cgroup *pc, bool active); 42extern void mem_cgroup_move_lists(struct page_cgroup *pc, bool active);
42extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, 43extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
43 struct list_head *dst, 44 struct list_head *dst,
@@ -55,11 +56,6 @@ static inline struct mem_cgroup *mm_cgroup(const struct mm_struct *mm)
55 return rcu_dereference(mm->mem_cgroup); 56 return rcu_dereference(mm->mem_cgroup);
56} 57}
57 58
58static inline void mem_cgroup_uncharge_page(struct page *page)
59{
60 mem_cgroup_uncharge(page_get_page_cgroup(page));
61}
62
63extern int mem_cgroup_prepare_migration(struct page *page); 59extern int mem_cgroup_prepare_migration(struct page *page);
64extern void mem_cgroup_end_migration(struct page *page); 60extern void mem_cgroup_end_migration(struct page *page);
65extern void mem_cgroup_page_migration(struct page *page, struct page *newpage); 61extern void mem_cgroup_page_migration(struct page *page, struct page *newpage);
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 315dee180129..5c2c702af617 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -131,7 +131,6 @@ struct mem_cgroup {
131 */ 131 */
132 struct mem_cgroup_lru_info info; 132 struct mem_cgroup_lru_info info;
133 133
134 unsigned long control_type; /* control RSS or RSS+Pagecache */
135 int prev_priority; /* for recording reclaim priority */ 134 int prev_priority; /* for recording reclaim priority */
136 /* 135 /*
137 * statistics. 136 * statistics.
@@ -709,24 +708,17 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
709 gfp_t gfp_mask) 708 gfp_t gfp_mask)
710{ 709{
711 int ret = 0; 710 int ret = 0;
712 struct mem_cgroup *mem;
713 if (!mm) 711 if (!mm)
714 mm = &init_mm; 712 mm = &init_mm;
715 713
716 rcu_read_lock(); 714 ret = mem_cgroup_charge_common(page, mm, gfp_mask,
717 mem = rcu_dereference(mm->mem_cgroup);
718 css_get(&mem->css);
719 rcu_read_unlock();
720 if (mem->control_type == MEM_CGROUP_TYPE_ALL)
721 ret = mem_cgroup_charge_common(page, mm, gfp_mask,
722 MEM_CGROUP_CHARGE_TYPE_CACHE); 715 MEM_CGROUP_CHARGE_TYPE_CACHE);
723 css_put(&mem->css);
724 return ret; 716 return ret;
725} 717}
726 718
727/* 719/*
728 * Uncharging is always a welcome operation, we never complain, simply 720 * Uncharging is always a welcome operation, we never complain, simply
729 * uncharge. 721 * uncharge. This routine should be called with lock_page_cgroup held
730 */ 722 */
731void mem_cgroup_uncharge(struct page_cgroup *pc) 723void mem_cgroup_uncharge(struct page_cgroup *pc)
732{ 724{
@@ -736,8 +728,7 @@ void mem_cgroup_uncharge(struct page_cgroup *pc)
736 unsigned long flags; 728 unsigned long flags;
737 729
738 /* 730 /*
739 * This can handle cases when a page is not charged at all and we 731 * Check if our page_cgroup is valid
740 * are switching between handling the control_type.
741 */ 732 */
742 if (!pc) 733 if (!pc)
743 return; 734 return;
@@ -749,6 +740,7 @@ void mem_cgroup_uncharge(struct page_cgroup *pc)
749 * get page->cgroup and clear it under lock. 740 * get page->cgroup and clear it under lock.
750 * force_empty can drop page->cgroup without checking refcnt. 741 * force_empty can drop page->cgroup without checking refcnt.
751 */ 742 */
743 unlock_page_cgroup(page);
752 if (clear_page_cgroup(page, pc) == pc) { 744 if (clear_page_cgroup(page, pc) == pc) {
753 mem = pc->mem_cgroup; 745 mem = pc->mem_cgroup;
754 css_put(&mem->css); 746 css_put(&mem->css);
@@ -758,9 +750,17 @@ void mem_cgroup_uncharge(struct page_cgroup *pc)
758 spin_unlock_irqrestore(&mz->lru_lock, flags); 750 spin_unlock_irqrestore(&mz->lru_lock, flags);
759 kfree(pc); 751 kfree(pc);
760 } 752 }
753 lock_page_cgroup(page);
761 } 754 }
762} 755}
763 756
757void mem_cgroup_uncharge_page(struct page *page)
758{
759 lock_page_cgroup(page);
760 mem_cgroup_uncharge(page_get_page_cgroup(page));
761 unlock_page_cgroup(page);
762}
763
764/* 764/*
765 * Returns non-zero if a page (under migration) has valid page_cgroup member. 765 * Returns non-zero if a page (under migration) has valid page_cgroup member.
766 * Refcnt of page_cgroup is incremented. 766 * Refcnt of page_cgroup is incremented.
@@ -780,8 +780,12 @@ int mem_cgroup_prepare_migration(struct page *page)
780 780
781void mem_cgroup_end_migration(struct page *page) 781void mem_cgroup_end_migration(struct page *page)
782{ 782{
783 struct page_cgroup *pc = page_get_page_cgroup(page); 783 struct page_cgroup *pc;
784
785 lock_page_cgroup(page);
786 pc = page_get_page_cgroup(page);
784 mem_cgroup_uncharge(pc); 787 mem_cgroup_uncharge(pc);
788 unlock_page_cgroup(page);
785} 789}
786/* 790/*
787 * We know both *page* and *newpage* are now not-on-LRU and Pg_locked. 791 * We know both *page* and *newpage* are now not-on-LRU and Pg_locked.
@@ -936,61 +940,6 @@ static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
936 mem_cgroup_write_strategy); 940 mem_cgroup_write_strategy);
937} 941}
938 942
939static ssize_t mem_control_type_write(struct cgroup *cont,
940 struct cftype *cft, struct file *file,
941 const char __user *userbuf,
942 size_t nbytes, loff_t *pos)
943{
944 int ret;
945 char *buf, *end;
946 unsigned long tmp;
947 struct mem_cgroup *mem;
948
949 mem = mem_cgroup_from_cont(cont);
950 buf = kmalloc(nbytes + 1, GFP_KERNEL);
951 ret = -ENOMEM;
952 if (buf == NULL)
953 goto out;
954
955 buf[nbytes] = 0;
956 ret = -EFAULT;
957 if (copy_from_user(buf, userbuf, nbytes))
958 goto out_free;
959
960 ret = -EINVAL;
961 tmp = simple_strtoul(buf, &end, 10);
962 if (*end != '\0')
963 goto out_free;
964
965 if (tmp <= MEM_CGROUP_TYPE_UNSPEC || tmp >= MEM_CGROUP_TYPE_MAX)
966 goto out_free;
967
968 mem->control_type = tmp;
969 ret = nbytes;
970out_free:
971 kfree(buf);
972out:
973 return ret;
974}
975
976static ssize_t mem_control_type_read(struct cgroup *cont,
977 struct cftype *cft,
978 struct file *file, char __user *userbuf,
979 size_t nbytes, loff_t *ppos)
980{
981 unsigned long val;
982 char buf[64], *s;
983 struct mem_cgroup *mem;
984
985 mem = mem_cgroup_from_cont(cont);
986 s = buf;
987 val = mem->control_type;
988 s += sprintf(s, "%lu\n", val);
989 return simple_read_from_buffer((void __user *)userbuf, nbytes,
990 ppos, buf, s - buf);
991}
992
993
994static ssize_t mem_force_empty_write(struct cgroup *cont, 943static ssize_t mem_force_empty_write(struct cgroup *cont,
995 struct cftype *cft, struct file *file, 944 struct cftype *cft, struct file *file,
996 const char __user *userbuf, 945 const char __user *userbuf,
@@ -1089,11 +1038,6 @@ static struct cftype mem_cgroup_files[] = {
1089 .read = mem_cgroup_read, 1038 .read = mem_cgroup_read,
1090 }, 1039 },
1091 { 1040 {
1092 .name = "control_type",
1093 .write = mem_control_type_write,
1094 .read = mem_control_type_read,
1095 },
1096 {
1097 .name = "force_empty", 1041 .name = "force_empty",
1098 .write = mem_force_empty_write, 1042 .write = mem_force_empty_write,
1099 .read = mem_force_empty_read, 1043 .read = mem_force_empty_read,
@@ -1161,7 +1105,6 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
1161 1105
1162 res_counter_init(&mem->res); 1106 res_counter_init(&mem->res);
1163 1107
1164 mem->control_type = MEM_CGROUP_TYPE_ALL;
1165 memset(&mem->info, 0, sizeof(mem->info)); 1108 memset(&mem->info, 0, sizeof(mem->info));
1166 1109
1167 for_each_node_state(node, N_POSSIBLE) 1110 for_each_node_state(node, N_POSSIBLE)