Whamcloud - gitweb
LU-4563 Fix unsafe userspace access in many proc files
[fs/lustre-release.git] / lustre / mdt / mdt_coordinator.c
index b11723d..651ed7a 100644 (file)
@@ -41,7 +41,6 @@
 #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"
@@ -973,7 +972,7 @@ int mdt_hsm_cdt_start(struct mdt_device *mdt)
        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");
@@ -1157,9 +1156,11 @@ out:
  * \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;
@@ -1182,15 +1183,28 @@ static int hsm_swap_layouts(struct mdt_thread_info *mti,
        /* 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);
@@ -1320,8 +1334,10 @@ static int hsm_cdt_request_completed(struct mdt_thread_info *mti,
                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;
@@ -1378,7 +1394,7 @@ unlock:
                 * 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;
@@ -1846,7 +1862,8 @@ static int lprocfs_wr_hsm_policy(struct file *file, const char *buffer,
                RETURN(-ENOMEM);
 
        if (copy_from_user(buf, buffer, count))
-               RETURN(-EFAULT);
+               GOTO(out, rc = -EFAULT);
+
        buf[count] = '\0';
 
        start = buf;
@@ -1871,7 +1888,7 @@ static int lprocfs_wr_hsm_policy(struct file *file, const char *buffer,
                        sz = PAGE_SIZE;
                        OBD_ALLOC(msg, sz);
                        if (!msg)
-                               RETURN(-ENOMEM);
+                               GOTO(out, rc = -ENOMEM);
 
                        hsm_policy_bit2str(0, false, msg, sz);
                        CWARN("%s: '%s' is unknown, "
@@ -1965,32 +1982,57 @@ GENERATE_PROC_METHOD(cdt_default_archive_id)
 #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,
+int lprocfs_wr_hsm_cdt_control(struct file *file, const char __user *buffer,
                               unsigned long count, void *data)
 {
        struct obd_device       *obd = data;
        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;