summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2012-11-16 00:27:51 +0100
committerThomas Graf <tgraf@suug.ch>2012-11-16 00:29:58 +0100
commit235aa7ff17e12ca7a76dcfd77abfe143c2ce4dea (patch)
treea9bb6b47292db0ff3c24cda3a2f9d3b5d4ee0f41
parentcb82c2a5451a52e7365957a2325258af1b179aee (diff)
downloadlibnl-235aa7ff17e12ca7a76dcfd77abfe143c2ce4dea.tar.gz
cache: hold a reference to the cache ops while a cache is provided over it
Signed-off-by: Thomas Graf <tgraf@suug.ch>
-rw-r--r--lib/cache_mngt.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c
index d5ca6d3..8f011fb 100644
--- a/lib/cache_mngt.c
+++ b/lib/cache_mngt.c
@@ -335,6 +335,14 @@ void nl_cache_mngt_provide(struct nl_cache *cache)
BUG();
else {
nl_cache_get(cache);
+
+ /*
+ * Hold a reference to the cache operations to ensure the
+ * ops don't go away while we use it to store the cache pointer.
+ */
+ if (!ops->co_major_cache)
+ nl_cache_ops_get(ops);
+
ops->co_major_cache = cache;
}
@@ -360,6 +368,7 @@ void nl_cache_mngt_unprovide(struct nl_cache *cache)
BUG();
else if (ops->co_major_cache == cache) {
nl_cache_free(ops->co_major_cache);
+ nl_cache_ops_put(ops);
ops->co_major_cache = NULL;
}
@@ -369,12 +378,15 @@ void nl_cache_mngt_unprovide(struct nl_cache *cache)
struct nl_cache *__nl_cache_mngt_require(const char *name)
{
struct nl_cache_ops *ops;
+ struct nl_cache *cache = NULL;
- ops = nl_cache_ops_lookup(name);
- if (ops)
- return ops->co_major_cache;
+ ops = nl_cache_ops_lookup_safe(name);
+ if (ops) {
+ cache = ops->co_major_cache;
+ nl_cache_ops_put(ops);
+ }
- return NULL;
+ return cache;
}
/**