staging: lustre: convert obd uuid hash to rhashtable
authorNeilBrown <neilb@suse.com>
Wed, 11 Apr 2018 21:54:48 +0000 (07:54 +1000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 23 Apr 2018 13:07:41 +0000 (15:07 +0200)
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>
drivers/staging/lustre/lustre/include/lustre_export.h
drivers/staging/lustre/lustre/include/obd.h
drivers/staging/lustre/lustre/include/obd_support.h
drivers/staging/lustre/lustre/obdclass/genops.c
drivers/staging/lustre/lustre/obdclass/obd_config.c

index 19ce13b..79ad5aa 100644 (file)
@@ -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;
        /**
index 7e1de03..0d0420e 100644 (file)
@@ -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"
index 730a6ee..a4c7a2e 100644 (file)
@@ -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) */
index 86e2247..af233b8 100644 (file)
@@ -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--;
index eab0376..ffc1814 100644 (file)
 
 #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,
-};