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

devlink: protect health reporter operation with instance lock

Similar to other devlink objects, protect the reporters list
by devlink instance lock. Alongside add unlocked versions
of health reporter create/destroy functions and use them in drivers
on call paths where the instance lock is held.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Jiri Pirko and committed by
Jakub Kicinski
dfdfd130 65a20c2e

+110 -39
+4 -4
drivers/net/ethernet/mellanox/mlxsw/core.c
··· 2051 2051 if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) 2052 2052 return 0; 2053 2053 2054 - fw_fatal = devlink_health_reporter_create(devlink, &mlxsw_core_health_fw_fatal_ops, 2055 - 0, mlxsw_core); 2054 + fw_fatal = devl_health_reporter_create(devlink, &mlxsw_core_health_fw_fatal_ops, 2055 + 0, mlxsw_core); 2056 2056 if (IS_ERR(fw_fatal)) { 2057 2057 dev_err(mlxsw_core->bus_info->dev, "Failed to create fw fatal reporter"); 2058 2058 return PTR_ERR(fw_fatal); ··· 2072 2072 err_fw_fatal_config: 2073 2073 mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_core_health_listener, mlxsw_core); 2074 2074 err_trap_register: 2075 - devlink_health_reporter_destroy(mlxsw_core->health.fw_fatal); 2075 + devl_health_reporter_destroy(mlxsw_core->health.fw_fatal); 2076 2076 return err; 2077 2077 } 2078 2078 ··· 2085 2085 mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_core_health_listener, mlxsw_core); 2086 2086 /* Make sure there is no more event work scheduled */ 2087 2087 mlxsw_core_flush_owq(); 2088 - devlink_health_reporter_destroy(mlxsw_core->health.fw_fatal); 2088 + devl_health_reporter_destroy(mlxsw_core->health.fw_fatal); 2089 2089 } 2090 2090 2091 2091 static void mlxsw_core_irq_event_handler_init(struct mlxsw_core *mlxsw_core)
+10 -10
drivers/net/netdevsim/health.c
··· 233 233 int err; 234 234 235 235 health->empty_reporter = 236 - devlink_health_reporter_create(devlink, 237 - &nsim_dev_empty_reporter_ops, 238 - 0, health); 236 + devl_health_reporter_create(devlink, 237 + &nsim_dev_empty_reporter_ops, 238 + 0, health); 239 239 if (IS_ERR(health->empty_reporter)) 240 240 return PTR_ERR(health->empty_reporter); 241 241 242 242 health->dummy_reporter = 243 - devlink_health_reporter_create(devlink, 244 - &nsim_dev_dummy_reporter_ops, 245 - 0, health); 243 + devl_health_reporter_create(devlink, 244 + &nsim_dev_dummy_reporter_ops, 245 + 0, health); 246 246 if (IS_ERR(health->dummy_reporter)) { 247 247 err = PTR_ERR(health->dummy_reporter); 248 248 goto err_empty_reporter_destroy; ··· 266 266 return 0; 267 267 268 268 err_dummy_reporter_destroy: 269 - devlink_health_reporter_destroy(health->dummy_reporter); 269 + devl_health_reporter_destroy(health->dummy_reporter); 270 270 err_empty_reporter_destroy: 271 - devlink_health_reporter_destroy(health->empty_reporter); 271 + devl_health_reporter_destroy(health->empty_reporter); 272 272 return err; 273 273 } 274 274 ··· 278 278 279 279 debugfs_remove_recursive(health->ddir); 280 280 kfree(health->recovered_break_msg); 281 - devlink_health_reporter_destroy(health->dummy_reporter); 282 - devlink_health_reporter_destroy(health->empty_reporter); 281 + devl_health_reporter_destroy(health->dummy_reporter); 282 + devl_health_reporter_destroy(health->empty_reporter); 283 283 }
+19 -3
include/net/devlink.h
··· 1865 1865 const void *value, u32 value_len); 1866 1866 1867 1867 struct devlink_health_reporter * 1868 - devlink_health_reporter_create(struct devlink *devlink, 1869 - const struct devlink_health_reporter_ops *ops, 1870 - u64 graceful_period, void *priv); 1868 + devl_port_health_reporter_create(struct devlink_port *port, 1869 + const struct devlink_health_reporter_ops *ops, 1870 + u64 graceful_period, void *priv); 1871 1871 1872 1872 struct devlink_health_reporter * 1873 1873 devlink_port_health_reporter_create(struct devlink_port *port, 1874 1874 const struct devlink_health_reporter_ops *ops, 1875 1875 u64 graceful_period, void *priv); 1876 1876 1877 + struct devlink_health_reporter * 1878 + devl_health_reporter_create(struct devlink *devlink, 1879 + const struct devlink_health_reporter_ops *ops, 1880 + u64 graceful_period, void *priv); 1881 + 1882 + struct devlink_health_reporter * 1883 + devlink_health_reporter_create(struct devlink *devlink, 1884 + const struct devlink_health_reporter_ops *ops, 1885 + u64 graceful_period, void *priv); 1886 + 1887 + void 1888 + devl_health_reporter_destroy(struct devlink_health_reporter *reporter); 1889 + 1877 1890 void 1878 1891 devlink_health_reporter_destroy(struct devlink_health_reporter *reporter); 1892 + 1893 + void 1894 + devl_port_health_reporter_destroy(struct devlink_health_reporter *reporter); 1879 1895 1880 1896 void 1881 1897 devlink_port_health_reporter_destroy(struct devlink_health_reporter *reporter);
+77 -22
net/devlink/leftover.c
··· 7337 7337 } 7338 7338 7339 7339 /** 7340 - * devlink_port_health_reporter_create - create devlink health reporter for 7341 - * specified port instance 7340 + * devl_port_health_reporter_create - create devlink health reporter for 7341 + * specified port instance 7342 7342 * 7343 7343 * @port: devlink_port which should contain the new reporter 7344 7344 * @ops: ops ··· 7346 7346 * @priv: priv 7347 7347 */ 7348 7348 struct devlink_health_reporter * 7349 - devlink_port_health_reporter_create(struct devlink_port *port, 7350 - const struct devlink_health_reporter_ops *ops, 7351 - u64 graceful_period, void *priv) 7349 + devl_port_health_reporter_create(struct devlink_port *port, 7350 + const struct devlink_health_reporter_ops *ops, 7351 + u64 graceful_period, void *priv) 7352 7352 { 7353 7353 struct devlink_health_reporter *reporter; 7354 7354 7355 + devl_assert_locked(port->devlink); 7355 7356 mutex_lock(&port->reporters_lock); 7356 7357 if (__devlink_health_reporter_find_by_name(&port->reporter_list, 7357 7358 &port->reporters_lock, ops->name)) { ··· 7371 7370 mutex_unlock(&port->reporters_lock); 7372 7371 return reporter; 7373 7372 } 7373 + EXPORT_SYMBOL_GPL(devl_port_health_reporter_create); 7374 + 7375 + struct devlink_health_reporter * 7376 + devlink_port_health_reporter_create(struct devlink_port *port, 7377 + const struct devlink_health_reporter_ops *ops, 7378 + u64 graceful_period, void *priv) 7379 + { 7380 + struct devlink_health_reporter *reporter; 7381 + struct devlink *devlink = port->devlink; 7382 + 7383 + devl_lock(devlink); 7384 + reporter = devl_port_health_reporter_create(port, ops, 7385 + graceful_period, priv); 7386 + devl_unlock(devlink); 7387 + return reporter; 7388 + } 7374 7389 EXPORT_SYMBOL_GPL(devlink_port_health_reporter_create); 7375 7390 7376 7391 /** 7377 - * devlink_health_reporter_create - create devlink health reporter 7392 + * devl_health_reporter_create - create devlink health reporter 7378 7393 * 7379 7394 * @devlink: devlink 7380 7395 * @ops: ops ··· 7398 7381 * @priv: priv 7399 7382 */ 7400 7383 struct devlink_health_reporter * 7401 - devlink_health_reporter_create(struct devlink *devlink, 7402 - const struct devlink_health_reporter_ops *ops, 7403 - u64 graceful_period, void *priv) 7384 + devl_health_reporter_create(struct devlink *devlink, 7385 + const struct devlink_health_reporter_ops *ops, 7386 + u64 graceful_period, void *priv) 7404 7387 { 7405 7388 struct devlink_health_reporter *reporter; 7406 7389 7390 + devl_assert_locked(devlink); 7407 7391 mutex_lock(&devlink->reporters_lock); 7408 7392 if (devlink_health_reporter_find_by_name(devlink, ops->name)) { 7409 7393 reporter = ERR_PTR(-EEXIST); ··· 7419 7401 list_add_tail(&reporter->list, &devlink->reporter_list); 7420 7402 unlock: 7421 7403 mutex_unlock(&devlink->reporters_lock); 7404 + return reporter; 7405 + } 7406 + EXPORT_SYMBOL_GPL(devl_health_reporter_create); 7407 + 7408 + struct devlink_health_reporter * 7409 + devlink_health_reporter_create(struct devlink *devlink, 7410 + const struct devlink_health_reporter_ops *ops, 7411 + u64 graceful_period, void *priv) 7412 + { 7413 + struct devlink_health_reporter *reporter; 7414 + 7415 + devl_lock(devlink); 7416 + reporter = devl_health_reporter_create(devlink, ops, 7417 + graceful_period, priv); 7418 + devl_unlock(devlink); 7422 7419 return reporter; 7423 7420 } 7424 7421 EXPORT_SYMBOL_GPL(devlink_health_reporter_create); ··· 7462 7429 } 7463 7430 7464 7431 /** 7465 - * devlink_health_reporter_destroy - destroy devlink health reporter 7432 + * devl_health_reporter_destroy - destroy devlink health reporter 7466 7433 * 7467 7434 * @reporter: devlink health reporter to destroy 7468 7435 */ 7469 7436 void 7470 - devlink_health_reporter_destroy(struct devlink_health_reporter *reporter) 7437 + devl_health_reporter_destroy(struct devlink_health_reporter *reporter) 7471 7438 { 7472 7439 struct mutex *lock = &reporter->devlink->reporters_lock; 7440 + 7441 + devl_assert_locked(reporter->devlink); 7473 7442 7474 7443 mutex_lock(lock); 7475 7444 __devlink_health_reporter_destroy(reporter); 7476 7445 mutex_unlock(lock); 7477 7446 } 7447 + EXPORT_SYMBOL_GPL(devl_health_reporter_destroy); 7448 + 7449 + void 7450 + devlink_health_reporter_destroy(struct devlink_health_reporter *reporter) 7451 + { 7452 + struct devlink *devlink = reporter->devlink; 7453 + 7454 + devl_lock(devlink); 7455 + devl_health_reporter_destroy(reporter); 7456 + devl_unlock(devlink); 7457 + } 7478 7458 EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy); 7479 7459 7480 7460 /** 7481 - * devlink_port_health_reporter_destroy - destroy devlink port health reporter 7461 + * devl_port_health_reporter_destroy - destroy devlink port health reporter 7482 7462 * 7483 7463 * @reporter: devlink health reporter to destroy 7484 7464 */ 7485 7465 void 7486 - devlink_port_health_reporter_destroy(struct devlink_health_reporter *reporter) 7466 + devl_port_health_reporter_destroy(struct devlink_health_reporter *reporter) 7487 7467 { 7488 7468 struct mutex *lock = &reporter->devlink_port->reporters_lock; 7469 + 7470 + devl_assert_locked(reporter->devlink); 7489 7471 7490 7472 mutex_lock(lock); 7491 7473 __devlink_health_reporter_destroy(reporter); 7492 7474 mutex_unlock(lock); 7475 + } 7476 + EXPORT_SYMBOL_GPL(devl_port_health_reporter_destroy); 7477 + 7478 + void 7479 + devlink_port_health_reporter_destroy(struct devlink_health_reporter *reporter) 7480 + { 7481 + struct devlink *devlink = reporter->devlink; 7482 + 7483 + devl_lock(devlink); 7484 + devl_port_health_reporter_destroy(reporter); 7485 + devl_unlock(devlink); 7493 7486 } 7494 7487 EXPORT_SYMBOL_GPL(devlink_port_health_reporter_destroy); 7495 7488 ··· 7864 7805 unsigned long port_index; 7865 7806 int idx = 0; 7866 7807 7808 + devl_lock(devlink); 7809 + if (!devl_is_registered(devlink)) 7810 + goto next_devlink; 7811 + 7867 7812 mutex_lock(&devlink->reporters_lock); 7868 - if (!devl_is_registered(devlink)) { 7869 - mutex_unlock(&devlink->reporters_lock); 7870 - devlink_put(devlink); 7871 - continue; 7872 - } 7873 7813 7874 7814 list_for_each_entry(reporter, &devlink->reporter_list, 7875 7815 list) { ··· 7882 7824 NLM_F_MULTI); 7883 7825 if (err) { 7884 7826 mutex_unlock(&devlink->reporters_lock); 7827 + devl_unlock(devlink); 7885 7828 devlink_put(devlink); 7886 7829 state->idx = idx; 7887 7830 goto out; ··· 7890 7831 idx++; 7891 7832 } 7892 7833 mutex_unlock(&devlink->reporters_lock); 7893 - 7894 - devl_lock(devlink); 7895 - if (!devl_is_registered(devlink)) 7896 - goto next_devlink; 7897 7834 7898 7835 xa_for_each(&devlink->ports, port_index, port) { 7899 7836 mutex_lock(&port->reporters_lock);