diff options
author | Sagi Grimberg <sagig@mellanox.com> | 2014-06-08 03:00:59 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-07-09 19:58:58 -0400 |
commit | 6ef07a9f369742a7b18c77484411cff0bd790291 (patch) | |
tree | 8210877bc950e9b09a37d65fd78b9fd204e5dc30 /drivers/net | |
parent | a497c3ba1d97fc69c1e78e7b96435ba8c2cb42ee (diff) |
mlx5_core: Fix possible race between mr tree insert/delete
In mlx5_core_destroy_mkey(), we must first remove the mr from the
radix tree and then destroy it. Otherwise we might hit a race if the
key was reallocated and we attempted to insert it to the radix tree.
Also handle radix tree insert/delete failures.
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Reviewed-by: Eli Cohen <elic@dev.mellanox.co.il>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/mr.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mr.c b/drivers/net/ethernet/mellanox/mlx5/core/mr.c index ba0401d4af50..184c3615f479 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mr.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/mr.c | |||
@@ -94,6 +94,11 @@ int mlx5_core_create_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr, | |||
94 | write_lock_irq(&table->lock); | 94 | write_lock_irq(&table->lock); |
95 | err = radix_tree_insert(&table->tree, mlx5_base_mkey(mr->key), mr); | 95 | err = radix_tree_insert(&table->tree, mlx5_base_mkey(mr->key), mr); |
96 | write_unlock_irq(&table->lock); | 96 | write_unlock_irq(&table->lock); |
97 | if (err) { | ||
98 | mlx5_core_warn(dev, "failed radix tree insert of mr 0x%x, %d\n", | ||
99 | mlx5_base_mkey(mr->key), err); | ||
100 | mlx5_core_destroy_mkey(dev, mr); | ||
101 | } | ||
97 | 102 | ||
98 | return err; | 103 | return err; |
99 | } | 104 | } |
@@ -104,12 +109,22 @@ int mlx5_core_destroy_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr) | |||
104 | struct mlx5_mr_table *table = &dev->priv.mr_table; | 109 | struct mlx5_mr_table *table = &dev->priv.mr_table; |
105 | struct mlx5_destroy_mkey_mbox_in in; | 110 | struct mlx5_destroy_mkey_mbox_in in; |
106 | struct mlx5_destroy_mkey_mbox_out out; | 111 | struct mlx5_destroy_mkey_mbox_out out; |
112 | struct mlx5_core_mr *deleted_mr; | ||
107 | unsigned long flags; | 113 | unsigned long flags; |
108 | int err; | 114 | int err; |
109 | 115 | ||
110 | memset(&in, 0, sizeof(in)); | 116 | memset(&in, 0, sizeof(in)); |
111 | memset(&out, 0, sizeof(out)); | 117 | memset(&out, 0, sizeof(out)); |
112 | 118 | ||
119 | write_lock_irqsave(&table->lock, flags); | ||
120 | deleted_mr = radix_tree_delete(&table->tree, mlx5_base_mkey(mr->key)); | ||
121 | write_unlock_irqrestore(&table->lock, flags); | ||
122 | if (!deleted_mr) { | ||
123 | mlx5_core_warn(dev, "failed radix tree delete of mr 0x%x\n", | ||
124 | mlx5_base_mkey(mr->key)); | ||
125 | return -ENOENT; | ||
126 | } | ||
127 | |||
113 | in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_MKEY); | 128 | in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_MKEY); |
114 | in.mkey = cpu_to_be32(mlx5_mkey_to_idx(mr->key)); | 129 | in.mkey = cpu_to_be32(mlx5_mkey_to_idx(mr->key)); |
115 | err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); | 130 | err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); |
@@ -119,10 +134,6 @@ int mlx5_core_destroy_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr) | |||
119 | if (out.hdr.status) | 134 | if (out.hdr.status) |
120 | return mlx5_cmd_status_to_err(&out.hdr); | 135 | return mlx5_cmd_status_to_err(&out.hdr); |
121 | 136 | ||
122 | write_lock_irqsave(&table->lock, flags); | ||
123 | radix_tree_delete(&table->tree, mlx5_base_mkey(mr->key)); | ||
124 | write_unlock_irqrestore(&table->lock, flags); | ||
125 | |||
126 | return err; | 137 | return err; |
127 | } | 138 | } |
128 | EXPORT_SYMBOL(mlx5_core_destroy_mkey); | 139 | EXPORT_SYMBOL(mlx5_core_destroy_mkey); |