]> git.ipfire.org Git - thirdparty/libnl.git/commitdiff
link/api: Convert link info ops to use nl_list_head
authorThomas Graf <tgraf@suug.ch>
Thu, 11 Nov 2010 15:18:53 +0000 (16:18 +0100)
committerThomas Graf <tgraf@suug.ch>
Thu, 11 Nov 2010 15:18:53 +0000 (16:18 +0100)
rtnl_link_info_ops_lookup() now returns a pointer with refcnt increment,
you must return it using rtnl_link_info_ops_put()

include/netlink/route/link/api.h
lib/route/link.c
lib/route/link/api.c

index ae5af5925d441e841c4afb6b61925d8487d2e3cf..42c00d93ebc5bccebf81750e3bd7625e05b7facf 100644 (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 *);
 
index 2082d6ed4d5fd7fd11ee1bb0771ecc2b71a0e6b0..7aed7083d0652b3711467e4d17b0f2ecc0da6c62 100644 (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]);
index 9e14e4b0448a9234d375fb4ddcdc785051cdc339..1830fe3759c66e2320fd4317fb522000a01225c1 100644 (file)
 #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];