#include "bcachefs.h"
#include "buckets_waiting_for_journal.h"
+#include <linux/hash.h>
#include <linux/random.h>
-#include <linux/siphash.h>
static inline struct bucket_hashed *
bucket_hash(struct buckets_waiting_for_journal_table *t,
unsigned hash_seed_idx, u64 dev_bucket)
{
- unsigned h = siphash_1u64(dev_bucket, &t->hash_seeds[hash_seed_idx]);
-
- EBUG_ON(!is_power_of_2(t->size));
-
- return t->d + (h & (t->size - 1));
+ return t->d + hash_64(dev_bucket ^ t->hash_seeds[hash_seed_idx], t->bits);
}
-static void bucket_table_init(struct buckets_waiting_for_journal_table *t, size_t size)
+static void bucket_table_init(struct buckets_waiting_for_journal_table *t, size_t bits)
{
unsigned i;
- t->size = size;
+ t->bits = bits;
for (i = 0; i < ARRAY_SIZE(t->hash_seeds); i++)
get_random_bytes(&t->hash_seeds[i], sizeof(t->hash_seeds[i]));
- memset(t->d, 0, sizeof(t->d[0]) * size);
+ memset(t->d, 0, sizeof(t->d[0]) << t->bits);
}
bool bch2_bucket_needs_journal_commit(struct buckets_waiting_for_journal *b,
.dev_bucket = (u64) dev << 56 | bucket,
.journal_seq = journal_seq,
};
- size_t i, new_size, nr_elements = 1, nr_rehashes = 0;
+ size_t i, size, new_bits, nr_elements = 1, nr_rehashes = 0;
int ret = 0;
mutex_lock(&b->lock);
goto out;
t = b->t;
- for (i = 0; i < t->size; i++)
+ size = 1UL << t->bits;
+ for (i = 0; i < size; i++)
nr_elements += t->d[i].journal_seq > flushed_seq;
- new_size = nr_elements < t->size / 3 ? t->size : t->size * 2;
+ new_bits = t->bits + (nr_elements * 3 > size);
- n = kvmalloc(sizeof(*n) + sizeof(n->d[0]) * new_size, GFP_KERNEL);
+ n = kvmalloc(sizeof(*n) + (sizeof(n->d[0]) << new_bits), GFP_KERNEL);
if (!n) {
- ret = -ENOMEM;
+ ret = -BCH_ERR_ENOMEM_buckets_waiting_for_journal_set;
goto out;
}
retry_rehash:
nr_rehashes++;
- bucket_table_init(n, new_size);
+ bucket_table_init(n, new_bits);
tmp = new;
BUG_ON(!bucket_table_insert(n, &tmp, flushed_seq));
- for (i = 0; i < t->size; i++) {
+ for (i = 0; i < 1UL << t->bits; i++) {
if (t->d[i].journal_seq <= flushed_seq)
continue;
kvfree(t);
pr_debug("took %zu rehashes, table at %zu/%zu elements",
- nr_rehashes, nr_elements, b->t->size);
+ nr_rehashes, nr_elements, 1UL << b->t->bits);
out:
mutex_unlock(&b->lock);
kvfree(b->t);
}
-#define INITIAL_TABLE_SIZE 8
+#define INITIAL_TABLE_BITS 3
int bch2_fs_buckets_waiting_for_journal_init(struct bch_fs *c)
{
mutex_init(&b->lock);
- b->t = kvmalloc(sizeof(*b->t) + sizeof(b->t->d[0]) * INITIAL_TABLE_SIZE, GFP_KERNEL);
+ b->t = kvmalloc(sizeof(*b->t) +
+ (sizeof(b->t->d[0]) << INITIAL_TABLE_BITS), GFP_KERNEL);
if (!b->t)
- return -ENOMEM;
+ return -BCH_ERR_ENOMEM_buckets_waiting_for_journal_init;
- bucket_table_init(b->t, INITIAL_TABLE_SIZE);
+ bucket_table_init(b->t, INITIAL_TABLE_BITS);
return 0;
}