networkd: introduce refcounting for Links and NetDevs

This commit is contained in:
Tom Gundersen 2014-05-08 18:54:26 +02:00
parent 68a8723c85
commit 14b746f721
4 changed files with 49 additions and 13 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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 */