link/api: Convert link info ops to use nl_list_head

rtnl_link_info_ops_lookup() now returns a pointer with refcnt increment,
you must return it using rtnl_link_info_ops_put()
This commit is contained in:
Thomas Graf 2010-11-11 16:18:53 +01:00
parent 800013b787
commit 67aeb7474f
3 changed files with 73 additions and 21 deletions

View file

@ -60,11 +60,11 @@ struct rtnl_link_info_ops
* in either io_alloc() or io_parse(). */
void (*io_free)(struct rtnl_link *);
struct rtnl_link_info_ops * io_next;
struct nl_list_head io_list;
};
extern struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *);
extern void rtnl_link_info_ops_put(struct rtnl_link_info_ops *);
extern int rtnl_link_register_info(struct rtnl_link_info_ops *);
extern int rtnl_link_unregister_info(struct rtnl_link_info_ops *);

View file

@ -266,8 +266,8 @@ static void release_link_info(struct rtnl_link *link)
struct rtnl_link_info_ops *io = link->l_info_ops;
if (io != NULL) {
io->io_refcnt--;
io->io_free(link);
rtnl_link_info_ops_put(io);
link->l_info_ops = NULL;
}
}
@ -562,7 +562,6 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
kind = nla_get_string(li[IFLA_INFO_KIND]);
ops = rtnl_link_info_ops_lookup(kind);
if (ops != NULL) {
ops->io_refcnt++;
link->l_info_ops = ops;
err = ops->io_parse(link, li[IFLA_INFO_DATA],
li[IFLA_INFO_XSTATS]);

View file

@ -45,53 +45,106 @@
#include <netlink/route/link.h>
#include <netlink/route/link/api.h>
static struct rtnl_link_info_ops *info_ops;
static NL_LIST_HEAD(info_ops);
struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *name)
static struct rtnl_link_info_ops *__rtnl_link_info_ops_lookup(const char *name)
{
struct rtnl_link_info_ops *ops;
for (ops = info_ops; ops; ops = ops->io_next)
nl_list_for_each_entry(ops, &info_ops, io_list)
if (!strcmp(ops->io_name, name))
return ops;
return NULL;
}
/**
* Return operations of a specific link info type
* @arg name Name of link info type.
*
* @note The returned pointer must be given back using rtnl_link_info_ops_put()
*
* @return Pointer to operations or NULL if unavailable.
*/
struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *name)
{
struct rtnl_link_info_ops *ops;
if ((ops = __rtnl_link_info_ops_lookup(name)))
ops->io_refcnt++;
return ops;
}
/**
* Give back reference to a set of operations.
* @arg ops Link info operations.
*/
void rtnl_link_info_ops_put(struct rtnl_link_info_ops *ops)
{
if (ops)
ops->io_refcnt--;
}
/**
* Register operations for a link info type
* @arg ops Link info operations
*
* This function must be called by modules implementing a specific link
* info type. It will make the operations implemented by the module
* available for everyone else.
*
* @return 0 on success or a negative error code.
* @return -NLE_INVAL Link info name not specified.
* @return -NLE_EXIST Operations for address family already registered.
*/
int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
{
if (ops->io_name == NULL)
return -NLE_INVAL;
if (rtnl_link_info_ops_lookup(ops->io_name))
if (__rtnl_link_info_ops_lookup(ops->io_name))
return -NLE_EXIST;
NL_DBG(1, "Registered link info operations %s\n", ops->io_name);
ops->io_next = info_ops;
info_ops = ops;
nl_list_add_tail(&ops->io_list, &info_ops);
return 0;
}
/**
* Unregister operations for a link info type
* @arg ops Link info operations
*
* This function must be called if a module implementing a specific link
* info type is unloaded or becomes unavailable. It must provide a
* set of operations which have previously been registered using
* rtnl_link_register_info().
*
* @return 0 on success or a negative error code
* @return _NLE_OPNOTSUPP Link info operations not registered.
* @return -NLE_BUSY Link info operations still in use.
*/
int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
{
struct rtnl_link_info_ops *t, **tp;
struct rtnl_link_info_ops *t;
for (tp = &info_ops; (t=*tp) != NULL; tp = &t->io_next)
if (t == ops)
break;
nl_list_for_each_entry(t, &info_ops, io_list) {
if (t == ops) {
if (t->io_refcnt > 0)
return -NLE_BUSY;
if (!t)
return -NLE_OPNOTSUPP;
nl_list_del(&t->io_list);
if (t->io_refcnt > 0)
return -NLE_BUSY;
NL_DBG(1, "Unregistered link info operations %s\n",
ops->io_name);
NL_DBG(1, "Unregistered link info perations %s\n", ops->io_name);
return 0;
}
}
*tp = t->io_next;
return 0;
return -NLE_OPNOTSUPP;
}
static struct rtnl_link_af_ops *af_ops[AF_MAX];