]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/tclass: introduce tclass_ref() and tclass_unref()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 2 Sep 2024 02:59:51 +0000 (11:59 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 2 Sep 2024 05:12:35 +0000 (14:12 +0900)
No functional change, just refactoring and preparation for later change.

src/network/networkd-network.c
src/network/tc/drr.c
src/network/tc/htb.c
src/network/tc/qfq.c
src/network/tc/tclass.c
src/network/tc/tclass.h

index fafa0e570ee369a73c8349585c761edbd4269a7a..a5bb6dd529822add4946b90a61a9ec98d80fe13c 100644 (file)
@@ -802,7 +802,7 @@ static Network *network_free(Network *network) {
         hashmap_free_with_destructor(network->dhcp_static_leases_by_section, dhcp_static_lease_free);
         ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
         hashmap_free(network->qdiscs_by_section);
-        hashmap_free_with_destructor(network->tclasses_by_section, tclass_free);
+        hashmap_free(network->tclasses_by_section);
 
         return mfree(network);
 }
index 373911bc70f31aa68c0c864fa7cf7bfdc5c9d7de..5d754101de2aff20f1bc66b45a033147259101f0 100644 (file)
@@ -54,7 +54,7 @@ int config_parse_drr_size(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
+        _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL;
         DeficitRoundRobinSchedulerClass *drr;
         Network *network = ASSERT_PTR(data);
         uint64_t u;
index 8f1faa1dc5d45900d2fb6bdee029dda9ef3db3d7..39f436a804d2a6df4cf8168d5725c6499219b29e 100644 (file)
@@ -251,7 +251,7 @@ int config_parse_hierarchy_token_bucket_class_u32(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
+        _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL;
         HierarchyTokenBucketClass *htb;
         Network *network = ASSERT_PTR(data);
         uint32_t v;
@@ -304,7 +304,7 @@ int config_parse_hierarchy_token_bucket_class_size(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
+        _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL;
         HierarchyTokenBucketClass *htb;
         Network *network = ASSERT_PTR(data);
         uint64_t v;
@@ -387,7 +387,7 @@ int config_parse_hierarchy_token_bucket_class_rate(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
+        _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL;
         HierarchyTokenBucketClass *htb;
         Network *network = ASSERT_PTR(data);
         uint64_t *v;
index 7702e6ff6e733fa0151bfa3d35ff71b646ef52bd..0da53a89e432ece2a7f9865ba0a1fe35dd6b01a6 100644 (file)
@@ -62,7 +62,7 @@ int config_parse_quick_fair_queueing_weight(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
+        _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL;
         QuickFairQueueingClass *qfq;
         Network *network = ASSERT_PTR(data);
         uint32_t v;
@@ -122,7 +122,7 @@ int config_parse_quick_fair_queueing_max_packet(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
+        _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL;
         QuickFairQueueingClass *qfq;
         Network *network = ASSERT_PTR(data);
         uint64_t v;
index fcbe8cbcf46bda8749fe74b50bd572202d4c69bb..168d93e1c521f58807e54af863ebaf2084f8ed05 100644 (file)
@@ -24,8 +24,54 @@ const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX] = {
         [TCLASS_KIND_QFQ] = &qfq_tclass_vtable,
 };
 
+static TClass* tclass_detach_impl(TClass *tclass) {
+        assert(tclass);
+        assert(!tclass->link || !tclass->network);
+
+        if (tclass->network) {
+                assert(tclass->section);
+                hashmap_remove(tclass->network->tclasses_by_section, tclass->section);
+
+                tclass->network = NULL;
+                return tclass;
+        }
+
+        if (tclass->link) {
+                set_remove(tclass->link->tclasses, tclass);
+
+                tclass->link = NULL;
+                return tclass;
+        }
+
+        return NULL;
+}
+
+static void tclass_detach(TClass *tclass) {
+        assert(tclass);
+
+        tclass_unref(tclass_detach_impl(tclass));
+}
+
+static void tclass_hash_func(const TClass *tclass, struct siphash *state);
+static int tclass_compare_func(const TClass *a, const TClass *b);
+
+DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
+        tclass_hash_ops,
+        TClass,
+        tclass_hash_func,
+        tclass_compare_func,
+        tclass_detach);
+
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
+        tclass_section_hash_ops,
+        ConfigSection,
+        config_section_hash_func,
+        config_section_compare_func,
+        TClass,
+        tclass_detach);
+
 static int tclass_new(TClassKind kind, TClass **ret) {
-        _cleanup_(tclass_freep) TClass *tclass = NULL;
+        _cleanup_(tclass_unrefp) TClass *tclass = NULL;
         int r;
 
         if (kind == _TCLASS_KIND_INVALID) {
@@ -34,6 +80,7 @@ static int tclass_new(TClassKind kind, TClass **ret) {
                         return -ENOMEM;
 
                 *tclass = (TClass) {
+                        .n_ref = 1,
                         .parent = TC_H_ROOT,
                         .kind = kind,
                 };
@@ -43,6 +90,7 @@ static int tclass_new(TClassKind kind, TClass **ret) {
                 if (!tclass)
                         return -ENOMEM;
 
+                tclass->n_ref = 1;
                 tclass->parent = TC_H_ROOT;
                 tclass->kind = kind;
 
@@ -60,7 +108,7 @@ static int tclass_new(TClassKind kind, TClass **ret) {
 
 int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret) {
         _cleanup_(config_section_freep) ConfigSection *n = NULL;
-        _cleanup_(tclass_freep) TClass *tclass = NULL;
+        _cleanup_(tclass_unrefp) TClass *tclass = NULL;
         TClass *existing;
         int r;
 
@@ -90,7 +138,7 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
         tclass->section = TAKE_PTR(n);
         tclass->source = NETWORK_CONFIG_SOURCE_STATIC;
 
-        r = hashmap_ensure_put(&network->tclasses_by_section, &config_section_hash_ops, tclass->section, tclass);
+        r = hashmap_ensure_put(&network->tclasses_by_section, &tclass_section_hash_ops, tclass->section, tclass);
         if (r < 0)
                 return r;
 
@@ -98,22 +146,20 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
         return 0;
 }
 
-TClass* tclass_free(TClass *tclass) {
+static TClass* tclass_free(TClass *tclass) {
         if (!tclass)
                 return NULL;
 
-        if (tclass->network && tclass->section)
-                hashmap_remove(tclass->network->tclasses_by_section, tclass->section);
+        tclass_detach_impl(tclass);
 
         config_section_free(tclass->section);
 
-        if (tclass->link)
-                set_remove(tclass->link->tclasses, tclass);
-
         free(tclass->tca_kind);
         return mfree(tclass);
 }
 
+DEFINE_TRIVIAL_REF_UNREF_FUNC(TClass, tclass, tclass_free);
+
 static const char *tclass_get_tca_kind(const TClass *tclass) {
         assert(tclass);
 
@@ -147,13 +193,6 @@ static int tclass_compare_func(const TClass *a, const TClass *b) {
         return strcmp_ptr(tclass_get_tca_kind(a), tclass_get_tca_kind(b));
 }
 
-DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
-        tclass_hash_ops,
-        TClass,
-        tclass_hash_func,
-        tclass_compare_func,
-        tclass_free);
-
 static int tclass_get(Link *link, const TClass *in, TClass **ret) {
         TClass *existing;
 
@@ -169,11 +208,13 @@ static int tclass_get(Link *link, const TClass *in, TClass **ret) {
         return 0;
 }
 
-static int tclass_add(Link *link, TClass *tclass) {
+static int tclass_attach(Link *link, TClass *tclass) {
         int r;
 
         assert(link);
         assert(tclass);
+        assert(!tclass->link);
+        assert(!tclass->network);
 
         r = set_ensure_put(&link->tclasses, &tclass_hash_ops, tclass);
         if (r < 0)
@@ -182,11 +223,12 @@ static int tclass_add(Link *link, TClass *tclass) {
                 return -EEXIST;
 
         tclass->link = link;
+        tclass_ref(tclass);
         return 0;
 }
 
 static int tclass_dup(const TClass *src, TClass **ret) {
-        _cleanup_(tclass_freep) TClass *dst = NULL;
+        _cleanup_(tclass_unrefp) TClass *dst = NULL;
 
         assert(src);
         assert(ret);
@@ -198,7 +240,8 @@ static int tclass_dup(const TClass *src, TClass **ret) {
         if (!dst)
                 return -ENOMEM;
 
-        /* clear all pointers */
+        /* clear the reference counter and all pointers */
+        dst->n_ref = 1;
         dst->network = NULL;
         dst->section = NULL;
         dst->link = NULL;
@@ -286,7 +329,7 @@ void link_tclass_drop_marked(Link *link) {
 
                 if (tclass->state == 0) {
                         log_tclass_debug(tclass, link, "Forgetting");
-                        tclass_free(tclass);
+                        tclass_detach(tclass);
                 } else
                         log_tclass_debug(tclass, link, "Removed");
         }
@@ -393,17 +436,17 @@ int link_request_tclass(Link *link, TClass *tclass) {
         assert(tclass);
 
         if (tclass_get(link, tclass, &existing) < 0) {
-                _cleanup_(tclass_freep) TClass *tmp = NULL;
+                _cleanup_(tclass_unrefp) TClass *tmp = NULL;
 
                 r = tclass_dup(tclass, &tmp);
                 if (r < 0)
                         return log_oom();
 
-                r = tclass_add(link, tmp);
+                r = tclass_attach(link, tmp);
                 if (r < 0)
                         return log_link_warning_errno(link, r, "Failed to store TClass: %m");
 
-                existing = TAKE_PTR(tmp);
+                existing = tmp;
         } else
                 existing->source = tclass->source;
 
@@ -426,7 +469,7 @@ int link_request_tclass(Link *link, TClass *tclass) {
 }
 
 int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
-        _cleanup_(tclass_freep) TClass *tmp = NULL;
+        _cleanup_(tclass_unrefp) TClass *tmp = NULL;
         TClass *tclass = NULL;
         Link *link;
         uint16_t type;
@@ -501,13 +544,13 @@ int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, M
                         tclass_enter_configured(tmp);
                         log_tclass_debug(tmp, link, "Received new");
 
-                        r = tclass_add(link, tmp);
+                        r = tclass_attach(link, tmp);
                         if (r < 0) {
                                 log_link_warning_errno(link, r, "Failed to remember TClass, ignoring: %m");
                                 return 0;
                         }
 
-                        tclass = TAKE_PTR(tmp);
+                        tclass = tmp;
                 }
 
                 break;
@@ -566,7 +609,7 @@ void network_drop_invalid_tclass(Network *network) {
 
         HASHMAP_FOREACH(tclass, network->tclasses_by_section)
                 if (tclass_section_verify(tclass) < 0)
-                        tclass_free(tclass);
+                        tclass_detach(tclass);
 }
 
 int config_parse_tclass_parent(
@@ -581,7 +624,7 @@ int config_parse_tclass_parent(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
+        _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL;
         Network *network = ASSERT_PTR(data);
         int r;
 
@@ -627,7 +670,7 @@ int config_parse_tclass_classid(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
+        _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL;
         Network *network = ASSERT_PTR(data);
         int r;
 
index 85df57d42c21eebd9ac8e56a2b656a8e8fbfd1e7..44f71814501dc8e95d595ad95a342e9e26429523 100644 (file)
@@ -24,6 +24,8 @@ typedef struct TClass {
         NetworkConfigSource source;
         NetworkConfigState state;
 
+        unsigned n_ref;
+
         uint32_t classid;
         uint32_t parent;
 
@@ -55,7 +57,8 @@ extern const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX];
 
 DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(TClass, tclass);
 
-TClass* tclass_free(TClass *tclass);
+TClass* tclass_ref(TClass *tclass);
+TClass* tclass_unref(TClass *tclass);
 int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret);
 
 void tclass_mark_recursive(TClass *tclass);
@@ -71,7 +74,7 @@ void network_drop_invalid_tclass(Network *network);
 int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
 int link_enumerate_tclass(Link *link, uint32_t parent);
 
-DEFINE_SECTION_CLEANUP_FUNCTIONS(TClass, tclass_free);
+DEFINE_SECTION_CLEANUP_FUNCTIONS(TClass, tclass_unref);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_tclass_parent);
 CONFIG_PARSER_PROTOTYPE(config_parse_tclass_classid);