On Wed, 28 Jan 2026 13:25:37 +0200 Tariq Toukan wrote:
quoted hunk ↗ jump to hunk
static int __devlink_nl_pre_doit(struct sk_buff *skb, struct genl_info *info,
u8 flags)
{
+ bool parent_dev = flags & DEVLINK_NL_FLAG_OPTIONAL_PARENT_DEV;
bool dev_lock = flags & DEVLINK_NL_FLAG_NEED_DEV_LOCK;
+ struct devlink *devlink, *parent_devlink = NULL;
+ struct net *net = genl_info_net(info);
+ struct nlattr **attrs = info->attrs;
struct devlink_port *devlink_port;
- struct devlink *devlink;
int err;
- devlink = devlink_get_from_attrs_lock(genl_info_net(info), info->attrs,
- dev_lock);
- if (IS_ERR(devlink))
- return PTR_ERR(devlink);
+ if (parent_dev && attrs[DEVLINK_ATTR_PARENT_DEV]) {
+ parent_devlink = devlink_get_parent_from_attrs_lock(net, attrs);
+ if (IS_ERR(parent_devlink))
+ return PTR_ERR(parent_devlink);
+ info->user_ptr[1] = parent_devlink;
Let's convert devlink to use proper overlay struct over info->cb ?
The user_ptr array only has two entries so devlink stuffs all the
extra pointers into the second slot. But the cb is much larger - 48B
so we can easily give each of these values a dedicated pointer.
quoted hunk ↗ jump to hunk
+ /* Drop the parent devlink lock but don't release the reference.
+ * This will keep it alive until the end of the request.
+ */
To be clear -- devlink instances do not behave like netdev instances.
netdev instances prevent unregistration of the netdev.
devlink refs are normal refs, they just keep the memory around.
If memory serves me..
quoted hunk ↗ jump to hunk
+ devl_unlock(parent_devlink);
+ }
+ devlink = devlink_get_from_attrs_lock(net, attrs, dev_lock);
+ if (IS_ERR(devlink)) {
+ err = PTR_ERR(devlink);
+ goto parent_put;
+ }