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 bool ipv4ll_is_bound(sd_ipv4ll *ll);
static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) { 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; uint16_t type;
char *ifname; char *ifname;
int r, ifindex; int r, ifindex;
@ -67,6 +67,7 @@ static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) {
if (!link) if (!link)
return -ENOMEM; return -ENOMEM;
link->n_ref = 1;
link->manager = manager; link->manager = manager;
link->state = LINK_STATE_INITIALIZING; link->state = LINK_STATE_INITIALIZING;
link->ifindex = ifindex; link->ifindex = ifindex;
@ -94,7 +95,7 @@ static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) {
return 0; return 0;
} }
void link_free(Link *link) { static void link_free(Link *link) {
if (!link) if (!link)
return; return;
@ -120,6 +121,20 @@ void link_free(Link *link) {
free(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) { int link_get(Manager *m, int ifindex, Link **ret) {
Link *link; Link *link;
uint64_t ifindex_64; uint64_t ifindex_64;

View file

@ -151,14 +151,14 @@ void manager_free(Manager *m) {
sd_event_unref(m->event); sd_event_unref(m->event);
while ((link = hashmap_first(m->links))) while ((link = hashmap_first(m->links)))
link_free(link); link_unref(link);
hashmap_free(m->links); hashmap_free(m->links);
while ((network = m->networks)) while ((network = m->networks))
network_free(network); network_free(network);
while ((netdev = hashmap_first(m->netdevs))) while ((netdev = hashmap_first(m->netdevs)))
netdev_free(netdev); netdev_unref(netdev);
hashmap_free(m->netdevs); hashmap_free(m->netdevs);
sd_rtnl_unref(m->rtnl); 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_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode);
DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode, "Failed to parse macvlan mode"); 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; netdev_enslave_callback *callback;
if (!netdev) if (!netdev)
@ -75,6 +75,20 @@ void netdev_free(NetDev *netdev) {
free(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) { int netdev_get(Manager *manager, const char *name, NetDev **ret) {
NetDev *netdev; 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) { 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; _cleanup_fclose_ FILE *file = NULL;
int r; int r;
@ -437,6 +451,7 @@ static int netdev_load_one(Manager *manager, const char *filename) {
if (!netdev) if (!netdev)
return log_oom(); return log_oom();
netdev->n_ref = 1;
netdev->manager = manager; netdev->manager = manager;
netdev->state = _NETDEV_STATE_INVALID; netdev->state = _NETDEV_STATE_INVALID;
netdev->kind = _NETDEV_KIND_INVALID; netdev->kind = _NETDEV_KIND_INVALID;
@ -517,7 +532,7 @@ int netdev_load(Manager *manager) {
assert(manager); assert(manager);
while ((netdev = hashmap_first(manager->netdevs))) while ((netdev = hashmap_first(manager->netdevs)))
netdev_free(netdev); netdev_unref(netdev);
r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs); r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs);
if (r < 0) { if (r < 0) {

View file

@ -83,6 +83,8 @@ typedef enum NetDevState {
struct NetDev { struct NetDev {
Manager *manager; Manager *manager;
int n_ref;
char *filename; char *filename;
Condition *match_host; Condition *match_host;
@ -199,6 +201,8 @@ typedef enum LinkState {
struct Link { struct Link {
Manager *manager; Manager *manager;
int n_ref;
uint64_t ifindex; uint64_t ifindex;
char *ifname; char *ifname;
char *state_file; char *state_file;
@ -268,10 +272,11 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
int netdev_load(Manager *manager); 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_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref);
#define _cleanup_netdev_free_ _cleanup_(netdev_freep) #define _cleanup_netdev_unref_ _cleanup_(netdev_unrefp)
int netdev_get(Manager *manager, const char *name, NetDev **ret); int netdev_get(Manager *manager, const char *name, NetDev **ret);
int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *newlink); 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 */ /* 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_get(Manager *m, int ifindex, Link **ret);
int link_add(Manager *manager, sd_rtnl_message *message, 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_; const char* link_state_to_string(LinkState s) _const_;
LinkState link_state_from_string(const char *s) _pure_; LinkState link_state_from_string(const char *s) _pure_;
DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref);
#define _cleanup_link_free_ _cleanup_(link_freep) #define _cleanup_link_unref_ _cleanup_(link_unrefp)
/* Macros which append INTERFACE= to the message */ /* Macros which append INTERFACE= to the message */