staging: lustre: convert obd uuid hash to rhashtable
The rhashtable data type is a perfect fit for the export uuid hash table, so use that instead of cfs_hash (which will eventually be removed). As rhashtable supports lookups and insertions in atomic context, there is no need to drop a spinlock while inserting a new entry, which simplifies code quite a bit. As there are no simple lookups on this hash table (only insertions which might fail and take a spinlock), there is no need to use rcu to free the exports. Signed-off-by: NeilBrown <neilb@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
055ed193b1
commit
4206c444e4
@ -89,7 +89,7 @@ struct obd_export {
|
||||
struct list_head exp_obd_chain;
|
||||
/** work_struct for destruction of export */
|
||||
struct work_struct exp_zombie_work;
|
||||
struct hlist_node exp_uuid_hash; /** uuid-export hash*/
|
||||
struct rhash_head exp_uuid_hash; /** uuid-export hash*/
|
||||
/** Obd device of this export */
|
||||
struct obd_device *exp_obd;
|
||||
/**
|
||||
|
@ -558,7 +558,7 @@ struct obd_device {
|
||||
*/
|
||||
unsigned long obd_recovery_expired:1;
|
||||
/* uuid-export hash body */
|
||||
struct cfs_hash *obd_uuid_hash;
|
||||
struct rhashtable obd_uuid_hash;
|
||||
wait_queue_head_t obd_refcount_waitq;
|
||||
struct list_head obd_exports;
|
||||
struct list_head obd_unlinked_exports;
|
||||
@ -622,6 +622,9 @@ struct obd_device {
|
||||
struct completion obd_kobj_unregister;
|
||||
};
|
||||
|
||||
int obd_uuid_add(struct obd_device *obd, struct obd_export *export);
|
||||
void obd_uuid_del(struct obd_device *obd, struct obd_export *export);
|
||||
|
||||
/* get/set_info keys */
|
||||
#define KEY_ASYNC "async"
|
||||
#define KEY_CHANGELOG_CLEAR "changelog_clear"
|
||||
|
@ -61,9 +61,6 @@ extern atomic_long_t obd_dirty_transit_pages;
|
||||
extern char obd_jobid_var[];
|
||||
|
||||
/* Some hash init argument constants */
|
||||
#define HASH_UUID_BKT_BITS 5
|
||||
#define HASH_UUID_CUR_BITS 7
|
||||
#define HASH_UUID_MAX_BITS 12
|
||||
/* Timeout definitions */
|
||||
#define OBD_TIMEOUT_DEFAULT 100
|
||||
/* Time to wait for all clients to reconnect during recovery (hard limit) */
|
||||
|
@ -713,7 +713,6 @@ struct obd_export *class_new_export(struct obd_device *obd,
|
||||
struct obd_uuid *cluuid)
|
||||
{
|
||||
struct obd_export *export;
|
||||
struct cfs_hash *hash = NULL;
|
||||
int rc = 0;
|
||||
|
||||
export = kzalloc(sizeof(*export), GFP_NOFS);
|
||||
@ -740,7 +739,6 @@ struct obd_export *class_new_export(struct obd_device *obd,
|
||||
class_handle_hash(&export->exp_handle, &export_handle_ops);
|
||||
spin_lock_init(&export->exp_lock);
|
||||
spin_lock_init(&export->exp_rpc_lock);
|
||||
INIT_HLIST_NODE(&export->exp_uuid_hash);
|
||||
spin_lock_init(&export->exp_bl_list_lock);
|
||||
INIT_LIST_HEAD(&export->exp_bl_list);
|
||||
INIT_WORK(&export->exp_zombie_work, obd_zombie_exp_cull);
|
||||
@ -757,44 +755,24 @@ struct obd_export *class_new_export(struct obd_device *obd,
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
hash = cfs_hash_getref(obd->obd_uuid_hash);
|
||||
if (!hash) {
|
||||
rc = -ENODEV;
|
||||
goto exit_unlock;
|
||||
}
|
||||
spin_unlock(&obd->obd_dev_lock);
|
||||
|
||||
if (!obd_uuid_equals(cluuid, &obd->obd_uuid)) {
|
||||
rc = cfs_hash_add_unique(hash, cluuid, &export->exp_uuid_hash);
|
||||
if (rc != 0) {
|
||||
rc = obd_uuid_add(obd, export);
|
||||
if (rc) {
|
||||
LCONSOLE_WARN("%s: denying duplicate export for %s, %d\n",
|
||||
obd->obd_name, cluuid->uuid, rc);
|
||||
rc = -EALREADY;
|
||||
goto exit_err;
|
||||
goto exit_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock(&obd->obd_dev_lock);
|
||||
if (obd->obd_stopping) {
|
||||
cfs_hash_del(hash, cluuid, &export->exp_uuid_hash);
|
||||
rc = -ENODEV;
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
class_incref(obd, "export", export);
|
||||
list_add(&export->exp_obd_chain, &export->exp_obd->obd_exports);
|
||||
export->exp_obd->obd_num_exports++;
|
||||
spin_unlock(&obd->obd_dev_lock);
|
||||
cfs_hash_putref(hash);
|
||||
return export;
|
||||
|
||||
exit_unlock:
|
||||
spin_unlock(&obd->obd_dev_lock);
|
||||
exit_err:
|
||||
if (hash)
|
||||
cfs_hash_putref(hash);
|
||||
class_handle_unhash(&export->exp_handle);
|
||||
LASSERT(hlist_unhashed(&export->exp_uuid_hash));
|
||||
obd_destroy_export(export);
|
||||
kfree(export);
|
||||
return ERR_PTR(rc);
|
||||
@ -807,10 +785,8 @@ void class_unlink_export(struct obd_export *exp)
|
||||
|
||||
spin_lock(&exp->exp_obd->obd_dev_lock);
|
||||
/* delete an uuid-export hashitem from hashtables */
|
||||
if (!hlist_unhashed(&exp->exp_uuid_hash))
|
||||
cfs_hash_del(exp->exp_obd->obd_uuid_hash,
|
||||
&exp->exp_client_uuid,
|
||||
&exp->exp_uuid_hash);
|
||||
if (exp != exp->exp_obd->obd_self_export)
|
||||
obd_uuid_del(exp->exp_obd, exp);
|
||||
|
||||
list_move(&exp->exp_obd_chain, &exp->exp_obd->obd_unlinked_exports);
|
||||
exp->exp_obd->obd_num_exports--;
|
||||
|
@ -48,7 +48,69 @@
|
||||
|
||||
#include "llog_internal.h"
|
||||
|
||||
static struct cfs_hash_ops uuid_hash_ops;
|
||||
/*
|
||||
* uuid<->export lustre hash operations
|
||||
*/
|
||||
/*
|
||||
* NOTE: It is impossible to find an export that is in failed
|
||||
* state with this function
|
||||
*/
|
||||
static int
|
||||
uuid_keycmp(struct rhashtable_compare_arg *arg, const void *obj)
|
||||
{
|
||||
const struct obd_uuid *uuid = arg->key;
|
||||
const struct obd_export *exp = obj;
|
||||
|
||||
if (obd_uuid_equals(uuid, &exp->exp_client_uuid) &&
|
||||
!exp->exp_failed)
|
||||
return 0;
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
static void
|
||||
uuid_export_exit(void *vexport, void *data)
|
||||
{
|
||||
struct obd_export *exp = vexport;
|
||||
|
||||
class_export_put(exp);
|
||||
}
|
||||
|
||||
static const struct rhashtable_params uuid_hash_params = {
|
||||
.key_len = sizeof(struct obd_uuid),
|
||||
.key_offset = offsetof(struct obd_export, exp_client_uuid),
|
||||
.head_offset = offsetof(struct obd_export, exp_uuid_hash),
|
||||
.obj_cmpfn = uuid_keycmp,
|
||||
.automatic_shrinking = true,
|
||||
};
|
||||
|
||||
int obd_uuid_add(struct obd_device *obd, struct obd_export *export)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = rhashtable_lookup_insert_fast(&obd->obd_uuid_hash,
|
||||
&export->exp_uuid_hash,
|
||||
uuid_hash_params);
|
||||
if (rc == 0)
|
||||
class_export_get(export);
|
||||
else if (rc == -EEXIST)
|
||||
rc = -EALREADY;
|
||||
else
|
||||
/* map obscure error codes to -ENOMEM */
|
||||
rc = -ENOMEM;
|
||||
return rc;
|
||||
}
|
||||
|
||||
void obd_uuid_del(struct obd_device *obd, struct obd_export *export)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = rhashtable_remove_fast(&obd->obd_uuid_hash,
|
||||
&export->exp_uuid_hash,
|
||||
uuid_hash_params);
|
||||
|
||||
if (rc == 0)
|
||||
class_export_put(export);
|
||||
}
|
||||
|
||||
/*********** string parsing utils *********/
|
||||
|
||||
@ -347,26 +409,18 @@ static 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_uuid_hash = NULL;
|
||||
spin_unlock(&obd->obd_dev_lock);
|
||||
|
||||
/* create an uuid-export lustre hash */
|
||||
obd->obd_uuid_hash = cfs_hash_create("UUID_HASH",
|
||||
HASH_UUID_CUR_BITS,
|
||||
HASH_UUID_MAX_BITS,
|
||||
HASH_UUID_BKT_BITS, 0,
|
||||
CFS_HASH_MIN_THETA,
|
||||
CFS_HASH_MAX_THETA,
|
||||
&uuid_hash_ops, CFS_HASH_DEFAULT);
|
||||
if (!obd->obd_uuid_hash) {
|
||||
err = -ENOMEM;
|
||||
err = rhashtable_init(&obd->obd_uuid_hash, &uuid_hash_params);
|
||||
|
||||
if (err)
|
||||
goto err_hash;
|
||||
}
|
||||
|
||||
exp = class_new_export(obd, &obd->obd_uuid);
|
||||
if (IS_ERR(exp)) {
|
||||
err = PTR_ERR(exp);
|
||||
goto err_hash;
|
||||
goto err_new;
|
||||
}
|
||||
|
||||
obd->obd_self_export = exp;
|
||||
@ -392,11 +446,9 @@ err_exp:
|
||||
class_unlink_export(obd->obd_self_export);
|
||||
obd->obd_self_export = NULL;
|
||||
}
|
||||
err_new:
|
||||
rhashtable_destroy(&obd->obd_uuid_hash);
|
||||
err_hash:
|
||||
if (obd->obd_uuid_hash) {
|
||||
cfs_hash_putref(obd->obd_uuid_hash);
|
||||
obd->obd_uuid_hash = NULL;
|
||||
}
|
||||
obd->obd_starting = 0;
|
||||
CERROR("setup %s failed (%d)\n", obd->obd_name, err);
|
||||
return err;
|
||||
@ -490,10 +542,7 @@ static int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
|
||||
obd->obd_name, err);
|
||||
|
||||
/* destroy an uuid-export hash body */
|
||||
if (obd->obd_uuid_hash) {
|
||||
cfs_hash_putref(obd->obd_uuid_hash);
|
||||
obd->obd_uuid_hash = NULL;
|
||||
}
|
||||
rhashtable_free_and_destroy(&obd->obd_uuid_hash, uuid_export_exit, NULL);
|
||||
|
||||
class_decref(obd, "setup", obd);
|
||||
obd->obd_set_up = 0;
|
||||
@ -1487,73 +1536,3 @@ out:
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(class_manual_cleanup);
|
||||
|
||||
/*
|
||||
* uuid<->export lustre hash operations
|
||||
*/
|
||||
|
||||
static unsigned int
|
||||
uuid_hash(struct cfs_hash *hs, const void *key, unsigned int mask)
|
||||
{
|
||||
return cfs_hash_djb2_hash(((struct obd_uuid *)key)->uuid,
|
||||
sizeof(((struct obd_uuid *)key)->uuid), mask);
|
||||
}
|
||||
|
||||
static void *
|
||||
uuid_key(struct hlist_node *hnode)
|
||||
{
|
||||
struct obd_export *exp;
|
||||
|
||||
exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
|
||||
|
||||
return &exp->exp_client_uuid;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: It is impossible to find an export that is in failed
|
||||
* state with this function
|
||||
*/
|
||||
static int
|
||||
uuid_keycmp(const void *key, struct hlist_node *hnode)
|
||||
{
|
||||
struct obd_export *exp;
|
||||
|
||||
LASSERT(key);
|
||||
exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
|
||||
|
||||
return obd_uuid_equals(key, &exp->exp_client_uuid) &&
|
||||
!exp->exp_failed;
|
||||
}
|
||||
|
||||
static void *
|
||||
uuid_export_object(struct hlist_node *hnode)
|
||||
{
|
||||
return hlist_entry(hnode, struct obd_export, exp_uuid_hash);
|
||||
}
|
||||
|
||||
static void
|
||||
uuid_export_get(struct cfs_hash *hs, struct hlist_node *hnode)
|
||||
{
|
||||
struct obd_export *exp;
|
||||
|
||||
exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
|
||||
class_export_get(exp);
|
||||
}
|
||||
|
||||
static void
|
||||
uuid_export_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
|
||||
{
|
||||
struct obd_export *exp;
|
||||
|
||||
exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
|
||||
class_export_put(exp);
|
||||
}
|
||||
|
||||
static struct cfs_hash_ops uuid_hash_ops = {
|
||||
.hs_hash = uuid_hash,
|
||||
.hs_key = uuid_key,
|
||||
.hs_keycmp = uuid_keycmp,
|
||||
.hs_object = uuid_export_object,
|
||||
.hs_get = uuid_export_get,
|
||||
.hs_put_locked = uuid_export_put_locked,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user