Whamcloud - gitweb
LU-3866 hsm: permission checks on HSM operations
[fs/lustre-release.git] / lustre / mdt / mdt_coordinator.c
index fbde2c5..9d5d4cd 100644 (file)
@@ -385,7 +385,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 +407,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,10 +450,6 @@ 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;
@@ -876,6 +895,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_delay = 60;
+       cdt->cdt_loop_period = 10;
+       cdt->cdt_max_request = 3;
+       cdt->cdt_policy = CDT_DEFAULT_POLICY;
+       cdt->cdt_timeout = 3600;
+
        RETURN(0);
 }
 
@@ -924,18 +952,18 @@ int mdt_hsm_cdt_start(struct mdt_device *mdt)
 
        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 */
@@ -988,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;
@@ -1930,7 +1954,7 @@ 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_default_archive_id)
 
 /*
  * procfs write method for MDT/hsm_control
@@ -2012,12 +2036,160 @@ 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,
+       { "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,
@@ -2034,5 +2206,11 @@ static struct lprocfs_vars lprocfs_mdt_hsm_vars[] = {
                                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 }
 };