Commit 1f13d2f7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'libnvdimm-for-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm

Pull libnvdimm updates from Dan Williams:
 "Twas the day before Christmas and the only thing stirring in libnvdimm
  / device-dax land is a pile of miscellaneous fixups and cleanups.

  The bulk of it has appeared in -next save the last two patches to
  device-dax that have passed my build and unit tests.

   - Fix a long standing block-window-namespace issue surfaced by the
     ndctl change to attempt to preserve the kernel device name over
     a 'reconfigure'

   - Fix a few error path memory leaks in nfit and device-dax

   - Silence a smatch warning in the ioctl path

   - Miscellaneous cleanups"

* tag 'libnvdimm-for-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
  device-dax: Avoid an unnecessary check in alloc_dev_dax_range()
  device-dax: Fix range release
  device-dax: delete a redundancy check in dev_dax_validate_align()
  libnvdimm/label: Return -ENXIO for no slot in __blk_label_update
  device-dax/core: Fix memory leak when rmmod dax.ko
  device-dax/pmem: Convert comma to semicolon
  libnvdimm: Cleanup include of badblocks.h
  ACPI: NFIT: Fix input validation of bus-family
  libnvdimm/namespace: Fix reaping of invalidated block-window-namespace labels
  ACPI/nfit: avoid accessing uninitialized memory in acpi_nfit_ctl()
parents ef2c8b81 127c3d2e
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/list_sort.h> #include <linux/list_sort.h>
#include <linux/libnvdimm.h> #include <linux/libnvdimm.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/nospec.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/ndctl.h> #include <linux/ndctl.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
...@@ -282,18 +283,19 @@ static union acpi_object *pkg_to_buf(union acpi_object *pkg) ...@@ -282,18 +283,19 @@ static union acpi_object *pkg_to_buf(union acpi_object *pkg)
static union acpi_object *int_to_buf(union acpi_object *integer) static union acpi_object *int_to_buf(union acpi_object *integer)
{ {
union acpi_object *buf = ACPI_ALLOCATE(sizeof(*buf) + 4); union acpi_object *buf = NULL;
void *dst = NULL; void *dst = NULL;
if (!buf)
goto err;
if (integer->type != ACPI_TYPE_INTEGER) { if (integer->type != ACPI_TYPE_INTEGER) {
WARN_ONCE(1, "BIOS bug, unexpected element type: %d\n", WARN_ONCE(1, "BIOS bug, unexpected element type: %d\n",
integer->type); integer->type);
goto err; goto err;
} }
buf = ACPI_ALLOCATE(sizeof(*buf) + 4);
if (!buf)
goto err;
dst = buf + 1; dst = buf + 1;
buf->type = ACPI_TYPE_BUFFER; buf->type = ACPI_TYPE_BUFFER;
buf->buffer.length = 4; buf->buffer.length = 4;
...@@ -478,8 +480,11 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, ...@@ -478,8 +480,11 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
cmd_mask = nd_desc->cmd_mask; cmd_mask = nd_desc->cmd_mask;
if (cmd == ND_CMD_CALL && call_pkg->nd_family) { if (cmd == ND_CMD_CALL && call_pkg->nd_family) {
family = call_pkg->nd_family; family = call_pkg->nd_family;
if (!test_bit(family, &nd_desc->bus_family_mask)) if (family > NVDIMM_BUS_FAMILY_MAX ||
!test_bit(family, &nd_desc->bus_family_mask))
return -EINVAL; return -EINVAL;
family = array_index_nospec(family,
NVDIMM_BUS_FAMILY_MAX + 1);
dsm_mask = acpi_desc->family_dsm_mask[family]; dsm_mask = acpi_desc->family_dsm_mask[family];
guid = to_nfit_bus_uuid(family); guid = to_nfit_bus_uuid(family);
} else { } else {
......
...@@ -367,19 +367,28 @@ void kill_dev_dax(struct dev_dax *dev_dax) ...@@ -367,19 +367,28 @@ void kill_dev_dax(struct dev_dax *dev_dax)
} }
EXPORT_SYMBOL_GPL(kill_dev_dax); EXPORT_SYMBOL_GPL(kill_dev_dax);
static void free_dev_dax_ranges(struct dev_dax *dev_dax) static void trim_dev_dax_range(struct dev_dax *dev_dax)
{ {
int i = dev_dax->nr_range - 1;
struct range *range = &dev_dax->ranges[i].range;
struct dax_region *dax_region = dev_dax->region; struct dax_region *dax_region = dev_dax->region;
int i;
device_lock_assert(dax_region->dev); device_lock_assert(dax_region->dev);
for (i = 0; i < dev_dax->nr_range; i++) { dev_dbg(&dev_dax->dev, "delete range[%d]: %#llx:%#llx\n", i,
struct range *range = &dev_dax->ranges[i].range; (unsigned long long)range->start,
(unsigned long long)range->end);
__release_region(&dax_region->res, range->start,
range_len(range)); __release_region(&dax_region->res, range->start, range_len(range));
if (--dev_dax->nr_range == 0) {
kfree(dev_dax->ranges);
dev_dax->ranges = NULL;
} }
dev_dax->nr_range = 0; }
static void free_dev_dax_ranges(struct dev_dax *dev_dax)
{
while (dev_dax->nr_range)
trim_dev_dax_range(dev_dax);
} }
static void unregister_dev_dax(void *dev) static void unregister_dev_dax(void *dev)
...@@ -763,22 +772,14 @@ static int alloc_dev_dax_range(struct dev_dax *dev_dax, u64 start, ...@@ -763,22 +772,14 @@ static int alloc_dev_dax_range(struct dev_dax *dev_dax, u64 start,
return 0; return 0;
} }
ranges = krealloc(dev_dax->ranges, sizeof(*ranges) alloc = __request_region(res, start, size, dev_name(dev), 0);
* (dev_dax->nr_range + 1), GFP_KERNEL); if (!alloc)
if (!ranges)
return -ENOMEM; return -ENOMEM;
alloc = __request_region(res, start, size, dev_name(dev), 0); ranges = krealloc(dev_dax->ranges, sizeof(*ranges)
if (!alloc) { * (dev_dax->nr_range + 1), GFP_KERNEL);
/* if (!ranges) {
* If this was an empty set of ranges nothing else __release_region(res, alloc->start, resource_size(alloc));
* will release @ranges, so do it now.
*/
if (!dev_dax->nr_range) {
kfree(ranges);
ranges = NULL;
}
dev_dax->ranges = ranges;
return -ENOMEM; return -ENOMEM;
} }
...@@ -804,15 +805,10 @@ static int alloc_dev_dax_range(struct dev_dax *dev_dax, u64 start, ...@@ -804,15 +805,10 @@ static int alloc_dev_dax_range(struct dev_dax *dev_dax, u64 start,
return 0; return 0;
rc = devm_register_dax_mapping(dev_dax, dev_dax->nr_range - 1); rc = devm_register_dax_mapping(dev_dax, dev_dax->nr_range - 1);
if (rc) { if (rc)
dev_dbg(dev, "delete range[%d]: %pa:%pa\n", dev_dax->nr_range - 1, trim_dev_dax_range(dev_dax);
&alloc->start, &alloc->end);
dev_dax->nr_range--;
__release_region(res, alloc->start, resource_size(alloc));
return rc;
}
return 0; return rc;
} }
static int adjust_dev_dax_range(struct dev_dax *dev_dax, struct resource *res, resource_size_t size) static int adjust_dev_dax_range(struct dev_dax *dev_dax, struct resource *res, resource_size_t size)
...@@ -885,12 +881,7 @@ static int dev_dax_shrink(struct dev_dax *dev_dax, resource_size_t size) ...@@ -885,12 +881,7 @@ static int dev_dax_shrink(struct dev_dax *dev_dax, resource_size_t size)
if (shrink >= range_len(range)) { if (shrink >= range_len(range)) {
devm_release_action(dax_region->dev, devm_release_action(dax_region->dev,
unregister_dax_mapping, &mapping->dev); unregister_dax_mapping, &mapping->dev);
__release_region(&dax_region->res, range->start, trim_dev_dax_range(dev_dax);
range_len(range));
dev_dax->nr_range--;
dev_dbg(dev, "delete range[%d]: %#llx:%#llx\n", i,
(unsigned long long) range->start,
(unsigned long long) range->end);
to_shrink -= shrink; to_shrink -= shrink;
if (!to_shrink) if (!to_shrink)
break; break;
...@@ -1114,16 +1105,9 @@ static ssize_t align_show(struct device *dev, ...@@ -1114,16 +1105,9 @@ static ssize_t align_show(struct device *dev,
static ssize_t dev_dax_validate_align(struct dev_dax *dev_dax) static ssize_t dev_dax_validate_align(struct dev_dax *dev_dax)
{ {
resource_size_t dev_size = dev_dax_size(dev_dax);
struct device *dev = &dev_dax->dev; struct device *dev = &dev_dax->dev;
int i; int i;
if (dev_size > 0 && !alloc_is_aligned(dev_dax, dev_size)) {
dev_dbg(dev, "%s: align %u invalid for size %pa\n",
__func__, dev_dax->align, &dev_size);
return -EINVAL;
}
for (i = 0; i < dev_dax->nr_range; i++) { for (i = 0; i < dev_dax->nr_range; i++) {
size_t len = range_len(&dev_dax->ranges[i].range); size_t len = range_len(&dev_dax->ranges[i].range);
...@@ -1274,7 +1258,6 @@ static void dev_dax_release(struct device *dev) ...@@ -1274,7 +1258,6 @@ static void dev_dax_release(struct device *dev)
put_dax(dax_dev); put_dax(dax_dev);
free_dev_dax_id(dev_dax); free_dev_dax_id(dev_dax);
dax_region_put(dax_region); dax_region_put(dax_region);
kfree(dev_dax->ranges);
kfree(dev_dax->pgmap); kfree(dev_dax->pgmap);
kfree(dev_dax); kfree(dev_dax);
} }
......
...@@ -52,7 +52,7 @@ struct dev_dax *__dax_pmem_probe(struct device *dev, enum dev_dax_subsys subsys) ...@@ -52,7 +52,7 @@ struct dev_dax *__dax_pmem_probe(struct device *dev, enum dev_dax_subsys subsys)
/* adjust the dax_region range to the start of data */ /* adjust the dax_region range to the start of data */
range = pgmap.range; range = pgmap.range;
range.start += offset, range.start += offset;
dax_region = alloc_dax_region(dev, region_id, &range, dax_region = alloc_dax_region(dev, region_id, &range,
nd_region->target_node, le32_to_cpu(pfn_sb->align), nd_region->target_node, le32_to_cpu(pfn_sb->align),
IORESOURCE_DAX_STATIC); IORESOURCE_DAX_STATIC);
......
...@@ -752,6 +752,7 @@ static int __init dax_core_init(void) ...@@ -752,6 +752,7 @@ static int __init dax_core_init(void)
static void __exit dax_core_exit(void) static void __exit dax_core_exit(void)
{ {
dax_bus_exit();
unregister_chrdev_region(dax_devt, MINORMASK+1); unregister_chrdev_region(dax_devt, MINORMASK+1);
ida_destroy(&dax_minor_ida); ida_destroy(&dax_minor_ida);
dax_fs_exit(); dax_fs_exit();
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#ifndef _LINUX_BTT_H #ifndef _LINUX_BTT_H
#define _LINUX_BTT_H #define _LINUX_BTT_H
#include <linux/badblocks.h>
#include <linux/types.h> #include <linux/types.h>
#define BTT_SIG_LEN 16 #define BTT_SIG_LEN 16
...@@ -197,6 +196,8 @@ struct arena_info { ...@@ -197,6 +196,8 @@ struct arena_info {
int log_index[2]; int log_index[2];
}; };
struct badblocks;
/** /**
* struct btt - handle for a BTT instance * struct btt - handle for a BTT instance
* @btt_disk: Pointer to the gendisk for BTT device * @btt_disk: Pointer to the gendisk for BTT device
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
#include <linux/device.h> #include <linux/device.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <linux/badblocks.h>
#include "nd-core.h" #include "nd-core.h"
#include "pmem.h" #include "pmem.h"
#include "pfn.h" #include "pfn.h"
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* Copyright(c) 2013-2015 Intel Corporation. All rights reserved. * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
*/ */
#include <linux/libnvdimm.h> #include <linux/libnvdimm.h>
#include <linux/badblocks.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/module.h> #include <linux/module.h>
......
...@@ -980,6 +980,15 @@ static int __blk_label_update(struct nd_region *nd_region, ...@@ -980,6 +980,15 @@ static int __blk_label_update(struct nd_region *nd_region,
} }
} }
/* release slots associated with any invalidated UUIDs */
mutex_lock(&nd_mapping->lock);
list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list)
if (test_and_clear_bit(ND_LABEL_REAP, &label_ent->flags)) {
reap_victim(nd_mapping, label_ent);
list_move(&label_ent->list, &list);
}
mutex_unlock(&nd_mapping->lock);
/* /*
* Find the resource associated with the first label in the set * Find the resource associated with the first label in the set
* per the v1.2 namespace specification. * per the v1.2 namespace specification.
...@@ -999,8 +1008,10 @@ static int __blk_label_update(struct nd_region *nd_region, ...@@ -999,8 +1008,10 @@ static int __blk_label_update(struct nd_region *nd_region,
if (is_old_resource(res, old_res_list, old_num_resources)) if (is_old_resource(res, old_res_list, old_num_resources))
continue; /* carry-over */ continue; /* carry-over */
slot = nd_label_alloc_slot(ndd); slot = nd_label_alloc_slot(ndd);
if (slot == UINT_MAX) if (slot == UINT_MAX) {
rc = -ENXIO;
goto abort; goto abort;
}
dev_dbg(ndd->dev, "allocated: %d\n", slot); dev_dbg(ndd->dev, "allocated: %d\n", slot);
nd_label = to_label(ndd, slot); nd_label = to_label(ndd, slot);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment