From 580ef453d1d6f901c3227a037137a7db9e600009 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Mon, 18 May 2020 18:10:10 -0400 Subject: [PATCH] LU-8130 obd: convert obd_nid_hash to rhashtable 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 Change-Id: I45154ceb48336b20161f771d986d8fe7333b9849 Reviewed-on: https://review.whamcloud.com/33518 Reviewed-by: Neil Brown Reviewed-by: Shaun Tancheff Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/include/lustre_export.h | 5 +- lustre/include/obd.h | 8 +- lustre/include/obd_support.h | 3 - lustre/ldlm/ldlm_flock.c | 31 +++-- lustre/ldlm/ldlm_lib.c | 13 +- lustre/mdt/mdt_lproc.c | 11 +- lustre/obdclass/genops.c | 71 +++++----- lustre/obdclass/lprocfs_status_server.c | 87 +++++-------- lustre/obdclass/obd_config.c | 221 +++++++++++++++++++------------- 9 files changed, 240 insertions(+), 210 deletions(-) diff --git a/lustre/include/lustre_export.h b/lustre/include/lustre_export.h index f6e136a..3ba56cb 100644 --- a/lustre/include/lustre_export.h +++ b/lustre/include/lustre_export.h @@ -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 */ diff --git a/lustre/include/obd.h b/lustre/include/obd.h index 9da2f12..4e585ad 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -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 */ diff --git a/lustre/include/obd_support.h b/lustre/include/obd_support.h index e8a99d5..69477d8 100644 --- a/lustre/include/obd_support.h +++ b/lustre/include/obd_support.h @@ -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 diff --git a/lustre/ldlm/ldlm_flock.c b/lustre/ldlm/ldlm_flock.c index 7866d3f..007d00ad 100644 --- a/lustre/ldlm/ldlm_flock.c +++ b/lustre/ldlm/ldlm_flock.c @@ -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; diff --git a/lustre/ldlm/ldlm_lib.c b/lustre/ldlm/ldlm_lib.c index 3139aaa..b0649fd 100644 --- a/lustre/ldlm/ldlm_lib.c +++ b/lustre/ldlm/ldlm_lib.c @@ -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); diff --git a/lustre/mdt/mdt_lproc.c b/lustre/mdt/mdt_lproc.c index 71b6943..e483884 100644 --- a/lustre/mdt/mdt_lproc.c +++ b/lustre/mdt/mdt_lproc.c @@ -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) diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index d4feb7c..18818af 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -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; diff --git a/lustre/obdclass/lprocfs_status_server.c b/lustre/obdclass/lprocfs_status_server.c index 9c38196..a8602c7 100644 --- a/lustre/obdclass/lprocfs_status_server.c +++ b/lustre/obdclass/lprocfs_status_server.c @@ -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; } diff --git a/lustre/obdclass/obd_config.c b/lustre/obdclass/obd_config.c index aef076f..882784a 100644 --- a/lustre/obdclass/obd_config.c +++ b/lustre/obdclass/obd_config.c @@ -49,9 +49,10 @@ #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 */ -- 1.8.3.1