Received: by 2002:ac0:a582:0:0:0:0:0 with SMTP id m2-v6csp1053861imm; Fri, 12 Oct 2018 10:57:29 -0700 (PDT) X-Google-Smtp-Source: ACcGV63Ud14tcWS1LJ9E+4OaEEjzRypxyysPevlA5GcVYlxBELJiZh7U+I2PqMF5iDysN+7iySrK X-Received: by 2002:a17:902:b943:: with SMTP id h3-v6mr6877665pls.5.1539367049275; Fri, 12 Oct 2018 10:57:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1539367049; cv=none; d=google.com; s=arc-20160816; b=UC8FJdBQc9aTZLQL6D2RwXNTij47KVZHLkafU1kAMfx/eYdalVwUP0qQuUrwX+PIoA VjLA7RTs0yJw44b+Mw8WULVMF6tMa/ms6dbmzXmS+9KokXGFcEsI9NIM8xaWjTOkc87n XLZZru3f4u48zBuySSUA5pxcRcCanHEi3KyelmTPxlYQvY2c43xV+mPyBCMBac4+0oDJ /i/Wq6NHZ6pN1mh/Upr/2MgD2O/WpIYVoIe5k24m3ictB6GOCWPZMSXcEEFrzPJOrPVo qzB25JBhVsWpX7e9yRvFhz3Z67wzh37cUVkT1ehZspI3+isbXf2UfJVrPcvevdhCNn0H Nc7g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=iV5VFz32MaU1tQi+waTBCEyqZTDOfcsanx0+g8kdM/4=; b=sf12qv+sU8jsdbdVQ2JZjaQ6zjFb1w3eUdH1c8cpoTYArNxRl44BZG2k4f3wuSVRG6 nOoviT4ItliMYPwqHaCjUaOCiqcSzVcWkWpHR6onKBGEHaX/J+ZhxUa3bZB/liGWNlLh iB1gQlM48G5ilyxKAsnc41kX73WYG2PtglRt8S1Xd2GrM8drmCAA80pnjeRTV2221e6i ido4GjQVi5z7YK6A/X+IzlQRcC1p8/pJ5U3lGhE4kak47B0qnc218r7j0RxrYeVD55pk dAjp/ZxqjLpQMbCBjn6IMl1RtyTPUdAqF06SG4rLSHsuE25ZTnRJYmu2OiNa0vayX9mQ 7qRQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b7-v6si1886157pfj.49.2018.10.12.10.57.14; Fri, 12 Oct 2018 10:57:29 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727376AbeJMBaP (ORCPT + 99 others); Fri, 12 Oct 2018 21:30:15 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56680 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726703AbeJMBaP (ORCPT ); Fri, 12 Oct 2018 21:30:15 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C58B0C04FF85; Fri, 12 Oct 2018 17:56:35 +0000 (UTC) Received: from llong.com (dhcp-17-8.bos.redhat.com [10.18.17.8]) by smtp.corp.redhat.com (Postfix) with ESMTP id B085B831B1; Fri, 12 Oct 2018 17:56:26 +0000 (UTC) From: Waiman Long To: Tejun Heo , Li Zefan , Johannes Weiner , Peter Zijlstra , Ingo Molnar Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, kernel-team@fb.com, pjt@google.com, luto@amacapital.net, Mike Galbraith , torvalds@linux-foundation.org, Roman Gushchin , Juri Lelli , Patrick Bellasi , Waiman Long Subject: [PATCH v13 06/11] cpuset: Track cpusets that use parent's effective_cpus Date: Fri, 12 Oct 2018 13:55:46 -0400 Message-Id: <1539366951-8498-7-git-send-email-longman@redhat.com> In-Reply-To: <1539366951-8498-1-git-send-email-longman@redhat.com> References: <1539366951-8498-1-git-send-email-longman@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 12 Oct 2018 17:56:36 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In the default hierarchy, a cpuset will use the parent's effective_cpus if none of the requested CPUs can be granted from the parent. That can be a problem if a parent is a partition root with children partition roots. Changes to a parent's effective_cpus list due to changes in a child partition root may not be properly reflected in a child cpuset that use parent's effective_cpus because the cpu_exclusive rule of a partition root will not guard against that. In order to avoid the mismatch, two new tracking variables are added to the cpuset structure to track if a cpuset uses parent's effective_cpus and the number of children cpusets that use its effective_cpus. So whenever cpumask changes are made to a parent, it will also check to see if it has other children cpusets that use its effective_cpus and call update_cpumasks_hier() if that is the case. Signed-off-by: Waiman Long --- kernel/cgroup/cpuset.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 12ec61d..463c583 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -147,6 +147,14 @@ struct cpuset { /* partition root state */ int partition_root_state; + + /* + * Default hierarchy only: + * use_parent_ecpus - set if using parent's effective_cpus + * child_ecpus_count - # of children with use_parent_ecpus set + */ + int use_parent_ecpus; + int child_ecpus_count; }; /* @@ -1221,8 +1229,17 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp) * If it becomes empty, inherit the effective mask of the * parent, which is guaranteed to have some CPUs. */ - if (is_in_v2_mode() && cpumask_empty(tmp->new_cpus)) + if (is_in_v2_mode() && cpumask_empty(tmp->new_cpus)) { cpumask_copy(tmp->new_cpus, parent->effective_cpus); + if (!cp->use_parent_ecpus) { + cp->use_parent_ecpus = true; + parent->child_ecpus_count++; + } + } else if (cp->use_parent_ecpus) { + cp->use_parent_ecpus = false; + WARN_ON_ONCE(!parent->child_ecpus_count); + parent->child_ecpus_count--; + } /* * Skip the whole subtree if the cpumask remains the same @@ -1335,6 +1352,35 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp) } /** + * update_sibling_cpumasks - Update siblings cpumasks + * @parent: Parent cpuset + * @cs: Current cpuset + * @tmp: Temp variables + */ +static void update_sibling_cpumasks(struct cpuset *parent, struct cpuset *cs, + struct tmpmasks *tmp) +{ + struct cpuset *sibling; + struct cgroup_subsys_state *pos_css; + + /* + * Check all its siblings and call update_cpumasks_hier() + * if their use_parent_ecpus flag is set in order for them + * to use the right effective_cpus value. + */ + rcu_read_lock(); + cpuset_for_each_child(sibling, pos_css, parent) { + if (sibling == cs) + continue; + if (!sibling->use_parent_ecpus) + continue; + + update_cpumasks_hier(sibling, tmp); + } + rcu_read_unlock(); +} + +/** * update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it * @cs: the cpuset to consider * @trialcs: trial cpuset @@ -1406,6 +1452,17 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, spin_unlock_irq(&callback_lock); update_cpumasks_hier(cs, &tmp); + + if (cs->partition_root_state) { + struct cpuset *parent = parent_cs(cs); + + /* + * For partition root, update the cpumasks of sibling + * cpusets if they use parent's effective_cpus. + */ + if (parent->child_ecpus_count) + update_sibling_cpumasks(parent, cs, &tmp); + } return 0; } @@ -1842,6 +1899,9 @@ static int update_prstate(struct cpuset *cs, int val) if (parent != &top_cpuset) update_tasks_cpumask(parent); + if (parent->child_ecpus_count) + update_sibling_cpumasks(parent, cs, &tmp); + rebuild_sched_domains_locked(); out: free_cpumasks(&tmp); @@ -2536,6 +2596,8 @@ static int cpuset_css_online(struct cgroup_subsys_state *css) if (is_in_v2_mode()) { cpumask_copy(cs->effective_cpus, parent->effective_cpus); cs->effective_mems = parent->effective_mems; + cs->use_parent_ecpus = true; + parent->child_ecpus_count++; } spin_unlock_irq(&callback_lock); @@ -2599,6 +2661,13 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css) is_sched_load_balance(cs)) update_flag(CS_SCHED_LOAD_BALANCE, cs, 0); + if (cs->use_parent_ecpus) { + struct cpuset *parent = parent_cs(cs); + + cs->use_parent_ecpus = false; + parent->child_ecpus_count--; + } + cpuset_dec(); clear_bit(CS_ONLINE, &cs->flags); -- 1.8.3.1