summaryrefslogtreecommitdiff
path: root/libmount/src/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmount/src/cache.c')
-rw-r--r--libmount/src/cache.c89
1 files changed, 60 insertions, 29 deletions
diff --git a/libmount/src/cache.c b/libmount/src/cache.c
index 7b651228a..92f469456 100644
--- a/libmount/src/cache.c
+++ b/libmount/src/cache.c
@@ -10,7 +10,7 @@
* @title: Cache
* @short_description: paths and tags (UUID/LABEL) caching
*
- * The cache is a very simple API for work with tags (LABEL, UUID, ...) and
+ * The cache is a very simple API for working with tags (LABEL, UUID, ...) and
* paths. The cache uses libblkid as a backend for TAGs resolution.
*
* All returned paths are always canonicalized.
@@ -48,6 +48,7 @@ struct libmnt_cache {
struct mnt_cache_entry *ents;
size_t nents;
size_t nallocs;
+ int refcount;
/* blkid_evaluate_tag() works in two ways:
*
@@ -72,6 +73,7 @@ struct libmnt_cache *mnt_new_cache(void)
if (!cache)
return NULL;
DBG(CACHE, mnt_debug_h(cache, "alloc"));
+ cache->refcount = 1;
return cache;
}
@@ -79,7 +81,8 @@ struct libmnt_cache *mnt_new_cache(void)
* mnt_free_cache:
* @cache: pointer to struct libmnt_cache instance
*
- * Deallocates the cache.
+ * Deallocates the cache. This function does not care about reference count. Don't
+ * use this function directly -- it's better to use use mnt_unref_cache().
*/
void mnt_free_cache(struct libmnt_cache *cache)
{
@@ -89,6 +92,7 @@ void mnt_free_cache(struct libmnt_cache *cache)
return;
DBG(CACHE, mnt_debug_h(cache, "free"));
+ WARN_REFCOUNT(CACHE, cache, cache->refcount);
for (i = 0; i < cache->nents; i++) {
struct mnt_cache_entry *e = &cache->ents[i];
@@ -102,7 +106,39 @@ void mnt_free_cache(struct libmnt_cache *cache)
free(cache);
}
-/* note that the @key could be tha same pointer as @value */
+/**
+ * mnt_ref_cache:
+ * @cache: cache pointer
+ *
+ * Increments reference counter.
+ */
+void mnt_ref_cache(struct libmnt_cache *cache)
+{
+ if (cache) {
+ cache->refcount++;
+ /*DBG(CACHE, mnt_debug_h(cache, "ref=%d", cache->refcount));*/
+ }
+}
+
+/**
+ * mnt_unref_cache:
+ * @cache: cache pointer
+ *
+ * De-increments reference counter, on zero the cache is automatically
+ * deallocated by mnt_free_cache().
+ */
+void mnt_unref_cache(struct libmnt_cache *cache)
+{
+ if (cache) {
+ cache->refcount--;
+ /*DBG(CACHE, mnt_debug_h(cache, "unref=%d", cache->refcount));*/
+ if (cache->refcount <= 0)
+ mnt_free_cache(cache);
+ }
+}
+
+
+/* note that the @key could be the same pointer as @value */
static int cache_add_entry(struct libmnt_cache *cache, char *key,
char *value, int flag)
{
@@ -135,7 +171,7 @@ static int cache_add_entry(struct libmnt_cache *cache, char *key,
return 0;
}
-/* add tag to the cache, @devname has to be allocated string */
+/* add tag to the cache, @devname has to be an allocated string */
static int cache_add_tag(struct libmnt_cache *cache, const char *tagname,
const char *tagval, char *devname, int flag)
{
@@ -270,13 +306,13 @@ int mnt_cache_read_tags(struct libmnt_cache *cache, const char *devname)
DBG(CACHE, mnt_debug_h(cache, "tags for %s requested", devname));
- /* check is device is already cached */
+ /* check if device is already cached */
for (i = 0; i < cache->nents; i++) {
struct mnt_cache_entry *e = &cache->ents[i];
if (!(e->flag & MNT_CACHE_TAGREAD))
continue;
if (strcmp(e->value, devname) == 0)
- /* tags has been already read */
+ /* tags have already been read */
return 0;
}
@@ -335,7 +371,7 @@ error:
* @token: tag name (e.g "LABEL")
* @value: tag value
*
- * Look up @cache to check it @tag+@value are associated with @devname.
+ * Look up @cache to check if @tag+@value are associated with @devname.
*
* Returns: 1 on success or 0.
*/
@@ -421,7 +457,7 @@ char *mnt_get_fstype(const char *devname, int *ambi, struct libmnt_cache *cache)
rc = blkid_do_safeprobe(pr);
- DBG(CACHE, mnt_debug_h(cache, "liblkid rc=%d", rc));
+ DBG(CACHE, mnt_debug_h(cache, "libblkid rc=%d", rc));
if (!rc && !blkid_probe_lookup_value(pr, "TYPE", &data, NULL))
type = strdup(data);
@@ -493,7 +529,7 @@ error:
* - /dev/loopN to the loop backing filename
* - empty path (NULL) to 'none'
*
- * Returns: new allocated string with path, result has to be always deallocated
+ * Returns: newly allocated string with path, result always has to be deallocated
* by free().
*/
char *mnt_pretty_path(const char *path, struct libmnt_cache *cache)
@@ -583,22 +619,18 @@ error:
char *mnt_resolve_spec(const char *spec, struct libmnt_cache *cache)
{
char *cn = NULL;
+ char *t = NULL, *v = NULL;
if (!spec)
return NULL;
- if (strchr(spec, '=')) {
- char *tag, *val;
-
- if (!blkid_parse_tag_string(spec, &tag, &val)) {
- cn = mnt_resolve_tag(tag, val, cache);
-
- free(tag);
- free(val);
- }
- } else
+ if (blkid_parse_tag_string(spec, &t, &v) == 0 && mnt_valid_tagname(t))
+ cn = mnt_resolve_tag(t, v, cache);
+ else
cn = mnt_resolve_path(spec, cache);
+ free(t);
+ free(v);
return cn;
}
@@ -624,7 +656,7 @@ int test_resolve_path(struct libmnt_test *ts, int argc, char *argv[])
p = mnt_resolve_path(line, cache);
printf("%s : %s\n", line, p);
}
- mnt_free_cache(cache);
+ mnt_unref_cache(cache);
return 0;
}
@@ -647,7 +679,7 @@ int test_resolve_spec(struct libmnt_test *ts, int argc, char *argv[])
p = mnt_resolve_spec(line, cache);
printf("%s : %s\n", line, p);
}
- mnt_free_cache(cache);
+ mnt_unref_cache(cache);
return 0;
}
@@ -663,6 +695,7 @@ int test_read_tags(struct libmnt_test *ts, int argc, char *argv[])
while(fgets(line, sizeof(line), stdin)) {
size_t sz = strlen(line);
+ char *t = NULL, *v = NULL;
if (sz > 0 && line[sz - 1] == '\n')
line[sz - 1] = '\0';
@@ -674,16 +707,14 @@ int test_read_tags(struct libmnt_test *ts, int argc, char *argv[])
if (mnt_cache_read_tags(cache, line) < 0)
fprintf(stderr, "%s: read tags failed\n", line);
- } else if (strchr(line, '=')) {
- char *tag, *val;
+ } else if (blkid_parse_tag_string(line, &t, &v) == 0) {
const char *cn = NULL;
- if (!blkid_parse_tag_string(line, &tag, &val)) {
- cn = cache_find_tag(cache, tag, val);
+ if (mnt_valid_tagname(t))
+ cn = cache_find_tag(cache, t, v);
+ free(t);
+ free(v);
- free(tag);
- free(val);
- }
if (cn)
printf("%s: %s\n", line, cn);
else
@@ -700,7 +731,7 @@ int test_read_tags(struct libmnt_test *ts, int argc, char *argv[])
e->key + strlen(e->key) + 1);
}
- mnt_free_cache(cache);
+ mnt_unref_cache(cache);
return 0;
}