#include <class_hash.h>
+static void
+lh_read_lock(lustre_hash_t *lh)
+{
+ if ((lh->lh_flags & LH_REHASH) != 0)
+ read_lock(&lh->lh_rwlock);
+}
+
+static void
+lh_read_unlock(lustre_hash_t *lh)
+{
+ if ((lh->lh_flags & LH_REHASH) != 0)
+ read_unlock(&lh->lh_rwlock);
+}
+
+static void
+lh_write_lock(lustre_hash_t *lh)
+{
+ if ((lh->lh_flags & LH_REHASH) != 0)
+ write_lock(&lh->lh_rwlock);
+}
+
+static void
+lh_write_unlock(lustre_hash_t *lh)
+{
+ if ((lh->lh_flags & LH_REHASH) != 0)
+ write_unlock(&lh->lh_rwlock);
+}
+
/**
* Initialize new lustre hash, where:
* \param name Descriptive hash name
LASSERT(max_bits >= cur_bits);
LASSERT(max_bits < 31);
- OBD_ALLOC_PTR(lh);
+ LIBCFS_ALLOC(lh, sizeof(*lh));
if (!lh)
RETURN(NULL);
lh->lh_max_theta = 1 << (LH_THETA_BITS + 1);
lh->lh_ops = ops;
lh->lh_flags = flags;
+ if (cur_bits != max_bits && (lh->lh_flags & LH_REHASH) == 0)
+ CWARN("Rehash is disabled, ignore max_bits %d\n", max_bits);
/* theta * 1000 */
__lustre_hash_set_theta(lh, 500, 2000);
- OBD_VMALLOC(lh->lh_buckets, sizeof(*lh->lh_buckets) << lh->lh_cur_bits);
- if (!lh->lh_buckets) {
- OBD_FREE_PTR(lh);
+ LIBCFS_ALLOC(lh->lh_buckets, sizeof(*lh->lh_buckets) << lh->lh_cur_bits);
+ if (lh->lh_buckets == NULL) {
+ LIBCFS_FREE(lh, sizeof(*lh));
RETURN(NULL);
}
for (i = 0; i <= lh->lh_cur_mask; i++) {
- INIT_HLIST_HEAD(&lh->lh_buckets[i].lhb_head);
- rwlock_init(&lh->lh_buckets[i].lhb_rwlock);
- atomic_set(&lh->lh_buckets[i].lhb_count, 0);
+ LIBCFS_ALLOC(lh->lh_buckets[i], sizeof(lustre_hash_bucket_t));
+ if (lh->lh_buckets[i] == NULL) {
+ lustre_hash_exit(lh);
+ return NULL;
+ }
+
+ INIT_HLIST_HEAD(&lh->lh_buckets[i]->lhb_head);
+ rwlock_init(&lh->lh_buckets[i]->lhb_rwlock);
+ atomic_set(&lh->lh_buckets[i]->lhb_count, 0);
}
return lh;
LASSERT(lh != NULL);
- write_lock(&lh->lh_rwlock);
+ lh_write_lock(lh);
lh_for_each_bucket(lh, lhb, i) {
+ if (lhb == NULL)
+ continue;
+
write_lock(&lhb->lhb_rwlock);
hlist_for_each_safe(hnode, pos, &(lhb->lhb_head)) {
__lustre_hash_bucket_validate(lh, lhb, hnode);
LASSERT(hlist_empty(&(lhb->lhb_head)));
LASSERT(atomic_read(&lhb->lhb_count) == 0);
write_unlock(&lhb->lhb_rwlock);
+ LIBCFS_FREE(lhb, sizeof(*lhb));
}
LASSERT(atomic_read(&lh->lh_count) == 0);
- write_unlock(&lh->lh_rwlock);
+ lh_write_unlock(lh);
- OBD_VFREE(lh->lh_buckets, sizeof(*lh->lh_buckets) << lh->lh_cur_bits);
- OBD_FREE_PTR(lh);
+ LIBCFS_FREE(lh->lh_buckets, sizeof(*lh->lh_buckets) << lh->lh_cur_bits);
+ LIBCFS_FREE(lh, sizeof(*lh));
EXIT;
}
EXPORT_SYMBOL(lustre_hash_exit);
__lustre_hash_key_validate(lh, key, hnode);
- read_lock(&lh->lh_rwlock);
+ lh_read_lock(lh);
i = lh_hash(lh, key, lh->lh_cur_mask);
- lhb = &lh->lh_buckets[i];
+ lhb = lh->lh_buckets[i];
LASSERT(i <= lh->lh_cur_mask);
LASSERT(hlist_unhashed(hnode));
write_unlock(&lhb->lhb_rwlock);
bits = lustre_hash_rehash_bits(lh);
- read_unlock(&lh->lh_rwlock);
+ lh_read_unlock(lh);
if (bits)
lustre_hash_rehash(lh, bits);
__lustre_hash_key_validate(lh, key, hnode);
- read_lock(&lh->lh_rwlock);
+ lh_read_lock(lh);
i = lh_hash(lh, key, lh->lh_cur_mask);
- lhb = &lh->lh_buckets[i];
+ lhb = lh->lh_buckets[i];
LASSERT(i <= lh->lh_cur_mask);
LASSERT(hlist_unhashed(hnode));
bits = lustre_hash_rehash_bits(lh);
}
write_unlock(&lhb->lhb_rwlock);
- read_unlock(&lh->lh_rwlock);
+ lh_read_unlock(lh);
if (bits)
lustre_hash_rehash(lh, bits);
__lustre_hash_key_validate(lh, key, hnode);
- read_lock(&lh->lh_rwlock);
+ lh_read_lock(lh);
i = lh_hash(lh, key, lh->lh_cur_mask);
- lhb = &lh->lh_buckets[i];
+ lhb = lh->lh_buckets[i];
LASSERT(i <= lh->lh_cur_mask);
LASSERT(!hlist_unhashed(hnode));
write_lock(&lhb->lhb_rwlock);
obj = __lustre_hash_bucket_del(lh, lhb, hnode);
write_unlock(&lhb->lhb_rwlock);
- read_unlock(&lh->lh_rwlock);
+ lh_read_unlock(lh);
RETURN(obj);
}
void *obj = NULL;
ENTRY;
- read_lock(&lh->lh_rwlock);
+ lh_read_lock(lh);
i = lh_hash(lh, key, lh->lh_cur_mask);
- lhb = &lh->lh_buckets[i];
+ lhb = lh->lh_buckets[i];
LASSERT(i <= lh->lh_cur_mask);
write_lock(&lhb->lhb_rwlock);
obj = __lustre_hash_bucket_del(lh, lhb, hnode);
write_unlock(&lhb->lhb_rwlock);
- read_unlock(&lh->lh_rwlock);
+ lh_read_unlock(lh);
RETURN(obj);
}
void *obj = NULL;
ENTRY;
- read_lock(&lh->lh_rwlock);
+ lh_read_lock(lh);
i = lh_hash(lh, key, lh->lh_cur_mask);
- lhb = &lh->lh_buckets[i];
+ lhb = lh->lh_buckets[i];
LASSERT(i <= lh->lh_cur_mask);
read_lock(&lhb->lhb_rwlock);
obj = lh_get(lh, hnode);
read_unlock(&lhb->lhb_rwlock);
- read_unlock(&lh->lh_rwlock);
+ lh_read_unlock(lh);
RETURN(obj);
}
int i;
ENTRY;
- read_lock(&lh->lh_rwlock);
+ lh_read_lock(lh);
lh_for_each_bucket(lh, lhb, i) {
read_lock(&lhb->lhb_rwlock);
hlist_for_each(hnode, &(lhb->lhb_head)) {
}
read_unlock(&lhb->lhb_rwlock);
}
- read_unlock(&lh->lh_rwlock);
+ lh_read_unlock(lh);
EXIT;
}
int i;
ENTRY;
- read_lock(&lh->lh_rwlock);
+ lh_read_lock(lh);
lh_for_each_bucket(lh, lhb, i) {
read_lock(&lhb->lhb_rwlock);
hlist_for_each_safe(hnode, pos, &(lhb->lhb_head)) {
}
read_unlock(&lhb->lhb_rwlock);
}
- read_unlock(&lh->lh_rwlock);
+ lh_read_unlock(lh);
EXIT;
}
EXPORT_SYMBOL(lustre_hash_for_each_safe);
ENTRY;
restart:
- read_lock(&lh->lh_rwlock);
+ lh_read_lock(lh);
lh_for_each_bucket(lh, lhb, i) {
write_lock(&lhb->lhb_rwlock);
while (!hlist_empty(&lhb->lhb_head)) {
__lustre_hash_bucket_validate(lh, lhb, hnode);
obj = lh_get(lh, hnode);
write_unlock(&lhb->lhb_rwlock);
- read_unlock(&lh->lh_rwlock);
+ lh_read_unlock(lh);
func(obj, data);
(void)lh_put(lh, hnode);
goto restart;
}
write_unlock(&lhb->lhb_rwlock);
}
- read_unlock(&lh->lh_rwlock);
+ lh_read_unlock(lh);
EXIT;
}
EXPORT_SYMBOL(lustre_hash_for_each_empty);
unsigned i;
ENTRY;
- read_lock(&lh->lh_rwlock);
+ lh_read_lock(lh);
i = lh_hash(lh, key, lh->lh_cur_mask);
- lhb = &lh->lh_buckets[i];
+ lhb = lh->lh_buckets[i];
LASSERT(i <= lh->lh_cur_mask);
read_lock(&lhb->lhb_rwlock);
}
read_unlock(&lhb->lhb_rwlock);
- read_unlock(&lh->lh_rwlock);
+ lh_read_unlock(lh);
EXIT;
}
{
struct hlist_node *hnode;
struct hlist_node *pos;
- lustre_hash_bucket_t *lh_buckets;
- lustre_hash_bucket_t *rehash_buckets;
+ lustre_hash_bucket_t **lh_buckets;
+ lustre_hash_bucket_t **rehash_buckets;
lustre_hash_bucket_t *lh_lhb;
lustre_hash_bucket_t *rehash_lhb;
int i;
int lh_mask;
int lh_bits;
int mask = (1 << bits) - 1;
+ int rc = 0;
void *key;
ENTRY;
LASSERT(!in_interrupt());
LASSERT(mask > 0);
+ LASSERT((lh->lh_flags & LH_REHASH) != 0);
- OBD_VMALLOC(rehash_buckets, sizeof(*rehash_buckets) << bits);
+ LIBCFS_ALLOC(rehash_buckets, sizeof(*rehash_buckets) << bits);
if (!rehash_buckets)
RETURN(-ENOMEM);
for (i = 0; i <= mask; i++) {
- INIT_HLIST_HEAD(&rehash_buckets[i].lhb_head);
- rwlock_init(&rehash_buckets[i].lhb_rwlock);
- atomic_set(&rehash_buckets[i].lhb_count, 0);
+ LIBCFS_ALLOC(rehash_buckets[i], sizeof(*rehash_buckets[i]));
+ if (rehash_buckets[i] == NULL)
+ GOTO(free, rc = -ENOMEM);
+
+ INIT_HLIST_HEAD(&rehash_buckets[i]->lhb_head);
+ rwlock_init(&rehash_buckets[i]->lhb_rwlock);
+ atomic_set(&rehash_buckets[i]->lhb_count, 0);
}
- write_lock(&lh->lh_rwlock);
+ lh_write_lock(lh);
/*
* Early return for multiple concurrent racing callers,
*/
theta = __lustre_hash_theta(lh);
if ((theta >= lh->lh_min_theta) && (theta <= lh->lh_max_theta)) {
- OBD_VFREE(rehash_buckets, sizeof(*rehash_buckets) << bits);
- write_unlock(&lh->lh_rwlock);
- RETURN(-EALREADY);
+ lh_write_unlock(lh);
+ GOTO(free, rc = -EALREADY);
}
lh_bits = lh->lh_cur_bits;
atomic_inc(&lh->lh_rehash_count);
for (i = 0; i <= lh_mask; i++) {
- lh_lhb = &lh_buckets[i];
+ lh_lhb = lh_buckets[i];
write_lock(&lh_lhb->lhb_rwlock);
hlist_for_each_safe(hnode, pos, &(lh_lhb->lhb_head)) {
/*
* Add to rehash bucket, ops->lh_key must be defined.
*/
- rehash_lhb = &rehash_buckets[lh_hash(lh, key, mask)];
+ rehash_lhb = rehash_buckets[lh_hash(lh, key, mask)];
hlist_add_head(hnode, &(rehash_lhb->lhb_head));
atomic_inc(&rehash_lhb->lhb_count);
}
write_unlock(&lh_lhb->lhb_rwlock);
}
- OBD_VFREE(lh_buckets, sizeof(*lh_buckets) << lh_bits);
- write_unlock(&lh->lh_rwlock);
-
- RETURN(0);
+ lh_write_unlock(lh);
+ rehash_buckets = lh_buckets;
+ i = (1 << lh_bits) - 1;
+ bits = lh_bits;
+ free:
+ while (i-- > 0)
+ LIBCFS_FREE(rehash_buckets[i], sizeof(*rehash_buckets[i]));
+ LIBCFS_FREE(rehash_buckets, sizeof(*rehash_buckets) << bits);
+ RETURN(rc);
}
EXPORT_SYMBOL(lustre_hash_rehash);
__lustre_hash_key_validate(lh, new_key, hnode);
LASSERT(!hlist_unhashed(hnode));
- read_lock(&lh->lh_rwlock);
+ lh_read_lock(lh);
i = lh_hash(lh, old_key, lh->lh_cur_mask);
- old_lhb = &lh->lh_buckets[i];
+ old_lhb = lh->lh_buckets[i];
LASSERT(i <= lh->lh_cur_mask);
j = lh_hash(lh, new_key, lh->lh_cur_mask);
- new_lhb = &lh->lh_buckets[j];
+ new_lhb = lh->lh_buckets[j];
LASSERT(j <= lh->lh_cur_mask);
if (i < j) { /* write_lock ordering */
write_unlock(&new_lhb->lhb_rwlock);
write_unlock(&old_lhb->lhb_rwlock);
- read_unlock(&lh->lh_rwlock);
+ lh_read_unlock(lh);
EXIT;
}
if (str == NULL || size == 0)
return 0;
- read_lock(&lh->lh_rwlock);
+ lh_read_lock(lh);
theta = __lustre_hash_theta(lh);
c += snprintf(str + c, size - c, "%-*s ",
c += snprintf(str + c, size - c, "%d%c", dist[i],
(i == 7) ? '\n' : '/');
- read_unlock(&lh->lh_rwlock);
+ lh_read_unlock(lh);
return c;
}