]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/qdisc: introduce qdisc_ref() and qdisc_unref()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 2 Sep 2024 02:41:57 +0000 (11:41 +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.

19 files changed:
src/network/networkd-network.c
src/network/tc/cake.c
src/network/tc/codel.c
src/network/tc/ets.c
src/network/tc/fifo.c
src/network/tc/fq-codel.c
src/network/tc/fq-pie.c
src/network/tc/fq.c
src/network/tc/gred.c
src/network/tc/hhf.c
src/network/tc/htb.c
src/network/tc/netem.c
src/network/tc/pie.c
src/network/tc/qdisc.c
src/network/tc/qdisc.h
src/network/tc/sfb.c
src/network/tc/sfq.c
src/network/tc/tbf.c
src/network/tc/teql.c

index 94666c2bdd03edd8ed67ee6171c4c6bc99d1aacd..fafa0e570ee369a73c8349585c761edbd4269a7a 100644 (file)
@@ -801,7 +801,7 @@ static Network *network_free(Network *network) {
         hashmap_free(network->rules_by_section);
         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_with_destructor(network->qdiscs_by_section, qdisc_free);
+        hashmap_free(network->qdiscs_by_section);
         hashmap_free_with_destructor(network->tclasses_by_section, tclass_free);
 
         return mfree(network);
index c495fafda4cc85678416d7b80a75a5f113d648fb..704e527b46a1f29245198ae6c67cf71329d653d3 100644 (file)
@@ -150,7 +150,7 @@ int config_parse_cake_bandwidth(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         CommonApplicationsKeptEnhanced *c;
         Network *network = ASSERT_PTR(data);
         uint64_t k;
@@ -204,7 +204,7 @@ int config_parse_cake_overhead(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         CommonApplicationsKeptEnhanced *c;
         Network *network = ASSERT_PTR(data);
         int32_t v;
@@ -263,7 +263,7 @@ int config_parse_cake_mpu(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         CommonApplicationsKeptEnhanced *c;
         Network *network = ASSERT_PTR(data);
         uint32_t v;
@@ -321,7 +321,7 @@ int config_parse_cake_tristate(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         CommonApplicationsKeptEnhanced *c;
         Network *network = ASSERT_PTR(data);
         int *dest, r;
@@ -386,7 +386,7 @@ int config_parse_cake_compensation_mode(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         CommonApplicationsKeptEnhanced *c;
         Network *network = ASSERT_PTR(data);
         CakeCompensationMode mode;
@@ -451,7 +451,7 @@ int config_parse_cake_flow_isolation_mode(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         CommonApplicationsKeptEnhanced *c;
         Network *network = ASSERT_PTR(data);
         CakeFlowIsolationMode mode;
@@ -513,7 +513,7 @@ int config_parse_cake_priority_queueing_preset(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         CommonApplicationsKeptEnhanced *c;
         CakePriorityQueueingPreset preset;
         Network *network = ASSERT_PTR(data);
@@ -565,7 +565,7 @@ int config_parse_cake_fwmark(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         CommonApplicationsKeptEnhanced *c;
         Network *network = ASSERT_PTR(data);
         uint32_t fwmark;
@@ -623,7 +623,7 @@ int config_parse_cake_rtt(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         CommonApplicationsKeptEnhanced *c;
         Network *network = ASSERT_PTR(data);
         usec_t t;
@@ -689,7 +689,7 @@ int config_parse_cake_ack_filter(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         CommonApplicationsKeptEnhanced *c;
         CakeAckFilter ack_filter;
         Network *network = ASSERT_PTR(data);
index e21252394c03e0b936871c7d4c98c089c589dc1d..53ccf66e419e64a04721d79720625d8d7250b4f1 100644 (file)
@@ -86,7 +86,7 @@ int config_parse_controlled_delay_u32(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         ControlledDelay *cd;
         Network *network = ASSERT_PTR(data);
         int r;
@@ -138,7 +138,7 @@ int config_parse_controlled_delay_usec(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         ControlledDelay *cd;
         Network *network = ASSERT_PTR(data);
         usec_t *p;
@@ -203,7 +203,7 @@ int config_parse_controlled_delay_bool(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         ControlledDelay *cd;
         Network *network = ASSERT_PTR(data);
         int r;
index 730b0a10c3cfb9d8a03a2e5fe1f9bea8731c42d1..4af750834cb30fafb14dd3c12b1a9e7fcf150bcd 100644 (file)
@@ -88,7 +88,7 @@ int config_parse_ets_u8(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         EnhancedTransmissionSelection *ets;
         Network *network = ASSERT_PTR(data);
         uint8_t v, *p;
@@ -154,7 +154,7 @@ int config_parse_ets_quanta(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         EnhancedTransmissionSelection *ets;
         Network *network = ASSERT_PTR(data);
         int r;
@@ -237,7 +237,7 @@ int config_parse_ets_prio(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         EnhancedTransmissionSelection *ets;
         Network *network = ASSERT_PTR(data);
         int r;
index 940fa0062f0016c44f79bd516864df3ad2df7513..9638be8ff9caa1d3e3e282ea0efbe8949ce1d576 100644 (file)
@@ -52,7 +52,7 @@ int config_parse_pfifo_size(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         Network *network = ASSERT_PTR(data);
         FirstInFirstOut *fifo;
         int r;
@@ -112,7 +112,7 @@ int config_parse_bfifo_size(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         Network *network = ASSERT_PTR(data);
         FirstInFirstOut *fifo;
         uint64_t u;
index 124faf73e72a4d9afae90a596c0501259293349a..9255cde4650d9c2093acc13822cace7a2413d99b 100644 (file)
@@ -106,7 +106,7 @@ int config_parse_fair_queueing_controlled_delay_u32(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         FairQueueingControlledDelay *fqcd;
         Network *network = ASSERT_PTR(data);
         uint32_t *p;
@@ -166,7 +166,7 @@ int config_parse_fair_queueing_controlled_delay_usec(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         FairQueueingControlledDelay *fqcd;
         Network *network = ASSERT_PTR(data);
         usec_t *p;
@@ -231,7 +231,7 @@ int config_parse_fair_queueing_controlled_delay_bool(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         FairQueueingControlledDelay *fqcd;
         Network *network = ASSERT_PTR(data);
         int r;
@@ -276,7 +276,7 @@ int config_parse_fair_queueing_controlled_delay_size(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         FairQueueingControlledDelay *fqcd;
         Network *network = ASSERT_PTR(data);
         uint64_t sz;
index c8b2e7b7ee90838c6db259b42103b0bceeaef7f5..8f4f7c431c441a074c4c40dc3843cd460084deff 100644 (file)
@@ -49,7 +49,7 @@ int config_parse_fq_pie_packet_limit(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         FlowQueuePIE *fq_pie;
         Network *network = ASSERT_PTR(data);
         uint32_t val;
index 74785c980ae4b932aa0ccd63b7f2b7ba1c0c19aa..ea55e5cb0a122d67370cb42bf41ebadf93f2fe93 100644 (file)
@@ -115,7 +115,7 @@ int config_parse_fair_queueing_u32(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         FairQueueing *fq;
         Network *network = ASSERT_PTR(data);
         uint32_t *p;
@@ -179,7 +179,7 @@ int config_parse_fair_queueing_size(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         FairQueueing *fq;
         Network *network = ASSERT_PTR(data);
         uint64_t sz;
@@ -247,7 +247,7 @@ int config_parse_fair_queueing_bool(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         FairQueueing *fq;
         Network *network = ASSERT_PTR(data);
         int r;
@@ -293,7 +293,7 @@ int config_parse_fair_queueing_usec(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         FairQueueing *fq;
         Network *network = ASSERT_PTR(data);
         usec_t sec;
@@ -353,7 +353,7 @@ int config_parse_fair_queueing_max_rate(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         FairQueueing *fq;
         Network *network = ASSERT_PTR(data);
         uint64_t sz;
index 2efb02c345f044e27434a7746f0badeb4d0036ab..198905a1521ff207f07a1d2a84083ae3c7ea2859 100644 (file)
@@ -77,7 +77,7 @@ int config_parse_generic_random_early_detection_u32(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         GenericRandomEarlyDetection *gred;
         Network *network = ASSERT_PTR(data);
         uint32_t *p;
@@ -143,7 +143,7 @@ int config_parse_generic_random_early_detection_bool(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         GenericRandomEarlyDetection *gred;
         Network *network = ASSERT_PTR(data);
         int r;
index d44522f98cc9292b6cf6fd06a098aacee01b3d2f..9ddb7ef9063d5d00ce209c052ff1dfe05dbaec2c 100644 (file)
@@ -49,7 +49,7 @@ int config_parse_heavy_hitter_filter_packet_limit(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         HeavyHitterFilter *hhf;
         Network *network = ASSERT_PTR(data);
         int r;
index eb2c8cfff4cd14ee415a923261bf4c6c713733da..8f1faa1dc5d45900d2fb6bdee029dda9ef3db3d7 100644 (file)
@@ -57,7 +57,7 @@ int config_parse_hierarchy_token_bucket_default_class(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         HierarchyTokenBucket *htb;
         Network *network = ASSERT_PTR(data);
         int r;
@@ -109,7 +109,7 @@ int config_parse_hierarchy_token_bucket_u32(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         HierarchyTokenBucket *htb;
         Network *network = ASSERT_PTR(data);
         int r;
index 6a63221c3ac30142093e7564b6692d0ba7207e3d..51039de1f4e7b7b4027a28cb96633f9418a15482 100644 (file)
@@ -60,7 +60,7 @@ int config_parse_network_emulator_delay(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         Network *network = ASSERT_PTR(data);
         NetworkEmulator *ne;
         usec_t u;
@@ -121,7 +121,7 @@ int config_parse_network_emulator_rate(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         Network *network = ASSERT_PTR(data);
         NetworkEmulator *ne;
         uint32_t rate;
@@ -181,7 +181,7 @@ int config_parse_network_emulator_packet_limit(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         Network *network = ASSERT_PTR(data);
         NetworkEmulator *ne;
         int r;
index c9b171baf11d7ed79064118c96ccdcca21f2c85e..c482f19787abc210c7e6d47cc8c867018869b3ac 100644 (file)
@@ -49,7 +49,7 @@ int config_parse_pie_packet_limit(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         ProportionalIntegralControllerEnhanced *pie;
         Network *network = ASSERT_PTR(data);
         int r;
index 38dee2c00157febd0c425399d10e6979ab75c2c7..d372481d6280b5bd3dcf9a3da7e49057cb769a44 100644 (file)
@@ -42,8 +42,54 @@ const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX] = {
         [QDISC_KIND_TEQL]            = &teql_vtable,
 };
 
+static QDisc* qdisc_detach_impl(QDisc *qdisc) {
+        assert(qdisc);
+        assert(!qdisc->link || !qdisc->network);
+
+        if (qdisc->network) {
+                assert(qdisc->section);
+                hashmap_remove(qdisc->network->qdiscs_by_section, qdisc->section);
+
+                qdisc->network = NULL;
+                return qdisc;
+        }
+
+        if (qdisc->link) {
+                set_remove(qdisc->link->qdiscs, qdisc);
+
+                qdisc->link = NULL;
+                return qdisc;
+        }
+
+        return NULL;
+}
+
+static void qdisc_detach(QDisc *qdisc) {
+        assert(qdisc);
+
+        qdisc_unref(qdisc_detach_impl(qdisc));
+}
+
+static void qdisc_hash_func(const QDisc *qdisc, struct siphash *state);
+static int qdisc_compare_func(const QDisc *a, const QDisc *b);
+
+DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
+        qdisc_hash_ops,
+        QDisc,
+        qdisc_hash_func,
+        qdisc_compare_func,
+        qdisc_detach);
+
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
+        qdisc_section_hash_ops,
+        ConfigSection,
+        config_section_hash_func,
+        config_section_compare_func,
+        QDisc,
+        qdisc_detach);
+
 static int qdisc_new(QDiscKind kind, QDisc **ret) {
-        _cleanup_(qdisc_freep) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unrefp) QDisc *qdisc = NULL;
         int r;
 
         if (kind == _QDISC_KIND_INVALID) {
@@ -52,6 +98,7 @@ static int qdisc_new(QDiscKind kind, QDisc **ret) {
                         return -ENOMEM;
 
                 *qdisc = (QDisc) {
+                        .n_ref = 1,
                         .parent = TC_H_ROOT,
                         .kind = kind,
                 };
@@ -61,6 +108,7 @@ static int qdisc_new(QDiscKind kind, QDisc **ret) {
                 if (!qdisc)
                         return -ENOMEM;
 
+                qdisc->n_ref = 1;
                 qdisc->parent = TC_H_ROOT;
                 qdisc->kind = kind;
 
@@ -78,7 +126,7 @@ static int qdisc_new(QDiscKind kind, QDisc **ret) {
 
 int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret) {
         _cleanup_(config_section_freep) ConfigSection *n = NULL;
-        _cleanup_(qdisc_freep) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unrefp) QDisc *qdisc = NULL;
         QDisc *existing;
         int r;
 
@@ -113,14 +161,14 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
                 qdisc->parent = existing->parent;
                 qdisc->tca_kind = TAKE_PTR(existing->tca_kind);
 
-                qdisc_free(existing);
+                qdisc_detach(existing);
         }
 
         qdisc->network = network;
         qdisc->section = TAKE_PTR(n);
         qdisc->source = NETWORK_CONFIG_SOURCE_STATIC;
 
-        r = hashmap_ensure_put(&network->qdiscs_by_section, &config_section_hash_ops, qdisc->section, qdisc);
+        r = hashmap_ensure_put(&network->qdiscs_by_section, &qdisc_section_hash_ops, qdisc->section, qdisc);
         if (r < 0)
                 return r;
 
@@ -128,22 +176,20 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
         return 0;
 }
 
-QDisc* qdisc_free(QDisc *qdisc) {
+static QDisc* qdisc_free(QDisc *qdisc) {
         if (!qdisc)
                 return NULL;
 
-        if (qdisc->network && qdisc->section)
-                hashmap_remove(qdisc->network->qdiscs_by_section, qdisc->section);
+        qdisc_detach_impl(qdisc);
 
         config_section_free(qdisc->section);
 
-        if (qdisc->link)
-                set_remove(qdisc->link->qdiscs, qdisc);
-
         free(qdisc->tca_kind);
         return mfree(qdisc);
 }
 
+DEFINE_TRIVIAL_REF_UNREF_FUNC(QDisc, qdisc, qdisc_free);
+
 static const char *qdisc_get_tca_kind(const QDisc *qdisc) {
         assert(qdisc);
 
@@ -177,13 +223,6 @@ static int qdisc_compare_func(const QDisc *a, const QDisc *b) {
         return strcmp_ptr(qdisc_get_tca_kind(a), qdisc_get_tca_kind(b));
 }
 
-DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
-        qdisc_hash_ops,
-        QDisc,
-        qdisc_hash_func,
-        qdisc_compare_func,
-        qdisc_free);
-
 static int qdisc_get(Link *link, const QDisc *in, QDisc **ret) {
         QDisc *existing;
 
@@ -199,11 +238,13 @@ static int qdisc_get(Link *link, const QDisc *in, QDisc **ret) {
         return 0;
 }
 
-static int qdisc_add(Link *link, QDisc *qdisc) {
+static int qdisc_attach(Link *link, QDisc *qdisc) {
         int r;
 
         assert(link);
         assert(qdisc);
+        assert(!qdisc->link);
+        assert(!qdisc->network);
 
         r = set_ensure_put(&link->qdiscs, &qdisc_hash_ops, qdisc);
         if (r < 0)
@@ -212,11 +253,12 @@ static int qdisc_add(Link *link, QDisc *qdisc) {
                 return -EEXIST;
 
         qdisc->link = link;
+        qdisc_ref(qdisc);
         return 0;
 }
 
 static int qdisc_dup(const QDisc *src, QDisc **ret) {
-        _cleanup_(qdisc_freep) QDisc *dst = NULL;
+        _cleanup_(qdisc_unrefp) QDisc *dst = NULL;
 
         assert(src);
         assert(ret);
@@ -228,7 +270,8 @@ static int qdisc_dup(const QDisc *src, QDisc **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;
@@ -319,7 +362,7 @@ void link_qdisc_drop_marked(Link *link) {
 
                 if (qdisc->state == 0) {
                         log_qdisc_debug(qdisc, link, "Forgetting");
-                        qdisc_free(qdisc);
+                        qdisc_detach(qdisc);
                 } else
                         log_qdisc_debug(qdisc, link, "Removed");
         }
@@ -443,17 +486,17 @@ int link_request_qdisc(Link *link, QDisc *qdisc) {
         assert(qdisc);
 
         if (qdisc_get(link, qdisc, &existing) < 0) {
-                _cleanup_(qdisc_freep) QDisc *tmp = NULL;
+                _cleanup_(qdisc_unrefp) QDisc *tmp = NULL;
 
                 r = qdisc_dup(qdisc, &tmp);
                 if (r < 0)
                         return log_oom();
 
-                r = qdisc_add(link, tmp);
+                r = qdisc_attach(link, tmp);
                 if (r < 0)
                         return log_link_warning_errno(link, r, "Failed to store QDisc: %m");
 
-                existing = TAKE_PTR(tmp);
+                existing = tmp;
         } else
                 existing->source = qdisc->source;
 
@@ -476,7 +519,7 @@ int link_request_qdisc(Link *link, QDisc *qdisc) {
 }
 
 int manager_rtnl_process_qdisc(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
-        _cleanup_(qdisc_freep) QDisc *tmp = NULL;
+        _cleanup_(qdisc_unrefp) QDisc *tmp = NULL;
         QDisc *qdisc = NULL;
         Link *link;
         uint16_t type;
@@ -551,13 +594,13 @@ int manager_rtnl_process_qdisc(sd_netlink *rtnl, sd_netlink_message *message, Ma
                         qdisc_enter_configured(tmp);
                         log_qdisc_debug(tmp, link, "Received new");
 
-                        r = qdisc_add(link, tmp);
+                        r = qdisc_attach(link, tmp);
                         if (r < 0) {
                                 log_link_warning_errno(link, r, "Failed to remember QDisc, ignoring: %m");
                                 return 0;
                         }
 
-                        qdisc = TAKE_PTR(tmp);
+                        qdisc = tmp;
                 }
 
                 if (!m->enumerating) {
@@ -628,7 +671,7 @@ void network_drop_invalid_qdisc(Network *network) {
 
         HASHMAP_FOREACH(qdisc, network->qdiscs_by_section)
                 if (qdisc_section_verify(qdisc, &has_root, &has_clsact) < 0)
-                        qdisc_free(qdisc);
+                        qdisc_detach(qdisc);
 }
 
 int config_parse_qdisc_parent(
@@ -643,7 +686,7 @@ int config_parse_qdisc_parent(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         Network *network = ASSERT_PTR(data);
         int r;
 
@@ -702,7 +745,7 @@ int config_parse_qdisc_handle(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         Network *network = ASSERT_PTR(data);
         uint16_t n;
         int r;
index cbba1bef71199a9b59849bf1cf405bfb7c86d857..3989ad76515313d7b63b5d6b51792d765754c587 100644 (file)
@@ -42,6 +42,8 @@ typedef struct QDisc {
         NetworkConfigSource source;
         NetworkConfigState state;
 
+        unsigned n_ref;
+
         uint32_t handle;
         uint32_t parent;
 
@@ -74,7 +76,8 @@ extern const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX];
 
 DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(QDisc, qdisc);
 
-QDisc* qdisc_free(QDisc *qdisc);
+QDisc* qdisc_ref(QDisc *qdisc);
+QDisc* qdisc_unref(QDisc *qdisc);
 int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret);
 
 void qdisc_mark_recursive(QDisc *qdisc);
@@ -89,7 +92,7 @@ void network_drop_invalid_qdisc(Network *network);
 
 int manager_rtnl_process_qdisc(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
 
-DEFINE_SECTION_CLEANUP_FUNCTIONS(QDisc, qdisc_free);
+DEFINE_SECTION_CLEANUP_FUNCTIONS(QDisc, qdisc_unref);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_qdisc_parent);
 CONFIG_PARSER_PROTOTYPE(config_parse_qdisc_handle);
index 861c5fe2a0c0b78574a454ba84c96404adeea758..07fac6700f693b83b11ab844dbe642959258b7f9 100644 (file)
@@ -60,7 +60,7 @@ int config_parse_stochastic_fair_blue_u32(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         StochasticFairBlue *sfb;
         Network *network = ASSERT_PTR(data);
         int r;
index 92dbae1166a66f46e5cfb75773a993c60dcfb29c..78778653439cbedf0640d1dccd0879592d4d9278 100644 (file)
@@ -44,7 +44,7 @@ int config_parse_stochastic_fairness_queueing_perturb_period(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         StochasticFairnessQueueing *sfq;
         Network *network = ASSERT_PTR(data);
         int r;
index 647fc8cb1eb8a78e6ba87ae5749b9abbfee64bac..3e7a3098dab3fa736f5be4becd78c432e4530f28 100644 (file)
@@ -122,7 +122,7 @@ int config_parse_token_bucket_filter_size(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         Network *network = ASSERT_PTR(data);
         TokenBucketFilter *tbf;
         uint64_t k;
@@ -195,7 +195,7 @@ int config_parse_token_bucket_filter_rate(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         Network *network = ASSERT_PTR(data);
         TokenBucketFilter *tbf;
         uint64_t k, *p;
@@ -256,7 +256,7 @@ int config_parse_token_bucket_filter_latency(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         Network *network = ASSERT_PTR(data);
         TokenBucketFilter *tbf;
         usec_t u;
index dcb149dbe2a5bc0f203b1b96de22c85fa7bb1961..f4fa331f523c237218fba3e8e39a580d5910d955 100644 (file)
@@ -50,7 +50,7 @@ int config_parse_trivial_link_equalizer_id(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+        _cleanup_(qdisc_unref_or_set_invalidp) QDisc *qdisc = NULL;
         TrivialLinkEqualizer *teql;
         Network *network = ASSERT_PTR(data);
         unsigned id;