+static unsigned ldlm_res_hop_hash(cfs_hash_t *hs, void *key, unsigned mask)
+{
+ struct ldlm_res_id *id = key;
+ unsigned val = 0;
+ unsigned i;
+
+ for (i = 0; i < RES_NAME_SIZE; i++)
+ val += id->name[i];
+ return val & mask;
+}
+
+static unsigned ldlm_res_hop_fid_hash(cfs_hash_t *hs, void *key, unsigned mask)
+{
+ struct ldlm_res_id *id = key;
+ struct lu_fid fid;
+ __u64 hash;
+
+ fid.f_seq = id->name[LUSTRE_RES_ID_SEQ_OFF];
+ fid.f_oid = (__u32)id->name[LUSTRE_RES_ID_OID_OFF];
+ fid.f_ver = (__u32)id->name[LUSTRE_RES_ID_VER_OFF];
+
+ hash = fid_flatten(&fid);
+ hash = cfs_hash_long(hash, hs->hs_bkt_bits);
+ /* ignore a few low bits */
+ if (id->name[LUSTRE_RES_ID_HSH_OFF] != 0)
+ hash += id->name[LUSTRE_RES_ID_HSH_OFF] >> 5;
+ else
+ hash = hash >> 5;
+ hash <<= hs->hs_cur_bits - hs->hs_bkt_bits;
+ hash |= ldlm_res_hop_hash(hs, key, CFS_HASH_NBKT(hs) - 1);
+
+ return hash & mask;
+}
+
+static void *ldlm_res_hop_key(cfs_hlist_node_t *hnode)
+{
+ struct ldlm_resource *res;
+
+ res = cfs_hlist_entry(hnode, struct ldlm_resource, lr_hash);
+ return &res->lr_name;
+}
+
+static int ldlm_res_eq(const struct ldlm_res_id *res0,
+ const struct ldlm_res_id *res1)
+{
+ return !memcmp(res0, res1, sizeof(*res0));
+}
+
+static int ldlm_res_hop_keycmp(void *key, cfs_hlist_node_t *hnode)
+{
+ struct ldlm_resource *res;
+
+ res = cfs_hlist_entry(hnode, struct ldlm_resource, lr_hash);
+ return ldlm_res_eq((const struct ldlm_res_id *)key,
+ (const struct ldlm_res_id *)&res->lr_name);
+}
+
+static void *ldlm_res_hop_object(cfs_hlist_node_t *hnode)
+{
+ return cfs_hlist_entry(hnode, struct ldlm_resource, lr_hash);
+}
+
+static void ldlm_res_hop_get_locked(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
+{
+ struct ldlm_resource *res;
+
+ res = cfs_hlist_entry(hnode, struct ldlm_resource, lr_hash);
+ ldlm_resource_getref(res);
+ LDLM_RESOURCE_ADDREF(res);
+}
+
+static void ldlm_res_hop_put_locked(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
+{
+ struct ldlm_resource *res;
+
+ res = cfs_hlist_entry(hnode, struct ldlm_resource, lr_hash);
+ /* cfs_hash_for_each_nolock is the only chance we call it */
+ LDLM_RESOURCE_DELREF(res);
+ ldlm_resource_putref_locked(res);
+}
+
+static void ldlm_res_hop_put(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
+{
+ struct ldlm_resource *res;
+
+ res = cfs_hlist_entry(hnode, struct ldlm_resource, lr_hash);
+ LDLM_RESOURCE_DELREF(res);
+ ldlm_resource_putref(res);
+}
+
+cfs_hash_ops_t ldlm_ns_hash_ops = {
+ .hs_hash = ldlm_res_hop_hash,
+ .hs_key = ldlm_res_hop_key,
+ .hs_keycmp = ldlm_res_hop_keycmp,
+ .hs_keycpy = NULL,
+ .hs_object = ldlm_res_hop_object,
+ .hs_get = ldlm_res_hop_get_locked,
+ .hs_put_locked = ldlm_res_hop_put_locked,
+ .hs_put = ldlm_res_hop_put
+};
+
+cfs_hash_ops_t ldlm_ns_fid_hash_ops = {
+ .hs_hash = ldlm_res_hop_fid_hash,
+ .hs_key = ldlm_res_hop_key,
+ .hs_keycmp = ldlm_res_hop_keycmp,
+ .hs_keycpy = NULL,
+ .hs_object = ldlm_res_hop_object,
+ .hs_get = ldlm_res_hop_get_locked,
+ .hs_put_locked = ldlm_res_hop_put_locked,
+ .hs_put = ldlm_res_hop_put
+};
+
+typedef struct {
+ ldlm_ns_type_t nsd_type;
+ /** hash bucket bits */
+ unsigned nsd_bkt_bits;
+ /** hash bits */
+ unsigned nsd_all_bits;
+ /** hash operations */
+ cfs_hash_ops_t *nsd_hops;
+} ldlm_ns_hash_def_t;
+
+ldlm_ns_hash_def_t ldlm_ns_hash_defs[] =
+{
+ {
+ .nsd_type = LDLM_NS_TYPE_MDC,
+ .nsd_bkt_bits = 11,
+ .nsd_all_bits = 15,
+ .nsd_hops = &ldlm_ns_fid_hash_ops,
+ },
+ {
+ .nsd_type = LDLM_NS_TYPE_MDT,
+ .nsd_bkt_bits = 14,
+ .nsd_all_bits = 21,
+ .nsd_hops = &ldlm_ns_fid_hash_ops,
+ },
+ {
+ .nsd_type = LDLM_NS_TYPE_OSC,
+ .nsd_bkt_bits = 8,
+ .nsd_all_bits = 12,
+ .nsd_hops = &ldlm_ns_hash_ops,
+ },
+ {
+ .nsd_type = LDLM_NS_TYPE_OST,
+ .nsd_bkt_bits = 11,
+ .nsd_all_bits = 17,
+ .nsd_hops = &ldlm_ns_hash_ops,
+ },
+ {
+ .nsd_type = LDLM_NS_TYPE_MGC,
+ .nsd_bkt_bits = 4,
+ .nsd_all_bits = 4,
+ .nsd_hops = &ldlm_ns_hash_ops,
+ },
+ {
+ .nsd_type = LDLM_NS_TYPE_MGT,
+ .nsd_bkt_bits = 4,
+ .nsd_all_bits = 4,
+ .nsd_hops = &ldlm_ns_hash_ops,
+ },
+ {
+ .nsd_type = LDLM_NS_TYPE_UNKNOWN,
+ },
+};
+