Whamcloud - gitweb
LU-18556 hsm: optimize llog record modification 28/57428/18
authorAlexander Boyko <alexander.boyko@hpe.com>
Fri, 13 Dec 2024 12:57:17 +0000 (13:57 +0100)
committerOleg Drokin <green@whamcloud.com>
Thu, 12 Jun 2025 06:31:51 +0000 (06:31 +0000)
This commit introduces a new llog modification mechanism for HSM
operations to address inefficiencies caused by prior reliance on
catalog processing. The new approach directly modifies llog record,
eliminating the need for catalog-based processing and reducing
latency.

Key changes include:
* Replacing the hsm_action_item (HAI) with a full in-memory llog
 record representation, increasing memory usage by ~80 bytes per
 record but removing the need for a dedicated llog cookie hash
 table.
* Unifying the coordinator's read/store logic for HAI data into a
 single in-memory item shared by mdt_hsm_agent_send() and
 mdt_hsm_add_hsr(). This reduces memory allocation steps: only one
 cdt_agent_req allocation is now required during llog read
 operations, eliminating subsequent allocations/copies.

Performance results on VMs 2 MDTs/2 OSTs/2 Clients no-op copytool:
Test 1 (1M archive requests): 572s -> 187s (~3 times faster)
Test 2 (1M archive + 1M queued): 558s -> 392s (~1.4 times faster)

HPE-bug-id: LUS-12583
Signed-off-by: Alexander Boyko <alexander.boyko@hpe.com>
Change-Id: I4b6e697bc3b1f0cf2c76f5433b49affbc933c653
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/57428
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Nikitas Angelinas <nikitas.angelinas@hpe.com>
Reviewed-by: Etienne AUJAMES <eaujames@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/lustre_log.h
lustre/include/uapi/linux/lustre/lustre_idl.h
lustre/mdt/mdt_coordinator.c
lustre/mdt/mdt_hsm_cdt_actions.c
lustre/mdt/mdt_hsm_cdt_agent.c
lustre/mdt/mdt_hsm_cdt_requests.c
lustre/mdt/mdt_internal.h
lustre/mgs/mgs_llog.c
lustre/obdclass/llog.c
lustre/obdclass/llog_cat.c
lustre/obdclass/llog_osd.c

index 31d0305..a88b13e 100644 (file)
@@ -164,6 +164,9 @@ int llog_cat_reverse_process(const struct lu_env *env,
                             void *data);
 int llog_cat_retain_cb(const struct lu_env *env, struct llog_handle *cat,
                       struct llog_rec_hdr *rec, void *data);
+int llog_cat_modify_rec(const struct lu_env *env, struct llog_handle *cathandle,
+                       struct llog_logid *lid, struct llog_rec_hdr *hdr,
+                       struct llog_cookie *cookie);
 /* llog_obd.c */
 int llog_setup(const struct lu_env *env, struct obd_device *obd,
               struct obd_llog_group *olg, int index,
@@ -600,7 +603,7 @@ int llog_open_create(const struct lu_env *env, struct llog_ctxt *ctxt,
                     char *name);
 int llog_erase(const struct lu_env *env, struct llog_ctxt *ctxt,
               struct llog_logid *logid, char *name);
-int llog_get_cookie(const struct lu_env *env, struct llog_cookie *out);
+void llog_get_cookie(const struct lu_env *env, struct llog_cookie *out);
 int llog_write_cookie(const struct lu_env *env, struct llog_handle *loghandle,
                      struct llog_rec_hdr *rec, struct llog_cookie *cookie,
                      int idx);
index cc59756..ef4bc35 100644 (file)
@@ -2920,6 +2920,12 @@ struct llog_rec_tail {
        __u32   lrt_index;
 } __attribute__((packed));
 
+static inline struct llog_rec_tail *llog_get_rec_tail(struct llog_rec_hdr *rec)
+{
+       return (struct llog_rec_tail *)((char *)rec + rec->lrh_len -
+                                       sizeof(struct llog_rec_tail));
+}
+
 /* Where data follow just after header */
 #define REC_DATA(ptr)                                          \
        ((void *)((char *)ptr + sizeof(struct llog_rec_hdr)))
index a1d113c..ec2411c 100644 (file)
@@ -104,16 +104,6 @@ void mdt_hsm_dump_hal(int level, const char *prefix,
        }
 }
 
-/**
- * data passed to llog_cat_process() callback
- * to scan requests and take actions
- */
-struct hsm_scan_request {
-       int                      hal_sz;
-       int                      hal_used_sz;
-       struct hsm_action_list  *hal;
-};
-
 struct hsm_scan_data {
        struct mdt_thread_info  *hsd_mti;
        char                     hsd_fsname[MTI_NAME_MAXLEN + 1];
@@ -130,6 +120,32 @@ struct hsm_scan_data {
        struct hsm_scan_request *hsd_request;
 };
 
+static inline int mdt_cdt_check_rec(struct llog_agent_req_rec *rec, size_t size)
+{
+       ENTRY;
+
+       if (rec->arr_hdr.lrh_len > size ||
+           rec->arr_hdr.lrh_len < sizeof(*rec) ||
+           rec->arr_hdr.lrh_type != HSM_AGENT_REC ||
+           rec->arr_hdr.lrh_index !=
+           llog_get_rec_tail(&rec->arr_hdr)->lrt_index ||
+           rec->arr_hdr.lrh_len != llog_get_rec_tail(&rec->arr_hdr)->lrt_len)
+               RETURN(-EBADR);
+
+       if (rec->arr_status > ARS_SUCCEED)
+               RETURN(-EBADR);
+
+       if (rec->arr_hai.hai_len > rec->arr_hdr.lrh_len ||
+           rec->arr_hai.hai_len < sizeof(rec->arr_hai) ||
+           (rec->arr_hai.hai_action != HSMA_NONE &&
+            rec->arr_hai.hai_action < HSMA_ARCHIVE &&
+            rec->arr_hai.hai_action > HSMA_CANCEL) ||
+           rec->arr_hai.hai_cookie == 0)
+               RETURN(-EBADR);
+
+       RETURN(0);
+}
+
 static int mdt_cdt_waiting_cb(const struct lu_env *env,
                              struct mdt_device *mdt,
                              struct llog_handle *llh,
@@ -138,7 +154,9 @@ static int mdt_cdt_waiting_cb(const struct lu_env *env,
 {
        struct coordinator *cdt = &mdt->mdt_coordinator;
        struct hsm_scan_request *request;
-       struct hsm_action_item *hai;
+       struct cdt_agent_req *car;
+       struct obd_uuid uuid = {.uuid = {0}};
+       struct llog_cookie cookie;
        size_t hai_size;
        u32 archive_id;
        bool wrapped;
@@ -165,11 +183,10 @@ static int mdt_cdt_waiting_cb(const struct lu_env *env,
        hai_size = round_up(larr->arr_hai.hai_len, 8);
        archive_id = larr->arr_archive_id;
 
-       /* Can we add this action to one of the existing HALs in hsd. */
        request = NULL;
        for (i = 0; i < hsd->hsd_request_count; i++) {
-               if (hsd->hsd_request[i].hal->hal_archive_id == archive_id &&
-                   hsd->hsd_request[i].hal_used_sz + hai_size <=
+               if (hsr_get_archive_id(&hsd->hsd_request[i]) == archive_id &&
+                   hsd->hsd_request[i].hsr_used_sz + hai_size <=
                    LDLM_MAXREQSIZE) {
                        request = &hsd->hsd_request[i];
                        break;
@@ -182,7 +199,7 @@ static int mdt_cdt_waiting_cb(const struct lu_env *env,
                /* Is there really no compatible hsm_scan_request? */
                if (!request) {
                        for (i -= 1; i >= 0; i--) {
-                               if (hsd->hsd_request[i].hal->hal_archive_id ==
+                               if (hsr_get_archive_id(&hsd->hsd_request[i]) ==
                                    archive_id) {
                                        request = &hsd->hsd_request[i];
                                        break;
@@ -190,30 +207,40 @@ static int mdt_cdt_waiting_cb(const struct lu_env *env,
                        }
                }
 
-               /* Make room for the hai */
+               /* Make room for the car */
                if (request) {
-                       /* Discard the last hai until there is enough space */
+                       /* Discard the last car until there is enough space */
                        do {
-                               request->hal->hal_count--;
+                               request->hsr_count--;
 
-                               hai = hai_first(request->hal);
-                               for (i = 0; i < request->hal->hal_count; i++)
-                                       hai = hai_next(hai);
-                               request->hal_used_sz -=
-                                       round_up(hai->hai_len, 8);
+                               car = list_last_entry(&request->hsr_cars,
+                                                     struct cdt_agent_req,
+                                                     car_scan_list);
+                               list_del_init(&car->car_scan_list);
+
+                               request->hsr_used_sz -=
+                                       round_up(car->car_hai.hai_len, 8);
+
+                               mdt_cdt_put_request(car);
                                hsd->hsd_action_count--;
-                       } while (request->hal_used_sz + hai_size >
+                       } while (request->hsr_used_sz + hai_size >
                                 LDLM_MAXREQSIZE);
                } else if (hsd->hsd_housekeeping) {
                        struct hsm_scan_request *tmp;
+                       struct cdt_agent_req *pos;
+                       struct cdt_agent_req *tmp2;
 
-                       /* Discard the (whole) last hal */
+                       /* Discard the (whole) records from request */
                        hsd->hsd_request_count--;
                        LASSERT(hsd->hsd_request_count >= 0);
                        tmp = &hsd->hsd_request[hsd->hsd_request_count];
-                       hsd->hsd_action_count -= tmp->hal->hal_count;
+                       hsd->hsd_action_count -= tmp->hsr_count;
                        LASSERT(hsd->hsd_action_count >= 0);
-                       OBD_FREE(tmp->hal, tmp->hal_sz);
+                       list_for_each_entry_safe(pos, tmp2, &tmp->hsr_cars,
+                                                car_scan_list) {
+                               list_del_init(&pos->car_scan_list);
+                               mdt_cdt_put_request(pos);
+                       }
                } else {
                        /* Bailing out, this code path is too hot */
                        RETURN(LLOG_PROC_BREAK);
@@ -222,66 +249,47 @@ static int mdt_cdt_waiting_cb(const struct lu_env *env,
        }
 
        if (!request) {
-               size_t count = round_up(MTI_NAME_MAXLEN + 1, 8) + 2 * hai_size;
-               struct hsm_action_list *hal;
-
                LASSERT(hsd->hsd_request_count < hsd->hsd_request_len);
                request = &hsd->hsd_request[hsd->hsd_request_count];
 
-               /* allocates hai vector size just needs to be large
-                * enough */
-               request->hal_sz = sizeof(*request->hal) + count;
-               OBD_ALLOC_LARGE(hal, request->hal_sz);
-               if (!hal)
-                       RETURN(-ENOMEM);
-
-               hal->hal_version = HAL_VERSION;
-               strscpy(hal->hal_fsname, hsd->hsd_fsname, MTI_NAME_MAXLEN + 1);
-               hal->hal_archive_id = larr->arr_archive_id;
-               hal->hal_flags = larr->arr_flags;
-               hal->hal_count = 0;
-               request->hal_used_sz = hal_size(hal);
-               request->hal = hal;
+               INIT_LIST_HEAD(&request->hsr_cars);
+               request->hsr_fsname = &hsd->hsd_fsname[0];
+               request->hsr_version = HAL_VERSION;
+               request->hsr_count = 0;
+               request->hsr_used_sz = sizeof(struct hsm_action_list) +
+                       __ALIGN_KERNEL(strlen(hsd->hsd_fsname) + 1, 8);
                hsd->hsd_request_count++;
-       } else if (request->hal_sz < request->hal_used_sz + hai_size) {
-               /* Not enough room, need an extension */
-               void *hal_buffer;
-               int sz;
-
-               sz = min_t(int, 2 * request->hal_sz, LDLM_MAXREQSIZE);
-               LASSERT(request->hal_used_sz + hai_size < sz);
-
-               OBD_ALLOC_LARGE(hal_buffer, sz);
-               if (!hal_buffer)
-                       RETURN(-ENOMEM);
-
-               memcpy(hal_buffer, request->hal, request->hal_used_sz);
-               OBD_FREE_LARGE(request->hal, request->hal_sz);
-               request->hal = hal_buffer;
-               request->hal_sz = sz;
        }
 
-       hai = hai_first(request->hal);
-       for (i = 0; i < request->hal->hal_count; i++)
-               hai = hai_next(hai);
+       cookie.lgc_offset = 0;
+       llog_get_cookie(env, &cookie);
+       LASSERTF(cookie.lgc_offset >= llh->lgh_hdr->llh_size,
+                "Bad record offset %llx for idx %d", cookie.lgc_offset,
+                larr->arr_hdr.lrh_index);
 
-       memcpy(hai, &larr->arr_hai, larr->arr_hai.hai_len);
+       car = mdt_cdt_alloc_request(&uuid, larr);
+       if (IS_ERR(car))
+               RETURN(PTR_ERR(car));
 
-       request->hal_used_sz += hai_size;
-       request->hal->hal_count++;
+       car->car_hmm->mr_offset = cookie.lgc_offset;
+       car->car_hmm->mr_lid = llh->lgh_id;
+       list_add_tail(&car->car_scan_list, &request->hsr_cars);
 
+       CDEBUG(D_HSM, "Copying record %d to request %px, count %d\n",
+              larr->arr_hdr.lrh_index, request, request->hsr_count);
+
+       request->hsr_count++;
+       request->hsr_used_sz += hai_size;
        hsd->hsd_action_count++;
 
-       switch (hai->hai_action) {
+       switch (car->car_hmm->mr_rec.arr_hai.hai_action) {
        case HSMA_CANCEL:
                break;
        case HSMA_RESTORE:
                hsd->hsd_one_restore = true;
                fallthrough;
        default:
-               cdt_agent_record_hash_add(cdt, hai->hai_cookie,
-                                         llh->lgh_hdr->llh_cat_idx,
-                                         larr->arr_hdr.lrh_index);
+               break;
        }
 
        wrapped = llh->lgh_hdr->llh_cat_idx >= llh->lgh_last_idx &&
@@ -408,12 +416,22 @@ static int mdt_coordinator_cb(const struct lu_env *env,
        struct hsm_scan_data *hsd = data;
        struct mdt_device *mdt = hsd->hsd_mti->mti_mdt;
        struct coordinator *cdt = &mdt->mdt_coordinator;
+       int rc;
+
        ENTRY;
 
        if (cdt->cdt_state == CDT_DISABLE)
                RETURN(-ECANCELED);
 
        larr = (struct llog_agent_req_rec *)hdr;
+       rc = mdt_cdt_check_rec(larr, larr->arr_hdr.lrh_len);
+       if (rc) {
+               CDEBUG(D_HSM, "%s: bad llog record "DOSTID" idx %d, rc = %d\n",
+                      llh->lgh_ctxt->loc_obd->obd_name,
+                      POSTID(&llh->lgh_id.lgl_oi), larr->arr_hdr.lrh_index,
+                      rc);
+               RETURN(LLOG_DEL_RECORD);
+       }
        dump_llog_agent_req_rec("mdt_coordinator_cb(): ", larr);
        switch (larr->arr_status) {
        case ARS_WAITING:
@@ -426,8 +444,6 @@ static int mdt_coordinator_cb(const struct lu_env *env,
 
                if ((larr->arr_req_change + cdt->cdt_grace_delay) <
                    ktime_get_real_seconds()) {
-                       cdt_agent_record_hash_del(cdt,
-                                                 larr->arr_hai.hai_cookie);
                        RETURN(LLOG_DEL_RECORD);
                }
 
@@ -487,7 +503,7 @@ static void mdt_hsm_cdt_cleanup(struct mdt_device *mdt)
        list_for_each_entry_safe(car, tmp1, &cdt->cdt_request_list,
                                 car_request_list) {
                cfs_hash_del(cdt->cdt_request_cookie_hash,
-                            &car->car_hai->hai_cookie,
+                            &car->car_hai.hai_cookie,
                             &car->car_cookie_hash);
                list_del(&car->car_request_list);
                mdt_cdt_put_request(car);
@@ -641,12 +657,8 @@ static int mdt_coordinator(void *data)
 
        while (1) {
                int i;
-               int update_idx = 0;
-               int updates_sz;
-               int updates_cnt;
                u32 start_cat_idx;
                u32 start_rec_idx;
-               struct hsm_record_update *updates;
 
                if (cdt->cdt_state == CDT_DISABLE) {
                        cdt->cdt_idle = true;
@@ -749,32 +761,9 @@ static int mdt_coordinator(void *data)
                        goto clean_cb_alloc;
                }
 
-               /* Compute how many HAI we have in all the requests */
-               updates_cnt = 0;
-               for (i = 0; i < hsd.hsd_request_count; i++) {
-                       const struct hsm_scan_request *request =
-                               &hsd.hsd_request[i];
-
-                       updates_cnt += request->hal->hal_count;
-               }
-
-               /* Allocate a temporary array to store the cookies to
-                * update, and their status. */
-               updates_sz = updates_cnt * sizeof(*updates);
-               OBD_ALLOC_LARGE(updates, updates_sz);
-               if (updates == NULL) {
-                       CERROR("%s: Cannot allocate memory (%d bytes) "
-                               "for %d updates. Too many HSM requests?\n",
-                              mdt_obd_name(mdt), updates_sz, updates_cnt);
-                       goto clean_cb_alloc;
-               }
-
                /* here hsd contains a list of requests to be started */
                for (i = 0; i < hsd.hsd_request_count; i++) {
                        struct hsm_scan_request *request = &hsd.hsd_request[i];
-                       struct hsm_action_list  *hal = request->hal;
-                       struct hsm_action_item  *hai;
-                       int                      j;
 
                        /* still room for work ? */
                        if (atomic_read(&cdt->cdt_request_count) >=
@@ -785,27 +774,14 @@ static int mdt_coordinator(void *data)
                         * assumes that other records are cancelled
                         */
                        if (cdt->cdt_state == CDT_DISABLE)
-                               goto update_recs;
-
+                               goto clean_cb_alloc;
 
-                       rc = mdt_hsm_agent_send(mti, hal, 0);
+                       rc = mdt_hsm_agent_send(mti, request, 0);
                        /* if failure, we suppose it is temporary
                         * if the copy tool failed to do the request
                         * it has to use hsm_progress
                         */
 
-                       /* set up cookie vector to set records status
-                        * after copy tools start or failed
-                        */
-                       hai = hai_first(hal);
-                       for (j = 0; j < hal->hal_count; j++) {
-                               updates[update_idx].cookie = hai->hai_cookie;
-                               updates[update_idx].status =
-                                       (rc ? ARS_WAITING : ARS_STARTED);
-                               hai = hai_next(hai);
-                               update_idx++;
-                       }
-
                        /* TODO: narrow down the HSM action range that already
                         * scanned accroding to the cookies when a failure
                         * occurs.
@@ -816,24 +792,19 @@ static int mdt_coordinator(void *data)
                        }
                }
 
-update_recs:
-               if (update_idx) {
-                       rc = mdt_agent_record_update(mti, updates, update_idx);
-                       if (rc)
-                               CERROR("%s: mdt_agent_record_update() failed, "
-                                      "rc=%d, cannot update records "
-                                      "for %d cookies\n",
-                                      mdt_obd_name(mdt), rc, update_idx);
-               }
-
-               OBD_FREE_LARGE(updates, updates_sz);
-
 clean_cb_alloc:
                /* free hal allocated by callback */
                for (i = 0; i < hsd.hsd_request_count; i++) {
                        struct hsm_scan_request *request = &hsd.hsd_request[i];
+                       struct cdt_agent_req *pos;
+                       struct cdt_agent_req *tmp;
+
+                       list_for_each_entry_safe(pos, tmp, &request->hsr_cars,
+                                                car_scan_list) {
+                               list_del_init(&pos->car_scan_list);
+                               mdt_cdt_put_request(pos);
+                       }
 
-                       OBD_FREE_LARGE(request->hal, request->hal_sz);
                }
        }
 
@@ -1124,21 +1095,9 @@ int mdt_hsm_cdt_init(struct mdt_device *mdt)
        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)
-               GOTO(out_agent_record_hash, rc);
+               GOTO(out_request_cookie_hash, rc);
 
        /* for mdt_ucred(), lu_ucred stored in lu_ucred_key */
        rc = lu_context_init(&cdt->cdt_session, LCT_SERVER_SESSION);
@@ -1173,9 +1132,6 @@ int mdt_hsm_cdt_init(struct mdt_device *mdt)
 
 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;
@@ -1197,9 +1153,6 @@ int  mdt_hsm_cdt_fini(struct mdt_device *mdt)
 
        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;
 
@@ -1329,27 +1282,32 @@ out:
 }
 
 /**
- * register all requests from an hal in the memory list
+ * register all agent requests from a scan phase
  * \param mti [IN] context
- * \param hal [IN] request
+ * \param rq [IN] request
  * \param uuid [OUT] in case of CANCEL, the uuid of the agent
  *  which is running the CT
  * \retval 0 success
  * \retval -ve failure
  */
-int mdt_hsm_add_hal(struct mdt_thread_info *mti,
-                   struct hsm_action_list *hal, struct obd_uuid *uuid)
+int mdt_hsm_add_hsr(struct mdt_thread_info *mti, struct hsm_scan_request *rq,
+                   struct obd_uuid *uuid)
 {
        struct mdt_device       *mdt = mti->mti_mdt;
        struct coordinator      *cdt = &mdt->mdt_coordinator;
+       struct cdt_agent_req *car;
+       struct hsm_mem_req_rec  *hmm;
        struct hsm_action_item  *hai;
-       int                      rc = 0, i;
+       int                      rc = 0;
        ENTRY;
 
        /* register request in memory list */
-       hai = hai_first(hal);
-       for (i = 0; i < hal->hal_count; i++, hai = hai_next(hai)) {
-               struct cdt_agent_req *car;
+       list_for_each_entry(car, &rq->hsr_cars, car_scan_list) {
+               hmm = car->car_hmm;
+               if (hmm->mr_rec.arr_status == ARS_FAILED)
+                       continue;
+
+               hai = &car->car_hai;
 
                /* in case of a cancel request, we first mark the ondisk
                 * record of the request we want to stop as canceled
@@ -1357,55 +1315,62 @@ int mdt_hsm_add_hal(struct mdt_thread_info *mti,
                 * it will be done when updating the request status
                 */
                if (hai->hai_action == HSMA_CANCEL) {
-                       struct hsm_record_update update = {
-                               .cookie = hai->hai_cookie,
-                               .status = ARS_CANCELED,
-                       };
+                       struct cdt_agent_req *orig;
+                       struct hsm_action_item *h;
+
+                       /* find the running request to set it canceled */
+                       orig = mdt_cdt_find_request(cdt, hai->hai_cookie);
+                       if (!orig)
+                               continue;
+
+                       h = &orig->car_hai;
+                       if (orig->car_cancel) {
+                               CDEBUG(D_HSM,
+                                      "%s: %llx already canceled %s "DFID"\n",
+                                      mdt_obd_name(mdt), h->hai_cookie,
+                                      hsm_copytool_action2name(h->hai_action),
+                                      PFID(&h->hai_fid));
+                               mdt_cdt_put_request(orig);
+                               continue;
+                       }
+                       orig->car_hmm->mr_rec.arr_status = ARS_CANCELED;
+
+                       rc = mdt_hsm_agent_modify_record(mti->mti_env, mdt,
+                                                        orig->car_hmm);
 
-                       rc = mdt_agent_record_update(mti, &update, 1);
                        if (rc) {
-                               CERROR("%s: mdt_agent_record_update() failed, "
-                                      "rc=%d, cannot update status to %s "
-                                      "for cookie %#llx\n",
-                                      mdt_obd_name(mdt), rc,
+                               CERROR("%s: modify record failed, cannot update status to %s for cookie %#llx : rc = %d\n",
+                                      mdt_obd_name(mdt),
                                       agent_req_status2name(ARS_CANCELED),
-                                      hai->hai_cookie);
+                                      hai->hai_cookie, rc);
+                               mdt_cdt_put_request(orig);
                                GOTO(out, rc);
                        }
 
-                       /* find the running request to set it canceled */
-                       car = mdt_cdt_find_request(cdt, hai->hai_cookie);
-                       if (car != NULL) {
-                               car->car_canceled = 1;
-                               /* uuid has to be changed to the one running the
-                               * request to cancel */
-                               *uuid = car->car_uuid;
-                               mdt_cdt_put_request(car);
-                       }
-                       /* no need to memorize cancel request
-                        * this also avoid a deadlock when we receive
-                        * a purge all requests command
+                       /* orig holding cancel request orig->car_cancel */
+                       mdt_cdt_get_request(car);
+                       /* uuid has to be changed to the one running the
+                        * request to cancel
                         */
+                       *uuid = orig->car_uuid;
+                       car->car_uuid = orig->car_uuid;
+                       orig->car_cancel = car;
                        continue;
                }
 
                if (hai->hai_action == HSMA_ARCHIVE) {
                        rc = mdt_hsm_set_exists(mti, &hai->hai_fid,
-                                               hal->hal_archive_id);
+                                               hsr_get_archive_id(rq));
                        if (rc == -ENOENT)
                                continue;
                        else if (rc < 0)
                                GOTO(out, rc);
                }
 
-               car = mdt_cdt_alloc_request(hal->hal_archive_id, hal->hal_flags,
-                                           uuid, hai);
-               if (IS_ERR(car))
-                       GOTO(out, rc = PTR_ERR(car));
-
+               car->car_uuid = *uuid;
                rc = mdt_cdt_add_request(cdt, car);
-               if (rc != 0)
-                       mdt_cdt_free_request(car);
+               if (rc)
+                       break;
        }
 out:
        RETURN(rc);
@@ -1504,7 +1469,7 @@ static int hsm_cdt_request_completed(struct mdt_thread_info *mti,
 
        /* find object by FID, mdt_hsm_get_md_hsm() returns obj or err
         * if error/removed continue anyway to get correct reporting done */
-       obj = mdt_hsm_get_md_hsm(mti, &car->car_hai->hai_fid, &mh);
+       obj = mdt_hsm_get_md_hsm(mti, &car->car_hai.hai_fid, &mh);
        /* we will update MD HSM only if needed */
        is_mh_changed = false;
 
@@ -1550,7 +1515,7 @@ static int hsm_cdt_request_completed(struct mdt_thread_info *mti,
                        rc = 0;
                }
 
-               switch (car->car_hai->hai_action) {
+               switch (car->car_hai.hai_action) {
                case HSMA_ARCHIVE:
                        hsm_set_cl_event(&clf_flags, HE_ARCHIVE);
                        break;
@@ -1573,13 +1538,13 @@ static int hsm_cdt_request_completed(struct mdt_thread_info *mti,
                               " %d is an unknown action\n",
                               mdt_obd_name(mdt),
                               pgs->hpk_cookie, PFID(&pgs->hpk_fid),
-                              car->car_hai->hai_action);
+                              car->car_hai.hai_action);
                        rc = -EINVAL;
                        break;
                }
        } else {
                *status = ARS_SUCCEED;
-               switch (car->car_hai->hai_action) {
+               switch (car->car_hai.hai_action) {
                case HSMA_ARCHIVE:
                        hsm_set_cl_event(&clf_flags, HE_ARCHIVE);
                        /* set ARCHIVE keep EXIST and clear LOST and
@@ -1618,7 +1583,7 @@ static int hsm_cdt_request_completed(struct mdt_thread_info *mti,
                        CERROR("%s: Successful request %#llx on "DFID" %d is an unknown action\n",
                               mdt_obd_name(mdt),
                               pgs->hpk_cookie, PFID(&pgs->hpk_fid),
-                              car->car_hai->hai_action);
+                              car->car_hai.hai_action);
                        rc = -EINVAL;
                        break;
                }
@@ -1640,13 +1605,13 @@ static int hsm_cdt_request_completed(struct mdt_thread_info *mti,
        /* we give back layout lock only if restore was successful or
         * if no retry will be attempted and if object is still alive,
         * in other cases we just unlock the object */
-       if (car->car_hai->hai_action == HSMA_RESTORE) {
+       if (car->car_hai.hai_action == HSMA_RESTORE) {
                struct mdt_lock_handle *lh;
 
                /* restore in data FID done, we swap the layouts
                 * only if restore is successful */
                if (pgs->hpk_errval == 0 && !IS_ERR(obj)) {
-                       rc = hsm_swap_layouts(mti, obj, &car->car_hai->hai_dfid,
+                       rc = hsm_swap_layouts(mti, obj, &car->car_hai.hai_dfid,
                                              &mh);
                        if (rc) {
                                if (cdt->cdt_policy & CDT_NORETRY_ACTION)
@@ -1663,10 +1628,10 @@ static int hsm_cdt_request_completed(struct mdt_thread_info *mti,
                 * before to give back layout lock to avoid concurrent
                 * file updater to post out of order ChangeLog */
                mo_changelog(env, CL_HSM, clf_flags, mdt->mdt_child,
-                            &car->car_hai->hai_fid);
+                            &car->car_hai.hai_fid);
                need_changelog = false;
 
-               cdt_restore_handle_del(mti, cdt, &car->car_hai->hai_fid);
+               cdt_restore_handle_del(mti, cdt, &car->car_hai.hai_fid);
                if (!IS_ERR_OR_NULL(obj)) {
                        /* flush UPDATE lock so attributes are upadated */
                        lh = &mti->mti_lh[MDT_LH_OLD];
@@ -1682,7 +1647,7 @@ out:
        /* always add a ChangeLog record */
        if (need_changelog)
                mo_changelog(env, CL_HSM, clf_flags, mdt->mdt_child,
-                            &car->car_hai->hai_fid);
+                            &car->car_hai.hai_fid);
 
        if (!IS_ERR(obj))
                mdt_object_put(mti->mti_env, obj);
@@ -1724,29 +1689,29 @@ int mdt_hsm_update_request_state(struct mdt_thread_info *mti,
        CDEBUG(D_HSM, "Progress received for fid="DFID" cookie=%#llx"
                      " action=%s flags=%d err=%d fid="DFID" dfid="DFID"\n",
                      PFID(&pgs->hpk_fid), pgs->hpk_cookie,
-                     hsm_copytool_action2name(car->car_hai->hai_action),
+                     hsm_copytool_action2name(car->car_hai.hai_action),
                      pgs->hpk_flags, pgs->hpk_errval,
-                     PFID(&car->car_hai->hai_fid),
-                     PFID(&car->car_hai->hai_dfid));
+                     PFID(&car->car_hai.hai_fid),
+                     PFID(&car->car_hai.hai_dfid));
 
        /* progress is done on FID or data FID depending of the action and
         * of the copy progress */
        /* for restore progress is used to send back the data FID to cdt */
-       if (car->car_hai->hai_action == HSMA_RESTORE &&
-           lu_fid_eq(&car->car_hai->hai_fid, &car->car_hai->hai_dfid))
-               car->car_hai->hai_dfid = pgs->hpk_fid;
-
-       if ((car->car_hai->hai_action == HSMA_RESTORE ||
-            car->car_hai->hai_action == HSMA_ARCHIVE) &&
-           (!lu_fid_eq(&pgs->hpk_fid, &car->car_hai->hai_dfid) &&
-            !lu_fid_eq(&pgs->hpk_fid, &car->car_hai->hai_fid))) {
+       if (car->car_hai.hai_action == HSMA_RESTORE &&
+           lu_fid_eq(&car->car_hai.hai_fid, &car->car_hai.hai_dfid))
+               car->car_hai.hai_dfid = pgs->hpk_fid;
+
+       if ((car->car_hai.hai_action == HSMA_RESTORE ||
+            car->car_hai.hai_action == HSMA_ARCHIVE) &&
+           (!lu_fid_eq(&pgs->hpk_fid, &car->car_hai.hai_dfid) &&
+            !lu_fid_eq(&pgs->hpk_fid, &car->car_hai.hai_fid))) {
                CERROR("%s: Progress on "DFID" for cookie %#llx"
                       " does not match request FID "DFID" nor data FID "
                       DFID"\n",
                       mdt_obd_name(mdt),
                       PFID(&pgs->hpk_fid), pgs->hpk_cookie,
-                      PFID(&car->car_hai->hai_fid),
-                      PFID(&car->car_hai->hai_dfid));
+                      PFID(&car->car_hai.hai_fid),
+                      PFID(&car->car_hai.hai_dfid));
                GOTO(out, rc = -EINVAL);
        }
 
@@ -1756,7 +1721,7 @@ int mdt_hsm_update_request_state(struct mdt_thread_info *mti,
                       " (flags=%d))\n",
                       mdt_obd_name(mdt),
                       PFID(&pgs->hpk_fid), pgs->hpk_cookie,
-                      hsm_copytool_action2name(car->car_hai->hai_action),
+                      hsm_copytool_action2name(car->car_hai.hai_action),
                       pgs->hpk_errval, pgs->hpk_flags);
                GOTO(out, rc = -EINVAL);
        }
@@ -1768,31 +1733,38 @@ int mdt_hsm_update_request_state(struct mdt_thread_info *mti,
 
        if (pgs->hpk_flags & HP_FLAG_COMPLETED) {
                enum agent_req_status status;
-               struct hsm_record_update update;
+               struct hsm_mem_req_rec *hmm;
                int rc1;
 
                rc = hsm_cdt_request_completed(mti, pgs, car, &status);
 
-               CDEBUG(D_HSM, "updating record: fid="DFID" cookie=%#llx action=%s "
-                             "status=%s\n",
+               /* if original record was canceled, need to update cancel rec */
+               if (unlikely(car->car_cancel))
+                       hmm = car->car_cancel->car_hmm;
+               else
+                       hmm = car->car_hmm;
+
+               CDEBUG(D_HSM, "updating record: fid="DFID" cookie=%#llx action=%s status=%s to %s\n",
                       PFID(&pgs->hpk_fid), pgs->hpk_cookie,
-                      hsm_copytool_action2name(car->car_hai->hai_action),
+                      hsm_copytool_action2name(hmm->mr_rec.arr_hai.hai_action),
+                      agent_req_status2name(hmm->mr_rec.arr_status),
                       agent_req_status2name(status));
 
-               /* update record first (LU-9075) */
-               update.cookie = pgs->hpk_cookie;
-               update.status = status;
+               if (hmm->mr_rec.arr_status == ARS_STARTED ||
+                   hmm->mr_rec.arr_status == ARS_WAITING) {
+                       /* update record first (LU-9075) */
+                       hmm->mr_rec.arr_status = status;
 
-               rc1 = mdt_agent_record_update(mti, &update, 1);
-               if (rc1)
-                       CERROR("%s: mdt_agent_record_update() failed,"
-                              " rc=%d, cannot update status to %s"
-                              " for cookie %#llx\n",
-                              mdt_obd_name(mdt), rc1,
-                              agent_req_status2name(status),
-                              pgs->hpk_cookie);
-               rc = (rc != 0 ? rc : rc1);
+                       rc1 = mdt_hsm_agent_modify_record(mti->mti_env, mdt,
+                                                         hmm);
 
+                       if (rc1)
+                               CERROR("%s: modify record failed, cannot update status to %s for cookie %#llx: rc = %d\n",
+                                      mdt_obd_name(mdt),
+                                      agent_req_status2name(status),
+                                      pgs->hpk_cookie, rc1);
+                       rc = (rc != 0 ? rc : rc1);
+               }
                /* then remove request from memory list (LU-9075) */
                mdt_cdt_remove_request(cdt, pgs->hpk_cookie);
 
@@ -1803,7 +1775,7 @@ int mdt_hsm_update_request_state(struct mdt_thread_info *mti,
                /* if copytool send a progress on a canceled request
                 * we inform copytool it should stop
                 */
-               if (car->car_canceled == 1)
+               if (car->car_cancel)
                        rc = -ECANCELED;
        }
        GOTO(out, rc);
@@ -1839,6 +1811,11 @@ static int mdt_cancel_all_cb(const struct lu_env *env,
        int rc;
        ENTRY;
 
+       CDEBUG(D_TRACE, "%s: HSM record idx %d "DFID" status %s\n",
+              mdt_obd_name(mti->mti_mdt), hdr->lrh_index,
+              PFID(&hai->hai_fid),
+              agent_req_status2name(larr->arr_status));
+
        if (larr->arr_status != ARS_WAITING &&
            larr->arr_status != ARS_STARTED)
                RETURN(0);
@@ -1865,15 +1842,19 @@ static int mdt_cancel_all_cb(const struct lu_env *env,
  */
 static int hsm_cancel_all_actions(struct mdt_device *mdt)
 {
-       struct lu_env                    env;
-       struct lu_context                session;
-       struct mdt_thread_info          *mti;
-       struct coordinator              *cdt = &mdt->mdt_coordinator;
-       struct cdt_agent_req            *car;
-       struct hsm_action_list          *hal = NULL;
-       struct hsm_action_item          *hai;
-       int                              hal_sz = 0, hal_len, rc;
-       enum cdt_states                  old_state;
+       struct lu_env env;
+       struct lu_context session;
+       struct mdt_thread_info *mti;
+       struct coordinator *cdt = &mdt->mdt_coordinator;
+       struct cdt_agent_req *car;
+       char fsname[MTI_NAME_MAXLEN];
+       struct hsm_scan_request rq = {
+               .hsr_version = HAL_VERSION,
+               .hsr_fsname = &fsname[0],
+               .hsr_count = 1,};
+       enum cdt_states old_state;
+       int rc;
+
        ENTRY;
 
        rc = lu_env_init(&env, LCT_MD_THREAD);
@@ -1895,6 +1876,7 @@ static int hsm_cancel_all_actions(struct mdt_device *mdt)
        mti->mti_mdt = mdt;
 
        hsm_init_ucred(mdt_ucred(mti));
+       obd_uuid2fsname(rq.hsr_fsname, mdt_obd_name(mdt), MTI_NAME_MAXLEN);
 
        mutex_lock(&cdt->cdt_state_lock);
        old_state = cdt->cdt_state;
@@ -1911,66 +1893,43 @@ static int hsm_cancel_all_actions(struct mdt_device *mdt)
        /* send cancel to all running requests */
        down_read(&cdt->cdt_request_lock);
        list_for_each_entry(car, &cdt->cdt_request_list, car_request_list) {
+               u32 action;
+
+               /* a cdt_agent_req could be at coordinator sending process
+                * still mdt_coordinator()->mdt_hsm_agent_send() in case
+                * of network resend inside ptlrpc. Skip it.
+                */
+               if (!list_empty(&car->car_scan_list))
+                       continue;
+
                mdt_cdt_get_request(car);
                /* request is not yet removed from list, it will be done
                 * when copytool will return progress
                 */
 
-               if (car->car_hai->hai_action == HSMA_CANCEL) {
+               if (car->car_hai.hai_action == HSMA_CANCEL) {
                        mdt_cdt_put_request(car);
                        continue;
                }
 
-               /* needed size */
-               hal_len = sizeof(*hal) + round_up(MTI_NAME_MAXLEN + 1, 8) +
-                         round_up(car->car_hai->hai_len, 8);
-
-               if (hal_len > hal_sz && hal_sz > 0) {
-                       /* not enough room, free old buffer */
-                       OBD_FREE(hal, hal_sz);
-                       hal = NULL;
-               }
-
-               /* empty buffer, allocate one */
-               if (hal == NULL) {
-                       hal_sz = hal_len;
-                       OBD_ALLOC(hal, hal_sz);
-                       if (hal == NULL) {
-                               mdt_cdt_put_request(car);
-                               up_read(&cdt->cdt_request_lock);
-                               GOTO(out_cdt_state, rc = -ENOMEM);
-                       }
-               }
+               INIT_LIST_HEAD(&rq.hsr_cars);
+               list_add_tail(&car->car_scan_list, &rq.hsr_cars);
+               action = car->car_hai.hai_action;
+               car->car_hai.hai_action = HSMA_CANCEL;
 
-               hal->hal_version = HAL_VERSION;
-               obd_uuid2fsname(hal->hal_fsname, mdt_obd_name(mdt),
-                               MTI_NAME_MAXLEN);
-               hal->hal_fsname[MTI_NAME_MAXLEN] = '\0';
-               hal->hal_archive_id = car->car_archive_id;
-               hal->hal_flags = car->car_flags;
-               hal->hal_count = 0;
-
-               hai = hai_first(hal);
-               memcpy(hai, car->car_hai, car->car_hai->hai_len);
-               hai->hai_action = HSMA_CANCEL;
-               hal->hal_count = 1;
-
-               /* it is possible to safely call mdt_hsm_agent_send()
-                * (ie without a deadlock on cdt_request_lock), because the
-                * write lock is taken only if we are not in purge mode
-                * (mdt_hsm_agent_send() does not call mdt_cdt_add_request()
-                *   nor mdt_cdt_remove_request())
-                */
                /* no conflict with cdt thread because cdt is disable and we
                 * have the request lock */
-               mdt_hsm_agent_send(mti, hal, 1);
+               mdt_hsm_agent_send(mti, &rq, 1);
+
+               car->car_hai.hai_action = action;
+               /* Unlock the EX layout lock */
+               if (action == HSMA_RESTORE)
+                       cdt_restore_handle_del(mti, cdt, &car->car_hai.hai_fid);
 
                mdt_cdt_put_request(car);
        }
        up_read(&cdt->cdt_request_lock);
 
-       OBD_FREE(hal, hal_sz);
-
        /* cancel all on-disk records */
        rc = cdt_llog_process(mti->mti_env, mti->mti_mdt, mdt_cancel_all_cb,
                              (void *)mti, 0, 0);
index 21256d3..2869c5d 100644 (file)
 #include <lustre_log.h>
 #include "mdt_internal.h"
 
-struct cdt_agent_record_loc {
-       struct hlist_node carl_hnode;
-       struct kref 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)
-{
-       kref_get(&carl->carl_refcount);
-}
-
-static void cdt_agent_record_loc_put_free(struct kref *kref)
-{
-       struct cdt_agent_record_loc *carl;
-
-       carl = container_of(kref, struct cdt_agent_record_loc, carl_refcount);
-       OBD_FREE_PTR(carl);
-
-}
-
-static inline void cdt_agent_record_loc_put(struct cdt_agent_record_loc *carl)
-{
-       kref_put(&carl->carl_refcount, cdt_agent_record_loc_put_free);
-}
-
-static unsigned int
-cdt_agent_record_hash(struct cfs_hash *hs, const void *key,
-                     const unsigned int bits)
-{
-       return cfs_hash_djb2_hash(key, sizeof(u64), bits);
-}
-
-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);
-       kref_init(&carl1->carl_refcount);
-       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)
 {
@@ -335,166 +207,17 @@ int mdt_agent_record_add(const struct lu_env *env, struct mdt_device *mdt,
 putctxt:
        llog_ctxt_put(lctxt);
 
+       CDEBUG(D_TRACE,
+              "%s: HSM added record idx %d "DFID" action %s: rc = %d\n",
+              mdt_obd_name(mdt), larr->arr_hdr.lrh_index, PFID(&hai->hai_fid),
+              hsm_copytool_action2name(hai->hai_action), rc);
+
        EXIT;
 free:
        OBD_FREE(larr, sz);
        return rc;
 }
 
-/**
- * data passed to llog_cat_process() callback
- * to find requests
- */
-struct data_update_cb {
-       struct mdt_thread_info *mti;
-       struct hsm_record_update *updates;
-       unsigned int updates_count;
-       unsigned int updates_done;
-       time64_t change_time;
-};
-
-/**
- *  llog_cat_process() callback, used to update a record
- * \param env [IN] environment
- * \param llh [IN] llog handle
- * \param hdr [IN] llog record
- * \param data [IN] cb data = data_update_cb
- * \retval 0 success
- * \retval -ve failure
- */
-static int mdt_agent_record_update_cb(const struct lu_env *env,
-                                     struct llog_handle *llh,
-                                     struct llog_rec_hdr *hdr,
-                                     void *data)
-{
-       struct llog_agent_req_rec *larr = (struct llog_agent_req_rec *)hdr;
-       struct hsm_action_item *hai = &larr->arr_hai;
-       struct data_update_cb *ducb = data;
-       struct mdt_thread_info *mti = ducb->mti;
-       struct mdt_device *mdt = ducb->mti->mti_mdt;
-       struct coordinator *cdt = &mdt->mdt_coordinator;
-       int rc, i;
-       ENTRY;
-
-       /* check if all done */
-       if (ducb->updates_count == ducb->updates_done)
-               RETURN(LLOG_PROC_BREAK);
-
-       /* if record is in final state, never change */
-       if (agent_req_in_final_state(larr->arr_status))
-               RETURN(0);
-
-       rc = 0;
-       for (i = 0 ; i < ducb->updates_count ; i++) {
-               struct hsm_record_update *update = &ducb->updates[i];
-
-               CDEBUG(D_HSM, "%s: search %#llx, found %#llx\n",
-                      mdt_obd_name(mdt), update->cookie,
-                      hai->hai_cookie);
-               if (hai->hai_cookie == update->cookie) {
-
-                       /* If record is a cancel request, it cannot be
-                        * canceled. This is to manage the following
-                        * case: when a request is canceled, we have 2
-                        * records with the the same cookie: the one
-                        * to cancel and the cancel request the 1st
-                        * has to be set to ARS_CANCELED and the 2nd
-                        * to ARS_SUCCEED
-                        */
-                       if (hai->hai_action == HSMA_CANCEL &&
-                           update->status == ARS_CANCELED)
-                               RETURN(0);
-
-                       larr->arr_status = update->status;
-                       larr->arr_req_change = ducb->change_time;
-                       rc = llog_write(env, llh, hdr, hdr->lrh_index);
-                       if (rc < 0)
-                               break;
-
-                       ducb->updates_done++;
-
-                       /* Unlock the EX layout lock */
-                       if (hai->hai_action == HSMA_RESTORE &&
-                           update->status == ARS_CANCELED)
-                               cdt_restore_handle_del(mti, cdt, &hai->hai_fid);
-
-                       break;
-               }
-       }
-
-       if (rc < 0)
-               CERROR("%s: mdt_agent_llog_update_rec() failed, rc = %d\n",
-                      mdt_obd_name(mdt), rc);
-
-       RETURN(rc);
-}
-
-/**
- * update an entry in agent llog
- *
- * \param env [IN] environment
- * \param mdt [IN] MDT device
- * \param updates [IN] array of entries to update
- * \param updates_count [IN] number of entries in updates
- *
- * \retval 0 on success
- * \retval negative on failure
- */
-int mdt_agent_record_update(struct mdt_thread_info *mti,
-                           struct hsm_record_update *updates,
-                           unsigned int updates_count)
-{
-       const struct lu_env *env = mti->mti_env;
-       struct mdt_device *mdt = mti->mti_mdt;
-       struct data_update_cb    ducb;
-       u32 start_cat_idx = -1;
-       u32 start_rec_idx = -1;
-       u32 cat_idx;
-       u32 rec_idx;
-       int i;
-       int rc;
-       ENTRY;
-
-       /* Find the first location (start_cat_idx, start_rec_idx)
-        * among the records corresponding to cookies. */
-       for (i = 0; i < updates_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,
-                                            updates[i].cookie,
-                                            &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.mti = mti;
-       ducb.updates = updates;
-       ducb.updates_count = updates_count;
-       ducb.updates_done = 0;
-       ducb.change_time = ktime_get_real_seconds();
-
-       rc = cdt_llog_process(env, mdt, mdt_agent_record_update_cb, &ducb,
-                             start_cat_idx, start_rec_idx);
-       if (rc < 0)
-               CERROR("%s: cdt_llog_process() failed, rc=%d, cannot update "
-                      "status for %u cookies, done %u\n",
-                      mdt_obd_name(mdt), rc,
-                      updates_count, ducb.updates_done);
-       RETURN(rc);
-}
-
 /*
  * Agent actions /proc seq_file methods
  * As llog processing uses a callback for each entry, we cannot do a sequential
index 0166557..a5e51ff 100644 (file)
@@ -21,6 +21,7 @@
 #include <lustre_export.h>
 #include <lprocfs_status.h>
 #include <lustre_kernelcomm.h>
+#include <lustre_log.h>
 #include "mdt_internal.h"
 
 /*
@@ -339,35 +340,109 @@ static int mdt_hsm_send_action_to_each_archive(struct mdt_thread_info *mti,
        RETURN(rc);
 }
 
+int mdt_hsm_agent_modify_record(const struct lu_env *env,
+                               struct mdt_device *mdt,
+                               struct hsm_mem_req_rec *hmm)
+{
+       struct obd_device *obd = mdt2obd_dev(mdt);
+       struct llog_ctxt *lctxt;
+       struct llog_cookie cookie;
+       int rc;
+
+       lctxt = llog_get_context(obd, LLOG_AGENT_ORIG_CTXT);
+       if (lctxt == NULL || lctxt->loc_handle == NULL)
+               RETURN(-ENOENT);
+
+       cookie.lgc_offset = hmm->mr_offset;
+       cookie.lgc_index = hmm->mr_rec.arr_hdr.lrh_index;
+       hmm->mr_rec.arr_req_change = ktime_get_real_seconds();
+       rc = llog_cat_modify_rec(env, lctxt->loc_handle, &hmm->mr_lid,
+                                (struct llog_rec_hdr *)&hmm->mr_rec,
+                                &cookie);
+
+       llog_ctxt_put(lctxt);
+       return rc;
+}
+
+static size_t hsr_hal_size(struct hsm_scan_request *rq)
+{
+       struct cdt_agent_req *car;
+       struct hsm_action_item *hai;
+       size_t sz;
+
+       sz = sizeof(struct hsm_action_list) +
+            __ALIGN_KERNEL(strlen(rq->hsr_fsname) + 1, 8);
+       list_for_each_entry(car, &rq->hsr_cars, car_scan_list) {
+               hai = &car->car_hai;
+               sz += __ALIGN_KERNEL(hai->hai_len, 8);
+       }
+       return sz;
+}
+
+static int hsr_hal_copy(struct hsm_scan_request *rq, void *buf, size_t buf_size)
+{
+       struct hsm_action_list *hal = buf;
+       struct cdt_agent_req *car;
+       struct hsm_action_item *hai;
+       struct hsm_action_item *shai;
+
+       hal->hal_version = rq->hsr_version;
+       strscpy(hal->hal_fsname, rq->hsr_fsname, MTI_NAME_MAXLEN + 1);
+       hal->hal_archive_id = hsr_get_archive_id(rq);
+       hal->hal_count = 0;
+
+       hai = hai_first(hal);
+       /* Copy only valid hai base on a record status */
+       list_for_each_entry(car, &rq->hsr_cars, car_scan_list) {
+               shai = &car->car_hai;
+               hal->hal_flags = car->car_flags;
+               if (car->car_hmm->mr_rec.arr_status == ARS_FAILED)
+                       continue;
+               if ((buf_size - ((char *)hai - (char *)buf)) < shai->hai_len) {
+                       CDEBUG(D_HA, "buffer overflow for hsm_action_item\n");
+                       return -EOVERFLOW;
+               }
+               memcpy(hai, shai, shai->hai_len);
+               hal->hal_count++;
+               hai = hai_next(hai);
+       }
+
+       return 0;
+}
+
 /**
- * send a HAL to the agent
+ * Checks agent records, creates a hal and sends it to the agent. Updates llog
+ * records at the end.
  * \param mti [IN] context
- * \param hal [IN] request (can be a kuc payload)
- * \param purge [IN] purge mode (no record)
+ * \param rq [IN] request
+ * \param purge [IN] purge mode (not register a record)
  * \retval 0 success
  * \retval -ve failure
  * This function supposes:
  *  - all actions are for the same archive number
  *  - in case of cancel, all cancel are for the same agent
  * This implies that request split has to be done
- *  before when building the hal
+ *  before when building the rq
  */
-int mdt_hsm_agent_send(struct mdt_thread_info *mti,
-                      struct hsm_action_list *hal, bool purge)
+int mdt_hsm_agent_send(struct mdt_thread_info *mti, struct hsm_scan_request *rq,
+                      bool purge)
 {
-       struct obd_export       *exp;
-       struct mdt_device       *mdt = mti->mti_mdt;
-       struct coordinator      *cdt = &mti->mti_mdt->mdt_coordinator;
-       struct hsm_action_list  *buf = NULL;
-       struct hsm_action_item  *hai;
-       struct obd_uuid          uuid;
-       int                      len, i, rc = 0;
-       bool                     fail_request;
-       bool                     is_registered = false;
+       struct obd_export *exp;
+       struct mdt_device *mdt = mti->mti_mdt;
+       struct coordinator *cdt = &mti->mti_mdt->mdt_coordinator;
+       struct hsm_action_list *buf = NULL;
+       struct hsm_action_item *hai;
+       struct cdt_agent_req *car;
+       struct obd_uuid uuid;
+       int len, rc = 0;
+       int fail_request = 0;
+       bool is_registered = false;
+       u32 archive_id = hsr_get_archive_id(rq);
+
        ENTRY;
 
-       rc = mdt_hsm_find_best_agent(cdt, hal->hal_archive_id, &uuid);
-       if (rc && hal->hal_archive_id == 0) {
+       rc = mdt_hsm_find_best_agent(cdt, archive_id, &uuid);
+       if (rc && archive_id == 0) {
                uint notrmcount = 0;
                int rc2 = 0;
 
@@ -380,11 +455,8 @@ int mdt_hsm_agent_send(struct mdt_thread_info *mti,
                 *     _ create a new LLOG record for each archive_id
                 *       presently being served by any CT
                 */
-               hai = hai_first(hal);
-               for (i = 0; i < hal->hal_count; i++,
-                    hai = hai_next(hai)) {
-                       struct hsm_record_update update;
-
+               list_for_each_entry(car, &rq->hsr_cars, car_scan_list) {
+                       hai = &car->car_hai;
                        /* only removes are concerned */
                        if (hai->hai_action != HSMA_REMOVE) {
                                /* count if other actions than HSMA_REMOVE,
@@ -405,102 +477,51 @@ int mdt_hsm_agent_send(struct mdt_thread_info *mti,
                         * unless a method to record already successfully
                         * reached archive_ids is implemented */
 
-                       update.cookie = hai->hai_cookie;
-                       update.status = ARS_SUCCEED;
-                       rc2 = mdt_agent_record_update(mti, &update, 1);
-                       if (rc2) {
-                               CERROR("%s: mdt_agent_record_update() "
-                                     "failed, cannot update "
-                                     "status to %s for cookie "
-                                     "%#llx: rc = %d\n",
-                                     mdt_obd_name(mdt),
-                                     agent_req_status2name(ARS_SUCCEED),
-                                     hai->hai_cookie, rc2);
-                               break;
-                       }
+                       car->car_hmm->mr_rec.arr_status = ARS_SUCCEED;
                }
                /* only remove requests with archive_id=0 */
                if (notrmcount == 0)
-                       RETURN(rc2);
+                       GOTO(update_records, rc = rc2);
 
        }
 
        if (rc) {
                CERROR("%s: Cannot find agent for archive %d: rc = %d\n",
-                      mdt_obd_name(mdt), hal->hal_archive_id, rc);
-               RETURN(rc);
+                      mdt_obd_name(mdt), archive_id, rc);
+               GOTO(update_records, rc);
        }
 
-       CDEBUG(D_HSM, "Agent %s selected for archive %d\n", obd_uuid2str(&uuid),
-              hal->hal_archive_id);
-
-       len = hal_size(hal);
-       buf = kuc_alloc(len, KUC_TRANSPORT_HSM, HMT_ACTION_LIST);
-       if (IS_ERR(buf))
-               RETURN(PTR_ERR(buf));
-       memcpy(buf, hal, len);
+       CDEBUG(D_HSM, "Agent %s selected for archive %d request %px items %d\n",
+              obd_uuid2str(&uuid), archive_id, rq, rq->hsr_count);
 
        /* Check if request is still valid (cf file hsm flags) */
-       fail_request = false;
-       hai = hai_first(hal);
-       for (i = 0; i < hal->hal_count; i++, hai = hai_next(hai)) {
+       list_for_each_entry(car, &rq->hsr_cars, car_scan_list) {
                struct mdt_object *obj;
                struct md_hsm hsm;
 
+               hai = &car->car_hai;
                if (hai->hai_action == HSMA_CANCEL)
                        continue;
 
                obj = mdt_hsm_get_md_hsm(mti, &hai->hai_fid, &hsm);
                if (!IS_ERR(obj)) {
                        mdt_object_put(mti->mti_env, obj);
-               } else if (PTR_ERR(obj) == -ENOENT) {
-                       struct hsm_record_update update = {
-                               .cookie = hai->hai_cookie,
-                               .status = ARS_FAILED,
-                       };
-
-                       if (hai->hai_action == HSMA_REMOVE)
+               } else {
+                       if (PTR_ERR(obj) == -ENOENT &&
+                           hai->hai_action == HSMA_REMOVE)
                                continue;
 
-                       fail_request = true;
-                       rc = mdt_agent_record_update(mti, &update, 1);
-                       if (rc < 0) {
-                               CERROR("%s: mdt_agent_record_update() failed, "
-                                      "cannot update status to %s for cookie "
-                                      "%#llx: rc = %d\n",
-                                      mdt_obd_name(mdt),
-                                      agent_req_status2name(ARS_FAILED),
-                                      hai->hai_cookie, rc);
-                               GOTO(out_buf, rc);
-                       }
-
+                       fail_request++;
+                       car->car_hmm->mr_rec.arr_status = ARS_FAILED;
                        continue;
-               } else {
-                       GOTO(out_buf, rc = PTR_ERR(obj));
                }
 
-               if (!mdt_hsm_is_action_compat(hai, hal->hal_archive_id,
-                                             hal->hal_flags, &hsm)) {
-                       struct hsm_record_update update = {
-                               .cookie = hai->hai_cookie,
-                               .status = ARS_FAILED,
-                       };
+               if (!mdt_hsm_is_action_compat(hai, archive_id, car->car_flags,
+                                             &hsm)) {
 
                        /* incompatible request, we abort the request */
-                       /* next time coordinator will wake up, it will
-                        * make the same HAL with valid only
-                        * records */
-                       fail_request = true;
-                       rc = mdt_agent_record_update(mti, &update, 1);
-                       if (rc) {
-                               CERROR("%s: mdt_agent_record_update() failed, "
-                                      "cannot update status to %s for cookie "
-                                      "%#llx: rc = %d\n",
-                                      mdt_obd_name(mdt),
-                                      agent_req_status2name(ARS_FAILED),
-                                      hai->hai_cookie, rc);
-                               GOTO(out_buf, rc);
-                       }
+                       fail_request++;
+                       car->car_hmm->mr_rec.arr_status = ARS_FAILED;
 
                        /* if restore and record status updated, give
                         * back granted layout lock */
@@ -509,13 +530,24 @@ int mdt_hsm_agent_send(struct mdt_thread_info *mti,
                }
        }
 
-       /* we found incompatible requests, so the HAL cannot be sent
-        * as is. Bad records have been invalidated in llog.
-        * Valid one will be reschedule next time coordinator will wake up
-        * So no need the rebuild a full valid HAL now
+       /* we found incompatible requests, so the HAL will be built only
+        * with a vaild one. Bad records have been invalidated in llog.
         */
        if (fail_request)
-               GOTO(out_buf, rc = -EAGAIN);
+               CDEBUG(D_HSM, "Some HSM actions are invalid, skipping it\n");
+
+       /* nothing to send to agent */
+       if (fail_request == rq->hsr_count)
+               GOTO(update_records, rc = 0);
+
+       len = hsr_hal_size(rq);
+       buf = kuc_alloc(len, KUC_TRANSPORT_HSM, HMT_ACTION_LIST);
+       if (IS_ERR(buf))
+               GOTO(update_records, rc = PTR_ERR(buf));
+
+       rc = hsr_hal_copy(rq, buf, len);
+       if (rc)
+               GOTO(update_records, rc);
 
        /* Cancel memory registration is useless for purge
         * non registration avoid a deadlock :
@@ -524,12 +556,10 @@ int mdt_hsm_agent_send(struct mdt_thread_info *mti,
         * by purge
         */
        if (!purge) {
-               /* set is_registered even if failure because we may have
-                * partial work done */
                is_registered = true;
-               rc = mdt_hsm_add_hal(mti, hal, &uuid);
+               rc = mdt_hsm_add_hsr(mti, rq, &uuid);
                if (rc)
-                       GOTO(out_buf, rc);
+                       GOTO(update_records, rc);
        }
 
        /* Uses the ldlm reverse import; this rpc will be seen by
@@ -546,7 +576,7 @@ int mdt_hsm_agent_send(struct mdt_thread_info *mti,
                       " rc = %d\n",
                       mdt_obd_name(mdt), obd_uuid2str(&uuid), rc);
                mdt_hsm_agent_unregister(mti, &uuid);
-               GOTO(out, rc);
+               GOTO(update_records, rc);
        }
 
        /* send request to agent */
@@ -568,19 +598,38 @@ int mdt_hsm_agent_send(struct mdt_thread_info *mti,
                mdt_hsm_agent_unregister(mti, &uuid);
        }
 
-out:
-       if (rc != 0 && is_registered) {
-               /* in case of error, we have to unregister requests */
-               hai = hai_first(hal);
-               for (i = 0; i < hal->hal_count; i++, hai = hai_next(hai)) {
-                       if (hai->hai_action == HSMA_CANCEL)
-                               continue;
+update_records:
+       /* for purge record updates do hsm_cancel_all_actions() */
+       if (purge)
+               GOTO(out_free, rc);
+
+       /* in case of error, we have to unregister requests
+        * also update request status here
+        */
+       list_for_each_entry(car, &rq->hsr_cars, car_scan_list) {
+               int rc2;
+
+               hai = &car->car_hai;
+               if (rc != 0 && hai->hai_action != HSMA_CANCEL)
                        mdt_cdt_remove_request(cdt, hai->hai_cookie);
-               }
-       }
 
-out_buf:
-       kuc_free(buf, len);
+               if (car->car_hmm->mr_rec.arr_status == ARS_WAITING && !rc)
+                       car->car_hmm->mr_rec.arr_status = ARS_STARTED;
+
+               /* update llog record with ARS_ status */
+               rc2 = mdt_hsm_agent_modify_record(mti->mti_env, mdt,
+                                                 car->car_hmm);
+               if (!rc2)
+                       continue;
+
+               CERROR("%s: modify record failed, cannot update status to %s for cookie %#llx: rc = %d\n",
+                      mdt_obd_name(mdt),
+                      agent_req_status2name(car->car_hmm->mr_rec.arr_status),
+                      hai->hai_cookie, rc2);
+       }
+out_free:
+       if (!IS_ERR_OR_NULL(buf))
+               kuc_free(buf, len);
 
        RETURN(rc);
 }
index 09662b3..829b094 100644 (file)
@@ -38,7 +38,7 @@ static void *cdt_request_cookie_key(struct hlist_node *hnode)
 {
        struct cdt_agent_req *car = cdt_request_cookie_object(hnode);
 
-       return &car->car_hai->hai_cookie;
+       return &car->car_hai.hai_cookie;
 }
 
 static int cdt_request_cookie_keycmp(const void *key, struct hlist_node *hnode)
@@ -88,16 +88,16 @@ void dump_requests(char *prefix, struct coordinator *cdt)
                       " action=%s archive#=%d flags=%#llx"
                       " extent=%#llx-%#llx"
                       " gid=%#llx refcount=%d canceled=%d\n",
-                      prefix, PFID(&car->car_hai->hai_fid),
-                      PFID(&car->car_hai->hai_dfid),
-                      car->car_hai->hai_cookie,
-                      hsm_copytool_action2name(car->car_hai->hai_action),
+                      prefix, PFID(&car->car_hai.hai_fid),
+                      PFID(&car->car_hai.hai_dfid),
+                      car->car_hai.hai_cookie,
+                      hsm_copytool_action2name(car->car_hai.hai_action),
                       car->car_archive_id, car->car_flags,
-                      car->car_hai->hai_extent.offset,
-                      car->car_hai->hai_extent.length,
-                      car->car_hai->hai_gid,
+                      car->car_hai.hai_extent.offset,
+                      car->car_hai.hai_extent.length,
+                      car->car_hai.hai_gid,
                       kref_read(&car->car_refcount),
-                      car->car_canceled);
+                      car->car_cancel ? 1 : 0);
        }
        up_read(&cdt->cdt_request_lock);
 }
@@ -199,18 +199,21 @@ static void mdt_cdt_init_request_tree(struct cdt_req_progress *crp)
                progress_iter_next(NULL, 0, 0);
 }
 
+static inline int hmmr_size(int rec_size)
+{
+       return __ALIGN_KERNEL(offsetof(struct hsm_mem_req_rec, mr_rec) +
+                             rec_size, 8);
+}
+
 /** Allocate/init an agent request and its sub-structures.
  *
- * \param archive_id [IN]
- * \param flags [IN]
  * \param uuid [IN]
- * \param hai [IN]
+ * \param rec [IN]
  * \retval car [OUT] success valid structure
- * \retval car [OUT]
+ * \retval -ve failure
  */
-struct cdt_agent_req *mdt_cdt_alloc_request(__u32 archive_id, __u64 flags,
-                                           struct obd_uuid *uuid,
-                                           struct hsm_action_item *hai)
+struct cdt_agent_req *mdt_cdt_alloc_request(struct obd_uuid *uuid,
+                                           struct llog_agent_req_rec *rec)
 {
        struct cdt_agent_req *car;
        ENTRY;
@@ -220,20 +223,15 @@ struct cdt_agent_req *mdt_cdt_alloc_request(__u32 archive_id, __u64 flags,
                RETURN(ERR_PTR(-ENOMEM));
 
        kref_init(&car->car_refcount);
-       car->car_archive_id = archive_id;
-       car->car_flags = flags;
-       car->car_canceled = 0;
-       car->car_req_start = ktime_get_real_seconds();
-       car->car_req_update = car->car_req_start;
        car->car_uuid = *uuid;
-       OBD_ALLOC(car->car_hai, hai->hai_len);
-       if (car->car_hai == NULL) {
+       OBD_ALLOC(car->car_hmm, hmmr_size(rec->arr_hdr.lrh_len));
+       if (car->car_hmm == NULL) {
                OBD_SLAB_FREE_PTR(car, mdt_hsm_car_kmem);
                RETURN(ERR_PTR(-ENOMEM));
        }
-       memcpy(car->car_hai, hai, hai->hai_len);
+       memcpy(&car->car_hmm->mr_rec, rec, rec->arr_hdr.lrh_len);
        mdt_cdt_init_request_tree(&car->car_progress);
-
+       car->car_cancel = NULL;
        RETURN(car);
 }
 
@@ -245,7 +243,7 @@ struct cdt_agent_req *mdt_cdt_alloc_request(__u32 archive_id, __u64 flags,
 void mdt_cdt_free_request(struct cdt_agent_req *car)
 {
        mdt_cdt_free_request_tree(&car->car_progress);
-       OBD_FREE(car->car_hai, car->car_hai->hai_len);
+       OBD_FREE(car->car_hmm, hmmr_size(car->car_hmm->mr_rec.arr_hdr.lrh_len));
        OBD_SLAB_FREE_PTR(car, mdt_hsm_car_kmem);
 }
 
@@ -289,12 +287,12 @@ int mdt_cdt_add_request(struct coordinator *cdt, struct cdt_agent_req *car)
        ENTRY;
 
        /* cancel requests are not kept in memory */
-       LASSERT(car->car_hai->hai_action != HSMA_CANCEL);
+       LASSERT(car->car_hai.hai_action != HSMA_CANCEL);
 
        down_write(&cdt->cdt_request_lock);
 
        rc = cfs_hash_add_unique(cdt->cdt_request_cookie_hash,
-                                &car->car_hai->hai_cookie,
+                                &car->car_hai.hai_cookie,
                                 &car->car_cookie_hash);
        if (rc < 0) {
                up_write(&cdt->cdt_request_lock);
@@ -303,11 +301,13 @@ int mdt_cdt_add_request(struct coordinator *cdt, struct cdt_agent_req *car)
 
        list_add_tail(&car->car_request_list, &cdt->cdt_request_list);
 
+       mdt_cdt_get_request(car);
+
        up_write(&cdt->cdt_request_lock);
 
        mdt_hsm_agent_update_statistics(cdt, 0, 0, 1, &car->car_uuid);
 
-       switch (car->car_hai->hai_action) {
+       switch (car->car_hai.hai_action) {
        case HSMA_ARCHIVE:
                atomic_inc(&cdt->cdt_archive_count);
                break;
@@ -363,7 +363,7 @@ int mdt_cdt_remove_request(struct coordinator *cdt, __u64 cookie)
        list_del(&car->car_request_list);
        up_write(&cdt->cdt_request_lock);
 
-       switch (car->car_hai->hai_action) {
+       switch (car->car_hai.hai_action) {
        case HSMA_ARCHIVE:
                atomic_dec(&cdt->cdt_archive_count);
                break;
@@ -375,6 +375,13 @@ int mdt_cdt_remove_request(struct coordinator *cdt, __u64 cookie)
                break;
        }
 
+       if (car->car_cancel) {
+               mdt_cdt_put_request(car->car_cancel);
+               /* ref from mdt_hsm_add_hsr()->mdt_cdt_find_request() */
+               mdt_cdt_put_request(car);
+               car->car_cancel = NULL;
+       }
+
        /* Drop reference from cdt_request_list. */
        mdt_cdt_put_request(car);
 
@@ -410,7 +417,7 @@ struct cdt_agent_req *mdt_cdt_update_request(struct coordinator *cdt,
        car->car_req_update = ktime_get_real_seconds();
 
        /* update data move progress done by copy tool */
-       if (car->car_hai->hai_action != HSMA_REMOVE && pgs->hpk_errval == 0 &&
+       if (car->car_hai.hai_action != HSMA_REMOVE && pgs->hpk_errval == 0 &&
            pgs->hpk_extent.length != 0) {
                rc = hsm_update_work(&car->car_progress, &pgs->hpk_extent);
                if (rc) {
@@ -502,16 +509,16 @@ static int mdt_hsm_active_requests_proc_show(struct seq_file *s, void *v)
                   " action=%s archive#=%d flags=%#llx"
                   " extent=%#llx-%#llx gid=%#llx"
                   " data=[%s] canceled=%d uuid=%s done=%llu\n",
-                  PFID(&car->car_hai->hai_fid),
-                  PFID(&car->car_hai->hai_dfid),
-                  0ULL /* compound_id */, car->car_hai->hai_cookie,
-                  hsm_copytool_action2name(car->car_hai->hai_action),
+                  PFID(&car->car_hai.hai_fid),
+                  PFID(&car->car_hai.hai_dfid),
+                  0ULL /* compound_id */, car->car_hai.hai_cookie,
+                  hsm_copytool_action2name(car->car_hai.hai_action),
                   car->car_archive_id, car->car_flags,
-                  car->car_hai->hai_extent.offset,
-                  car->car_hai->hai_extent.length,
-                  car->car_hai->hai_gid,
-                  hai_dump_data_field(car->car_hai, buf, sizeof(buf)),
-                  car->car_canceled, obd_uuid2str(&car->car_uuid),
+                  car->car_hai.hai_extent.offset,
+                  car->car_hai.hai_extent.length,
+                  car->car_hai.hai_gid,
+                  hai_dump_data_field(&car->car_hai, buf, sizeof(buf)),
+                  car->car_cancel ? 1 : 0, obd_uuid2str(&car->car_uuid),
                   car->car_progress.crp_total);
        RETURN(0);
 }
index ed954cb..b7ce7e2 100644 (file)
@@ -151,11 +151,6 @@ struct coordinator {
                                                       * restore requests
                                                       */
 
-       /* 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;
@@ -604,17 +599,19 @@ struct cdt_req_progress {
 struct cdt_agent_req {
        struct hlist_node        car_cookie_hash;  /**< find req by cookie */
        struct list_head         car_request_list; /**< to chain all the req. */
+       struct list_head         car_scan_list;    /**< list for scan process */
        struct kref              car_refcount;     /**< reference counter */
-       __u64                    car_flags;        /**< request original flags */
        struct obd_uuid          car_uuid;         /**< agent doing the req. */
-       __u32                    car_archive_id;   /**< archive id */
-       int                      car_canceled;     /**< request was canceled */
-       time64_t                 car_req_start;    /**< start time */
-       time64_t                 car_req_update;   /**< last update time */
-       struct hsm_action_item  *car_hai;          /**< req. to the agent */
+       struct hsm_mem_req_rec  *car_hmm;          /**< llog rec with cookies */
        struct cdt_req_progress  car_progress;     /**< track data mvt
                                                    *   progress */
+       struct cdt_agent_req *car_cancel;          /**< corresponding cancel */
 };
+#define car_flags      car_hmm->mr_rec.arr_flags /**< request original flags */
+#define car_archive_id car_hmm->mr_rec.arr_archive_id /**< archive id */
+#define car_req_update car_hmm->mr_rec.arr_req_change /**< last update time */
+#define car_hai                car_hmm->mr_rec.arr_hai /**< req. to the agent */
+
 extern struct kmem_cache *mdt_hsm_car_kmem;
 
 struct hsm_agent {
@@ -643,6 +640,37 @@ struct hsm_record_update {
        enum agent_req_status status;
 };
 
+struct hsm_mem_req_rec {
+       struct llog_logid mr_lid;
+       u64 mr_offset;
+       struct llog_agent_req_rec mr_rec;
+};
+
+/**
+ * data passed to llog_cat_process() callback
+ * to scan requests and take actions
+ */
+struct hsm_scan_request {
+       struct list_head hsr_cars;
+       char *hsr_fsname;
+       int hsr_used_sz;
+       u32 hsr_version;
+       u32 hsr_count;
+};
+
+static inline u32 hsr_get_archive_id(struct hsm_scan_request *rq)
+{
+       struct cdt_agent_req *car;
+
+       if (rq->hsr_count > 0) {
+               car = list_first_entry(&rq->hsr_cars, struct cdt_agent_req,
+                                      car_scan_list);
+
+               return car->car_archive_id;
+       }
+       return 0;
+}
+
 static inline
 const struct md_device_operations *mdt_child_ops(struct mdt_device *m)
 {
@@ -1071,15 +1099,9 @@ int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt,
 int mdt_agent_record_add(const struct lu_env *env, struct mdt_device *mdt,
                         __u32 archive_id, __u64 flags,
                         struct hsm_action_item *hai);
-int mdt_agent_record_update(struct mdt_thread_info *mti,
-                           struct hsm_record_update *updates,
-                           unsigned int updates_count);
-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);
-
+int mdt_hsm_agent_modify_record(const struct lu_env *env,
+                               struct mdt_device *mdt,
+                               struct hsm_mem_req_rec *hmm);
 /* mdt/mdt_hsm_cdt_agent.c */
 extern const struct file_operations mdt_hsm_agent_fops;
 int mdt_hsm_agent_register(struct mdt_thread_info *info,
@@ -1095,7 +1117,7 @@ int mdt_hsm_agent_update_statistics(struct coordinator *cdt,
                                    const struct obd_uuid *uuid);
 int mdt_hsm_find_best_agent(struct coordinator *cdt, __u32 archive,
                            struct obd_uuid *uuid);
-int mdt_hsm_agent_send(struct mdt_thread_info *mti, struct hsm_action_list *hal,
+int mdt_hsm_agent_send(struct mdt_thread_info *mti, struct hsm_scan_request *rq,
                       bool purge);
 /* mdt/mdt_hsm_cdt_client.c */
 int mdt_hsm_add_actions(struct mdt_thread_info *info,
@@ -1109,12 +1131,10 @@ 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;
-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(__u32 archive_id, __u64 flags,
-                                           struct obd_uuid *uuid,
-                                           struct hsm_action_item *hai);
+struct cdt_agent_req *mdt_cdt_alloc_request(struct obd_uuid *uuid,
+                                           struct llog_agent_req_rec *rec);
 void mdt_cdt_free_request(struct cdt_agent_req *car);
 int mdt_cdt_add_request(struct coordinator *cdt, struct cdt_agent_req *new_car);
 struct cdt_agent_req *mdt_cdt_find_request(struct coordinator *cdt, u64 cookie);
@@ -1161,8 +1181,8 @@ struct mdt_object *mdt_hsm_get_md_hsm(struct mdt_thread_info *mti,
                                      const struct lu_fid *fid,
                                      struct md_hsm *hsm);
 /* actions/request helpers */
-int mdt_hsm_add_hal(struct mdt_thread_info *mti,
-                   struct hsm_action_list *hal, struct obd_uuid *uuid);
+int mdt_hsm_add_hsr(struct mdt_thread_info *mti, struct hsm_scan_request *hsr,
+                   struct obd_uuid *uuid);
 bool mdt_hsm_is_action_compat(const struct hsm_action_item *hai,
                              u32 archive_id, u64 rq_flags,
                              const struct md_hsm *hsm);
index 1934e27..a8b9ee2 100644 (file)
@@ -1152,9 +1152,7 @@ static int mgs_modify_param_hdl(const struct lu_env *env,
                                GOTO(free_mdp, rc = -EBADMSG);
 
                        /* save the start marker to skip */
-                       rc = llog_get_cookie(env, &mpm->mpm_start_cookie);
-                       if (rc)
-                               RETURN(rc);
+                       llog_get_cookie(env, &mpm->mpm_start_cookie);
 
                        OBD_ALLOC(mpm->mpm_start, rec->lrh_len);
                        if (!mpm->mpm_start)
index 982d21b..0a1119f 100644 (file)
@@ -1325,17 +1325,19 @@ int llog_erase(const struct lu_env *env, struct llog_ctxt *ctxt,
 }
 EXPORT_SYMBOL(llog_erase);
 
-/* Get current llog cookie from llog_process_thread session */
-int llog_get_cookie(const struct lu_env *env, struct llog_cookie *out)
+/*
+ * Get record cookie, with record file offset, should be called only by
+ * llog_process_thread() callbacks.
+ */
+void llog_get_cookie(const struct lu_env *env, struct llog_cookie *out)
 {
        struct llog_thread_info *lti = llog_info(env);
 
-       if (!out || !lti)
-               return -EINVAL;
+       LASSERT(out && env && lti);
 
        memcpy(out, &lti->lgi_cookie, sizeof(lti->lgi_cookie));
 
-       return 0;
+       return;
 }
 EXPORT_SYMBOL(llog_get_cookie);
 
index 4252abd..93b9ac1 100644 (file)
@@ -1272,4 +1272,36 @@ int llog_cat_retain_cb(const struct lu_env *env, struct llog_handle *cat,
 }
 EXPORT_SYMBOL(llog_cat_retain_cb);
 
+/* Modify a llog record base on llog_logid and record cookie,
+ * with valid offset.
+ */
+int llog_cat_modify_rec(const struct lu_env *env, struct llog_handle *cathandle,
+                       struct llog_logid *lid, struct llog_rec_hdr *rec,
+                       struct llog_cookie *cookie)
+{
+       struct llog_handle *llh;
+       int rc;
+
+       ENTRY;
+
+       rc = llog_cat_id2handle(env, cathandle, &llh, lid);
+       if (rc) {
+               CDEBUG(D_OTHER, "%s: failed to find log file "DFID": rc = %d\n",
+                      loghandle2name(llh), PLOGID(lid), rc);
 
+               RETURN(rc);
+       }
+
+       rc = llog_write_cookie(env, llh, rec, cookie, rec->lrh_index);
+       if (rc < 0) {
+               CDEBUG(D_OTHER,
+                      "%s: failed to modify record "DFID".%d: rc = %d\n",
+                      loghandle2name(llh), PLOGID(lid), rec->lrh_index, rc);
+       } else {
+               rc = 0;
+       }
+       llog_handle_put(env, llh);
+
+       RETURN(rc);
+}
+EXPORT_SYMBOL(llog_cat_modify_rec);
index af20930..3669b6d 100644 (file)
@@ -109,12 +109,6 @@ static int llog_osd_exist(struct llog_handle *handle)
        return dt_object_exists(handle->lgh_obj) && !handle->lgh_destroyed;
 }
 
-static void *rec_tail(struct llog_rec_hdr *rec)
-{
-       return (void *)((char *)rec + rec->lrh_len -
-                       sizeof(struct llog_rec_tail));
-}
-
 /**
  * Write a padding record to the llog
  *
@@ -159,7 +153,7 @@ static int llog_osd_pad(const struct lu_env *env, struct dt_object *o,
        rec->lrh_index = index;
        rec->lrh_type = LLOG_PAD_MAGIC;
 
-       tail = rec_tail(rec);
+       tail = llog_get_rec_tail(rec);
        tail->lrt_len = len;
        tail->lrt_index = index;
 
@@ -600,7 +594,7 @@ static int llog_osd_write_rec(const struct lu_env *env,
         */
        LASSERT(index < LLOG_HDR_BITMAP_SIZE(llh));
        rec->lrh_index = index;
-       lrt = rec_tail(rec);
+       lrt = llog_get_rec_tail(rec);
        lrt->lrt_len = rec->lrh_len;
        lrt->lrt_index = rec->lrh_index;