svn commit: r354648 - head/sys/dev/nvdimm
D Scott Phillips
scottph at FreeBSD.org
Tue Nov 12 16:24:37 UTC 2019
Author: scottph
Date: Tue Nov 12 16:24:37 2019
New Revision: 354648
URL: https://svnweb.freebsd.org/changeset/base/354648
Log:
nvdimm(4): Fix various problems when the using the second label index block
struct nvdimm_label_index is dynamically sized, with the `free`
bitfield expanding to hold `slot_cnt` entries. Fix a few places
where we were treating the struct as though it had a fixed sized.
Reviewed by: cem
Approved by: scottl (mentor)
MFC after: 1 week
Sponsored by: Intel Corporation
Differential Revision: https://reviews.freebsd.org/D22253
Modified:
head/sys/dev/nvdimm/nvdimm.c
Modified: head/sys/dev/nvdimm/nvdimm.c
==============================================================================
--- head/sys/dev/nvdimm/nvdimm.c Tue Nov 12 15:56:27 2019 (r354647)
+++ head/sys/dev/nvdimm/nvdimm.c Tue Nov 12 16:24:37 2019 (r354648)
@@ -183,7 +183,7 @@ label_index_is_valid(struct nvdimm_label_index *index,
{
uint64_t checksum;
- index = (struct nvdimm_label_index *)((uint8_t *)index + offset);
+ index = (struct nvdimm_label_index *)((uint8_t *)index + size * offset);
if (strcmp(index->signature, NVDIMM_INDEX_BLOCK_SIGNATURE) != 0)
return false;
checksum = index->checksum;
@@ -242,7 +242,7 @@ read_label(struct nvdimm_dev *nv, int num)
static int
read_labels(struct nvdimm_dev *nv)
{
- struct nvdimm_label_index *indices;
+ struct nvdimm_label_index *indices, *index1;
size_t bitfield_size, index_size, num_labels;
int error, n;
bool index_0_valid, index_1_valid;
@@ -258,6 +258,7 @@ read_labels(struct nvdimm_dev *nv)
sizeof(struct nvdimm_label);
bitfield_size = roundup2(num_labels, 8) / 8;
indices = malloc(2 * index_size, M_NVDIMM, M_WAITOK);
+ index1 = (void *)((uint8_t *)indices + index_size);
error = read_label_area(nv, (void *)indices, 0, 2 * index_size);
if (error != 0) {
free(indices, M_NVDIMM);
@@ -271,18 +272,29 @@ read_labels(struct nvdimm_dev *nv)
free(indices, M_NVDIMM);
return (ENXIO);
}
- if (index_0_valid && index_1_valid &&
- (indices[1].seq > indices[0].seq ||
- (indices[1].seq == 1 && indices[0].seq == 3)))
- index_0_valid = false;
+ if (index_0_valid && index_1_valid) {
+ if (((int)indices->seq - (int)index1->seq + 3) % 3 == 1) {
+ /* index 0 was more recently updated */
+ index_1_valid = false;
+ } else {
+ /*
+ * either index 1 was more recently updated,
+ * or the sequence numbers are equal, in which
+ * case the specification says the block with
+ * the higher offset is to be treated as valid
+ */
+ index_0_valid = false;
+ }
+ }
nv->label_index = malloc(index_size, M_NVDIMM, M_WAITOK);
- bcopy(indices + (index_0_valid ? 0 : 1), nv->label_index, index_size);
+ bcopy(index_0_valid ? indices : index1, nv->label_index, index_size);
free(indices, M_NVDIMM);
- for (bit_ffc_at((bitstr_t *)nv->label_index->free, 0, num_labels, &n);
- n >= 0;
- bit_ffc_at((bitstr_t *)nv->label_index->free, n + 1, num_labels,
- &n)) {
+ bit_ffc_at((bitstr_t *)nv->label_index->free, 0,
+ nv->label_index->slot_cnt, &n);
+ while (n >= 0) {
read_label(nv, n);
+ bit_ffc_at((bitstr_t *)nv->label_index->free, n + 1,
+ nv->label_index->slot_cnt, &n);
}
return (0);
}
More information about the svn-src-all
mailing list