aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorVladyslav Tarasiuk2020-07-10 15:25:08 +0300
committerDavid S. Miller2020-07-10 14:32:02 -0700
commit3c5584bf0a0493e8d232ade65f4b9c5e995f3a0c (patch)
tree0f400f9ec0b31b4f3a7d5f40d6da03159568ecee /net
parentc57544b3dec4480c1b455a43f18be5ec91ab3136 (diff)
devlink: Rework devlink health reporter destructor
Devlink keeps its own reference to every reporter in a list and inits refcount to 1 upon reporter's creation. Existing destructor waits to free the memory indefinitely using msleep() until all references except devlink's own are put. Rework this mechanism by moving memory free routine to a separate function, which is called when the last reporter reference is put. Besides, it allows to call __devlink_health_reporter_destroy() while locked on a reporters list mutex in symmetry to __devlink_health_reporter_create(), which is required in follow-up patch. Signed-off-by: Vladyslav Tarasiuk <vladyslavt@mellanox.com> Reviewed-by: Moshe Shemesh <moshe@mellanox.com> Reviewed-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/devlink.c37
1 files changed, 24 insertions, 13 deletions
diff --git a/net/core/devlink.c b/net/core/devlink.c
index a203d35fb56f..b85f2113398d 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -5379,6 +5379,29 @@ unlock:
}
EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
+static void
+devlink_health_reporter_free(struct devlink_health_reporter *reporter)
+{
+ mutex_destroy(&reporter->dump_lock);
+ if (reporter->dump_fmsg)
+ devlink_fmsg_free(reporter->dump_fmsg);
+ kfree(reporter);
+}
+
+static void
+devlink_health_reporter_put(struct devlink_health_reporter *reporter)
+{
+ if (refcount_dec_and_test(&reporter->refcount))
+ devlink_health_reporter_free(reporter);
+}
+
+static void
+__devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
+{
+ list_del(&reporter->list);
+ devlink_health_reporter_put(reporter);
+}
+
/**
* devlink_health_reporter_destroy - destroy devlink health reporter
*
@@ -5388,14 +5411,8 @@ void
devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
{
mutex_lock(&reporter->devlink->reporters_lock);
- list_del(&reporter->list);
+ __devlink_health_reporter_destroy(reporter);
mutex_unlock(&reporter->devlink->reporters_lock);
- while (refcount_read(&reporter->refcount) > 1)
- msleep(100);
- mutex_destroy(&reporter->dump_lock);
- if (reporter->dump_fmsg)
- devlink_fmsg_free(reporter->dump_fmsg);
- kfree(reporter);
}
EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
@@ -5665,12 +5682,6 @@ unlock:
return NULL;
}
-static void
-devlink_health_reporter_put(struct devlink_health_reporter *reporter)
-{
- refcount_dec(&reporter->refcount);
-}
-
void
devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
enum devlink_health_reporter_state state)