@@ -65,12 +65,16 @@ static unsigned int sizeof_namespace_label(struct nvdimm_data *ndd)
return ndctl_dimm_sizeof_namespace_label(to_dimm(ndd));
}
-static unsigned int sizeof_namespace_index(struct nvdimm_data *ndd)
+static int nvdimm_num_label_slots(struct nvdimm_data *ndd)
{
- u32 index_span;
+ return ndd->config_size / (sizeof_namespace_label(ndd) + 1);
+}
- if (ndd->nsindex_size)
- return ndd->nsindex_size;
+static unsigned int sizeof_namespace_index(struct nvdimm_data *ndd)
+{
+ u32 nslot, space, size;
+ struct ndctl_dimm *dimm = to_dimm(ndd);
+ struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
/*
* The minimum index space is 512 bytes, with that amount of
@@ -80,16 +84,17 @@ static unsigned int sizeof_namespace_index(struct nvdimm_data *ndd)
* starts to waste space at larger config_sizes, but it's
* unlikely we'll ever see anything but 128K.
*/
- index_span = ndd->config_size / (sizeof_namespace_label(ndd) + 1);
- index_span /= NSINDEX_ALIGN * 2;
- ndd->nsindex_size = index_span * NSINDEX_ALIGN;
-
- return ndd->nsindex_size;
-}
-
-static int nvdimm_num_label_slots(struct nvdimm_data *ndd)
-{
- return ndd->config_size / (sizeof_namespace_label(ndd) + 1);
+ nslot = nvdimm_num_label_slots(ndd);
+ space = ndd->config_size - nslot * sizeof_namespace_label(ndd);
+ size = ALIGN(sizeof(struct namespace_index) + ALIGN(nslot, 8) / 8,
+ NSINDEX_ALIGN) * 2;
+ if (size <= space)
+ return size / 2;
+
+ err(ctx, "%s: label area (%ld) too small to host (%d byte) labels\n",
+ ndctl_dimm_get_devname(dimm), ndd->config_size,
+ sizeof_namespace_label(ndd));
+ return 0;
}
static struct namespace_index *to_namespace_index(struct nvdimm_data *ndd,
@@ -356,7 +361,6 @@ static void init_ndd(struct nvdimm_data *ndd, struct ndctl_cmd *cmd_read)
ndctl_cmd_ref(cmd_read);
ndd->data = cmd_read->iter.total_buf;
ndd->config_size = cmd_read->iter.total_xfer;
- ndd->nsindex_size = 0;
ndd->ns_current = -1;
ndd->ns_next = -1;
}
@@ -39,7 +39,6 @@ struct nvdimm_data {
void *data;
unsigned long config_size;
size_t nslabel_size;
- int nsindex_size;
int ns_current, ns_next;
};
The old calculation assumed that the label space was 128k and the label size is 128. With v1.2 labels where the label size is 512 this calculation will return zero. We were previously saved by the fact that the nsindex_size is always pre-initialized from a previous 128 byte assumption and we are lucky that the index sizes turn out the same. However the new 'autolabel' code checked the size without it having been initialized by a previous call where nslabel_size was 128. Fix this going forward in case we start encountering different geometries of label areas besides 128k. Since the label size can change from one call to the next, drop the caching of nsindex_size. Signed-off-by: Dan Williams <dan.j.williams@intel.com> --- ndctl/lib/dimm.c | 34 +++++++++++++++++++--------------- ndctl/lib/private.h | 1 - 2 files changed, 19 insertions(+), 16 deletions(-)