X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fmdt%2Fmdt_coordinator.c;h=3915e21978167a56a61344b214fc853243feff0e;hb=da12d3ba35bbb86c8e5860a5ed161a55f01b69d5;hp=fa92f7505d56a5c10ffca8a9d2e38360b1f4a89c;hpb=b87e99adf44b80308f341cbf143374034f627ab9;p=fs%2Flustre-release.git diff --git a/lustre/mdt/mdt_coordinator.c b/lustre/mdt/mdt_coordinator.c index fa92f75..3915e21 100644 --- a/lustre/mdt/mdt_coordinator.c +++ b/lustre/mdt/mdt_coordinator.c @@ -133,7 +133,7 @@ struct hsm_scan_data { char fs_name[MTI_NAME_MAXLEN+1]; /* request to be send to agents */ int request_sz; /** allocated size */ - int max_request; /** vector size */ + int max_requests; /** vector size */ int request_cnt; /** used count */ struct { int hal_sz; @@ -182,14 +182,14 @@ static int mdt_coordinator_cb(const struct lu_env *env, /* Are agents full? */ if (atomic_read(&cdt->cdt_request_count) == - cdt->cdt_max_request) + 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_request && + for (i = 0; i < hsd->max_requests && (empty_slot == -1 || found == -1); i++) { if (hsd->request[i].hal == NULL) { empty_slot = i; @@ -308,7 +308,8 @@ static int mdt_coordinator_cb(const struct lu_env *env, /* test if request too long, if yes cancel it * the same way the copy tool acknowledge a cancel request */ - if ((last + cdt->cdt_timeout) < cfs_time_current_sec()) { + if ((last + cdt->cdt_active_req_timeout) + < cfs_time_current_sec()) { struct hsm_progress_kernel pgs; dump_llog_agent_req_rec("mdt_coordinator_cb(): " @@ -371,7 +372,7 @@ static int mdt_coordinator_cb(const struct lu_env *env, case ARS_FAILED: case ARS_CANCELED: case ARS_SUCCEED: - if ((larr->arr_req_change + cdt->cdt_delay) < + if ((larr->arr_req_change + cdt->cdt_grace_delay) < cfs_time_current_sec()) RETURN(LLOG_DEL_RECORD); break; @@ -385,7 +386,7 @@ static int mdt_coordinator_cb(const struct lu_env *env, * \retval 0 success * \retval -ve failure */ -static int hsm_cdt_procfs_init(struct mdt_device *mdt) +int hsm_cdt_procfs_init(struct mdt_device *mdt) { struct coordinator *cdt = &mdt->mdt_coordinator; int rc = 0; @@ -407,6 +408,29 @@ static int hsm_cdt_procfs_init(struct mdt_device *mdt) } /** + * remove /proc entries for coordinator + * \param mdt [IN] + */ +void hsm_cdt_procfs_fini(struct mdt_device *mdt) +{ + struct coordinator *cdt = &mdt->mdt_coordinator; + + LASSERT(cdt->cdt_state == CDT_STOPPED); + if (cdt->cdt_proc_dir != NULL) + lprocfs_remove(&cdt->cdt_proc_dir); +} + +/** + * get vector of hsm cdt /proc vars + * \param none + * \retval var vector + */ +struct lprocfs_vars *hsm_cdt_get_proc_vars(void) +{ + return lprocfs_mdt_hsm_vars; +} + +/** * coordinator thread * \param data [IN] obd device * \retval 0 success @@ -427,20 +451,16 @@ static int mdt_coordinator(void *data) CDEBUG(D_HSM, "%s: coordinator thread starting, pid=%d\n", mdt_obd_name(mdt), current_pid()); - /* - * create /proc entries for coordinator - */ - hsm_cdt_procfs_init(mdt); /* timeouted cookie vector initialization */ hsd.max_cookie = 0; hsd.cookie_cnt = 0; hsd.cookies = NULL; - /* we use a copy of cdt_max_request in the cb, so if cdt_max_request + /* 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_request = cdt->cdt_max_request; - hsd.request_sz = hsd.max_request * sizeof(*hsd.request); + hsd.max_requests = cdt->cdt_max_requests; + hsd.request_sz = hsd.max_requests * sizeof(*hsd.request); OBD_ALLOC(hsd.request, hsd.request_sz); if (!hsd.request) GOTO(out, rc = -ENOMEM); @@ -480,14 +500,14 @@ static int mdt_coordinator(void *data) CDEBUG(D_HSM, "coordinator starts reading llog\n"); - if (hsd.max_request != cdt->cdt_max_request) { - /* cdt_max_request has changed, + if (hsd.max_requests != cdt->cdt_max_requests) { + /* cdt_max_requests has changed, * we need to allocate a new buffer */ OBD_FREE(hsd.request, hsd.request_sz); - hsd.max_request = cdt->cdt_max_request; + hsd.max_requests = cdt->cdt_max_requests; hsd.request_sz = - hsd.max_request * sizeof(*hsd.request); + hsd.max_requests * sizeof(*hsd.request); OBD_ALLOC(hsd.request, hsd.request_sz); if (!hsd.request) { rc = -ENOMEM; @@ -537,7 +557,7 @@ static int mdt_coordinator(void *data) } /* here hsd contains a list of requests to be started */ - for (i = 0; i < hsd.max_request; i++) { + for (i = 0; i < hsd.max_requests; i++) { struct hsm_action_list *hal; struct hsm_action_item *hai; __u64 *cookies; @@ -546,7 +566,7 @@ static int mdt_coordinator(void *data) /* still room for work ? */ if (atomic_read(&cdt->cdt_request_count) == - cdt->cdt_max_request) + cdt->cdt_max_requests) break; if (hsd.request[i].hal == NULL) @@ -619,7 +639,7 @@ clean_cb_alloc: } /* free hal allocated by callback */ - for (i = 0; i < hsd.max_request; i++) { + for (i = 0; i < hsd.max_requests; i++) { if (hsd.request[i].hal) { OBD_FREE(hsd.request[i].hal, hsd.request[i].hal_sz); @@ -859,7 +879,7 @@ int mdt_hsm_cdt_init(struct mdt_device *mdt) RETURN(rc); /* for mdt_ucred(), lu_ucred stored in lu_ucred_key */ - rc = lu_context_init(&cdt->cdt_session, LCT_SESSION); + rc = lu_context_init(&cdt->cdt_session, LCT_SERVER_SESSION); if (rc == 0) { lu_context_enter(&cdt->cdt_session); cdt->cdt_env.le_ses = &cdt->cdt_session; @@ -876,6 +896,15 @@ int mdt_hsm_cdt_init(struct mdt_device *mdt) hsm_init_ucred(mdt_ucred(cdt_mti)); + /* default values for /proc tunnables + * can be override by MGS conf */ + cdt->cdt_default_archive_id = 1; + cdt->cdt_grace_delay = 60; + cdt->cdt_loop_period = 10; + cdt->cdt_max_requests = 3; + cdt->cdt_policy = CDT_DEFAULT_POLICY; + cdt->cdt_active_req_timeout = 3600; + RETURN(0); } @@ -922,19 +951,19 @@ int mdt_hsm_cdt_start(struct mdt_device *mdt) RETURN(-EALREADY); } + CLASSERT(1 << (CDT_POLICY_SHIFT_COUNT - 1) == CDT_POLICY_LAST); cdt->cdt_policy = CDT_DEFAULT_POLICY; + cdt->cdt_state = CDT_INIT; atomic_set(&cdt->cdt_compound_id, cfs_time_current_sec()); /* just need to be larger than previous one */ /* cdt_last_cookie is protected by cdt_llog_lock */ cdt->cdt_last_cookie = cfs_time_current_sec(); - cdt->cdt_loop_period = 10; - cdt->cdt_delay = 60; - cdt->cdt_timeout = 3600; - cdt->cdt_max_request = 3; - cdt->cdt_archive_id = 1; atomic_set(&cdt->cdt_request_count, 0); + cdt->cdt_user_request_mask = (1UL << HSMA_RESTORE); + cdt->cdt_group_request_mask = (1UL << HSMA_RESTORE); + cdt->cdt_other_request_mask = (1UL << HSMA_RESTORE); /* to avoid deadlock when start is made through /proc * /proc entries are created by the coordinator thread */ @@ -987,10 +1016,6 @@ int mdt_hsm_cdt_stop(struct mdt_device *mdt) RETURN(-EALREADY); } - /* remove proc entries */ - if (cdt->cdt_proc_dir != NULL) - lprocfs_remove(&cdt->cdt_proc_dir); - if (cdt->cdt_state != CDT_STOPPING) { /* stop coordinator thread before cleaning */ cdt->cdt_thread.t_flags = SVC_STOPPING; @@ -1716,8 +1741,8 @@ static const struct { char *name; char *nickname; } hsm_policy_names[] = { - { CDT_NONBLOCKING_RESTORE, "non_blocking_restore", "nbr"}, - { CDT_NORETRY_ACTION, "no_retry_action", "nra"}, + { CDT_NONBLOCKING_RESTORE, "NonBlockingRestore", "NBR"}, + { CDT_NORETRY_ACTION, "NoRetryAction", "NRA"}, { 0 }, }; @@ -1732,7 +1757,8 @@ static __u64 hsm_policy_str2bit(const char *name) int i; for (i = 0; hsm_policy_names[i].bit != 0; i++) - if (strcmp(hsm_policy_names[i].nickname, name) == 0) + if (strcmp(hsm_policy_names[i].nickname, name) == 0 || + strcmp(hsm_policy_names[i].name, name) == 0) return hsm_policy_names[i].bit; return 0; } @@ -1740,11 +1766,13 @@ static __u64 hsm_policy_str2bit(const char *name) /** * convert a policy bit field to a string * \param mask [IN] policy bit field + * \param hexa [IN] print mask before bit names * \param buffer [OUT] string * \param count [IN] size of buffer * \retval size filled in buffer */ -static int hsm_policy_bit2str(const __u64 mask, char *buffer, int count) +static int hsm_policy_bit2str(const __u64 mask, const bool hexa, char *buffer, + int count) { int i, j, sz; char *ptr; @@ -1752,25 +1780,31 @@ static int hsm_policy_bit2str(const __u64 mask, char *buffer, int count) ENTRY; ptr = buffer; - sz = snprintf(buffer, count, "("LPX64") ", mask); - ptr += sz; - count -= sz; - for (i = 0; i < (sizeof(mask) * 8); i++) { + if (hexa) { + sz = snprintf(buffer, count, "("LPX64") ", mask); + ptr += sz; + count -= sz; + } + for (i = 0; i < CDT_POLICY_SHIFT_COUNT; i++) { bit = (1ULL << i); - if (!(bit & mask)) - continue; for (j = 0; hsm_policy_names[j].bit != 0; j++) { - if (hsm_policy_names[j].bit == bit) { - sz = snprintf(ptr, count, "%s(%s) ", - hsm_policy_names[j].name, - hsm_policy_names[j].nickname); - ptr += sz; - count -= sz; + if (hsm_policy_names[j].bit == bit) break; - } } + if (bit & mask) + sz = snprintf(ptr, count, "[%s] ", + hsm_policy_names[j].name); + else + sz = snprintf(ptr, count, "%s ", + hsm_policy_names[j].name); + + ptr += sz; + count -= sz; } + /* remove last ' ' */ + *ptr = '\0'; + ptr--; RETURN(ptr - buffer); } @@ -1783,7 +1817,7 @@ static int lprocfs_rd_hsm_policy(char *page, char **start, off_t off, int sz; ENTRY; - sz = hsm_policy_bit2str(cdt->cdt_policy, page, count); + sz = hsm_policy_bit2str(cdt->cdt_policy, false, page, count); page[sz] = '\n'; sz++; page[sz] = '\0'; @@ -1796,73 +1830,92 @@ static int lprocfs_wr_hsm_policy(struct file *file, const char *buffer, { struct mdt_device *mdt = data; struct coordinator *cdt = &mdt->mdt_coordinator; - int sz; - char *start, *end; - __u64 policy; - int set; + char *start, *token, sign; char *buf; + __u64 policy; + __u64 add_mask, remove_mask, set_mask; + int sz; + int rc; ENTRY; - if (strncmp(buffer, "help", 4) == 0) { - sz = PAGE_SIZE; - OBD_ALLOC(buf, sz); - if (!buf) - RETURN(-ENOMEM); - - hsm_policy_bit2str(CDT_POLICY_MASK, buf, sz); - CWARN("Supported policies are: %s\n", buf); - OBD_FREE(buf, sz); - RETURN(count); - } + if (count + 1 > PAGE_SIZE) + RETURN(-EINVAL); OBD_ALLOC(buf, count + 1); if (buf == NULL) RETURN(-ENOMEM); if (copy_from_user(buf, buffer, count)) - RETURN(-EFAULT); + GOTO(out, rc = -EFAULT); buf[count] = '\0'; + start = buf; + CDEBUG(D_HSM, "%s: receive new policy: '%s'\n", mdt_obd_name(mdt), + start); - policy = 0; + add_mask = remove_mask = set_mask = 0; do { - end = strchr(start, ' '); - if (end != NULL) - *end = '\0'; - switch (*start) { + token = strsep(&start, "\n "); + sign = *token; + + if (sign == '\0') + continue; + + if (sign == '-' || sign == '+') + token++; + + policy = hsm_policy_str2bit(token); + if (policy == 0) { + char *msg; + + sz = PAGE_SIZE; + OBD_ALLOC(msg, sz); + if (!msg) + GOTO(out, rc = -ENOMEM); + + hsm_policy_bit2str(0, false, msg, sz); + CWARN("%s: '%s' is unknown, " + "supported policies are: %s\n", mdt_obd_name(mdt), + token, msg); + OBD_FREE(msg, sz); + GOTO(out, rc = -EINVAL); + } + switch (sign) { case '-': - start++; - set = 0; + remove_mask |= policy; break; case '+': - start++; - set = 1; + add_mask |= policy; break; default: - set = 2; + set_mask |= policy; break; } - policy = hsm_policy_str2bit(start); - if (!policy) - break; - switch (set) { - case 0: - cdt->cdt_policy &= ~policy; - break; - case 1: - cdt->cdt_policy |= policy; - break; - case 2: - cdt->cdt_policy = policy; - break; - } + } while (start != NULL); + + CDEBUG(D_HSM, "%s: new policy: rm="LPX64" add="LPX64" set="LPX64"\n", + mdt_obd_name(mdt), remove_mask, add_mask, set_mask); - start = end + 1; - } while (end != NULL); + /* if no sign in all string, it is a clear and set + * if some sign found, all unsigned are converted + * to add + * P1 P2 = set to P1 and P2 + * P1 -P2 = add P1 clear P2 same as +P1 -P2 + */ + if (remove_mask == 0 && add_mask == 0) { + cdt->cdt_policy = set_mask; + } else { + cdt->cdt_policy |= set_mask | add_mask; + cdt->cdt_policy &= ~remove_mask; + } + + GOTO(out, rc = count); + +out: OBD_FREE(buf, count + 1); - RETURN(count); + RETURN(rc); } #define GENERATE_PROC_METHOD(VAR) \ @@ -1899,10 +1952,10 @@ static int lprocfs_wr_hsm_##VAR(struct file *file, const char *buffer, \ } GENERATE_PROC_METHOD(cdt_loop_period) -GENERATE_PROC_METHOD(cdt_delay) -GENERATE_PROC_METHOD(cdt_timeout) -GENERATE_PROC_METHOD(cdt_max_request) -GENERATE_PROC_METHOD(cdt_archive_id) +GENERATE_PROC_METHOD(cdt_grace_delay) +GENERATE_PROC_METHOD(cdt_active_req_timeout) +GENERATE_PROC_METHOD(cdt_max_requests) +GENERATE_PROC_METHOD(cdt_default_archive_id) /* * procfs write method for MDT/hsm_control @@ -1932,10 +1985,24 @@ int lprocfs_wr_hsm_cdt_control(struct file *file, const char *buffer, rc = mdt_hsm_cdt_start(mdt); } } else if (strncmp(buffer, CDT_STOP_CMD, strlen(CDT_STOP_CMD)) == 0) { - cdt->cdt_state = CDT_STOPPING; + if ((cdt->cdt_state == CDT_STOPPING) || + (cdt->cdt_state == CDT_STOPPED)) { + CERROR("%s: Coordinator already stopped\n", + mdt_obd_name(mdt)); + rc = -EALREADY; + } else { + cdt->cdt_state = CDT_STOPPING; + } } else if (strncmp(buffer, CDT_DISABLE_CMD, strlen(CDT_DISABLE_CMD)) == 0) { - cdt->cdt_state = CDT_DISABLE; + if ((cdt->cdt_state == CDT_STOPPING) || + (cdt->cdt_state == CDT_STOPPED)) { + CERROR("%s: Coordinator is stopped\n", + mdt_obd_name(mdt)); + rc = -EINVAL; + } else { + cdt->cdt_state = CDT_DISABLE; + } } else if (strncmp(buffer, CDT_PURGE_CMD, strlen(CDT_PURGE_CMD)) == 0) { rc = hsm_cancel_all_actions(mdt); } else if (strncmp(buffer, CDT_HELP_CMD, strlen(CDT_HELP_CMD)) == 0) { @@ -1984,27 +2051,184 @@ int lprocfs_rd_hsm_cdt_control(char *page, char **start, off_t off, RETURN(sz); } +static int +lprocfs_rd_hsm_request_mask(char *page, char **start, off_t off, + int count, int *eof, __u64 mask) +{ + int i, rc = 0; + ENTRY; + + for (i = 0; i < 8 * sizeof(mask); i++) { + if (mask & (1UL << i)) + rc += snprintf(page + rc, count - rc, "%s%s", + rc == 0 ? "" : " ", + hsm_copytool_action2name(i)); + } + + rc += snprintf(page + rc, count - rc, "\n"); + + RETURN(rc); +} + +static int +lprocfs_rd_hsm_user_request_mask(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct mdt_device *mdt = data; + struct coordinator *cdt = &mdt->mdt_coordinator; + + return lprocfs_rd_hsm_request_mask(page, start, off, count, eof, + cdt->cdt_user_request_mask); +} + +static int +lprocfs_rd_hsm_group_request_mask(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct mdt_device *mdt = data; + struct coordinator *cdt = &mdt->mdt_coordinator; + + return lprocfs_rd_hsm_request_mask(page, start, off, count, eof, + cdt->cdt_group_request_mask); +} + +static int +lprocfs_rd_hsm_other_request_mask(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct mdt_device *mdt = data; + struct coordinator *cdt = &mdt->mdt_coordinator; + + return lprocfs_rd_hsm_request_mask(page, start, off, count, eof, + cdt->cdt_other_request_mask); +} + +static inline enum hsm_copytool_action +hsm_copytool_name2action(const char *name) +{ + if (strcasecmp(name, "NOOP") == 0) + return HSMA_NONE; + else if (strcasecmp(name, "ARCHIVE") == 0) + return HSMA_ARCHIVE; + else if (strcasecmp(name, "RESTORE") == 0) + return HSMA_RESTORE; + else if (strcasecmp(name, "REMOVE") == 0) + return HSMA_REMOVE; + else if (strcasecmp(name, "CANCEL") == 0) + return HSMA_CANCEL; + else + return -1; +} + +static int +lprocfs_wr_hsm_request_mask(struct file *file, const char __user *user_buf, + unsigned long user_count, __u64 *mask) +{ + char *buf, *pos, *name; + size_t buf_size; + __u64 new_mask = 0; + int rc; + ENTRY; + + if (!(user_count < 4096)) + RETURN(-ENOMEM); + + buf_size = user_count + 1; + + OBD_ALLOC(buf, buf_size); + if (buf == NULL) + RETURN(-ENOMEM); + + if (copy_from_user(buf, user_buf, buf_size - 1)) + GOTO(out, rc = -EFAULT); + + buf[buf_size - 1] = '\0'; + + pos = buf; + while ((name = strsep(&pos, " \t\v\n")) != NULL) { + int action; + + if (*name == '\0') + continue; + + action = hsm_copytool_name2action(name); + if (action < 0) + GOTO(out, rc = -EINVAL); + + new_mask |= (1UL << action); + } + + *mask = new_mask; + rc = user_count; +out: + OBD_FREE(buf, buf_size); + + RETURN(rc); +} + +static int +lprocfs_wr_hsm_user_request_mask(struct file *file, const char __user *buf, + unsigned long count, void *data) +{ + struct mdt_device *mdt = data; + struct coordinator *cdt = &mdt->mdt_coordinator; + + return lprocfs_wr_hsm_request_mask(file, buf, count, + &cdt->cdt_user_request_mask); +} + +static int +lprocfs_wr_hsm_group_request_mask(struct file *file, const char __user *buf, + unsigned long count, void *data) +{ + struct mdt_device *mdt = data; + struct coordinator *cdt = &mdt->mdt_coordinator; + + return lprocfs_wr_hsm_request_mask(file, buf, count, + &cdt->cdt_group_request_mask); +} + +static int +lprocfs_wr_hsm_other_request_mask(struct file *file, const char __user *buf, + unsigned long count, void *data) +{ + struct mdt_device *mdt = data; + struct coordinator *cdt = &mdt->mdt_coordinator; + + return lprocfs_wr_hsm_request_mask(file, buf, count, + &cdt->cdt_other_request_mask); +} + static struct lprocfs_vars lprocfs_mdt_hsm_vars[] = { - { "agents", NULL, NULL, NULL, &mdt_hsm_agent_fops, 0 }, - { "agent_actions", NULL, NULL, NULL, - &mdt_agent_actions_fops, 0444 }, - { "archive_id", lprocfs_rd_hsm_cdt_archive_id, - lprocfs_wr_hsm_cdt_archive_id, - NULL, NULL, 0 }, - { "grace_delay", lprocfs_rd_hsm_cdt_delay, - lprocfs_wr_hsm_cdt_delay, - NULL, NULL, 0 }, - { "loop_period", lprocfs_rd_hsm_cdt_loop_period, - lprocfs_wr_hsm_cdt_loop_period, - NULL, NULL, 0 }, - { "max_requests", lprocfs_rd_hsm_cdt_max_request, - lprocfs_wr_hsm_cdt_max_request, - NULL, NULL, 0 }, - { "policy", lprocfs_rd_hsm_policy, lprocfs_wr_hsm_policy, - NULL, NULL, 0 }, - { "request_timeout", lprocfs_rd_hsm_cdt_timeout, - lprocfs_wr_hsm_cdt_timeout, - NULL, NULL, 0 }, - { "requests", NULL, NULL, NULL, &mdt_hsm_request_fops, 0 }, + { "agents", NULL, NULL, NULL, &mdt_hsm_agent_fops, + 0 }, + { "actions", NULL, NULL, NULL, &mdt_hsm_actions_fops, + 0444 }, + { "default_archive_id", lprocfs_rd_hsm_cdt_default_archive_id, + lprocfs_wr_hsm_cdt_default_archive_id, + NULL, NULL, 0 }, + { "grace_delay", lprocfs_rd_hsm_cdt_grace_delay, + lprocfs_wr_hsm_cdt_grace_delay, + NULL, NULL, 0 }, + { "loop_period", lprocfs_rd_hsm_cdt_loop_period, + lprocfs_wr_hsm_cdt_loop_period, + NULL, NULL, 0 }, + { "max_requests", lprocfs_rd_hsm_cdt_max_requests, + lprocfs_wr_hsm_cdt_max_requests, + NULL, NULL, 0 }, + { "policy", lprocfs_rd_hsm_policy, + lprocfs_wr_hsm_policy, + NULL, NULL, 0 }, + { "active_request_timeout", lprocfs_rd_hsm_cdt_active_req_timeout, + lprocfs_wr_hsm_cdt_active_req_timeout, + NULL, NULL, 0 }, + { "active_requests", NULL, NULL, NULL, + &mdt_hsm_active_requests_fops, 0 }, + { "user_request_mask", lprocfs_rd_hsm_user_request_mask, + lprocfs_wr_hsm_user_request_mask, }, + { "group_request_mask", lprocfs_rd_hsm_group_request_mask, + lprocfs_wr_hsm_group_request_mask, }, + { "other_request_mask", lprocfs_rd_hsm_other_request_mask, + lprocfs_wr_hsm_other_request_mask, }, { 0 } };