static NL_LIST_HEAD(info_ops);
+/* lock protecting info_ops and af_ops */
+static NL_RW_LOCK(info_lock);
+
static struct rtnl_link_info_ops *__rtnl_link_info_ops_lookup(const char *name)
{
struct rtnl_link_info_ops *ops;
{
struct rtnl_link_info_ops *ops;
+ nl_write_lock(&info_lock);
if ((ops = __rtnl_link_info_ops_lookup(name)))
ops->io_refcnt++;
+ nl_write_unlock(&info_lock);
return ops;
}
*/
int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
{
+ int err = 0;
+
if (ops->io_name == NULL)
return -NLE_INVAL;
- if (__rtnl_link_info_ops_lookup(ops->io_name))
- return -NLE_EXIST;
+ nl_write_lock(&info_lock);
+ if (__rtnl_link_info_ops_lookup(ops->io_name)) {
+ err = -NLE_EXIST;
+ goto errout;
+ }
NL_DBG(1, "Registered link info operations %s\n", ops->io_name);
nl_list_add_tail(&ops->io_list, &info_ops);
+errout:
+ nl_write_unlock(&info_lock);
- return 0;
+ return err;
}
/**
int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
{
struct rtnl_link_info_ops *t;
+ int err = -NLE_OPNOTSUPP;
+
+ nl_write_lock(&info_lock);
nl_list_for_each_entry(t, &info_ops, io_list) {
if (t == ops) {
- if (t->io_refcnt > 0)
- return -NLE_BUSY;
+ if (t->io_refcnt > 0) {
+ err = -NLE_BUSY;
+ goto errout;
+ }
nl_list_del(&t->io_list);
NL_DBG(1, "Unregistered link info operations %s\n",
ops->io_name);
-
- return 0;
+ err = 0;
+ goto errout;
}
}
- return -NLE_OPNOTSUPP;
+errout:
+ nl_write_unlock(&info_lock);
+
+ return err;
}
/** @} */
if (family == AF_UNSPEC || family >= AF_MAX)
return NULL;
+ nl_write_lock(&info_lock);
if (af_ops[family])
af_ops[family]->ao_refcnt++;
+ nl_write_unlock(&info_lock);
return af_ops[family];
}
*/
int rtnl_link_af_register(struct rtnl_link_af_ops *ops)
{
+ int err = 0;
+
if (ops->ao_family == AF_UNSPEC || ops->ao_family >= AF_MAX)
return -NLE_INVAL;
- if (af_ops[ops->ao_family])
- return -NLE_EXIST;
+ nl_write_lock(&info_lock);
+ if (af_ops[ops->ao_family]) {
+ err = -NLE_EXIST;
+ goto errout;
+ }
ops->ao_refcnt = 0;
af_ops[ops->ao_family] = ops;
NL_DBG(1, "Registered link address family operations %u\n",
ops->ao_family);
- return 0;
+errout:
+ nl_write_unlock(&info_lock);
+
+ return err;
}
/**
*/
int rtnl_link_af_unregister(struct rtnl_link_af_ops *ops)
{
+ int err = -NLE_INVAL;
+
if (!ops)
- return -NLE_INVAL;
+ goto errout;
- if (!af_ops[ops->ao_family])
- return -NLE_OBJ_NOTFOUND;
+ nl_write_lock(&info_lock);
+ if (!af_ops[ops->ao_family]) {
+ err = -NLE_OBJ_NOTFOUND;
+ goto errout;
+ }
- if (ops->ao_refcnt > 0)
- return -NLE_BUSY;
+ if (ops->ao_refcnt > 0) {
+ err = -NLE_BUSY;
+ goto errout;
+ }
af_ops[ops->ao_family] = NULL;
NL_DBG(1, "Unregistered link address family operations %u\n",
ops->ao_family);
- return 0;
+errout:
+ nl_write_lock(&info_lock);
+
+ return err;
}
/** @} */