Merge tag 'libnvdimm-for-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdim...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 24 Dec 2020 20:18:11 +0000 (12:18 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 24 Dec 2020 20:18:11 +0000 (12:18 -0800)
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()

drivers/acpi/nfit/core.c
drivers/dax/bus.c
drivers/dax/pmem/core.c
drivers/dax/super.c
drivers/nvdimm/btt.h
drivers/nvdimm/claim.c
drivers/nvdimm/core.c
drivers/nvdimm/label.c

index 4426082..b11b08a 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/list_sort.h>
 #include <linux/libnvdimm.h>
 #include <linux/module.h>
+#include <linux/nospec.h>
 #include <linux/mutex.h>
 #include <linux/ndctl.h>
 #include <linux/sysfs.h>
@@ -282,18 +283,19 @@ err:
 
 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;
 
-       if (!buf)
-               goto err;
-
        if (integer->type != ACPI_TYPE_INTEGER) {
                WARN_ONCE(1, "BIOS bug, unexpected element type: %d\n",
                                integer->type);
                goto err;
        }
 
+       buf = ACPI_ALLOCATE(sizeof(*buf) + 4);
+       if (!buf)
+               goto err;
+
        dst = buf + 1;
        buf->type = ACPI_TYPE_BUFFER;
        buf->buffer.length = 4;
@@ -478,8 +480,11 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
                cmd_mask = nd_desc->cmd_mask;
                if (cmd == ND_CMD_CALL && 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;
+                       family = array_index_nospec(family,
+                                                   NVDIMM_BUS_FAMILY_MAX + 1);
                        dsm_mask = acpi_desc->family_dsm_mask[family];
                        guid = to_nfit_bus_uuid(family);
                } else {
index 27513d3..737b207 100644 (file)
@@ -367,19 +367,28 @@ void kill_dev_dax(struct dev_dax *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;
-       int i;
 
        device_lock_assert(dax_region->dev);
-       for (i = 0; i < dev_dax->nr_range; i++) {
-               struct range *range = &dev_dax->ranges[i].range;
-
-               __release_region(&dax_region->res, range->start,
-                               range_len(range));
+       dev_dbg(&dev_dax->dev, "delete range[%d]: %#llx:%#llx\n", i,
+               (unsigned long long)range->start,
+               (unsigned long long)range->end);
+
+       __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)
@@ -763,22 +772,14 @@ static int alloc_dev_dax_range(struct dev_dax *dev_dax, u64 start,
                return 0;
        }
 
-       ranges = krealloc(dev_dax->ranges, sizeof(*ranges)
-                       * (dev_dax->nr_range + 1), GFP_KERNEL);
-       if (!ranges)
+       alloc = __request_region(res, start, size, dev_name(dev), 0);
+       if (!alloc)
                return -ENOMEM;
 
-       alloc = __request_region(res, start, size, dev_name(dev), 0);
-       if (!alloc) {
-               /*
-                * If this was an empty set of ranges nothing else
-                * will release @ranges, so do it now.
-                */
-               if (!dev_dax->nr_range) {
-                       kfree(ranges);
-                       ranges = NULL;
-               }
-               dev_dax->ranges = ranges;
+       ranges = krealloc(dev_dax->ranges, sizeof(*ranges)
+                       * (dev_dax->nr_range + 1), GFP_KERNEL);
+       if (!ranges) {
+               __release_region(res, alloc->start, resource_size(alloc));
                return -ENOMEM;
        }
 
@@ -804,15 +805,10 @@ static int alloc_dev_dax_range(struct dev_dax *dev_dax, u64 start,
                return 0;
 
        rc = devm_register_dax_mapping(dev_dax, dev_dax->nr_range - 1);
-       if (rc) {
-               dev_dbg(dev, "delete range[%d]: %pa:%pa\n", dev_dax->nr_range - 1,
-                               &alloc->start, &alloc->end);
-               dev_dax->nr_range--;
-               __release_region(res, alloc->start, resource_size(alloc));
-               return rc;
-       }
+       if (rc)
+               trim_dev_dax_range(dev_dax);
 
-       return 0;
+       return rc;
 }
 
 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)
                if (shrink >= range_len(range)) {
                        devm_release_action(dax_region->dev,
                                        unregister_dax_mapping, &mapping->dev);
-                       __release_region(&dax_region->res, range->start,
-                                       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);
+                       trim_dev_dax_range(dev_dax);
                        to_shrink -= shrink;
                        if (!to_shrink)
                                break;
@@ -1114,16 +1105,9 @@ static ssize_t align_show(struct device *dev,
 
 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;
        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++) {
                size_t len = range_len(&dev_dax->ranges[i].range);
 
@@ -1274,7 +1258,6 @@ static void dev_dax_release(struct device *dev)
        put_dax(dax_dev);
        free_dev_dax_id(dev_dax);
        dax_region_put(dax_region);
-       kfree(dev_dax->ranges);
        kfree(dev_dax->pgmap);
        kfree(dev_dax);
 }
index 62b26bf..062e8bc 100644 (file)
@@ -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 */
        range = pgmap.range;
-       range.start += offset,
+       range.start += offset;
        dax_region = alloc_dax_region(dev, region_id, &range,
                        nd_region->target_node, le32_to_cpu(pfn_sb->align),
                        IORESOURCE_DAX_STATIC);
index edc279b..cadbd0a 100644 (file)
@@ -752,6 +752,7 @@ err_chrdev:
 
 static void __exit dax_core_exit(void)
 {
+       dax_bus_exit();
        unregister_chrdev_region(dax_devt, MINORMASK+1);
        ida_destroy(&dax_minor_ida);
        dax_fs_exit();
index 2e258be..aa53e0b 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _LINUX_BTT_H
 #define _LINUX_BTT_H
 
-#include <linux/badblocks.h>
 #include <linux/types.h>
 
 #define BTT_SIG_LEN 16
@@ -197,6 +196,8 @@ struct arena_info {
        int log_index[2];
 };
 
+struct badblocks;
+
 /**
  * struct btt - handle for a BTT instance
  * @btt_disk:          Pointer to the gendisk for BTT device
index 5a7c800..030dbde 100644 (file)
@@ -4,6 +4,7 @@
  */
 #include <linux/device.h>
 #include <linux/sizes.h>
+#include <linux/badblocks.h>
 #include "nd-core.h"
 #include "pmem.h"
 #include "pfn.h"
index c21ba06..7de592d 100644 (file)
@@ -3,7 +3,6 @@
  * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
  */
 #include <linux/libnvdimm.h>
-#include <linux/badblocks.h>
 #include <linux/suspend.h>
 #include <linux/export.h>
 #include <linux/module.h>
index 47a4828..9251441 100644 (file)
@@ -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
         * per the v1.2 namespace specification.
@@ -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))
                        continue; /* carry-over */
                slot = nd_label_alloc_slot(ndd);
-               if (slot == UINT_MAX)
+               if (slot == UINT_MAX) {
+                       rc = -ENXIO;
                        goto abort;
+               }
                dev_dbg(ndd->dev, "allocated: %d\n", slot);
 
                nd_label = to_label(ndd, slot);