diff mbox series

[net-next,v2,6/7] devlink: allow to call devl_param_driverinit_value_get() without holding instance lock

Message ID 20230210100131.3088240-7-jiri@resnulli.us (mailing list archive)
State Accepted
Commit 280f7b2adca09c8d5f34b99f49e5c570aa81daad
Delegated to: Netdev Maintainers
Headers show
Series devlink: params cleanups and devl_param_driverinit_value_get() fix | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 2 this patch: 2
netdev/cc_maintainers success CCed 9 of 9 maintainers
netdev/build_clang success Errors and warnings before: 1 this patch: 1
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 2 this patch: 2
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 25 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Jiri Pirko Feb. 10, 2023, 10:01 a.m. UTC
From: Jiri Pirko <jiri@nvidia.com>

If the driver maintains following basic sane behavior, the
devl_param_driverinit_value_get() function could be called without
holding instance lock:

1) Driver ensures a call to devl_param_driverinit_value_get() cannot
   race with registering/unregistering the parameter with
   the same parameter ID.
2) Driver ensures a call to devl_param_driverinit_value_get() cannot
   race with devl_param_driverinit_value_set() call with
   the same parameter ID.
3) Driver ensures a call to devl_param_driverinit_value_get() cannot
   race with reload operation.

By the nature of params usage, these requirements should be
trivially achievable. If the driver for some off reason
is not able to comply, it has to take the devlink->lock while
calling devl_param_driverinit_value_get().

Remove the lock assertion and add comment describing
the locking requirements.

This fixes a splat in mlx5 driver introduced by the commit
referenced in the "Fixes" tag.

Lore: https://lore.kernel.org/netdev/719de4f0-76ac-e8b9-38a9-167ae239efc7@amd.com/
Reported-by: Kim Phillips <kim.phillips@amd.com>
Fixes: 075935f0ae0f ("devlink: protect devlink param list by instance lock")
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Acked-by: Jakub Kicinski <kuba@kernel.org>
---
 net/devlink/leftover.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

Comments

Jacob Keller Feb. 10, 2023, 7:41 p.m. UTC | #1
On 2/10/2023 2:01 AM, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@nvidia.com>
> 
> If the driver maintains following basic sane behavior, the
> devl_param_driverinit_value_get() function could be called without
> holding instance lock:
> 
> 1) Driver ensures a call to devl_param_driverinit_value_get() cannot
>    race with registering/unregistering the parameter with
>    the same parameter ID.
> 2) Driver ensures a call to devl_param_driverinit_value_get() cannot
>    race with devl_param_driverinit_value_set() call with
>    the same parameter ID.
> 3) Driver ensures a call to devl_param_driverinit_value_get() cannot
>    race with reload operation.
> 
> By the nature of params usage, these requirements should be
> trivially achievable. If the driver for some off reason
> is not able to comply, it has to take the devlink->lock while
> calling devl_param_driverinit_value_get().
> 
> Remove the lock assertion and add comment describing
> the locking requirements.
> 
> This fixes a splat in mlx5 driver introduced by the commit
> referenced in the "Fixes" tag.

Just to clarify, is it possible for mlx5 to take the instance lock
instead of these changes? I agree the improvements make sense here, but
it seems like an alternative fix would be to grab the lock around the
get function call in mlx5.

Either way, the assumptions here seem reasonable and the series makes sense.

Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>

Thanks,
Jake

> 
> Lore: https://lore.kernel.org/netdev/719de4f0-76ac-e8b9-38a9-167ae239efc7@amd.com/
> Reported-by: Kim Phillips <kim.phillips@amd.com>
> Fixes: 075935f0ae0f ("devlink: protect devlink param list by instance lock")
> Signed-off-by: Jiri Pirko <jiri@nvidia.com>
> Reviewed-by: Simon Horman <simon.horman@corigine.com>
> Acked-by: Jakub Kicinski <kuba@kernel.org>
> ---
>  net/devlink/leftover.c | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/net/devlink/leftover.c b/net/devlink/leftover.c
> index 6d3988f4e843..9f0256c2c323 100644
> --- a/net/devlink/leftover.c
> +++ b/net/devlink/leftover.c
> @@ -9628,14 +9628,23 @@ EXPORT_SYMBOL_GPL(devlink_params_unregister);
>   *
>   *	This function should be used by the driver to get driverinit
>   *	configuration for initialization after reload command.
> + *
> + *	Note that lockless call of this function relies on the
> + *	driver to maintain following basic sane behavior:
> + *	1) Driver ensures a call to this function cannot race with
> + *	   registering/unregistering the parameter with the same parameter ID.
> + *	2) Driver ensures a call to this function cannot race with
> + *	   devl_param_driverinit_value_set() call with the same parameter ID.
> + *	3) Driver ensures a call to this function cannot race with
> + *	   reload operation.
> + *	If the driver is not able to comply, it has to take the devlink->lock
> + *	while calling this.
>   */
>  int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
>  				    union devlink_param_value *val)
>  {
>  	struct devlink_param_item *param_item;
>  
> -	lockdep_assert_held(&devlink->lock);
> -
>  	if (WARN_ON(!devlink_reload_supported(devlink->ops)))
>  		return -EOPNOTSUPP;
>
Kim Phillips Feb. 10, 2023, 10:11 p.m. UTC | #2
On 2/10/23 4:01 AM, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@nvidia.com>
> 
> If the driver maintains following basic sane behavior, the
> devl_param_driverinit_value_get() function could be called without
> holding instance lock:
> 
> 1) Driver ensures a call to devl_param_driverinit_value_get() cannot
>     race with registering/unregistering the parameter with
>     the same parameter ID.
> 2) Driver ensures a call to devl_param_driverinit_value_get() cannot
>     race with devl_param_driverinit_value_set() call with
>     the same parameter ID.
> 3) Driver ensures a call to devl_param_driverinit_value_get() cannot
>     race with reload operation.
> 
> By the nature of params usage, these requirements should be
> trivially achievable. If the driver for some off reason
> is not able to comply, it has to take the devlink->lock while
> calling devl_param_driverinit_value_get().
> 
> Remove the lock assertion and add comment describing
> the locking requirements.
> 
> This fixes a splat in mlx5 driver introduced by the commit
> referenced in the "Fixes" tag.
> 
> Lore: https://lore.kernel.org/netdev/719de4f0-76ac-e8b9-38a9-167ae239efc7@amd.com/
> Reported-by: Kim Phillips <kim.phillips@amd.com>
> Fixes: 075935f0ae0f ("devlink: protect devlink param list by instance lock")
> Signed-off-by: Jiri Pirko <jiri@nvidia.com>
> Reviewed-by: Simon Horman <simon.horman@corigine.com>
> Acked-by: Jakub Kicinski <kuba@kernel.org>
> ---

Please add my:

Tested-by: Kim Phillips <kim.phillips@amd.com>

to this patch, if not the entire series.

Thanks!

Kim

p.s. Sorry about my testing snafu on v1 of this series - it wasn't
clear to me what fixes were where...
Jiri Pirko Feb. 13, 2023, 7:44 a.m. UTC | #3
Fri, Feb 10, 2023 at 08:41:27PM CET, jacob.e.keller@intel.com wrote:
>
>
>On 2/10/2023 2:01 AM, Jiri Pirko wrote:
>> From: Jiri Pirko <jiri@nvidia.com>
>> 
>> If the driver maintains following basic sane behavior, the
>> devl_param_driverinit_value_get() function could be called without
>> holding instance lock:
>> 
>> 1) Driver ensures a call to devl_param_driverinit_value_get() cannot
>>    race with registering/unregistering the parameter with
>>    the same parameter ID.
>> 2) Driver ensures a call to devl_param_driverinit_value_get() cannot
>>    race with devl_param_driverinit_value_set() call with
>>    the same parameter ID.
>> 3) Driver ensures a call to devl_param_driverinit_value_get() cannot
>>    race with reload operation.
>> 
>> By the nature of params usage, these requirements should be
>> trivially achievable. If the driver for some off reason
>> is not able to comply, it has to take the devlink->lock while
>> calling devl_param_driverinit_value_get().
>> 
>> Remove the lock assertion and add comment describing
>> the locking requirements.
>> 
>> This fixes a splat in mlx5 driver introduced by the commit
>> referenced in the "Fixes" tag.
>
>Just to clarify, is it possible for mlx5 to take the instance lock
>instead of these changes? I agree the improvements make sense here, but
>it seems like an alternative fix would be to grab the lock around the
>get function call in mlx5.

You are correct, yes.

>
>Either way, the assumptions here seem reasonable and the series makes sense.
>
>Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
>
>Thanks,
>Jake
>
>> 
>> Lore: https://lore.kernel.org/netdev/719de4f0-76ac-e8b9-38a9-167ae239efc7@amd.com/
>> Reported-by: Kim Phillips <kim.phillips@amd.com>
>> Fixes: 075935f0ae0f ("devlink: protect devlink param list by instance lock")
>> Signed-off-by: Jiri Pirko <jiri@nvidia.com>
>> Reviewed-by: Simon Horman <simon.horman@corigine.com>
>> Acked-by: Jakub Kicinski <kuba@kernel.org>
>> ---
>>  net/devlink/leftover.c | 13 +++++++++++--
>>  1 file changed, 11 insertions(+), 2 deletions(-)
>> 
>> diff --git a/net/devlink/leftover.c b/net/devlink/leftover.c
>> index 6d3988f4e843..9f0256c2c323 100644
>> --- a/net/devlink/leftover.c
>> +++ b/net/devlink/leftover.c
>> @@ -9628,14 +9628,23 @@ EXPORT_SYMBOL_GPL(devlink_params_unregister);
>>   *
>>   *	This function should be used by the driver to get driverinit
>>   *	configuration for initialization after reload command.
>> + *
>> + *	Note that lockless call of this function relies on the
>> + *	driver to maintain following basic sane behavior:
>> + *	1) Driver ensures a call to this function cannot race with
>> + *	   registering/unregistering the parameter with the same parameter ID.
>> + *	2) Driver ensures a call to this function cannot race with
>> + *	   devl_param_driverinit_value_set() call with the same parameter ID.
>> + *	3) Driver ensures a call to this function cannot race with
>> + *	   reload operation.
>> + *	If the driver is not able to comply, it has to take the devlink->lock
>> + *	while calling this.
>>   */
>>  int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
>>  				    union devlink_param_value *val)
>>  {
>>  	struct devlink_param_item *param_item;
>>  
>> -	lockdep_assert_held(&devlink->lock);
>> -
>>  	if (WARN_ON(!devlink_reload_supported(devlink->ops)))
>>  		return -EOPNOTSUPP;
>>
diff mbox series

Patch

diff --git a/net/devlink/leftover.c b/net/devlink/leftover.c
index 6d3988f4e843..9f0256c2c323 100644
--- a/net/devlink/leftover.c
+++ b/net/devlink/leftover.c
@@ -9628,14 +9628,23 @@  EXPORT_SYMBOL_GPL(devlink_params_unregister);
  *
  *	This function should be used by the driver to get driverinit
  *	configuration for initialization after reload command.
+ *
+ *	Note that lockless call of this function relies on the
+ *	driver to maintain following basic sane behavior:
+ *	1) Driver ensures a call to this function cannot race with
+ *	   registering/unregistering the parameter with the same parameter ID.
+ *	2) Driver ensures a call to this function cannot race with
+ *	   devl_param_driverinit_value_set() call with the same parameter ID.
+ *	3) Driver ensures a call to this function cannot race with
+ *	   reload operation.
+ *	If the driver is not able to comply, it has to take the devlink->lock
+ *	while calling this.
  */
 int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
 				    union devlink_param_value *val)
 {
 	struct devlink_param_item *param_item;
 
-	lockdep_assert_held(&devlink->lock);
-
 	if (WARN_ON(!devlink_reload_supported(devlink->ops)))
 		return -EOPNOTSUPP;