[PATCH] libnvdimm, pmem: Fix badblocks population for 'raw' namespaces
by Dan Williams
The driver is only initializing bb_res in the devm_memremap_pages()
paths, but the raw namespace case is passing an uninitialized bb_res to
nvdimm_badblocks_populate().
Fixes: e8d513483300 ("memremap: change devm_memremap_pages interface...")
Cc: <stable(a)vger.kernel.org>
Cc: Christoph Hellwig <hch(a)lst.de>
Reported-by: Jacek Zloch <jacek.zloch(a)intel.com>
Reported-by: Krzysztof Rusocki <krzysztof.rusocki(a)intel.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/nvdimm/pmem.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 6071e2942053..2082ae01b9c8 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -421,9 +421,11 @@ static int pmem_attach_disk(struct device *dev,
addr = devm_memremap_pages(dev, &pmem->pgmap);
pmem->pfn_flags |= PFN_MAP;
memcpy(&bb_res, &pmem->pgmap.res, sizeof(bb_res));
- } else
+ } else {
addr = devm_memremap(dev, pmem->phys_addr,
pmem->size, ARCH_MEMREMAP_PMEM);
+ memcpy(&bb_res, &nsio->res, sizeof(bb_res));
+ }
/*
* At release time the queue must be frozen before
2 years, 3 months
[ndctl PATCH v2] libndctl: set errno for routines that don't return an error status
by Vishal Verma
For routines that return a UINT_MAX or UL{L}ONG_MAX, there isn't a way
to get any information as to what went wrong. Set errno in such routines
so that the callers can get some additional context about the error.
Reported-by: Lukasz Dorau <lukasz.dorau(a)intel.com>
Cc: Dan Williams <dan.j.williams(a)intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma(a)intel.com>
---
ndctl/lib/dimm.c | 8 +++--
ndctl/lib/hpe1.c | 79 +++++++++++++++++++++++++++++++++++++-------
ndctl/lib/inject.c | 2 ++
ndctl/lib/intel.c | 45 +++++++++++++++++++++----
ndctl/lib/libndctl.c | 54 ++++++++++++++++++++++--------
ndctl/lib/msft.c | 27 ++++++++++++---
6 files changed, 177 insertions(+), 38 deletions(-)
v2: s/EOVERFLOW/ENOMEM/ (Dan)
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index b3e032e..5e41734 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -565,17 +565,21 @@ NDCTL_EXPORT unsigned long ndctl_dimm_get_available_labels(
{
struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
char *path = dimm->dimm_buf;
- int len = dimm->buf_len;
+ int rc, len = dimm->buf_len;
char buf[20];
if (snprintf(path, len, "%s/available_slots", dimm->dimm_path) >= len) {
err(ctx, "%s: buffer too small!\n",
ndctl_dimm_get_devname(dimm));
+ errno = ENOMEM;
return ULONG_MAX;
}
- if (sysfs_read_attr(ctx, path, buf) < 0)
+ rc = sysfs_read_attr(ctx, path, buf);
+ if (rc < 0) {
+ errno = -rc;
return ULONG_MAX;
+ }
return strtoul(buf, NULL, 0);
}
diff --git a/ndctl/lib/hpe1.c b/ndctl/lib/hpe1.c
index dbc1ff0..b26120e 100644
--- a/ndctl/lib/hpe1.c
+++ b/ndctl/lib/hpe1.c
@@ -90,9 +90,13 @@ static unsigned int hpe1_cmd_smart_get_flags(struct ndctl_cmd *cmd)
{
unsigned int hpe1flags;
unsigned int flags;
+ int rc;
- if (hpe1_smart_valid(cmd) < 0)
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
hpe1flags = CMD_HPE1_SMART(cmd)->out_valid_flags;
flags = 0;
@@ -118,9 +122,13 @@ static unsigned int hpe1_cmd_smart_get_health(struct ndctl_cmd *cmd)
{
unsigned char hpe1health;
unsigned int health;
+ int rc;
- if (hpe1_smart_valid(cmd) < 0)
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
hpe1health = CMD_HPE1_SMART(cmd)->stat_summary;
health = 0;
@@ -136,16 +144,26 @@ static unsigned int hpe1_cmd_smart_get_health(struct ndctl_cmd *cmd)
static unsigned int hpe1_cmd_smart_get_media_temperature(struct ndctl_cmd *cmd)
{
- if (hpe1_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_HPE1_SMART(cmd)->curr_temp;
}
static unsigned int hpe1_cmd_smart_get_spares(struct ndctl_cmd *cmd)
{
- if (hpe1_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_HPE1_SMART(cmd)->spare_blocks;
}
@@ -154,9 +172,13 @@ static unsigned int hpe1_cmd_smart_get_alarm_flags(struct ndctl_cmd *cmd)
{
unsigned int hpe1flags;
unsigned int flags;
+ int rc;
- if (hpe1_smart_valid(cmd) < 0)
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
hpe1flags = CMD_HPE1_SMART(cmd)->alarm_trips;
flags = 0;
@@ -170,8 +192,13 @@ static unsigned int hpe1_cmd_smart_get_alarm_flags(struct ndctl_cmd *cmd)
static unsigned int hpe1_cmd_smart_get_life_used(struct ndctl_cmd *cmd)
{
- if (hpe1_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_HPE1_SMART(cmd)->device_life;
}
@@ -179,9 +206,13 @@ static unsigned int hpe1_cmd_smart_get_life_used(struct ndctl_cmd *cmd)
static unsigned int hpe1_cmd_smart_get_shutdown_state(struct ndctl_cmd *cmd)
{
unsigned int shutdown;
+ int rc;
- if (hpe1_smart_valid(cmd) < 0)
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
shutdown = CMD_HPE1_SMART(cmd)->last_shutdown_stat;
if (shutdown == NDN_HPE1_SMART_LASTSAVEGOOD)
@@ -192,16 +223,26 @@ static unsigned int hpe1_cmd_smart_get_shutdown_state(struct ndctl_cmd *cmd)
static unsigned int hpe1_cmd_smart_get_vendor_size(struct ndctl_cmd *cmd)
{
- if (hpe1_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_HPE1_SMART(cmd)->vndr_spec_data_size;
}
static unsigned char *hpe1_cmd_smart_get_vendor_data(struct ndctl_cmd *cmd)
{
- if (hpe1_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return NULL;
+ }
return CMD_HPE1_SMART(cmd)->vnd_spec_data;
}
@@ -265,9 +306,13 @@ static unsigned int hpe1_cmd_smart_threshold_get_alarm_control(struct ndctl_cmd
{
unsigned int hpe1flags;
unsigned int flags;
+ int rc;
- if (hpe1_smart_threshold_valid(cmd) < 0)
+ rc = hpe1_smart_threshold_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
hpe1flags = CMD_HPE1_SMART_THRESH(cmd)->threshold_alarm_ctl;
flags = 0;
@@ -282,16 +327,26 @@ static unsigned int hpe1_cmd_smart_threshold_get_alarm_control(struct ndctl_cmd
static unsigned int hpe1_cmd_smart_threshold_get_media_temperature(
struct ndctl_cmd *cmd)
{
- if (hpe1_smart_threshold_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_threshold_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_HPE1_SMART_THRESH(cmd)->temp_threshold;
}
static unsigned int hpe1_cmd_smart_threshold_get_spares(struct ndctl_cmd *cmd)
{
- if (hpe1_smart_threshold_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_threshold_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_HPE1_SMART_THRESH(cmd)->spare_block_threshold;
}
diff --git a/ndctl/lib/inject.c b/ndctl/lib/inject.c
index 268c5cd..2b0702e 100644
--- a/ndctl/lib/inject.c
+++ b/ndctl/lib/inject.c
@@ -498,6 +498,7 @@ NDCTL_EXPORT unsigned long long ndctl_bb_get_block(struct ndctl_bb *bb)
{
if (bb)
return bb->block;
+ errno = EINVAL;
return ULLONG_MAX;
}
@@ -505,5 +506,6 @@ NDCTL_EXPORT unsigned long long ndctl_bb_get_count(struct ndctl_bb *bb)
{
if (bb)
return bb->count;
+ errno = EINVAL;
return ULLONG_MAX;
}
diff --git a/ndctl/lib/intel.c b/ndctl/lib/intel.c
index 0abea1e..744386f 100644
--- a/ndctl/lib/intel.c
+++ b/ndctl/lib/intel.c
@@ -85,8 +85,12 @@ static int intel_smart_valid(struct ndctl_cmd *cmd)
#define intel_smart_get_field(cmd, field) \
static unsigned int intel_cmd_smart_get_##field(struct ndctl_cmd *cmd) \
{ \
- if (intel_smart_valid(cmd) < 0) \
+ int rc; \
+ rc = intel_smart_valid(cmd); \
+ if (rc < 0) { \
+ errno = -rc; \
return UINT_MAX; \
+ } \
return cmd->intel->smart.field; \
}
@@ -173,8 +177,12 @@ static int intel_smart_threshold_valid(struct ndctl_cmd *cmd)
static unsigned int intel_cmd_smart_threshold_get_##field( \
struct ndctl_cmd *cmd) \
{ \
- if (intel_smart_threshold_valid(cmd) < 0) \
+ int rc; \
+ rc = intel_smart_threshold_valid(cmd); \
+ if (rc < 0) { \
+ errno = -rc; \
return UINT_MAX; \
+ } \
return cmd->intel->thresh.field; \
}
@@ -431,8 +439,12 @@ static int intel_fw_get_info_valid(struct ndctl_cmd *cmd)
static unsigned int intel_cmd_fw_info_get_##field( \
struct ndctl_cmd *cmd) \
{ \
- if (intel_fw_get_info_valid(cmd) < 0) \
+ int rc; \
+ rc = intel_fw_get_info_valid(cmd); \
+ if (rc < 0) { \
+ errno = -rc; \
return UINT_MAX; \
+ } \
return cmd->intel->info.field; \
}
@@ -440,8 +452,12 @@ static unsigned int intel_cmd_fw_info_get_##field( \
static unsigned long long intel_cmd_fw_info_get_##field( \
struct ndctl_cmd *cmd) \
{ \
- if (intel_fw_get_info_valid(cmd) < 0) \
+ int rc; \
+ rc = intel_fw_get_info_valid(cmd); \
+ if (rc < 0) { \
+ errno = -rc; \
return ULLONG_MAX; \
+ } \
return cmd->intel->info.field; \
}
@@ -454,8 +470,13 @@ intel_fw_info_get_field64(cmd, run_version);
static unsigned long long intel_cmd_fw_info_get_updated_version(
struct ndctl_cmd *cmd)
{
- if (intel_fw_get_info_valid(cmd) < 0)
+ int rc;
+
+ rc = intel_fw_get_info_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return ULLONG_MAX;
+ }
return cmd->intel->info.updated_version;
}
@@ -488,8 +509,13 @@ static int intel_fw_start_valid(struct ndctl_cmd *cmd)
static unsigned int intel_cmd_fw_start_get_context(struct ndctl_cmd *cmd)
{
- if (intel_fw_start_valid(cmd) < 0)
+ int rc;
+
+ rc = intel_fw_start_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return cmd->intel->start.context;
}
@@ -580,8 +606,13 @@ static int intel_fw_fquery_valid(struct ndctl_cmd *cmd)
static unsigned long long
intel_cmd_fw_fquery_get_fw_rev(struct ndctl_cmd *cmd)
{
- if (intel_fw_fquery_valid(cmd) < 0)
+ int rc;
+
+ rc = intel_fw_fquery_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return ULLONG_MAX;
+ }
return cmd->intel->fquery.updated_fw_rev;
}
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 4ceb70e..0c3a35e 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -1112,12 +1112,15 @@ NDCTL_EXPORT unsigned long long ndctl_region_get_resource(struct ndctl_region *r
if (snprintf(path, len, "%s/resource", region->region_path) >= len) {
err(ctx, "%s: buffer too small!\n",
ndctl_region_get_devname(region));
+ errno = ENOMEM;
return ULLONG_MAX;
}
rc = sysfs_read_attr(ctx, path, buf);
- if (rc < 0)
+ if (rc < 0) {
+ errno = -rc;
return ULLONG_MAX;
+ }
return strtoull(buf, NULL, 0);
}
@@ -1256,9 +1259,13 @@ NDCTL_EXPORT unsigned int ndctl_bus_get_scrub_count(struct ndctl_bus *bus)
{
unsigned int scrub_count = 0;
bool active = false;
+ int rc;
- if (__ndctl_bus_get_scrub_state(bus, &scrub_count, &active))
+ rc = __ndctl_bus_get_scrub_state(bus, &scrub_count, &active);
+ if (rc) {
+ errno = -rc;
return UINT_MAX;
+ }
return scrub_count;
}
@@ -1720,15 +1727,19 @@ NDCTL_EXPORT unsigned int ndctl_dimm_get_health(struct ndctl_dimm *dimm)
unsigned int health;
struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
const char *devname = ndctl_dimm_get_devname(dimm);
+ int rc;
cmd = ndctl_dimm_cmd_new_smart(dimm);
if (!cmd) {
err(ctx, "%s: no smart command support\n", devname);
return UINT_MAX;
}
- if (ndctl_cmd_submit(cmd)) {
+ rc = ndctl_cmd_submit(cmd);
+ if (rc) {
err(ctx, "%s: smart command failed\n", devname);
ndctl_cmd_unref(cmd);
+ if (rc < 0)
+ errno = -rc;
return UINT_MAX;
}
@@ -1743,15 +1754,19 @@ NDCTL_EXPORT unsigned int ndctl_dimm_get_flags(struct ndctl_dimm *dimm)
unsigned int flags;
struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
const char *devname = ndctl_dimm_get_devname(dimm);
+ int rc;
cmd = ndctl_dimm_cmd_new_smart(dimm);
if (!cmd) {
dbg(ctx, "%s: no smart command support\n", devname);
return UINT_MAX;
}
- if (ndctl_cmd_submit(cmd)) {
+ rc = ndctl_cmd_submit(cmd);
+ if (rc) {
dbg(ctx, "%s: smart command failed\n", devname);
ndctl_cmd_unref(cmd);
+ if (rc < 0)
+ errno = -rc;
return UINT_MAX;
}
@@ -1769,6 +1784,7 @@ NDCTL_EXPORT int ndctl_dimm_is_flag_supported(struct ndctl_dimm *dimm,
NDCTL_EXPORT unsigned int ndctl_dimm_get_event_flags(struct ndctl_dimm *dimm)
{
+ int rc;
struct ndctl_cmd *cmd = NULL;
unsigned int alarm_flags, event_flags = 0;
struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
@@ -1779,9 +1795,12 @@ NDCTL_EXPORT unsigned int ndctl_dimm_get_event_flags(struct ndctl_dimm *dimm)
err(ctx, "%s: no smart command support\n", devname);
return UINT_MAX;
}
- if (ndctl_cmd_submit(cmd)) {
+ rc = ndctl_cmd_submit(cmd);
+ if (rc) {
err(ctx, "%s: smart command failed\n", devname);
ndctl_cmd_unref(cmd);
+ if (rc < 0)
+ errno = -rc;
return UINT_MAX;
}
@@ -2166,7 +2185,7 @@ NDCTL_EXPORT unsigned long long ndctl_region_get_available_size(
unsigned int nstype = ndctl_region_get_nstype(region);
struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
char *path = region->region_buf;
- int len = region->buf_len;
+ int rc, len = region->buf_len;
char buf[SYSFS_ATTR_SIZE];
switch (nstype) {
@@ -2180,11 +2199,15 @@ NDCTL_EXPORT unsigned long long ndctl_region_get_available_size(
if (snprintf(path, len, "%s/available_size", region->region_path) >= len) {
err(ctx, "%s: buffer too small!\n",
ndctl_region_get_devname(region));
+ errno = ENOMEM;
return ULLONG_MAX;
}
- if (sysfs_read_attr(ctx, path, buf) < 0)
+ rc = sysfs_read_attr(ctx, path, buf);
+ if (rc < 0) {
+ errno = -rc;
return ULLONG_MAX;
+ }
return strtoull(buf, NULL, 0);
}
@@ -2195,7 +2218,7 @@ NDCTL_EXPORT unsigned long long ndctl_region_get_max_available_extent(
unsigned int nstype = ndctl_region_get_nstype(region);
struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
char *path = region->region_buf;
- int len = region->buf_len;
+ int rc, len = region->buf_len;
char buf[SYSFS_ATTR_SIZE];
switch (nstype) {
@@ -2210,12 +2233,15 @@ NDCTL_EXPORT unsigned long long ndctl_region_get_max_available_extent(
"%s/max_available_extent", region->region_path) >= len) {
err(ctx, "%s: buffer too small!\n",
ndctl_region_get_devname(region));
+ errno = ENOMEM;
return ULLONG_MAX;
}
/* fall back to legacy behavior if max extents is not exported */
- if (sysfs_read_attr(ctx, path, buf) < 0) {
+ rc = sysfs_read_attr(ctx, path, buf);
+ if (rc < 0) {
dbg(ctx, "max extents attribute not exported on older kernels\n");
+ errno = -rc;
return ULLONG_MAX;
}
@@ -4017,9 +4043,10 @@ NDCTL_EXPORT unsigned int ndctl_namespace_get_supported_sector_size(
if (ndns->lbasize.num == 0)
return 0;
- if (i < 0 || i > ndns->lbasize.num)
+ if (i < 0 || i > ndns->lbasize.num) {
+ errno = EINVAL;
return UINT_MAX;
- else
+ } else
return ndns->lbasize.supported[i];
}
@@ -4428,9 +4455,10 @@ NDCTL_EXPORT unsigned int ndctl_btt_get_id(struct ndctl_btt *btt)
NDCTL_EXPORT unsigned int ndctl_btt_get_supported_sector_size(
struct ndctl_btt *btt, int i)
{
- if (i < 0 || i > btt->lbasize.num)
+ if (i < 0 || i > btt->lbasize.num) {
+ errno = EINVAL;
return UINT_MAX;
- else
+ } else
return btt->lbasize.supported[i];
}
diff --git a/ndctl/lib/msft.c b/ndctl/lib/msft.c
index e15bc07..19453cd 100644
--- a/ndctl/lib/msft.c
+++ b/ndctl/lib/msft.c
@@ -77,8 +77,13 @@ static int msft_smart_valid(struct ndctl_cmd *cmd)
static unsigned int msft_cmd_smart_get_flags(struct ndctl_cmd *cmd)
{
- if (msft_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = msft_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
/* below health data can be retrieved via MSFT _DSM function 11 */
return NDN_MSFT_SMART_HEALTH_VALID |
@@ -103,9 +108,13 @@ static unsigned int msft_cmd_smart_get_health(struct ndctl_cmd *cmd)
{
unsigned int health;
unsigned int num;
+ int rc;
- if (msft_smart_valid(cmd) < 0)
+ rc = msft_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
num = num_set_bit_health(CMD_MSFT_SMART(cmd)->health);
if (num == 0)
@@ -122,16 +131,26 @@ static unsigned int msft_cmd_smart_get_health(struct ndctl_cmd *cmd)
static unsigned int msft_cmd_smart_get_media_temperature(struct ndctl_cmd *cmd)
{
- if (msft_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = msft_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_MSFT_SMART(cmd)->temp * 16;
}
static unsigned int msft_cmd_smart_get_life_used(struct ndctl_cmd *cmd)
{
- if (msft_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = msft_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return 100 - CMD_MSFT_SMART(cmd)->nvm_lifetime;
}
--
2.17.1
2 years, 3 months
[ndctl PATCH] libndctl: set errno for routines that don't return an error status
by Vishal Verma
For routines that return a UINT_MAX or UL{L}ONG_MAX, there isn't a way
to get any information as to what went wrong. Set errno in such routines
so that the callers can get some additional context about the error.
Reported-by: Lukasz Dorau <lukasz.dorau(a)intel.com>
Cc: Dan Williams <dan.j.williams(a)intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma(a)intel.com>
---
ndctl/lib/dimm.c | 8 +++--
ndctl/lib/hpe1.c | 79 +++++++++++++++++++++++++++++++++++++-------
ndctl/lib/inject.c | 2 ++
ndctl/lib/intel.c | 45 +++++++++++++++++++++----
ndctl/lib/libndctl.c | 54 ++++++++++++++++++++++--------
ndctl/lib/msft.c | 27 ++++++++++++---
6 files changed, 177 insertions(+), 38 deletions(-)
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index b3e032e..0299b41 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -565,17 +565,21 @@ NDCTL_EXPORT unsigned long ndctl_dimm_get_available_labels(
{
struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
char *path = dimm->dimm_buf;
- int len = dimm->buf_len;
+ int rc, len = dimm->buf_len;
char buf[20];
if (snprintf(path, len, "%s/available_slots", dimm->dimm_path) >= len) {
err(ctx, "%s: buffer too small!\n",
ndctl_dimm_get_devname(dimm));
+ errno = EOVERFLOW;
return ULONG_MAX;
}
- if (sysfs_read_attr(ctx, path, buf) < 0)
+ rc = sysfs_read_attr(ctx, path, buf);
+ if (rc < 0) {
+ errno = -rc;
return ULONG_MAX;
+ }
return strtoul(buf, NULL, 0);
}
diff --git a/ndctl/lib/hpe1.c b/ndctl/lib/hpe1.c
index dbc1ff0..b26120e 100644
--- a/ndctl/lib/hpe1.c
+++ b/ndctl/lib/hpe1.c
@@ -90,9 +90,13 @@ static unsigned int hpe1_cmd_smart_get_flags(struct ndctl_cmd *cmd)
{
unsigned int hpe1flags;
unsigned int flags;
+ int rc;
- if (hpe1_smart_valid(cmd) < 0)
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
hpe1flags = CMD_HPE1_SMART(cmd)->out_valid_flags;
flags = 0;
@@ -118,9 +122,13 @@ static unsigned int hpe1_cmd_smart_get_health(struct ndctl_cmd *cmd)
{
unsigned char hpe1health;
unsigned int health;
+ int rc;
- if (hpe1_smart_valid(cmd) < 0)
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
hpe1health = CMD_HPE1_SMART(cmd)->stat_summary;
health = 0;
@@ -136,16 +144,26 @@ static unsigned int hpe1_cmd_smart_get_health(struct ndctl_cmd *cmd)
static unsigned int hpe1_cmd_smart_get_media_temperature(struct ndctl_cmd *cmd)
{
- if (hpe1_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_HPE1_SMART(cmd)->curr_temp;
}
static unsigned int hpe1_cmd_smart_get_spares(struct ndctl_cmd *cmd)
{
- if (hpe1_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_HPE1_SMART(cmd)->spare_blocks;
}
@@ -154,9 +172,13 @@ static unsigned int hpe1_cmd_smart_get_alarm_flags(struct ndctl_cmd *cmd)
{
unsigned int hpe1flags;
unsigned int flags;
+ int rc;
- if (hpe1_smart_valid(cmd) < 0)
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
hpe1flags = CMD_HPE1_SMART(cmd)->alarm_trips;
flags = 0;
@@ -170,8 +192,13 @@ static unsigned int hpe1_cmd_smart_get_alarm_flags(struct ndctl_cmd *cmd)
static unsigned int hpe1_cmd_smart_get_life_used(struct ndctl_cmd *cmd)
{
- if (hpe1_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_HPE1_SMART(cmd)->device_life;
}
@@ -179,9 +206,13 @@ static unsigned int hpe1_cmd_smart_get_life_used(struct ndctl_cmd *cmd)
static unsigned int hpe1_cmd_smart_get_shutdown_state(struct ndctl_cmd *cmd)
{
unsigned int shutdown;
+ int rc;
- if (hpe1_smart_valid(cmd) < 0)
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
shutdown = CMD_HPE1_SMART(cmd)->last_shutdown_stat;
if (shutdown == NDN_HPE1_SMART_LASTSAVEGOOD)
@@ -192,16 +223,26 @@ static unsigned int hpe1_cmd_smart_get_shutdown_state(struct ndctl_cmd *cmd)
static unsigned int hpe1_cmd_smart_get_vendor_size(struct ndctl_cmd *cmd)
{
- if (hpe1_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_HPE1_SMART(cmd)->vndr_spec_data_size;
}
static unsigned char *hpe1_cmd_smart_get_vendor_data(struct ndctl_cmd *cmd)
{
- if (hpe1_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return NULL;
+ }
return CMD_HPE1_SMART(cmd)->vnd_spec_data;
}
@@ -265,9 +306,13 @@ static unsigned int hpe1_cmd_smart_threshold_get_alarm_control(struct ndctl_cmd
{
unsigned int hpe1flags;
unsigned int flags;
+ int rc;
- if (hpe1_smart_threshold_valid(cmd) < 0)
+ rc = hpe1_smart_threshold_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
hpe1flags = CMD_HPE1_SMART_THRESH(cmd)->threshold_alarm_ctl;
flags = 0;
@@ -282,16 +327,26 @@ static unsigned int hpe1_cmd_smart_threshold_get_alarm_control(struct ndctl_cmd
static unsigned int hpe1_cmd_smart_threshold_get_media_temperature(
struct ndctl_cmd *cmd)
{
- if (hpe1_smart_threshold_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_threshold_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_HPE1_SMART_THRESH(cmd)->temp_threshold;
}
static unsigned int hpe1_cmd_smart_threshold_get_spares(struct ndctl_cmd *cmd)
{
- if (hpe1_smart_threshold_valid(cmd) < 0)
+ int rc;
+
+ rc = hpe1_smart_threshold_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_HPE1_SMART_THRESH(cmd)->spare_block_threshold;
}
diff --git a/ndctl/lib/inject.c b/ndctl/lib/inject.c
index 268c5cd..2b0702e 100644
--- a/ndctl/lib/inject.c
+++ b/ndctl/lib/inject.c
@@ -498,6 +498,7 @@ NDCTL_EXPORT unsigned long long ndctl_bb_get_block(struct ndctl_bb *bb)
{
if (bb)
return bb->block;
+ errno = EINVAL;
return ULLONG_MAX;
}
@@ -505,5 +506,6 @@ NDCTL_EXPORT unsigned long long ndctl_bb_get_count(struct ndctl_bb *bb)
{
if (bb)
return bb->count;
+ errno = EINVAL;
return ULLONG_MAX;
}
diff --git a/ndctl/lib/intel.c b/ndctl/lib/intel.c
index 0abea1e..744386f 100644
--- a/ndctl/lib/intel.c
+++ b/ndctl/lib/intel.c
@@ -85,8 +85,12 @@ static int intel_smart_valid(struct ndctl_cmd *cmd)
#define intel_smart_get_field(cmd, field) \
static unsigned int intel_cmd_smart_get_##field(struct ndctl_cmd *cmd) \
{ \
- if (intel_smart_valid(cmd) < 0) \
+ int rc; \
+ rc = intel_smart_valid(cmd); \
+ if (rc < 0) { \
+ errno = -rc; \
return UINT_MAX; \
+ } \
return cmd->intel->smart.field; \
}
@@ -173,8 +177,12 @@ static int intel_smart_threshold_valid(struct ndctl_cmd *cmd)
static unsigned int intel_cmd_smart_threshold_get_##field( \
struct ndctl_cmd *cmd) \
{ \
- if (intel_smart_threshold_valid(cmd) < 0) \
+ int rc; \
+ rc = intel_smart_threshold_valid(cmd); \
+ if (rc < 0) { \
+ errno = -rc; \
return UINT_MAX; \
+ } \
return cmd->intel->thresh.field; \
}
@@ -431,8 +439,12 @@ static int intel_fw_get_info_valid(struct ndctl_cmd *cmd)
static unsigned int intel_cmd_fw_info_get_##field( \
struct ndctl_cmd *cmd) \
{ \
- if (intel_fw_get_info_valid(cmd) < 0) \
+ int rc; \
+ rc = intel_fw_get_info_valid(cmd); \
+ if (rc < 0) { \
+ errno = -rc; \
return UINT_MAX; \
+ } \
return cmd->intel->info.field; \
}
@@ -440,8 +452,12 @@ static unsigned int intel_cmd_fw_info_get_##field( \
static unsigned long long intel_cmd_fw_info_get_##field( \
struct ndctl_cmd *cmd) \
{ \
- if (intel_fw_get_info_valid(cmd) < 0) \
+ int rc; \
+ rc = intel_fw_get_info_valid(cmd); \
+ if (rc < 0) { \
+ errno = -rc; \
return ULLONG_MAX; \
+ } \
return cmd->intel->info.field; \
}
@@ -454,8 +470,13 @@ intel_fw_info_get_field64(cmd, run_version);
static unsigned long long intel_cmd_fw_info_get_updated_version(
struct ndctl_cmd *cmd)
{
- if (intel_fw_get_info_valid(cmd) < 0)
+ int rc;
+
+ rc = intel_fw_get_info_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return ULLONG_MAX;
+ }
return cmd->intel->info.updated_version;
}
@@ -488,8 +509,13 @@ static int intel_fw_start_valid(struct ndctl_cmd *cmd)
static unsigned int intel_cmd_fw_start_get_context(struct ndctl_cmd *cmd)
{
- if (intel_fw_start_valid(cmd) < 0)
+ int rc;
+
+ rc = intel_fw_start_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return cmd->intel->start.context;
}
@@ -580,8 +606,13 @@ static int intel_fw_fquery_valid(struct ndctl_cmd *cmd)
static unsigned long long
intel_cmd_fw_fquery_get_fw_rev(struct ndctl_cmd *cmd)
{
- if (intel_fw_fquery_valid(cmd) < 0)
+ int rc;
+
+ rc = intel_fw_fquery_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return ULLONG_MAX;
+ }
return cmd->intel->fquery.updated_fw_rev;
}
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 4ceb70e..1506e53 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -1112,12 +1112,15 @@ NDCTL_EXPORT unsigned long long ndctl_region_get_resource(struct ndctl_region *r
if (snprintf(path, len, "%s/resource", region->region_path) >= len) {
err(ctx, "%s: buffer too small!\n",
ndctl_region_get_devname(region));
+ errno = EOVERFLOW;
return ULLONG_MAX;
}
rc = sysfs_read_attr(ctx, path, buf);
- if (rc < 0)
+ if (rc < 0) {
+ errno = -rc;
return ULLONG_MAX;
+ }
return strtoull(buf, NULL, 0);
}
@@ -1256,9 +1259,13 @@ NDCTL_EXPORT unsigned int ndctl_bus_get_scrub_count(struct ndctl_bus *bus)
{
unsigned int scrub_count = 0;
bool active = false;
+ int rc;
- if (__ndctl_bus_get_scrub_state(bus, &scrub_count, &active))
+ rc = __ndctl_bus_get_scrub_state(bus, &scrub_count, &active);
+ if (rc) {
+ errno = -rc;
return UINT_MAX;
+ }
return scrub_count;
}
@@ -1720,15 +1727,19 @@ NDCTL_EXPORT unsigned int ndctl_dimm_get_health(struct ndctl_dimm *dimm)
unsigned int health;
struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
const char *devname = ndctl_dimm_get_devname(dimm);
+ int rc;
cmd = ndctl_dimm_cmd_new_smart(dimm);
if (!cmd) {
err(ctx, "%s: no smart command support\n", devname);
return UINT_MAX;
}
- if (ndctl_cmd_submit(cmd)) {
+ rc = ndctl_cmd_submit(cmd);
+ if (rc) {
err(ctx, "%s: smart command failed\n", devname);
ndctl_cmd_unref(cmd);
+ if (rc < 0)
+ errno = -rc;
return UINT_MAX;
}
@@ -1743,15 +1754,19 @@ NDCTL_EXPORT unsigned int ndctl_dimm_get_flags(struct ndctl_dimm *dimm)
unsigned int flags;
struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
const char *devname = ndctl_dimm_get_devname(dimm);
+ int rc;
cmd = ndctl_dimm_cmd_new_smart(dimm);
if (!cmd) {
dbg(ctx, "%s: no smart command support\n", devname);
return UINT_MAX;
}
- if (ndctl_cmd_submit(cmd)) {
+ rc = ndctl_cmd_submit(cmd);
+ if (rc) {
dbg(ctx, "%s: smart command failed\n", devname);
ndctl_cmd_unref(cmd);
+ if (rc < 0)
+ errno = -rc;
return UINT_MAX;
}
@@ -1769,6 +1784,7 @@ NDCTL_EXPORT int ndctl_dimm_is_flag_supported(struct ndctl_dimm *dimm,
NDCTL_EXPORT unsigned int ndctl_dimm_get_event_flags(struct ndctl_dimm *dimm)
{
+ int rc;
struct ndctl_cmd *cmd = NULL;
unsigned int alarm_flags, event_flags = 0;
struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
@@ -1779,9 +1795,12 @@ NDCTL_EXPORT unsigned int ndctl_dimm_get_event_flags(struct ndctl_dimm *dimm)
err(ctx, "%s: no smart command support\n", devname);
return UINT_MAX;
}
- if (ndctl_cmd_submit(cmd)) {
+ rc = ndctl_cmd_submit(cmd);
+ if (rc) {
err(ctx, "%s: smart command failed\n", devname);
ndctl_cmd_unref(cmd);
+ if (rc < 0)
+ errno = -rc;
return UINT_MAX;
}
@@ -2166,7 +2185,7 @@ NDCTL_EXPORT unsigned long long ndctl_region_get_available_size(
unsigned int nstype = ndctl_region_get_nstype(region);
struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
char *path = region->region_buf;
- int len = region->buf_len;
+ int rc, len = region->buf_len;
char buf[SYSFS_ATTR_SIZE];
switch (nstype) {
@@ -2180,11 +2199,15 @@ NDCTL_EXPORT unsigned long long ndctl_region_get_available_size(
if (snprintf(path, len, "%s/available_size", region->region_path) >= len) {
err(ctx, "%s: buffer too small!\n",
ndctl_region_get_devname(region));
+ errno = EOVERFLOW;
return ULLONG_MAX;
}
- if (sysfs_read_attr(ctx, path, buf) < 0)
+ rc = sysfs_read_attr(ctx, path, buf);
+ if (rc < 0) {
+ errno = -rc;
return ULLONG_MAX;
+ }
return strtoull(buf, NULL, 0);
}
@@ -2195,7 +2218,7 @@ NDCTL_EXPORT unsigned long long ndctl_region_get_max_available_extent(
unsigned int nstype = ndctl_region_get_nstype(region);
struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
char *path = region->region_buf;
- int len = region->buf_len;
+ int rc, len = region->buf_len;
char buf[SYSFS_ATTR_SIZE];
switch (nstype) {
@@ -2210,12 +2233,15 @@ NDCTL_EXPORT unsigned long long ndctl_region_get_max_available_extent(
"%s/max_available_extent", region->region_path) >= len) {
err(ctx, "%s: buffer too small!\n",
ndctl_region_get_devname(region));
+ errno = EOVERFLOW;
return ULLONG_MAX;
}
/* fall back to legacy behavior if max extents is not exported */
- if (sysfs_read_attr(ctx, path, buf) < 0) {
+ rc = sysfs_read_attr(ctx, path, buf);
+ if (rc < 0) {
dbg(ctx, "max extents attribute not exported on older kernels\n");
+ errno = -rc;
return ULLONG_MAX;
}
@@ -4017,9 +4043,10 @@ NDCTL_EXPORT unsigned int ndctl_namespace_get_supported_sector_size(
if (ndns->lbasize.num == 0)
return 0;
- if (i < 0 || i > ndns->lbasize.num)
+ if (i < 0 || i > ndns->lbasize.num) {
+ errno = EINVAL;
return UINT_MAX;
- else
+ } else
return ndns->lbasize.supported[i];
}
@@ -4428,9 +4455,10 @@ NDCTL_EXPORT unsigned int ndctl_btt_get_id(struct ndctl_btt *btt)
NDCTL_EXPORT unsigned int ndctl_btt_get_supported_sector_size(
struct ndctl_btt *btt, int i)
{
- if (i < 0 || i > btt->lbasize.num)
+ if (i < 0 || i > btt->lbasize.num) {
+ errno = EINVAL;
return UINT_MAX;
- else
+ } else
return btt->lbasize.supported[i];
}
diff --git a/ndctl/lib/msft.c b/ndctl/lib/msft.c
index e15bc07..19453cd 100644
--- a/ndctl/lib/msft.c
+++ b/ndctl/lib/msft.c
@@ -77,8 +77,13 @@ static int msft_smart_valid(struct ndctl_cmd *cmd)
static unsigned int msft_cmd_smart_get_flags(struct ndctl_cmd *cmd)
{
- if (msft_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = msft_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
/* below health data can be retrieved via MSFT _DSM function 11 */
return NDN_MSFT_SMART_HEALTH_VALID |
@@ -103,9 +108,13 @@ static unsigned int msft_cmd_smart_get_health(struct ndctl_cmd *cmd)
{
unsigned int health;
unsigned int num;
+ int rc;
- if (msft_smart_valid(cmd) < 0)
+ rc = msft_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
num = num_set_bit_health(CMD_MSFT_SMART(cmd)->health);
if (num == 0)
@@ -122,16 +131,26 @@ static unsigned int msft_cmd_smart_get_health(struct ndctl_cmd *cmd)
static unsigned int msft_cmd_smart_get_media_temperature(struct ndctl_cmd *cmd)
{
- if (msft_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = msft_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return CMD_MSFT_SMART(cmd)->temp * 16;
}
static unsigned int msft_cmd_smart_get_life_used(struct ndctl_cmd *cmd)
{
- if (msft_smart_valid(cmd) < 0)
+ int rc;
+
+ rc = msft_smart_valid(cmd);
+ if (rc < 0) {
+ errno = -rc;
return UINT_MAX;
+ }
return 100 - CMD_MSFT_SMART(cmd)->nvm_lifetime;
}
--
2.17.1
2 years, 3 months
RE.Enquiry
by Mr. Emi Kikuchi Tatsumi Marine Co. Ltd.
Dear Sirs,
Here is our attached open invoice.
Please check it, we need your reply and confirmation by return.
Before we arrange remittance tomorrow.
Thanks and best regards,
Mr. Emi Kikuchi
Tatsumi Marine Co. Ltd.
Adress : Tatsumi Building. 3rd Floor 3-8-7, Iidabashi,
Chiyoda-ku Tokyo 102-0072, Japan
Tel : +81 3 3265 5216
Fax : +81 3 3265 5315
mobile: +81 90 7007 5979
E-mail : operation(a)tatsumimarine.co.jp (General)
E-mail: e-kikuchi(a)tatsumimarine.co.jp (Personal)
E-mail: ekikuchi-tatsumimarine(a)docomo.ne.jp (mobile)
2 years, 3 months
[PATCH] ndctl, check-labels: correct check-labels message wording
by Robert Elliott
ndctl check-labels prints the number of labels, not the number of
nmems. Changed the print for:
$ ndctl check-labels nmem0 nmem1
from:
successfully verified 510 nmems
to:
successfully verified 510 nmem labels
Signed-off-by: Robert Elliott <elliott(a)hpe.com>
---
ndctl/dimm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index a4203f3..699ab57 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -1147,7 +1147,7 @@ int cmd_check_labels(int argc, const char **argv, void *ctx)
int count = dimm_action(argc, argv, ctx, action_check, base_options,
"ndctl check-labels <nmem0> [<nmem1>..<nmemN>] [<options>]");
- fprintf(stderr, "successfully verified %d nmem%s\n",
+ fprintf(stderr, "successfully verified %d nmem label%s\n",
count >= 0 ? count : 0, count > 1 ? "s" : "");
return count >= 0 ? 0 : EXIT_FAILURE;
}
--
2.14.4
2 years, 3 months
[ndctl PATCH v2 1/5] ndctl, lib: refactor badblocks retrieval routines
by Vishal Verma
From: Dan Williams <dan.j.williams(a)intel.com>
The kernel provides two locations in sysfs that contain badblocks
information. The only one ndctl currently uses is region based
badblocks. The problem with this is that this requires root privileges
to calculate namespace-offset badblocks. Since the kernel already
provides a world readable location for namespace badblocks, we can fall
back to that.
Refactor the badblocks retrieval routines to use a bb_iter structure
that contains information for what badblocks file in sysfs to use, to
prepare for a direct namespace-badblocks fallback.
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
[vishal] remove an error print triggered by opening an invalid file
Signed-off-by: Vishal Verma <vishal.l.verma(a)intel.com>
---
ndctl/lib/libndctl.c | 141 +++++++++++++++++++++++--------------------
ndctl/lib/private.h | 6 ++
2 files changed, 82 insertions(+), 65 deletions(-)
No changes since v1
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 481b110..d58be47 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -178,8 +178,7 @@ struct ndctl_region {
int state;
unsigned long long cookie;
} iset;
- FILE *badblocks;
- struct badblock bb;
+ struct badblocks_iter bb_iter;
enum ndctl_persistence_domain persistence_domain;
/* file descriptor for deep flush sysfs entry */
int flush_fd;
@@ -376,6 +375,77 @@ NDCTL_EXPORT struct ndctl_ctx *ndctl_ref(struct ndctl_ctx *ctx)
return ctx;
}
+static void badblocks_iter_free(struct badblocks_iter *bb_iter)
+{
+ if (bb_iter->file)
+ fclose(bb_iter->file);
+}
+
+static int badblocks_iter_init(struct badblocks_iter *bb_iter, const char *path)
+{
+ char *bb_path;
+ int rc = 0;
+
+ /* if the file is already open */
+ if (bb_iter->file) {
+ fclose(bb_iter->file);
+ bb_iter->file = NULL;
+ }
+
+ if (asprintf(&bb_path, "%s/badblocks", path) < 0)
+ return -errno;
+
+ bb_iter->file = fopen(bb_path, "re");
+ if (!bb_iter->file) {
+ rc = -errno;
+ free(bb_path);
+ return rc;
+ }
+
+ free(bb_path);
+ return rc;
+}
+
+static struct badblock *badblocks_iter_next(struct badblocks_iter *bb_iter)
+{
+ int rc;
+ char *buf = NULL;
+ size_t rlen = 0;
+
+ if (!bb_iter->file)
+ return NULL;
+
+ rc = getline(&buf, &rlen, bb_iter->file);
+ if (rc == -1) {
+ free(buf);
+ return NULL;
+ }
+
+ rc = sscanf(buf, "%llu %u", &bb_iter->bb.offset, &bb_iter->bb.len);
+ free(buf);
+ if (rc != 2) {
+ fclose(bb_iter->file);
+ bb_iter->file = NULL;
+ bb_iter->bb.offset = 0;
+ bb_iter->bb.len = 0;
+ return NULL;
+ }
+
+ return &bb_iter->bb;
+}
+
+static struct badblock *badblocks_iter_first(struct badblocks_iter *bb_iter,
+ struct ndctl_ctx *ctx, const char *path)
+{
+ int rc;
+
+ rc = badblocks_iter_init(bb_iter, path);
+ if (rc < 0)
+ return NULL;
+
+ return badblocks_iter_next(bb_iter);
+}
+
static void free_namespace(struct ndctl_namespace *ndns, struct list_head *head)
{
struct ndctl_bb *bb, *next;
@@ -511,8 +581,7 @@ static void free_region(struct ndctl_region *region)
kmod_module_unref(region->module);
free(region->region_buf);
free(region->region_path);
- if (region->badblocks)
- fclose(region->badblocks);
+ badblocks_iter_free(®ion->bb_iter);
if (region->flush_fd > 0)
close(region->flush_fd);
free(region);
@@ -2253,73 +2322,15 @@ NDCTL_EXPORT int ndctl_region_get_numa_node(struct ndctl_region *region)
return region->numa_node;
}
-static int regions_badblocks_init(struct ndctl_region *region)
-{
- struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
- char *bb_path;
- int rc = 0;
-
- /* if the file is already open */
- if (region->badblocks) {
- fclose(region->badblocks);
- region->badblocks = NULL;
- }
-
- if (asprintf(&bb_path, "%s/badblocks",
- region->region_path) < 0) {
- rc = -errno;
- err(ctx, "region badblocks path allocation failure\n");
- return rc;
- }
-
- region->badblocks = fopen(bb_path, "re");
- if (!region->badblocks) {
- rc = -errno;
- free(bb_path);
- return rc;
- }
-
- free(bb_path);
- return rc;
-}
-
NDCTL_EXPORT struct badblock *ndctl_region_get_next_badblock(struct ndctl_region *region)
{
- int rc;
- char *buf = NULL;
- size_t rlen = 0;
-
- if (!region->badblocks)
- return NULL;
-
- rc = getline(&buf, &rlen, region->badblocks);
- if (rc == -1) {
- free(buf);
- return NULL;
- }
-
- rc = sscanf(buf, "%llu %u", ®ion->bb.offset, ®ion->bb.len);
- free(buf);
- if (rc != 2) {
- fclose(region->badblocks);
- region->badblocks = NULL;
- region->bb.offset = 0;
- region->bb.len = 0;
- return NULL;
- }
-
- return ®ion->bb;
+ return badblocks_iter_next(®ion->bb_iter);
}
NDCTL_EXPORT struct badblock *ndctl_region_get_first_badblock(struct ndctl_region *region)
{
- int rc;
-
- rc = regions_badblocks_init(region);
- if (rc < 0)
- return NULL;
-
- return ndctl_region_get_next_badblock(region);
+ return badblocks_iter_first(®ion->bb_iter,
+ ndctl_region_get_ctx(region), region->region_path);
}
NDCTL_EXPORT enum ndctl_persistence_domain
diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
index b6e438a..d8ed614 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -185,6 +185,11 @@ struct ndctl_lbasize {
int num;
};
+struct badblocks_iter {
+ struct badblock bb;
+ FILE *file;
+};
+
/**
* struct ndctl_namespace - device claimed by the nd_blk or nd_pmem driver
* @module: kernel module
@@ -209,6 +214,7 @@ struct ndctl_namespace {
int generation;
unsigned long long resource, size;
enum ndctl_namespace_mode enforce_mode;
+ struct badblocks_iter bb_iter;
char *alt_name;
uuid_t uuid;
struct ndctl_lbasize lbasize;
--
2.17.1
2 years, 3 months
[ndctl PATCH 1/5] ndctl, lib: refactor badblocks retrieval routines
by Vishal Verma
From: Dan Williams <dan.j.williams(a)intel.com>
From: Dan Williams <dan.j.williams(a)intel.com>
The kernel provides two locations in sysfs that contain badblocks
information. The only one ndctl currently uses is region based
badblocks. The problem with this is that this requires root privileges
to calculate namespace-offset badblocks. Since the kernel already
provides a world readable location for namespace badblocks, we can fall
back to that.
Refactor the badblocks retrieval routines to use a bb_iter structure
that contains information for what badblocks file in sysfs to use, to
prepare for a direct namespace-badblocks fallback.
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
[vishal] remove an error print triggered by opening an invalid file
Signed-off-by: Vishal Verma <vishal.l.verma(a)intel.com>
---
ndctl/lib/libndctl.c | 141 +++++++++++++++++++++++--------------------
ndctl/lib/private.h | 6 ++
2 files changed, 82 insertions(+), 65 deletions(-)
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 481b110..d58be47 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -178,8 +178,7 @@ struct ndctl_region {
int state;
unsigned long long cookie;
} iset;
- FILE *badblocks;
- struct badblock bb;
+ struct badblocks_iter bb_iter;
enum ndctl_persistence_domain persistence_domain;
/* file descriptor for deep flush sysfs entry */
int flush_fd;
@@ -376,6 +375,77 @@ NDCTL_EXPORT struct ndctl_ctx *ndctl_ref(struct ndctl_ctx *ctx)
return ctx;
}
+static void badblocks_iter_free(struct badblocks_iter *bb_iter)
+{
+ if (bb_iter->file)
+ fclose(bb_iter->file);
+}
+
+static int badblocks_iter_init(struct badblocks_iter *bb_iter, const char *path)
+{
+ char *bb_path;
+ int rc = 0;
+
+ /* if the file is already open */
+ if (bb_iter->file) {
+ fclose(bb_iter->file);
+ bb_iter->file = NULL;
+ }
+
+ if (asprintf(&bb_path, "%s/badblocks", path) < 0)
+ return -errno;
+
+ bb_iter->file = fopen(bb_path, "re");
+ if (!bb_iter->file) {
+ rc = -errno;
+ free(bb_path);
+ return rc;
+ }
+
+ free(bb_path);
+ return rc;
+}
+
+static struct badblock *badblocks_iter_next(struct badblocks_iter *bb_iter)
+{
+ int rc;
+ char *buf = NULL;
+ size_t rlen = 0;
+
+ if (!bb_iter->file)
+ return NULL;
+
+ rc = getline(&buf, &rlen, bb_iter->file);
+ if (rc == -1) {
+ free(buf);
+ return NULL;
+ }
+
+ rc = sscanf(buf, "%llu %u", &bb_iter->bb.offset, &bb_iter->bb.len);
+ free(buf);
+ if (rc != 2) {
+ fclose(bb_iter->file);
+ bb_iter->file = NULL;
+ bb_iter->bb.offset = 0;
+ bb_iter->bb.len = 0;
+ return NULL;
+ }
+
+ return &bb_iter->bb;
+}
+
+static struct badblock *badblocks_iter_first(struct badblocks_iter *bb_iter,
+ struct ndctl_ctx *ctx, const char *path)
+{
+ int rc;
+
+ rc = badblocks_iter_init(bb_iter, path);
+ if (rc < 0)
+ return NULL;
+
+ return badblocks_iter_next(bb_iter);
+}
+
static void free_namespace(struct ndctl_namespace *ndns, struct list_head *head)
{
struct ndctl_bb *bb, *next;
@@ -511,8 +581,7 @@ static void free_region(struct ndctl_region *region)
kmod_module_unref(region->module);
free(region->region_buf);
free(region->region_path);
- if (region->badblocks)
- fclose(region->badblocks);
+ badblocks_iter_free(®ion->bb_iter);
if (region->flush_fd > 0)
close(region->flush_fd);
free(region);
@@ -2253,73 +2322,15 @@ NDCTL_EXPORT int ndctl_region_get_numa_node(struct ndctl_region *region)
return region->numa_node;
}
-static int regions_badblocks_init(struct ndctl_region *region)
-{
- struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
- char *bb_path;
- int rc = 0;
-
- /* if the file is already open */
- if (region->badblocks) {
- fclose(region->badblocks);
- region->badblocks = NULL;
- }
-
- if (asprintf(&bb_path, "%s/badblocks",
- region->region_path) < 0) {
- rc = -errno;
- err(ctx, "region badblocks path allocation failure\n");
- return rc;
- }
-
- region->badblocks = fopen(bb_path, "re");
- if (!region->badblocks) {
- rc = -errno;
- free(bb_path);
- return rc;
- }
-
- free(bb_path);
- return rc;
-}
-
NDCTL_EXPORT struct badblock *ndctl_region_get_next_badblock(struct ndctl_region *region)
{
- int rc;
- char *buf = NULL;
- size_t rlen = 0;
-
- if (!region->badblocks)
- return NULL;
-
- rc = getline(&buf, &rlen, region->badblocks);
- if (rc == -1) {
- free(buf);
- return NULL;
- }
-
- rc = sscanf(buf, "%llu %u", ®ion->bb.offset, ®ion->bb.len);
- free(buf);
- if (rc != 2) {
- fclose(region->badblocks);
- region->badblocks = NULL;
- region->bb.offset = 0;
- region->bb.len = 0;
- return NULL;
- }
-
- return ®ion->bb;
+ return badblocks_iter_next(®ion->bb_iter);
}
NDCTL_EXPORT struct badblock *ndctl_region_get_first_badblock(struct ndctl_region *region)
{
- int rc;
-
- rc = regions_badblocks_init(region);
- if (rc < 0)
- return NULL;
-
- return ndctl_region_get_next_badblock(region);
+ return badblocks_iter_first(®ion->bb_iter,
+ ndctl_region_get_ctx(region), region->region_path);
}
NDCTL_EXPORT enum ndctl_persistence_domain
diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
index b6e438a..d8ed614 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -185,6 +185,11 @@ struct ndctl_lbasize {
int num;
};
+struct badblocks_iter {
+ struct badblock bb;
+ FILE *file;
+};
+
/**
* struct ndctl_namespace - device claimed by the nd_blk or nd_pmem driver
* @module: kernel module
@@ -209,6 +214,7 @@ struct ndctl_namespace {
int generation;
unsigned long long resource, size;
enum ndctl_namespace_mode enforce_mode;
+ struct badblocks_iter bb_iter;
char *alt_name;
uuid_t uuid;
struct ndctl_lbasize lbasize;
--
2.17.1
2 years, 3 months
[ndctl PATCH v3 0/3] Replace udev rule for latch and dirty-shutdown-count
by Dan Williams
Changes since v2 [1]:
* Drop the 'dirty-dimm' command
* Add ndctl_dimm_get_dirty_shutdown() api
[1]: https://lists.01.org/pipermail/linux-nvdimm/2018-September/017890.html
---
The latch mechanism is awkward especially when all that it needed is a
rolling count of dirty-shutdown events. The expectation going forward is
that the platform firmware will handle the latch, if it is present, and
the OS need only consume the dirty-shutdown count. The ndctl
implementation called libndctl apis from the udev queue which we
discovered injects unnecessary udev queue drains / stalls into the boot
path. Lastly, the userspace caching scheme for non-root users to consume
the dirty-shutdown-count just isn't as efficient as teaching the kernel
to cache this value and export it as a standard sysfs attribute.
---
Dan Williams (3):
ndctl, lib: Add dirty-shutdown-count retrieval helper
ndctl: Revert "ndctl, intel: Fallback to smart cached shutdown_count"
ndctl: Revert "ndctl: Create ndctl udev rules for dirty shutdown"
.gitignore | 1
Makefile.am | 3 -
configure.ac | 10 ---
contrib/80-ndctl.rules | 3 -
ndctl.spec.in | 3 -
ndctl/Makefile.am | 5 --
ndctl/lib/intel.c | 41 -------------
ndctl/lib/libndctl.c | 16 ++++-
ndctl/lib/libndctl.sym | 5 ++
ndctl/lib/private.h | 4 -
ndctl/libndctl.h | 1
ndctl/ndctl-udev.c | 150 ------------------------------------------------
test/libndctl.c | 29 +++++++--
13 files changed, 40 insertions(+), 231 deletions(-)
delete mode 100644 contrib/80-ndctl.rules
delete mode 100644 ndctl/ndctl-udev.c
2 years, 3 months
[RFC workqueue/driver-core PATCH 0/5] Add NUMA aware async_schedule calls
by Alexander Duyck
This patch set provides functionality that will help to improve the
locality of the async_schedule calls used to provide deferred
initialization.
This patch set originally started out with me focused on just the one call
to async_schedule_domain in the nvdimm tree that was being used to
defer the device_add call however after doing some digging I realized the
scope of this was much broader than I had originally planned. As such I
went through and reworked the underlying infrastructure down to replacing
the queue_work call itself with a function of my own and opted to try and
provide a NUMA aware solution that would work for a broader audience.
I am submitting this an RFC to figure out just how far off I am from where
I need to be on this patch set and to determine which tree I should
ultimately be submitting this to.
---
Alexander Duyck (5):
workqueue: Provide queue_work_near to queue work near a given NUMA node
async: Add support for queueing on specific NUMA node
driver core: Probe devices asynchronously instead of the driver
driver core: Use new async_schedule_dev command
nvdimm: Schedule device registration on node local to the device
drivers/base/bus.c | 23 +-------
drivers/base/dd.c | 44 +++++++++++++++
drivers/base/power/main.c | 12 ++--
drivers/nvdimm/bus.c | 11 +++-
include/linux/async.h | 27 ++++++++-
include/linux/workqueue.h | 2 +
kernel/async.c | 62 ++++++++++++++++------
kernel/workqueue.c | 129 ++++++++++++++++++++++++++++++++++++++++++++-
8 files changed, 258 insertions(+), 52 deletions(-)
--
2 years, 3 months
[PATCH v2] libnvdimm, dimm: Maximize label transfer size
by Dan Williams
Use kvzalloc() to bypass the arbitrary PAGE_SIZE limit of label transfer
operations. Given the expense of calling into firmware, maximize the
amount of label data we transfer per call to be up to the total label
space if allowed by the firmware, or 256K whichever is smaller.
Cc: Alexander Duyck <alexander.h.duyck(a)linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
Changes in v2:
* clamp the max allocation size at 256K in case large label areas with
unlimited transfer sizes appear in the future.
drivers/nvdimm/dimm_devs.c | 14 ++++++++------
tools/testing/nvdimm/test/nfit.c | 2 +-
2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 863cabc35215..3616e2e47788 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -111,8 +111,9 @@ int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
if (!ndd->data)
return -ENOMEM;
- max_cmd_size = min_t(u32, PAGE_SIZE, ndd->nsarea.max_xfer);
- cmd = kzalloc(max_cmd_size + sizeof(*cmd), GFP_KERNEL);
+ max_cmd_size = min_t(u32, ndd->nsarea.config_size, SZ_256K);
+ max_cmd_size = min_t(u32, max_cmd_size, ndd->nsarea.max_xfer);
+ cmd = kvzalloc(max_cmd_size + sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
@@ -134,7 +135,7 @@ int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
memcpy(ndd->data + offset, cmd->out_buf, cmd->in_length);
}
dev_dbg(ndd->dev, "len: %zu rc: %d\n", offset, rc);
- kfree(cmd);
+ kvfree(cmd);
return rc;
}
@@ -157,9 +158,10 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
if (offset + len > ndd->nsarea.config_size)
return -ENXIO;
- max_cmd_size = min_t(u32, PAGE_SIZE, len);
+ max_cmd_size = min_t(u32, ndd->nsarea.config_size, SZ_256K);
max_cmd_size = min_t(u32, max_cmd_size, ndd->nsarea.max_xfer);
- cmd = kzalloc(max_cmd_size + sizeof(*cmd) + sizeof(u32), GFP_KERNEL);
+ max_cmd_size = min_t(u32, max_cmd_size, len);
+ cmd = kvzalloc(max_cmd_size + sizeof(*cmd) + sizeof(u32), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
@@ -183,7 +185,7 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
break;
}
}
- kfree(cmd);
+ kvfree(cmd);
return rc;
}
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index cffc2c5a778d..caa58d8533f5 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -448,7 +448,7 @@ static int nfit_test_cmd_get_config_size(struct nd_cmd_get_config_size *nd_cmd,
nd_cmd->status = 0;
nd_cmd->config_size = LABEL_SIZE;
- nd_cmd->max_xfer = SZ_4K;
+ nd_cmd->max_xfer = LABEL_SIZE;
return 0;
}
2 years, 3 months