devlink: Rework devlink health reporter destructor
authorVladyslav Tarasiuk <vladyslavt@mellanox.com>
Fri, 10 Jul 2020 12:25:08 +0000 (15:25 +0300)
committerDavid S. Miller <davem@davemloft.net>
Fri, 10 Jul 2020 21:32:02 +0000 (14:32 -0700)
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>
net/core/devlink.c

index a203d35fb56f3edcf27d41fa239874f2356f0c3b..b85f2113398d87de1026ffce74f4e2c4dc1e6b8d 100644 (file)
@@ -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)