Skip to content

Commit bf6b200

Browse files
idoschdavem330
authored andcommitted
devlink: Acquire device lock during reload command
Device drivers register with devlink from their probe routines (under the device lock) by acquiring the devlink instance lock and calling devl_register(). Drivers that support a devlink reload usually implement the reload_{down, up}() operations in a similar fashion to their remove and probe routines, respectively. However, while the remove and probe routines are invoked with the device lock held, the reload operations are only invoked with the devlink instance lock held. It is therefore impossible for drivers to acquire the device lock from their reload operations, as this would result in lock inversion. The motivating use case for invoking the reload operations with the device lock held is in mlxsw which needs to trigger a PCI reset as part of the reload. The driver cannot call pci_reset_function() as this function acquires the device lock. Instead, it needs to call __pci_reset_function_locked which expects the device lock to be held. To that end, adjust devlink to always acquire the device lock before the devlink instance lock when performing a reload. Do that when reload is explicitly triggered by user space by specifying the 'DEVLINK_NL_FLAG_NEED_DEV_LOCK' flag in the pre_doit and post_doit operations of the reload command. A previous patch already handled the case where reload is invoked as part of netns dismantle. Signed-off-by: Ido Schimmel <[email protected]> Reviewed-by: Jiri Pirko <[email protected]> Signed-off-by: Petr Machata <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d32c382 commit bf6b200

File tree

4 files changed

+22
-4
lines changed

4 files changed

+22
-4
lines changed

Documentation/netlink/specs/devlink.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,8 +1484,8 @@ operations:
14841484
dont-validate: [ strict ]
14851485
flags: [ admin-perm ]
14861486
do:
1487-
pre: devlink-nl-pre-doit
1488-
post: devlink-nl-post-doit
1487+
pre: devlink-nl-pre-doit-dev-lock
1488+
post: devlink-nl-post-doit-dev-lock
14891489
request:
14901490
attributes:
14911491
- bus-name

net/devlink/netlink.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@ int devlink_nl_pre_doit_port(const struct genl_split_ops *ops,
138138
return __devlink_nl_pre_doit(skb, info, DEVLINK_NL_FLAG_NEED_PORT);
139139
}
140140

141+
int devlink_nl_pre_doit_dev_lock(const struct genl_split_ops *ops,
142+
struct sk_buff *skb, struct genl_info *info)
143+
{
144+
return __devlink_nl_pre_doit(skb, info, DEVLINK_NL_FLAG_NEED_DEV_LOCK);
145+
}
146+
141147
int devlink_nl_pre_doit_port_optional(const struct genl_split_ops *ops,
142148
struct sk_buff *skb,
143149
struct genl_info *info)
@@ -162,6 +168,13 @@ void devlink_nl_post_doit(const struct genl_split_ops *ops,
162168
__devlink_nl_post_doit(skb, info, 0);
163169
}
164170

171+
void
172+
devlink_nl_post_doit_dev_lock(const struct genl_split_ops *ops,
173+
struct sk_buff *skb, struct genl_info *info)
174+
{
175+
__devlink_nl_post_doit(skb, info, DEVLINK_NL_FLAG_NEED_DEV_LOCK);
176+
}
177+
165178
static int devlink_nl_inst_single_dumpit(struct sk_buff *msg,
166179
struct netlink_callback *cb, int flags,
167180
devlink_nl_dump_one_func_t *dump_one,

net/devlink/netlink_gen.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -846,9 +846,9 @@ const struct genl_split_ops devlink_nl_ops[73] = {
846846
{
847847
.cmd = DEVLINK_CMD_RELOAD,
848848
.validate = GENL_DONT_VALIDATE_STRICT,
849-
.pre_doit = devlink_nl_pre_doit,
849+
.pre_doit = devlink_nl_pre_doit_dev_lock,
850850
.doit = devlink_nl_reload_doit,
851-
.post_doit = devlink_nl_post_doit,
851+
.post_doit = devlink_nl_post_doit_dev_lock,
852852
.policy = devlink_reload_nl_policy,
853853
.maxattr = DEVLINK_ATTR_RELOAD_LIMITS,
854854
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,

net/devlink/netlink_gen.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,17 @@ int devlink_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
2222
struct genl_info *info);
2323
int devlink_nl_pre_doit_port(const struct genl_split_ops *ops,
2424
struct sk_buff *skb, struct genl_info *info);
25+
int devlink_nl_pre_doit_dev_lock(const struct genl_split_ops *ops,
26+
struct sk_buff *skb, struct genl_info *info);
2527
int devlink_nl_pre_doit_port_optional(const struct genl_split_ops *ops,
2628
struct sk_buff *skb,
2729
struct genl_info *info);
2830
void
2931
devlink_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
3032
struct genl_info *info);
33+
void
34+
devlink_nl_post_doit_dev_lock(const struct genl_split_ops *ops,
35+
struct sk_buff *skb, struct genl_info *info);
3136

3237
int devlink_nl_get_doit(struct sk_buff *skb, struct genl_info *info);
3338
int devlink_nl_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);

0 commit comments

Comments
 (0)