Skip to content

Commit 747ffe1

Browse files
committed
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: <[email protected]> Cc: Vishal Verma <[email protected]> Signed-off-by: Dan Williams <[email protected]>
1 parent 6697b2c commit 747ffe1

File tree

4 files changed

+17
-13
lines changed

4 files changed

+17
-13
lines changed

drivers/acpi/nfit.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,13 +1516,13 @@ static int ars_do_start(struct nvdimm_bus_descriptor *nd_desc,
15161516
}
15171517

15181518
static 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)
15201520
{
15211521
int rc;
15221522

15231523
while (1) {
15241524
rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_STATUS, cmd,
1525-
sizeof(*cmd));
1525+
size);
15261526
if (rc || cmd->status & 0xffff)
15271527
return -ENXIO;
15281528

@@ -1580,6 +1580,7 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
15801580
struct nd_cmd_ars_start *ars_start = NULL;
15811581
struct nd_cmd_ars_cap *ars_cap = NULL;
15821582
u64 start, len, cur, remaining;
1583+
u32 ars_status_size;
15831584
int rc;
15841585

15851586
ars_cap = kzalloc(sizeof(*ars_cap), GFP_KERNEL);
@@ -1609,14 +1610,14 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
16091610
* Check if a full-range ARS has been run. If so, use those results
16101611
* without having to start a new ARS.
16111612
*/
1612-
ars_status = kzalloc(ars_cap->max_ars_out + sizeof(*ars_status),
1613-
GFP_KERNEL);
1613+
ars_status_size = ars_cap->max_ars_out;
1614+
ars_status = kzalloc(ars_status_size, GFP_KERNEL);
16141615
if (!ars_status) {
16151616
rc = -ENOMEM;
16161617
goto out;
16171618
}
16181619

1619-
rc = ars_get_status(nd_desc, ars_status);
1620+
rc = ars_get_status(nd_desc, ars_status, ars_status_size);
16201621
if (rc)
16211622
goto out;
16221623

@@ -1646,7 +1647,7 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
16461647
if (rc)
16471648
goto out;
16481649

1649-
rc = ars_get_status(nd_desc, ars_status);
1650+
rc = ars_get_status(nd_desc, ars_status, ars_status_size);
16501651
if (rc)
16511652
goto out;
16521653

drivers/nvdimm/bus.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,8 @@ static const struct nd_cmd_desc __nd_cmd_bus_descs[] = {
392392
.out_sizes = { 4, },
393393
},
394394
[ND_CMD_ARS_STATUS] = {
395-
.out_num = 2,
396-
.out_sizes = { 4, UINT_MAX, },
395+
.out_num = 3,
396+
.out_sizes = { 4, 4, UINT_MAX, },
397397
},
398398
};
399399

@@ -442,8 +442,8 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
442442
return in_field[1];
443443
else if (nvdimm && cmd == ND_CMD_VENDOR && idx == 2)
444444
return out_field[1];
445-
else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 1)
446-
return ND_CMD_ARS_STATUS_MAX;
445+
else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2)
446+
return out_field[1] - 8;
447447

448448
return UINT_MAX;
449449
}

include/linux/libnvdimm.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ enum {
2828
ND_IOCTL_MAX_BUFLEN = SZ_4M,
2929
ND_CMD_MAX_ELEM = 4,
3030
ND_CMD_MAX_ENVELOPE = 16,
31-
ND_CMD_ARS_STATUS_MAX = SZ_4K,
3231
ND_MAX_MAPPINGS = 32,
3332

3433
/* region flag indicating to direct-map persistent memory by default */

tools/testing/nvdimm/test/nfit.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,13 +217,16 @@ static int nfit_test_cmd_set_config_data(struct nd_cmd_set_config_hdr *nd_cmd,
217217
return rc;
218218
}
219219

220+
#define NFIT_TEST_ARS_RECORDS 4
221+
220222
static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd,
221223
unsigned int buf_len)
222224
{
223225
if (buf_len < sizeof(*nd_cmd))
224226
return -EINVAL;
225227

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);
227230
nd_cmd->status = (ND_ARS_PERSISTENT | ND_ARS_VOLATILE) << 16;
228231

229232
return 0;
@@ -246,7 +249,8 @@ static int nfit_test_cmd_ars_status(struct nd_cmd_ars_status *nd_cmd,
246249
if (buf_len < sizeof(*nd_cmd))
247250
return -EINVAL;
248251

249-
nd_cmd->out_length = 256;
252+
nd_cmd->out_length = sizeof(struct nd_cmd_ars_status);
253+
/* TODO: emit error records */
250254
nd_cmd->num_records = 0;
251255
nd_cmd->address = 0;
252256
nd_cmd->length = -1ULL;

0 commit comments

Comments
 (0)