No functional change, just refactoring and preparation for later change.
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);
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;
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;
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;
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;
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;
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;
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);
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;
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;
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);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
[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) {
return -ENOMEM;
*qdisc = (QDisc) {
+ .n_ref = 1,
.parent = TC_H_ROOT,
.kind = kind,
};
if (!qdisc)
return -ENOMEM;
+ qdisc->n_ref = 1;
qdisc->parent = TC_H_ROOT;
qdisc->kind = kind;
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;
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;
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);
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;
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)
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);
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;
if (qdisc->state == 0) {
log_qdisc_debug(qdisc, link, "Forgetting");
- qdisc_free(qdisc);
+ qdisc_detach(qdisc);
} else
log_qdisc_debug(qdisc, link, "Removed");
}
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;
}
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;
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) {
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(
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;
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;
NetworkConfigSource source;
NetworkConfigState state;
+ unsigned n_ref;
+
uint32_t handle;
uint32_t parent;
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);
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);
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;
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;
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;
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;
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;
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;