| From bc042fdfbb92b5b13421316b4548e2d6e98eed37 Mon Sep 17 00:00:00 2001 |
| From: Dan Williams <dan.j.williams@intel.com> |
| Date: Mon, 24 Apr 2017 15:43:05 -0700 |
| Subject: [PATCH] libnvdimm, region: fix flush hint detection crash |
| |
| commit bc042fdfbb92b5b13421316b4548e2d6e98eed37 upstream. |
| |
| In the case where a dimm does not have any associated flush hints the |
| ndrd->flush_wpq array may be uninitialized leading to crashes with the |
| following signature: |
| |
| BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 |
| IP: region_visible+0x10f/0x160 [libnvdimm] |
| |
| Call Trace: |
| internal_create_group+0xbe/0x2f0 |
| sysfs_create_groups+0x40/0x80 |
| device_add+0x2d8/0x650 |
| nd_async_device_register+0x12/0x40 [libnvdimm] |
| async_run_entry_fn+0x39/0x170 |
| process_one_work+0x212/0x6c0 |
| ? process_one_work+0x197/0x6c0 |
| worker_thread+0x4e/0x4a0 |
| kthread+0x10c/0x140 |
| ? process_one_work+0x6c0/0x6c0 |
| ? kthread_create_on_node+0x60/0x60 |
| ret_from_fork+0x31/0x40 |
| |
| Cc: <stable@vger.kernel.org> |
| Reviewed-by: Jeff Moyer <jmoyer@redhat.com> |
| Fixes: f284a4f23752 ("libnvdimm: introduce nvdimm_flush() and nvdimm_has_flush()") |
| Signed-off-by: Dan Williams <dan.j.williams@intel.com> |
| |
| diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c |
| index 8de5a04644a1..24abceda986a 100644 |
| --- a/drivers/nvdimm/region_devs.c |
| +++ b/drivers/nvdimm/region_devs.c |
| @@ -1000,17 +1000,20 @@ EXPORT_SYMBOL_GPL(nvdimm_flush); |
| */ |
| int nvdimm_has_flush(struct nd_region *nd_region) |
| { |
| - struct nd_region_data *ndrd = dev_get_drvdata(&nd_region->dev); |
| int i; |
| |
| /* no nvdimm == flushing capability unknown */ |
| if (nd_region->ndr_mappings == 0) |
| return -ENXIO; |
| |
| - for (i = 0; i < nd_region->ndr_mappings; i++) |
| - /* flush hints present, flushing required */ |
| - if (ndrd_get_flush_wpq(ndrd, i, 0)) |
| + for (i = 0; i < nd_region->ndr_mappings; i++) { |
| + struct nd_mapping *nd_mapping = &nd_region->mapping[i]; |
| + struct nvdimm *nvdimm = nd_mapping->nvdimm; |
| + |
| + /* flush hints present / available */ |
| + if (nvdimm->num_flush) |
| return 1; |
| + } |
| |
| /* |
| * The platform defines dimm devices without hints, assume |
| -- |
| 2.12.0 |
| |