diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 94666c2bdd0..fafa0e570ee 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -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); diff --git a/src/network/tc/cake.c b/src/network/tc/cake.c index c495fafda4c..704e527b46a 100644 --- a/src/network/tc/cake.c +++ b/src/network/tc/cake.c @@ -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); diff --git a/src/network/tc/codel.c b/src/network/tc/codel.c index e21252394c0..53ccf66e419 100644 --- a/src/network/tc/codel.c +++ b/src/network/tc/codel.c @@ -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; diff --git a/src/network/tc/ets.c b/src/network/tc/ets.c index 730b0a10c3c..4af750834cb 100644 --- a/src/network/tc/ets.c +++ b/src/network/tc/ets.c @@ -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; diff --git a/src/network/tc/fifo.c b/src/network/tc/fifo.c index 940fa0062f0..9638be8ff9c 100644 --- a/src/network/tc/fifo.c +++ b/src/network/tc/fifo.c @@ -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; diff --git a/src/network/tc/fq-codel.c b/src/network/tc/fq-codel.c index 124faf73e72..9255cde4650 100644 --- a/src/network/tc/fq-codel.c +++ b/src/network/tc/fq-codel.c @@ -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; diff --git a/src/network/tc/fq-pie.c b/src/network/tc/fq-pie.c index c8b2e7b7ee9..8f4f7c431c4 100644 --- a/src/network/tc/fq-pie.c +++ b/src/network/tc/fq-pie.c @@ -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; diff --git a/src/network/tc/fq.c b/src/network/tc/fq.c index 74785c980ae..ea55e5cb0a1 100644 --- a/src/network/tc/fq.c +++ b/src/network/tc/fq.c @@ -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; diff --git a/src/network/tc/gred.c b/src/network/tc/gred.c index 2efb02c345f..198905a1521 100644 --- a/src/network/tc/gred.c +++ b/src/network/tc/gred.c @@ -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; diff --git a/src/network/tc/hhf.c b/src/network/tc/hhf.c index d44522f98cc..9ddb7ef9063 100644 --- a/src/network/tc/hhf.c +++ b/src/network/tc/hhf.c @@ -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; diff --git a/src/network/tc/htb.c b/src/network/tc/htb.c index eb2c8cfff4c..8f1faa1dc5d 100644 --- a/src/network/tc/htb.c +++ b/src/network/tc/htb.c @@ -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; diff --git a/src/network/tc/netem.c b/src/network/tc/netem.c index 6a63221c3ac..51039de1f4e 100644 --- a/src/network/tc/netem.c +++ b/src/network/tc/netem.c @@ -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; diff --git a/src/network/tc/pie.c b/src/network/tc/pie.c index c9b171baf11..c482f19787a 100644 --- a/src/network/tc/pie.c +++ b/src/network/tc/pie.c @@ -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; diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c index 38dee2c0015..d372481d628 100644 --- a/src/network/tc/qdisc.c +++ b/src/network/tc/qdisc.c @@ -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; diff --git a/src/network/tc/qdisc.h b/src/network/tc/qdisc.h index cbba1bef711..3989ad76515 100644 --- a/src/network/tc/qdisc.h +++ b/src/network/tc/qdisc.h @@ -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); diff --git a/src/network/tc/sfb.c b/src/network/tc/sfb.c index 861c5fe2a0c..07fac6700f6 100644 --- a/src/network/tc/sfb.c +++ b/src/network/tc/sfb.c @@ -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; diff --git a/src/network/tc/sfq.c b/src/network/tc/sfq.c index 92dbae1166a..78778653439 100644 --- a/src/network/tc/sfq.c +++ b/src/network/tc/sfq.c @@ -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; diff --git a/src/network/tc/tbf.c b/src/network/tc/tbf.c index 647fc8cb1eb..3e7a3098dab 100644 --- a/src/network/tc/tbf.c +++ b/src/network/tc/tbf.c @@ -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; diff --git a/src/network/tc/teql.c b/src/network/tc/teql.c index dcb149dbe2a..f4fa331f523 100644 --- a/src/network/tc/teql.c +++ b/src/network/tc/teql.c @@ -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;