aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2016-02-19 18:21:14 -0500
committerDan Williams <dan.j.williams@intel.com>2016-02-19 18:21:52 -0500
commit747ffe11b440ef9ea752888806d3aac677ca52a4 (patch)
tree0f96d8b4c4ef887294ab8be03621053b961d9ee2
parent6697b2cf69d4363266ca47eaebc49ef13dabc1c9 (diff)
libnvdimm, tools/testing/nvdimm: fix 'ars_status' output buffer sizing
Use the output length specified in the command to size the receive buffer rather than the arbitrary 4K limit. This bug was hiding the fact that the ndctl implementation of ndctl_bus_cmd_new_ars_status() was not specifying an output buffer size. Cc: <stable@vger.kernel.org> Cc: Vishal Verma <vishal.l.verma@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--drivers/acpi/nfit.c13
-rw-r--r--drivers/nvdimm/bus.c8
-rw-r--r--include/linux/libnvdimm.h1
-rw-r--r--tools/testing/nvdimm/test/nfit.c8
4 files changed, 17 insertions, 13 deletions
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c
index 424b362e8fdc..1d4b9c6bdf45 100644
--- a/drivers/acpi/nfit.c
+++ b/drivers/acpi/nfit.c
@@ -1516,13 +1516,13 @@ static int ars_do_start(struct nvdimm_bus_descriptor *nd_desc,
1516} 1516}
1517 1517
1518static int ars_get_status(struct nvdimm_bus_descriptor *nd_desc, 1518static int ars_get_status(struct nvdimm_bus_descriptor *nd_desc,
1519 struct nd_cmd_ars_status *cmd) 1519 struct nd_cmd_ars_status *cmd, u32 size)
1520{ 1520{
1521 int rc; 1521 int rc;
1522 1522
1523 while (1) { 1523 while (1) {
1524 rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_STATUS, cmd, 1524 rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_STATUS, cmd,
1525 sizeof(*cmd)); 1525 size);
1526 if (rc || cmd->status & 0xffff) 1526 if (rc || cmd->status & 0xffff)
1527 return -ENXIO; 1527 return -ENXIO;
1528 1528
@@ -1580,6 +1580,7 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
1580 struct nd_cmd_ars_start *ars_start = NULL; 1580 struct nd_cmd_ars_start *ars_start = NULL;
1581 struct nd_cmd_ars_cap *ars_cap = NULL; 1581 struct nd_cmd_ars_cap *ars_cap = NULL;
1582 u64 start, len, cur, remaining; 1582 u64 start, len, cur, remaining;
1583 u32 ars_status_size;
1583 int rc; 1584 int rc;
1584 1585
1585 ars_cap = kzalloc(sizeof(*ars_cap), GFP_KERNEL); 1586 ars_cap = kzalloc(sizeof(*ars_cap), GFP_KERNEL);
@@ -1609,14 +1610,14 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
1609 * Check if a full-range ARS has been run. If so, use those results 1610 * Check if a full-range ARS has been run. If so, use those results
1610 * without having to start a new ARS. 1611 * without having to start a new ARS.
1611 */ 1612 */
1612 ars_status = kzalloc(ars_cap->max_ars_out + sizeof(*ars_status), 1613 ars_status_size = ars_cap->max_ars_out;
1613 GFP_KERNEL); 1614 ars_status = kzalloc(ars_status_size, GFP_KERNEL);
1614 if (!ars_status) { 1615 if (!ars_status) {
1615 rc = -ENOMEM; 1616 rc = -ENOMEM;
1616 goto out; 1617 goto out;
1617 } 1618 }
1618 1619
1619 rc = ars_get_status(nd_desc, ars_status); 1620 rc = ars_get_status(nd_desc, ars_status, ars_status_size);
1620 if (rc) 1621 if (rc)
1621 goto out; 1622 goto out;
1622 1623
@@ -1646,7 +1647,7 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
1646 if (rc) 1647 if (rc)
1647 goto out; 1648 goto out;
1648 1649
1649 rc = ars_get_status(nd_desc, ars_status); 1650 rc = ars_get_status(nd_desc, ars_status, ars_status_size);
1650 if (rc) 1651 if (rc)
1651 goto out; 1652 goto out;
1652 1653
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 7e2c43f701bc..99953b34fa1d 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -392,8 +392,8 @@ static const struct nd_cmd_desc __nd_cmd_bus_descs[] = {
392 .out_sizes = { 4, }, 392 .out_sizes = { 4, },
393 }, 393 },
394 [ND_CMD_ARS_STATUS] = { 394 [ND_CMD_ARS_STATUS] = {
395 .out_num = 2, 395 .out_num = 3,
396 .out_sizes = { 4, UINT_MAX, }, 396 .out_sizes = { 4, 4, UINT_MAX, },
397 }, 397 },
398}; 398};
399 399
@@ -442,8 +442,8 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
442 return in_field[1]; 442 return in_field[1];
443 else if (nvdimm && cmd == ND_CMD_VENDOR && idx == 2) 443 else if (nvdimm && cmd == ND_CMD_VENDOR && idx == 2)
444 return out_field[1]; 444 return out_field[1];
445 else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 1) 445 else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2)
446 return ND_CMD_ARS_STATUS_MAX; 446 return out_field[1] - 8;
447 447
448 return UINT_MAX; 448 return UINT_MAX;
449} 449}
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index bed40dff0e86..c736382fd260 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -28,7 +28,6 @@ enum {
28 ND_IOCTL_MAX_BUFLEN = SZ_4M, 28 ND_IOCTL_MAX_BUFLEN = SZ_4M,
29 ND_CMD_MAX_ELEM = 4, 29 ND_CMD_MAX_ELEM = 4,
30 ND_CMD_MAX_ENVELOPE = 16, 30 ND_CMD_MAX_ENVELOPE = 16,
31 ND_CMD_ARS_STATUS_MAX = SZ_4K,
32 ND_MAX_MAPPINGS = 32, 31 ND_MAX_MAPPINGS = 32,
33 32
34 /* region flag indicating to direct-map persistent memory by default */ 33 /* region flag indicating to direct-map persistent memory by default */
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 90bd2ea41032..b3281dcd4a5d 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -217,13 +217,16 @@ static int nfit_test_cmd_set_config_data(struct nd_cmd_set_config_hdr *nd_cmd,
217 return rc; 217 return rc;
218} 218}
219 219
220#define NFIT_TEST_ARS_RECORDS 4
221
220static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd, 222static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd,
221 unsigned int buf_len) 223 unsigned int buf_len)
222{ 224{
223 if (buf_len < sizeof(*nd_cmd)) 225 if (buf_len < sizeof(*nd_cmd))
224 return -EINVAL; 226 return -EINVAL;
225 227
226 nd_cmd->max_ars_out = 256; 228 nd_cmd->max_ars_out = sizeof(struct nd_cmd_ars_status)
229 + NFIT_TEST_ARS_RECORDS * sizeof(struct nd_ars_record);
227 nd_cmd->status = (ND_ARS_PERSISTENT | ND_ARS_VOLATILE) << 16; 230 nd_cmd->status = (ND_ARS_PERSISTENT | ND_ARS_VOLATILE) << 16;
228 231
229 return 0; 232 return 0;
@@ -246,7 +249,8 @@ static int nfit_test_cmd_ars_status(struct nd_cmd_ars_status *nd_cmd,
246 if (buf_len < sizeof(*nd_cmd)) 249 if (buf_len < sizeof(*nd_cmd))
247 return -EINVAL; 250 return -EINVAL;
248 251
249 nd_cmd->out_length = 256; 252 nd_cmd->out_length = sizeof(struct nd_cmd_ars_status);
253 /* TODO: emit error records */
250 nd_cmd->num_records = 0; 254 nd_cmd->num_records = 0;
251 nd_cmd->address = 0; 255 nd_cmd->address = 0;
252 nd_cmd->length = -1ULL; 256 nd_cmd->length = -1ULL;