summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2014-05-08 18:54:26 +0200
committerTom Gundersen <teg@jklm.no>2014-05-09 14:41:27 +0200
commit14b746f72132324e637c4e39694bd474f85e19f7 (patch)
tree7a99b9d37b073cb5d42bb1769c8639bae47fdc2b /src
parent68a8723c8592c06b2c978f391cb47db266d9d6de (diff)
networkd: introduce refcounting for Links and NetDevs
Diffstat (limited to 'src')
-rw-r--r--src/network/networkd-link.c19
-rw-r--r--src/network/networkd-manager.c4
-rw-r--r--src/network/networkd-netdev.c21
-rw-r--r--src/network/networkd.h18
4 files changed, 49 insertions, 13 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 74860196a5..525fe1442f 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 4b29553330..71c54254e3 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 a8a629bd1f..961404295d 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 57eecf4db3..b2794bad2d 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 */