aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/res_counter.h14
-rw-r--r--kernel/res_counter.c4
-rw-r--r--mm/memcontrol.c17
3 files changed, 35 insertions, 0 deletions
diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h
index 8cb1ecd420a..df8085acba1 100644
--- a/include/linux/res_counter.h
+++ b/include/linux/res_counter.h
@@ -25,6 +25,10 @@ struct res_counter {
*/
unsigned long long usage;
/*
+ * the maximal value of the usage from the counter creation
+ */
+ unsigned long long max_usage;
+ /*
* the limit that usage cannot exceed
*/
unsigned long long limit;
@@ -67,6 +71,7 @@ ssize_t res_counter_write(struct res_counter *counter, int member,
enum {
RES_USAGE,
+ RES_MAX_USAGE,
RES_LIMIT,
RES_FAILCNT,
};
@@ -127,4 +132,13 @@ static inline bool res_counter_check_under_limit(struct res_counter *cnt)
return ret;
}
+static inline void res_counter_reset_max(struct res_counter *cnt)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cnt->lock, flags);
+ cnt->max_usage = cnt->usage;
+ spin_unlock_irqrestore(&cnt->lock, flags);
+}
+
#endif
diff --git a/kernel/res_counter.c b/kernel/res_counter.c
index 70587657dda..d3c61b4ebef 100644
--- a/kernel/res_counter.c
+++ b/kernel/res_counter.c
@@ -28,6 +28,8 @@ int res_counter_charge_locked(struct res_counter *counter, unsigned long val)
}
counter->usage += val;
+ if (counter->usage > counter->max_usage)
+ counter->max_usage = counter->usage;
return 0;
}
@@ -66,6 +68,8 @@ res_counter_member(struct res_counter *counter, int member)
switch (member) {
case RES_USAGE:
return &counter->usage;
+ case RES_MAX_USAGE:
+ return &counter->max_usage;
case RES_LIMIT:
return &counter->limit;
case RES_FAILCNT:
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 49d80814798..350a14da652 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -855,6 +855,17 @@ static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
mem_cgroup_write_strategy);
}
+static ssize_t mem_cgroup_max_reset(struct cgroup *cont, struct cftype *cft,
+ struct file *file, const char __user *userbuf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct mem_cgroup *mem;
+
+ mem = mem_cgroup_from_cont(cont);
+ res_counter_reset_max(&mem->res);
+ return nbytes;
+}
+
static ssize_t mem_force_empty_write(struct cgroup *cont,
struct cftype *cft, struct file *file,
const char __user *userbuf,
@@ -910,6 +921,12 @@ static struct cftype mem_cgroup_files[] = {
.read_u64 = mem_cgroup_read,
},
{
+ .name = "max_usage_in_bytes",
+ .private = RES_MAX_USAGE,
+ .write = mem_cgroup_max_reset,
+ .read_u64 = mem_cgroup_read,
+ },
+ {
.name = "limit_in_bytes",
.private = RES_LIMIT,
.write = mem_cgroup_write,