* [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace
@ 2026-07-14 14:29 Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 01/14] RDMA/core: Pass the net namespace to the device name lookups Jiri Pirko
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
RDMA device names are unique system-wide today:
__ib_device_get_by_name() checks a requested name against every
registered device regardless of the network namespace it lives in.
A device in one network namespace therefore cannot use a name already
taken in another, even in exclusive netns mode (netns_mode=0) where
the two are otherwise isolated. Net devices have no such restriction -
their names only need to be unique within a network namespace.
This series makes RDMA device names unique per network namespace,
matching net device semantics, and adapts the users that assumed
system-wide unique names.
Scoping reuses the existing rdma_dev_access_netns() predicate, so
behavior only changes in exclusive mode:
- shared mode (default): names stay unique system-wide, no change;
- exclusive mode: names only need to be unique within a namespace;
- CONFIG_NET_NS=n: everything is init_net, names stay system-wide
unique.
There are two users that cannot be made per-namespace and are
documented as known limitations instead of changed:
- the rdma_cm configfs tree: configfs has no network namespace
support, so it cannot represent two same-named devices;
- SELinux ibendport labelling: endports are labelled by (device
name, port) from a global policy; distinguishing same-named
devices would need net namespace support in the SELinux policy
language and tooling.
Tested with the new rxe_netns_names kselftest added in the last patch.
Jiri Pirko (14):
RDMA/core: Pass the net namespace to the device name lookups
RDMA/core: Handle device name conflicts when changing net namespace
RDMA/core: Support renaming a device when changing its net namespace
RDMA/nldev: Report net namespace move errors through extack
RDMA/nldev: Allow setting the device name while changing net namespace
net/smc: Look up the pnetid ib device within the net namespace
RDMA/srp: Make the SRP sysfs class net namespace aware
RDMA/cgroup: Disambiguate devices across net namespaces
RDMA/cma: Document that CM configfs cannot be net namespace scoped
RDMA/core: Document the SELinux ibendport net namespace limitation
RDMA/core: Make device names unique per net namespace
RDMA/rxe: Allow queue VMAs to outlive ucontexts
RDMA/rxe: Implement disassociate_ucontext callback
RDMA/selftests: Add rxe_netns_names test
Documentation/ABI/testing/configfs-rdma_cm | 4 +
Documentation/admin-guide/cgroup-v1/rdma.rst | 8 +
Documentation/admin-guide/cgroup-v2.rst | 15 +-
drivers/infiniband/core/cgroup.c | 1 +
drivers/infiniband/core/cma_configfs.c | 4 +
drivers/infiniband/core/core_priv.h | 3 +-
drivers/infiniband/core/device.c | 245 ++++++++++++---
drivers/infiniband/core/nldev.c | 26 +-
drivers/infiniband/core/security.c | 6 +
drivers/infiniband/sw/rxe/rxe_mmap.c | 35 +--
drivers/infiniband/sw/rxe/rxe_verbs.c | 5 +
drivers/infiniband/ulp/srp/ib_srp.c | 16 +-
include/linux/cgroup_rdma.h | 1 +
include/uapi/rdma/rdma_netlink.h | 5 +-
kernel/cgroup/rdma.c | 71 ++++-
net/smc/smc_pnet.c | 20 +-
tools/testing/selftests/rdma/Makefile | 3 +-
tools/testing/selftests/rdma/config | 2 +
.../testing/selftests/rdma/rxe_netns_names.sh | 282 ++++++++++++++++++
19 files changed, 653 insertions(+), 99 deletions(-)
create mode 100755 tools/testing/selftests/rdma/rxe_netns_names.sh
--
2.54.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 01/14] RDMA/core: Pass the net namespace to the device name lookups
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 02/14] RDMA/core: Handle device name conflicts when changing net namespace Jiri Pirko
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Prepare for per-netns RDMA device names by passing the target net
namespace through the name lookup and allocation helpers. Keep current
global uniqueness behaviour.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/device.c | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index b8193e077a74..de610f52c9b2 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -351,7 +351,8 @@ void ib_device_put(struct ib_device *device)
}
EXPORT_SYMBOL(ib_device_put);
-static struct ib_device *__ib_device_get_by_name(const char *name)
+static struct ib_device *__ib_device_get_by_name(const char *name,
+ const struct net *net)
{
struct ib_device *device;
unsigned long index;
@@ -395,7 +396,7 @@ int ib_device_rename(struct ib_device *ibdev, const char *name)
return 0;
}
- if (__ib_device_get_by_name(name)) {
+ if (__ib_device_get_by_name(name, rdma_dev_net(ibdev))) {
up_write(&devices_rwsem);
return -EEXIST;
}
@@ -435,7 +436,8 @@ int ib_device_set_dim(struct ib_device *ibdev, u8 use_dim)
return 0;
}
-static int alloc_name(struct ib_device *ibdev, const char *name)
+/* Pick a free index for the '%d' style @name pattern. */
+static int alloc_name_id(struct net *net, const char *name)
{
struct ib_device *device;
unsigned long index;
@@ -462,15 +464,22 @@ static int alloc_name(struct ib_device *ibdev, const char *name)
}
rc = ida_alloc(&inuse, GFP_KERNEL);
- if (rc < 0)
- goto out;
-
- rc = dev_set_name(&ibdev->dev, name, rc);
out:
ida_destroy(&inuse);
return rc;
}
+static int alloc_name(struct ib_device *ibdev, const char *name)
+{
+ int id;
+
+ id = alloc_name_id(rdma_dev_net(ibdev), name);
+ if (id < 0)
+ return id;
+
+ return dev_set_name(&ibdev->dev, name, id);
+}
+
static void ib_device_release(struct device *device)
{
struct ib_device *dev = container_of(device, struct ib_device, dev);
@@ -1223,7 +1232,8 @@ static int assign_name(struct ib_device *device, const char *name)
if (ret)
goto out;
- if (__ib_device_get_by_name(dev_name(&device->dev))) {
+ if (__ib_device_get_by_name(dev_name(&device->dev),
+ rdma_dev_net(device))) {
ret = -ENFILE;
goto out;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 02/14] RDMA/core: Handle device name conflicts when changing net namespace
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 01/14] RDMA/core: Pass the net namespace to the device name lookups Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 03/14] RDMA/core: Support renaming a device when changing its " Jiri Pirko
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Prepare namespace moves for per-netns names. Check user-initiated moves for
destination-name conflicts before disabling the device, keep same-netns
moves as no-ops, and make teardown moves detach from the exiting namespace
even if fallback naming fails.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v1->v2:
- fixed possible bogus race-triggered-WARN in rdma_dev_exit_net()
---
drivers/infiniband/core/device.c | 155 ++++++++++++++++++++++++++-----
drivers/infiniband/core/nldev.c | 3 +
2 files changed, 137 insertions(+), 21 deletions(-)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index de610f52c9b2..b55fb075d0ae 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -268,7 +268,7 @@ static struct notifier_block ibdev_lsm_nb = {
};
static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
- struct net *net);
+ struct net *net, const char *fallback_pattern);
/* Pointer to the RCU head at the start of the ib_port_data array */
struct ib_port_data_rcu {
@@ -437,7 +437,8 @@ int ib_device_set_dim(struct ib_device *ibdev, u8 use_dim)
}
/* Pick a free index for the '%d' style @name pattern. */
-static int alloc_name_id(struct net *net, const char *name)
+static int __alloc_name_id(struct net *net, const char *name,
+ const struct ib_device *skip)
{
struct ib_device *device;
unsigned long index;
@@ -450,6 +451,8 @@ static int alloc_name_id(struct net *net, const char *name)
xa_for_each (&devices, index, device) {
char buf[IB_DEVICE_NAME_MAX];
+ if (device == skip)
+ continue;
if (sscanf(dev_name(&device->dev), name, &i) != 1)
continue;
if (i < 0 || i >= INT_MAX)
@@ -469,6 +472,11 @@ static int alloc_name_id(struct net *net, const char *name)
return rc;
}
+static int alloc_name_id(struct net *net, const char *name)
+{
+ return __alloc_name_id(net, name, NULL);
+}
+
static int alloc_name(struct ib_device *ibdev, const char *name)
{
int id;
@@ -1160,8 +1168,17 @@ static void rdma_dev_exit_net(struct net *net)
/*
* If the real device is in the NS then move it back to init.
+ * Provide a fallback pattern so a name conflict in init_net
+ * cannot make the teardown move fail.
*/
- rdma_dev_change_netns(dev, net, &init_net);
+ if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
+ ret = rdma_dev_change_netns(dev, net, &init_net,
+ "ibdev%d");
+ if (ret && ret != -ENODEV)
+ WARN(1,
+ "Failed to move RDMA device %s to init_net on netns exit: %d\n",
+ dev_name(&dev->dev), ret);
+ }
put_device(&dev->dev);
down_read(&devices_rwsem);
@@ -1680,14 +1697,71 @@ void ib_unregister_device_queued(struct ib_device *ib_dev)
}
EXPORT_SYMBOL(ib_unregister_device_queued);
+static bool rdma_dev_name_in_netns(struct ib_device *skip, struct net *net,
+ const char *name)
+{
+ struct ib_device *device;
+ unsigned long index;
+
+ lockdep_assert_held_write(&devices_rwsem);
+
+ xa_for_each(&devices, index, device)
+ if (device != skip &&
+ !strcmp(name, dev_name(&device->dev)))
+ return true;
+
+ return false;
+}
+
+/*
+ * Choose the name @device should use in net namespace @net: keep the current
+ * name when it is free, otherwise use a trusted '%d' @fallback_pattern
+ * (namespace teardown) to pick a free index. The caller must hold the write
+ * side of devices_rwsem.
+ */
+static int rdma_dev_pick_netns_name(struct ib_device *device, struct net *net,
+ const char *fallback_pattern,
+ char *buf, size_t buf_len,
+ const char **new_name)
+{
+ int id;
+
+ lockdep_assert_held_write(&devices_rwsem);
+
+ if (!rdma_dev_name_in_netns(device, net, dev_name(&device->dev))) {
+ *new_name = dev_name(&device->dev);
+ return 0;
+ }
+
+ if (!fallback_pattern)
+ return -EEXIST;
+
+ snprintf(buf, buf_len, "ibdev%u", device->index);
+ if (!rdma_dev_name_in_netns(device, net, buf)) {
+ *new_name = buf;
+ return 0;
+ }
+
+ id = __alloc_name_id(net, fallback_pattern, device);
+ if (id < 0)
+ return id;
+ snprintf(buf, buf_len, fallback_pattern, id);
+ *new_name = buf;
+ return 0;
+}
+
/*
* The caller must pass in a device that has the kref held and the refcount
* released. If the device is in cur_net and still registered then it is moved
* into net.
+ *
+ * Naming rules are handled by rdma_dev_pick_netns_name().
*/
static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
- struct net *net)
+ struct net *net, const char *fallback_pattern)
{
+ char buf[IB_DEVICE_NAME_MAX];
+ const char *new_name;
int ret2 = -EINVAL;
int ret;
@@ -1704,30 +1778,63 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
goto out;
}
+ if (!fallback_pattern) {
+ /*
+ * Reject a predictable name conflict before tearing anything
+ * down, so a doomed user move does not disable a live device.
+ */
+ down_write(&devices_rwsem);
+ ret = rdma_dev_pick_netns_name(device, net, fallback_pattern,
+ buf, sizeof(buf), &new_name);
+ up_write(&devices_rwsem);
+ if (ret)
+ goto out;
+ }
+
kobject_uevent(&device->dev.kobj, KOBJ_REMOVE);
disable_device(device);
/*
- * At this point no one can be using the device, so it is safe to
- * change the namespace.
+ * Recompute the destination name under the write side of devices_rwsem
+ * now that the device is disabled, closing races with a concurrent
+ * registration or rename, then publish the new namespace at the sysfs
+ * level.
*/
- write_pnet(&device->coredev.rdma_net, net);
+ down_write(&devices_rwsem);
+ ret = rdma_dev_pick_netns_name(device, net, fallback_pattern, buf,
+ sizeof(buf), &new_name);
+ if (ret) {
+ if (fallback_pattern) {
+ WARN(1,
+ "%s: failed to pick device name during namespace teardown: %d\n",
+ __func__, ret);
+ write_pnet(&device->coredev.rdma_net, net);
+ ret = 0;
+ }
+ goto rename_done;
+ }
- down_read(&devices_rwsem);
- /*
- * Currently rdma devices are system wide unique. So the device name
- * is guaranteed free in the new namespace. Publish the new namespace
- * at the sysfs level.
- */
- ret = device_rename(&device->dev, dev_name(&device->dev));
- up_read(&devices_rwsem);
+ write_pnet(&device->coredev.rdma_net, net);
+ ret = device_rename(&device->dev, new_name);
if (ret) {
- dev_warn(&device->dev,
- "%s: Couldn't rename device after namespace change\n",
- __func__);
- /* Try and put things back and re-enable the device */
- write_pnet(&device->coredev.rdma_net, cur_net);
+ if (fallback_pattern) {
+ WARN(1,
+ "%s: failed to rename device during namespace teardown: %d\n",
+ __func__, ret);
+ ret = 0;
+ } else {
+ dev_warn(&device->dev,
+ "%s: Couldn't rename device after namespace change\n",
+ __func__);
+ /* Try and put things back and re-enable the device */
+ write_pnet(&device->coredev.rdma_net, cur_net);
+ }
+ } else {
+ strscpy(device->name, dev_name(&device->dev),
+ IB_DEVICE_NAME_MAX);
}
+rename_done:
+ up_write(&devices_rwsem);
ret2 = enable_device_and_get(device);
if (ret2) {
@@ -1766,6 +1873,12 @@ int ib_device_set_netns_put(struct sk_buff *skb,
goto ns_err;
}
+ /* Moving a device to the namespace it already lives in is a no-op. */
+ if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
+ ret = 0;
+ goto ns_err;
+ }
+
/*
* All the ib_clients, including uverbs, are reset when the namespace is
* changed and this cannot be blocked waiting for userspace to do
@@ -1778,7 +1891,7 @@ int ib_device_set_netns_put(struct sk_buff *skb,
get_device(&dev->dev);
ib_device_put(dev);
- ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net);
+ ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net, NULL);
put_device(&dev->dev);
put_net(net);
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index aae4f3f6bcba..32b6c4d68ca0 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1196,6 +1196,9 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
err = ib_device_set_netns_put(skb, device, ns_fd);
+ if (err == -EEXIST)
+ NL_SET_ERR_MSG(extack,
+ "Device name already exists in the target net namespace");
goto put_done;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 03/14] RDMA/core: Support renaming a device when changing its net namespace
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 01/14] RDMA/core: Pass the net namespace to the device name lookups Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 02/14] RDMA/core: Handle device name conflicts when changing net namespace Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 04/14] RDMA/nldev: Report net namespace move errors through extack Jiri Pirko
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Allow namespace moves to request a destination device name. Keep requested
names on the same literal-name path as the existing RDMA rename operation,
and keep teardown fallback naming on the trusted kernel-controlled path.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/core_priv.h | 2 +-
drivers/infiniband/core/device.c | 48 ++++++++++++++++++++---------
drivers/infiniband/core/nldev.c | 2 +-
3 files changed, 35 insertions(+), 17 deletions(-)
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 19104c542b27..3bd5bb7135a3 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -356,7 +356,7 @@ void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,
const struct attribute_group **groups);
int ib_device_set_netns_put(struct sk_buff *skb,
- struct ib_device *dev, u32 ns_fd);
+ struct ib_device *dev, u32 ns_fd, const char *name);
int rdma_nl_net_init(struct rdma_dev_net *rnet);
void rdma_nl_net_exit(struct rdma_dev_net *rnet);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index b55fb075d0ae..c0b6613dba4c 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -268,7 +268,8 @@ static struct notifier_block ibdev_lsm_nb = {
};
static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
- struct net *net, const char *fallback_pattern);
+ struct net *net, const char *requested_name,
+ const char *fallback_pattern);
/* Pointer to the RCU head at the start of the ib_port_data array */
struct ib_port_data_rcu {
@@ -1173,7 +1174,7 @@ static void rdma_dev_exit_net(struct net *net)
*/
if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
ret = rdma_dev_change_netns(dev, net, &init_net,
- "ibdev%d");
+ NULL, "ibdev%d");
if (ret && ret != -ENODEV)
WARN(1,
"Failed to move RDMA device %s to init_net on netns exit: %d\n",
@@ -1714,12 +1715,13 @@ static bool rdma_dev_name_in_netns(struct ib_device *skip, struct net *net,
}
/*
- * Choose the name @device should use in net namespace @net: keep the current
- * name when it is free, otherwise use a trusted '%d' @fallback_pattern
- * (namespace teardown) to pick a free index. The caller must hold the write
- * side of devices_rwsem.
+ * Choose the name @device should use in net namespace @net. @requested_name
+ * is used as a literal device name when set. Otherwise keep the current name
+ * when it is free, or use a trusted '%d' @fallback_pattern for teardown. The
+ * caller must hold the write side of devices_rwsem.
*/
static int rdma_dev_pick_netns_name(struct ib_device *device, struct net *net,
+ const char *requested_name,
const char *fallback_pattern,
char *buf, size_t buf_len,
const char **new_name)
@@ -1728,6 +1730,15 @@ static int rdma_dev_pick_netns_name(struct ib_device *device, struct net *net,
lockdep_assert_held_write(&devices_rwsem);
+ if (requested_name) {
+ if (!rdma_dev_name_in_netns(device, net, requested_name)) {
+ *new_name = requested_name;
+ return 0;
+ }
+
+ return -EEXIST;
+ }
+
if (!rdma_dev_name_in_netns(device, net, dev_name(&device->dev))) {
*new_name = dev_name(&device->dev);
return 0;
@@ -1758,7 +1769,8 @@ static int rdma_dev_pick_netns_name(struct ib_device *device, struct net *net,
* Naming rules are handled by rdma_dev_pick_netns_name().
*/
static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
- struct net *net, const char *fallback_pattern)
+ struct net *net, const char *requested_name,
+ const char *fallback_pattern)
{
char buf[IB_DEVICE_NAME_MAX];
const char *new_name;
@@ -1784,8 +1796,9 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
* down, so a doomed user move does not disable a live device.
*/
down_write(&devices_rwsem);
- ret = rdma_dev_pick_netns_name(device, net, fallback_pattern,
- buf, sizeof(buf), &new_name);
+ ret = rdma_dev_pick_netns_name(device, net, requested_name,
+ fallback_pattern, buf,
+ sizeof(buf), &new_name);
up_write(&devices_rwsem);
if (ret)
goto out;
@@ -1801,8 +1814,9 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
* level.
*/
down_write(&devices_rwsem);
- ret = rdma_dev_pick_netns_name(device, net, fallback_pattern, buf,
- sizeof(buf), &new_name);
+ ret = rdma_dev_pick_netns_name(device, net, requested_name,
+ fallback_pattern, buf, sizeof(buf),
+ &new_name);
if (ret) {
if (fallback_pattern) {
WARN(1,
@@ -1857,7 +1871,7 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
}
int ib_device_set_netns_put(struct sk_buff *skb,
- struct ib_device *dev, u32 ns_fd)
+ struct ib_device *dev, u32 ns_fd, const char *name)
{
struct net *net;
int ret;
@@ -1873,9 +1887,12 @@ int ib_device_set_netns_put(struct sk_buff *skb,
goto ns_err;
}
- /* Moving a device to the namespace it already lives in is a no-op. */
+ /*
+ * Moving a device to the namespace it already lives in is a no-op; a
+ * supplied name still renames it in place.
+ */
if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
- ret = 0;
+ ret = name ? ib_device_rename(dev, name) : 0;
goto ns_err;
}
@@ -1891,7 +1908,8 @@ int ib_device_set_netns_put(struct sk_buff *skb,
get_device(&dev->dev);
ib_device_put(dev);
- ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net, NULL);
+ ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net, name,
+ NULL);
put_device(&dev->dev);
put_net(net);
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 32b6c4d68ca0..77a758080148 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1195,7 +1195,7 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
u32 ns_fd;
ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
- err = ib_device_set_netns_put(skb, device, ns_fd);
+ err = ib_device_set_netns_put(skb, device, ns_fd, NULL);
if (err == -EEXIST)
NL_SET_ERR_MSG(extack,
"Device name already exists in the target net namespace");
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 04/14] RDMA/nldev: Report net namespace move errors through extack
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
` (2 preceding siblings ...)
2026-07-14 14:29 ` [PATCH rdma-next v2 03/14] RDMA/core: Support renaming a device when changing its " Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 05/14] RDMA/nldev: Allow setting the device name while changing net namespace Jiri Pirko
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Thread extack through the existing net namespace move helper and report the
main failure reasons from the core path. Keep the existing move UAPI shape
unchanged.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/core_priv.h | 3 ++-
drivers/infiniband/core/device.c | 24 ++++++++++++++++++++++--
drivers/infiniband/core/nldev.c | 6 ++----
3 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 3bd5bb7135a3..aaf330b0d333 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -356,7 +356,8 @@ void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,
const struct attribute_group **groups);
int ib_device_set_netns_put(struct sk_buff *skb,
- struct ib_device *dev, u32 ns_fd, const char *name);
+ struct ib_device *dev, u32 ns_fd, const char *name,
+ struct netlink_ext_ack *extack);
int rdma_nl_net_init(struct rdma_dev_net *rnet);
void rdma_nl_net_exit(struct rdma_dev_net *rnet);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index c0b6613dba4c..366bd8463c07 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1871,18 +1871,22 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
}
int ib_device_set_netns_put(struct sk_buff *skb,
- struct ib_device *dev, u32 ns_fd, const char *name)
+ struct ib_device *dev, u32 ns_fd, const char *name,
+ struct netlink_ext_ack *extack)
{
struct net *net;
int ret;
net = get_net_ns_by_fd(ns_fd);
if (IS_ERR(net)) {
+ NL_SET_ERR_MSG(extack, "Invalid target net namespace fd");
ret = PTR_ERR(net);
goto net_err;
}
if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
+ NL_SET_ERR_MSG(extack,
+ "Missing CAP_NET_ADMIN in the target net namespace");
ret = -EPERM;
goto ns_err;
}
@@ -1893,6 +1897,10 @@ int ib_device_set_netns_put(struct sk_buff *skb,
*/
if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
ret = name ? ib_device_rename(dev, name) : 0;
+
+ if (ret == -EEXIST)
+ NL_SET_ERR_MSG(extack,
+ "Device name already exists in the target net namespace");
goto ns_err;
}
@@ -1901,7 +1909,16 @@ int ib_device_set_netns_put(struct sk_buff *skb,
* changed and this cannot be blocked waiting for userspace to do
* something, so disassociation is mandatory.
*/
- if (!dev->ops.disassociate_ucontext || ib_devices_shared_netns) {
+ if (ib_devices_shared_netns) {
+ NL_SET_ERR_MSG(extack,
+ "Cannot change net namespace of RDMA device in shared netns mode");
+ ret = -EOPNOTSUPP;
+ goto ns_err;
+ }
+
+ if (!dev->ops.disassociate_ucontext) {
+ NL_SET_ERR_MSG(extack,
+ "Device does not support namespace changes (no disassociate support)");
ret = -EOPNOTSUPP;
goto ns_err;
}
@@ -1911,6 +1928,9 @@ int ib_device_set_netns_put(struct sk_buff *skb,
ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net, name,
NULL);
put_device(&dev->dev);
+ if (ret == -EEXIST)
+ NL_SET_ERR_MSG(extack,
+ "Device name already exists in the target net namespace");
put_net(net);
return ret;
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 77a758080148..8648e95700bf 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1195,10 +1195,8 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
u32 ns_fd;
ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
- err = ib_device_set_netns_put(skb, device, ns_fd, NULL);
- if (err == -EEXIST)
- NL_SET_ERR_MSG(extack,
- "Device name already exists in the target net namespace");
+ err = ib_device_set_netns_put(skb, device, ns_fd, NULL,
+ extack);
goto put_done;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 05/14] RDMA/nldev: Allow setting the device name while changing net namespace
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
` (3 preceding siblings ...)
2026-07-14 14:29 ` [PATCH rdma-next v2 04/14] RDMA/nldev: Report net namespace move errors through extack Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 06/14] net/smc: Look up the pnetid ib device within the " Jiri Pirko
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Accept RDMA_NLDEV_ATTR_DEV_NAME together with RDMA_NLDEV_NET_NS_FD so a
netlink move can rename the device in the destination namespace. Keep the
name semantics aligned with the existing RDMA rename path.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/device.c | 6 ++++++
drivers/infiniband/core/nldev.c | 27 ++++++++++++++++++---------
include/uapi/rdma/rdma_netlink.h | 5 ++++-
3 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 366bd8463c07..bb02640239d7 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1901,6 +1901,9 @@ int ib_device_set_netns_put(struct sk_buff *skb,
if (ret == -EEXIST)
NL_SET_ERR_MSG(extack,
"Device name already exists in the target net namespace");
+ else if (ret == -EINVAL && name)
+ NL_SET_ERR_MSG(extack,
+ "Unable to use requested device name in the target net namespace");
goto ns_err;
}
@@ -1931,6 +1934,9 @@ int ib_device_set_netns_put(struct sk_buff *skb,
if (ret == -EEXIST)
NL_SET_ERR_MSG(extack,
"Device name already exists in the target net namespace");
+ else if (ret == -EINVAL && name)
+ NL_SET_ERR_MSG(extack,
+ "Unable to use requested device name in the target net namespace");
put_net(net);
return ret;
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 8648e95700bf..4efa387ec1be 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1178,6 +1178,24 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
if (!device)
return -EINVAL;
+ if (tb[RDMA_NLDEV_NET_NS_FD]) {
+ char name[IB_DEVICE_NAME_MAX] = {};
+ u32 ns_fd;
+
+ if (tb[RDMA_NLDEV_ATTR_DEV_NAME]) {
+ nla_strscpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
+ IB_DEVICE_NAME_MAX);
+ if (strlen(name) == 0) {
+ err = -EINVAL;
+ goto done;
+ }
+ }
+ ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
+ err = ib_device_set_netns_put(skb, device, ns_fd,
+ name[0] ? name : NULL, extack);
+ goto put_done;
+ }
+
if (tb[RDMA_NLDEV_ATTR_DEV_NAME]) {
char name[IB_DEVICE_NAME_MAX] = {};
@@ -1191,15 +1209,6 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
goto done;
}
- if (tb[RDMA_NLDEV_NET_NS_FD]) {
- u32 ns_fd;
-
- ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
- err = ib_device_set_netns_put(skb, device, ns_fd, NULL,
- extack);
- goto put_done;
- }
-
if (tb[RDMA_NLDEV_ATTR_DEV_DIM]) {
u8 use_dim;
diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h
index 3af946ecbac3..ee11c3bbbae2 100644
--- a/include/uapi/rdma/rdma_netlink.h
+++ b/include/uapi/rdma/rdma_netlink.h
@@ -516,7 +516,10 @@ enum rdma_nldev_attr {
RDMA_NLDEV_ATTR_DEV_PROTOCOL, /* string */
/*
- * File descriptor handle of the net namespace object
+ * File descriptor handle of the net namespace object. May be combined
+ * with RDMA_NLDEV_ATTR_DEV_NAME (a literal device name) to also rename
+ * the device in the destination namespace; the move fails with -EEXIST
+ * if that name is already taken there.
*/
RDMA_NLDEV_NET_NS_FD, /* u32 */
/*
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 06/14] net/smc: Look up the pnetid ib device within the net namespace
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
` (4 preceding siblings ...)
2026-07-14 14:29 ` [PATCH rdma-next v2 05/14] RDMA/nldev: Allow setting the device name while changing net namespace Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 07/14] RDMA/srp: Make the SRP sysfs class net namespace aware Jiri Pirko
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Scope smc_pnet_find_ib() to the caller's net namespace so pnetid setup
cannot bind to a same-named RDMA device from another namespace once names
become per-netns.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
net/smc/smc_pnet.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
index 63e286e2dfaa..ff9c9c35cc2f 100644
--- a/net/smc/smc_pnet.c
+++ b/net/smc/smc_pnet.c
@@ -304,13 +304,18 @@ static bool smc_pnetid_valid(const char *pnet_name, char *pnetid)
return true;
}
-/* Find an infiniband device by a given name. The device might not exist. */
-static struct smc_ib_device *smc_pnet_find_ib(char *ib_name)
+/*
+ * Find an infiniband device by a given name, restricted to the devices
+ * accessible from @net. The device might not exist.
+ */
+static struct smc_ib_device *smc_pnet_find_ib(struct net *net, char *ib_name)
{
struct smc_ib_device *ibdev;
mutex_lock(&smc_ib_devices.mutex);
list_for_each_entry(ibdev, &smc_ib_devices.list, list) {
+ if (!rdma_dev_access_netns(ibdev->ibdev, net))
+ continue;
if (!strncmp(ibdev->ibdev->name, ib_name,
sizeof(ibdev->ibdev->name)) ||
(ibdev->ibdev->dev.parent &&
@@ -408,8 +413,8 @@ static int smc_pnet_add_eth(struct smc_pnettable *pnettable, struct net *net,
return rc;
}
-static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name,
- u8 ib_port, char *pnet_name)
+static int smc_pnet_add_ib(struct smc_pnettable *pnettable, struct net *net,
+ char *ib_name, u8 ib_port, char *pnet_name)
{
struct smc_pnetentry *tmp_pe, *new_pe;
struct smc_ib_device *ib_dev;
@@ -419,7 +424,7 @@ static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name,
bool new_ibdev;
/* try to apply the pnetid to active devices */
- ib_dev = smc_pnet_find_ib(ib_name);
+ ib_dev = smc_pnet_find_ib(net, ib_name);
if (ib_dev) {
ibdev_applied = smc_pnet_apply_ib(ib_dev, ib_port, pnet_name);
if (ibdev_applied)
@@ -518,7 +523,7 @@ static int smc_pnet_enter(struct net *net, struct nlattr *tb[])
if (ibport < 1 || ibport > SMC_MAX_PORTS)
goto error;
}
- rc = smc_pnet_add_ib(pnettable, string, ibport, pnet_name);
+ rc = smc_pnet_add_ib(pnettable, net, string, ibport, pnet_name);
if (!rc)
new_ibdev = true;
else if (rc != -EEXIST)
@@ -1170,6 +1175,9 @@ int smc_pnetid_by_table_ib(struct smc_ib_device *smcibdev, u8 ib_port)
struct smc_net *sn;
int rc = -ENOENT;
+ if (!rdma_dev_access_netns(smcibdev->ibdev, &init_net))
+ return -ENOENT;
+
/* get pnettable for init namespace */
sn = net_generic(&init_net, smc_net_id);
pnettable = &sn->pnettable;
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 07/14] RDMA/srp: Make the SRP sysfs class net namespace aware
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
` (5 preceding siblings ...)
2026-07-14 14:29 ` [PATCH rdma-next v2 06/14] net/smc: Look up the pnetid ib device within the " Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 08/14] RDMA/cgroup: Disambiguate devices across net namespaces Jiri Pirko
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Tag srp_class by the RDMA device's net namespace so SRP hosts derived from
same-named RDMA devices can coexist across namespaces.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/ulp/srp/ib_srp.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 0caebbc2810f..2fc8e133c70f 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -3189,10 +3189,24 @@ static struct attribute *srp_class_attrs[];
ATTRIBUTE_GROUPS(srp_class);
+/*
+ * SRP hosts are named after their ib device, so tag the class by the ib
+ * device's net namespace.
+ */
+static const struct ns_common *srp_net_namespace(const struct device *dev)
+{
+ struct srp_host *host = container_of(dev, struct srp_host, dev);
+ struct net *net = rdma_dev_net(host->srp_dev->dev);
+
+ return net ? to_ns_common(net) : NULL;
+}
+
static struct class srp_class = {
.name = "infiniband_srp",
.dev_groups = srp_class_groups,
- .dev_release = srp_release_dev
+ .dev_release = srp_release_dev,
+ .ns_type = &net_ns_type_operations,
+ .namespace = srp_net_namespace,
};
/**
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 08/14] RDMA/cgroup: Disambiguate devices across net namespaces
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
` (6 preceding siblings ...)
2026-07-14 14:29 ` [PATCH rdma-next v2 07/14] RDMA/srp: Make the SRP sysfs class net namespace aware Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 09/14] RDMA/cma: Document that CM configfs cannot be net namespace scoped Jiri Pirko
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
RDMA device names are unique only within a network namespace, but an
RDMA cgroup can account resources for devices from multiple namespaces.
Duplicate names therefore make cgroup output ambiguous and can cause
limit writes to select the wrong device.
Use the system-wide RDMA device index to distinguish duplicate names
while preserving the existing UAPI for unique names. Reject ambiguous
name-only writes with -ENOTUNIQ and expose a complete device view to
administrators.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v1->v2:
- replace caller-netns filtering with global visibility and index-based
disambiguation
---
Documentation/admin-guide/cgroup-v1/rdma.rst | 8 +++
Documentation/admin-guide/cgroup-v2.rst | 15 ++++-
drivers/infiniband/core/cgroup.c | 1 +
include/linux/cgroup_rdma.h | 1 +
kernel/cgroup/rdma.c | 71 ++++++++++++++++----
5 files changed, 83 insertions(+), 13 deletions(-)
diff --git a/Documentation/admin-guide/cgroup-v1/rdma.rst b/Documentation/admin-guide/cgroup-v1/rdma.rst
index e69369b7252e..8d0c3a796ee3 100644
--- a/Documentation/admin-guide/cgroup-v1/rdma.rst
+++ b/Documentation/admin-guide/cgroup-v1/rdma.rst
@@ -90,6 +90,13 @@ Following resources can be accounted by rdma controller.
hca_object Maximum number of HCA Objects
========== =============================
+RDMA devices from all network namespaces are listed. Each line starts with
+the device name. If more than one device has the same name, ``index=N``
+follows the name, where ``N`` is the system-wide RDMA device index, unique
+among registered devices. When configuring a limit, the index is optional
+for a globally unique name and required for a duplicate name. A write without
+the required index fails with ``-ENOTUNIQ``.
+
2. Usage Examples
=================
@@ -97,6 +104,7 @@ Following resources can be accounted by rdma controller.
echo mlx4_0 hca_handle=2 hca_object=2000 > /sys/fs/cgroup/rdma/1/rdma.max
echo ocrdma1 hca_handle=3 > /sys/fs/cgroup/rdma/2/rdma.max
+ echo "rxe0 index=5 hca_handle=2" > /sys/fs/cgroup/rdma/3/rdma.max
(b) Query resource limit::
diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index 993446ab66d0..df74d554d2cd 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -2752,6 +2752,11 @@ RDMA
The "rdma" controller regulates the distribution and accounting of
RDMA resources.
+RDMA devices from all network namespaces are listed. Each line starts with
+the device name. If more than one device has the same name, ``index=N``
+follows the name, where ``N`` is the system-wide RDMA device index, unique
+among registered devices.
+
RDMA Interface Files
~~~~~~~~~~~~~~~~~~~~
@@ -2760,7 +2765,11 @@ RDMA Interface Files
except root that describes current configured resource limit
for a RDMA/IB device.
- Lines are keyed by device name and are not ordered.
+ Lines are keyed by device name and are not ordered. A write may
+ include ``index=N`` after the device name. The index is optional
+ when the name is globally unique. If multiple devices have that
+ name, the index is required and a write without it fails with
+ ``-ENOTUNIQ``.
Each line contains space separated resource name and its configured
limit that can be distributed.
@@ -2776,6 +2785,10 @@ RDMA Interface Files
mlx4_0 hca_handle=2 hca_object=2000
ocrdma1 hca_handle=3 hca_object=max
+ For devices with duplicate names, select the device by index::
+
+ echo "rxe0 index=5 hca_handle=2" > rdma.max
+
rdma.current
A read-only file that describes current resource usage.
It exists for all the cgroup except root.
diff --git a/drivers/infiniband/core/cgroup.c b/drivers/infiniband/core/cgroup.c
index 1f037fe01450..8611b4e32cfb 100644
--- a/drivers/infiniband/core/cgroup.c
+++ b/drivers/infiniband/core/cgroup.c
@@ -17,6 +17,7 @@
void ib_device_register_rdmacg(struct ib_device *device)
{
device->cg_device.name = device->name;
+ device->cg_device.index = device->index;
rdmacg_register_device(&device->cg_device);
}
diff --git a/include/linux/cgroup_rdma.h b/include/linux/cgroup_rdma.h
index 404e746552ca..9a5c9ee728e7 100644
--- a/include/linux/cgroup_rdma.h
+++ b/include/linux/cgroup_rdma.h
@@ -34,6 +34,7 @@ struct rdmacg_device {
struct list_head dev_node;
struct list_head rpools;
char *name;
+ u32 index;
};
/*
diff --git a/kernel/cgroup/rdma.c b/kernel/cgroup/rdma.c
index 5e82a03b3270..9489f3df0bf3 100644
--- a/kernel/cgroup/rdma.c
+++ b/kernel/cgroup/rdma.c
@@ -19,6 +19,7 @@
#define RDMACG_MAX_STR "max"
enum rdmacg_limit_tokens {
+ RDMACG_DEVICE_INDEX,
RDMACG_HCA_HANDLE_VAL,
RDMACG_HCA_HANDLE_MAX,
RDMACG_HCA_OBJECT_VAL,
@@ -27,6 +28,7 @@ enum rdmacg_limit_tokens {
};
static const match_table_t rdmacg_limit_tokens = {
+ { RDMACG_DEVICE_INDEX, "index=%u" },
{ RDMACG_HCA_HANDLE_VAL, "hca_handle=%d" },
{ RDMACG_HCA_HANDLE_MAX, "hca_handle=max" },
{ RDMACG_HCA_OBJECT_VAL, "hca_object=%d" },
@@ -464,17 +466,53 @@ void rdmacg_unregister_device(struct rdmacg_device *device)
}
EXPORT_SYMBOL(rdmacg_unregister_device);
-static struct rdmacg_device *rdmacg_get_device_locked(const char *name)
+static struct rdmacg_device *
+rdmacg_get_device_locked(const char *name, bool has_index, u32 index)
{
+ struct rdmacg_device *match = NULL;
struct rdmacg_device *device;
lockdep_assert_held(&rdmacg_mutex);
- list_for_each_entry(device, &rdmacg_devices, dev_node)
- if (!strcmp(name, device->name))
- return device;
+ list_for_each_entry(device, &rdmacg_devices, dev_node) {
+ if (strcmp(name, device->name))
+ continue;
- return NULL;
+ if (has_index) {
+ if (device->index == index)
+ return device;
+ continue;
+ }
+
+ if (match)
+ return ERR_PTR(-ENOTUNIQ);
+ match = device;
+ }
+
+ return match ?: ERR_PTR(-ENODEV);
+}
+
+static bool
+rdmacg_device_name_unique_locked(const struct rdmacg_device *device)
+{
+ struct rdmacg_device *other;
+
+ lockdep_assert_held(&rdmacg_mutex);
+
+ list_for_each_entry(other, &rdmacg_devices, dev_node)
+ if (other != device && !strcmp(other->name, device->name))
+ return false;
+
+ return true;
+}
+
+static void rdmacg_print_device_key(struct seq_file *sf,
+ const struct rdmacg_device *device)
+{
+ seq_puts(sf, device->name);
+ if (!rdmacg_device_name_unique_locked(device))
+ seq_printf(sf, " index=%u", device->index);
+ seq_putc(sf, ' ');
}
static ssize_t rdmacg_resource_set_max(struct kernfs_open_file *of,
@@ -488,6 +526,8 @@ static ssize_t rdmacg_resource_set_max(struct kernfs_open_file *of,
char *p;
int *new_limits;
unsigned long enables = 0;
+ u32 dev_index = 0;
+ bool has_index = false;
int i = 0, ret = 0;
/* extract the device name first */
@@ -503,7 +543,7 @@ static ssize_t rdmacg_resource_set_max(struct kernfs_open_file *of,
goto err;
}
- /* parse resource limit tokens */
+ /* parse the optional device index and resource limit tokens */
while ((p = strsep(&options, " \t\n"))) {
substring_t args[MAX_OPT_ARGS];
int tok, intval;
@@ -513,6 +553,13 @@ static ssize_t rdmacg_resource_set_max(struct kernfs_open_file *of,
tok = match_token(p, rdmacg_limit_tokens, args);
switch (tok) {
+ case RDMACG_DEVICE_INDEX:
+ if (has_index || match_uint(&args[0], &dev_index)) {
+ ret = -EINVAL;
+ goto parse_err;
+ }
+ has_index = true;
+ break;
case RDMACG_HCA_HANDLE_VAL:
if (match_int(&args[0], &intval) || intval < 0) {
ret = -EINVAL;
@@ -546,9 +593,9 @@ static ssize_t rdmacg_resource_set_max(struct kernfs_open_file *of,
/* acquire lock to synchronize with hot plug devices */
mutex_lock(&rdmacg_mutex);
- device = rdmacg_get_device_locked(dev_name);
- if (!device) {
- ret = -ENODEV;
+ device = rdmacg_get_device_locked(dev_name, has_index, dev_index);
+ if (IS_ERR(device)) {
+ ret = PTR_ERR(device);
goto dev_err;
}
@@ -626,7 +673,7 @@ static int rdmacg_resource_read(struct seq_file *sf, void *v)
mutex_lock(&rdmacg_mutex);
list_for_each_entry(device, &rdmacg_devices, dev_node) {
- seq_printf(sf, "%s ", device->name);
+ rdmacg_print_device_key(sf, device);
rpool = find_cg_rpool_locked(cg, device);
print_rpool_values(sf, rpool);
@@ -650,7 +697,7 @@ static int rdmacg_events_show(struct seq_file *sf, void *v)
list_for_each_entry(device, &rdmacg_devices, dev_node) {
rpool = find_cg_rpool_locked(cg, device);
- seq_printf(sf, "%s ", device->name);
+ rdmacg_print_device_key(sf, device);
for (i = 0; i < RDMACG_RESOURCE_MAX; i++) {
seq_printf(sf, "%s.max=%llu %s.alloc_fail=%llu",
rdmacg_resource_names[i],
@@ -679,7 +726,7 @@ static int rdmacg_events_local_show(struct seq_file *sf, void *v)
list_for_each_entry(device, &rdmacg_devices, dev_node) {
rpool = find_cg_rpool_locked(cg, device);
- seq_printf(sf, "%s ", device->name);
+ rdmacg_print_device_key(sf, device);
for (i = 0; i < RDMACG_RESOURCE_MAX; i++) {
seq_printf(sf, "%s.max=%llu %s.alloc_fail=%llu",
rdmacg_resource_names[i],
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 09/14] RDMA/cma: Document that CM configfs cannot be net namespace scoped
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
` (7 preceding siblings ...)
2026-07-14 14:29 ` [PATCH rdma-next v2 08/14] RDMA/cgroup: Disambiguate devices across net namespaces Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 10/14] RDMA/core: Document the SELinux ibendport net namespace limitation Jiri Pirko
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Document the rdma_cm configfs limitation: configfs is global, so same-named
RDMA devices in different net namespaces cannot both be represented there.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
Documentation/ABI/testing/configfs-rdma_cm | 4 ++++
drivers/infiniband/core/cma_configfs.c | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/Documentation/ABI/testing/configfs-rdma_cm b/Documentation/ABI/testing/configfs-rdma_cm
index 74f9506f42e7..739f7b6a1259 100644
--- a/Documentation/ABI/testing/configfs-rdma_cm
+++ b/Documentation/ABI/testing/configfs-rdma_cm
@@ -12,6 +12,10 @@ Description: Interface is used to configure RDMA-cable HCAs in respect to
for this HCA has to be created:
mkdir -p /config/rdma_cm/<hca>
+ Note: configfs has no network namespace support, so this
+ interface cannot represent two devices that share a name in
+ different network namespaces (possible in exclusive netns mode).
+
What: /config/rdma_cm/<hca>/ports/<port-num>/default_roce_mode
Date: November 29, 2015
diff --git a/drivers/infiniband/core/cma_configfs.c b/drivers/infiniband/core/cma_configfs.c
index 891e52afb8f4..c389d4e37b6b 100644
--- a/drivers/infiniband/core/cma_configfs.c
+++ b/drivers/infiniband/core/cma_configfs.c
@@ -65,6 +65,10 @@ static struct cma_dev_port_group *to_dev_port_group(struct config_item *item)
return container_of(group, struct cma_dev_port_group, group);
}
+/*
+ * configfs is not net namespace aware, so a name shared by devices in
+ * different namespaces resolves to the first match here.
+ */
static bool filter_by_name(struct ib_device *ib_dev, void *cookie)
{
return !strcmp(dev_name(&ib_dev->dev), cookie);
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 10/14] RDMA/core: Document the SELinux ibendport net namespace limitation
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
` (8 preceding siblings ...)
2026-07-14 14:29 ` [PATCH rdma-next v2 09/14] RDMA/cma: Document that CM configfs cannot be net namespace scoped Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 11/14] RDMA/core: Make device names unique per net namespace Jiri Pirko
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Document that SELinux ibendport labels use a global (device name, port)
key, so same-named RDMA devices in different net namespaces share a label.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/security.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/infiniband/core/security.c b/drivers/infiniband/core/security.c
index 9af31d1d9d70..a82c46965416 100644
--- a/drivers/infiniband/core/security.c
+++ b/drivers/infiniband/core/security.c
@@ -700,6 +700,12 @@ int ib_mad_agent_security_setup(struct ib_mad_agent *agent,
if (qp_type != IB_QPT_SMI)
return 0;
+ /*
+ * SELinux labels an endport by (device name, port) from a global
+ * policy. If devices in different net namespaces share a name, they get
+ * the same label; distinguishing them would need net namespace support
+ * in the policy language and tooling.
+ */
spin_lock(&mad_agent_list_lock);
ret = security_ib_endport_manage_subnet(agent->security,
dev_name(&agent->device->dev),
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 11/14] RDMA/core: Make device names unique per net namespace
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
` (9 preceding siblings ...)
2026-07-14 14:29 ` [PATCH rdma-next v2 10/14] RDMA/core: Document the SELinux ibendport net namespace limitation Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 12/14] RDMA/rxe: Allow queue VMAs to outlive ucontexts Jiri Pirko
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Use rdma_dev_access_netns() to scope RDMA device name lookup and "%d" name
allocation to the relevant net namespace. Keep shared mode and
CONFIG_NET_NS=n behaviour system-wide.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/device.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index bb02640239d7..4c75078448a3 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -129,7 +129,7 @@ static DECLARE_RWSEM(rdma_nets_rwsem);
bool ib_devices_shared_netns = true;
module_param_named(netns_mode, ib_devices_shared_netns, bool, 0444);
MODULE_PARM_DESC(netns_mode,
- "Share device among net namespaces; default=1 (shared)");
+ "Share device among net namespaces; default=1 (shared). In exclusive mode device names are unique per net namespace");
/**
* rdma_dev_access_netns() - Return whether an rdma device can be accessed
* from a specified net namespace or not.
@@ -359,7 +359,8 @@ static struct ib_device *__ib_device_get_by_name(const char *name,
unsigned long index;
xa_for_each (&devices, index, device)
- if (!strcmp(name, dev_name(&device->dev)))
+ if (rdma_dev_access_netns(device, net) &&
+ !strcmp(name, dev_name(&device->dev)))
return device;
return NULL;
@@ -437,7 +438,11 @@ int ib_device_set_dim(struct ib_device *ibdev, u8 use_dim)
return 0;
}
-/* Pick a free index for the '%d' style @name pattern. */
+/*
+ * Pick a free index for the '%d' style @name pattern within net namespace
+ * @net. Returns the index on success or a negative errno. The caller builds
+ * the final unique device name from the returned index.
+ */
static int __alloc_name_id(struct net *net, const char *name,
const struct ib_device *skip)
{
@@ -452,7 +457,7 @@ static int __alloc_name_id(struct net *net, const char *name,
xa_for_each (&devices, index, device) {
char buf[IB_DEVICE_NAME_MAX];
- if (device == skip)
+ if (device == skip || !rdma_dev_access_netns(device, net))
continue;
if (sscanf(dev_name(&device->dev), name, &i) != 1)
continue;
@@ -1233,7 +1238,8 @@ static __net_init int rdma_dev_init_net(struct net *net)
}
/*
- * Assign the unique string device name and the unique device index. This is
+ * Assign the unique string device name and the unique device index. The device
+ * name is unique within the net namespace the device is assigned to. This is
* undone by ib_dealloc_device.
*/
static int assign_name(struct ib_device *device, const char *name)
@@ -1416,8 +1422,9 @@ static void ib_device_notify_register(struct ib_device *device)
/**
* ib_register_device - Register an IB device with IB core
* @device: Device to register
- * @name: unique string device name. This may include a '%' which will
- * cause a unique index to be added to the passed device name.
+ * @name: device name, unique within the device's net namespace. This may
+ * include a '%' which will cause a unique index to be added to the
+ * passed device name.
* @dma_device: pointer to a DMA-capable device. If %NULL, then the IB
* device will be used. In this case the caller should fully
* setup the ibdev for DMA. This usually means using dma_virt_ops.
@@ -1708,6 +1715,7 @@ static bool rdma_dev_name_in_netns(struct ib_device *skip, struct net *net,
xa_for_each(&devices, index, device)
if (device != skip &&
+ rdma_dev_access_netns(device, net) &&
!strcmp(name, dev_name(&device->dev)))
return true;
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 12/14] RDMA/rxe: Allow queue VMAs to outlive ucontexts
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
` (10 preceding siblings ...)
2026-07-14 14:29 ` [PATCH rdma-next v2 11/14] RDMA/core: Make device names unique per net namespace Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 13/14] RDMA/rxe: Implement disassociate_ucontext callback Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 14/14] RDMA/selftests: Add rxe_netns_names test Jiri Pirko
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Prepare queue mappings for asynchronous ucontext disassociation during
device disable. Rely on the VMA page references to preserve mapped
memory until the final unmap.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v1->v2:
- new patch
---
drivers/infiniband/sw/rxe/rxe_mmap.c | 35 ++--------------------------
1 file changed, 2 insertions(+), 33 deletions(-)
diff --git a/drivers/infiniband/sw/rxe/rxe_mmap.c b/drivers/infiniband/sw/rxe/rxe_mmap.c
index 7f723a2f3700..a4ead89ccbd3 100644
--- a/drivers/infiniband/sw/rxe/rxe_mmap.c
+++ b/drivers/infiniband/sw/rxe/rxe_mmap.c
@@ -11,7 +11,6 @@
#include "rxe.h"
#include "rxe_loc.h"
-#include "rxe_queue.h"
void rxe_mmap_release(struct kref *ref)
{
@@ -30,29 +29,6 @@ void rxe_mmap_release(struct kref *ref)
kfree(ip);
}
-/*
- * open and close keep track of how many times the memory region is mapped,
- * to avoid releasing it.
- */
-static void rxe_vma_open(struct vm_area_struct *vma)
-{
- struct rxe_mmap_info *ip = vma->vm_private_data;
-
- kref_get(&ip->ref);
-}
-
-static void rxe_vma_close(struct vm_area_struct *vma)
-{
- struct rxe_mmap_info *ip = vma->vm_private_data;
-
- kref_put(&ip->ref, rxe_mmap_release);
-}
-
-static const struct vm_operations_struct rxe_vm_ops = {
- .open = rxe_vma_open,
- .close = rxe_vma_close,
-};
-
/**
* rxe_mmap - create a new mmap region
* @context: the IB user context of the process making the mmap() call
@@ -106,17 +82,10 @@ int rxe_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
list_del_init(&ip->pending_mmaps);
spin_unlock_bh(&rxe->pending_lock);
- vma->vm_ops = &rxe_vm_ops;
- vma->vm_private_data = ip;
-
ret = remap_vmalloc_range(vma, ip->obj, 0);
- if (ret) {
- vma->vm_private_data = NULL;
- vma->vm_ops = NULL;
- kref_put(&ip->ref, rxe_mmap_release);
+ kref_put(&ip->ref, rxe_mmap_release);
+ if (ret)
rxe_dbg_dev(rxe, "err %d from remap_vmalloc_range\n", ret);
- goto done;
- }
done:
return ret;
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 13/14] RDMA/rxe: Implement disassociate_ucontext callback
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
` (11 preceding siblings ...)
2026-07-14 14:29 ` [PATCH rdma-next v2 12/14] RDMA/rxe: Allow queue VMAs to outlive ucontexts Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 14/14] RDMA/selftests: Add rxe_netns_names test Jiri Pirko
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Implement an empty disassociate_ucontext() callback so the RDMA core
can move rxe devices between net namespaces. The core requires this
callback to reset user contexts without waiting for userspace.
rxe needs no teardown here: its user-mapped queues live in
reference-counted vmalloc memory (see rxe_mmap.c) that stays valid
while userspace holds the mappings.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/sw/rxe/rxe_verbs.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index 1ec130fee8ea..6eb10d2f0653 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -240,6 +240,10 @@ static void rxe_dealloc_ucontext(struct ib_ucontext *ibuc)
rxe_err_uc(uc, "cleanup failed, err = %d\n", err);
}
+static void rxe_disassociate_ucontext(struct ib_ucontext *ibuc)
+{
+}
+
/* pd */
static int rxe_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
{
@@ -1478,6 +1482,7 @@ static const struct ib_device_ops rxe_dev_ops = {
.destroy_srq = rxe_destroy_srq,
.detach_mcast = rxe_detach_mcast,
.device_group = &rxe_attr_group,
+ .disassociate_ucontext = rxe_disassociate_ucontext,
.enable_driver = rxe_enable_driver,
.get_dma_mr = rxe_get_dma_mr,
.get_hw_stats = rxe_ib_get_hw_stats,
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH rdma-next v2 14/14] RDMA/selftests: Add rxe_netns_names test
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
` (12 preceding siblings ...)
2026-07-14 14:29 ` [PATCH rdma-next v2 13/14] RDMA/rxe: Implement disassociate_ucontext callback Jiri Pirko
@ 2026-07-14 14:29 ` Jiri Pirko
13 siblings, 0 replies; 15+ messages in thread
From: Jiri Pirko @ 2026-07-14 14:29 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia,
yanjun.zhu, cui.tao
From: Jiri Pirko <jiri@nvidia.com>
Add a kselftest script that exercises per-netns RDMA device naming
with RXE. Cover duplicate names across namespaces, move conflict
handling, move-with-rename, and same-namespace rename requests.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
v1->v2:
- fixed ktap_set_plan
- s/RXE_A/RXE_SAME/ in dup rename
---
tools/testing/selftests/rdma/Makefile | 3 +-
tools/testing/selftests/rdma/config | 2 +
.../testing/selftests/rdma/rxe_netns_names.sh | 282 ++++++++++++++++++
3 files changed, 286 insertions(+), 1 deletion(-)
create mode 100755 tools/testing/selftests/rdma/rxe_netns_names.sh
diff --git a/tools/testing/selftests/rdma/Makefile b/tools/testing/selftests/rdma/Makefile
index 07af7f15c1bf..a91c14c45006 100644
--- a/tools/testing/selftests/rdma/Makefile
+++ b/tools/testing/selftests/rdma/Makefile
@@ -3,6 +3,7 @@ TEST_PROGS := rxe_rping_between_netns.sh \
rxe_ipv6.sh \
rxe_socket_with_netns.sh \
rxe_test_NETDEV_UNREGISTER.sh \
- rxe_sent_rcvd_bytes.sh
+ rxe_sent_rcvd_bytes.sh \
+ rxe_netns_names.sh
include ../lib.mk
diff --git a/tools/testing/selftests/rdma/config b/tools/testing/selftests/rdma/config
index 4ffb814e253b..e1ff54ec0f57 100644
--- a/tools/testing/selftests/rdma/config
+++ b/tools/testing/selftests/rdma/config
@@ -1,3 +1,5 @@
CONFIG_TUN
CONFIG_VETH
+CONFIG_DUMMY
+CONFIG_NET_NS
CONFIG_RDMA_RXE
diff --git a/tools/testing/selftests/rdma/rxe_netns_names.sh b/tools/testing/selftests/rdma/rxe_netns_names.sh
new file mode 100755
index 000000000000..a4fabf86bdf7
--- /dev/null
+++ b/tools/testing/selftests/rdma/rxe_netns_names.sh
@@ -0,0 +1,282 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Exercise RDMA device name handling across network namespaces.
+
+source "$(dirname "$0")/../kselftest/ktap_helpers.sh"
+
+NAME_PREFIX="rxe_netns_names_$$"
+NETDEV_PREFIX="rxn$$"
+NS1="${NAME_PREFIX}ns1"
+NS2="${NAME_PREFIX}ns2"
+RXE_A="${NAME_PREFIX}rxe_a"
+RXE_B="${NAME_PREFIX}rxe_b"
+RXE_SAME="${NAME_PREFIX}rxe_same"
+RXE_NEW="${NAME_PREFIX}rxe_new"
+DUMMY_A="${NETDEV_PREFIX}a"
+DUMMY_B="${NETDEV_PREFIX}b"
+OLD_MODE=""
+MODE_CHANGED=0
+MODS=("dummy" "rdma_rxe")
+TEST_SAME_NAMES="same RDMA device name can exist in two net namespaces"
+TEST_MOVE_CONFLICT="move without rename fails on destination name conflict"
+TEST_MOVE_RENAME="move then rename succeeds"
+TEST_COMBINED_MOVE_RENAME="move with requested destination name succeeds"
+TEST_SAME_NETNS_DUP_RENAME="same-netns rename rejects duplicate name"
+TEST_TEARDOWN_RETURN="netns delete returns device to init_net and renames on conflict"
+
+ksft_skip()
+{
+ ktap_skip_all "$*"
+ exit "$KSFT_SKIP"
+}
+
+fail()
+{
+ ktap_exit_fail_msg "$*"
+}
+
+need_cmd()
+{
+ command -v "$1" >/dev/null 2>&1 || ksft_skip "missing command: $1"
+}
+
+rdma_ns()
+{
+ local ns=$1
+
+ shift
+ ip netns exec "$ns" rdma "$@"
+}
+
+rdma_dev_exists()
+{
+ local ns=$1
+ local dev=$2
+
+ if [ -n "$ns" ]; then
+ rdma_ns "$ns" dev show "$dev" >/dev/null 2>&1
+ else
+ rdma dev show "$dev" >/dev/null 2>&1
+ fi
+}
+
+add_dummy()
+{
+ local netdev=$1
+
+ ip link add "$netdev" type dummy || return 1
+ ip link set "$netdev" up || return 1
+}
+
+add_rxe()
+{
+ local dev=$1
+ local netdev=$2
+
+ rdma link add "$dev" type rxe netdev "$netdev"
+}
+
+rdma_dev_on_netdev()
+{
+ local netdev=$1
+
+ rdma link show 2>/dev/null | awk -v want="$netdev" '
+ {
+ for (i = 1; i < NF; i++)
+ if ($i == "netdev" && $(i + 1) == want) {
+ dev = $2
+ sub(/\/.*/, "", dev)
+ print dev
+ exit
+ }
+ }'
+}
+
+wait_rdma_dev_on_netdev()
+{
+ local netdev=$1
+ local dev
+ local i
+
+ for i in $(seq 1 50); do
+ dev=$(rdma_dev_on_netdev "$netdev")
+ if [ -n "$dev" ]; then
+ echo "$dev"
+ return 0
+ fi
+ sleep 0.1
+ done
+
+ return 1
+}
+
+setup_devs()
+{
+ cleanup_devs
+
+ add_dummy "$DUMMY_A" || return 1
+ add_dummy "$DUMMY_B" || return 1
+
+ add_rxe "$RXE_A" "$DUMMY_A" || return 1
+ add_rxe "$RXE_B" "$DUMMY_B" || return 1
+}
+
+cleanup_devs()
+{
+ ip link del "$DUMMY_A" 2>/dev/null
+ ip link del "$DUMMY_B" 2>/dev/null
+}
+
+setup()
+{
+ OLD_MODE=$(rdma system show 2>/dev/null |
+ sed -n 's/.*netns \([^ ]*\).*/\1/p')
+ [ -n "$OLD_MODE" ] || ksft_skip "failed to read RDMA netns mode"
+
+ rdma system set netns exclusive >/dev/null 2>&1 ||
+ ksft_skip "rdma netns exclusive mode is not supported"
+ MODE_CHANGED=1
+
+ ip netns add "$NS1" || return 1
+ ip netns add "$NS2" || return 1
+}
+
+cleanup()
+{
+ cleanup_devs
+
+ ip netns del "$NS1" 2>/dev/null
+ ip netns del "$NS2" 2>/dev/null
+
+ if [ "$MODE_CHANGED" -eq 1 ]; then
+ rdma system set netns "$OLD_MODE" 2>/dev/null
+ fi
+
+ for m in "${MODS[@]}"; do
+ modprobe -r "$m" 2>/dev/null
+ done
+}
+
+rdma_supports_combined_move_rename()
+{
+ rdma dev help 2>&1 | grep -Eq 'netns .*name|name .*netns'
+}
+
+[ "$(id -u)" -eq 0 ] || ksft_skip "must be run as root"
+need_cmd ip
+need_cmd rdma
+need_cmd modprobe
+
+trap cleanup EXIT
+
+for m in "${MODS[@]}"; do
+ modinfo "$m" >/dev/null 2>&1 || ksft_skip "module $m not found"
+ modprobe "$m" || fail "failed to load $m"
+done
+
+setup || fail "failed to create net namespaces"
+
+ktap_print_header
+ktap_set_plan 6
+
+if setup_devs &&
+ rdma dev set "$RXE_A" netns "$NS1" &&
+ rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" &&
+ rdma dev set "$RXE_B" netns "$NS2" &&
+ rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" &&
+ rdma_dev_exists "$NS1" "$RXE_SAME" &&
+ rdma_dev_exists "$NS2" "$RXE_SAME"; then
+ ktap_test_pass "$TEST_SAME_NAMES"
+else
+ ktap_test_fail "$TEST_SAME_NAMES"
+fi
+cleanup_devs
+
+if ! setup_devs ||
+ ! rdma dev set "$RXE_A" netns "$NS1" ||
+ ! rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" ||
+ ! rdma dev set "$RXE_B" netns "$NS2" ||
+ ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME"; then
+ ktap_test_fail "$TEST_MOVE_CONFLICT"
+elif rdma_ns "$NS1" dev set "$RXE_SAME" netns "$NS2" >/dev/null 2>&1; then
+ ktap_test_fail "$TEST_MOVE_CONFLICT"
+elif rdma_dev_exists "$NS1" "$RXE_SAME" &&
+ rdma_dev_exists "$NS2" "$RXE_SAME"; then
+ ktap_test_pass "$TEST_MOVE_CONFLICT"
+else
+ ktap_test_fail "$TEST_MOVE_CONFLICT"
+fi
+cleanup_devs
+
+if ! setup_devs; then
+ ktap_test_fail "$TEST_MOVE_RENAME"
+elif rdma dev set "$RXE_A" netns "$NS2" &&
+ rdma_ns "$NS2" dev set "$RXE_A" name "$RXE_NEW"; then
+ if rdma_dev_exists "$NS2" "$RXE_NEW" &&
+ ! rdma_dev_exists "" "$RXE_A"; then
+ ktap_test_pass "$TEST_MOVE_RENAME"
+ else
+ ktap_test_fail "$TEST_MOVE_RENAME"
+ fi
+else
+ ktap_test_fail "$TEST_MOVE_RENAME"
+fi
+cleanup_devs
+
+if ! rdma_supports_combined_move_rename; then
+ ktap_test_skip "$TEST_COMBINED_MOVE_RENAME"
+elif ! setup_devs; then
+ ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
+elif rdma dev set "$RXE_A" netns "$NS2" name "$RXE_NEW"; then
+ if rdma_dev_exists "$NS2" "$RXE_NEW" &&
+ ! rdma_dev_exists "" "$RXE_A"; then
+ ktap_test_pass "$TEST_COMBINED_MOVE_RENAME"
+ else
+ ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
+ fi
+else
+ ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
+fi
+cleanup_devs
+
+if ! setup_devs; then
+ ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
+elif rdma dev set "$RXE_A" name "$RXE_SAME" &&
+ rdma dev set "$RXE_B" name "$RXE_NEW"; then
+ if rdma dev set "$RXE_SAME" name "$RXE_NEW" >/dev/null 2>&1; then
+ ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
+ elif rdma_dev_exists "" "$RXE_SAME" &&
+ rdma_dev_exists "" "$RXE_NEW"; then
+ ktap_test_pass "$TEST_SAME_NETNS_DUP_RENAME"
+ else
+ ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
+ fi
+else
+ ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
+fi
+cleanup_devs
+
+if ! setup_devs; then
+ ktap_test_fail "$TEST_TEARDOWN_RETURN"
+elif ! rdma dev set "$RXE_A" name "$RXE_SAME" ||
+ ! rdma dev set "$RXE_B" netns "$NS2" ||
+ ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" ||
+ ! rdma_dev_exists "$NS2" "$RXE_SAME"; then
+ ktap_test_fail "$TEST_TEARDOWN_RETURN"
+else
+ ip netns del "$NS2"
+ returned=$(wait_rdma_dev_on_netdev "$DUMMY_B")
+ ktap_print_msg "device returned to init_net as '${returned:-<missing>}'"
+ if rdma_dev_exists "" "$RXE_SAME" &&
+ [ -n "$returned" ] &&
+ [ "$returned" != "$RXE_SAME" ] &&
+ [ "${returned#ibdev}" != "$returned" ]; then
+ ktap_test_pass "$TEST_TEARDOWN_RETURN"
+ else
+ ktap_test_fail "$TEST_TEARDOWN_RETURN"
+ fi
+fi
+cleanup_devs
+
+ktap_finished
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-07-14 14:30 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-14 14:29 [PATCH rdma-next v2 00/14] RDMA: Make device names unique per net namespace Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 01/14] RDMA/core: Pass the net namespace to the device name lookups Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 02/14] RDMA/core: Handle device name conflicts when changing net namespace Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 03/14] RDMA/core: Support renaming a device when changing its " Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 04/14] RDMA/nldev: Report net namespace move errors through extack Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 05/14] RDMA/nldev: Allow setting the device name while changing net namespace Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 06/14] net/smc: Look up the pnetid ib device within the " Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 07/14] RDMA/srp: Make the SRP sysfs class net namespace aware Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 08/14] RDMA/cgroup: Disambiguate devices across net namespaces Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 09/14] RDMA/cma: Document that CM configfs cannot be net namespace scoped Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 10/14] RDMA/core: Document the SELinux ibendport net namespace limitation Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 11/14] RDMA/core: Make device names unique per net namespace Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 12/14] RDMA/rxe: Allow queue VMAs to outlive ucontexts Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 13/14] RDMA/rxe: Implement disassociate_ucontext callback Jiri Pirko
2026-07-14 14:29 ` [PATCH rdma-next v2 14/14] RDMA/selftests: Add rxe_netns_names test Jiri Pirko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox