Since this protection may break userspace tools, it should
be an opt-in until those tools have time to update to the
new daxN.M/hotplug interface instead of memory blocks.

Suggested-by: Dan Williams <[email protected]>
Signed-off-by: Gregory Price <[email protected]>
---
 drivers/dax/Kconfig | 18 ++++++++++++++++++
 drivers/dax/kmem.c  | 29 ++++++++++++++++++++---------
 2 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/drivers/dax/Kconfig b/drivers/dax/Kconfig
index d656e4c0eb84..cc13c22eb8f8 100644
--- a/drivers/dax/Kconfig
+++ b/drivers/dax/Kconfig
@@ -78,4 +78,22 @@ config DEV_DAX_KMEM
 
          Say N if unsure.
 
+config DEV_DAX_KMEM_PROTECTED
+       bool "Protect DAX_KMEM memory blocks being changed"
+       depends on DEV_DAX_KMEM
+       default n
+       help
+         Prevents actions from outside the KMEM DAX driver from changing
+         DAX KMEM memory block states. For example, the memory block
+         sysfs functions (online, state) will return -EBUSY, and normal
+         calls to memory_hotplug functions from other drivers and kernel
+         sources will fail.
+
+         This may break existing memory block management patterns that
+         depend on offlining DAX KMEM blocks from userland before unbinding
+         the driver.  Use this only if your tools have been updated to use
+         the daxN.M/hotplug interface.
+
+         Say N if unsure.
+
 endif
diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c
index f3562f65376c..094b8a51099e 100644
--- a/drivers/dax/kmem.c
+++ b/drivers/dax/kmem.c
@@ -184,6 +184,21 @@ static int dax_kmem_memory_notifier_cb(struct 
notifier_block *nb,
        return NOTIFY_BAD;
 }
 
+static int dax_kmem_register_notifier(struct dax_kmem_data *data)
+{
+       if (!IS_ENABLED(DEV_DAX_KMEM_PROTECTED))
+               return 0;
+       data->mem_nb.notifier_call = dax_kmem_memory_notifier_cb;
+       return register_memory_notifier(&data->mem_nb);
+}
+
+static void dax_kmem_unregister_notifier(struct dax_kmem_data *data)
+{
+       if (!IS_ENABLED(DEV_DAX_KMEM_PROTECTED))
+               return;
+       unregister_memory_notifier(&data->mem_nb);
+}
+
 /**
  * dax_kmem_do_hotplug - hotplug memory for dax kmem device
  * @dev_dax: the dev_dax instance
@@ -563,13 +578,9 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
        if (rc < 0)
                goto err_resources;
 
-       /* Register memory notifier to block external operations */
-       data->mem_nb.notifier_call = dax_kmem_memory_notifier_cb;
-       rc = register_memory_notifier(&data->mem_nb);
-       if (rc) {
-               dev_warn(dev, "failed to register memory notifier\n");
+       rc = dax_kmem_register_notifier(data);
+       if (rc)
                goto err_notifier;
-       }
 
        /*
         * Hotplug using the system default policy - this preserves backwards
@@ -595,7 +606,7 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
        return 0;
 
 err_hotplug:
-       unregister_memory_notifier(&data->mem_nb);
+       dax_kmem_unregister_notifier(data);
 err_notifier:
        dax_kmem_cleanup_resources(dev_dax, data);
 err_resources:
@@ -619,7 +630,7 @@ static void dev_dax_kmem_remove(struct dev_dax *dev_dax)
 
        device_remove_file(dev, &dev_attr_hotplug);
        dax_kmem_cleanup_resources(dev_dax, data);
-       unregister_memory_notifier(&data->mem_nb);
+       dax_kmem_unregister_notifier(data);
        memory_group_unregister(data->mgid);
        kfree(data->res_name);
        kfree(data);
@@ -640,7 +651,7 @@ static void dev_dax_kmem_remove(struct dev_dax *dev_dax)
        struct dax_kmem_data *data = dev_get_drvdata(dev);
 
        device_remove_file(dev, &dev_attr_hotplug);
-       unregister_memory_notifier(&data->mem_nb);
+       dax_kmem_unregister_notifier(data);
 
        /*
         * Without hotremove purposely leak the request_mem_region() for the
-- 
2.52.0


Reply via email to