* \param mti [IN] context
* \param fid [IN] object fid
* \param hsm [OUT] HSM meta data
- * \retval obj
+ * \retval obj or error (-ENOENT if not found)
*/
struct mdt_object *mdt_hsm_get_md_hsm(struct mdt_thread_info *mti,
const struct lu_fid *fid,
prefix, hal->hal_version, hal->hal_count,
hal->hal_compound_id, hal->hal_archive_id, hal->hal_flags);
- hai = hai_zero(hal);
+ hai = hai_first(hal);
for (i = 0; i < hal->hal_count; i++) {
sz = hai->hai_len - sizeof(*hai);
CDEBUG(level, "%s %d: fid="DFID" dfid="DFID
continue;
}
}
- if ((found == -1) && (empty_slot == -1))
+ 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
hsd->request[empty_slot].hal = hal;
hsd->request_cnt++;
found = empty_slot;
- hai = hai_zero(hal);
+ hai = hai_first(hal);
} else {
/* request is known */
/* we check if record archive num is the same as the
hsd->request[found].hal = hal_buffer;
hsd->request[found].hal_sz = sz;
}
- hai = hai_zero(hsd->request[found].hal);
+ hai = hai_first(hsd->request[found].hal);
for (i = 0; i < hsd->request[found].hal->hal_count;
i++)
hai = hai_next(hai);
* \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;
}
/**
+ * 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
ENTRY;
cdt->cdt_thread.t_flags = SVC_RUNNING;
- cfs_waitq_signal(&cdt->cdt_thread.t_ctl_waitq);
+ wake_up(&cdt->cdt_thread.t_ctl_waitq);
CDEBUG(D_HSM, "%s: coordinator thread starting, pid=%d\n",
- mdt_obd_name(mdt), cfs_curproc_pid());
+ 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;
CDEBUG(D_HSM, "coordinator resumes\n");
- if ((cdt->cdt_thread.t_flags & SVC_STOPPING) ||
- (cdt->cdt_state == CDT_STOPPING)) {
+ if (cdt->cdt_thread.t_flags & SVC_STOPPING ||
+ cdt->cdt_state == CDT_STOPPING) {
cdt->cdt_thread.t_flags &= ~SVC_STOPPING;
rc = 0;
break;
kuc_free(hal, hsd.request[i].hal_used_sz);
continue;
}
- hai = hai_zero(hal);
+ hai = hai_first(hal);
for (j = 0; j < hsd.request[i].hal->hal_count; j++) {
cookies[j] = hai->hai_cookie;
hai = hai_next(hai);
* and cdt cleaning will be done by event sender
*/
cdt->cdt_thread.t_flags = SVC_STOPPED;
- cfs_waitq_signal(&cdt->cdt_thread.t_ctl_waitq);
+ wake_up(&cdt->cdt_thread.t_ctl_waitq);
}
if (rc != 0)
CERROR("%s: coordinator thread exiting, process=%d, rc=%d\n",
- mdt_obd_name(mdt), cfs_curproc_pid(), rc);
+ mdt_obd_name(mdt), current_pid(), rc);
else
CDEBUG(D_HSM, "%s: coordinator thread exiting, process=%d,"
" no error\n",
- mdt_obd_name(mdt), cfs_curproc_pid());
+ mdt_obd_name(mdt), current_pid());
return rc;
}
larr = (struct llog_agent_req_rec *)hdr;
hai = &larr->arr_hai;
- if ((hai->hai_action != HSMA_RESTORE) ||
- agent_req_in_final_state(larr->arr_status))
+ 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);
/* restore request not in a final state */
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,
uc->uc_fsgid = 0;
uc->uc_suppgids[0] = -1;
uc->uc_suppgids[1] = -1;
- uc->uc_cap = 0;
+ uc->uc_cap = CFS_CAP_FS_MASK;
uc->uc_umask = 0777;
uc->uc_ginfo = NULL;
uc->uc_identity = NULL;
/* wake up coordinator */
cdt->cdt_thread.t_flags = SVC_EVENT;
- cfs_waitq_signal(&cdt->cdt_thread.t_ctl_waitq);
+ wake_up(&cdt->cdt_thread.t_ctl_waitq);
RETURN(0);
}
cdt->cdt_state = CDT_STOPPED;
- cfs_waitq_init(&cdt->cdt_thread.t_ctl_waitq);
+ init_waitqueue_head(&cdt->cdt_thread.t_ctl_waitq);
mutex_init(&cdt->cdt_llog_lock);
init_rwsem(&cdt->cdt_agent_lock);
init_rwsem(&cdt->cdt_request_lock);
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_delay = 60;
+ cdt->cdt_loop_period = 10;
+ cdt->cdt_max_request = 3;
+ cdt->cdt_policy = CDT_DEFAULT_POLICY;
+ cdt->cdt_timeout = 3600;
+
RETURN(0);
}
int rc;
void *ptr;
struct mdt_thread_info *cdt_mti;
- cfs_task_t *task;
+ struct task_struct *task;
ENTRY;
/* functions defined but not yet used
RETURN(-EALREADY);
}
+ CLASSERT(1 << (CDT_POLICY_SHIFT_COUNT - 1) == CDT_POLICY_LAST);
cdt->cdt_policy = CDT_DEFAULT_POLICY;
+
cdt->cdt_state = CDT_INIT;
- cfs_atomic_set(&cdt->cdt_compound_id, cfs_time_current_sec());
+ 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;
+
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 = 0;
}
- cfs_wait_event(cdt->cdt_thread.t_ctl_waitq,
+ wait_event(cdt->cdt_thread.t_ctl_waitq,
(cdt->cdt_thread.t_flags & SVC_RUNNING));
cdt->cdt_state = CDT_RUNNING;
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;
- cfs_waitq_signal(&cdt->cdt_thread.t_ctl_waitq);
- cfs_wait_event(cdt->cdt_thread.t_ctl_waitq,
- cdt->cdt_thread.t_flags & SVC_STOPPED);
+ 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_state = CDT_STOPPED;
ENTRY;
/* register request in memory list */
- hai = hai_zero(hal);
+ hai = hai_first(hal);
for (i = 0; i < hal->hal_count; i++, hai = hai_next(hai)) {
struct cdt_agent_req *car;
*status = ARS_SUCCEED;
break;
default:
- *status = (((cdt->cdt_policy &
- CDT_NORETRY_ACTION) ||
- !(pgs->hpk_flags & HP_FLAG_RETRY)) ?
+ *status = (cdt->cdt_policy & CDT_NORETRY_ACTION ||
+ !(pgs->hpk_flags & HP_FLAG_RETRY) ?
ARS_FAILED : ARS_WAITING);
break;
}
* a crasy CT no need to manage DIRTY
*/
if (rc == 0)
- hsm_set_cl_flags(&cl_flags, ((mh.mh_flags & HS_DIRTY) ?
- CLF_HSM_DIRTY : 0));
+ hsm_set_cl_flags(&cl_flags,
+ mh.mh_flags & HS_DIRTY ? CLF_HSM_DIRTY : 0);
/* unlock is done later, after layout lock management */
if (is_mh_changed)
/* we give back layout lock only if restore was successful or
* if restore was canceled or if policy is to not retry
* 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 &&
+ (pgs->hpk_errval == 0 || pgs->hpk_errval == ECANCELED ||
+ cdt->cdt_policy & CDT_NORETRY_ACTION)) {
struct cdt_restore_handle *crh;
/* restore in data FID done, we swap the layouts
/* just give back layout lock, we keep
* the reference which is given back
* later with the lock for HSM flags */
- if (!IS_ERR(obj))
+ if (!IS_ERR(obj) && crh != NULL)
mdt_object_unlock(mti, obj, &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)) {
+ if (obj != NULL && !IS_ERR(obj)) {
mo_changelog(env, CL_HSM, cl_flags,
mdt_object_child(obj));
mdt_object_put(mti->mti_env, obj);
" on fid="DFID"\n",
mdt_obd_name(mdt),
pgs->hpk_cookie, PFID(&pgs->hpk_fid));
+ if (car == NULL)
+ RETURN(-ENOENT);
RETURN(PTR_ERR(car));
}
/* 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)))
+ 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)) &&
+ 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 "LPX64
larr = (struct llog_agent_req_rec *)hdr;
hcad = data;
- if ((larr->arr_status == ARS_WAITING) ||
- (larr->arr_status == ARS_STARTED)) {
+ if (larr->arr_status == ARS_WAITING ||
+ 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);
hal_len = sizeof(*hal) + cfs_size_round(MTI_NAME_MAXLEN + 1) +
cfs_size_round(car->car_hai->hai_len);
- if ((hal_len > hal_sz) && (hal_sz > 0)) {
+ if (hal_len > hal_sz && hal_sz > 0) {
/* not enough room, free old buffer */
OBD_FREE(hal, hal_sz);
hal = NULL;
hal->hal_flags = car->car_flags;
hal->hal_count = 0;
- hai = hai_zero(hal);
+ hai = hai_first(hal);
memcpy(hai, car->car_hai, car->car_hai->hai_len);
hai->hai_action = HSMA_CANCEL;
hal->hal_count = 1;
switch (hai->hai_action) {
case HSMA_ARCHIVE:
if (!(hsm_flags & HS_NOARCHIVE) &&
- ((hsm_flags & HS_DIRTY) || !(hsm_flags & HS_ARCHIVED)))
+ (hsm_flags & HS_DIRTY || !(hsm_flags & HS_ARCHIVED)))
is_compat = true;
break;
case HSMA_RESTORE:
if (!(hsm_flags & HS_DIRTY) && (hsm_flags & HS_RELEASED) &&
- (hsm_flags & HS_ARCHIVED) && !(hsm_flags & HS_LOST))
+ hsm_flags & HS_ARCHIVED && !(hsm_flags & HS_LOST))
is_compat = true;
break;
case HSMA_REMOVE:
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 int hsm_policy_bit2str(const __u64 mask, const bool hexa, char *buffer,
+ int count)
{
int i, j, sz;
char *ptr;
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);
}
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';
{
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)
if (copy_from_user(buf, buffer, count))
RETURN(-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)
+ RETURN(-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);
- 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);
}
#define GENERATE_PROC_METHOD(VAR) \
GENERATE_PROC_METHOD(cdt_delay)
GENERATE_PROC_METHOD(cdt_timeout)
GENERATE_PROC_METHOD(cdt_max_request)
+GENERATE_PROC_METHOD(cdt_default_archive_id)
/*
* procfs write method for MDT/hsm_control
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 },
+ { "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_delay,
lprocfs_wr_hsm_cdt_delay,
NULL, NULL, 0 },
lprocfs_wr_hsm_cdt_timeout,
NULL, NULL, 0 },
{ "requests", NULL, NULL, NULL, &mdt_hsm_request_fops, 0 },
- { 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, },
+ { NULL }
};