NVMe: CPU hot plug notification
authorKeith Busch <keith.busch@intel.com>
Mon, 24 Mar 2014 16:46:26 +0000 (10:46 -0600)
committerMatthew Wilcox <matthew.r.wilcox@intel.com>
Thu, 10 Apr 2014 21:03:42 +0000 (17:03 -0400)
Registers with hot cpu notification to rebalance, and potentially allocate
additional, io queues.

Signed-off-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
drivers/block/nvme-core.c
include/linux/nvme.h

index 48d7bd55207a452f43f37ba118d8695e05bf260b..ce5a4f1a3950c445e2ca82f0dbe09658e2383194 100644 (file)
@@ -2002,6 +2002,19 @@ static size_t db_bar_size(struct nvme_dev *dev, unsigned nr_io_queues)
        return 4096 + ((nr_io_queues + 1) * 8 * dev->db_stride);
 }
 
+static int nvme_cpu_notify(struct notifier_block *self,
+                               unsigned long action, void *hcpu)
+{
+       struct nvme_dev *dev = container_of(self, struct nvme_dev, nb);
+       switch (action) {
+       case CPU_ONLINE:
+       case CPU_DEAD:
+               nvme_assign_io_queues(dev);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
 static int nvme_setup_io_queues(struct nvme_dev *dev)
 {
        struct nvme_queue *adminq = raw_nvmeq(dev, 0);
@@ -2080,6 +2093,11 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        nvme_free_queues(dev, nr_io_queues + 1);
        nvme_assign_io_queues(dev);
 
+       dev->nb.notifier_call = &nvme_cpu_notify;
+       result = register_hotcpu_notifier(&dev->nb);
+       if (result)
+               goto free_queues;
+
        return 0;
 
  free_queues:
@@ -2357,6 +2375,7 @@ static void nvme_dev_shutdown(struct nvme_dev *dev)
        int i;
 
        dev->initialized = 0;
+       unregister_hotcpu_notifier(&dev->nb);
 
        spin_lock(&dev_list_lock);
        list_del_init(&dev->node);
index f0f95c7196850d2cdd13960c2aa76b034e36bc7e..15d071eba8b8b75d880ce1ec69308914350a5ae4 100644 (file)
@@ -92,6 +92,7 @@ struct nvme_dev {
        struct kref kref;
        struct miscdevice miscdev;
        struct work_struct reset_work;
+       struct notifier_block nb;
        char name[12];
        char serial[20];
        char model[40];