From: Thomas Graf <tgraf@suug.ch>
Date: Thu, 15 Nov 2012 23:19:38 +0000 (+0100)
Subject: cache: Provide safe versions of nl_cache_ops_associate() and nl_cache_ops_lookup()
X-Git-Tag: libnl3_2_15~10
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2b3912a320ef74b31d84380d91ec036dbf1b9f52;p=libnl

cache: Provide safe versions of nl_cache_ops_associate() and nl_cache_ops_lookup()

Signed-off-by: Thomas Graf <tgraf@suug.ch>
---

diff --git a/include/netlink/cache.h b/include/netlink/cache.h
index 0bd4037..f193c76 100644
--- a/include/netlink/cache.h
+++ b/include/netlink/cache.h
@@ -106,7 +106,9 @@ extern void			nl_cache_foreach_filter(struct nl_cache *,
 
 /* Cache type management */
 extern struct nl_cache_ops *	nl_cache_ops_lookup(const char *);
+extern struct nl_cache_ops *	nl_cache_ops_lookup_safe(const char *);
 extern struct nl_cache_ops *	nl_cache_ops_associate(int, int);
+extern struct nl_cache_ops *	nl_cache_ops_associate_safe(int, int);
 extern struct nl_msgtype *	nl_msgtype_lookup(struct nl_cache_ops *, int);
 extern void			nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *);
 extern int			nl_cache_mngt_register(struct nl_cache_ops *);
diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c
index d0dfcdd..d5ca6d3 100644
--- a/lib/cache_mngt.c
+++ b/lib/cache_mngt.c
@@ -68,11 +68,13 @@ void nl_cache_ops_put(struct nl_cache_ops *ops)
 }
 
 /**
- * Lookup the set cache operations of a certain cache type
+ * Lookup cache operations by name
  * @arg name		name of the cache type
  *
- * @return The cache operations or NULL if no operations
- *         have been registered under the specified name.
+ * @attention This function is not safe, it does not increment the reference
+ *            counter. Please use nl_cache_ops_lookup_safe().
+ *
+ * @return The cache operations or NULL if not found.
  */
 struct nl_cache_ops *nl_cache_ops_lookup(const char *name)
 {
@@ -86,38 +88,91 @@ struct nl_cache_ops *nl_cache_ops_lookup(const char *name)
 }
 
 /**
- * Associate a message type to a set of cache operations
- * @arg protocol		netlink protocol
- * @arg msgtype			netlink message type
+ * Lookup cache operations by name
+ * @arg name		name of the cache type
  *
- * Associates the specified netlink message type with
- * a registered set of cache operations.
+ * @note The reference counter of the returned cache operation is incremented
+ *       and must be decremented after use with nl_cache_ops_put().
  *
- * @return The cache operations or NULL if no association
- *         could be made.
+ * @return The cache operations or NULL if not found.
  */
-struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype)
+struct nl_cache_ops *nl_cache_ops_lookup_safe(const char *name)
+{
+	struct nl_cache_ops *ops;
+
+	nl_write_lock(&cache_ops_lock);
+	if ((ops = __nl_cache_ops_lookup(name)))
+		nl_cache_ops_get(ops);
+	nl_write_unlock(&cache_ops_lock);
+
+	return ops;
+}
+
+static struct nl_cache_ops *__cache_ops_associate(int protocol, int msgtype)
 {
 	int i;
 	struct nl_cache_ops *ops;
 
-	nl_read_lock(&cache_ops_lock);
 	for (ops = cache_ops; ops; ops = ops->co_next) {
 		if (ops->co_protocol != protocol)
 			continue;
 
-		for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) {
-			if (ops->co_msgtypes[i].mt_id == msgtype) {
-				nl_read_unlock(&cache_ops_lock);
+		for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
+			if (ops->co_msgtypes[i].mt_id == msgtype)
 				return ops;
-			}
-		}
 	}
-	nl_read_unlock(&cache_ops_lock);
 
 	return NULL;
 }
 
+/**
+ * Associate protocol and message type to cache operations
+ * @arg protocol		netlink protocol
+ * @arg msgtype			netlink message type
+ *
+ * @attention This function is not safe, it does not increment the reference
+ *            counter. Please use nl_cache_ops_associate_safe().
+ *
+ * @see nl_cache_ops_associate_safe()
+ *
+ * @return The cache operations or NULL if no match found.
+ */
+struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype)
+{
+	struct nl_cache_ops *ops;
+
+	nl_read_lock(&cache_ops_lock);
+	ops = __cache_ops_associate(protocol, msgtype);
+	nl_read_unlock(&cache_ops_lock);
+
+	return ops;
+}
+
+/**
+ * Associate protocol and message type to cache operations
+ * @arg protocol		netlink protocol
+ * @arg msgtype			netlink message type
+ *
+ * Searches the registered cache operations for a matching protocol
+ * and message type.
+ *
+ * @note The reference counter of the returned cache operation is incremented
+ *       and must be decremented after use with nl_cache_ops_put().
+ *
+ * @return The cache operations or NULL if no no match was found.
+ */
+struct nl_cache_ops *nl_cache_ops_associate_safe(int protocol, int msgtype)
+{
+	struct nl_cache_ops *ops;
+
+	nl_write_lock(&cache_ops_lock);
+	if ((ops = __cache_ops_associate(protocol, msgtype)))
+		nl_cache_ops_get(ops);
+	nl_write_unlock(&cache_ops_lock);
+
+	return ops;
+}
+
 /**
  * Lookup message type cache association
  * @arg ops			cache operations
@@ -126,6 +181,9 @@ struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype)
  * Searches for a matching message type association ing the specified
  * cache operations.
  *
+ * @attention The guranteed lifetime of the returned message type is bound
+ *            to the lifetime of the underlying cache operations.
+ *
  * @return A message type association or NULL.
  */
 struct nl_msgtype *nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype)