* GPL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/
/*
struct cfs_hash_bucket **hs_buckets; /* hash buckets */
struct cfs_hash_ops *hs_ops; /* hash operations */
cfs_rwlock_t hs_rwlock; /* cfs_hash */
+ cfs_atomic_t hs_refcount;
char hs_name[CFS_MAX_HASH_NAME];
} cfs_hash_t;
#define CFS_HASH_DEBUG 0x0001 /* Enable expensive debug checks */
#define CFS_HASH_REHASH 0x0002 /* Enable dynamic hash resizing */
-#define CFS_HO(hs) (hs)->hs_ops
#define CFS_HOP(hs, op) (hs)->hs_ops->hs_ ## op
static inline unsigned
cfs_hash_id(cfs_hash_t *hs, void *key, unsigned mask)
{
- LASSERT(hs);
- LASSERT(CFS_HO(hs));
- LASSERT(CFS_HOP(hs, hash));
-
return CFS_HOP(hs, hash)(hs, key, mask);
}
static inline void *
cfs_hash_key(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
{
- LASSERT(hs);
- LASSERT(hnode);
- LASSERT(CFS_HO(hs));
- LASSERT(CFS_HOP(hs, key));
-
return CFS_HOP(hs, key)(hnode);
}
-/* Returns 1 on a match,
- * XXX: This would be better if it returned, -1, 0, or 1 for
- * <, =, > respectivly. It could then be used to implement
- * a CFS_HASH_SORT feature flags which could keep each hash
- * bucket in order. This would increase insertion times
- * but could reduce lookup times for deep chains. Ideally,
- * the rehash should keep chain depth short but if that
- * ends up not being the case this would be a nice feature.
- */
+/* Returns TRUE on a match. */
static inline int
cfs_hash_compare(cfs_hash_t *hs, void *key, cfs_hlist_node_t *hnode)
{
- LASSERT(hs);
- LASSERT(hnode);
- LASSERT(CFS_HO(hs));
-
- if (CFS_HOP(hs, compare))
- return CFS_HOP(hs, compare)(key, hnode);
-
- return -EOPNOTSUPP;
+ return CFS_HOP(hs, compare)(key, hnode);
}
static inline void *
cfs_hash_get(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
{
- LASSERT(hs);
- LASSERT(hnode);
- LASSERT(CFS_HO(hs));
-
- if (CFS_HOP(hs, get))
- return CFS_HOP(hs, get)(hnode);
-
- return NULL;
+ return CFS_HOP(hs, get)(hnode);
}
static inline void *
cfs_hash_put(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
{
- LASSERT(hs);
- LASSERT(hnode);
- LASSERT(CFS_HO(hs));
-
- if (CFS_HOP(hs, put))
- return CFS_HOP(hs, put)(hnode);
-
- return NULL;
+ return CFS_HOP(hs, put)(hnode);
}
static inline void
cfs_hash_exit(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
{
- LASSERT(hs);
- LASSERT(hnode);
- LASSERT(CFS_HO(hs));
-
- if (CFS_HOP(hs, exit))
+ /* This is allowed to be a NOOP */
+ if (CFS_HOP(hs, exit) != NULL)
return CFS_HOP(hs, exit)(hnode);
}
cfs_hlist_node_t *hnode)
{
if (unlikely(hs->hs_flags & CFS_HASH_DEBUG))
- LASSERT(cfs_hash_compare(hs, key, hnode) > 0);
+ LASSERT(cfs_hash_compare(hs, key, hnode));
}
/* Validate hnode is in the correct bucket */
cfs_hlist_node_t *hnode;
cfs_hlist_for_each(hnode, &hsb->hsb_head)
- if (cfs_hash_compare(hs, key, hnode) > 0)
+ if (cfs_hash_compare(hs, key, hnode))
return hnode;
return NULL;
cfs_hash_t *cfs_hash_create(char *name, unsigned int cur_bits,
unsigned int max_bits,
cfs_hash_ops_t *ops, int flags);
-void cfs_hash_destroy(cfs_hash_t *hs);
+cfs_hash_t *cfs_hash_getref(cfs_hash_t *hs);
+void cfs_hash_putref(cfs_hash_t *hs);
/* Hash addition functions */
void cfs_hash_add(cfs_hash_t *hs, void *key,
void cfs_hash_for_each_empty(cfs_hash_t *hs, cfs_hash_for_each_cb_t, void *data);
void cfs_hash_for_each_key(cfs_hash_t *hs, void *key,
cfs_hash_for_each_cb_t, void *data);
+typedef int (*cfs_hash_cond_opt_cb_t)(void *obj, void *data);
+void cfs_hash_cond_del(cfs_hash_t *hs, cfs_hash_cond_opt_cb_t, void *data);
/*
* Rehash - Theta is calculated to be the average chained