@@ -175,6 +175,12 @@ include::xable-region-options.txt[]
--idle::
Include idle (not enabled) devices in the listing
+-C::
+--capabilities::
+ Include region capabilities in the listing, i.e. supported
+ namespace modes and variable properties like sector sizes and
+ alignments.
+
-M::
--media-errors::
Include media errors (badblocks) in the listing. Note that the
@@ -222,7 +228,8 @@ include::xable-region-options.txt[]
Everything '-v' provides, plus automatically enable --dimms,
--buses, and --regions. +
- *-vvv*
- Everything '-vv' provides, plus --health, --idle, and --firmware.
+ Everything '-vv' provides, plus --health, --capabilities,
+ --idle, and --firmware.
include::human-option.txt[]
@@ -36,6 +36,7 @@ static struct {
bool media_errors;
bool human;
bool firmware;
+ bool capabilities;
int verbose;
} list;
@@ -53,6 +54,8 @@ static unsigned long listopts_to_flags(void)
flags |= UTIL_JSON_HUMAN;
if (list.verbose)
flags |= UTIL_JSON_VERBOSE;
+ if (list.capabilities)
+ flags |= UTIL_JSON_CAPABILITIES;
return flags;
}
@@ -186,6 +189,12 @@ static struct json_object *region_to_json(struct ndctl_region *region,
if ((flags & UTIL_JSON_MEDIA_ERRORS) && jbbs)
json_object_object_add(jregion, "badblocks", jbbs);
+ if (flags & UTIL_JSON_CAPABILITIES) {
+ jobj = util_region_capabilities_to_json(region);
+ if (jobj)
+ json_object_object_add(jregion, "capabilities", jobj);
+ }
+
pd = ndctl_region_get_persistence_domain(region);
switch (pd) {
case PERSISTENCE_CPU_CACHE:
@@ -450,6 +459,8 @@ int cmd_list(int argc, const char **argv, struct ndctl_ctx *ctx)
"include namespace info (default)"),
OPT_BOOLEAN('X', "device-dax", &list.dax,
"include device-dax info"),
+ OPT_BOOLEAN('C', "capabilities", &list.capabilities,
+ "include region capability info"),
OPT_BOOLEAN('i', "idle", &list.idle, "include idle devices"),
OPT_BOOLEAN('M', "media-errors", &list.media_errors,
"include media errors"),
@@ -487,6 +498,7 @@ int cmd_list(int argc, const char **argv, struct ndctl_ctx *ctx)
list.idle = true;
list.firmware = true;
list.health = true;
+ list.capabilities = true;
case 2:
list.dimms = true;
list.buses = true;
@@ -321,7 +321,7 @@ struct json_object *util_daxctl_devs_to_list(struct daxctl_region *region,
}
#define _SZ(get_max, get_elem, type) \
-static struct json_object *type##_build_size_array(struct type *arg) \
+static struct json_object *util_##type##_build_size_array(struct ndctl_##type *arg) \
{ \
struct json_object *arr = json_object_new_array(); \
int i; \
@@ -346,11 +346,78 @@ err: \
return NULL; \
}
#define SZ(type, kind) _SZ(ndctl_##type##_get_num_##kind##s, \
- ndctl_##type##_get_supported_##kind, ndctl_##type)
+ ndctl_##type##_get_supported_##kind, type)
SZ(pfn, alignment)
SZ(dax, alignment)
SZ(btt, sector_size)
-//SZ(namespace, sector_size)
+
+struct json_object *util_region_capabilities_to_json(struct ndctl_region *region)
+{
+ struct json_object *jcaps, *jcap, *jobj;
+ struct ndctl_btt *btt = ndctl_region_get_btt_seed(region);
+ struct ndctl_pfn *pfn = ndctl_region_get_pfn_seed(region);
+ struct ndctl_dax *dax = ndctl_region_get_dax_seed(region);
+
+ if (!btt || !pfn || !dax)
+ return NULL;
+
+ jcaps = json_object_new_array();
+ if (!jcaps)
+ return NULL;
+
+ if (btt) {
+ jcap = json_object_new_object();
+ if (!jcap)
+ goto err;
+ json_object_array_add(jcaps, jcap);
+
+ jobj = json_object_new_string("sector");
+ if (!jobj)
+ goto err;
+ json_object_object_add(jcap, "mode", jobj);
+ jobj = util_btt_build_size_array(btt);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jcap, "sector_sizes", jobj);
+ }
+
+ if (pfn) {
+ jcap = json_object_new_object();
+ if (!jcap)
+ goto err;
+ json_object_array_add(jcaps, jcap);
+
+ jobj = json_object_new_string("fsdax");
+ if (!jobj)
+ goto err;
+ json_object_object_add(jcap, "mode", jobj);
+ jobj = util_pfn_build_size_array(pfn);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jcap, "alignments", jobj);
+ }
+
+ if (dax) {
+ jcap = json_object_new_object();
+ if (!jcap)
+ goto err;
+ json_object_array_add(jcaps, jcap);
+
+ jobj = json_object_new_string("devdax");
+ if (!jobj)
+ goto err;
+ json_object_object_add(jcap, "mode", jobj);
+ jobj = util_dax_build_size_array(dax);
+ if (!jobj)
+ goto err;
+ json_object_object_add(jcap, "alignments", jobj);
+ }
+
+ return jcaps;
+err:
+ json_object_put(jcaps);
+ return NULL;
+}
struct json_object *util_daxctl_region_to_json(struct daxctl_region *region,
const char *ident, unsigned long flags)
@@ -788,7 +855,7 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns,
{
struct json_object *jndns = json_object_new_object();
enum ndctl_pfn_loc loc = NDCTL_PFN_LOC_NONE;
- struct json_object *jobj, *jbbs = NULL, *size_array = NULL;
+ struct json_object *jobj, *jbbs = NULL;
const char *locations[] = {
[NDCTL_PFN_LOC_NONE] = "none",
[NDCTL_PFN_LOC_RAM] = "mem",
@@ -798,7 +865,6 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns,
unsigned int sector_size = UINT_MAX;
enum ndctl_namespace_mode mode;
const char *bdev = NULL, *name;
- const char *size_array_name;
unsigned int bb_count = 0;
struct ndctl_btt *btt;
struct ndctl_pfn *pfn;
@@ -986,19 +1052,6 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns,
json_object_object_add(jndns, "numa_node", jobj);
}
- if (pfn) {
- size_array_name = "supported_alignments";
- size_array = ndctl_pfn_build_size_array(pfn);
- } else if (dax) {
- size_array_name = "supported_alignments";
- size_array = ndctl_dax_build_size_array(dax);
- } else if (btt) {
- size_array_name = "supported sector sizes";
- size_array = ndctl_btt_build_size_array(btt);
- }
- if (size_array && flags & UTIL_JSON_VERBOSE)
- json_object_object_add(jndns, size_array_name, size_array);
-
if (pfn)
jbbs = util_pfn_badblocks_to_json(pfn, &bb_count, flags);
else if (dax)
@@ -24,6 +24,7 @@ enum util_json_flags {
UTIL_JSON_DAX_DEVS = (1 << 3),
UTIL_JSON_HUMAN = (1 << 4),
UTIL_JSON_VERBOSE = (1 << 5),
+ UTIL_JSON_CAPABILITIES = (1 << 6),
};
struct json_object;
@@ -56,4 +57,5 @@ struct json_object *util_json_object_hex(unsigned long long val,
struct json_object *util_dimm_health_to_json(struct ndctl_dimm *dimm);
struct json_object *util_dimm_firmware_to_json(struct ndctl_dimm *dimm,
unsigned long flags);
+struct json_object *util_region_capabilities_to_json(struct ndctl_region *region);
#endif /* __NDCTL_JSON_H__ */
For common capabilities that a region can create provide a json object of the following form: "capabilities":[ { "mode":"sector", "sector_sizes":[ 512, 520, 528, 4096, 4104, 4160, 4224 ] }, { "mode":"fsdax", "alignments":[ 4096, 2097152, 1073741824 ] }, { "mode":"devdax", "alignments":[ 4096, 2097152, 1073741824 ] } ] This replaces the "supported_alignments" and "supported sector sizes" fields which ended up being too repetitive at the namespace level. Cc: Oliver O'Halloran <oohall@gmail.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> --- Documentation/ndctl/ndctl-list.txt | 9 +++- ndctl/list.c | 12 +++++ util/json.c | 89 +++++++++++++++++++++++++++++------- util/json.h | 2 + 4 files changed, 93 insertions(+), 19 deletions(-)