Skip to content

Commit 11a0ae4

Browse files
committed
RDMA: Allow ib_client's to fail when add() is called
When a client is added it isn't allowed to fail, but all the client's have various failure paths within their add routines. This creates the very fringe condition where the client was added, failed during add and didn't set the client_data. The core code will then still call other client_data centric ops like remove(), rename(), get_nl_info(), and get_net_dev_by_params() with NULL client_data - which is confusing and unexpected. If the add() callback fails, then do not call any more client ops for the device, even remove. Remove all the now redundant checks for NULL client_data in ops callbacks. Update all the add() callbacks to return error codes appropriately. EOPNOTSUPP is used for cases where the ULP does not support the ib_device - eg because it only works with IB. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Leon Romanovsky <[email protected]> Acked-by: Ursula Braun <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 04c349a commit 11a0ae4

File tree

15 files changed

+142
-124
lines changed

15 files changed

+142
-124
lines changed

drivers/infiniband/core/cm.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ const char *__attribute_const__ ibcm_reject_msg(int reason)
8181
EXPORT_SYMBOL(ibcm_reject_msg);
8282

8383
struct cm_id_private;
84-
static void cm_add_one(struct ib_device *device);
84+
static int cm_add_one(struct ib_device *device);
8585
static void cm_remove_one(struct ib_device *device, void *client_data);
8686
static int cm_send_sidr_rep_locked(struct cm_id_private *cm_id_priv,
8787
struct ib_cm_sidr_rep_param *param);
@@ -4382,7 +4382,7 @@ static void cm_remove_port_fs(struct cm_port *port)
43824382

43834383
}
43844384

4385-
static void cm_add_one(struct ib_device *ib_device)
4385+
static int cm_add_one(struct ib_device *ib_device)
43864386
{
43874387
struct cm_device *cm_dev;
43884388
struct cm_port *port;
@@ -4401,7 +4401,7 @@ static void cm_add_one(struct ib_device *ib_device)
44014401
cm_dev = kzalloc(struct_size(cm_dev, port, ib_device->phys_port_cnt),
44024402
GFP_KERNEL);
44034403
if (!cm_dev)
4404-
return;
4404+
return -ENOMEM;
44054405

44064406
cm_dev->ib_device = ib_device;
44074407
cm_dev->ack_delay = ib_device->attrs.local_ca_ack_delay;
@@ -4413,8 +4413,10 @@ static void cm_add_one(struct ib_device *ib_device)
44134413
continue;
44144414

44154415
port = kzalloc(sizeof *port, GFP_KERNEL);
4416-
if (!port)
4416+
if (!port) {
4417+
ret = -ENOMEM;
44174418
goto error1;
4419+
}
44184420

44194421
cm_dev->port[i-1] = port;
44204422
port->cm_dev = cm_dev;
@@ -4435,8 +4437,10 @@ static void cm_add_one(struct ib_device *ib_device)
44354437
cm_recv_handler,
44364438
port,
44374439
0);
4438-
if (IS_ERR(port->mad_agent))
4440+
if (IS_ERR(port->mad_agent)) {
4441+
ret = PTR_ERR(port->mad_agent);
44394442
goto error2;
4443+
}
44404444

44414445
ret = ib_modify_port(ib_device, i, 0, &port_modify);
44424446
if (ret)
@@ -4445,15 +4449,17 @@ static void cm_add_one(struct ib_device *ib_device)
44454449
count++;
44464450
}
44474451

4448-
if (!count)
4452+
if (!count) {
4453+
ret = -EOPNOTSUPP;
44494454
goto free;
4455+
}
44504456

44514457
ib_set_client_data(ib_device, &cm_client, cm_dev);
44524458

44534459
write_lock_irqsave(&cm.device_lock, flags);
44544460
list_add_tail(&cm_dev->list, &cm.device_list);
44554461
write_unlock_irqrestore(&cm.device_lock, flags);
4456-
return;
4462+
return 0;
44574463

44584464
error3:
44594465
ib_unregister_mad_agent(port->mad_agent);
@@ -4475,6 +4481,7 @@ static void cm_add_one(struct ib_device *ib_device)
44754481
}
44764482
free:
44774483
kfree(cm_dev);
4484+
return ret;
44784485
}
44794486

44804487
static void cm_remove_one(struct ib_device *ib_device, void *client_data)
@@ -4489,9 +4496,6 @@ static void cm_remove_one(struct ib_device *ib_device, void *client_data)
44894496
unsigned long flags;
44904497
int i;
44914498

4492-
if (!cm_dev)
4493-
return;
4494-
44954499
write_lock_irqsave(&cm.device_lock, flags);
44964500
list_del(&cm_dev->list);
44974501
write_unlock_irqrestore(&cm.device_lock, flags);

drivers/infiniband/core/cma.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ struct rdma_cm_id *rdma_res_to_id(struct rdma_restrack_entry *res)
153153
}
154154
EXPORT_SYMBOL(rdma_res_to_id);
155155

156-
static void cma_add_one(struct ib_device *device);
156+
static int cma_add_one(struct ib_device *device);
157157
static void cma_remove_one(struct ib_device *device, void *client_data);
158158

159159
static struct ib_client cma_client = {
@@ -4638,29 +4638,34 @@ static struct notifier_block cma_nb = {
46384638
.notifier_call = cma_netdev_callback
46394639
};
46404640

4641-
static void cma_add_one(struct ib_device *device)
4641+
static int cma_add_one(struct ib_device *device)
46424642
{
46434643
struct cma_device *cma_dev;
46444644
struct rdma_id_private *id_priv;
46454645
unsigned int i;
46464646
unsigned long supported_gids = 0;
4647+
int ret;
46474648

46484649
cma_dev = kmalloc(sizeof *cma_dev, GFP_KERNEL);
46494650
if (!cma_dev)
4650-
return;
4651+
return -ENOMEM;
46514652

46524653
cma_dev->device = device;
46534654
cma_dev->default_gid_type = kcalloc(device->phys_port_cnt,
46544655
sizeof(*cma_dev->default_gid_type),
46554656
GFP_KERNEL);
4656-
if (!cma_dev->default_gid_type)
4657+
if (!cma_dev->default_gid_type) {
4658+
ret = -ENOMEM;
46574659
goto free_cma_dev;
4660+
}
46584661

46594662
cma_dev->default_roce_tos = kcalloc(device->phys_port_cnt,
46604663
sizeof(*cma_dev->default_roce_tos),
46614664
GFP_KERNEL);
4662-
if (!cma_dev->default_roce_tos)
4665+
if (!cma_dev->default_roce_tos) {
4666+
ret = -ENOMEM;
46634667
goto free_gid_type;
4668+
}
46644669

46654670
rdma_for_each_port (device, i) {
46664671
supported_gids = roce_gid_type_mask_support(device, i);
@@ -4686,15 +4691,14 @@ static void cma_add_one(struct ib_device *device)
46864691
mutex_unlock(&lock);
46874692

46884693
trace_cm_add_one(device);
4689-
return;
4694+
return 0;
46904695

46914696
free_gid_type:
46924697
kfree(cma_dev->default_gid_type);
46934698

46944699
free_cma_dev:
46954700
kfree(cma_dev);
4696-
4697-
return;
4701+
return ret;
46984702
}
46994703

47004704
static int cma_remove_id_dev(struct rdma_id_private *id_priv)
@@ -4756,9 +4760,6 @@ static void cma_remove_one(struct ib_device *device, void *client_data)
47564760

47574761
trace_cm_remove_one(device);
47584762

4759-
if (!cma_dev)
4760-
return;
4761-
47624763
mutex_lock(&lock);
47634764
list_del(&cma_dev->list);
47644765
mutex_unlock(&lock);

drivers/infiniband/core/device.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -677,8 +677,20 @@ static int add_client_context(struct ib_device *device,
677677
if (ret)
678678
goto out;
679679
downgrade_write(&device->client_data_rwsem);
680-
if (client->add)
681-
client->add(device);
680+
if (client->add) {
681+
if (client->add(device)) {
682+
/*
683+
* If a client fails to add then the error code is
684+
* ignored, but we won't call any more ops on this
685+
* client.
686+
*/
687+
xa_erase(&device->client_data, client->client_id);
688+
up_read(&device->client_data_rwsem);
689+
ib_device_put(device);
690+
ib_client_put(client);
691+
return 0;
692+
}
693+
}
682694

683695
/* Readers shall not see a client until add has been completed */
684696
xa_set_mark(&device->client_data, client->client_id,

drivers/infiniband/core/mad.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3076,27 +3076,35 @@ static int ib_mad_port_close(struct ib_device *device, int port_num)
30763076
return 0;
30773077
}
30783078

3079-
static void ib_mad_init_device(struct ib_device *device)
3079+
static int ib_mad_init_device(struct ib_device *device)
30803080
{
30813081
int start, i;
3082+
unsigned int count = 0;
3083+
int ret;
30823084

30833085
start = rdma_start_port(device);
30843086

30853087
for (i = start; i <= rdma_end_port(device); i++) {
30863088
if (!rdma_cap_ib_mad(device, i))
30873089
continue;
30883090

3089-
if (ib_mad_port_open(device, i)) {
3091+
ret = ib_mad_port_open(device, i);
3092+
if (ret) {
30903093
dev_err(&device->dev, "Couldn't open port %d\n", i);
30913094
goto error;
30923095
}
3093-
if (ib_agent_port_open(device, i)) {
3096+
ret = ib_agent_port_open(device, i);
3097+
if (ret) {
30943098
dev_err(&device->dev,
30953099
"Couldn't open port %d for agents\n", i);
30963100
goto error_agent;
30973101
}
3102+
count++;
30983103
}
3099-
return;
3104+
if (!count)
3105+
return -EOPNOTSUPP;
3106+
3107+
return 0;
31003108

31013109
error_agent:
31023110
if (ib_mad_port_close(device, i))
@@ -3113,6 +3121,7 @@ static void ib_mad_init_device(struct ib_device *device)
31133121
if (ib_mad_port_close(device, i))
31143122
dev_err(&device->dev, "Couldn't close port %d\n", i);
31153123
}
3124+
return ret;
31163125
}
31173126

31183127
static void ib_mad_remove_device(struct ib_device *device, void *client_data)

drivers/infiniband/core/multicast.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
#include <rdma/ib_cache.h>
4343
#include "sa.h"
4444

45-
static void mcast_add_one(struct ib_device *device);
45+
static int mcast_add_one(struct ib_device *device);
4646
static void mcast_remove_one(struct ib_device *device, void *client_data);
4747

4848
static struct ib_client mcast_client = {
@@ -815,7 +815,7 @@ static void mcast_event_handler(struct ib_event_handler *handler,
815815
}
816816
}
817817

818-
static void mcast_add_one(struct ib_device *device)
818+
static int mcast_add_one(struct ib_device *device)
819819
{
820820
struct mcast_device *dev;
821821
struct mcast_port *port;
@@ -825,7 +825,7 @@ static void mcast_add_one(struct ib_device *device)
825825
dev = kmalloc(struct_size(dev, port, device->phys_port_cnt),
826826
GFP_KERNEL);
827827
if (!dev)
828-
return;
828+
return -ENOMEM;
829829

830830
dev->start_port = rdma_start_port(device);
831831
dev->end_port = rdma_end_port(device);
@@ -845,14 +845,15 @@ static void mcast_add_one(struct ib_device *device)
845845

846846
if (!count) {
847847
kfree(dev);
848-
return;
848+
return -EOPNOTSUPP;
849849
}
850850

851851
dev->device = device;
852852
ib_set_client_data(device, &mcast_client, dev);
853853

854854
INIT_IB_EVENT_HANDLER(&dev->event_handler, device, mcast_event_handler);
855855
ib_register_event_handler(&dev->event_handler);
856+
return 0;
856857
}
857858

858859
static void mcast_remove_one(struct ib_device *device, void *client_data)
@@ -861,9 +862,6 @@ static void mcast_remove_one(struct ib_device *device, void *client_data)
861862
struct mcast_port *port;
862863
int i;
863864

864-
if (!dev)
865-
return;
866-
867865
ib_unregister_event_handler(&dev->event_handler);
868866
flush_workqueue(mcast_wq);
869867

drivers/infiniband/core/sa_query.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ static const struct nla_policy ib_nl_policy[LS_NLA_TYPE_MAX] = {
174174
};
175175

176176

177-
static void ib_sa_add_one(struct ib_device *device);
177+
static int ib_sa_add_one(struct ib_device *device);
178178
static void ib_sa_remove_one(struct ib_device *device, void *client_data);
179179

180180
static struct ib_client sa_client = {
@@ -2322,18 +2322,19 @@ static void ib_sa_event(struct ib_event_handler *handler,
23222322
}
23232323
}
23242324

2325-
static void ib_sa_add_one(struct ib_device *device)
2325+
static int ib_sa_add_one(struct ib_device *device)
23262326
{
23272327
struct ib_sa_device *sa_dev;
23282328
int s, e, i;
23292329
int count = 0;
2330+
int ret;
23302331

23312332
s = rdma_start_port(device);
23322333
e = rdma_end_port(device);
23332334

23342335
sa_dev = kzalloc(struct_size(sa_dev, port, e - s + 1), GFP_KERNEL);
23352336
if (!sa_dev)
2336-
return;
2337+
return -ENOMEM;
23372338

23382339
sa_dev->start_port = s;
23392340
sa_dev->end_port = e;
@@ -2353,8 +2354,10 @@ static void ib_sa_add_one(struct ib_device *device)
23532354
ib_register_mad_agent(device, i + s, IB_QPT_GSI,
23542355
NULL, 0, send_handler,
23552356
recv_handler, sa_dev, 0);
2356-
if (IS_ERR(sa_dev->port[i].agent))
2357+
if (IS_ERR(sa_dev->port[i].agent)) {
2358+
ret = PTR_ERR(sa_dev->port[i].agent);
23572359
goto err;
2360+
}
23582361

23592362
INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah);
23602363
INIT_DELAYED_WORK(&sa_dev->port[i].ib_cpi_work,
@@ -2363,8 +2366,10 @@ static void ib_sa_add_one(struct ib_device *device)
23632366
count++;
23642367
}
23652368

2366-
if (!count)
2369+
if (!count) {
2370+
ret = -EOPNOTSUPP;
23672371
goto free;
2372+
}
23682373

23692374
ib_set_client_data(device, &sa_client, sa_dev);
23702375

@@ -2383,7 +2388,7 @@ static void ib_sa_add_one(struct ib_device *device)
23832388
update_sm_ah(&sa_dev->port[i].update_task);
23842389
}
23852390

2386-
return;
2391+
return 0;
23872392

23882393
err:
23892394
while (--i >= 0) {
@@ -2392,17 +2397,14 @@ static void ib_sa_add_one(struct ib_device *device)
23922397
}
23932398
free:
23942399
kfree(sa_dev);
2395-
return;
2400+
return ret;
23962401
}
23972402

23982403
static void ib_sa_remove_one(struct ib_device *device, void *client_data)
23992404
{
24002405
struct ib_sa_device *sa_dev = client_data;
24012406
int i;
24022407

2403-
if (!sa_dev)
2404-
return;
2405-
24062408
ib_unregister_event_handler(&sa_dev->event_handler);
24072409
flush_workqueue(ib_wq);
24082410

0 commit comments

Comments
 (0)