From mboxrd@z Thu Jan 1 00:00:00 1970 From: Greg Thelen Subject: [PATCH v8 07/12] memcg: add cgroupfs interface to memcg dirty limits Date: Fri, 3 Jun 2011 09:12:13 -0700 Message-ID: <1307117538-14317-8-git-send-email-gthelen@google.com> References: <1307117538-14317-1-git-send-email-gthelen@google.com> Return-path: In-Reply-To: <1307117538-14317-1-git-send-email-gthelen@google.com> Sender: owner-linux-mm@kvack.org To: Andrew Morton Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, containers@lists.osdl.org, linux-fsdevel@vger.kernel.org, Andrea Righi , Balbir Singh , KAMEZAWA Hiroyuki , Daisuke Nishimura , Minchan Kim , Johannes Weiner , Ciju Rajan K , David Rientjes , Wu Fengguang , Vivek Goyal , Dave Chinner , Greg Thelen List-Id: containers.vger.kernel.org Add cgroupfs interface to memcg dirty page limits: Direct write-out is controlled with: - memory.dirty_ratio - memory.dirty_limit_in_bytes Background write-out is controlled with: - memory.dirty_background_ratio - memory.dirty_background_limit_bytes Other memcg cgroupfs files support 'M', 'm', 'k', 'K', 'g' and 'G' suffixes for byte counts. This patch provides the same functionality for memory.dirty_limit_in_bytes and memory.dirty_background_limit_bytes. Signed-off-by: Andrea Righi Signed-off-by: Balbir Singh Signed-off-by: Greg Thelen Acked-by: KAMEZAWA Hiroyuki --- mm/memcontrol.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 114 insertions(+), 0 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 91e0692..72fed89 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -126,6 +126,13 @@ enum mem_cgroup_events_target { #define THRESHOLDS_EVENTS_TARGET (128) #define SOFTLIMIT_EVENTS_TARGET (1024) +enum { + MEM_CGROUP_DIRTY_RATIO, + MEM_CGROUP_DIRTY_LIMIT_IN_BYTES, + MEM_CGROUP_DIRTY_BACKGROUND_RATIO, + MEM_CGROUP_DIRTY_BACKGROUND_LIMIT_IN_BYTES, +}; + struct mem_cgroup_stat_cpu { long count[MEM_CGROUP_STAT_NSTATS]; unsigned long events[MEM_CGROUP_EVENTS_NSTATS]; @@ -4638,6 +4645,89 @@ static int mem_cgroup_oom_control_write(struct cgroup *cgrp, return 0; } +static u64 mem_cgroup_dirty_read(struct cgroup *cgrp, struct cftype *cft) +{ + struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp); + bool use_sys = !mem_cgroup_has_dirty_limit(mem); + + switch (cft->private) { + case MEM_CGROUP_DIRTY_RATIO: + return use_sys ? vm_dirty_ratio : mem->dirty_param.dirty_ratio; + case MEM_CGROUP_DIRTY_LIMIT_IN_BYTES: + return use_sys ? vm_dirty_bytes : mem->dirty_param.dirty_bytes; + case MEM_CGROUP_DIRTY_BACKGROUND_RATIO: + return use_sys ? dirty_background_ratio : + mem->dirty_param.dirty_background_ratio; + case MEM_CGROUP_DIRTY_BACKGROUND_LIMIT_IN_BYTES: + return use_sys ? dirty_background_bytes : + mem->dirty_param.dirty_background_bytes; + default: + BUG(); + } +} + +static int +mem_cgroup_dirty_write_string(struct cgroup *cgrp, struct cftype *cft, + const char *buffer) +{ + struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); + int type = cft->private; + int ret = -EINVAL; + unsigned long long val; + + if (!mem_cgroup_has_dirty_limit(memcg)) + return ret; + + switch (type) { + case MEM_CGROUP_DIRTY_LIMIT_IN_BYTES: + /* This function does all necessary parse...reuse it */ + ret = res_counter_memparse_write_strategy(buffer, &val); + if (ret) + break; + memcg->dirty_param.dirty_bytes = val; + memcg->dirty_param.dirty_ratio = 0; + break; + case MEM_CGROUP_DIRTY_BACKGROUND_LIMIT_IN_BYTES: + ret = res_counter_memparse_write_strategy(buffer, &val); + if (ret) + break; + memcg->dirty_param.dirty_background_bytes = val; + memcg->dirty_param.dirty_background_ratio = 0; + break; + default: + BUG(); + break; + } + return ret; +} + +static int +mem_cgroup_dirty_write(struct cgroup *cgrp, struct cftype *cft, u64 val) +{ + struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); + int type = cft->private; + + if (!mem_cgroup_has_dirty_limit(memcg)) + return -EINVAL; + if ((type == MEM_CGROUP_DIRTY_RATIO || + type == MEM_CGROUP_DIRTY_BACKGROUND_RATIO) && val > 100) + return -EINVAL; + switch (type) { + case MEM_CGROUP_DIRTY_RATIO: + memcg->dirty_param.dirty_ratio = val; + memcg->dirty_param.dirty_bytes = 0; + break; + case MEM_CGROUP_DIRTY_BACKGROUND_RATIO: + memcg->dirty_param.dirty_background_ratio = val; + memcg->dirty_param.dirty_background_bytes = 0; + break; + default: + BUG(); + break; + } + return 0; +} + static struct cftype mem_cgroup_files[] = { { .name = "usage_in_bytes", @@ -4701,6 +4791,30 @@ static struct cftype mem_cgroup_files[] = { .unregister_event = mem_cgroup_oom_unregister_event, .private = MEMFILE_PRIVATE(_OOM_TYPE, OOM_CONTROL), }, + { + .name = "dirty_ratio", + .read_u64 = mem_cgroup_dirty_read, + .write_u64 = mem_cgroup_dirty_write, + .private = MEM_CGROUP_DIRTY_RATIO, + }, + { + .name = "dirty_limit_in_bytes", + .read_u64 = mem_cgroup_dirty_read, + .write_string = mem_cgroup_dirty_write_string, + .private = MEM_CGROUP_DIRTY_LIMIT_IN_BYTES, + }, + { + .name = "dirty_background_ratio", + .read_u64 = mem_cgroup_dirty_read, + .write_u64 = mem_cgroup_dirty_write, + .private = MEM_CGROUP_DIRTY_BACKGROUND_RATIO, + }, + { + .name = "dirty_background_limit_in_bytes", + .read_u64 = mem_cgroup_dirty_read, + .write_string = mem_cgroup_dirty_write_string, + .private = MEM_CGROUP_DIRTY_BACKGROUND_LIMIT_IN_BYTES, + }, }; #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP -- 1.7.3.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ Don't email: email@kvack.org From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754363Ab1FCQOx (ORCPT ); Fri, 3 Jun 2011 12:14:53 -0400 Received: from smtp-out.google.com ([216.239.44.51]:42058 "EHLO smtp-out.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753891Ab1FCQOu (ORCPT ); Fri, 3 Jun 2011 12:14:50 -0400 DomainKey-Signature: a=rsa-sha1; s=beta; d=google.com; c=nofws; q=dns; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=Xp3XPPD0zmqwIAD2iTT2Ev0os/7Ni4dLyQXZTIdsV0q94vyNU0uSTiv6ezoeVWLYf YtV4SgRrdjg3KK87VHyQA== From: Greg Thelen To: Andrew Morton Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, containers@lists.osdl.org, linux-fsdevel@vger.kernel.org, Andrea Righi , Balbir Singh , KAMEZAWA Hiroyuki , Daisuke Nishimura , Minchan Kim , Johannes Weiner , Ciju Rajan K , David Rientjes , Wu Fengguang , Vivek Goyal , Dave Chinner , Greg Thelen Subject: [PATCH v8 07/12] memcg: add cgroupfs interface to memcg dirty limits Date: Fri, 3 Jun 2011 09:12:13 -0700 Message-Id: <1307117538-14317-8-git-send-email-gthelen@google.com> X-Mailer: git-send-email 1.7.3.1 In-Reply-To: <1307117538-14317-1-git-send-email-gthelen@google.com> References: <1307117538-14317-1-git-send-email-gthelen@google.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add cgroupfs interface to memcg dirty page limits: Direct write-out is controlled with: - memory.dirty_ratio - memory.dirty_limit_in_bytes Background write-out is controlled with: - memory.dirty_background_ratio - memory.dirty_background_limit_bytes Other memcg cgroupfs files support 'M', 'm', 'k', 'K', 'g' and 'G' suffixes for byte counts. This patch provides the same functionality for memory.dirty_limit_in_bytes and memory.dirty_background_limit_bytes. Signed-off-by: Andrea Righi Signed-off-by: Balbir Singh Signed-off-by: Greg Thelen Acked-by: KAMEZAWA Hiroyuki --- mm/memcontrol.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 114 insertions(+), 0 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 91e0692..72fed89 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -126,6 +126,13 @@ enum mem_cgroup_events_target { #define THRESHOLDS_EVENTS_TARGET (128) #define SOFTLIMIT_EVENTS_TARGET (1024) +enum { + MEM_CGROUP_DIRTY_RATIO, + MEM_CGROUP_DIRTY_LIMIT_IN_BYTES, + MEM_CGROUP_DIRTY_BACKGROUND_RATIO, + MEM_CGROUP_DIRTY_BACKGROUND_LIMIT_IN_BYTES, +}; + struct mem_cgroup_stat_cpu { long count[MEM_CGROUP_STAT_NSTATS]; unsigned long events[MEM_CGROUP_EVENTS_NSTATS]; @@ -4638,6 +4645,89 @@ static int mem_cgroup_oom_control_write(struct cgroup *cgrp, return 0; } +static u64 mem_cgroup_dirty_read(struct cgroup *cgrp, struct cftype *cft) +{ + struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp); + bool use_sys = !mem_cgroup_has_dirty_limit(mem); + + switch (cft->private) { + case MEM_CGROUP_DIRTY_RATIO: + return use_sys ? vm_dirty_ratio : mem->dirty_param.dirty_ratio; + case MEM_CGROUP_DIRTY_LIMIT_IN_BYTES: + return use_sys ? vm_dirty_bytes : mem->dirty_param.dirty_bytes; + case MEM_CGROUP_DIRTY_BACKGROUND_RATIO: + return use_sys ? dirty_background_ratio : + mem->dirty_param.dirty_background_ratio; + case MEM_CGROUP_DIRTY_BACKGROUND_LIMIT_IN_BYTES: + return use_sys ? dirty_background_bytes : + mem->dirty_param.dirty_background_bytes; + default: + BUG(); + } +} + +static int +mem_cgroup_dirty_write_string(struct cgroup *cgrp, struct cftype *cft, + const char *buffer) +{ + struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); + int type = cft->private; + int ret = -EINVAL; + unsigned long long val; + + if (!mem_cgroup_has_dirty_limit(memcg)) + return ret; + + switch (type) { + case MEM_CGROUP_DIRTY_LIMIT_IN_BYTES: + /* This function does all necessary parse...reuse it */ + ret = res_counter_memparse_write_strategy(buffer, &val); + if (ret) + break; + memcg->dirty_param.dirty_bytes = val; + memcg->dirty_param.dirty_ratio = 0; + break; + case MEM_CGROUP_DIRTY_BACKGROUND_LIMIT_IN_BYTES: + ret = res_counter_memparse_write_strategy(buffer, &val); + if (ret) + break; + memcg->dirty_param.dirty_background_bytes = val; + memcg->dirty_param.dirty_background_ratio = 0; + break; + default: + BUG(); + break; + } + return ret; +} + +static int +mem_cgroup_dirty_write(struct cgroup *cgrp, struct cftype *cft, u64 val) +{ + struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); + int type = cft->private; + + if (!mem_cgroup_has_dirty_limit(memcg)) + return -EINVAL; + if ((type == MEM_CGROUP_DIRTY_RATIO || + type == MEM_CGROUP_DIRTY_BACKGROUND_RATIO) && val > 100) + return -EINVAL; + switch (type) { + case MEM_CGROUP_DIRTY_RATIO: + memcg->dirty_param.dirty_ratio = val; + memcg->dirty_param.dirty_bytes = 0; + break; + case MEM_CGROUP_DIRTY_BACKGROUND_RATIO: + memcg->dirty_param.dirty_background_ratio = val; + memcg->dirty_param.dirty_background_bytes = 0; + break; + default: + BUG(); + break; + } + return 0; +} + static struct cftype mem_cgroup_files[] = { { .name = "usage_in_bytes", @@ -4701,6 +4791,30 @@ static struct cftype mem_cgroup_files[] = { .unregister_event = mem_cgroup_oom_unregister_event, .private = MEMFILE_PRIVATE(_OOM_TYPE, OOM_CONTROL), }, + { + .name = "dirty_ratio", + .read_u64 = mem_cgroup_dirty_read, + .write_u64 = mem_cgroup_dirty_write, + .private = MEM_CGROUP_DIRTY_RATIO, + }, + { + .name = "dirty_limit_in_bytes", + .read_u64 = mem_cgroup_dirty_read, + .write_string = mem_cgroup_dirty_write_string, + .private = MEM_CGROUP_DIRTY_LIMIT_IN_BYTES, + }, + { + .name = "dirty_background_ratio", + .read_u64 = mem_cgroup_dirty_read, + .write_u64 = mem_cgroup_dirty_write, + .private = MEM_CGROUP_DIRTY_BACKGROUND_RATIO, + }, + { + .name = "dirty_background_limit_in_bytes", + .read_u64 = mem_cgroup_dirty_read, + .write_string = mem_cgroup_dirty_write_string, + .private = MEM_CGROUP_DIRTY_BACKGROUND_LIMIT_IN_BYTES, + }, }; #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP -- 1.7.3.1