summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-07-21 13:30:34 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-07-21 13:30:34 +0200
commit321290241e84a3a2cfc30b65fc6e79ecd266e420 (patch)
tree1a12686dd3ea7afe0d6e6d93fac3440d2c70bd8d
parent1bb19e4e6980019d0e4ac348f99d9d2cf0074d6b (diff)
Keep track of xattr key & value references AFTER deduplication
This commit adds a reference count functionality to the string table implementation and uses this functionality in the fstree code to count how often each key and value is referenced by the deduplicated Xattr blocks. This is needed to support deduplication through out-of-band storage of xattrs. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--include/str_table.h7
-rw-r--r--lib/fstree/xattr.c17
-rw-r--r--lib/util/str_table.c46
3 files changed, 68 insertions, 2 deletions
diff --git a/include/str_table.h b/include/str_table.h
index db36c5b..56b601a 100644
--- a/include/str_table.h
+++ b/include/str_table.h
@@ -6,6 +6,7 @@ typedef struct str_bucket_t {
struct str_bucket_t *next;
char *str;
size_t index;
+ size_t refcount;
} str_bucket_t;
/* Stores strings in a hash table and assigns an incremental, unique ID to
@@ -34,4 +35,10 @@ int str_table_get_index(str_table_t *table, const char *str, size_t *idx);
Returns NULL if the ID is unknown, i.e. out of bounds. */
const char *str_table_get_string(str_table_t *table, size_t index);
+void str_table_reset_ref_count(str_table_t *table);
+
+void str_table_add_ref(str_table_t *table, size_t index);
+
+size_t str_table_get_ref_count(str_table_t *table, size_t index);
+
#endif /* STR_TABLE_H */
diff --git a/lib/fstree/xattr.c b/lib/fstree/xattr.c
index 38f7703..4597d9d 100644
--- a/lib/fstree/xattr.c
+++ b/lib/fstree/xattr.c
@@ -102,11 +102,24 @@ static int cmp_u64(const void *lhs, const void *rhs)
void fstree_xattr_reindex(fstree_t *fs)
{
+ uint32_t key_idx, value_idx;
+ size_t i, index = 0;
tree_xattr_t *it;
- size_t index = 0;
- for (it = fs->xattr; it != NULL; it = it->next)
+ str_table_reset_ref_count(&fs->xattr_keys);
+ str_table_reset_ref_count(&fs->xattr_values);
+
+ for (it = fs->xattr; it != NULL; it = it->next) {
it->index = index++;
+
+ for (i = 0; i < it->num_attr; ++i) {
+ key_idx = (it->ref[i] >> 32) & 0x00000000FFFFFFFF;
+ value_idx = it->ref[i] & 0x00000000FFFFFFFF;
+
+ str_table_add_ref(&fs->xattr_keys, key_idx);
+ str_table_add_ref(&fs->xattr_values, value_idx);
+ }
+ }
}
void fstree_xattr_deduplicate(fstree_t *fs)
diff --git a/lib/util/str_table.c b/lib/util/str_table.c
index a9d91e5..72579ce 100644
--- a/lib/util/str_table.c
+++ b/lib/util/str_table.c
@@ -128,3 +128,49 @@ const char *str_table_get_string(str_table_t *table, size_t index)
return table->strings[index];
}
+
+static str_bucket_t *bucket_by_index(str_table_t *table, size_t index)
+{
+ str_bucket_t *bucket = NULL;
+ uint32_t hash;
+
+ if (index < table->num_strings) {
+ hash = strhash(table->strings[index]);
+ bucket = table->buckets[hash % table->num_buckets];
+
+ while (bucket != NULL && bucket->index != index)
+ bucket = bucket->next;
+ }
+
+ return bucket;
+}
+
+void str_table_reset_ref_count(str_table_t *table)
+{
+ str_bucket_t *bucket;
+ size_t i;
+
+ for (i = 0; i < table->num_buckets; ++i) {
+ bucket = table->buckets[i];
+
+ while (bucket != NULL) {
+ bucket->refcount = 0;
+ bucket = bucket->next;
+ }
+ }
+}
+
+void str_table_add_ref(str_table_t *table, size_t index)
+{
+ str_bucket_t *bucket = bucket_by_index(table, index);
+
+ if (bucket != NULL && bucket->refcount < ~((size_t)0))
+ bucket->refcount += 1;
+}
+
+size_t str_table_get_ref_count(str_table_t *table, size_t index)
+{
+ str_bucket_t *bucket = bucket_by_index(table, index);
+
+ return bucket != NULL ? bucket->refcount : 0;
+}