lkml.org 
[lkml]   [2021]   [Dec]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v9 5/7] cgroup/cpuset: Show invalid partition reason string
    Date
    There are a number of different reasons which can cause a partition to
    become invalid. A user seeing an invalid partition may not know exactly
    why. To help user to get a better understanding of the underlying reason,
    The cpuset.cpus.partition control file, when read, will now report the
    reason why a partition become invalid. When a partition does become
    invalid, reading the control file will show "root invalid (<reason>)"
    where <reason> is a string that describes why the partition is invalid.

    Signed-off-by: Waiman Long <longman@redhat.com>
    ---
    kernel/cgroup/cpuset.c | 58 ++++++++++++++++++++++++++++++++++++++----
    1 file changed, 53 insertions(+), 5 deletions(-)

    diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
    index cfab10911682..d1025470b9ea 100644
    --- a/kernel/cgroup/cpuset.c
    +++ b/kernel/cgroup/cpuset.c
    @@ -85,6 +85,26 @@ struct fmeter {
    spinlock_t lock; /* guards read or write of above */
    };

    +/*
    + * Invalid partition error code
    + */
    +enum prs_errcode {
    + PERR_NONE = 0,
    + PERR_INVCPUS,
    + PERR_INVPARENT,
    + PERR_NOTPART,
    + PERR_NOCPUS,
    + PERR_HOTPLUG,
    +};
    +
    +static const char * const perr_strings[] = {
    + [PERR_INVCPUS] = "Invalid change to cpuset.cpus",
    + [PERR_INVPARENT] = "Parent is an invalid partition root",
    + [PERR_NOTPART] = "Parent is not a partition root",
    + [PERR_NOCPUS] = "Parent unable to distribute cpu downstream",
    + [PERR_HOTPLUG] = "No cpu available due to hotplug",
    +};
    +
    struct cpuset {
    struct cgroup_subsys_state css;

    @@ -168,6 +188,9 @@ struct cpuset {
    int use_parent_ecpus;
    int child_ecpus_count;

    + /* Invalid partition error code, not lock protected */
    + enum prs_errcode prs_err;
    +
    /* Handle for cpuset.cpus.partition */
    struct cgroup_file partition_file;
    };
    @@ -282,8 +305,13 @@ static inline int is_partition_root(const struct cpuset *cs)
    static inline void notify_partition_change(struct cpuset *cs,
    int old_prs, int new_prs)
    {
    - if (old_prs != new_prs)
    - cgroup_file_notify(&cs->partition_file);
    + if (old_prs == new_prs)
    + return;
    + cgroup_file_notify(&cs->partition_file);
    +
    + /* Reset prs_err if not invalid */
    + if (new_prs != PRS_ERROR)
    + WRITE_ONCE(cs->prs_err, PERR_NONE);
    }

    static struct cpuset top_cpuset = {
    @@ -1292,6 +1320,9 @@ static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,
    part_error = partition_is_populated(parent, cpuset) &&
    cpumask_subset(parent->effective_cpus, tmp->addmask) &&
    !cpumask_intersects(tmp->delmask, cpu_active_mask);
    +
    + if ((READ_ONCE(cpuset->prs_err) == PERR_NONE) && part_error)
    + WRITE_ONCE(cpuset->prs_err, PERR_INVCPUS);
    } else {
    /*
    * partcmd_update w/o newmask:
    @@ -1315,6 +1346,9 @@ static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,
    !parent->nr_subparts_cpus) ||
    (cpumask_equal(parent->effective_cpus, tmp->addmask) &&
    partition_is_populated(parent, cpuset));
    +
    + if (is_partition_root(cpuset) && part_error)
    + WRITE_ONCE(cpuset->prs_err, PERR_NOCPUS);
    }

    if (cmd == partcmd_update) {
    @@ -1471,6 +1505,9 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp,
    * invalid too.
    */
    new_prs = PRS_ERROR;
    + WRITE_ONCE(cp->prs_err,
    + (parent->partition_root_state == PRS_ERROR)
    + ? PERR_INVPARENT : PERR_NOTPART);
    break;
    }
    }
    @@ -2632,7 +2669,7 @@ static s64 cpuset_read_s64(struct cgroup_subsys_state *css, struct cftype *cft)
    static int sched_partition_show(struct seq_file *seq, void *v)
    {
    struct cpuset *cs = css_cs(seq_css(seq));
    - const char *type;
    + const char *err, *type;

    switch (cs->partition_root_state) {
    case PRS_ENABLED:
    @@ -2646,7 +2683,11 @@ static int sched_partition_show(struct seq_file *seq, void *v)
    break;
    case PRS_ERROR:
    type = is_sched_load_balance(cs) ? "root" : "isolated";
    - seq_printf(seq, "%s invalid\n", type);
    + err = perr_strings[READ_ONCE(cs->prs_err)];
    + if (err)
    + seq_printf(seq, "%s invalid (%s)\n", type, err);
    + else
    + seq_printf(seq, "%s invalid\n", type);
    break;
    }
    return 0;
    @@ -3236,7 +3277,7 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)
    if (is_partition_root(cs) &&
    ((cpumask_empty(&new_cpus) && partition_is_populated(cs, NULL)) ||
    !parent->nr_subparts_cpus)) {
    - int old_prs;
    + int old_prs, parent_prs;

    update_parent_subparts_cpumask(cs, partcmd_disable,
    NULL, tmp);
    @@ -3249,10 +3290,17 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)
    }

    old_prs = cs->partition_root_state;
    + parent_prs = parent->partition_root_state;
    if (old_prs != PRS_ERROR) {
    spin_lock_irq(&callback_lock);
    cs->partition_root_state = PRS_ERROR;
    spin_unlock_irq(&callback_lock);
    + if (parent_prs == PRS_ERROR)
    + WRITE_ONCE(cs->prs_err, PERR_INVPARENT);
    + else if (!parent_prs)
    + WRITE_ONCE(cs->prs_err, PERR_NOTPART);
    + else
    + WRITE_ONCE(cs->prs_err, PERR_HOTPLUG);
    notify_partition_change(cs, old_prs, PRS_ERROR);
    }
    cpuset_force_rebuild();
    --
    2.27.0
    \
     
     \ /
      Last update: 2021-12-05 19:34    [W:2.928 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site