From: "Verma, Vishal L" <vishal.l.verma@intel.com>
To: "Williams, Dan J" <dan.j.williams@intel.com>
Cc: "linux-cxl@vger.kernel.org" <linux-cxl@vger.kernel.org>,
"nvdimm@lists.linux.dev" <nvdimm@lists.linux.dev>
Subject: Re: [ndctl PATCH 11/15] cxl/region: Use cxl_filter_walk() to gather create-region targets
Date: Tue, 8 Nov 2022 08:31:58 +0000 [thread overview]
Message-ID: <07dc26a831b0b93f28db45729972a23d19f21205.camel@intel.com> (raw)
In-Reply-To: <166777846906.1238089.13466320510516058152.stgit@dwillia2-xfh.jf.intel.com>
On Sun, 2022-11-06 at 15:47 -0800, Dan Williams wrote:
> > The core of 'cxl list' knows, among other things, how to filter memdevs by
> > their connectivity to a root decoder, enabled status, and how to identify
> > memdevs by name, id, serial number. Use the fact that the json-c object
> > array returned by cxl_filter_walk() also includes the corresponding libcxl
> > objects to populate and validate the memdev target list for 'cxl
> > create-region'.
> >
> > With this in place a default set of memdev targets can be derived from the
> > specified root decoder, and the connectivity is validated by the same logic
> > that prepares the hierarchical json topology. The argument list becomes
> > as tolerant of different id formats as 'cxl list'. For example "mem9" and
> > "9" are equivalent.
> >
> > Comma separated lists are also allowed, e.g. "mem9,mem10". However the
> > sorting of memdevs by filter position falls back to the 'cxl list' order in
> > that case. In other words:
> >
> > arg order region position
> > mem9 mem10 => [0]: mem9 [1]: mem10
> > mem10 mem9 => [0]: mem10 [1]: mem9
> > mem9,mem10 => [0]: mem9 [1]: mem10
> > mem10,mem9 => [0]: mem9 [1]: mem10
Hm, this does create an awkward situation where
cxl create-region -m mem10 mem9 (same as first arg order above)
can behave differently from
cxl create-region -m "mem10 mem9" (behaves like 4th arg order above)
i.e. if the args happen to get quoted into a single space separated
list, then it switches back to cxl-list ordering as "mem10 mem9" gets
treated as a single filter string.
I wonder if we should add another step after collect_memdevs() (or
change memdev_sort()) to return the arg order by default, so:
mem9 mem10 => [0]: mem9 [1]: mem10
mem10 mem9 => [0]: mem10 [1]: mem9
mem9,mem10 => [0]: mem9 [1]: mem10
mem10,mem9 => [0]: mem10 [1]: mem9
"mem9 mem10" => [0]: mem9 [1]: mem10
"mem10 mem9" => [0]: mem10 [1]: mem9
i.e. region positioning stays consistent no matter what combination of
field separators, or quoting, or word splitting ends up happening.
Then (future patches) add a --relax-ordering or --allow-reordering
option that can fix up the order for creating a region successfully
with the given set.
With this, the only two options create-region has are either try the
user-specified order exactly, or reorder to something that wil be
successful. The cxl-list default order doesn't seem as a useful 'mode'
to have as it can be hit-or-miss.
> >
> > Note that 'cxl list' order groups memdevs by port, later this will need to
> > augmented with a sort implementation that orders memdevs by a topology
> > compatible decode order.
> >
> > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> > ---
> > cxl/region.c | 274 +++++++++++++++++++++++++++++++++++++---------------------
> > 1 file changed, 175 insertions(+), 99 deletions(-)
> >
> > diff --git a/cxl/region.c b/cxl/region.c
> > index c6d7d1a973a8..e47709754447 100644
> > --- a/cxl/region.c
> > +++ b/cxl/region.c
> > @@ -40,8 +40,10 @@ struct parsed_params {
> > u64 ep_min_size;
> > int ways;
> > int granularity;
> > - const char **targets;
> > - int num_targets;
> > + struct json_object *memdevs;
> > + int num_memdevs;
> > + int argc;
> > + const char **argv;
> > struct cxl_decoder *root_decoder;
> > enum cxl_decoder_mode mode;
> > };
> > @@ -99,16 +101,148 @@ static const struct option destroy_options[] = {
> > OPT_END(),
> > };
> >
> > -static int parse_create_options(int argc, const char **argv,
> > - struct parsed_params *p)
> > +/*
> > + * Convert an array of strings into a single comma-separated-value
> > + * string that can be passed as a single 'filter' string to
> > + * cxl_filter_walk()
> > + */
> > +static const char *to_csv(int count, const char **strings)
> > {
> > + ssize_t len = count + 1, cursor = 0;
> > + char *csv;
> > int i;
> >
> > + if (!count)
> > + return NULL;
> > +
> > + for (i = 0; i < count; i++)
> > + len += strlen(strings[i]);
> > + csv = calloc(1, len);
> > + if (!csv)
> > + return NULL;
> > + for (i = 0; i < count; i++) {
> > + cursor += snprintf(csv + cursor, len - cursor, "%s%s",
> > + strings[i], i + 1 < count ? "," : "");
> > + if (cursor >= len) {
> > + csv[len] = 0;
> > + break;
> > + }
> > + }
> > + return csv;
> > +}
> > +
> > +static struct sort_context {
> > + int count;
> > + const char **sort;
> > +} sort_context;
> > +
> > +static int memdev_filter_pos(struct json_object *jobj, int count, const char **sort)
> > +{
> > + struct cxl_memdev *memdev = json_object_get_userdata(jobj);
> > + int pos;
> > +
> > + for (pos = 0; pos < count; pos++)
> > + if (util_cxl_memdev_filter(memdev, sort[pos], NULL))
> > + return pos;
> > + return count;
> > +}
> > +
> > +static int memdev_sort(const void *a, const void *b)
> > +{
> > + int a_pos, b_pos, count = sort_context.count;
> > + const char **sort = sort_context.sort;
> > + struct json_object **a_obj, **b_obj;
> > +
> > + a_obj = (struct json_object **) a;
> > + b_obj = (struct json_object **) b;
> > +
> > + a_pos = memdev_filter_pos(*a_obj, count, sort);
> > + b_pos = memdev_filter_pos(*b_obj, count, sort);
> > +
> > + return a_pos - b_pos;
> > +}
> > +
> > +static struct json_object *collect_memdevs(struct cxl_ctx *ctx,
> > + const char *decoder, int count,
> > + const char **mems)
> > +{
> > + const char *csv = to_csv(count, mems);
> > + struct cxl_filter_params filter_params = {
> > + .decoder_filter = decoder,
> > + .memdevs = true,
> > + .memdev_filter = csv,
> > + };
> > + struct json_object *jmemdevs;
> > +
> > + jmemdevs = cxl_filter_walk(ctx, &filter_params);
> > +
> > + if (!jmemdevs) {
> > + log_err(&rl, "failed to retrieve memdevs\n");
> > + goto out;
> > + }
> > +
> > + if (json_object_array_length(jmemdevs) == 0) {
> > + log_err(&rl,
> > + "no active memdevs found: decoder: %s filter: %s\n",
> > + decoder, csv ? csv : "none");
> > + json_object_put(jmemdevs);
> > + jmemdevs = NULL;
> > + goto out;
> > + }
> > +
> > + sort_context = (struct sort_context){
> > + .count = count,
> > + .sort = mems,
> > + };
> > + json_object_array_sort(jmemdevs, memdev_sort);
> > +
> > +out:
> > + free((void *)csv);
> > + return jmemdevs;
> > +}
> > +
> > +static bool validate_ways(struct parsed_params *p, int count)
> > +{
> > + /*
> > + * Validate interleave ways against targets found in the topology. If
> > + * the targets were specified, then non-default param.ways must equal
> > + * that number of targets.
> > + */
> > + if (p->ways > p->num_memdevs || (count && p->ways != p->num_memdevs)) {
This falls over when doing something like
cxl create-region -m mem0,mem1
as @count ends up being '1' from the single filter spec passed in.
I think doing a 'count = p->num_memdevs' (below) should fix it - we
don't care about how many separate filter specs were passed in, once
they have been combined, and the resulting memdevfs collected.
> > + log_err(&rl,
> > + "Interleave ways %d is %s than number of memdevs %s: %d\n",
> > + p->ways, p->ways > p->num_memdevs ? "greater" : "less",
> > + count ? "specified" : "found", p->num_memdevs);
> > + return false;
> > + }
> > + return true;
> > +}
> > +
> > +static int parse_create_options(struct cxl_ctx *ctx, int count,
> > + const char **mems, struct parsed_params *p)
> > +{
> > if (!param.root_decoder) {
> > log_err(&rl, "no root decoder specified\n");
> > return -EINVAL;
> > }
> >
> > + /*
> > + * For all practical purposes, -m is the default target type, but
> > + * hold off on actively making that decision until a second target
> > + * option is available.
> > + */
> > + if (!param.memdevs) {
> > + log_err(&rl,
> > + "must specify option for target object types (-m)\n");
> > + return -EINVAL;
> > + }
> > +
> > + /* Collect the valid memdevs relative to the given root decoder */
> > + p->memdevs = collect_memdevs(ctx, param.root_decoder, count, mems);
> > + if (!p->memdevs)
> > + return -ENXIO;
> > + p->num_memdevs = json_object_array_length(p->memdevs);
Per the above comment, either
count = p->num_memdevs;
here, or alternatively, the interleave ways validation shouldn't use
@count anymore.
> > +
> > if (param.type) {
> > p->mode = cxl_decoder_mode_from_ident(param.type);
> > if (p->mode == CXL_DECODER_MODE_NONE) {
<snip>
> >
> > @@ -664,8 +738,10 @@ static int region_action(int argc, const char **argv, struct cxl_ctx *ctx,
> > if (rc)
> > return rc;
> >
> > - if (action == ACTION_CREATE)
> > - return create_region(ctx, count, p);
> > + if (action == ACTION_CREATE) {
> > + rc = create_region(ctx, count, p);
> > + json_object_put(p->memdevs);
Should this dereference happen just before returning from
create_region() since that is where cxl_filter_walk() was called from,
and is also where p->memdevs is last used.
> > + }
> >
> > cxl_bus_foreach(ctx, bus) {
> > struct cxl_decoder *decoder;
> >
next prev parent reply other threads:[~2022-11-08 8:32 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-06 23:46 [ndctl PATCH 00/15] cxl-cli test and usability updates Dan Williams
2022-11-06 23:46 ` [ndctl PATCH 01/15] ndctl/test: Move firmware-update.sh to the 'descructive' set Dan Williams
2022-11-06 23:46 ` [ndctl PATCH 02/15] ndctl/test: Add kernel backtrace detection to some dax tests Dan Williams
2022-11-07 22:55 ` Alison Schofield
2022-11-06 23:47 ` [ndctl PATCH 03/15] ndctl/clang-format: Move minimum version to 6 Dan Williams
2022-11-06 23:47 ` [ndctl PATCH 04/15] ndctl/clang-format: Fix space after for_each macros Dan Williams
2022-11-06 23:47 ` [ndctl PATCH 05/15] cxl/list: Always attempt to collect child objects Dan Williams
2022-11-06 23:47 ` [ndctl PATCH 06/15] cxl/list: Skip emitting pmem_size when it is zero Dan Williams
2022-11-07 20:23 ` Alison Schofield
2022-11-07 23:42 ` Dan Williams
2022-12-08 3:36 ` Dan Williams
2022-11-07 22:47 ` Alison Schofield
2022-11-07 23:51 ` Dan Williams
2022-12-08 4:14 ` Dan Williams
2022-11-06 23:47 ` [ndctl PATCH 07/15] cxl/filter: Return json-c topology Dan Williams
2022-11-06 23:47 ` [ndctl PATCH 08/15] cxl/list: Record cxl objects in json objects Dan Williams
2022-11-06 23:47 ` [ndctl PATCH 09/15] cxl/region: Make ways an integer argument Dan Williams
2022-11-07 22:43 ` Alison Schofield
2022-11-07 23:50 ` Dan Williams
2022-11-08 19:36 ` Verma, Vishal L
2022-11-06 23:47 ` [ndctl PATCH 10/15] cxl/region: Make granularity " Dan Williams
2022-11-06 23:47 ` [ndctl PATCH 11/15] cxl/region: Use cxl_filter_walk() to gather create-region targets Dan Williams
2022-11-08 8:31 ` Verma, Vishal L [this message]
2022-12-08 20:23 ` Dan Williams
2022-11-06 23:47 ` [ndctl PATCH 12/15] cxl/region: Trim region size by max available extent Dan Williams
2022-11-06 23:48 ` [ndctl PATCH 13/15] cxl/region: Default to memdev mode for create with no arguments Dan Williams
2022-11-07 20:36 ` Alison Schofield
2022-11-07 23:48 ` Dan Williams
2022-11-08 16:03 ` Alison Schofield
2022-12-08 4:09 ` Dan Williams
2022-11-06 23:48 ` [ndctl PATCH 14/15] cxl/test: Extend cxl-topology.sh for a single root-port host-bridge Dan Williams
2022-11-07 22:38 ` Alison Schofield
2022-11-08 20:23 ` Verma, Vishal L
2022-12-08 20:25 ` Dan Williams
2022-11-06 23:48 ` [ndctl PATCH 15/15] cxl/test: Test single-port host-bridge region creation Dan Williams
2022-11-07 22:36 ` Alison Schofield
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=07dc26a831b0b93f28db45729972a23d19f21205.camel@intel.com \
--to=vishal.l.verma@intel.com \
--cc=dan.j.williams@intel.com \
--cc=linux-cxl@vger.kernel.org \
--cc=nvdimm@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox