Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

RDMA/srp: Rename SRP sysfs name after IB device rename trigger

SRP logic used device name and port index as symlink to relevant
kobject. If the IB device is renamed then the prior name will be re-used
by the next device plugged in and sysfs will panic as SRP will try to
re-use the same name.

mlx5_ib: Mellanox Connect-IB Infiniband driver v5.0-0
sysfs: cannot create duplicate filename '/class/infiniband_srp/srp-mlx5_0-1'
CPU: 3 PID: 1107 Comm: modprobe Not tainted 5.1.0-for-upstream-perf-2019-05-12_15-09-52-87 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
Call Trace:
dump_stack+0x5a/0x73
sysfs_warn_dup+0x58/0x70
sysfs_do_create_link_sd.isra.2+0xa3/0xb0
device_add+0x33f/0x660
srp_add_one+0x301/0x4f0 [ib_srp]
add_client_context+0x99/0xe0 [ib_core]
enable_device_and_get+0xd1/0x1b0 [ib_core]
ib_register_device+0x533/0x710 [ib_core]
? mutex_lock+0xe/0x30
__mlx5_ib_add+0x23/0x70 [mlx5_ib]
mlx5_add_device+0x4e/0xd0 [mlx5_core]
mlx5_register_interface+0x85/0xc0 [mlx5_core]
? 0xffffffffa0791000
do_one_initcall+0x4b/0x1cb
? kmem_cache_alloc_trace+0xc6/0x1d0
? do_init_module+0x22/0x21f
do_init_module+0x5a/0x21f
load_module+0x17f2/0x1ca0
? m_show+0x1c0/0x1c0
__do_sys_finit_module+0x94/0xe0
do_syscall_64+0x48/0x120
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f157cce10d9

The module load/unload sequence was used to trigger such kernel panic:
sudo modprobe ib_srp
sudo modprobe -r mlx5_ib
sudo modprobe -r mlx5_core
sudo modprobe mlx5_core

Have SRP track the name of the core device so that it can't have a name
collision.

Fixes: d21943dd19b5 ("RDMA/core: Implement IB device rename function")
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>

authored by

Leon Romanovsky and committed by
Jason Gunthorpe
dc1435c0 a188339c

+44 -10
+26 -9
drivers/infiniband/core/device.c
··· 409 409 410 410 int ib_device_rename(struct ib_device *ibdev, const char *name) 411 411 { 412 + unsigned long index; 413 + void *client_data; 412 414 int ret; 413 415 414 416 down_write(&devices_rwsem); 415 417 if (!strcmp(name, dev_name(&ibdev->dev))) { 416 - ret = 0; 417 - goto out; 418 + up_write(&devices_rwsem); 419 + return 0; 418 420 } 419 421 420 422 if (__ib_device_get_by_name(name)) { 421 - ret = -EEXIST; 422 - goto out; 423 + up_write(&devices_rwsem); 424 + return -EEXIST; 423 425 } 424 426 425 427 ret = device_rename(&ibdev->dev, name); 426 - if (ret) 427 - goto out; 428 + if (ret) { 429 + up_write(&devices_rwsem); 430 + return ret; 431 + } 432 + 428 433 strlcpy(ibdev->name, name, IB_DEVICE_NAME_MAX); 429 434 ret = rename_compat_devs(ibdev); 430 - out: 431 - up_write(&devices_rwsem); 432 - return ret; 435 + 436 + downgrade_write(&devices_rwsem); 437 + down_read(&ibdev->client_data_rwsem); 438 + xan_for_each_marked(&ibdev->client_data, index, client_data, 439 + CLIENT_DATA_REGISTERED) { 440 + struct ib_client *client = xa_load(&clients, index); 441 + 442 + if (!client || !client->rename) 443 + continue; 444 + 445 + client->rename(ibdev, client_data); 446 + } 447 + up_read(&ibdev->client_data_rwsem); 448 + up_read(&devices_rwsem); 449 + return 0; 433 450 } 434 451 435 452 static int alloc_name(struct ib_device *ibdev, const char *name)
+17 -1
drivers/infiniband/ulp/srp/ib_srp.c
··· 148 148 149 149 static void srp_add_one(struct ib_device *device); 150 150 static void srp_remove_one(struct ib_device *device, void *client_data); 151 + static void srp_rename_dev(struct ib_device *device, void *client_data); 151 152 static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc); 152 153 static void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc, 153 154 const char *opname); ··· 163 162 static struct ib_client srp_client = { 164 163 .name = "srp", 165 164 .add = srp_add_one, 166 - .remove = srp_remove_one 165 + .remove = srp_remove_one, 166 + .rename = srp_rename_dev 167 167 }; 168 168 169 169 static struct ib_sa_client srp_sa_client; ··· 4112 4110 kfree(host); 4113 4111 4114 4112 return NULL; 4113 + } 4114 + 4115 + static void srp_rename_dev(struct ib_device *device, void *client_data) 4116 + { 4117 + struct srp_device *srp_dev = client_data; 4118 + struct srp_host *host, *tmp_host; 4119 + 4120 + list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) { 4121 + char name[IB_DEVICE_NAME_MAX + 8]; 4122 + 4123 + snprintf(name, sizeof(name), "srp-%s-%d", 4124 + dev_name(&device->dev), host->port); 4125 + device_rename(&host->dev, name); 4126 + } 4115 4127 } 4116 4128 4117 4129 static void srp_add_one(struct ib_device *device)
+1
include/rdma/ib_verbs.h
··· 2698 2698 const char *name; 2699 2699 void (*add) (struct ib_device *); 2700 2700 void (*remove)(struct ib_device *, void *client_data); 2701 + void (*rename)(struct ib_device *dev, void *client_data); 2701 2702 2702 2703 /* Returns the net_dev belonging to this ib_client and matching the 2703 2704 * given parameters.