]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
memcg: allow setting low_limit
authorMichal Hocko <mhocko@suse.cz>
Sat, 17 May 2014 13:19:26 +0000 (23:19 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Mon, 19 May 2014 07:35:01 +0000 (17:35 +1000)
Export memory.low_limit_in_bytes knob with the same rules as the hard
limit represented by limit_in_bytes knob (e.g.  no limit to be set for the
root cgroup).  There is no memsw alternative for low_limit_in_bytes
because the primary motivation behind this limit is to protect the working
set of the group and so considering swap doesn't make much sense.  There
is also no kmem variant exported because we do not have any easy way to
protect kernel allocations now.

Please note that the low limit might exceed the hard limit which basically
means that the group is not reclaimable if there is other reclaim target
in the hierarchy under pressure.

Signed-off-by: Michal Hocko <mhocko@suse.cz>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Greg Thelen <gthelen@google.com>
Cc: Michel Lespinasse <walken@google.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Roman Gushchin <klamm@yandex-team.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/linux/res_counter.h
kernel/res_counter.c
mm/memcontrol.c

index 408724eeec7138c9b60facc2c2b07daf15ecc184..b810855024f9b8d84f75178c8a074c507a3d6ffc 100644 (file)
@@ -93,6 +93,7 @@ enum {
        RES_LIMIT,
        RES_FAILCNT,
        RES_SOFT_LIMIT,
+       RES_LOW_LIMIT,
 };
 
 /*
@@ -247,4 +248,16 @@ res_counter_set_soft_limit(struct res_counter *cnt,
        return 0;
 }
 
+static inline int
+res_counter_set_low_limit(struct res_counter *cnt,
+                               unsigned long long low_limit)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cnt->lock, flags);
+       cnt->low_limit = low_limit;
+       spin_unlock_irqrestore(&cnt->lock, flags);
+       return 0;
+}
+
 #endif
index e791130f85a7ace7bbfc4d412151b912d6b87d49..85ea94305015d30a11d4cec352f7d3d73611c15d 100644 (file)
@@ -136,6 +136,8 @@ res_counter_member(struct res_counter *counter, int member)
                return &counter->failcnt;
        case RES_SOFT_LIMIT:
                return &counter->soft_limit;
+       case RES_LOW_LIMIT:
+               return &counter->low_limit;
        };
 
        BUG();
index 96fe3a0dcba458a6ea36d2e4e9b6f8cb4a474b6a..aca2b62e71bd495f4876c98e7e4d982f3ecc6d81 100644 (file)
@@ -1674,8 +1674,9 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
 
        rcu_read_unlock();
 
-       pr_info("memory: usage %llukB, limit %llukB, failcnt %llu\n",
+       pr_info("memory: usage %llukB, low_limit %llukB limit %llukB, failcnt %llu\n",
                res_counter_read_u64(&memcg->res, RES_USAGE) >> 10,
+               res_counter_read_u64(&memcg->res, RES_LOW_LIMIT) >> 10,
                res_counter_read_u64(&memcg->res, RES_LIMIT) >> 10,
                res_counter_read_u64(&memcg->res, RES_FAILCNT));
        pr_info("memory+swap: usage %llukB, limit %llukB, failcnt %llu\n",
@@ -5096,6 +5097,24 @@ static ssize_t mem_cgroup_write(struct kernfs_open_file *of,
                else
                        return -EINVAL;
                break;
+       case RES_LOW_LIMIT:
+               if (mem_cgroup_is_root(memcg)) { /* Can't set limit on root */
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = res_counter_memparse_write_strategy(buf, &val);
+               if (ret)
+                       break;
+               if (type == _MEM) {
+                       ret = res_counter_set_low_limit(&memcg->res, val);
+                       break;
+               }
+               /*
+                * memsw low limit doesn't make any sense and kmem is not
+                * implemented yet - if ever
+                */
+               return -EINVAL;
+
        case RES_SOFT_LIMIT:
                ret = res_counter_memparse_write_strategy(buf, &val);
                if (ret)
@@ -6021,6 +6040,12 @@ static struct cftype mem_cgroup_files[] = {
                .write = mem_cgroup_write,
                .read_u64 = mem_cgroup_read_u64,
        },
+       {
+               .name = "low_limit_in_bytes",
+               .private = MEMFILE_PRIVATE(_MEM, RES_LOW_LIMIT),
+               .write = mem_cgroup_write,
+               .read_u64 = mem_cgroup_read_u64,
+       },
        {
                .name = "soft_limit_in_bytes",
                .private = MEMFILE_PRIVATE(_MEM, RES_SOFT_LIMIT),