Skip to content

Commit 489beb9

Browse files
rolanddChristoph Hellwig
authored andcommitted
nvme-fabrics: Convert nvmf_transports_mutex to an rwsem
The mutex protects against the list of transports changing while a controller is being created, but using a plain old mutex means that it also serializes controller creation. This unnecessarily slows down creating multiple controllers - for example for the RDMA transport, creating a controller involves establishing one connection for every IO queue, which involves even more network/software round trips, so the delay can become significant. The simplest way to fix this is to change the mutex to an rwsem and only hold it for writing when the list is being mutated. Since we can take the rwsem for reading while creating a controller, we can create multiple controllers in parallel. Signed-off-by: Roland Dreier <[email protected]> Reviewed-by: Sagi Grimberg <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]>
1 parent 2b76da9 commit 489beb9

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

drivers/nvme/host/fabrics.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include "fabrics.h"
2323

2424
static LIST_HEAD(nvmf_transports);
25-
static DEFINE_MUTEX(nvmf_transports_mutex);
25+
static DECLARE_RWSEM(nvmf_transports_rwsem);
2626

2727
static LIST_HEAD(nvmf_hosts);
2828
static DEFINE_MUTEX(nvmf_hosts_mutex);
@@ -495,9 +495,9 @@ int nvmf_register_transport(struct nvmf_transport_ops *ops)
495495
if (!ops->create_ctrl)
496496
return -EINVAL;
497497

498-
mutex_lock(&nvmf_transports_mutex);
498+
down_write(&nvmf_transports_rwsem);
499499
list_add_tail(&ops->entry, &nvmf_transports);
500-
mutex_unlock(&nvmf_transports_mutex);
500+
up_write(&nvmf_transports_rwsem);
501501

502502
return 0;
503503
}
@@ -514,9 +514,9 @@ EXPORT_SYMBOL_GPL(nvmf_register_transport);
514514
*/
515515
void nvmf_unregister_transport(struct nvmf_transport_ops *ops)
516516
{
517-
mutex_lock(&nvmf_transports_mutex);
517+
down_write(&nvmf_transports_rwsem);
518518
list_del(&ops->entry);
519-
mutex_unlock(&nvmf_transports_mutex);
519+
up_write(&nvmf_transports_rwsem);
520520
}
521521
EXPORT_SYMBOL_GPL(nvmf_unregister_transport);
522522

@@ -525,7 +525,7 @@ static struct nvmf_transport_ops *nvmf_lookup_transport(
525525
{
526526
struct nvmf_transport_ops *ops;
527527

528-
lockdep_assert_held(&nvmf_transports_mutex);
528+
lockdep_assert_held(&nvmf_transports_rwsem);
529529

530530
list_for_each_entry(ops, &nvmf_transports, entry) {
531531
if (strcmp(ops->name, opts->transport) == 0)
@@ -851,7 +851,7 @@ nvmf_create_ctrl(struct device *dev, const char *buf, size_t count)
851851
goto out_free_opts;
852852
opts->mask &= ~NVMF_REQUIRED_OPTS;
853853

854-
mutex_lock(&nvmf_transports_mutex);
854+
down_read(&nvmf_transports_rwsem);
855855
ops = nvmf_lookup_transport(opts);
856856
if (!ops) {
857857
pr_info("no handler found for transport %s.\n",
@@ -878,16 +878,16 @@ nvmf_create_ctrl(struct device *dev, const char *buf, size_t count)
878878
dev_warn(ctrl->device,
879879
"controller returned incorrect NQN: \"%s\".\n",
880880
ctrl->subnqn);
881-
mutex_unlock(&nvmf_transports_mutex);
881+
up_read(&nvmf_transports_rwsem);
882882
ctrl->ops->delete_ctrl(ctrl);
883883
return ERR_PTR(-EINVAL);
884884
}
885885

886-
mutex_unlock(&nvmf_transports_mutex);
886+
up_read(&nvmf_transports_rwsem);
887887
return ctrl;
888888

889889
out_unlock:
890-
mutex_unlock(&nvmf_transports_mutex);
890+
up_read(&nvmf_transports_rwsem);
891891
out_free_opts:
892892
nvmf_free_options(opts);
893893
return ERR_PTR(ret);

0 commit comments

Comments
 (0)