diff options
-rw-r--r-- | libmount/docs/libmount-sections.txt | 2 | ||||
-rw-r--r-- | libmount/src/cache.c | 41 | ||||
-rw-r--r-- | libmount/src/context.c | 36 | ||||
-rw-r--r-- | libmount/src/libmount.h.in | 3 | ||||
-rw-r--r-- | libmount/src/libmount.sym | 2 | ||||
-rw-r--r-- | libmount/src/tab.c | 16 |
6 files changed, 70 insertions, 30 deletions
diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt index 97e0851e5..3ebc4aaf2 100644 --- a/libmount/docs/libmount-sections.txt +++ b/libmount/docs/libmount-sections.txt @@ -3,6 +3,8 @@ libmnt_cache mnt_new_cache mnt_free_cache +mnt_ref_cache +mnt_unref_cache mnt_cache_device_has_tag mnt_cache_find_tag_value mnt_cache_read_tags diff --git a/libmount/src/cache.c b/libmount/src/cache.c index ef1a64107..cf5c6d430 100644 --- a/libmount/src/cache.c +++ b/libmount/src/cache.c @@ -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; } @@ -89,6 +91,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,6 +105,38 @@ void mnt_free_cache(struct libmnt_cache *cache) free(cache); } +/** + * 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) @@ -620,7 +655,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; } @@ -643,7 +678,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; } @@ -695,7 +730,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; } diff --git a/libmount/src/context.c b/libmount/src/context.c index ea13f0d1e..5d5e8fba8 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -91,8 +91,8 @@ void mnt_free_context(struct libmnt_context *cxt) if (!(cxt->flags & MNT_FL_EXTERN_FSTAB)) mnt_free_table(cxt->fstab); - if (!(cxt->flags & MNT_FL_EXTERN_CACHE)) - mnt_free_cache(cxt->cache); + + mnt_unref_cache(cxt->cache); mnt_context_clear_loopdev(cxt); mnt_free_lock(cxt->lock); @@ -925,8 +925,6 @@ int mnt_context_set_fstab(struct libmnt_context *cxt, struct libmnt_table *tb) */ int mnt_context_get_fstab(struct libmnt_context *cxt, struct libmnt_table **tb) { - struct libmnt_cache *cache; - assert(cxt); if (!cxt) return -EINVAL; @@ -944,11 +942,9 @@ int mnt_context_get_fstab(struct libmnt_context *cxt, struct libmnt_table **tb) return rc; } - cache = mnt_context_get_cache(cxt); - /* never touch an external fstab */ if (!(cxt->flags & MNT_FL_EXTERN_FSTAB)) - mnt_table_set_cache(cxt->fstab, cache); + mnt_table_set_cache(cxt->fstab, mnt_context_get_cache(cxt)); if (tb) *tb = cxt->fstab; @@ -967,8 +963,6 @@ int mnt_context_get_fstab(struct libmnt_context *cxt, struct libmnt_table **tb) */ int mnt_context_get_mtab(struct libmnt_context *cxt, struct libmnt_table **tb) { - struct libmnt_cache *cache; - assert(cxt); if (!cxt) return -EINVAL; @@ -991,8 +985,7 @@ int mnt_context_get_mtab(struct libmnt_context *cxt, struct libmnt_table **tb) return rc; } - cache = mnt_context_get_cache(cxt); - mnt_table_set_cache(cxt->mtab, cache); + mnt_table_set_cache(cxt->mtab, mnt_context_get_cache(cxt)); if (tb) *tb = cxt->mtab; @@ -1048,7 +1041,6 @@ int mnt_context_set_tabfilter(struct libmnt_context *cxt, int mnt_context_get_table(struct libmnt_context *cxt, const char *filename, struct libmnt_table **tb) { - struct libmnt_cache *cache; int rc; assert(cxt); @@ -1069,10 +1061,7 @@ int mnt_context_get_table(struct libmnt_context *cxt, return rc; } - cache = mnt_context_get_cache(cxt); - if (cache) - mnt_table_set_cache(*tb, cache); - + mnt_table_set_cache(*tb, mnt_context_get_cache(cxt)); return 0; } @@ -1106,23 +1095,25 @@ int mnt_context_set_tables_errcb(struct libmnt_context *cxt, * @cxt: mount context * @cache: cache instance or nULL * - * The mount context maintains a private struct libmnt_cache by default. This function - * allows to overwrite the private cache with an external instance. Note that - * the external instance is not deallocated by mnt_free_context(). + * The mount context maintains a private struct libmnt_cache by default. This + * function allows to overwrite the private cache with an external instance. + * This function increments cache reference counter. * * If the @cache argument is NULL, then the current private cache instance is * reset. * + * The old cache instance reference counter is de-incremented. + * * Returns: 0 on success, negative number in case of error. */ int mnt_context_set_cache(struct libmnt_context *cxt, struct libmnt_cache *cache) { if (!cxt) return -EINVAL; - if (!(cxt->flags & MNT_FL_EXTERN_CACHE)) - mnt_free_cache(cxt->cache); - set_flag(cxt, MNT_FL_EXTERN_CACHE, cache != NULL); + mnt_ref_cache(cache); /* new */ + mnt_unref_cache(cxt->cache); /* old */ + cxt->cache = cache; return 0; } @@ -1145,7 +1136,6 @@ struct libmnt_cache *mnt_context_get_cache(struct libmnt_context *cxt) cxt->cache = mnt_new_cache(); if (!cxt->cache) return NULL; - cxt->flags &= ~MNT_FL_EXTERN_CACHE; } return cxt->cache; } diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in index 29659628d..f4efd9804 100644 --- a/libmount/src/libmount.h.in +++ b/libmount/src/libmount.h.in @@ -216,6 +216,9 @@ extern struct libmnt_cache *mnt_new_cache(void) __ul_attribute__((warn_unused_result)); extern void mnt_free_cache(struct libmnt_cache *cache); +extern void mnt_ref_cache(struct libmnt_cache *cache); +extern void mnt_unref_cache(struct libmnt_cache *cache); + extern int mnt_cache_read_tags(struct libmnt_cache *cache, const char *devname); extern int mnt_cache_device_has_tag(struct libmnt_cache *cache, diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym index 621821e97..5a7e0def3 100644 --- a/libmount/src/libmount.sym +++ b/libmount/src/libmount.sym @@ -265,6 +265,7 @@ global: mnt_fs_append_comment; mnt_fs_get_comment; mnt_fs_set_comment; + mnt_ref_cache; mnt_ref_fs; mnt_table_append_intro_comment; mnt_table_append_trailing_comment; @@ -281,5 +282,6 @@ global: mnt_table_set_userdata; mnt_table_with_comments; mnt_table_write_file; + mnt_unref_cache; mnt_unref_fs; } MOUNT_2.23; diff --git a/libmount/src/tab.c b/libmount/src/tab.c index 58edf2f42..a2ad604f7 100644 --- a/libmount/src/tab.c +++ b/libmount/src/tab.c @@ -109,6 +109,7 @@ void mnt_free_table(struct libmnt_table *tb) return; mnt_reset_table(tb); + mnt_unref_cache(tb->cache); DBG(TAB, mnt_debug_h(tb, "free")); free(tb->comm_intro); @@ -338,6 +339,10 @@ int mnt_table_append_trailing_comment(struct libmnt_table *tb, const char *comm) * same cache between more threads -- currently the cache does not provide any * locking method. * + * This function increments cache refrence counter. It's recomented to use + * mnt_unref_cache() after mnt_table_set_cache() if you want to keep the cache + * referenced by @tb only. + * * See also mnt_new_cache(). * * Returns: 0 on success or negative number in case of error. @@ -347,6 +352,9 @@ int mnt_table_set_cache(struct libmnt_table *tb, struct libmnt_cache *mpc) assert(tb); if (!tb) return -EINVAL; + + mnt_ref_cache(mpc); /* new */ + mnt_unref_cache(tb->cache); /* old */ tb->cache = mpc; return 0; } @@ -1456,6 +1464,7 @@ int test_find(struct libmnt_test *ts, int argc, char *argv[], int dr) if (!mpc) goto done; mnt_table_set_cache(tb, mpc); + mnt_unref_cache(mpc); if (strcasecmp(find, "source") == 0) fs = mnt_table_find_source(tb, what, dr); @@ -1470,7 +1479,6 @@ int test_find(struct libmnt_test *ts, int argc, char *argv[], int dr) } done: mnt_free_table(tb); - mnt_free_cache(mpc); return rc; } @@ -1498,6 +1506,7 @@ int test_find_pair(struct libmnt_test *ts, int argc, char *argv[]) if (!mpc) goto done; mnt_table_set_cache(tb, mpc); + mnt_unref_cache(mpc); fs = mnt_table_find_pair(tb, argv[2], argv[3], MNT_ITER_FORWARD); if (!fs) @@ -1507,7 +1516,6 @@ int test_find_pair(struct libmnt_test *ts, int argc, char *argv[]) rc = 0; done: mnt_free_table(tb); - mnt_free_cache(mpc); return rc; } @@ -1525,6 +1533,7 @@ int test_find_mountpoint(struct libmnt_test *ts, int argc, char *argv[]) if (!mpc) goto done; mnt_table_set_cache(tb, mpc); + mnt_unref_cache(mpc); fs = mnt_table_find_mountpoint(tb, argv[1], MNT_ITER_BACKWARD); if (!fs) @@ -1534,7 +1543,6 @@ int test_find_mountpoint(struct libmnt_test *ts, int argc, char *argv[]) rc = 0; done: mnt_free_table(tb); - mnt_free_cache(mpc); return rc; } @@ -1564,6 +1572,7 @@ static int test_is_mounted(struct libmnt_test *ts, int argc, char *argv[]) if (!mpc) goto done; mnt_table_set_cache(tb, mpc); + mnt_unref_cache(mpc); while(mnt_table_next_fs(fstab, itr, &fs) == 0) { if (mnt_table_is_fs_mounted(tb, fs)) @@ -1580,7 +1589,6 @@ static int test_is_mounted(struct libmnt_test *ts, int argc, char *argv[]) done: mnt_free_table(tb); mnt_free_table(fstab); - mnt_free_cache(mpc); mnt_free_iter(itr); return rc; } |