From: Tom Gundersen Date: Thu, 8 May 2014 16:54:26 +0000 (+0200) Subject: networkd: introduce refcounting for Links and NetDevs X-Git-Tag: v213~212 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=14b746f72132324e637c4e39694bd474f85e19f7 networkd: introduce refcounting for Links and NetDevs --- diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 74860196a..525fe1442 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -37,7 +37,7 @@ static int ipv4ll_address_update(Link *link, bool deprecate); static bool ipv4ll_is_bound(sd_ipv4ll *ll); static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) { - _cleanup_link_free_ Link *link = NULL; + _cleanup_link_unref_ Link *link = NULL; uint16_t type; char *ifname; int r, ifindex; @@ -67,6 +67,7 @@ static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) { if (!link) return -ENOMEM; + link->n_ref = 1; link->manager = manager; link->state = LINK_STATE_INITIALIZING; link->ifindex = ifindex; @@ -94,7 +95,7 @@ static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) { return 0; } -void link_free(Link *link) { +static void link_free(Link *link) { if (!link) return; @@ -120,6 +121,20 @@ void link_free(Link *link) { free(link); } +Link *link_unref(Link *link) { + if (link && (-- link->n_ref <= 0)) + link_free(link); + + return NULL; +} + +Link *link_ref(Link *link) { + if (link) + assert_se(++ link->n_ref >= 2); + + return link; +} + int link_get(Manager *m, int ifindex, Link **ret) { Link *link; uint64_t ifindex_64; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 4b2955333..71c54254e 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -151,14 +151,14 @@ void manager_free(Manager *m) { sd_event_unref(m->event); while ((link = hashmap_first(m->links))) - link_free(link); + link_unref(link); hashmap_free(m->links); while ((network = m->networks)) network_free(network); while ((netdev = hashmap_first(m->netdevs))) - netdev_free(netdev); + netdev_unref(netdev); hashmap_free(m->netdevs); sd_rtnl_unref(m->rtnl); diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index a8a629bd1..961404295 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -48,7 +48,7 @@ static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = { DEFINE_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode); DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode, "Failed to parse macvlan mode"); -void netdev_free(NetDev *netdev) { +static void netdev_free(NetDev *netdev) { netdev_enslave_callback *callback; if (!netdev) @@ -75,6 +75,20 @@ void netdev_free(NetDev *netdev) { free(netdev); } +NetDev *netdev_unref(NetDev *netdev) { + if (netdev && (-- netdev->n_ref <= 0)) + netdev_free(netdev); + + return NULL; +} + +NetDev *netdev_ref(NetDev *netdev) { + if (netdev) + assert_se(++ netdev->n_ref >= 2); + + return netdev; +} + int netdev_get(Manager *manager, const char *name, NetDev **ret) { NetDev *netdev; @@ -413,7 +427,7 @@ int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) { } static int netdev_load_one(Manager *manager, const char *filename) { - _cleanup_netdev_free_ NetDev *netdev = NULL; + _cleanup_netdev_unref_ NetDev *netdev = NULL; _cleanup_fclose_ FILE *file = NULL; int r; @@ -437,6 +451,7 @@ static int netdev_load_one(Manager *manager, const char *filename) { if (!netdev) return log_oom(); + netdev->n_ref = 1; netdev->manager = manager; netdev->state = _NETDEV_STATE_INVALID; netdev->kind = _NETDEV_KIND_INVALID; @@ -517,7 +532,7 @@ int netdev_load(Manager *manager) { assert(manager); while ((netdev = hashmap_first(manager->netdevs))) - netdev_free(netdev); + netdev_unref(netdev); r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs); if (r < 0) { diff --git a/src/network/networkd.h b/src/network/networkd.h index 57eecf4db..b2794bad2 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -83,6 +83,8 @@ typedef enum NetDevState { struct NetDev { Manager *manager; + int n_ref; + char *filename; Condition *match_host; @@ -199,6 +201,8 @@ typedef enum LinkState { struct Link { Manager *manager; + int n_ref; + uint64_t ifindex; char *ifname; char *state_file; @@ -268,10 +272,11 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); int netdev_load(Manager *manager); -void netdev_free(NetDev *netdev); +NetDev *netdev_unref(NetDev *netdev); +NetDev *netdev_ref(NetDev *netdev); -DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_free); -#define _cleanup_netdev_free_ _cleanup_(netdev_freep) +DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref); +#define _cleanup_netdev_unref_ _cleanup_(netdev_unrefp) int netdev_get(Manager *manager, const char *name, NetDev **ret); int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *newlink); @@ -371,7 +376,8 @@ int config_parse_label(const char *unit, const char *filename, unsigned line, /* Link */ -void link_free(Link *link); +Link *link_unref(Link *link); +Link *link_ref(Link *link); int link_get(Manager *m, int ifindex, Link **ret); int link_add(Manager *manager, sd_rtnl_message *message, Link **ret); @@ -386,8 +392,8 @@ bool link_has_carrier(unsigned flags, uint8_t operstate); const char* link_state_to_string(LinkState s) _const_; LinkState link_state_from_string(const char *s) _pure_; -DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); -#define _cleanup_link_free_ _cleanup_(link_freep) +DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); +#define _cleanup_link_unref_ _cleanup_(link_unrefp) /* Macros which append INTERFACE= to the message */