Whamcloud - gitweb
LU-9611 lod: allow -1 for default stripe count/offset
[fs/lustre-release.git] / lustre / mdt / mdt_hsm_cdt_agent.c
index 158cced..d73b20a 100644 (file)
@@ -21,6 +21,8 @@
  */
 /*
  * (C) Copyright 2012 Commissariat a l'energie atomique et aux energies
+ *
+ * Copyright (c) 2016, Intel Corporation.
  *     alternatives
  *
  */
@@ -40,6 +42,7 @@
 #include <lustre_export.h>
 #include <lustre/lustre_user.h>
 #include <lprocfs_status.h>
+#include <lustre_kernelcomm.h>
 #include "mdt_internal.h"
 
 /*
@@ -48,7 +51,7 @@
 
 /*
  * find a hsm_agent by uuid
- * lock cdt_agent_lock needs to be hold by caller
+ * lock cdt_agent_lock needs to be held by caller
  * \param cdt [IN] coordinator
  * \param uuid [IN] agent UUID
  * \retval hsm_agent pointer or NULL if not found
@@ -305,6 +308,59 @@ int mdt_hsm_find_best_agent(struct coordinator *cdt, __u32 archive,
        RETURN(rc);
 }
 
+int mdt_hsm_send_action_to_each_archive(struct mdt_thread_info *mti,
+                                   struct hsm_action_item *hai)
+{
+       __u64 compound_id;
+       struct hsm_agent *ha;
+       __u32 archive_mask = 0;
+       struct coordinator *cdt = &mti->mti_mdt->mdt_coordinator;
+       int i;
+       /* return error by default in case all archive_ids have unregistered */
+       int rc = -EAGAIN;
+       ENTRY;
+
+       /* send action to all registered archive_ids */
+       down_read(&cdt->cdt_agent_lock);
+       list_for_each_entry(ha, &cdt->cdt_agents, ha_list) {
+               for (i = 0; (i < ha->ha_archive_cnt); i++) {
+                       /* only send once for each archive_id */
+                       if ((1 << ha->ha_archive_id[i]) & archive_mask)
+                               continue;
+                       archive_mask |= (1 << ha->ha_archive_id[i]);
+
+                       /* XXX: instead of creating one request record per
+                        * new action, it could make sense to gather
+                        * all for the same archive_id as one compound
+                        * request/id, like in mdt_hsm_add_actions() ?? */
+                       compound_id = atomic_inc_return(&cdt->cdt_compound_id);
+                       rc = mdt_agent_record_add(mti->mti_env, mti->mti_mdt,
+                                                 compound_id,
+                                                 ha->ha_archive_id[i], 0,
+                                                 hai);
+                       if (rc) {
+                               CERROR("%s: unable to add HSM remove request "
+                                      "for "DFID": rc=%d\n",
+                                      mdt_obd_name(mti->mti_mdt),
+                                      PFID(&hai->hai_fid), rc);
+                               break;
+                       } else {
+                               CDEBUG(D_HSM, "%s: added HSM remove request "
+                                      "for "DFID", archive_id=%d\n",
+                                      mdt_obd_name(mti->mti_mdt),
+                                      PFID(&hai->hai_fid),
+                                      ha->ha_archive_id[i]);
+                       }
+               }
+               /* early exit from loop due to error? */
+               if (i != ha->ha_archive_cnt)
+                       break;
+       }
+       up_read(&cdt->cdt_agent_lock);
+
+       RETURN(rc);
+}
+
 /**
  * send a compound request to the agent
  * \param mti [IN] context
@@ -333,6 +389,61 @@ int mdt_hsm_agent_send(struct mdt_thread_info *mti,
        ENTRY;
 
        rc = mdt_hsm_find_best_agent(cdt, hal->hal_archive_id, &uuid);
+       if (rc && hal->hal_archive_id == 0) {
+               uint notrmcount = 0;
+               int rc2 = 0;
+
+               /* special case of remove requests with no archive_id specified,
+                * and no agent registered to serve all archives, then create a
+                * set of new requests, each to be sent to each registered
+                * archives.
+                * Todo so, find all HSMA_REMOVE entries, and then :
+                *     _ set completed status as SUCCESS (or FAIL?)
+                *     _ create a new LLOG record for each archive_id
+                *       presently being served by any CT
+                */
+               hai = hai_first(hal);
+               for (i = 0; i < hal->hal_count; i++,
+                    hai = hai_next(hai)) {
+                       /* only removes are concerned */
+                       if (hai->hai_action != HSMA_REMOVE) {
+                               /* count if other actions than HSMA_REMOVE,
+                                * to return original error/rc */
+                               notrmcount++;
+                               continue;
+                       }
+
+                       /* send remove request to all registered archive_ids */
+                       rc2 = mdt_hsm_send_action_to_each_archive(mti, hai);
+                       if (rc2)
+                               break;
+
+                       /* only update original request as SUCCEED if it has
+                        * been successfully broadcasted to all available
+                        * archive_ids
+                        * XXX: this should only cause duplicates to be sent,
+                        * unless a method to record already successfully
+                        * reached archive_ids is implemented */
+                       rc2 = mdt_agent_record_update(mti->mti_env, mdt,
+                                                    &hai->hai_cookie,
+                                                    1, ARS_SUCCEED);
+                       if (rc2) {
+                               CERROR("%s: mdt_agent_record_update() "
+                                     "failed, cannot update "
+                                     "status to %s for cookie "
+                                     "%#llx: rc = %d\n",
+                                     mdt_obd_name(mdt),
+                                     agent_req_status2name(ARS_SUCCEED),
+                                     hai->hai_cookie, rc2);
+                               break;
+                       }
+               }
+               /* only remove requests with archive_id=0 */
+               if (notrmcount == 0)
+                       RETURN(rc2);
+
+       }
+
        if (rc) {
                CERROR("%s: Cannot find agent for archive %d: rc = %d\n",
                       mdt_obd_name(mdt), hal->hal_archive_id, rc);
@@ -343,75 +454,83 @@ int mdt_hsm_agent_send(struct mdt_thread_info *mti,
               hal->hal_archive_id);
 
        len = hal_size(hal);
-       if (kuc_ispayload(hal)) {
-               /* hal is already a kuc payload
-                * we do not need to alloc a new one
-                * this avoid a alloc/memcpy/free
-                */
-               buf = hal;
-       } else {
-               buf = kuc_alloc(len, KUC_TRANSPORT_HSM, HMT_ACTION_LIST);
-               if (IS_ERR(buf))
-                       RETURN(PTR_ERR(buf));
-               memcpy(buf, hal, len);
-       }
+       buf = kuc_alloc(len, KUC_TRANSPORT_HSM, HMT_ACTION_LIST);
+       if (IS_ERR(buf))
+               RETURN(PTR_ERR(buf));
+       memcpy(buf, hal, len);
 
        /* Check if request is still valid (cf file hsm flags) */
        fail_request = false;
        hai = hai_first(hal);
        for (i = 0; i < hal->hal_count; i++, hai = hai_next(hai)) {
-               if (hai->hai_action != HSMA_CANCEL) {
-                       struct mdt_object *obj;
-                       struct md_hsm hsm;
+               struct mdt_object *obj;
+               struct md_hsm hsm;
 
-                       obj = mdt_hsm_get_md_hsm(mti, &hai->hai_fid, &hsm);
-                       if (!IS_ERR(obj) && obj != NULL) {
-                               mdt_object_put(mti->mti_env, obj);
-                       } else {
-                               if (hai->hai_action == HSMA_REMOVE)
-                                       continue;
-
-                               if (obj == NULL) {
-                                       fail_request = true;
-                                       rc = mdt_agent_record_update(
-                                                            mti->mti_env, mdt,
-                                                            &hai->hai_cookie,
-                                                            1, ARS_FAILED);
-                                       if (rc) {
-                                               CERROR(
-                                             "%s: mdt_agent_record_update() "
-                                             "failed, cannot update "
-                                             "status to %s for cookie "
-                                             LPX64": rc = %d\n",
-                                             mdt_obd_name(mdt),
-                                             agent_req_status2name(ARS_FAILED),
-                                             hai->hai_cookie, rc);
-                                               GOTO(out_buf, rc);
-                                       }
-                                       continue;
-                               }
-                               GOTO(out_buf, rc = PTR_ERR(obj));
+               if (hai->hai_action == HSMA_CANCEL)
+                       continue;
+
+               obj = mdt_hsm_get_md_hsm(mti, &hai->hai_fid, &hsm);
+               if (!IS_ERR(obj)) {
+                       mdt_object_put(mti->mti_env, obj);
+               } else if (PTR_ERR(obj) == -ENOENT) {
+                       if (hai->hai_action == HSMA_REMOVE)
+                               continue;
+
+                       fail_request = true;
+                       rc = mdt_agent_record_update(mti->mti_env, mdt,
+                                                    &hai->hai_cookie,
+                                                    1, ARS_FAILED);
+                       if (rc < 0) {
+                               CERROR("%s: mdt_agent_record_update() failed, "
+                                      "cannot update status to %s for cookie "
+                                      "%#llx: rc = %d\n",
+                                      mdt_obd_name(mdt),
+                                      agent_req_status2name(ARS_FAILED),
+                                      hai->hai_cookie, rc);
+                               GOTO(out_buf, rc);
+                       }
+
+                       continue;
+               } else {
+                       GOTO(out_buf, rc = PTR_ERR(obj));
+               }
+
+               if (!mdt_hsm_is_action_compat(hai, hal->hal_archive_id,
+                                             hal->hal_flags, &hsm)) {
+                       /* incompatible request, we abort the request */
+                       /* next time coordinator will wake up, it will
+                        * make the same compound with valid only
+                        * records */
+                       fail_request = true;
+                       rc = mdt_agent_record_update(mti->mti_env, mdt,
+                                                    &hai->hai_cookie,
+                                                    1, ARS_FAILED);
+                       if (rc) {
+                               CERROR("%s: mdt_agent_record_update() failed, "
+                                      "cannot update status to %s for cookie "
+                                      "%#llx: rc = %d\n",
+                                      mdt_obd_name(mdt),
+                                      agent_req_status2name(ARS_FAILED),
+                                      hai->hai_cookie, rc);
+                               GOTO(out_buf, rc);
                        }
 
-                       if (!mdt_hsm_is_action_compat(hai, hal->hal_archive_id,
-                                                     hal->hal_flags, &hsm)) {
-                               /* incompatible request, we abort the request */
-                               /* next time coordinator will wake up, it will
-                                * make the same compound with valid only
-                                * records */
-                               fail_request = true;
-                               rc = mdt_agent_record_update(mti->mti_env, mdt,
-                                                            &hai->hai_cookie,
-                                                            1, ARS_FAILED);
-                               if (rc) {
-                                       CERROR("%s: mdt_agent_record_update() "
-                                             "failed, cannot update "
-                                             "status to %s for cookie "
-                                             LPX64": rc = %d\n",
-                                             mdt_obd_name(mdt),
-                                             agent_req_status2name(ARS_FAILED),
-                                             hai->hai_cookie, rc);
-                                       GOTO(out_buf, rc);
+                       /* if restore and record status updated, give
+                        * back granted layout lock */
+                       if (hai->hai_action == HSMA_RESTORE) {
+                               struct cdt_restore_handle *crh = NULL;
+
+                               mutex_lock(&cdt->cdt_restore_lock);
+                               crh = mdt_hsm_restore_hdl_find(cdt,
+                                                              &hai->hai_fid);
+                               if (crh != NULL)
+                                       list_del(&crh->crh_list);
+                               mutex_unlock(&cdt->cdt_restore_lock);
+                               if (crh != NULL) {
+                                       mdt_object_unlock(mti, NULL,
+                                                         &crh->crh_lh, 1);
+                                       OBD_SLAB_FREE_PTR(crh,
+                                                         mdt_hsm_cdt_kmem);
                                }
                        }
                }
@@ -446,6 +565,8 @@ int mdt_hsm_agent_send(struct mdt_thread_info *mti,
         */
        exp = cfs_hash_lookup(mdt2obd_dev(mdt)->obd_uuid_hash, &uuid);
        if (exp == NULL || exp->exp_disconnected) {
+               if (exp != NULL)
+                       class_export_put(exp);
                /* This should clean up agents on evicted exports */
                rc = -ENOENT;
                CERROR("%s: agent uuid (%s) not found, unregistering:"
@@ -486,8 +607,7 @@ out:
        }
 
 out_buf:
-       if (buf != hal)
-               kuc_free(buf, len);
+       kuc_free(buf, len);
 
        RETURN(rc);
 }
@@ -505,7 +625,7 @@ int mdt_hsm_coordinator_update(struct mdt_thread_info *mti,
        int      rc;
 
        ENTRY;
-       /* ask to coodinator to update request state and
+       /* ask to coordinator to update request state and
         * to record on disk the result */
        rc = mdt_hsm_update_request_state(mti, pgs, 1);
        RETURN(rc);