Whamcloud - gitweb
LU-9338 hsm: cache agent record locations 01/26901/5
authorJohn L. Hammond <john.hammond@intel.com>
Tue, 23 Feb 2016 17:26:00 +0000 (11:26 -0600)
committerOleg Drokin <oleg.drokin@intel.com>
Sat, 3 Jun 2017 03:55:39 +0000 (03:55 +0000)
Create a cookie indexed hash of record locations for the agent actions
log. Use this cache to avoid linear scans of the log in HSM RPC
handlers that must update given entries of the log.

Signed-off-by: John L. Hammond <john.hammond@intel.com>
Change-Id: I1b9bb0746e88fb0bed81fe1174b5d3c7abac1211
Reviewed-by: Mike Pershin <mike.pershin@intel.com>
Reviewed-by: Faccini Bruno <bruno.faccini@intel.com>
Signed-off-by: Minh Diep <minh.diep@intel.com>
Reviewed-on: https://review.whamcloud.com/26901
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Ben Evans <bevans@cray.com>
Reviewed-by: Quentin Bouget <quentin.bouget@cea.fr>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/mdt/mdt_coordinator.c
lustre/mdt/mdt_hsm_cdt_actions.c
lustre/mdt/mdt_hsm_cdt_client.c
lustre/mdt/mdt_internal.h

index 55c4cc5..3e43a16 100644 (file)
@@ -269,6 +269,11 @@ static int mdt_coordinator_cb(const struct lu_env *env,
 
                request->hal_used_sz += cfs_size_round(hai->hai_len);
                request->hal->hal_count++;
 
                request->hal_used_sz += cfs_size_round(hai->hai_len);
                request->hal->hal_count++;
+
+               if (hai->hai_action != HSMA_CANCEL)
+                       cdt_agent_record_hash_add(cdt, hai->hai_cookie,
+                                                 llh->lgh_hdr->llh_cat_idx,
+                                                 hdr->lrh_index);
                break;
        }
        case ARS_STARTED: {
                break;
        }
        case ARS_STARTED: {
@@ -324,6 +329,8 @@ static int mdt_coordinator_cb(const struct lu_env *env,
                         * to the client, for which an error will be
                         * sent back, leading to an endless cycle of
                         * cancellation. */
                         * to the client, for which an error will be
                         * sent back, leading to an endless cycle of
                         * cancellation. */
+                       cdt_agent_record_hash_del(cdt,
+                                                 larr->arr_hai.hai_cookie);
                        RETURN(LLOG_DEL_RECORD);
                }
 
                        RETURN(LLOG_DEL_RECORD);
                }
 
@@ -343,8 +350,11 @@ static int mdt_coordinator_cb(const struct lu_env *env,
        case ARS_CANCELED:
        case ARS_SUCCEED:
                if ((larr->arr_req_change + cdt->cdt_grace_delay) <
        case ARS_CANCELED:
        case ARS_SUCCEED:
                if ((larr->arr_req_change + cdt->cdt_grace_delay) <
-                   cfs_time_current_sec())
+                   cfs_time_current_sec()) {
+                       cdt_agent_record_hash_del(cdt,
+                                                 larr->arr_hai.hai_cookie);
                        RETURN(LLOG_DEL_RECORD);
                        RETURN(LLOG_DEL_RECORD);
+               }
                break;
        }
        RETURN(0);
                break;
        }
        RETURN(0);
@@ -568,7 +578,7 @@ static int mdt_coordinator(void *data)
                hsd.request_cnt = 0;
 
                rc = cdt_llog_process(mti->mti_env, mdt, mdt_coordinator_cb,
                hsd.request_cnt = 0;
 
                rc = cdt_llog_process(mti->mti_env, mdt, mdt_coordinator_cb,
-                                     &hsd, WRITE);
+                                     &hsd, 0, 0, WRITE);
                if (rc < 0)
                        goto clean_cb_alloc;
 
                if (rc < 0)
                        goto clean_cb_alloc;
 
@@ -782,8 +792,8 @@ static int mdt_hsm_pending_restore(struct mdt_thread_info *mti)
 
        hrd.hrd_mti = mti;
 
 
        hrd.hrd_mti = mti;
 
-       rc = cdt_llog_process(mti->mti_env, mti->mti_mdt,
-                             hsm_restore_cb, &hrd, WRITE);
+       rc = cdt_llog_process(mti->mti_env, mti->mti_mdt, hsm_restore_cb, &hrd,
+                             0, 0, READ);
 
        RETURN(rc);
 }
 
        RETURN(rc);
 }
@@ -869,9 +879,21 @@ int mdt_hsm_cdt_init(struct mdt_device *mdt)
        if (cdt->cdt_request_cookie_hash == NULL)
                RETURN(-ENOMEM);
 
        if (cdt->cdt_request_cookie_hash == NULL)
                RETURN(-ENOMEM);
 
+       cdt->cdt_agent_record_hash = cfs_hash_create("AGENT_RECORD_HASH",
+                                                    CFS_HASH_BITS_MIN,
+                                                    CFS_HASH_BITS_MAX,
+                                                    CFS_HASH_BKT_BITS,
+                                                    0 /* extra bytes */,
+                                                    CFS_HASH_MIN_THETA,
+                                                    CFS_HASH_MAX_THETA,
+                                                    &cdt_agent_record_hash_ops,
+                                                    CFS_HASH_DEFAULT);
+       if (cdt->cdt_agent_record_hash == NULL)
+               GOTO(out_request_cookie_hash, rc = -ENOMEM);
+
        rc = lu_env_init(&cdt->cdt_env, LCT_MD_THREAD);
        if (rc < 0)
        rc = lu_env_init(&cdt->cdt_env, LCT_MD_THREAD);
        if (rc < 0)
-               GOTO(out_request_cookie_hash, rc);
+               GOTO(out_agent_record_hash, rc);
 
        /* for mdt_ucred(), lu_ucred stored in lu_ucred_key */
        rc = lu_context_init(&cdt->cdt_session, LCT_SERVER_SESSION);
 
        /* for mdt_ucred(), lu_ucred stored in lu_ucred_key */
        rc = lu_context_init(&cdt->cdt_session, LCT_SERVER_SESSION);
@@ -902,6 +924,9 @@ int mdt_hsm_cdt_init(struct mdt_device *mdt)
 
 out_env:
        lu_env_fini(&cdt->cdt_env);
 
 out_env:
        lu_env_fini(&cdt->cdt_env);
+out_agent_record_hash:
+       cfs_hash_putref(cdt->cdt_agent_record_hash);
+       cdt->cdt_agent_record_hash = NULL;
 out_request_cookie_hash:
        cfs_hash_putref(cdt->cdt_request_cookie_hash);
        cdt->cdt_request_cookie_hash = NULL;
 out_request_cookie_hash:
        cfs_hash_putref(cdt->cdt_request_cookie_hash);
        cdt->cdt_request_cookie_hash = NULL;
@@ -923,6 +948,9 @@ int  mdt_hsm_cdt_fini(struct mdt_device *mdt)
 
        lu_env_fini(&cdt->cdt_env);
 
 
        lu_env_fini(&cdt->cdt_env);
 
+       cfs_hash_putref(cdt->cdt_agent_record_hash);
+       cdt->cdt_agent_record_hash = NULL;
+
        cfs_hash_putref(cdt->cdt_request_cookie_hash);
        cdt->cdt_request_cookie_hash = NULL;
 
        cfs_hash_putref(cdt->cdt_request_cookie_hash);
        cdt->cdt_request_cookie_hash = NULL;
 
@@ -1694,8 +1722,8 @@ static int hsm_cancel_all_actions(struct mdt_device *mdt)
        /* cancel all on-disk records */
        hcad.mdt = mdt;
 
        /* cancel all on-disk records */
        hcad.mdt = mdt;
 
-       rc = cdt_llog_process(mti->mti_env, mti->mti_mdt,
-                             mdt_cancel_all_cb, &hcad, WRITE);
+       rc = cdt_llog_process(mti->mti_env, mti->mti_mdt, mdt_cancel_all_cb,
+                             &hcad, 0, 0, WRITE);
 out_cdt_state:
        /* Enable coordinator, unless the coordinator was stopping. */
        set_cdt_state(cdt, old_state, NULL);
 out_cdt_state:
        /* Enable coordinator, unless the coordinator was stopping. */
        set_cdt_state(cdt, old_state, NULL);
index 94bc265..abb3e6a 100644 (file)
@@ -36,6 +36,8 @@
 
 #define DEBUG_SUBSYSTEM S_MDS
 
 
 #define DEBUG_SUBSYSTEM S_MDS
 
+#include <libcfs/libcfs.h>
+#include <libcfs/libcfs_hash.h>
 #include <obd_support.h>
 #include <lustre_export.h>
 #include <obd.h>
 #include <obd_support.h>
 #include <lustre_export.h>
 #include <obd.h>
 #include <lustre_log.h>
 #include "mdt_internal.h"
 
 #include <lustre_log.h>
 #include "mdt_internal.h"
 
+struct cdt_agent_record_loc {
+       struct hlist_node carl_hnode;
+       atomic_t carl_refcount;
+       u64 carl_cookie;
+       u32 carl_cat_idx;
+       u32 carl_rec_idx;
+};
+
+static inline void cdt_agent_record_loc_get(struct cdt_agent_record_loc *carl)
+{
+       LASSERT(atomic_read(&carl->carl_refcount) > 0);
+       atomic_inc(&carl->carl_refcount);
+}
+
+static inline void cdt_agent_record_loc_put(struct cdt_agent_record_loc *carl)
+{
+       LASSERT(atomic_read(&carl->carl_refcount) > 0);
+       if (atomic_dec_and_test(&carl->carl_refcount))
+               OBD_FREE_PTR(carl);
+}
+
+static unsigned int
+cdt_agent_record_hash(struct cfs_hash *hs, const void *key, unsigned int mask)
+{
+       return cfs_hash_djb2_hash(key, sizeof(u64), mask);
+}
+
+static void *cdt_agent_record_object(struct hlist_node *hnode)
+{
+       return hlist_entry(hnode, struct cdt_agent_record_loc, carl_hnode);
+}
+
+static void *cdt_agent_record_key(struct hlist_node *hnode)
+{
+       struct cdt_agent_record_loc *carl = cdt_agent_record_object(hnode);
+
+       return &carl->carl_cookie;
+}
+
+static int cdt_agent_record_keycmp(const void *key, struct hlist_node *hnode)
+{
+       const u64 *cookie2 = cdt_agent_record_key(hnode);
+
+       return *(const u64 *)key == *cookie2;
+}
+
+static void cdt_agent_record_get(struct cfs_hash *hs, struct hlist_node *hnode)
+{
+       struct cdt_agent_record_loc *carl = cdt_agent_record_object(hnode);
+
+       cdt_agent_record_loc_get(carl);
+}
+
+static void cdt_agent_record_put(struct cfs_hash *hs, struct hlist_node *hnode)
+{
+       struct cdt_agent_record_loc *carl = cdt_agent_record_object(hnode);
+
+       cdt_agent_record_loc_put(carl);
+}
+
+struct cfs_hash_ops cdt_agent_record_hash_ops = {
+       .hs_hash        = cdt_agent_record_hash,
+       .hs_key         = cdt_agent_record_key,
+       .hs_keycmp      = cdt_agent_record_keycmp,
+       .hs_object      = cdt_agent_record_object,
+       .hs_get         = cdt_agent_record_get,
+       .hs_put_locked  = cdt_agent_record_put,
+};
+
+void cdt_agent_record_hash_add(struct coordinator *cdt, u64 cookie, u32 cat_idx,
+                              u32 rec_idx)
+{
+       struct cdt_agent_record_loc *carl0;
+       struct cdt_agent_record_loc *carl1;
+
+       OBD_ALLOC_PTR(carl1);
+       if (carl1 == NULL)
+               return;
+
+       INIT_HLIST_NODE(&carl1->carl_hnode);
+       atomic_set(&carl1->carl_refcount, 1);
+       carl1->carl_cookie = cookie;
+       carl1->carl_cat_idx = cat_idx;
+       carl1->carl_rec_idx = rec_idx;
+
+       carl0 = cfs_hash_findadd_unique(cdt->cdt_agent_record_hash,
+                                       &carl1->carl_cookie,
+                                       &carl1->carl_hnode);
+
+       LASSERT(carl0->carl_cookie == carl1->carl_cookie);
+       LASSERT(carl0->carl_cat_idx == carl1->carl_cat_idx);
+       LASSERT(carl0->carl_rec_idx == carl1->carl_rec_idx);
+
+       if (carl0 != carl1)
+               cdt_agent_record_loc_put(carl0);
+
+       cdt_agent_record_loc_put(carl1);
+}
+
+void cdt_agent_record_hash_lookup(struct coordinator *cdt, u64 cookie,
+                                 u32 *cat_idx, u32 *rec_idx)
+{
+       struct cdt_agent_record_loc *carl;
+
+       carl = cfs_hash_lookup(cdt->cdt_agent_record_hash, &cookie);
+       if (carl != NULL) {
+               LASSERT(carl->carl_cookie == cookie);
+               *cat_idx = carl->carl_cat_idx;
+               *rec_idx = carl->carl_rec_idx;
+               cdt_agent_record_loc_put(carl);
+       } else {
+               *cat_idx = 0;
+               *rec_idx = 0;
+       }
+}
+
+void cdt_agent_record_hash_del(struct coordinator *cdt, u64 cookie)
+{
+       cfs_hash_del_key(cdt->cdt_agent_record_hash, &cookie);
+}
+
 void dump_llog_agent_req_rec(const char *prefix,
                             const struct llog_agent_req_rec *larr)
 {
 void dump_llog_agent_req_rec(const char *prefix,
                             const struct llog_agent_req_rec *larr)
 {
@@ -81,11 +204,14 @@ void dump_llog_agent_req_rec(const char *prefix,
  * \param cb [IN] llog callback funtion
  * \param data [IN] llog callback  data
  * \param rw [IN] cdt_llog_lock mode (READ or WRITE)
  * \param cb [IN] llog callback funtion
  * \param data [IN] llog callback  data
  * \param rw [IN] cdt_llog_lock mode (READ or WRITE)
+ * \param start_cat_idx first catalog index to examine
+ * \param start_rec_idx first record index to examine
  * \retval 0 success
  * \retval -ve failure
  */
 int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt,
  * \retval 0 success
  * \retval -ve failure
  */
 int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt,
-                    llog_cb_t cb, void *data, int rw)
+                    llog_cb_t cb, void *data, u32 start_cat_idx,
+                    u32 start_rec_idx, int rw)
 {
        struct obd_device       *obd = mdt2obd_dev(mdt);
        struct llog_ctxt        *lctxt = NULL;
 {
        struct obd_device       *obd = mdt2obd_dev(mdt);
        struct llog_ctxt        *lctxt = NULL;
@@ -102,7 +228,8 @@ int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt,
        else
                down_write(&cdt->cdt_llog_lock);
 
        else
                down_write(&cdt->cdt_llog_lock);
 
-       rc = llog_cat_process(env, lctxt->loc_handle, cb, data, 0, 0);
+       rc = llog_cat_process(env, lctxt->loc_handle, cb, data, start_cat_idx,
+                             start_rec_idx);
        if (rc < 0)
                CERROR("%s: failed to process HSM_ACTIONS llog (rc=%d)\n",
                        mdt_obd_name(mdt), rc);
        if (rc < 0)
                CERROR("%s: failed to process HSM_ACTIONS llog (rc=%d)\n",
                        mdt_obd_name(mdt), rc);
@@ -273,9 +400,37 @@ int mdt_agent_record_update(const struct lu_env *env, struct mdt_device *mdt,
                            enum agent_req_status status)
 {
        struct data_update_cb    ducb;
                            enum agent_req_status status)
 {
        struct data_update_cb    ducb;
-       int                      rc;
+       u32 start_cat_idx = -1;
+       u32 start_rec_idx = -1;
+       u32 cat_idx;
+       u32 rec_idx;
+       int i;
+       int rc;
        ENTRY;
 
        ENTRY;
 
+       /* Find the first location (start_cat_idx, start_rec_idx)
+        * among the records corresponding to cookies. */
+       for (i = 0; i < cookies_count; i++) {
+               /* If we cannot find a cached location for a cookie
+                * (perhaps because the MDT was restart then we must
+                * start from the beginning. In this case
+                * mdt_agent_record_hash_get() sets both of cat_idx and
+                * rec_idx to 0. */
+               cdt_agent_record_hash_lookup(&mdt->mdt_coordinator, cookies[i],
+                                            &cat_idx, &rec_idx);
+               if (cat_idx < start_cat_idx) {
+                       start_cat_idx = cat_idx;
+                       start_rec_idx = rec_idx;
+               } else if (cat_idx == start_cat_idx &&
+                          rec_idx < start_rec_idx) {
+                       start_rec_idx = rec_idx;
+               }
+       }
+
+       /* Fixup starting record index for llog_cat_process(). */
+       if (start_rec_idx != 0)
+               start_rec_idx -= 1;
+
        ducb.mdt = mdt;
        ducb.cookies = cookies;
        ducb.cookies_count = cookies_count;
        ducb.mdt = mdt;
        ducb.cookies = cookies;
        ducb.cookies_count = cookies_count;
@@ -284,7 +439,7 @@ int mdt_agent_record_update(const struct lu_env *env, struct mdt_device *mdt,
        ducb.change_time = cfs_time_current_sec();
 
        rc = cdt_llog_process(env, mdt, mdt_agent_record_update_cb, &ducb,
        ducb.change_time = cfs_time_current_sec();
 
        rc = cdt_llog_process(env, mdt, mdt_agent_record_update_cb, &ducb,
-                             WRITE);
+                             start_cat_idx, start_rec_idx, WRITE);
        if (rc < 0)
                CERROR("%s: cdt_llog_process() failed, rc=%d, cannot update "
                       "status to %s for %d cookies, done %d\n",
        if (rc < 0)
                CERROR("%s: cdt_llog_process() failed, rc=%d, cannot update "
                       "status to %s for %d cookies, done %d\n",
index 3ccb802..a2be524 100644 (file)
@@ -154,7 +154,8 @@ static int hsm_find_compatible(const struct lu_env *env, struct mdt_device *mdt,
        hcdcb.cdt = &mdt->mdt_coordinator;
        hcdcb.hal = hal;
 
        hcdcb.cdt = &mdt->mdt_coordinator;
        hcdcb.hal = hal;
 
-       rc = cdt_llog_process(env, mdt, hsm_find_compatible_cb, &hcdcb, READ);
+       rc = cdt_llog_process(env, mdt, hsm_find_compatible_cb, &hcdcb, 0, 0,
+                             READ);
 
        RETURN(rc);
 }
 
        RETURN(rc);
 }
index db40237..5810af8 100644 (file)
@@ -167,6 +167,11 @@ struct coordinator {
                                                       * agents */
        struct list_head         cdt_restore_hdl;     /**< list of restore lock
                                                       * handles */
                                                       * agents */
        struct list_head         cdt_restore_hdl;     /**< list of restore lock
                                                       * handles */
+
+       /* Hash of cookies to locations of record locations in agent
+        * request log. */
+       struct cfs_hash         *cdt_agent_record_hash;
+
        /* Bitmasks indexed by the HSMA_XXX constants. */
        __u64                    cdt_user_request_mask;
        __u64                    cdt_group_request_mask;
        /* Bitmasks indexed by the HSMA_XXX constants. */
        __u64                    cdt_user_request_mask;
        __u64                    cdt_group_request_mask;
@@ -823,13 +828,19 @@ extern const struct file_operations mdt_hsm_actions_fops;
 void dump_llog_agent_req_rec(const char *prefix,
                             const struct llog_agent_req_rec *larr);
 int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt,
 void dump_llog_agent_req_rec(const char *prefix,
                             const struct llog_agent_req_rec *larr);
 int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt,
-                    llog_cb_t cb, void *data, int rw);
+                    llog_cb_t cb, void *data, u32 start_cat_idx,
+                    u32 start_rec_idx, int rw);
 int mdt_agent_record_add(const struct lu_env *env, struct mdt_device *mdt,
                         __u64 compound_id, __u32 archive_id,
                         __u64 flags, struct hsm_action_item *hai);
 int mdt_agent_record_update(const struct lu_env *env,
                            struct mdt_device *mdt, __u64 *cookies,
                            int cookies_count, enum agent_req_status status);
 int mdt_agent_record_add(const struct lu_env *env, struct mdt_device *mdt,
                         __u64 compound_id, __u32 archive_id,
                         __u64 flags, struct hsm_action_item *hai);
 int mdt_agent_record_update(const struct lu_env *env,
                            struct mdt_device *mdt, __u64 *cookies,
                            int cookies_count, enum agent_req_status status);
+void cdt_agent_record_hash_add(struct coordinator *cdt, u64 cookie, u32 cat_idt,
+                              u32 rec_idx);
+void cdt_agent_record_hash_lookup(struct coordinator *cdt, u64 cookie,
+                                 u32 *cat_idt, u32 *rec_idx);
+void cdt_agent_record_hash_del(struct coordinator *cdt, u64 cookie);
 
 /* mdt/mdt_hsm_cdt_agent.c */
 extern const struct file_operations mdt_hsm_agent_fops;
 
 /* mdt/mdt_hsm_cdt_agent.c */
 extern const struct file_operations mdt_hsm_agent_fops;
@@ -859,6 +870,7 @@ bool mdt_hsm_restore_is_running(struct mdt_thread_info *mti,
                                const struct lu_fid *fid);
 /* mdt/mdt_hsm_cdt_requests.c */
 extern struct cfs_hash_ops cdt_request_cookie_hash_ops;
                                const struct lu_fid *fid);
 /* mdt/mdt_hsm_cdt_requests.c */
 extern struct cfs_hash_ops cdt_request_cookie_hash_ops;
+extern struct cfs_hash_ops cdt_agent_record_hash_ops;
 extern const struct file_operations mdt_hsm_active_requests_fops;
 void dump_requests(char *prefix, struct coordinator *cdt);
 struct cdt_agent_req *mdt_cdt_alloc_request(__u64 compound_id, __u32 archive_id,
 extern const struct file_operations mdt_hsm_active_requests_fops;
 void dump_requests(char *prefix, struct coordinator *cdt);
 struct cdt_agent_req *mdt_cdt_alloc_request(__u64 compound_id, __u32 archive_id,