libnvdimm, namespace: fix btt claim class crash
authorDan Williams <dan.j.williams@intel.com>
Mon, 18 Sep 2017 21:48:58 +0000 (14:48 -0700)
committerDan Williams <dan.j.williams@intel.com>
Tue, 19 Sep 2017 00:29:01 +0000 (17:29 -0700)
Maurice reports:

    BUG: unable to handle kernel NULL pointer dereference at 0000000000000028
    IP: holder_class_store+0x253/0x2b0 [libnvdimm]

...while trying to reconfigure an NVDIMM-N namespace into 'sector' /
'btt' mode. The crash points to this line:

    (gdb) li *(holder_class_store+0x253)
    0x7773 is in holder_class_store (drivers/nvdimm/namespace_devs.c:1420).
    1415            for (i = 0; i < nd_region->ndr_mappings; i++) {
    1416                    struct nd_mapping *nd_mapping = &nd_region->mapping[i];
    1417                    struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
    1418                    struct nd_namespace_index *nsindex;
    1419
    1420                    nsindex = to_namespace_index(ndd, ndd->ns_current);

...where we are failing because ndd is NULL due to NVDIMM-N dimms not
supporting labels.

Long story short, default to the BTTv1 format in the label-less /
NVDIMM-N case.

Fixes: 14e494542636 ("libnvdimm, btt: BTT updates for UEFI 2.7 format")
Cc: <stable@vger.kernel.org>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Reported-by: Maurice A. Saldivar <maurice.a.saldivar@hpe.com>
Tested-by: Maurice A. Saldivar <maurice.a.saldivar@hpe.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/nvdimm/namespace_devs.c

index 1427a38..3e4d1e7 100644 (file)
@@ -1417,6 +1417,15 @@ static int btt_claim_class(struct device *dev)
                struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
                struct nd_namespace_index *nsindex;
 
+               /*
+                * If any of the DIMMs do not support labels the only
+                * possible BTT format is v1.
+                */
+               if (!ndd) {
+                       loop_bitmask = 0;
+                       break;
+               }
+
                nsindex = to_namespace_index(ndd, ndd->ns_current);
                if (nsindex == NULL)
                        loop_bitmask |= 1;