summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2012-11-15 23:48:03 +0100
committerThomas Graf <tgraf@suug.ch>2012-11-16 00:17:50 +0100
commit1a2c3e36a8aa6b3a0a568f587669c7c8d5ddac28 (patch)
tree5cf589f50c5ec64924fd9a5d1399190c651a6d1d
parent74926f92dd3a65e378def1a3e7309a027b8efbd3 (diff)
downloadlibnl-1a2c3e36a8aa6b3a0a568f587669c7c8d5ddac28.tar.gz
cache: Add reference counter to cache operations
Signed-off-by: Thomas Graf <tgraf@suug.ch>
-rw-r--r--include/netlink/cache-api.h6
-rw-r--r--lib/cache_mngt.c32
2 files changed, 35 insertions, 3 deletions
diff --git a/include/netlink/cache-api.h b/include/netlink/cache-api.h
index dd42671..f2111b9 100644
--- a/include/netlink/cache-api.h
+++ b/include/netlink/cache-api.h
@@ -192,6 +192,9 @@ struct nl_cache_ops
/** cache flags */
unsigned int co_flags;
+ /** Reference counter */
+ unsigned int co_refcnt;
+
/** Group definition */
struct nl_af_group * co_groups;
@@ -262,6 +265,9 @@ struct nl_cache_ops
struct nl_msgtype co_msgtypes[];
};
+extern void nl_cache_ops_get(struct nl_cache_ops *);
+extern void nl_cache_ops_put(struct nl_cache_ops *);
+
/** @} */
#ifdef __cplusplus
diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c
index 65c4707..d0dfcdd 100644
--- a/lib/cache_mngt.c
+++ b/lib/cache_mngt.c
@@ -50,6 +50,24 @@ struct nl_cache_ops *__nl_cache_ops_lookup(const char *name)
}
/**
+ * Increment reference counter
+ * @arg ops Cache operations
+ */
+void nl_cache_ops_get(struct nl_cache_ops *ops)
+{
+ ops->co_refcnt++;
+}
+
+/**
+ * Decrement reference counter
+ * @arg ops Cache operations
+ */
+void nl_cache_ops_put(struct nl_cache_ops *ops)
+{
+ ops->co_refcnt--;
+}
+
+/**
* Lookup the set cache operations of a certain cache type
* @arg name name of the cache type
*
@@ -182,6 +200,7 @@ int nl_cache_mngt_register(struct nl_cache_ops *ops)
return -NLE_EXIST;
}
+ ops->co_refcnt = 0;
ops->co_next = cache_ops;
cache_ops = ops;
nl_write_unlock(&cache_ops_lock);
@@ -205,24 +224,31 @@ int nl_cache_mngt_register(struct nl_cache_ops *ops)
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
{
struct nl_cache_ops *t, **tp;
+ int err = 0;
nl_write_lock(&cache_ops_lock);
+ if (ops->co_refcnt > 0) {
+ err = -NLE_BUSY;
+ goto errout;
+ }
+
for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next)
if (t == ops)
break;
if (!t) {
- nl_write_unlock(&cache_ops_lock);
- return -NLE_NOCACHE;
+ err = -NLE_NOCACHE;
+ goto errout;
}
NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name);
*tp = t->co_next;
+errout:
nl_write_unlock(&cache_ops_lock);
- return 0;
+ return err;
}
/** @} */