lightnvm: use system block for mm initialization
authorMatias Bjørling <m@bjorling.me>
Tue, 12 Jan 2016 06:49:38 +0000 (07:49 +0100)
committerJens Axboe <axboe@fb.com>
Tue, 12 Jan 2016 15:21:18 +0000 (08:21 -0700)
Use system block information to register the appropriate media manager.
This enables the LightNVM subsystem to instantiate a media manager
selected by the user, instead of relying on automatic detection by each
media manager loaded in the kernel.

A device must now be initialized before it can proceed to initialize its
media manager. Upon initialization, the configured media manager is
automatically initialized as well.

Signed-off-by: Matias Bjørling <m@bjorling.me>
Signed-off-by: Jens Axboe <axboe@fb.com>
drivers/lightnvm/core.c
include/linux/lightnvm.h

index ee08fac6f327ee78078a55ca89f834821d5e0ae9..9e5712dda062e288ccaf96bac984b995439217df 100644 (file)
@@ -106,6 +106,9 @@ struct nvmm_type *nvm_init_mgr(struct nvm_dev *dev)
        lockdep_assert_held(&nvm_lock);
 
        list_for_each_entry(mt, &nvm_mgrs, list) {
+               if (strncmp(dev->sb.mmtype, mt->name, NVM_MMTYPE_LEN))
+                       continue;
+
                ret = mt->register_mgr(dev);
                if (ret < 0) {
                        pr_err("nvm: media mgr failed to init (%d) on dev %s\n",
@@ -569,9 +572,16 @@ int nvm_register(struct request_queue *q, char *disk_name,
                }
        }
 
+       ret = nvm_get_sysblock(dev, &dev->sb);
+       if (!ret)
+               pr_err("nvm: device not initialized.\n");
+       else if (ret < 0)
+               pr_err("nvm: err (%d) on device initialization\n", ret);
+
        /* register device with a supported media manager */
        down_write(&nvm_lock);
-       dev->mt = nvm_init_mgr(dev);
+       if (ret > 0)
+               dev->mt = nvm_init_mgr(dev);
        list_add(&dev->devices, &nvm_devices);
        up_write(&nvm_lock);
 
@@ -1030,6 +1040,7 @@ static long __nvm_ioctl_dev_init(struct nvm_ioctl_dev_init *init)
 {
        struct nvm_dev *dev;
        struct nvm_sb_info info;
+       int ret;
 
        down_write(&nvm_lock);
        dev = nvm_find_nvm_dev(init->dev);
@@ -1044,7 +1055,17 @@ static long __nvm_ioctl_dev_init(struct nvm_ioctl_dev_init *init)
        strncpy(info.mmtype, init->mmtype, NVM_MMTYPE_LEN);
        info.fs_ppa.ppa = -1;
 
-       return nvm_init_sysblock(dev, &info);
+       ret = nvm_init_sysblock(dev, &info);
+       if (ret)
+               return ret;
+
+       memcpy(&dev->sb, &info, sizeof(struct nvm_sb_info));
+
+       down_write(&nvm_lock);
+       dev->mt = nvm_init_mgr(dev);
+       up_write(&nvm_lock);
+
+       return 0;
 }
 
 static long nvm_ioctl_dev_init(struct file *file, void __user *arg)
index 7ad22d3f0d2eacb39af10ac2cb3ca50ea1b8621c..02f36bdf216eddd996c00199ce3b653d8ecdc3a2 100644 (file)
@@ -301,6 +301,9 @@ struct nvm_dev {
        struct nvmm_type *mt;
        void *mp;
 
+       /* System blocks */
+       struct nvm_sb_info sb;
+
        /* Device information */
        int nr_chnls;
        int nr_planes;