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,
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);
__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)))
}
}
-/**
- * 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];
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,
{
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;
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;
/* 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;
}
}
- /* 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);
}
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 &&
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:
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);
}
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);
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;
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) >=
* 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.
}
}
-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);
}
}
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);
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;
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;
}
/**
- * 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
* 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);
/* 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;
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;
" %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
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;
}
/* 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)
* 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];
/* 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);
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);
}
" (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);
}
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);
/* 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);
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);
*/
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);
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;
/* 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);
#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)
{
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
#include <lustre_export.h>
#include <lprocfs_status.h>
#include <lustre_kernelcomm.h>
+#include <lustre_log.h>
#include "mdt_internal.h"
/*
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;
* _ 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,
* 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 */
}
}
- /* 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 :
* 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
" 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 */
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);
}
{
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)
" 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);
}
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;
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);
}
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);
}
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);
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;
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;
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);
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) {
" 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);
}
* 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;
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 {
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)
{
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,
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,
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);
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);
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)
}
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, <i->lgi_cookie, sizeof(lti->lgi_cookie));
- return 0;
+ return;
}
EXPORT_SYMBOL(llog_get_cookie);
}
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);
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
*
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;
*/
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;