* GPL HEADER END
*/
/*
- * Copyright (c) 2012, 2013, Intel Corporation.
- * Use is subject to license terms.
* Copyright (c) 2011, 2012 Commissariat a l'energie atomique et aux energies
* alternatives
+ *
+ * Copyright (c) 2013, 2016, Intel Corporation.
+ * Use is subject to license terms.
*/
/*
* lustre/mdt/mdt_coordinator.c
#define DEBUG_SUBSYSTEM S_MDS
+#include <linux/kthread.h>
#include <obd_support.h>
#include <lustre_net.h>
#include <lustre_export.h>
#include <obd.h>
#include <lprocfs_status.h>
#include <lustre_log.h>
+#include <lustre_kernelcomm.h>
#include "mdt_internal.h"
-static struct lprocfs_seq_vars lprocfs_mdt_hsm_vars[];
+static struct lprocfs_vars lprocfs_mdt_hsm_vars[];
/**
* get obj and HSM attributes on a fid
struct hsm_action_item *hai;
char buf[12];
- CDEBUG(level, "%s: HAL header: version %X count %d compound "LPX64
- " archive_id %d flags "LPX64"\n",
+ CDEBUG(level, "%s: HAL header: version %X count %d compound %#llx"
+ " archive_id %d flags %#llx\n",
prefix, hal->hal_version, hal->hal_count,
hal->hal_compound_id, hal->hal_archive_id, hal->hal_flags);
for (i = 0; i < hal->hal_count; i++) {
sz = hai->hai_len - sizeof(*hai);
CDEBUG(level, "%s %d: fid="DFID" dfid="DFID
- " compound/cookie="LPX64"/"LPX64
- " action=%s extent="LPX64"-"LPX64" gid="LPX64
+ " compound/cookie=%#llx/%#llx"
+ " action=%s extent=%#llx-%#llx gid=%#llx"
" datalen=%d data=[%s]\n",
prefix, i,
PFID(&hai->hai_fid), PFID(&hai->hai_dfid),
* 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 *mti;
char fs_name[MTI_NAME_MAXLEN+1];
/* request to be send to agents */
- int request_sz; /** allocated size */
int max_requests; /** vector size */
int request_cnt; /** used count */
- struct {
- int hal_sz;
- int hal_used_sz;
- struct hsm_action_list *hal;
- } *request;
- /* records to be canceled */
- int max_cookie; /** vector size */
- int cookie_cnt; /** used count */
- __u64 *cookies;
+ struct hsm_scan_request *request;
};
/**
struct llog_rec_hdr *hdr,
void *data)
{
- const struct llog_agent_req_rec *larr;
+ struct llog_agent_req_rec *larr;
struct hsm_scan_data *hsd;
struct hsm_action_item *hai;
struct mdt_device *mdt;
dump_llog_agent_req_rec("mdt_coordinator_cb(): ", larr);
switch (larr->arr_status) {
case ARS_WAITING: {
- int i, empty_slot, found;
+ int i;
+ struct hsm_scan_request *request;
/* Are agents full? */
- if (atomic_read(&cdt->cdt_request_count) ==
+ if (atomic_read(&cdt->cdt_request_count) >=
cdt->cdt_max_requests)
break;
- /* first search if the request if known in the list we have
- * build and if there is room in the request vector */
- empty_slot = -1;
- found = -1;
- for (i = 0; i < hsd->max_requests &&
- (empty_slot == -1 || found == -1); i++) {
- if (hsd->request[i].hal == NULL) {
- empty_slot = i;
- continue;
- }
+ /* first search whether the request is found in the
+ * list we have built. */
+ request = NULL;
+ for (i = 0; i < hsd->request_cnt; i++) {
if (hsd->request[i].hal->hal_compound_id ==
- larr->arr_compound_id) {
- found = i;
- continue;
+ larr->arr_compound_id) {
+ request = &hsd->request[i];
+ break;
}
}
- if (found == -1 && empty_slot == -1)
- /* unknown request and no more room for new request,
- * continue scan for to find other entries for
- * already found request
- */
- RETURN(0);
- if (found == -1) {
+ if (!request) {
struct hsm_action_list *hal;
- /* request is not already known */
+ if (hsd->request_cnt == hsd->max_requests)
+ /* Unknown request and no more room
+ * for a new request. Continue to scan
+ * to find other entries for already
+ * existing requests.
+ */
+ RETURN(0);
+
+ request = &hsd->request[hsd->request_cnt];
+
/* allocates hai vector size just needs to be large
* enough */
- hsd->request[empty_slot].hal_sz =
- sizeof(*hsd->request[empty_slot].hal) +
- cfs_size_round(MTI_NAME_MAXLEN+1) +
- 2 * cfs_size_round(larr->arr_hai.hai_len);
- OBD_ALLOC(hal, hsd->request[empty_slot].hal_sz);
- if (!hal) {
- CERROR("%s: Cannot allocate memory (%d o)"
- "for compound "LPX64"\n",
- mdt_obd_name(mdt),
- hsd->request[i].hal_sz,
- larr->arr_compound_id);
+ request->hal_sz =
+ sizeof(*request->hal) +
+ cfs_size_round(MTI_NAME_MAXLEN+1) +
+ 2 * cfs_size_round(larr->arr_hai.hai_len);
+ OBD_ALLOC(hal, request->hal_sz);
+ if (!hal)
RETURN(-ENOMEM);
- }
hal->hal_version = HAL_VERSION;
strlcpy(hal->hal_fsname, hsd->fs_name,
MTI_NAME_MAXLEN + 1);
hal->hal_archive_id = larr->arr_archive_id;
hal->hal_flags = larr->arr_flags;
hal->hal_count = 0;
- hsd->request[empty_slot].hal_used_sz = hal_size(hal);
- hsd->request[empty_slot].hal = hal;
+ request->hal_used_sz = hal_size(hal);
+ request->hal = hal;
hsd->request_cnt++;
- found = empty_slot;
hai = hai_first(hal);
} else {
/* request is known */
* where the files are not archived in the same backend
*/
if (larr->arr_archive_id !=
- hsd->request[found].hal->hal_archive_id)
+ request->hal->hal_archive_id)
RETURN(0);
- if (hsd->request[found].hal_sz <
- hsd->request[found].hal_used_sz +
- cfs_size_round(larr->arr_hai.hai_len)) {
+ if (request->hal_sz <
+ request->hal_used_sz +
+ cfs_size_round(larr->arr_hai.hai_len)) {
/* Not enough room, need an extension */
void *hal_buffer;
int sz;
- sz = 2 * hsd->request[found].hal_sz;
+ sz = 2 * request->hal_sz;
OBD_ALLOC(hal_buffer, sz);
- if (!hal_buffer) {
- CERROR("%s: Cannot allocate memory "
- "(%d o) for compound "LPX64"\n",
- mdt_obd_name(mdt), sz,
- larr->arr_compound_id);
+ if (!hal_buffer)
RETURN(-ENOMEM);
- }
- memcpy(hal_buffer, hsd->request[found].hal,
- hsd->request[found].hal_used_sz);
- OBD_FREE(hsd->request[found].hal,
- hsd->request[found].hal_sz);
- hsd->request[found].hal = hal_buffer;
- hsd->request[found].hal_sz = sz;
+ memcpy(hal_buffer, request->hal,
+ request->hal_used_sz);
+ OBD_FREE(request->hal,
+ request->hal_sz);
+ request->hal = hal_buffer;
+ request->hal_sz = sz;
}
- hai = hai_first(hsd->request[found].hal);
- for (i = 0; i < hsd->request[found].hal->hal_count;
- i++)
+ hai = hai_first(request->hal);
+ for (i = 0; i < request->hal->hal_count; i++)
hai = hai_next(hai);
}
memcpy(hai, &larr->arr_hai, larr->arr_hai.hai_len);
hai->hai_cookie = larr->arr_hai.hai_cookie;
hai->hai_gid = larr->arr_hai.hai_gid;
- hsd->request[found].hal_used_sz +=
- cfs_size_round(hai->hai_len);
- hsd->request[found].hal->hal_count++;
+ request->hal_used_sz += cfs_size_round(hai->hai_len);
+ request->hal->hal_count++;
break;
}
case ARS_STARTED: {
+ struct hsm_progress_kernel pgs;
struct cdt_agent_req *car;
+ cfs_time_t now = cfs_time_current_sec();
cfs_time_t last;
/* we search for a running request
/* test if request too long, if yes cancel it
* the same way the copy tool acknowledge a cancel request */
- if ((last + cdt->cdt_active_req_timeout)
- < cfs_time_current_sec()) {
- struct hsm_progress_kernel pgs;
-
- dump_llog_agent_req_rec("mdt_coordinator_cb(): "
- "request timeouted, start "
- "cleaning", larr);
- /* a too old cancel request just needs to be removed
- * this can happen, if copy tool does not support cancel
- * for other requests, we have to remove the running
- * request and notify the copytool
- */
- pgs.hpk_fid = larr->arr_hai.hai_fid;
- pgs.hpk_cookie = larr->arr_hai.hai_cookie;
- pgs.hpk_extent = larr->arr_hai.hai_extent;
- pgs.hpk_flags = HP_FLAG_COMPLETED;
- pgs.hpk_errval = ENOSYS;
- pgs.hpk_data_version = 0;
- /* update request state, but do not record in llog, to
- * avoid deadlock on cdt_llog_lock
- */
- rc = mdt_hsm_update_request_state(hsd->mti, &pgs, 0);
- if (rc)
- CERROR("%s: Cannot cleanup timeouted request: "
- DFID" for cookie "LPX64" action=%s\n",
- mdt_obd_name(mdt),
- PFID(&pgs.hpk_fid), pgs.hpk_cookie,
- hsm_copytool_action2name(
- larr->arr_hai.hai_action));
-
- if (rc == -ENOENT) {
- /* The request no longer exists, forget
- * about it, and do not send a cancel request
- * to the client, for which an error will be
- * sent back, leading to an endless cycle of
- * cancellation. */
- RETURN(LLOG_DEL_RECORD);
- }
-
- /* add the cookie to the list of record to be
- * canceled by caller */
- if (hsd->max_cookie == (hsd->cookie_cnt - 1)) {
- __u64 *ptr, *old_ptr;
- int old_sz, new_sz, new_cnt;
+ if (now <= last + cdt->cdt_active_req_timeout)
+ RETURN(0);
- /* need to increase vector size */
- old_sz = sizeof(__u64) * hsd->max_cookie;
- old_ptr = hsd->cookies;
+ dump_llog_agent_req_rec("request timed out, start cleaning",
+ larr);
+ /* a too old cancel request just needs to be removed
+ * this can happen, if copy tool does not support
+ * cancel for other requests, we have to remove the
+ * running request and notify the copytool */
+ pgs.hpk_fid = larr->arr_hai.hai_fid;
+ pgs.hpk_cookie = larr->arr_hai.hai_cookie;
+ pgs.hpk_extent = larr->arr_hai.hai_extent;
+ pgs.hpk_flags = HP_FLAG_COMPLETED;
+ pgs.hpk_errval = ENOSYS;
+ pgs.hpk_data_version = 0;
+
+ /* update request state, but do not record in llog, to
+ * avoid deadlock on cdt_llog_lock */
+ rc = mdt_hsm_update_request_state(hsd->mti, &pgs, 0);
+ if (rc)
+ CERROR("%s: cannot cleanup timed out request: "
+ DFID" for cookie %#llx action=%s\n",
+ mdt_obd_name(mdt),
+ PFID(&pgs.hpk_fid), pgs.hpk_cookie,
+ hsm_copytool_action2name(
+ larr->arr_hai.hai_action));
+
+ if (rc == -ENOENT) {
+ /* The request no longer exists, forget
+ * about it, and do not send a cancel request
+ * to the client, for which an error will be
+ * sent back, leading to an endless cycle of
+ * cancellation. */
+ RETURN(LLOG_DEL_RECORD);
+ }
- new_cnt = 2 * hsd->max_cookie;
- new_sz = sizeof(__u64) * new_cnt;
+ /* XXX A cancel request cannot be cancelled. */
+ if (larr->arr_hai.hai_action == HSMA_CANCEL)
+ RETURN(0);
- OBD_ALLOC(ptr, new_sz);
- if (!ptr) {
- CERROR("%s: Cannot allocate memory "
- "(%d o) for cookie vector\n",
- mdt_obd_name(mdt), new_sz);
- RETURN(-ENOMEM);
- }
- memcpy(ptr, hsd->cookies, old_sz);
- hsd->cookies = ptr;
- hsd->max_cookie = new_cnt;
- OBD_FREE(old_ptr, old_sz);
- }
- hsd->cookies[hsd->cookie_cnt] =
- larr->arr_hai.hai_cookie;
- hsd->cookie_cnt++;
- }
+ larr->arr_status = ARS_CANCELED;
+ larr->arr_req_change = now;
+ rc = llog_write(hsd->mti->mti_env, llh, hdr, hdr->lrh_index);
+ if (rc < 0)
+ CERROR("%s: cannot update agent log: rc = %d\n",
+ mdt_obd_name(mdt), rc);
break;
}
case ARS_FAILED:
ENTRY;
/* init /proc entries, failure is not critical */
- cdt->cdt_proc_dir = lprocfs_seq_register("hsm",
+ cdt->cdt_proc_dir = lprocfs_register("hsm",
mdt2obd_dev(mdt)->obd_proc_entry,
lprocfs_mdt_hsm_vars, mdt);
if (IS_ERR(cdt->cdt_proc_dir)) {
* \param none
* \retval var vector
*/
-struct lprocfs_seq_vars *hsm_cdt_get_proc_vars(void)
+struct lprocfs_vars *hsm_cdt_get_proc_vars(void)
{
return lprocfs_mdt_hsm_vars;
}
struct mdt_thread_info *mti = data;
struct mdt_device *mdt = mti->mti_mdt;
struct coordinator *cdt = &mdt->mdt_coordinator;
- struct hsm_scan_data hsd = { 0 };
+ struct hsm_scan_data hsd = { NULL };
int rc = 0;
+ int request_sz;
ENTRY;
- cdt->cdt_thread.t_flags = SVC_RUNNING;
- wake_up(&cdt->cdt_thread.t_ctl_waitq);
+ cdt->cdt_flags = SVC_RUNNING;
+ wake_up(&cdt->cdt_waitq);
CDEBUG(D_HSM, "%s: coordinator thread starting, pid=%d\n",
mdt_obd_name(mdt), current_pid());
- /* timeouted cookie vector initialization */
- hsd.max_cookie = 0;
- hsd.cookie_cnt = 0;
- hsd.cookies = NULL;
/* we use a copy of cdt_max_requests in the cb, so if cdt_max_requests
* increases due to a change from /proc we do not overflow the
* hsd.request[] vector
*/
hsd.max_requests = cdt->cdt_max_requests;
- hsd.request_sz = hsd.max_requests * sizeof(*hsd.request);
- OBD_ALLOC(hsd.request, hsd.request_sz);
+ request_sz = hsd.max_requests * sizeof(*hsd.request);
+ OBD_ALLOC(hsd.request, request_sz);
if (!hsd.request)
GOTO(out, rc = -ENOMEM);
lwi = LWI_TIMEOUT(cfs_time_seconds(cdt->cdt_loop_period),
NULL, NULL);
- l_wait_event(cdt->cdt_thread.t_ctl_waitq,
- (cdt->cdt_thread.t_flags &
- (SVC_STOPPING|SVC_EVENT)),
+ l_wait_event(cdt->cdt_waitq,
+ cdt->cdt_flags & (SVC_STOPPING|SVC_EVENT),
&lwi);
CDEBUG(D_HSM, "coordinator resumes\n");
- if (cdt->cdt_thread.t_flags & SVC_STOPPING ||
+ if (cdt->cdt_flags & SVC_STOPPING ||
cdt->cdt_state == CDT_STOPPING) {
- cdt->cdt_thread.t_flags &= ~SVC_STOPPING;
+ cdt->cdt_flags &= ~SVC_STOPPING;
rc = 0;
break;
}
/* wake up before timeout, new work arrives */
- if (cdt->cdt_thread.t_flags & SVC_EVENT)
- cdt->cdt_thread.t_flags &= ~SVC_EVENT;
+ if (cdt->cdt_flags & SVC_EVENT)
+ cdt->cdt_flags &= ~SVC_EVENT;
/* if coordinator is suspended continue to wait */
if (cdt->cdt_state == CDT_DISABLE) {
/* cdt_max_requests has changed,
* we need to allocate a new buffer
*/
- OBD_FREE(hsd.request, hsd.request_sz);
+ OBD_FREE(hsd.request, request_sz);
hsd.max_requests = cdt->cdt_max_requests;
- hsd.request_sz =
- hsd.max_requests * sizeof(*hsd.request);
- OBD_ALLOC(hsd.request, hsd.request_sz);
+ request_sz = hsd.max_requests * sizeof(*hsd.request);
+ OBD_ALLOC(hsd.request, request_sz);
if (!hsd.request) {
rc = -ENOMEM;
break;
}
}
- /* create canceled cookie vector for an arbitrary size
- * if needed, vector will grow during llog scan
- */
- hsd.max_cookie = 10;
- hsd.cookie_cnt = 0;
- OBD_ALLOC(hsd.cookies, hsd.max_cookie * sizeof(__u64));
- if (!hsd.cookies) {
- rc = -ENOMEM;
- goto clean_cb_alloc;
- }
hsd.request_cnt = 0;
rc = cdt_llog_process(mti->mti_env, mdt,
if (rc < 0)
goto clean_cb_alloc;
- CDEBUG(D_HSM, "Found %d requests to send and %d"
- " requests to cancel\n",
- hsd.request_cnt, hsd.cookie_cnt);
- /* first we cancel llog records of the timeouted requests */
- if (hsd.cookie_cnt > 0) {
- rc = mdt_agent_record_update(mti->mti_env, mdt,
- hsd.cookies,
- hsd.cookie_cnt,
- ARS_CANCELED);
- if (rc)
- CERROR("%s: mdt_agent_record_update() failed, "
- "rc=%d, cannot update status to %s "
- "for %d cookies\n",
- mdt_obd_name(mdt), rc,
- agent_req_status2name(ARS_CANCELED),
- hsd.cookie_cnt);
- }
+ CDEBUG(D_HSM, "found %d requests to send\n", hsd.request_cnt);
if (list_empty(&cdt->cdt_agents)) {
CDEBUG(D_HSM, "no agent available, "
}
/* here hsd contains a list of requests to be started */
- for (i = 0; i < hsd.max_requests; i++) {
- struct hsm_action_list *hal;
+ for (i = 0; i < hsd.request_cnt; i++) {
+ struct hsm_scan_request *request = &hsd.request[i];
+ struct hsm_action_list *hal = request->hal;
struct hsm_action_item *hai;
__u64 *cookies;
int sz, j;
enum agent_req_status status;
/* still room for work ? */
- if (atomic_read(&cdt->cdt_request_count) ==
+ if (atomic_read(&cdt->cdt_request_count) >=
cdt->cdt_max_requests)
break;
- if (hsd.request[i].hal == NULL)
- continue;
-
- /* found a request, we start it */
- /* kuc payload allocation so we avoid an additionnal
- * allocation in mdt_hsm_agent_send()
- */
- hal = kuc_alloc(hsd.request[i].hal_used_sz,
- KUC_TRANSPORT_HSM, HMT_ACTION_LIST);
- if (IS_ERR(hal)) {
- CERROR("%s: Cannot allocate memory (%d o) "
- "for compound "LPX64"\n",
- mdt_obd_name(mdt),
- hsd.request[i].hal_used_sz,
- hsd.request[i].hal->hal_compound_id);
- continue;
- }
- memcpy(hal, hsd.request[i].hal,
- hsd.request[i].hal_used_sz);
-
rc = mdt_hsm_agent_send(mti, hal, 0);
/* if failure, we suppose it is temporary
* if the copy tool failed to do the request
/* set up cookie vector to set records status
* after copy tools start or failed
*/
- sz = hsd.request[i].hal->hal_count * sizeof(__u64);
+ sz = hal->hal_count * sizeof(__u64);
OBD_ALLOC(cookies, sz);
- if (cookies == NULL) {
- CERROR("%s: Cannot allocate memory (%d o) "
- "for cookies vector "LPX64"\n",
- mdt_obd_name(mdt), sz,
- hsd.request[i].hal->hal_compound_id);
- kuc_free(hal, hsd.request[i].hal_used_sz);
+ if (cookies == NULL)
continue;
- }
+
hai = hai_first(hal);
- for (j = 0; j < hsd.request[i].hal->hal_count; j++) {
+ for (j = 0; j < hal->hal_count; j++) {
cookies[j] = hai->hai_cookie;
hai = hai_next(hai);
}
rc = mdt_agent_record_update(mti->mti_env, mdt, cookies,
- hsd.request[i].hal->hal_count,
- status);
+ hal->hal_count, status);
if (rc)
CERROR("%s: mdt_agent_record_update() failed, "
"rc=%d, cannot update status to %s "
"for %d cookies\n",
mdt_obd_name(mdt), rc,
agent_req_status2name(status),
- hsd.request[i].hal->hal_count);
+ hal->hal_count);
OBD_FREE(cookies, sz);
- kuc_free(hal, hsd.request[i].hal_used_sz);
}
clean_cb_alloc:
- /* free cookie vector allocated for/by callback */
- if (hsd.cookies) {
- OBD_FREE(hsd.cookies, hsd.max_cookie * sizeof(__u64));
- hsd.max_cookie = 0;
- hsd.cookie_cnt = 0;
- hsd.cookies = NULL;
- }
-
/* free hal allocated by callback */
- for (i = 0; i < hsd.max_requests; i++) {
- if (hsd.request[i].hal) {
- OBD_FREE(hsd.request[i].hal,
- hsd.request[i].hal_sz);
- hsd.request[i].hal_sz = 0;
- hsd.request[i].hal = NULL;
- hsd.request_cnt--;
- }
- }
- LASSERT(hsd.request_cnt == 0);
+ for (i = 0; i < hsd.request_cnt; i++) {
+ struct hsm_scan_request *request = &hsd.request[i];
- /* reset callback data */
- memset(hsd.request, 0, hsd.request_sz);
+ OBD_FREE(request->hal, request->hal_sz);
+ }
}
EXIT;
out:
if (hsd.request)
- OBD_FREE(hsd.request, hsd.request_sz);
-
- if (hsd.cookies)
- OBD_FREE(hsd.cookies, hsd.max_cookie * sizeof(__u64));
+ OBD_FREE(hsd.request, request_sz);
if (cdt->cdt_state == CDT_STOPPING) {
/* request comes from /proc path, so we need to clean cdt
* by mdt_stop_coordinator(), we have to ack
* and cdt cleaning will be done by event sender
*/
- cdt->cdt_thread.t_flags = SVC_STOPPED;
- wake_up(&cdt->cdt_thread.t_ctl_waitq);
+ cdt->cdt_flags = SVC_STOPPED;
+ wake_up(&cdt->cdt_waitq);
}
if (rc != 0)
* \retval cdt_restore_handle found
* \retval NULL not found
*/
-static struct cdt_restore_handle *hsm_restore_hdl_find(struct coordinator *cdt,
+struct cdt_restore_handle *mdt_hsm_restore_hdl_find(struct coordinator *cdt,
const struct lu_fid *fid)
{
struct cdt_restore_handle *crh;
/* restore request not in a final state */
+ /* force replay of restore requests left in started state from previous
+ * CDT context, to be canceled later if finally found to be incompatible
+ * when being re-started */
+ if (larr->arr_status == ARS_STARTED) {
+ larr->arr_status = ARS_WAITING;
+ larr->arr_req_change = cfs_time_current_sec();
+ rc = llog_write(env, llh, hdr, hdr->lrh_index);
+ if (rc != 0)
+ GOTO(out, rc);
+ }
+
OBD_SLAB_ALLOC_PTR(crh, mdt_hsm_cdt_kmem);
if (crh == NULL)
RETURN(-ENOMEM);
RETURN(-ESRCH);
/* wake up coordinator */
- cdt->cdt_thread.t_flags = SVC_EVENT;
- wake_up(&cdt->cdt_thread.t_ctl_waitq);
+ cdt->cdt_flags = SVC_EVENT;
+ wake_up(&cdt->cdt_waitq);
RETURN(0);
}
cdt->cdt_state = CDT_STOPPED;
- init_waitqueue_head(&cdt->cdt_thread.t_ctl_waitq);
+ init_waitqueue_head(&cdt->cdt_waitq);
mutex_init(&cdt->cdt_llog_lock);
init_rwsem(&cdt->cdt_agent_lock);
init_rwsem(&cdt->cdt_request_lock);
* \retval 0 success
* \retval -ve failure
*/
-int mdt_hsm_cdt_start(struct mdt_device *mdt)
+static int mdt_hsm_cdt_start(struct mdt_device *mdt)
{
struct coordinator *cdt = &mdt->mdt_coordinator;
int rc;
" for registered restore: %d\n",
mdt_obd_name(mdt), rc);
+ if (mdt->mdt_bottom->dd_rdonly)
+ RETURN(0);
+
task = kthread_run(mdt_coordinator, cdt_mti, "hsm_cdtr");
if (IS_ERR(task)) {
rc = PTR_ERR(task);
rc = 0;
}
- wait_event(cdt->cdt_thread.t_ctl_waitq,
- (cdt->cdt_thread.t_flags & SVC_RUNNING));
+ wait_event(cdt->cdt_waitq,
+ (cdt->cdt_flags & SVC_RUNNING));
cdt->cdt_state = CDT_RUNNING;
mdt->mdt_opts.mo_coordinator = 1;
struct mdt_thread_info *cdt_mti;
ENTRY;
+ if (mdt->mdt_opts.mo_coordinator == 0)
+ RETURN(0);
+
if (cdt->cdt_state == CDT_STOPPED) {
CERROR("%s: Coordinator already stopped\n",
mdt_obd_name(mdt));
if (cdt->cdt_state != CDT_STOPPING) {
/* stop coordinator thread before cleaning */
- cdt->cdt_thread.t_flags = SVC_STOPPING;
- wake_up(&cdt->cdt_thread.t_ctl_waitq);
- wait_event(cdt->cdt_thread.t_ctl_waitq,
- cdt->cdt_thread.t_flags & SVC_STOPPED);
+ cdt->cdt_flags = SVC_STOPPING;
+ wake_up(&cdt->cdt_waitq);
+ wait_event(cdt->cdt_waitq,
+ cdt->cdt_flags & SVC_STOPPED);
}
cdt->cdt_state = CDT_STOPPED;
if (rc) {
CERROR("%s: mdt_agent_record_update() failed, "
"rc=%d, cannot update status to %s "
- "for cookie "LPX64"\n",
+ "for cookie %#llx\n",
mdt_obd_name(mdt), rc,
agent_req_status2name(ARS_CANCELED),
hai->hai_cookie);
/**
* swap layouts between 2 fids
* \param mti [IN] context
- * \param fid1 [IN]
- * \param fid2 [IN]
+ * \param obj [IN]
+ * \param dfid [IN]
* \param mh_common [IN] MD HSM
*/
static int hsm_swap_layouts(struct mdt_thread_info *mti,
- const lustre_fid *fid, const lustre_fid *dfid,
+ struct mdt_object *obj, const struct lu_fid *dfid,
struct md_hsm *mh_common)
{
- struct mdt_device *mdt = mti->mti_mdt;
- struct mdt_object *child1, *child2;
- struct mdt_lock_handle *lh2;
+ struct mdt_object *dobj;
+ struct mdt_lock_handle *dlh;
int rc;
ENTRY;
- child1 = mdt_object_find(mti->mti_env, mdt, fid);
- if (IS_ERR(child1))
- GOTO(out, rc = PTR_ERR(child1));
+ if (!mdt_object_exists(obj))
+ GOTO(out, rc = -ENOENT);
- /* we already have layout lock on FID so take only
+ /* we already have layout lock on obj so take only
* on dfid */
- lh2 = &mti->mti_lh[MDT_LH_OLD];
- mdt_lock_reg_init(lh2, LCK_EX);
- child2 = mdt_object_find_lock(mti, dfid, lh2, MDS_INODELOCK_LAYOUT);
- if (IS_ERR(child2))
- GOTO(out_child1, rc = PTR_ERR(child2));
+ dlh = &mti->mti_lh[MDT_LH_OLD];
+ mdt_lock_reg_init(dlh, LCK_EX);
+ dobj = mdt_object_find_lock(mti, dfid, dlh, MDS_INODELOCK_LAYOUT);
+ if (IS_ERR(dobj))
+ GOTO(out, rc = PTR_ERR(dobj));
/* if copy tool closes the volatile before sending the final
* progress through llapi_hsm_copy_end(), all the objects
* are removed and mdd_swap_layout LBUG */
- if (!mdt_object_exists(child2)) {
+ if (!mdt_object_exists(dobj)) {
CERROR("%s: Copytool has closed volatile file "DFID"\n",
mdt_obd_name(mti->mti_mdt), PFID(dfid));
- GOTO(out_child2, rc = -ENOENT);
+ GOTO(out_dobj, rc = -ENOENT);
}
/* Since we only handle restores here, unconditionally use
* SWAP_LAYOUTS_MDS_HSM flag to ensure original layout will
* only need to clear RELEASED and DIRTY.
*/
mh_common->mh_flags &= ~(HS_RELEASED | HS_DIRTY);
- rc = mdt_hsm_attr_set(mti, child2, mh_common);
+ rc = mdt_hsm_attr_set(mti, dobj, mh_common);
if (rc == 0)
rc = mo_swap_layouts(mti->mti_env,
- mdt_object_child(child1),
- mdt_object_child(child2),
+ mdt_object_child(obj),
+ mdt_object_child(dobj),
SWAP_LAYOUTS_MDS_HSM);
-out_child2:
- mdt_object_unlock_put(mti, child2, lh2, 1);
-out_child1:
- mdt_object_put(mti->mti_env, child1);
+out_dobj:
+ mdt_object_unlock_put(mti, dobj, dlh, 1);
out:
RETURN(rc);
}
int cl_flags = 0, rc = 0;
struct md_hsm mh;
bool is_mh_changed;
+ bool need_changelog = true;
ENTRY;
/* default is to retry */
*status = ARS_WAITING;
- /* find object by FID */
+ /* 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);
/* we will update MD HSM only if needed */
is_mh_changed = false;
- if (IS_ERR(obj)) {
- /* object removed */
- *status = ARS_SUCCEED;
- goto unlock;
- }
/* no need to change mh->mh_arch_id
* mdt_hsm_get_md_hsm() got it from disk and it is still valid
* ENOSYS only if does not support cancel
*/
/* this can also happen when cdt calls it to
- * for a timeouted request */
+ * for a timed out request */
*status = ARS_FAILED;
/* to have a cancel event in changelog */
pgs->hpk_errval = ECANCELED;
*status = ARS_SUCCEED;
break;
default:
+ /* retry only if current policy or requested, and
+ * object is not on error/removed */
*status = (cdt->cdt_policy & CDT_NORETRY_ACTION ||
- !(pgs->hpk_flags & HP_FLAG_RETRY) ?
- ARS_FAILED : ARS_WAITING);
+ !(pgs->hpk_flags & HP_FLAG_RETRY) ||
+ IS_ERR(obj)) ? ARS_FAILED : ARS_WAITING;
break;
}
if (pgs->hpk_errval > CLF_HSM_MAXERROR) {
- CERROR("%s: Request "LPX64" on "DFID
+ CERROR("%s: Request %#llx on "DFID
" failed, error code %d too large\n",
mdt_obd_name(mdt),
pgs->hpk_cookie, PFID(&pgs->hpk_fid),
break;
case HSMA_CANCEL:
hsm_set_cl_event(&cl_flags, HE_CANCEL);
- CERROR("%s: Failed request "LPX64" on "DFID
+ CERROR("%s: Failed request %#llx on "DFID
" cannot be a CANCEL\n",
mdt_obd_name(mdt),
pgs->hpk_cookie,
PFID(&pgs->hpk_fid));
break;
default:
- CERROR("%s: Failed request "LPX64" on "DFID
+ CERROR("%s: Failed request %#llx on "DFID
" %d is an unknown action\n",
mdt_obd_name(mdt),
pgs->hpk_cookie, PFID(&pgs->hpk_fid),
break;
case HSMA_CANCEL:
hsm_set_cl_event(&cl_flags, HE_CANCEL);
- CERROR("%s: Successful request "LPX64
- " on "DFID
- " cannot be a CANCEL\n",
+ CERROR("%s: Successful request %#llx on "DFID" cannot be a CANCEL\n",
mdt_obd_name(mdt),
pgs->hpk_cookie,
PFID(&pgs->hpk_fid));
break;
default:
- CERROR("%s: Successful request "LPX64
- " on "DFID
- " %d is an unknown action\n",
+ 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);
mh.mh_flags & HS_DIRTY ? CLF_HSM_DIRTY : 0);
/* unlock is done later, after layout lock management */
- if (is_mh_changed)
+ if (is_mh_changed && !IS_ERR(obj))
rc = mdt_hsm_attr_set(mti, obj, &mh);
-unlock:
/* we give back layout lock only if restore was successful or
- * if restore was canceled or if policy is to not retry
+ * 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 &&
- (pgs->hpk_errval == 0 || pgs->hpk_errval == ECANCELED ||
- cdt->cdt_policy & CDT_NORETRY_ACTION)) {
+ if (car->car_hai->hai_action == HSMA_RESTORE) {
struct cdt_restore_handle *crh;
/* restore in data FID done, we swap the layouts
- * only if restore is successfull */
- if (pgs->hpk_errval == 0) {
- rc = hsm_swap_layouts(mti, &car->car_hai->hai_fid,
- &car->car_hai->hai_dfid, &mh);
+ * only if restore is successful */
+ if (pgs->hpk_errval == 0 && !IS_ERR_OR_NULL(obj)) {
+ rc = hsm_swap_layouts(mti, obj, &car->car_hai->hai_dfid,
+ &mh);
if (rc) {
if (cdt->cdt_policy & CDT_NORETRY_ACTION)
*status = ARS_FAILED;
if (*status == ARS_WAITING)
GOTO(out, rc);
+ /* restore special case, need to create ChangeLog record
+ * before to give back layout lock to avoid concurrent
+ * file updater to post out of order ChangeLog */
+ mo_changelog(env, CL_HSM, cl_flags, mdt->mdt_child,
+ &car->car_hai->hai_fid);
+ need_changelog = false;
+
/* give back layout lock */
mutex_lock(&cdt->cdt_restore_lock);
- crh = hsm_restore_hdl_find(cdt, &car->car_hai->hai_fid);
+ crh = mdt_hsm_restore_hdl_find(cdt, &car->car_hai->hai_fid);
if (crh != NULL)
list_del(&crh->crh_list);
mutex_unlock(&cdt->cdt_restore_lock);
- /* just give back layout lock, we keep
- * the reference which is given back
- * later with the lock for HSM flags */
- if (!IS_ERR(obj) && crh != NULL)
- mdt_object_unlock(mti, obj, &crh->crh_lh, 1);
+ /* Just give back layout lock, we keep the reference
+ * which is given back later with the lock for HSM
+ * flags.
+ * XXX obj may be invalid so we do not pass it. */
+ if (crh != NULL)
+ mdt_object_unlock(mti, NULL, &crh->crh_lh, 1);
if (crh != NULL)
OBD_SLAB_FREE_PTR(crh, mdt_hsm_cdt_kmem);
GOTO(out, rc);
out:
- if (obj != NULL && !IS_ERR(obj)) {
- mo_changelog(env, CL_HSM, cl_flags,
- mdt_object_child(obj));
+ /* always add a ChangeLog record */
+ if (need_changelog)
+ mo_changelog(env, CL_HSM, cl_flags, mdt->mdt_child,
+ &car->car_hai->hai_fid);
+
+ if (!IS_ERR(obj))
mdt_object_put(mti->mti_env, obj);
- }
RETURN(rc);
}
/* first do sanity checks */
car = mdt_cdt_update_request(cdt, pgs);
if (IS_ERR(car)) {
- CERROR("%s: Cannot find running request for cookie "LPX64
+ CERROR("%s: Cannot find running request for cookie %#llx"
" on fid="DFID"\n",
mdt_obd_name(mdt),
pgs->hpk_cookie, PFID(&pgs->hpk_fid));
- if (car == NULL)
- RETURN(-ENOENT);
+
RETURN(PTR_ERR(car));
}
- CDEBUG(D_HSM, "Progress received for fid="DFID" cookie="LPX64
+ 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),
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 "LPX64
+ CERROR("%s: Progress on "DFID" for cookie %#llx"
" does not match request FID "DFID" nor data FID "
DFID"\n",
mdt_obd_name(mdt),
}
if (pgs->hpk_errval != 0 && !(pgs->hpk_flags & HP_FLAG_COMPLETED)) {
- CERROR("%s: Progress on "DFID" for cookie "LPX64" action=%s"
+ CERROR("%s: Progress on "DFID" for cookie %#llx action=%s"
" is not coherent (err=%d and not completed"
" (flags=%d))\n",
mdt_obd_name(mdt),
/* remove request from memory list */
mdt_cdt_remove_request(cdt, pgs->hpk_cookie);
- CDEBUG(D_HSM, "Updating record: fid="DFID" cookie="LPX64
+ CDEBUG(D_HSM, "Updating record: fid="DFID" cookie=%#llx"
" action=%s status=%s\n", PFID(&pgs->hpk_fid),
pgs->hpk_cookie,
hsm_copytool_action2name(car->car_hai->hai_action),
if (rc1)
CERROR("%s: mdt_agent_record_update() failed,"
" rc=%d, cannot update status to %s"
- " for cookie "LPX64"\n",
+ " for cookie %#llx\n",
mdt_obd_name(mdt), rc1,
agent_req_status2name(status),
pgs->hpk_cookie);
larr->arr_status == ARS_STARTED) {
larr->arr_status = ARS_CANCELED;
larr->arr_req_change = cfs_time_current_sec();
- rc = mdt_agent_llog_update_rec(env, hcad->mdt, llh, larr);
- if (rc == 0)
- RETURN(LLOG_DEL_RECORD);
+ rc = llog_write(env, llh, hdr, hdr->lrh_index);
}
+
RETURN(rc);
}
*/
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;
enum cdt_states save_state;
ENTRY;
- /* retrieve coordinator context */
- mti = lu_context_key_get(&cdt->cdt_env.le_ctx, &mdt_thread_key);
+ rc = lu_env_init(&env, LCT_MD_THREAD);
+ if (rc < 0)
+ RETURN(rc);
+
+ /* for mdt_ucred(), lu_ucred stored in lu_ucred_key */
+ rc = lu_context_init(&session, LCT_SERVER_SESSION);
+ if (rc < 0)
+ GOTO(out_env, rc);
+
+ lu_context_enter(&session);
+ env.le_ses = &session;
+
+ mti = lu_context_key_get(&env.le_ctx, &mdt_thread_key);
+ LASSERT(mti != NULL);
+
+ mti->mti_env = &env;
+ mti->mti_mdt = mdt;
+
+ hsm_init_ucred(mdt_ucred(mti));
/* disable coordinator */
save_state = cdt->cdt_state;
if (hal == NULL) {
mdt_cdt_put_request(car);
up_read(&cdt->cdt_request_lock);
- GOTO(out, rc = -ENOMEM);
+ GOTO(out_cdt_state, rc = -ENOMEM);
}
}
rc = cdt_llog_process(mti->mti_env, mti->mti_mdt,
mdt_cancel_all_cb, &hcad);
-out:
+out_cdt_state:
/* enable coordinator */
cdt->cdt_state = save_state;
+ lu_context_exit(&session);
+ lu_context_fini(&session);
+out_env:
+ lu_env_fini(&env);
RETURN(rc);
}
/**
- * check if a request is comptaible with file status
+ * check if a request is compatible with file status
* \param hai [IN] request description
* \param hal_an [IN] request archive number (not used)
* \param rq_flags [IN] request flags
is_compat = true;
break;
}
- CDEBUG(D_HSM, "fid="DFID" action=%s flags="LPX64
- " extent="LPX64"-"LPX64" hsm_flags=%.8X %s\n",
+ CDEBUG(D_HSM, "fid="DFID" action=%s flags=%#llx"
+ " extent=%#llx-%#llx hsm_flags=%.8X %s\n",
PFID(&hai->hai_fid),
hsm_copytool_action2name(hai->hai_action), rq_flags,
hai->hai_extent.offset, hai->hai_extent.length,
ENTRY;
if (hexa)
- seq_printf(m, "("LPX64") ", mask);
+ seq_printf(m, "(%#llx) ", mask);
for (i = 0; i < CDT_POLICY_SHIFT_COUNT; i++) {
bit = (1ULL << i);
} while (start != NULL);
- CDEBUG(D_HSM, "%s: new policy: rm="LPX64" add="LPX64" set="LPX64"\n",
+ CDEBUG(D_HSM, "%s: new policy: rm=%#llx add=%#llx set=%#llx\n",
mdt_obd_name(mdt), remove_mask, add_mask, set_mask);
/* if no sign in all string, it is a clear and set
struct coordinator *cdt = &mdt->mdt_coordinator; \
ENTRY; \
\
- seq_printf(m, LPU64"\n", (__u64)cdt->VAR); \
+ seq_printf(m, "%llu\n", (__u64)cdt->VAR); \
RETURN(0); \
} \
static ssize_t \
struct seq_file *m = file->private_data; \
struct mdt_device *mdt = m->private; \
struct coordinator *cdt = &mdt->mdt_coordinator; \
- int val; \
+ __s64 val; \
int rc; \
ENTRY; \
\
- rc = lprocfs_write_helper(buffer, count, &val); \
+ rc = lprocfs_str_to_s64(buffer, count, &val); \
if (rc) \
RETURN(rc); \
- if (val > 0) { \
+ if (val > 0 && val < INT_MAX) { \
cdt->VAR = val; \
RETURN(count); \
} \
static int
mdt_hsm_request_mask_show(struct seq_file *m, __u64 mask)
{
- int i, rc = 0;
+ bool first = true;
+ int i;
ENTRY;
for (i = 0; i < 8 * sizeof(mask); i++) {
- if (mask & (1UL << i))
- rc += seq_printf(m, "%s%s", rc == 0 ? "" : " ",
- hsm_copytool_action2name(i));
+ if (mask & (1UL << i)) {
+ seq_printf(m, "%s%s", first ? "" : " ",
+ hsm_copytool_action2name(i));
+ first = false;
+ }
}
- rc += seq_printf(m, "\n");
+ seq_putc(m, '\n');
- RETURN(rc);
+ RETURN(0);
}
static int
LPROC_SEQ_FOPS(mdt_hsm_group_request_mask);
LPROC_SEQ_FOPS(mdt_hsm_other_request_mask);
-static struct lprocfs_seq_vars lprocfs_mdt_hsm_vars[] = {
+static struct lprocfs_vars lprocfs_mdt_hsm_vars[] = {
{ .name = "agents",
.fops = &mdt_hsm_agent_fops },
{ .name = "actions",