#include <lustre_net.h>
#include <lustre_export.h>
#include <obd.h>
-#include <obd_lov.h>
#include <lprocfs_status.h>
#include <lustre_log.h>
#include "mdt_internal.h"
-static struct lprocfs_vars lprocfs_mdt_hsm_vars[];
+static struct lprocfs_seq_vars lprocfs_mdt_hsm_vars[];
/**
* get obj and HSM attributes on a fid
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;
/* 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;
RETURN(-ENOMEM);
}
hal->hal_version = HAL_VERSION;
- strncpy(hal->hal_fsname, hsd->fs_name,
- MTI_NAME_MAXLEN);
- hal->hal_fsname[MTI_NAME_MAXLEN] = '\0';
+ strlcpy(hal->hal_fsname, hsd->fs_name,
+ MTI_NAME_MAXLEN + 1);
hal->hal_compound_id = larr->arr_compound_id;
hal->hal_archive_id = larr->arr_archive_id;
hal->hal_flags = larr->arr_flags;
/* 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(): "
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;
* \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;
ENTRY;
/* init /proc entries, failure is not critical */
- cdt->cdt_proc_dir = lprocfs_register("hsm",
+ cdt->cdt_proc_dir = lprocfs_seq_register("hsm",
mdt2obd_dev(mdt)->obd_proc_entry,
lprocfs_mdt_hsm_vars, mdt);
if (IS_ERR(cdt->cdt_proc_dir)) {
}
/**
+ * 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_seq_vars *hsm_cdt_get_proc_vars(void)
+{
+ return lprocfs_mdt_hsm_vars;
+}
+
+/**
* coordinator thread
* \param data [IN] obd device
* \retval 0 success
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);
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;
}
/* 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;
/* 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)
}
/* 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);
larr = (struct llog_agent_req_rec *)hdr;
hai = &larr->arr_hai;
+ if (hai->hai_cookie > cdt->cdt_last_cookie)
+ /* update the cookie to avoid collision */
+ cdt->cdt_last_cookie = hai->hai_cookie + 1;
+
if (hai->hai_action != HSMA_RESTORE ||
agent_req_in_final_state(larr->arr_status))
RETURN(0);
crh->extent.end = hai->hai_extent.offset + hai->hai_extent.length;
*/
crh->crh_extent.start = 0;
- crh->crh_extent.end = OBD_OBJECT_EOF;
+ crh->crh_extent.end = hai->hai_extent.length;
/* get the layout lock */
mdt_lock_reg_init(&crh->crh_lh, LCK_EX);
child = mdt_object_find_lock(mti, &crh->crh_fid, &crh->crh_lh,
init_rwsem(&cdt->cdt_request_lock);
mutex_init(&cdt->cdt_restore_lock);
- CFS_INIT_LIST_HEAD(&cdt->cdt_requests);
- CFS_INIT_LIST_HEAD(&cdt->cdt_agents);
- CFS_INIT_LIST_HEAD(&cdt->cdt_restore_hdl);
+ INIT_LIST_HEAD(&cdt->cdt_requests);
+ INIT_LIST_HEAD(&cdt->cdt_agents);
+ INIT_LIST_HEAD(&cdt->cdt_restore_hdl);
rc = lu_env_init(&cdt->cdt_env, LCT_MD_THREAD);
if (rc < 0)
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;
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);
}
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 */
rc = mdt_hsm_pending_restore(cdt_mti);
if (rc)
CERROR("%s: cannot take the layout locks needed"
- " for registered restore: %d",
+ " for registered restore: %d\n",
mdt_obd_name(mdt), rc);
task = kthread_run(mdt_coordinator, cdt_mti, "hsm_cdtr");
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;
* \param mti [IN] context
* \param fid1 [IN]
* \param fid2 [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)
+ const lustre_fid *fid, const lustre_fid *dfid,
+ struct md_hsm *mh_common)
{
struct mdt_device *mdt = mti->mti_mdt;
struct mdt_object *child1, *child2;
/* 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)) {
- rc = mo_swap_layouts(mti->mti_env, mdt_object_child(child1),
- mdt_object_child(child2), 0);
- } else {
+ if (!mdt_object_exists(child2)) {
CERROR("%s: Copytool has closed volatile file "DFID"\n",
mdt_obd_name(mti->mti_mdt), PFID(dfid));
- rc = -ENOENT;
+ GOTO(out_child2, rc = -ENOENT);
}
+ /* Since we only handle restores here, unconditionally use
+ * SWAP_LAYOUTS_MDS_HSM flag to ensure original layout will
+ * be preserved in case of failure during swap_layout and not
+ * leave a file in an intermediate but incoherent state.
+ * But need to setup HSM xattr of data FID before, reuse
+ * mti and mh presets for FID in hsm_cdt_request_completed(),
+ * only need to clear RELEASED and DIRTY.
+ */
+ mh_common->mh_flags &= ~(HS_RELEASED | HS_DIRTY);
+ rc = mdt_hsm_attr_set(mti, child2, mh_common);
+ if (rc == 0)
+ rc = mo_swap_layouts(mti->mti_env,
+ mdt_object_child(child1),
+ mdt_object_child(child2),
+ SWAP_LAYOUTS_MDS_HSM);
+out_child2:
mdt_object_unlock_put(mti, child2, lh2, 1);
out_child1:
mdt_object_put(mti->mti_env, child1);
case HSMA_RESTORE:
hsm_set_cl_event(&cl_flags, HE_RESTORE);
- /* clear RELEASED and DIRTY */
- mh.mh_flags &= ~(HS_RELEASED | HS_DIRTY);
+ /* do not clear RELEASED and DIRTY here
+ * this will occur in hsm_swap_layouts()
+ */
+
/* Restoring has changed the file version on
* disk. */
mh.mh_arch_ver = pgs->hpk_data_version;
* 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);
+ &car->car_hai->hai_dfid, &mh);
if (rc) {
if (cdt->cdt_policy & CDT_NORETRY_ACTION)
*status = ARS_FAILED;
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 },
};
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;
}
/**
* 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 void hsm_policy_bit2str(struct seq_file *m, const __u64 mask,
+ const bool hexa)
{
- int i, j, sz;
- char *ptr;
+ int i, j;
__u64 bit;
ENTRY;
- ptr = buffer;
- sz = snprintf(buffer, count, "("LPX64") ", mask);
- ptr += sz;
- count -= sz;
- for (i = 0; i < (sizeof(mask) * 8); i++) {
+ if (hexa)
+ seq_printf(m, "("LPX64") ", mask);
+
+ 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)
+ seq_printf(m, "[%s] ", hsm_policy_names[j].name);
+ else
+ seq_printf(m, "%s ", hsm_policy_names[j].name);
}
- RETURN(ptr - buffer);
+ /* remove last ' ' */
+ m->count--;
+ seq_putc(m, '\0');
}
/* methods to read/write HSM policy flags */
-static int lprocfs_rd_hsm_policy(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static int mdt_hsm_policy_seq_show(struct seq_file *m, void *data)
{
- struct mdt_device *mdt = data;
+ struct mdt_device *mdt = m->private;
struct coordinator *cdt = &mdt->mdt_coordinator;
- int sz;
ENTRY;
- sz = hsm_policy_bit2str(cdt->cdt_policy, page, count);
- page[sz] = '\n';
- sz++;
- page[sz] = '\0';
- *eof = 1;
- RETURN(sz);
+ hsm_policy_bit2str(m, cdt->cdt_policy, false);
+ RETURN(0);
}
-static int lprocfs_wr_hsm_policy(struct file *file, const char *buffer,
- unsigned long count, void *data)
+static ssize_t
+mdt_hsm_policy_seq_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *off)
{
- struct mdt_device *mdt = data;
+ struct seq_file *m = file->private_data;
+ struct mdt_device *mdt = m->private;
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 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) {
+ CWARN("%s: '%s' is unknown, "
+ "supported policies are:\n", mdt_obd_name(mdt),
+ token);
+ hsm_policy_bit2str(m, 0, false);
+ 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);
- start = end + 1;
- } while (end != NULL);
+ CDEBUG(D_HSM, "%s: new policy: rm="LPX64" add="LPX64" set="LPX64"\n",
+ mdt_obd_name(mdt), remove_mask, add_mask, set_mask);
+
+ /* 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);
}
+LPROC_SEQ_FOPS(mdt_hsm_policy);
#define GENERATE_PROC_METHOD(VAR) \
-static int lprocfs_rd_hsm_##VAR(char *page, char **start, off_t off, \
- int count, int *eof, void *data) \
+static int mdt_hsm_##VAR##_seq_show(struct seq_file *m, void *data) \
{ \
- struct mdt_device *mdt = data; \
+ struct mdt_device *mdt = m->private; \
struct coordinator *cdt = &mdt->mdt_coordinator; \
- int sz; \
ENTRY; \
\
- sz = snprintf(page, count, LPU64"\n", (__u64)cdt->VAR); \
- *eof = 1; \
- RETURN(sz); \
+ seq_printf(m, LPU64"\n", (__u64)cdt->VAR); \
+ RETURN(0); \
} \
-static int lprocfs_wr_hsm_##VAR(struct file *file, const char *buffer, \
- unsigned long count, void *data) \
+static ssize_t \
+mdt_hsm_##VAR##_seq_write(struct file *file, const char __user *buffer, \
+ size_t count, loff_t *off) \
\
{ \
- struct mdt_device *mdt = data; \
+ struct seq_file *m = file->private_data; \
+ struct mdt_device *mdt = m->private; \
struct coordinator *cdt = &mdt->mdt_coordinator; \
int val; \
int rc; \
RETURN(count); \
} \
RETURN(-EINVAL); \
-}
+} \
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
#define CDT_DISABLE_CMD "disabled"
#define CDT_PURGE_CMD "purge"
#define CDT_HELP_CMD "help"
+#define CDT_MAX_CMD_LEN 10
-int lprocfs_wr_hsm_cdt_control(struct file *file, const char *buffer,
- unsigned long count, void *data)
+ssize_t
+mdt_hsm_cdt_control_seq_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *off)
{
- struct obd_device *obd = data;
+ struct seq_file *m = file->private_data;
+ struct obd_device *obd = m->private;
struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
struct coordinator *cdt = &(mdt->mdt_coordinator);
int rc, usage = 0;
+ char kernbuf[CDT_MAX_CMD_LEN];
ENTRY;
+ if (count == 0 || count >= sizeof(kernbuf))
+ RETURN(-EINVAL);
+
+ if (copy_from_user(kernbuf, buffer, count))
+ RETURN(-EFAULT);
+ kernbuf[count] = 0;
+
+ if (kernbuf[count - 1] == '\n')
+ kernbuf[count - 1] = 0;
+
rc = 0;
- if (strncmp(buffer, CDT_ENABLE_CMD, strlen(CDT_ENABLE_CMD)) == 0) {
+ if (strcmp(kernbuf, CDT_ENABLE_CMD) == 0) {
if (cdt->cdt_state == CDT_DISABLE) {
cdt->cdt_state = CDT_RUNNING;
mdt_hsm_cdt_wakeup(mdt);
} else {
rc = mdt_hsm_cdt_start(mdt);
}
- } else if (strncmp(buffer, CDT_STOP_CMD, strlen(CDT_STOP_CMD)) == 0) {
- cdt->cdt_state = CDT_STOPPING;
- } else if (strncmp(buffer, CDT_DISABLE_CMD,
- strlen(CDT_DISABLE_CMD)) == 0) {
- cdt->cdt_state = CDT_DISABLE;
- } else if (strncmp(buffer, CDT_PURGE_CMD, strlen(CDT_PURGE_CMD)) == 0) {
+ } else if (strcmp(kernbuf, CDT_STOP_CMD) == 0) {
+ 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 (strcmp(kernbuf, CDT_DISABLE_CMD) == 0) {
+ 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 (strcmp(kernbuf, CDT_PURGE_CMD) == 0) {
rc = hsm_cancel_all_actions(mdt);
- } else if (strncmp(buffer, CDT_HELP_CMD, strlen(CDT_HELP_CMD)) == 0) {
+ } else if (strcmp(kernbuf, CDT_HELP_CMD) == 0) {
usage = 1;
} else {
usage = 1;
RETURN(count);
}
-int lprocfs_rd_hsm_cdt_control(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+int mdt_hsm_cdt_control_seq_show(struct seq_file *m, void *data)
{
- struct obd_device *obd = data;
+ struct obd_device *obd = m->private;
struct coordinator *cdt;
- int sz;
ENTRY;
cdt = &(mdt_dev(obd->obd_lu_dev)->mdt_coordinator);
- *eof = 1;
if (cdt->cdt_state == CDT_INIT)
- sz = snprintf(page, count, "init\n");
+ seq_printf(m, "init\n");
else if (cdt->cdt_state == CDT_RUNNING)
- sz = snprintf(page, count, "enabled\n");
+ seq_printf(m, "enabled\n");
else if (cdt->cdt_state == CDT_STOPPING)
- sz = snprintf(page, count, "stopping\n");
+ seq_printf(m, "stopping\n");
else if (cdt->cdt_state == CDT_STOPPED)
- sz = snprintf(page, count, "stopped\n");
+ seq_printf(m, "stopped\n");
else if (cdt->cdt_state == CDT_DISABLE)
- sz = snprintf(page, count, "disabled\n");
+ seq_printf(m, "disabled\n");
else
- sz = snprintf(page, count, "unknown\n");
+ seq_printf(m, "unknown\n");
+
+ RETURN(0);
+}
+
+static int
+mdt_hsm_request_mask_show(struct seq_file *m, __u64 mask)
+{
+ int i, rc = 0;
+ 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));
+ }
+ rc += seq_printf(m, "\n");
+
+ RETURN(rc);
+}
+
+static int
+mdt_hsm_user_request_mask_seq_show(struct seq_file *m, void *data)
+{
+ struct mdt_device *mdt = m->private;
+ struct coordinator *cdt = &mdt->mdt_coordinator;
+
+ return mdt_hsm_request_mask_show(m, cdt->cdt_user_request_mask);
+}
+
+static int
+mdt_hsm_group_request_mask_seq_show(struct seq_file *m, void *data)
+{
+ struct mdt_device *mdt = m->private;
+ struct coordinator *cdt = &mdt->mdt_coordinator;
+
+ return mdt_hsm_request_mask_show(m, cdt->cdt_group_request_mask);
+}
+
+static int
+mdt_hsm_other_request_mask_seq_show(struct seq_file *m, void *data)
+{
+ struct mdt_device *mdt = m->private;
+ struct coordinator *cdt = &mdt->mdt_coordinator;
+
+ return mdt_hsm_request_mask_show(m, 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 ssize_t
+mdt_write_hsm_request_mask(struct file *file, const char __user *user_buf,
+ size_t 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 ssize_t
+mdt_hsm_user_request_mask_seq_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ struct seq_file *m = file->private_data;
+ struct mdt_device *mdt = m->private;
+ struct coordinator *cdt = &mdt->mdt_coordinator;
+
+ return mdt_write_hsm_request_mask(file, buf, count,
+ &cdt->cdt_user_request_mask);
+}
+
+static ssize_t
+mdt_hsm_group_request_mask_seq_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ struct seq_file *m = file->private_data;
+ struct mdt_device *mdt = m->private;
+ struct coordinator *cdt = &mdt->mdt_coordinator;
+
+ return mdt_write_hsm_request_mask(file, buf, count,
+ &cdt->cdt_group_request_mask);
+}
+
+static ssize_t
+mdt_hsm_other_request_mask_seq_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ struct seq_file *m = file->private_data;
+ struct mdt_device *mdt = m->private;
+ struct coordinator *cdt = &mdt->mdt_coordinator;
- RETURN(sz);
+ return mdt_write_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 },
+LPROC_SEQ_FOPS(mdt_hsm_cdt_loop_period);
+LPROC_SEQ_FOPS(mdt_hsm_cdt_grace_delay);
+LPROC_SEQ_FOPS(mdt_hsm_cdt_active_req_timeout);
+LPROC_SEQ_FOPS(mdt_hsm_cdt_max_requests);
+LPROC_SEQ_FOPS(mdt_hsm_cdt_default_archive_id);
+LPROC_SEQ_FOPS(mdt_hsm_user_request_mask);
+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[] = {
+ { .name = "agents",
+ .fops = &mdt_hsm_agent_fops },
+ { .name = "actions",
+ .fops = &mdt_hsm_actions_fops,
+ .proc_mode = 0444 },
+ { .name = "default_archive_id",
+ .fops = &mdt_hsm_cdt_default_archive_id_fops },
+ { .name = "grace_delay",
+ .fops = &mdt_hsm_cdt_grace_delay_fops },
+ { .name = "loop_period",
+ .fops = &mdt_hsm_cdt_loop_period_fops },
+ { .name = "max_requests",
+ .fops = &mdt_hsm_cdt_max_requests_fops },
+ { .name = "policy",
+ .fops = &mdt_hsm_policy_fops },
+ { .name = "active_request_timeout",
+ .fops = &mdt_hsm_cdt_active_req_timeout_fops },
+ { .name = "active_requests",
+ .fops = &mdt_hsm_active_requests_fops },
+ { .name = "user_request_mask",
+ .fops = &mdt_hsm_user_request_mask_fops, },
+ { .name = "group_request_mask",
+ .fops = &mdt_hsm_group_request_mask_fops, },
+ { .name = "other_request_mask",
+ .fops = &mdt_hsm_other_request_mask_fops, },
{ 0 }
};