Whamcloud - gitweb
b=11089
[fs/lustre-release.git] / lustre / obdclass / class_hash.c
index 766e16d..a66bad5 100644 (file)
@@ -39,7 +39,7 @@ int lustre_hash_init(struct lustre_class_hash_body **hash_body_new,
                         n++;
                 i >>= 1;
         }
-        
+
         LASSERTF(n == 1, "hashsize %u isn't 2^n\n", hashsize);
 
         /* alloc space for hash_body */   
@@ -59,7 +59,7 @@ int lustre_hash_init(struct lustre_class_hash_body **hash_body_new,
 
         /* alloc space for the hash tables */
         OBD_ALLOC(hash_body->lchb_hash_tables, 
-                  sizeof(*hash_body->lchb_hash_tables) * hash_body->lchb_hash_max_size);     
+                  sizeof(*hash_body->lchb_hash_tables) * hash_body->lchb_hash_max_size);
 
         if (hash_body->lchb_hash_tables == NULL) {
                 OBD_FREE(hash_body, sizeof(*hash_body)); 
@@ -178,6 +178,53 @@ int lustre_hash_additem_unique(struct lustre_class_hash_body *hash_body,
 EXPORT_SYMBOL(lustre_hash_additem_unique);
 
 /*
+ * only allow unique @key in hashtables, if the same @key has existed
+ * in hashtables, it will return with fails.
+ */
+void* lustre_hash_findadd_unique(struct lustre_class_hash_body *hash_body,
+                                     void *key, struct hlist_node *actual_hnode)
+{
+        int hashent;
+        struct lustre_hash_bucket *bucket = NULL;
+        struct lustre_hash_operations *hop = hash_body->lchb_hash_operations;
+        struct hlist_node * hash_item_hnode = NULL;
+        void *obj;
+        ENTRY;
+
+        LASSERT(hlist_unhashed(actual_hnode));
+        hashent = hop->lustre_hashfn(hash_body, key);
+
+        /* get the hash-bucket and lock it */
+        bucket = &hash_body->lchb_hash_tables[hashent];
+        spin_lock(&bucket->lhb_lock);
+
+        hash_item_hnode = lustre_hash_getitem_in_bucket_nolock(hash_body,
+                                                               hashent, key);
+        if ( hash_item_hnode != NULL) {
+                /* the added-item exist in hashtables, so cannot add it again */
+                obj = hop->lustre_hash_object_refcount_get(hash_item_hnode);
+                spin_unlock(&bucket->lhb_lock);
+                RETURN(obj);
+        }
+
+        hlist_add_head(actual_hnode, &(bucket->lhb_head));
+
+#ifdef LUSTRE_HASH_DEBUG
+        /* hash distribute debug */
+        hash_body->lchb_hash_tables[hashent].lhb_item_count++;
+        CDEBUG(D_INFO, "hashname[%s] bucket[%d] has [%d] hashitem\n",
+                        hash_body->hashname, hashent,
+                        hash_body->lchb_hash_tables[hashent].lhb_item_count);
+#endif
+        obj = hop->lustre_hash_object_refcount_get(actual_hnode);
+
+        spin_unlock(&bucket->lhb_lock);
+
+        RETURN(obj);
+}
+EXPORT_SYMBOL(lustre_hash_findadd_unique);
+
+/*
  * this version of additem, it allow multi same @key <key, value> in hashtables. 
  * in this additem version, we don't need to check if exist same @key in hash 
  * tables, we only add it to related hashbucket.
@@ -286,6 +333,62 @@ int lustre_hash_delitem(struct lustre_class_hash_body *hash_body,
 }
 EXPORT_SYMBOL(lustre_hash_delitem);
 
+void lustre_hash_bucket_iterate(struct lustre_class_hash_body *hash_body,
+                                void *key, hash_item_iterate_cb func, void *data)
+{
+        int hashent, find = 0;
+        struct lustre_hash_bucket *bucket = NULL;
+        struct hlist_node *hash_item_node = NULL;
+        struct lustre_hash_operations *hop = hash_body->lchb_hash_operations;
+        struct obd_export *tmp = NULL;
+
+        ENTRY;
+
+        hashent = hop->lustre_hashfn(hash_body, key);
+        bucket = &hash_body->lchb_hash_tables[hashent];
+
+        spin_lock(&bucket->lhb_lock);
+        hlist_for_each(hash_item_node, &(bucket->lhb_head)) {
+                find = hop->lustre_hash_key_compare(key, hash_item_node);
+                if (find) {
+                        tmp = hop->lustre_hash_object_refcount_get(hash_item_node);
+                        func(tmp, data);
+                        hop->lustre_hash_object_refcount_put(hash_item_node);
+                }
+        }
+        spin_unlock(&bucket->lhb_lock);
+}
+EXPORT_SYMBOL(lustre_hash_bucket_iterate);
+
+void lustre_hash_iterate_all(struct lustre_class_hash_body *hash_body,
+                            hash_item_iterate_cb func, void *data)
+{
+        int i;
+        struct lustre_hash_operations *hop = hash_body->lchb_hash_operations;
+        ENTRY;
+
+        for( i = 0; i < hash_body->lchb_hash_max_size; i++ ) {
+                struct lustre_hash_bucket * bucket;
+                struct hlist_node * actual_hnode, *pos;
+                void *obj;
+
+                bucket = &hash_body->lchb_hash_tables[i];
+#ifdef LUSTRE_HASH_DEBUG
+                CDEBUG(D_INFO, "idx %d - bucket %p\n", i, bucket);
+#endif
+                spin_lock(&bucket->lhb_lock); /* lock the bucket */
+                hlist_for_each_safe(actual_hnode, pos, &(bucket->lhb_head)) {
+                        obj = hop->lustre_hash_object_refcount_get(actual_hnode);
+                        func(obj, data);
+                        hop->lustre_hash_object_refcount_put(actual_hnode);
+                }
+                spin_unlock(&bucket->lhb_lock);
+        }
+        EXIT;
+}
+EXPORT_SYMBOL(lustre_hash_iterate_all);
+
+
 void * lustre_hash_get_object_by_key(struct lustre_class_hash_body *hash_body,
                                      void *key)
 {
@@ -317,6 +420,24 @@ void * lustre_hash_get_object_by_key(struct lustre_class_hash_body *hash_body,
 }
 EXPORT_SYMBOL(lustre_hash_get_object_by_key);
 
+/* string hashing using djb2 hash algorithm */
+__u32 djb2_hashfn(struct lustre_class_hash_body *hash_body,  void* key,
+                  size_t size)
+{
+        __u32 hash = 5381;
+        int i;
+        char *ptr = key;
+
+        LASSERT(key != NULL);
+
+        for( i = 0; i < size; i++ )
+                hash = hash * 33 + ptr[i];
+
+        hash &= (hash_body->lchb_hash_max_size - 1);
+
+        RETURN(hash);
+}
+
 /*
  * define (uuid <-> export) hash operations and function define
  */
@@ -329,26 +450,11 @@ struct lustre_hash_operations uuid_hash_operations = {
         .lustre_hash_object_refcount_put = uuid_export_refcount_put,
 };
 
-/* string hashing using djb2 hash algorithm */
 __u32 uuid_hashfn(struct lustre_class_hash_body *hash_body,  void * key)
 {
-        __u32 hash = 5381;
-        struct obd_uuid * uuid_key = NULL;
-        int c;
-        char *ptr = NULL;
-
-        LASSERT(key != NULL); 
+        struct obd_uuid * uuid_key = key;
 
-        uuid_key = (struct obd_uuid*)key;
-        ptr = uuid_key->uuid;
-
-        while ((c = *ptr++)) {
-                hash = hash * 33 + c;
-        }
-
-        hash &= (hash_body->lchb_hash_max_size - 1);
-
-        RETURN(hash);             
+        return djb2_hashfn(hash_body, uuid_key->uuid, sizeof(uuid_key->uuid));
 }
 
 /* Note, it is impossible to find an export that is in failed state with
@@ -410,21 +516,9 @@ struct lustre_hash_operations nid_hash_operations = {
         .lustre_hash_object_refcount_put = nid_export_refcount_put,
 };
 
-/* string hashing using djb2 hash algorithm */
 __u32 nid_hashfn(struct lustre_class_hash_body *hash_body,  void * key)
 {
-        __u32 hash = 5381;
-        int i;
-        char *ptr = key;
-
-        LASSERT(key != NULL); 
-
-        for(i = 0 ; i < sizeof(lnet_nid_t) ; i ++)
-                hash = hash * 33 + ptr[i];
-
-        hash &= (hash_body->lchb_hash_max_size - 1);
-
-        RETURN(hash);             
+        return djb2_hashfn(hash_body, key, sizeof(lnet_nid_t));
 }
 
 /* Note, it is impossible to find an export that is in failed state with
@@ -485,21 +579,9 @@ struct lustre_hash_operations conn_hash_operations = {
 };
 EXPORT_SYMBOL(conn_hash_operations);
 
-/* string hashing using djb2 hash algorithm */
 __u32 conn_hashfn(struct lustre_class_hash_body *hash_body,  void * key)
 {
-        __u32 hash = 5381;
-        char *ptr = key;
-        int i;
-
-        LASSERT(key != NULL); 
-
-        for(i = 0 ; i < sizeof(lnet_process_id_t) ; i ++)
-                hash = hash * 33 + ptr[i];
-
-        hash &= (hash_body->lchb_hash_max_size - 1);
-
-        RETURN(hash);             
+        return djb2_hashfn(hash_body, key, sizeof(lnet_process_id_t));
 }
 
 int conn_hash_key_compare(void *key, struct hlist_node *compared_hnode)
@@ -545,3 +627,47 @@ void conn_refcount_put(struct hlist_node *actual_hnode)
         atomic_dec(&c->c_refcount);
 }
 
+/*******************************************************************************/
+/* ( nid<>nidstats ) hash operations define */
+
+struct lustre_hash_operations nid_stat_hash_operations = {
+        .lustre_hashfn = nid_hashfn,
+        .lustre_hash_key_compare = nidstats_hash_key_compare,
+        .lustre_hash_object_refcount_get = nidstats_refcount_get,
+        .lustre_hash_object_refcount_put = nidstats_refcount_put,
+};
+EXPORT_SYMBOL(nid_stat_hash_operations);
+
+int nidstats_hash_key_compare(void *key, struct hlist_node * compared_hnode)
+{
+        struct nid_stat *data;
+        lnet_nid_t *nid_key;
+
+        LASSERT( key != NULL);
+
+        nid_key = (lnet_nid_t*)key;
+        data = hlist_entry(compared_hnode, struct nid_stat, nid_hash);
+
+        return (data->nid == *nid_key);
+}
+
+void* nidstats_refcount_get(struct hlist_node * actual_hnode)
+{
+        struct nid_stat *data;
+
+        data = hlist_entry(actual_hnode, struct nid_stat, nid_hash);
+        data->nid_exp_ref_count++;
+
+        RETURN(data);
+}
+
+void nidstats_refcount_put(struct hlist_node * actual_hnode)
+{
+        struct nid_stat *data;
+
+        data = hlist_entry(actual_hnode, struct nid_stat, nid_hash);
+        data->nid_exp_ref_count--;
+
+}
+
+/*******************************************************************************/