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:
parent
800013b787
commit
67aeb7474f
3 changed files with 73 additions and 21 deletions
|
@ -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 *);
|
||||
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Add table
Reference in a new issue