summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2012-11-16 00:19:38 +0100
committerThomas Graf <tgraf@suug.ch>2012-11-16 00:19:38 +0100
commit2b3912a320ef74b31d84380d91ec036dbf1b9f52 (patch)
tree1177e19ba0d6b6f8c8b92cab0c2c49ce654f028a
parent1a2c3e36a8aa6b3a0a568f587669c7c8d5ddac28 (diff)
downloadlibnl-2b3912a320ef74b31d84380d91ec036dbf1b9f52.tar.gz
cache: Provide safe versions of nl_cache_ops_associate() and nl_cache_ops_lookup()
Signed-off-by: Thomas Graf <tgraf@suug.ch>
-rw-r--r--include/netlink/cache.h2
-rw-r--r--lib/cache_mngt.c94
2 files changed, 78 insertions, 18 deletions
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,39 +88,92 @@ 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
* @arg msgtype netlink message type
@@ -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)