nvme: don't hold nvmf_transports_rwsem for more than transport lookups
authorJohannes Thumshirn <jthumshirn@suse.de>
Fri, 1 Jun 2018 07:11:20 +0000 (09:11 +0200)
committerJens Axboe <axboe@kernel.dk>
Fri, 8 Jun 2018 18:51:10 +0000 (12:51 -0600)
Only take nvmf_transports_rwsem when doing a lookup of registered
transports, so that a blocking ->create_ctrl doesn't prevent other
actions on /dev/nvme-fabrics.

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
[hch: increased lock hold time a bit to be safe, added a comment
 and updated the changelog]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/nvme/host/fabrics.c
drivers/nvme/host/fabrics.h

index 5f5f7067c41d63975142f1d0c8f174c5640d5357..fa32c1216409a349ed502902317e443471bbd747 100644 (file)
@@ -952,6 +952,7 @@ nvmf_create_ctrl(struct device *dev, const char *buf, size_t count)
                ret = -EBUSY;
                goto out_unlock;
        }
+       up_read(&nvmf_transports_rwsem);
 
        ret = nvmf_check_required_opts(opts, ops->required_opts);
        if (ret)
@@ -968,11 +969,11 @@ nvmf_create_ctrl(struct device *dev, const char *buf, size_t count)
        }
 
        module_put(ops->module);
-       up_read(&nvmf_transports_rwsem);
        return ctrl;
 
 out_module_put:
        module_put(ops->module);
+       goto out_free_opts;
 out_unlock:
        up_read(&nvmf_transports_rwsem);
 out_free_opts:
index 0cf0460a5c921f337f05559c507a1fef73178ba2..7491a0bbf711d6eb3321a7bdc4d3ff22699d3416 100644 (file)
@@ -124,6 +124,9 @@ struct nvmf_ctrl_options {
  *     1. At minimum, 'required_opts' and 'allowed_opts' should
  *        be set to the same enum parsing options defined earlier.
  *     2. create_ctrl() must be defined (even if it does nothing)
+ *     3. struct nvmf_transport_ops must be statically allocated in the
+ *        modules .bss section so that a pure module_get on @module
+ *        prevents the memory from beeing freed.
  */
 struct nvmf_transport_ops {
        struct list_head        entry;