| From d9cee9f85b22fab88d2b76d2e92b18e3d0e6aa8c Mon Sep 17 00:00:00 2001 |
| From: Dan Williams <dan.j.williams@intel.com> |
| Date: Fri, 30 Jul 2021 09:46:04 -0700 |
| Subject: libnvdimm/region: Fix label activation vs errors |
| |
| From: Dan Williams <dan.j.williams@intel.com> |
| |
| commit d9cee9f85b22fab88d2b76d2e92b18e3d0e6aa8c upstream. |
| |
| There are a few scenarios where init_active_labels() can return without |
| registering deactivate_labels() to run when the region is disabled. In |
| particular label error injection creates scenarios where a DIMM is |
| disabled, but labels on other DIMMs in the region become activated. |
| |
| Arrange for init_active_labels() to always register deactivate_labels(). |
| |
| Reported-by: Krzysztof Kensicki <krzysztof.kensicki@intel.com> |
| Cc: <stable@vger.kernel.org> |
| Fixes: bf9bccc14c05 ("libnvdimm: pmem label sets and namespace instantiation.") |
| Reviewed-by: Jeff Moyer <jmoyer@redhat.com> |
| Link: https://lore.kernel.org/r/162766356450.3223041.1183118139023841447.stgit@dwillia2-desk3.amr.corp.intel.com |
| Signed-off-by: Dan Williams <dan.j.williams@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/nvdimm/namespace_devs.c | 17 +++++++++++------ |
| 1 file changed, 11 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/nvdimm/namespace_devs.c |
| +++ b/drivers/nvdimm/namespace_devs.c |
| @@ -2527,7 +2527,7 @@ static void deactivate_labels(void *regi |
| |
| static int init_active_labels(struct nd_region *nd_region) |
| { |
| - int i; |
| + int i, rc = 0; |
| |
| for (i = 0; i < nd_region->ndr_mappings; i++) { |
| struct nd_mapping *nd_mapping = &nd_region->mapping[i]; |
| @@ -2546,13 +2546,14 @@ static int init_active_labels(struct nd_ |
| else if (test_bit(NDD_LABELING, &nvdimm->flags)) |
| /* fail, labels needed to disambiguate dpa */; |
| else |
| - return 0; |
| + continue; |
| |
| dev_err(&nd_region->dev, "%s: is %s, failing probe\n", |
| dev_name(&nd_mapping->nvdimm->dev), |
| test_bit(NDD_LOCKED, &nvdimm->flags) |
| ? "locked" : "disabled"); |
| - return -ENXIO; |
| + rc = -ENXIO; |
| + goto out; |
| } |
| nd_mapping->ndd = ndd; |
| atomic_inc(&nvdimm->busy); |
| @@ -2586,13 +2587,17 @@ static int init_active_labels(struct nd_ |
| break; |
| } |
| |
| - if (i < nd_region->ndr_mappings) { |
| + if (i < nd_region->ndr_mappings) |
| + rc = -ENOMEM; |
| + |
| +out: |
| + if (rc) { |
| deactivate_labels(nd_region); |
| - return -ENOMEM; |
| + return rc; |
| } |
| |
| return devm_add_action_or_reset(&nd_region->dev, deactivate_labels, |
| - nd_region); |
| + nd_region); |
| } |
| |
| int nd_region_register_namespaces(struct nd_region *nd_region, int *err) |