Whamcloud - gitweb
LU-8130 obd: convert obd_nid_hash to rhashtable 18/33518/21
authorJames Simmons <jsimmons@infradead.org>
Mon, 18 May 2020 22:10:10 +0000 (18:10 -0400)
committerOleg Drokin <green@whamcloud.com>
Tue, 16 Jun 2020 02:21:28 +0000 (02:21 +0000)
Linux has a resizeable hashtable implementation in lib,
so we should use that instead of having one in libcfs.

This patch converts the struct obd_export obd_nid_hash to use
rhashtable. In the process we gain lockless lookup which should
improve performance. For the nid hash we use rhltable since the
mapping can be many exports to a NID key.

Signed-off-by: James Simmons <jsimmons@infradead.org>
Change-Id: I45154ceb48336b20161f771d986d8fe7333b9849
Reviewed-on: https://review.whamcloud.com/33518
Reviewed-by: Neil Brown <neilb@suse.de>
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/lustre_export.h
lustre/include/obd.h
lustre/include/obd_support.h
lustre/ldlm/ldlm_flock.c
lustre/ldlm/ldlm_lib.c
lustre/mdt/mdt_lproc.c
lustre/obdclass/genops.c
lustre/obdclass/lprocfs_status_server.c
lustre/obdclass/obd_config.c

index f6e136a..3ba56cb 100644 (file)
@@ -213,7 +213,7 @@ struct obd_export {
        /* Unlinked export list */
        struct list_head        exp_stale_list;
        struct rhash_head       exp_uuid_hash;  /** uuid-export hash */
-       struct hlist_node       exp_nid_hash;   /** nid-export hash */
+       struct rhlist_head      exp_nid_hash;   /** nid-export hash */
        struct hlist_node       exp_gen_hash;   /** last_rcvd clt gen hash */
         /**
          * All exports eligible for ping evictor are linked into a list
@@ -279,7 +279,8 @@ struct obd_export {
                                 * request. */
                                exp_replay_done:1,
                                /* local client with recovery disabled */
-                               exp_no_recovery:1;
+                               exp_no_recovery:1,
+                               exp_hashed:1;
        /* also protected by exp_lock */
        enum lustre_sec_part    exp_sp_peer;
        struct sptlrpc_flavor   exp_flvr;               /* current */
index 9da2f12..4e585ad 100644 (file)
@@ -634,7 +634,7 @@ struct obd_device {
         /* uuid-export hash body */
        struct rhashtable               obd_uuid_hash;
         /* nid-export hash body */
-       struct cfs_hash             *obd_nid_hash;
+       struct rhltable                 obd_nid_hash;
        /* nid stats body */
        struct cfs_hash             *obd_nid_stats_hash;
        /* client_generation-export hash body */
@@ -753,6 +753,12 @@ void obd_uuid_del(struct obd_device *obd, struct obd_export *export);
 #ifdef HAVE_SERVER_SUPPORT
 struct obd_export *obd_uuid_lookup(struct obd_device *obd,
                                   struct obd_uuid *uuid);
+
+int obd_nid_export_for_each(struct obd_device *obd, lnet_nid_t nid,
+                           int cb(struct obd_export *exp, void *data),
+                           void *data);
+int obd_nid_add(struct obd_device *obd, struct obd_export *exp);
+void obd_nid_del(struct obd_device *obd, struct obd_export *exp);
 #endif
 
 /* get/set_info keys */
index e8a99d5..69477d8 100644 (file)
@@ -71,9 +71,6 @@ extern atomic_long_t obd_dirty_pages;
 extern char obd_jobid_var[];
 
 /* Some hash init argument constants */
-#define HASH_NID_BKT_BITS 5
-#define HASH_NID_CUR_BITS 7
-#define HASH_NID_MAX_BITS 12
 #define HASH_NID_STATS_BKT_BITS 5
 #define HASH_NID_STATS_CUR_BITS 7
 #define HASH_NID_STATS_MAX_BITS 12
index 7866d3f..007d00a 100644 (file)
@@ -151,6 +151,7 @@ ldlm_flock_destroy(struct ldlm_lock *lock, enum ldlm_mode mode, __u64 flags)
        EXIT;
 }
 
+#ifdef HAVE_SERVER_SUPPORT
 /**
  * POSIX locks deadlock detection code.
  *
@@ -167,11 +168,9 @@ struct ldlm_flock_lookup_cb_data {
        struct obd_export *exp;
 };
 
-static int ldlm_flock_lookup_cb(struct cfs_hash *hs, struct cfs_hash_bd *bd,
-                               struct hlist_node *hnode, void *data)
+static int ldlm_flock_lookup_cb(struct obd_export *exp, void *data)
 {
        struct ldlm_flock_lookup_cb_data *cb_data = data;
-       struct obd_export *exp = cfs_hash_object(hs, hnode);
        struct ldlm_lock *lock;
 
        lock = cfs_hash_lookup(exp->exp_flock_hash, cb_data->bl_owner);
@@ -204,16 +203,21 @@ ldlm_flock_deadlock(struct ldlm_lock *req, struct ldlm_lock *bl_lock)
                        .lock = NULL,
                        .exp = NULL,
                };
+               struct ptlrpc_connection *bl_exp_conn;
                struct obd_export *bl_exp_new;
                struct ldlm_lock *lock = NULL;
                struct ldlm_flock *flock;
 
+               bl_exp_conn = bl_exp->exp_connection;
                if (bl_exp->exp_flock_hash != NULL) {
-                       cfs_hash_for_each_key(
-                               bl_exp->exp_obd->obd_nid_hash,
-                               &bl_exp->exp_connection->c_peer.nid,
-                               ldlm_flock_lookup_cb, &cb_data);
-                       lock = cb_data.lock;
+                       int found;
+
+                       found = obd_nid_export_for_each(bl_exp->exp_obd,
+                                                       bl_exp_conn->c_peer.nid,
+                                                       ldlm_flock_lookup_cb,
+                                                       &cb_data);
+                       if (found)
+                               lock = cb_data.lock;
                }
                if (lock == NULL)
                        break;
@@ -235,7 +239,7 @@ ldlm_flock_deadlock(struct ldlm_lock *req, struct ldlm_lock *bl_lock)
                        break;
 
                if (bl_owner == req_owner &&
-                   (bl_exp->exp_connection->c_peer.nid ==
+                   (bl_exp_conn->c_peer.nid ==
                     req_exp->exp_connection->c_peer.nid)) {
                        class_export_put(bl_exp);
                        return 1;
@@ -264,6 +268,7 @@ static void ldlm_flock_cancel_on_deadlock(struct ldlm_lock *lock,
                ldlm_add_ast_work_item(lock, NULL, work_list);
        }
 }
+#endif /* HAVE_SERVER_SUPPORT */
 
 /**
  * Process a granting attempt for flock lock.
@@ -291,8 +296,10 @@ ldlm_process_flock_lock(struct ldlm_lock *req, __u64 *flags,
        int overlaps = 0;
        int splitted = 0;
        const struct ldlm_callback_suite null_cbs = { NULL };
+#ifdef HAVE_SERVER_SUPPORT
        struct list_head *grant_work = (intention == LDLM_PROCESS_ENQUEUE ?
                                        NULL : work_list);
+#endif
        ENTRY;
 
        CDEBUG(D_DLMTRACE, "flags %#llx owner %llu pid %u mode %u start "
@@ -327,7 +334,9 @@ reprocess:
                                break;
                        }
                }
-       } else {
+       }
+#ifdef HAVE_SERVER_SUPPORT
+       else {
                int reprocess_failed = 0;
                lockmode_verify(mode);
 
@@ -411,11 +420,11 @@ reprocess:
         * deadlock detection hash list.
         */
        ldlm_flock_blocking_unlink(req);
+#endif /* HAVE_SERVER_SUPPORT */
 
        /* Scan the locks owned by this process that overlap this request.
         * We may have to merge or split existing locks.
         */
-
        if (!ownlocks)
                ownlocks = &res->lr_granted;
 
index 3139aaa..b0649fd 100644 (file)
@@ -818,7 +818,6 @@ static inline int target_check_recovery_timer(struct obd_device *target)
  * from old lib/target.c
  * --------------------------------------------------------------------------
  */
-
 static int target_handle_reconnect(struct lustre_handle *conn,
                                   struct obd_export *exp,
                                   struct obd_uuid *cluuid)
@@ -1448,11 +1447,8 @@ dont_check_exports:
 
        if (export->exp_connection != NULL) {
                /* Check to see if connection came from another NID. */
-               if ((export->exp_connection->c_peer.nid != req->rq_peer.nid) &&
-                   !hlist_unhashed(&export->exp_nid_hash))
-                       cfs_hash_del(export->exp_obd->obd_nid_hash,
-                                    &export->exp_connection->c_peer.nid,
-                                    &export->exp_nid_hash);
+               if (export->exp_connection->c_peer.nid != req->rq_peer.nid)
+                       obd_nid_del(export->exp_obd, export);
 
                ptlrpc_connection_put(export->exp_connection);
        }
@@ -1460,10 +1456,7 @@ dont_check_exports:
        export->exp_connection = ptlrpc_connection_get(req->rq_peer,
                                                       req->rq_self,
                                                       &cluuid);
-       if (hlist_unhashed(&export->exp_nid_hash))
-               cfs_hash_add(export->exp_obd->obd_nid_hash,
-                            &export->exp_connection->c_peer.nid,
-                            &export->exp_nid_hash);
+       obd_nid_add(export->exp_obd, export);
 
        lustre_msg_set_handle(req->rq_repmsg, &conn);
 
index 71b6943..e483884 100644 (file)
@@ -1304,10 +1304,8 @@ static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
 };
 
 static int
-lprocfs_mdt_print_open_files(struct cfs_hash *hs, struct cfs_hash_bd *bd,
-                            struct hlist_node *hnode, void *v)
+lprocfs_mdt_print_open_files(struct obd_export *exp, void *v)
 {
-       struct obd_export       *exp = cfs_hash_object(hs, hnode);
        struct seq_file         *seq = v;
 
        if (exp->exp_lock_hash != NULL) {
@@ -1328,12 +1326,9 @@ lprocfs_mdt_print_open_files(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 static int lprocfs_mdt_open_files_seq_show(struct seq_file *seq, void *v)
 {
        struct nid_stat *stats = seq->private;
-       struct obd_device *obd = stats->nid_obd;
 
-       cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
-                             lprocfs_mdt_print_open_files, seq);
-
-       return 0;
+       return obd_nid_export_for_each(stats->nid_obd, stats->nid,
+                                      lprocfs_mdt_print_open_files, seq);
 }
 
 int lprocfs_mdt_open_files_seq_open(struct inode *inode, struct file *file)
index d4feb7c..18818af 100644 (file)
@@ -1057,7 +1057,6 @@ struct obd_export *__class_new_export(struct obd_device *obd,
        export->exp_last_request_time = ktime_get_real_seconds();
        spin_lock_init(&export->exp_lock);
        spin_lock_init(&export->exp_rpc_lock);
-       INIT_HLIST_NODE(&export->exp_nid_hash);
        INIT_HLIST_NODE(&export->exp_gen_hash);
        spin_lock_init(&export->exp_bl_list_lock);
        INIT_LIST_HEAD(&export->exp_bl_list);
@@ -1427,22 +1426,21 @@ int class_disconnect(struct obd_export *export)
        spin_lock(&export->exp_lock);
        already_disconnected = export->exp_disconnected;
        export->exp_disconnected = 1;
+#ifdef HAVE_SERVER_SUPPORT
        /*  We hold references of export for uuid hash
         *  and nid_hash and export link at least. So
-        *  it is safe to call cfs_hash_del in there.  */
-       if (!hlist_unhashed(&export->exp_nid_hash))
-               cfs_hash_del(export->exp_obd->obd_nid_hash,
-                            &export->exp_connection->c_peer.nid,
-                            &export->exp_nid_hash);
+        *  it is safe to call rh*table_remove_fast in
+        *  there.
+        */
+       obd_nid_del(export->exp_obd, export);
+#endif /* HAVE_SERVER_SUPPORT */
        spin_unlock(&export->exp_lock);
 
         /* class_cleanup(), abort_recovery(), and class_fail_export()
          * all end up in here, and if any of them race we shouldn't
          * call extra class_export_puts(). */
-        if (already_disconnected) {
-               LASSERT(hlist_unhashed(&export->exp_nid_hash));
+       if (already_disconnected)
                 GOTO(no_disconn, already_disconnected);
-        }
 
        CDEBUG(D_IOCTL, "disconnect: cookie %#llx\n",
                export->exp_handle.h_cookie);
@@ -1626,13 +1624,13 @@ void class_fail_export(struct obd_export *exp)
 }
 EXPORT_SYMBOL(class_fail_export);
 
+#ifdef HAVE_SERVER_SUPPORT
 int obd_export_evict_by_nid(struct obd_device *obd, const char *nid)
 {
-       struct cfs_hash *nid_hash;
-       struct obd_export *doomed_exp = NULL;
-       int exports_evicted = 0;
-
        lnet_nid_t nid_key = libcfs_str2nid((char *)nid);
+       struct obd_export *doomed_exp;
+       struct rhashtable_iter iter;
+       int exports_evicted = 0;
 
        spin_lock(&obd->obd_dev_lock);
        /* umount has run already, so evict thread should leave
@@ -1641,31 +1639,39 @@ int obd_export_evict_by_nid(struct obd_device *obd, const char *nid)
                spin_unlock(&obd->obd_dev_lock);
                return exports_evicted;
        }
-       nid_hash = obd->obd_nid_hash;
-       cfs_hash_getref(nid_hash);
        spin_unlock(&obd->obd_dev_lock);
 
-       do {
-               doomed_exp = cfs_hash_lookup(nid_hash, &nid_key);
-                if (doomed_exp == NULL)
-                        break;
+       rhltable_walk_enter(&obd->obd_nid_hash, &iter);
+       rhashtable_walk_start(&iter);
+       while ((doomed_exp = rhashtable_walk_next(&iter)) != NULL) {
+               if (IS_ERR(doomed_exp))
+                       continue;
 
-                LASSERTF(doomed_exp->exp_connection->c_peer.nid == nid_key,
-                         "nid %s found, wanted nid %s, requested nid %s\n",
-                         obd_export_nid2str(doomed_exp),
-                         libcfs_nid2str(nid_key), nid);
-                LASSERTF(doomed_exp != obd->obd_self_export,
-                         "self-export is hashed by NID?\n");
-                exports_evicted++;
-               LCONSOLE_WARN("%s: evicting %s (at %s) by administrative "
-                             "request\n", obd->obd_name,
+               if (!doomed_exp->exp_connection ||
+                   doomed_exp->exp_connection->c_peer.nid != nid_key)
+                       continue;
+
+               if (!refcount_inc_not_zero(&doomed_exp->exp_handle.h_ref))
+                       continue;
+
+               rhashtable_walk_stop(&iter);
+
+               LASSERTF(doomed_exp != obd->obd_self_export,
+                        "self-export is hashed by NID?\n");
+
+               LCONSOLE_WARN("%s: evicting %s (at %s) by administrative request\n",
+                             obd->obd_name,
                              obd_uuid2str(&doomed_exp->exp_client_uuid),
                              obd_export_nid2str(doomed_exp));
-                class_fail_export(doomed_exp);
-                class_export_put(doomed_exp);
-        } while (1);
 
-       cfs_hash_putref(nid_hash);
+               class_fail_export(doomed_exp);
+               class_export_put(doomed_exp);
+               exports_evicted++;
+
+               rhashtable_walk_start(&iter);
+       }
+       rhashtable_walk_stop(&iter);
+       rhashtable_walk_exit(&iter);
 
         if (!exports_evicted)
                 CDEBUG(D_HA,"%s: can't disconnect NID '%s': no exports found\n",
@@ -1674,7 +1680,6 @@ int obd_export_evict_by_nid(struct obd_device *obd, const char *nid)
 }
 EXPORT_SYMBOL(obd_export_evict_by_nid);
 
-#ifdef HAVE_SERVER_SUPPORT
 int obd_export_evict_by_uuid(struct obd_device *obd, const char *uuid)
 {
        struct obd_export *doomed_exp = NULL;
index 9c38196..a8602c7 100644 (file)
@@ -168,11 +168,9 @@ static int obd_export_flags2str(struct obd_export *exp, struct seq_file *m)
 }
 
 static int
-lprocfs_exp_print_export_seq(struct cfs_hash *hs, struct cfs_hash_bd *bd,
-                            struct hlist_node *hnode, void *cb_data)
+lprocfs_exp_print_export_seq(struct obd_export *exp, void *cb_data)
 {
        struct seq_file         *m = cb_data;
-       struct obd_export       *exp = cfs_hash_object(hs, hnode);
        struct obd_device       *obd;
        struct obd_connect_data *ocd;
 
@@ -227,11 +225,9 @@ out:
 static int lprocfs_exp_export_seq_show(struct seq_file *m, void *data)
 {
        struct nid_stat *stats = m->private;
-       struct obd_device *obd = stats->nid_obd;
 
-       cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
-                             lprocfs_exp_print_export_seq, m);
-       return 0;
+       return obd_nid_export_for_each(stats->nid_obd, stats->nid,
+                                      lprocfs_exp_print_export_seq, m);
 }
 LPROC_SEQ_FOPS_RO(lprocfs_exp_export);
 
@@ -276,50 +272,42 @@ void lprocfs_free_per_client_stats(struct obd_device *obd)
 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
 
 static int
-lprocfs_exp_print_uuid_seq(struct cfs_hash *hs, struct cfs_hash_bd *bd,
-                          struct hlist_node *hnode, void *cb_data)
+lprocfs_exp_print_nodemap_seq(struct obd_export *exp, void *cb_data)
 {
+       struct lu_nodemap *nodemap = exp->exp_target_data.ted_nodemap;
        struct seq_file *m = cb_data;
-       struct obd_export *exp = cfs_hash_object(hs, hnode);
 
-       if (exp->exp_nid_stats != NULL)
-               seq_printf(m, "%s\n", obd_uuid2str(&exp->exp_client_uuid));
+       if (nodemap)
+               seq_printf(m, "%s\n", nodemap->nm_name);
        return 0;
 }
 
 static int
-lprocfs_exp_print_nodemap_seq(struct cfs_hash *hs, struct cfs_hash_bd *bd,
-                             struct hlist_node *hnode, void *cb_data)
+lprocfs_exp_nodemap_seq_show(struct seq_file *m, void *data)
 {
-       struct seq_file *m = cb_data;
-       struct obd_export *exp = cfs_hash_object(hs, hnode);
-       struct lu_nodemap *nodemap = exp->exp_target_data.ted_nodemap;
+       struct nid_stat *stats = m->private;
 
-       if (nodemap != NULL)
-               seq_printf(m, "%s\n", nodemap->nm_name);
-       return 0;
+       return obd_nid_export_for_each(stats->nid_obd, stats->nid,
+                                      lprocfs_exp_print_nodemap_seq, m);
 }
+LPROC_SEQ_FOPS_RO(lprocfs_exp_nodemap);
 
 static int
-lprocfs_exp_nodemap_seq_show(struct seq_file *m, void *data)
+lprocfs_exp_print_uuid_seq(struct obd_export *exp, void *cb_data)
 {
-       struct nid_stat *stats = m->private;
-       struct obd_device *obd = stats->nid_obd;
+       struct seq_file *m = cb_data;
 
-       cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
-                             lprocfs_exp_print_nodemap_seq, m);
+       if (exp->exp_nid_stats)
+               seq_printf(m, "%s\n", obd_uuid2str(&exp->exp_client_uuid));
        return 0;
 }
-LPROC_SEQ_FOPS_RO(lprocfs_exp_nodemap);
 
 static int lprocfs_exp_uuid_seq_show(struct seq_file *m, void *data)
 {
        struct nid_stat *stats = m->private;
-       struct obd_device *obd = stats->nid_obd;
 
-       cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
-                               lprocfs_exp_print_uuid_seq, m);
-       return 0;
+       return obd_nid_export_for_each(stats->nid_obd, stats->nid,
+                                      lprocfs_exp_print_uuid_seq, m);
 }
 LPROC_SEQ_FOPS_RO(lprocfs_exp_uuid);
 
@@ -362,16 +350,16 @@ static void ldebugfs_rhash_seq_show(const char *name, struct rhashtable *ht,
 }
 
 static int
-lprocfs_exp_print_hash_seq(struct cfs_hash *hs, struct cfs_hash_bd *bd,
-                          struct hlist_node *hnode, void *cb_data)
+lprocfs_exp_print_hash_seq(struct obd_export *exp, void *cb_data)
 
 {
+       struct obd_device *obd = exp->exp_obd;
        struct seq_file *m = cb_data;
-       struct obd_export *exp = cfs_hash_object(hs, hnode);
 
        if (exp->exp_lock_hash != NULL) {
-               cfs_hash_debug_header(m);
-               cfs_hash_debug_str(hs, m);
+               seq_printf(m, "%-*s   cur   min        max theta t-min t-max flags rehash   count distribution\n",
+                          HASH_NAME_LEN, "name");
+               ldebugfs_rhash_seq_show("NID_HASH", &obd->obd_nid_hash.ht, m);
        }
        return 0;
 }
@@ -379,19 +367,15 @@ lprocfs_exp_print_hash_seq(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 static int lprocfs_exp_hash_seq_show(struct seq_file *m, void *data)
 {
        struct nid_stat *stats = m->private;
-       struct obd_device *obd = stats->nid_obd;
 
-       cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
-                               lprocfs_exp_print_hash_seq, m);
-       return 0;
+       return obd_nid_export_for_each(stats->nid_obd, stats->nid,
+                                      lprocfs_exp_print_hash_seq, m);
 }
 LPROC_SEQ_FOPS_RO(lprocfs_exp_hash);
 
-int lprocfs_exp_print_replydata_seq(struct cfs_hash *hs, struct cfs_hash_bd *bd,
-                                   struct hlist_node *hnode, void *cb_data)
+int lprocfs_exp_print_replydata_seq(struct obd_export *exp, void *cb_data)
 
 {
-       struct obd_export *exp = cfs_hash_object(hs, hnode);
        struct seq_file *m = cb_data;
        struct tg_export_data *ted = &exp->exp_target_data;
 
@@ -409,19 +393,14 @@ int lprocfs_exp_print_replydata_seq(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 int lprocfs_exp_replydata_seq_show(struct seq_file *m, void *data)
 {
        struct nid_stat *stats = m->private;
-       struct obd_device *obd = stats->nid_obd;
 
-       cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
-                               lprocfs_exp_print_replydata_seq, m);
-       return 0;
+       return obd_nid_export_for_each(stats->nid_obd, stats->nid,
+                                      lprocfs_exp_print_replydata_seq, m);
 }
 LPROC_SEQ_FOPS_RO(lprocfs_exp_replydata);
 
-int lprocfs_exp_print_fmd_count_seq(struct cfs_hash *hs, struct cfs_hash_bd *bd,
-                                   struct hlist_node *hnode, void *cb_data)
-
+int lprocfs_exp_print_fmd_count_seq(struct obd_export *exp, void *cb_data)
 {
-       struct obd_export *exp = cfs_hash_object(hs, hnode);
        struct seq_file *m = cb_data;
        struct tg_export_data *ted = &exp->exp_target_data;
 
@@ -433,11 +412,9 @@ int lprocfs_exp_print_fmd_count_seq(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 int lprocfs_exp_fmd_count_seq_show(struct seq_file *m, void *data)
 {
        struct nid_stat *stats = m->private;
-       struct obd_device *obd = stats->nid_obd;
 
-       cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
-                             lprocfs_exp_print_fmd_count_seq, m);
-       return 0;
+       return obd_nid_export_for_each(stats->nid_obd, stats->nid,
+                                      lprocfs_exp_print_fmd_count_seq, m);
 }
 LPROC_SEQ_FOPS_RO(lprocfs_exp_fmd_count);
 
@@ -691,9 +668,9 @@ int lprocfs_hash_seq_show(struct seq_file *m, void *data)
        seq_printf(m, "%-*s   cur   min        max theta t-min t-max flags  rehash   count  maxdep distribution\n",
                   HASH_NAME_LEN, "name");
        ldebugfs_rhash_seq_show("UUID_HASH", &obd->obd_uuid_hash, m);
+       ldebugfs_rhash_seq_show("NID_HASH", &obd->obd_nid_hash.ht, m);
 
        cfs_hash_debug_header(m);
-       cfs_hash_debug_str(obd->obd_nid_hash, m);
        cfs_hash_debug_str(obd->obd_nid_stats_hash, m);
        return 0;
 }
index aef076f..882784a 100644 (file)
 
 #include "llog_internal.h"
 
-static struct cfs_hash_ops nid_hash_ops;
+#ifdef HAVE_SERVER_SUPPORT
 static struct cfs_hash_ops nid_stat_hash_ops;
 static struct cfs_hash_ops gen_hash_ops;
+#endif /* HAVE_SERVER_SUPPORT */
 
 /*
  * uuid<->export lustre hash operations
@@ -146,6 +147,118 @@ struct obd_export *obd_uuid_lookup(struct obd_device *obd,
        return export;
 }
 EXPORT_SYMBOL(obd_uuid_lookup);
+
+/*
+ * nid<->export hash operations
+ */
+static u32 nid_keyhash(const void *data, u32 key_len, u32 seed)
+{
+       const struct obd_export *exp = data;
+       void *key;
+
+       if (!exp->exp_connection)
+               return 0;
+
+       key = &exp->exp_connection->c_peer.nid;
+       return jhash2(key, key_len / sizeof(u32), seed);
+}
+
+/*
+ * NOTE: It is impossible to find an export that is in failed
+ *      state with this function
+ */
+static int
+nid_keycmp(struct rhashtable_compare_arg *arg, const void *obj)
+{
+       const lnet_nid_t *nid = arg->key;
+       const struct obd_export *exp = obj;
+
+       if (exp->exp_connection->c_peer.nid == *nid && !exp->exp_failed)
+               return 0;
+
+       return -ESRCH;
+}
+
+static void
+nid_export_exit(void *vexport, void *data)
+{
+       struct obd_export *exp = vexport;
+
+       class_export_put(exp);
+}
+
+const struct rhashtable_params nid_hash_params = {
+       .key_len                = sizeof(lnet_nid_t),
+       .head_offset            = offsetof(struct obd_export, exp_nid_hash),
+       .obj_hashfn             = nid_keyhash,
+       .obj_cmpfn              = nid_keycmp,
+       .automatic_shrinking    = true,
+};
+
+int obd_nid_add(struct obd_device *obd, struct obd_export *exp)
+{
+       int rc;
+
+       if (exp == exp->exp_obd->obd_self_export || exp->exp_hashed)
+               return 0;
+
+       class_export_get(exp);
+       rc = rhltable_insert_key(&obd->obd_nid_hash,
+                                &exp->exp_connection->c_peer.nid,
+                                &exp->exp_nid_hash,
+                                nid_hash_params);
+       if (rc) {
+               class_export_put(exp);
+               /* map obscure error codes to -ENOMEM */
+               rc = -ENOMEM;
+       } else {
+               exp->exp_hashed = 1;
+       }
+       return rc;
+}
+EXPORT_SYMBOL(obd_nid_add);
+
+void obd_nid_del(struct obd_device *obd, struct obd_export *exp)
+{
+       int rc;
+
+       if (exp == exp->exp_obd->obd_self_export || !exp->exp_hashed)
+               return;
+
+       rc = rhltable_remove(&obd->obd_nid_hash, &exp->exp_nid_hash,
+                            nid_hash_params);
+       if (rc == 0) {
+               class_export_put(exp);
+               exp->exp_hashed = 0;
+       }
+}
+EXPORT_SYMBOL(obd_nid_del);
+
+int obd_nid_export_for_each(struct obd_device *obd, lnet_nid_t nid,
+                           int cb(struct obd_export *exp, void *data),
+                           void *data)
+{
+       struct rhlist_head *exports, *tmp;
+       struct obd_export *exp;
+       int ret = 0;
+
+       rcu_read_lock();
+       exports = rhltable_lookup(&obd->obd_nid_hash, &nid, nid_hash_params);
+       if (!exports) {
+               ret = -ENODEV;
+               goto out_unlock;
+       }
+
+       rhl_for_each_entry_rcu(exp, tmp, exports, exp_nid_hash) {
+               if (cb(exp, data))
+                       ret++;
+       }
+
+out_unlock:
+       rcu_read_unlock();
+       return ret;
+}
+EXPORT_SYMBOL(obd_nid_export_for_each);
 #endif /* HAVE_SERVER_SUPPORT */
 
 /*********** string parsing utils *********/
@@ -582,7 +695,6 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
         * other fns check that status, and we're not actually set up yet.
         */
        obd->obd_starting = 1;
-       obd->obd_nid_hash = NULL;
        obd->obd_nid_stats_hash = NULL;
        obd->obd_gen_hash = NULL;
        spin_unlock(&obd->obd_dev_lock);
@@ -592,15 +704,10 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
        if (err)
                GOTO(err_starting, err);
 
+#ifdef HAVE_SERVER_SUPPORT
        /* create a nid-export lustre hash */
-       obd->obd_nid_hash = cfs_hash_create("NID_HASH",
-                                           HASH_NID_CUR_BITS,
-                                           HASH_NID_MAX_BITS,
-                                           HASH_NID_BKT_BITS, 0,
-                                           CFS_HASH_MIN_THETA,
-                                           CFS_HASH_MAX_THETA,
-                                           &nid_hash_ops, CFS_HASH_DEFAULT);
-       if (!obd->obd_nid_hash)
+       err = rhltable_init(&obd->obd_nid_hash, &nid_hash_params);
+       if (err)
                GOTO(err_uuid_hash, err = -ENOMEM);
 
        /* create a nid-stats lustre hash */
@@ -625,10 +732,15 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
                                            &gen_hash_ops, CFS_HASH_DEFAULT);
        if (!obd->obd_gen_hash)
                GOTO(err_nid_stats_hash, err = -ENOMEM);
+#endif /* HAVE_SERVER_SUPPORT */
 
        err = obd_setup(obd, lcfg);
        if (err)
+#ifdef HAVE_SERVER_SUPPORT
                GOTO(err_gen_hash, err);
+#else
+               GOTO(err_uuid_hash, err);
+#endif /* ! HAVE_SERVER_SUPPORT */
 
        obd->obd_set_up = 1;
 
@@ -642,6 +754,7 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
 
        RETURN(0);
 
+#ifdef HAVE_SERVER_SUPPORT
 err_gen_hash:
        if (obd->obd_gen_hash) {
                cfs_hash_putref(obd->obd_gen_hash);
@@ -653,10 +766,8 @@ err_nid_stats_hash:
                obd->obd_nid_stats_hash = NULL;
        }
 err_nid_hash:
-       if (obd->obd_nid_hash) {
-               cfs_hash_putref(obd->obd_nid_hash);
-               obd->obd_nid_hash = NULL;
-       }
+       rhltable_destroy(&obd->obd_nid_hash);
+#endif /* HAVE_SERVER_SUPPORT */
 err_uuid_hash:
        rhashtable_destroy(&obd->obd_uuid_hash);
 err_starting:
@@ -782,12 +893,9 @@ int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
        /* destroy an uuid-export hash body */
        rhashtable_free_and_destroy(&obd->obd_uuid_hash, obd_export_exit,
                                    NULL);
-
+#ifdef HAVE_SERVER_SUPPORT
        /* destroy a nid-export hash body */
-       if (obd->obd_nid_hash) {
-               cfs_hash_putref(obd->obd_nid_hash);
-               obd->obd_nid_hash = NULL;
-       }
+       rhltable_free_and_destroy(&obd->obd_nid_hash, nid_export_exit, NULL);
 
        /* destroy a nid-stats hash body */
        if (obd->obd_nid_stats_hash) {
@@ -800,7 +908,7 @@ int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
                cfs_hash_putref(obd->obd_gen_hash);
                obd->obd_gen_hash = NULL;
        }
-
+#endif /* HAVE_SERVER_SUPPORT */
        class_decref(obd, "setup", obd);
        obd->obd_set_up = 0;
 
@@ -2225,80 +2333,17 @@ out:
 }
 EXPORT_SYMBOL(class_manual_cleanup);
 
+#ifdef HAVE_SERVER_SUPPORT
 /*
- * nid<->export hash operations
+ * nid<->nidstats hash operations
  */
 static unsigned
-nid_hash(struct cfs_hash *hs, const void *key, unsigned mask)
+nidstats_hash(struct cfs_hash *hs, const void *key, unsigned int mask)
 {
        return cfs_hash_djb2_hash(key, sizeof(lnet_nid_t), mask);
 }
 
 static void *
-nid_key(struct hlist_node *hnode)
-{
-       struct obd_export *exp;
-
-       exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
-
-       RETURN(&exp->exp_connection->c_peer.nid);
-}
-
-/*
- * NOTE: It is impossible to find an export that is in failed
- *       state with this function
- */
-static int
-nid_kepcmp(const void *key, struct hlist_node *hnode)
-{
-       struct obd_export *exp;
-
-       LASSERT(key);
-       exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
-
-       RETURN(exp->exp_connection->c_peer.nid == *(lnet_nid_t *)key &&
-              !exp->exp_failed);
-}
-
-static void *
-nid_export_object(struct hlist_node *hnode)
-{
-       return hlist_entry(hnode, struct obd_export, exp_nid_hash);
-}
-
-static void
-nid_export_get(struct cfs_hash *hs, struct hlist_node *hnode)
-{
-       struct obd_export *exp;
-
-       exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
-       class_export_get(exp);
-}
-
-static void
-nid_export_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
-{
-       struct obd_export *exp;
-
-       exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
-       class_export_put(exp);
-}
-
-static struct cfs_hash_ops nid_hash_ops = {
-       .hs_hash        = nid_hash,
-       .hs_key         = nid_key,
-       .hs_keycmp      = nid_kepcmp,
-       .hs_object      = nid_export_object,
-       .hs_get         = nid_export_get,
-       .hs_put_locked  = nid_export_put_locked,
-};
-
-
-/*
- * nid<->nidstats hash operations
- */
-
-static void *
 nidstats_key(struct hlist_node *hnode)
 {
        struct nid_stat *ns;
@@ -2339,7 +2384,7 @@ nidstats_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
 }
 
 static struct cfs_hash_ops nid_stat_hash_ops = {
-       .hs_hash        = nid_hash,
+       .hs_hash        = nidstats_hash,
        .hs_key         = nidstats_key,
        .hs_keycmp      = nidstats_keycmp,
        .hs_object      = nidstats_object,
@@ -2416,3 +2461,5 @@ static struct cfs_hash_ops gen_hash_ops = {
        .hs_get         = gen_export_get,
        .hs_put_locked  = gen_export_put_locked,
 };
+
+#endif /* HAVE_SERVER_SUPPORT */