Whamcloud - gitweb
LU-3339 mdt: HSM on disk actions record 29/6529/8
authorjcl <jacques-charles.lafoucriere@cea.fr>
Mon, 3 Jun 2013 14:03:36 +0000 (16:03 +0200)
committerOleg Drokin <oleg.drokin@intel.com>
Wed, 10 Jul 2013 04:09:52 +0000 (04:09 +0000)
HSM coordinator memorizes all actions in a llog
This patch implements the methods needed to create
update display these records.

Signed-off-by: JC Lafoucriere <jacques-charles.lafoucriere@cea.fr>
Change-Id: I58bdbbd52a75a841c30e4477f3cb4c942d6d2a20
Reviewed-on: http://review.whamcloud.com/6529
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
12 files changed:
lustre/include/lprocfs_status.h
lustre/include/lustre/lustre_idl.h
lustre/include/lustre_disk.h
lustre/include/obd.h
lustre/mdd/mdd_device.c
lustre/mdd/mdd_internal.h
lustre/mdt/Makefile.in
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_hsm_cdt_actions.c [new file with mode: 0644]
lustre/mdt/mdt_internal.h
lustre/obdclass/llog_swab.c
lustre/utils/llog_reader.c

index 63b5174..ff60773 100644 (file)
 #include <libcfs/params_tree.h>
 
 struct lprocfs_vars {
-        const char             *name;
-        cfs_read_proc_t        *read_fptr;
-        cfs_write_proc_t       *write_fptr;
-        void                   *data;
-        struct file_operations *fops;
-        /**
-         * /proc file mode.
-         */
-        mode_t                  proc_mode;
+       const char                      *name;
+       cfs_read_proc_t                 *read_fptr;
+       cfs_write_proc_t                *write_fptr;
+       void                            *data;
+       const struct file_operations    *fops;
+       /**
+        * /proc file mode.
+       */
+       mode_t                           proc_mode;
 };
 
 struct lprocfs_static_vars {
@@ -863,9 +863,6 @@ extern int lprocfs_quota_rd_qs_factor(char *page, char **start, off_t off,
 extern int lprocfs_quota_wr_qs_factor(struct file *file,
                                       const char *buffer,
                                       unsigned long count, void *data);
-
-
-
 #else
 /* LPROCFS is not defined */
 
index ee5406e..a2dc8ab 100644 (file)
@@ -2992,6 +2992,7 @@ typedef enum {
        /* LLOG_JOIN_REC        = LLOG_OP_MAGIC | 0x50000, obsolete  1.8.0 */
        CHANGELOG_REC           = LLOG_OP_MAGIC | 0x60000,
        CHANGELOG_USER_REC      = LLOG_OP_MAGIC | 0x70000,
+       HSM_AGENT_REC           = LLOG_OP_MAGIC | 0x80000,
        LLOG_HDR_MAGIC          = LLOG_OP_MAGIC | 0x45539,
        LLOG_LOGID_MAGIC        = LLOG_OP_MAGIC | 0x4553b,
 } llog_op_type;
@@ -3111,6 +3112,52 @@ struct llog_changelog_user_rec {
         struct llog_rec_tail  cur_tail;
 } __attribute__((packed));
 
+enum agent_req_status {
+       ARS_WAITING,
+       ARS_STARTED,
+       ARS_FAILED,
+       ARS_CANCELED,
+       ARS_SUCCEED,
+};
+
+static inline char *agent_req_status2name(enum agent_req_status ars)
+{
+       switch (ars) {
+       case ARS_WAITING:
+               return "WAITING";
+       case ARS_STARTED:
+               return "STARTED";
+       case ARS_FAILED:
+               return "FAILED";
+       case ARS_CANCELED:
+               return "CANCELED";
+       case ARS_SUCCEED:
+               return "SUCCEED";
+       default:
+               return "UNKNOWN";
+       }
+}
+
+static inline bool agent_req_in_final_state(enum agent_req_status ars)
+{
+       return ((ars == ARS_SUCCEED) || (ars == ARS_FAILED) ||
+               (ars == ARS_CANCELED));
+}
+
+struct llog_agent_req_rec {
+       struct llog_rec_hdr     arr_hdr;        /**< record header */
+       __u32                   arr_status;     /**< status of the request */
+                                               /* must match enum
+                                                * agent_req_status */
+       __u32                   arr_archive_id; /**< backend archive number */
+       __u64                   arr_flags;      /**< req flags */
+       __u64                   arr_compound_id;        /**< compound cookie */
+       __u64                   arr_req_create; /**< req. creation time */
+       __u64                   arr_req_change; /**< req. status change time */
+       struct hsm_action_item  arr_hai;        /**< req. to the agent */
+       struct llog_rec_tail    arr_tail; /**< record tail for_sizezof_only */
+} __attribute__((packed));
+
 /* Old llog gen for compatibility */
 struct llog_gen {
        __u64 mnt_cnt;
index 5081819..48406b5 100644 (file)
 
 /****************** on-disk files *********************/
 
-#define MDT_LOGS_DIR      "LOGS"  /* COMPAT_146 */
-#define MOUNT_CONFIGS_DIR "CONFIGS"
-#define CONFIGS_FILE      "mountdata"
+#define MDT_LOGS_DIR           "LOGS"  /* COMPAT_146 */
+#define MOUNT_CONFIGS_DIR      "CONFIGS"
+#define CONFIGS_FILE           "mountdata"
 /** Persistent mount data are stored on the disk in this file. */
-#define MOUNT_DATA_FILE    MOUNT_CONFIGS_DIR"/"CONFIGS_FILE
-#define LAST_RCVD         "last_rcvd"
-#define LOV_OBJID         "lov_objid"
+#define MOUNT_DATA_FILE                MOUNT_CONFIGS_DIR"/"CONFIGS_FILE
+#define LAST_RCVD              "last_rcvd"
+#define LOV_OBJID              "lov_objid"
 #define LOV_OBJSEQ             "lov_objseq"
-#define HEALTH_CHECK      "health_check"
-#define CAPA_KEYS         "capa_keys"
-#define CHANGELOG_USERS   "changelog_users"
-#define MGS_NIDTBL_DIR    "NIDTBL_VERSIONS"
-#define QMT_DIR           "quota_master"
-#define QSD_DIR           "quota_slave"
+#define HEALTH_CHECK           "health_check"
+#define CAPA_KEYS              "capa_keys"
+#define CHANGELOG_USERS                "changelog_users"
+#define MGS_NIDTBL_DIR         "NIDTBL_VERSIONS"
+#define QMT_DIR                        "quota_master"
+#define QSD_DIR                        "quota_slave"
+#define HSM_ACTIONS            "hsm_actions"
 
 /****************** persistent mount data *********************/
 
@@ -226,21 +227,22 @@ struct lustre_mount_data {
        char    *lmd_osd_type;      /* OSD type */
 };
 
-#define LMD_FLG_SERVER       0x0001  /* Mounting a server */
-#define LMD_FLG_CLIENT       0x0002  /* Mounting a client */
-#define LMD_FLG_ABORT_RECOV  0x0008  /* Abort recovery */
-#define LMD_FLG_NOSVC        0x0010  /* Only start MGS/MGC for servers,
-                                        no other services */
-#define LMD_FLG_NOMGS        0x0020  /* Only start target for servers, reusing
-                                        existing MGS services */
-#define LMD_FLG_WRITECONF    0x0040  /* Rewrite config log */
-#define LMD_FLG_NOIR         0x0080  /* NO imperative recovery */
-#define LMD_FLG_NOSCRUB             0x0100  /* Do not trigger scrub automatically */
-#define LMD_FLG_MGS         0x0200  /* Also start MGS along with server */
-#define LMD_FLG_IAM         0x0400  /* IAM dir */
-#define LMD_FLG_NO_PRIMNODE  0x0800  /* all nodes are service nodes */
-#define LMD_FLG_VIRGIN      0x1000  /* the service registers first time */
-#define LMD_FLG_UPDATE      0x2000  /* update parameters */
+#define LMD_FLG_SERVER         0x0001  /* Mounting a server */
+#define LMD_FLG_CLIENT         0x0002  /* Mounting a client */
+#define LMD_FLG_ABORT_RECOV    0x0008  /* Abort recovery */
+#define LMD_FLG_NOSVC          0x0010  /* Only start MGS/MGC for servers,
+                                          no other services */
+#define LMD_FLG_NOMGS          0x0020  /* Only start target for servers, reusing
+                                          existing MGS services */
+#define LMD_FLG_WRITECONF      0x0040  /* Rewrite config log */
+#define LMD_FLG_NOIR           0x0080  /* NO imperative recovery */
+#define LMD_FLG_NOSCRUB                0x0100  /* Do not trigger scrub automatically */
+#define LMD_FLG_MGS            0x0200  /* Also start MGS along with server */
+#define LMD_FLG_IAM            0x0400  /* IAM dir */
+#define LMD_FLG_NO_PRIMNODE    0x0800  /* all nodes are service nodes */
+#define LMD_FLG_VIRGIN         0x1000  /* the service registers first time */
+#define LMD_FLG_UPDATE         0x2000  /* update parameters */
+#define LMD_FLG_HSM            0x4000  /* Start coordinator */
 
 #define lmd_is_client(x) ((x)->lmd_flags & LMD_FLG_CLIENT)
 
index 6afec97..73805a4 100644 (file)
@@ -266,22 +266,23 @@ struct brw_page {
 
 /* llog contexts */
 enum llog_ctxt_id {
-        LLOG_CONFIG_ORIG_CTXT  =  0,
-        LLOG_CONFIG_REPL_CTXT,
-        LLOG_MDS_OST_ORIG_CTXT,
-        LLOG_MDS_OST_REPL_CTXT,
-        LLOG_SIZE_ORIG_CTXT,
-        LLOG_SIZE_REPL_CTXT,
-        LLOG_RD1_ORIG_CTXT,
-        LLOG_RD1_REPL_CTXT,
-        LLOG_TEST_ORIG_CTXT,
-        LLOG_TEST_REPL_CTXT,
-        LLOG_LOVEA_ORIG_CTXT,
-        LLOG_LOVEA_REPL_CTXT,
-        LLOG_CHANGELOG_ORIG_CTXT,      /**< changelog generation on mdd */
-        LLOG_CHANGELOG_REPL_CTXT,      /**< changelog access on clients */
-        LLOG_CHANGELOG_USER_ORIG_CTXT, /**< for multiple changelog consumers */
-        LLOG_MAX_CTXTS
+       LLOG_CONFIG_ORIG_CTXT  =  0,
+       LLOG_CONFIG_REPL_CTXT,
+       LLOG_MDS_OST_ORIG_CTXT,
+       LLOG_MDS_OST_REPL_CTXT,
+       LLOG_SIZE_ORIG_CTXT,
+       LLOG_SIZE_REPL_CTXT,
+       LLOG_RD1_ORIG_CTXT,
+       LLOG_RD1_REPL_CTXT,
+       LLOG_TEST_ORIG_CTXT,
+       LLOG_TEST_REPL_CTXT,
+       LLOG_LOVEA_ORIG_CTXT,
+       LLOG_LOVEA_REPL_CTXT,
+       LLOG_CHANGELOG_ORIG_CTXT,       /**< changelog generation on mdd */
+       LLOG_CHANGELOG_REPL_CTXT,       /**< changelog access on clients */
+       LLOG_CHANGELOG_USER_ORIG_CTXT,  /**< for multiple changelog consumers */
+       LLOG_AGENT_ORIG_CTXT,           /**< agent requests generation on cdt */
+       LLOG_MAX_CTXTS
 };
 
 struct timeout_item {
index 6db4bb2..7d7c66f 100644 (file)
@@ -709,10 +709,84 @@ out:
        return rc;
 }
 
+
+static struct llog_operations hsm_actions_logops;
+
+/**
+ * set llog methods and create LLOG_AGENT_ORIG_CTXT llog
+ * object in obd_device
+ */
+static int mdd_hsm_actions_llog_init(const struct lu_env *env,
+                                    struct mdd_device *m)
+{
+       struct obd_device       *obd = mdd2obd_dev(m);
+       struct llog_ctxt        *ctxt = NULL;
+       int                      rc;
+       ENTRY;
+
+       OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
+       obd->obd_lvfs_ctxt.dt = m->mdd_bottom;
+
+       rc = llog_setup(env, obd, &obd->obd_olg, LLOG_AGENT_ORIG_CTXT,
+                       obd, &hsm_actions_logops);
+       if (rc) {
+               CERROR("%s: hsm actions llog setup failed: rc = %d\n",
+                       obd->obd_name, rc);
+               RETURN(rc);
+       }
+
+       ctxt = llog_get_context(obd, LLOG_AGENT_ORIG_CTXT);
+       LASSERT(ctxt);
+
+       rc = llog_open_create(env, ctxt, &ctxt->loc_handle, NULL,
+                             HSM_ACTIONS);
+       if (rc) {
+               CERROR("%s: hsm actions llog open_create failed: rc = %d\n",
+                       obd->obd_name, rc);
+               GOTO(out_cleanup, rc);
+       }
+
+       rc = llog_cat_init_and_process(env, ctxt->loc_handle);
+       if (rc)
+               GOTO(out_close, rc);
+
+       llog_ctxt_put(ctxt);
+       RETURN(0);
+
+out_close:
+       llog_cat_close(env, ctxt->loc_handle);
+       ctxt->loc_handle = NULL;
+out_cleanup:
+       llog_cleanup(env, ctxt);
+
+       return rc;
+}
+
+/**
+ * cleanup the context created by llog_setup_named()
+ */
+static int mdd_hsm_actions_llog_fini(const struct lu_env *env,
+                                    struct mdd_device *m)
+{
+       struct obd_device       *obd = mdd2obd_dev(m);
+       struct llog_ctxt        *lctxt;
+       ENTRY;
+
+       lctxt = llog_get_context(obd, LLOG_AGENT_ORIG_CTXT);
+       if (lctxt) {
+               llog_cat_close(env, lctxt->loc_handle);
+               lctxt->loc_handle = NULL;
+               llog_cleanup(env, lctxt);
+       }
+
+       RETURN(0);
+}
+
 static void mdd_device_shutdown(const struct lu_env *env, struct mdd_device *m,
                                struct lustre_cfg *cfg)
 {
        lfsck_degister(env, m->mdd_bottom);
+       mdd_hsm_actions_llog_fini(env, m);
        mdd_changelog_fini(env, m);
        orph_index_fini(env, m);
        if (m->mdd_dot_lustre_objs.mdd_obf)
@@ -882,13 +956,19 @@ static int mdd_prepare(const struct lu_env *env,
                GOTO(out_orph, rc);
        }
 
+       rc = mdd_hsm_actions_llog_init(env, mdd);
+       if (rc != 0)
+               GOTO(out_changelog, rc);
+
        rc = lfsck_register(env, mdd->mdd_bottom, mdd->mdd_child, true);
        if (rc != 0) {
                CERROR("%s: failed to initialize lfsck: rc = %d\n",
                       mdd2obd_dev(mdd)->obd_name, rc);
-               GOTO(out_changelog, rc);
+               GOTO(out_hsm, rc);
        }
        RETURN(0);
+out_hsm:
+       mdd_hsm_actions_llog_fini(env, mdd);
 out_changelog:
        mdd_changelog_fini(env, mdd);
 out_orph:
@@ -903,6 +983,7 @@ out_dot:
 out_los:
        local_oid_storage_fini(env, mdd->mdd_los);
        mdd->mdd_los = NULL;
+
        return rc;
 }
 
@@ -1416,6 +1497,10 @@ static int __init mdd_mod_init(void)
        changelog_orig_logops.lop_add = llog_cat_add_rec;
        changelog_orig_logops.lop_declare_add = llog_cat_declare_add_rec;
 
+       hsm_actions_logops = llog_osd_ops;
+       hsm_actions_logops.lop_add = llog_cat_add_rec;
+       hsm_actions_logops.lop_declare_add = llog_cat_declare_add_rec;
+
        rc = class_register_type(&mdd_obd_device_ops, NULL, lvars.module_vars,
                                 LUSTRE_MDD_NAME, &mdd_device_type);
        if (rc)
index 4d965d9..1b37f46 100644 (file)
@@ -454,6 +454,7 @@ int mdd_capa_get(const struct lu_env *env, struct md_object *obj,
 /* mdd_prepare.c */
 int mdd_compat_fixes(const struct lu_env *env, struct mdd_device *mdd);
 
+/* inline functions */
 static inline int lu_device_is_mdd(struct lu_device *d)
 {
         return ergo(d != NULL && d->ld_ops != NULL, d->ld_ops == &mdd_lu_ops);
index 3867fd4..6761762 100644 (file)
@@ -2,5 +2,6 @@ MODULES := mdt
 mdt-objs := mdt_handler.o mdt_lib.o mdt_reint.o mdt_xattr.o mdt_recovery.o
 mdt-objs += mdt_open.o mdt_idmap.o mdt_identity.o mdt_capa.o mdt_lproc.o mdt_fs.o
 mdt-objs += mdt_lvb.o mdt_hsm.o mdt_mds.o out_handler.o
+mdt-objs += mdt_hsm_cdt_actions.o
 
 @INCLUDE_RULES@
index d13acbb..ca2090d 100644 (file)
@@ -4599,8 +4599,9 @@ static void mdt_fini(const struct lu_env *env, struct mdt_device *m)
 
         ping_evictor_stop();
 
-
        mdt_stack_pre_fini(env, m, md2lu_dev(m->mdt_child));
+
+       mdt_llog_ctxt_unclone(env, m, LLOG_AGENT_ORIG_CTXT);
         mdt_llog_ctxt_unclone(env, m, LLOG_CHANGELOG_ORIG_CTXT);
         obd_exports_barrier(obd);
         obd_zombie_barrier();
@@ -4717,6 +4718,7 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m,
         m->mdt_som_conf = 0;
 
         m->mdt_opts.mo_cos = MDT_COS_DEFAULT;
+
        lmi = server_get_mount(dev);
         if (lmi == NULL) {
                 CERROR("Cannot get mount info for %s!\n", dev);
@@ -4888,20 +4890,21 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m,
         RETURN(0);
 
 err_procfs:
-        mdt_procfs_fini(m);
+       mdt_procfs_fini(m);
 err_recovery:
-        target_recovery_fini(obd);
-        upcall_cache_cleanup(m->mdt_identity_cache);
-        m->mdt_identity_cache = NULL;
+       target_recovery_fini(obd);
+       upcall_cache_cleanup(m->mdt_identity_cache);
+       m->mdt_identity_cache = NULL;
 err_llog_cleanup:
-        mdt_llog_ctxt_unclone(env, m, LLOG_CHANGELOG_ORIG_CTXT);
-        mdt_fs_cleanup(env, m);
+       mdt_llog_ctxt_unclone(env, m, LLOG_AGENT_ORIG_CTXT);
+       mdt_llog_ctxt_unclone(env, m, LLOG_CHANGELOG_ORIG_CTXT);
+       mdt_fs_cleanup(env, m);
 err_capa:
-        cfs_timer_disarm(&m->mdt_ck_timer);
-        mdt_ck_thread_stop(m);
+       cfs_timer_disarm(&m->mdt_ck_timer);
+       mdt_ck_thread_stop(m);
 err_free_ns:
-        ldlm_namespace_free(m->mdt_namespace, NULL, 0);
-        obd->obd_namespace = m->mdt_namespace = NULL;
+       ldlm_namespace_free(m->mdt_namespace, NULL, 0);
+       obd->obd_namespace = m->mdt_namespace = NULL;
 err_fini_seq:
        mdt_seq_fini(env, m);
 err_fini_fld:
@@ -4909,11 +4912,11 @@ err_fini_fld:
 err_lut:
        tgt_fini(env, &m->mdt_lut);
 err_fini_stack:
-        mdt_stack_fini(env, m, md2lu_dev(m->mdt_child));
+       mdt_stack_fini(env, m, md2lu_dev(m->mdt_child));
 err_lmi:
        if (lmi)
                server_put_mount(dev, lmi->lmi_mnt);
-        return (rc);
+       return(rc);
 }
 
 /* For interoperability, the left element is old parameter, the right one
@@ -5092,6 +5095,10 @@ static int mdt_prepare(const struct lu_env *env,
        if (rc)
                RETURN(rc);
 
+       rc = mdt_llog_ctxt_clone(env, mdt, LLOG_AGENT_ORIG_CTXT);
+       if (rc)
+               RETURN(rc);
+
        lsp.lsp_start = NULL;
        lsp.lsp_namespace = mdt->mdt_namespace;
        rc = mdt->mdt_child->md_ops->mdo_iocontrol(env, mdt->mdt_child,
@@ -5109,6 +5116,7 @@ static int mdt_prepare(const struct lu_env *env,
                if (rc)
                        RETURN(rc);
        }
+
        LASSERT(!test_bit(MDT_FL_CFGLOG, &mdt->mdt_state));
        target_recovery_init(&mdt->mdt_lut, mdt_recovery_handle);
        set_bit(MDT_FL_CFGLOG, &mdt->mdt_state);
diff --git a/lustre/mdt/mdt_hsm_cdt_actions.c b/lustre/mdt/mdt_hsm_cdt_actions.c
new file mode 100644 (file)
index 0000000..37a4da1
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License version 2 for more details.  A copy is
+ * included in the COPYING file that accompanied this code.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * GPL HEADER END
+ */
+/*
+ * (C) Copyright 2012 Commissariat a l'energie atomique et aux energies
+ *     alternatives
+ *
+ */
+/*
+ * lustre/mdt/mdt_agent_actions.c
+ *
+ * Lustre HSM
+ *
+ * Author: Jacques-Charles Lafoucriere <jacques-charles.lafoucriere@cea.fr>
+ * Author: Aurelien Degremont <aurelien.degremont@cea.fr>
+ */
+
+#define DEBUG_SUBSYSTEM S_MDS
+
+#include <obd_support.h>
+#include <lustre_net.h>
+#include <lustre_export.h>
+#include <obd.h>
+#include <lprocfs_status.h>
+#include <lustre_log.h>
+#include "mdt_internal.h"
+
+void dump_llog_agent_req_rec(char *prefix, struct llog_agent_req_rec *larr)
+{
+       char    buf[12];
+       int     sz;
+
+       sz = larr->arr_hai.hai_len - sizeof(larr->arr_hai);
+       CDEBUG(D_HSM, "%slrh=[type=%X len=%d idx=%d] fid="DFID
+              " dfid="DFID
+              " compound/cookie="LPX64"/"LPX64
+              " status=%s action=%s archive#=%d flags="LPX64
+              " create="LPU64" change="LPU64
+              " extent="LPX64"-"LPX64" gid="LPX64" datalen=%d"
+              " data=[%s]\n",
+              prefix,
+              larr->arr_hdr.lrh_type,
+              larr->arr_hdr.lrh_len, larr->arr_hdr.lrh_index,
+              PFID(&larr->arr_hai.hai_fid),
+              PFID(&larr->arr_hai.hai_dfid),
+              larr->arr_compound_id, larr->arr_hai.hai_cookie,
+              agent_req_status2name(larr->arr_status),
+              hsm_copytool_action2name(larr->arr_hai.hai_action),
+              larr->arr_archive_id,
+              larr->arr_flags,
+              larr->arr_req_create, larr->arr_req_change,
+              larr->arr_hai.hai_extent.offset,
+              larr->arr_hai.hai_extent.length,
+              larr->arr_hai.hai_gid, sz,
+              hai_dump_data_field(&larr->arr_hai, buf, sizeof(buf)));
+}
+
+/*
+ * process the actions llog
+ * \param env [IN] environment
+ * \param mdt [IN] MDT device
+ * \param cb [IN] llog callback funtion
+ * \param data [IN] llog callback  data
+ * \retval 0 success
+ * \retval -ve failure
+ */
+int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt,
+                    llog_cb_t cb, void *data)
+{
+       struct obd_device       *obd = mdt2obd_dev(mdt);
+       struct llog_ctxt        *lctxt = NULL;
+       struct coordinator      *cdt = &mdt->mdt_coordinator;
+       int                      rc;
+       ENTRY;
+
+       lctxt = llog_get_context(obd, LLOG_AGENT_ORIG_CTXT);
+       if ((lctxt == NULL) || (lctxt->loc_handle == NULL))
+               RETURN(-ENOENT);
+
+       down(&cdt->cdt_llog_lock);
+
+       rc = llog_cat_process(env, lctxt->loc_handle, cb, data, 0, 0);
+       if (rc < 0)
+               CERROR("%s: failed to process HSM_ACTIONS llog (rc=%d)\n",
+                       mdt_obd_name(mdt), rc);
+       else
+               rc = 0;
+
+       llog_ctxt_put(lctxt);
+       up(&cdt->cdt_llog_lock);
+       RETURN(rc);
+}
+
+/**
+ * add an entry in agent llog
+ * \param env [IN] environment
+ * \param mdt [IN] PDT device
+ * \param compound_id [IN] global id associated with the record
+ * \param archive_id [IN] backend archive number
+ * \param hai [IN] record to register
+ * \retval 0 success
+ * \retval -ve failure
+ */
+int mdt_agent_record_add(const struct lu_env *env,
+                        struct mdt_device *mdt,
+                        __u64 compound_id, __u32 archive_id,
+                        __u64 flags, struct hsm_action_item *hai)
+{
+       struct obd_device               *obd = mdt2obd_dev(mdt);
+       struct coordinator              *cdt = &mdt->mdt_coordinator;
+       struct llog_ctxt                *lctxt = NULL;
+       struct llog_agent_req_rec       *larr;
+       int                              rc;
+       int                              sz;
+       ENTRY;
+
+       sz = llog_data_len(sizeof(*larr) + hai->hai_len - sizeof(*hai));
+       OBD_ALLOC(larr, sz);
+       if (!larr)
+               RETURN(-ENOMEM);
+       larr->arr_hdr.lrh_len = sz;
+       larr->arr_hdr.lrh_type = HSM_AGENT_REC;
+       larr->arr_status = ARS_WAITING;
+       larr->arr_compound_id = compound_id;
+       larr->arr_archive_id = archive_id;
+       larr->arr_flags = flags;
+       larr->arr_req_create = cfs_time_current_sec();
+       larr->arr_req_change = larr->arr_req_create;
+       memcpy(&larr->arr_hai, hai, hai->hai_len);
+
+       lctxt = llog_get_context(obd, LLOG_AGENT_ORIG_CTXT);
+       if ((lctxt == NULL) || (lctxt->loc_handle == NULL))
+               GOTO(free, rc = -ENOENT);
+
+       down(&cdt->cdt_llog_lock);
+
+       /* in case of cancel request, the cookie is already set to the
+        * value of the request cookie to be cancelled
+        * so we do not change it */
+       if (hai->hai_action != HSMA_CANCEL) {
+               cdt->cdt_last_cookie++;
+               hai->hai_cookie = cdt->cdt_last_cookie;
+       }
+       larr->arr_hai.hai_cookie = hai->hai_cookie;
+       rc = llog_cat_add(env, lctxt->loc_handle, &larr->arr_hdr, NULL, NULL);
+       if (rc > 0)
+               rc = 0;
+
+       up(&cdt->cdt_llog_lock);
+       llog_ctxt_put(lctxt);
+
+       EXIT;
+free:
+       OBD_FREE(larr, sz);
+       return rc;
+}
+
+/**
+ * data passed to llog_cat_process() callback
+ * to find requests
+ */
+struct data_update_cb {
+       struct mdt_device       *mdt;
+       __u64                   *cookies;
+       int                      cookies_count;
+       int                      cookies_done;
+       enum agent_req_status    status;
+       cfs_time_t               change_time;
+};
+
+/**
+ *  llog_cat_process() callback, used to update a record
+ * \param env [IN] environment
+ * \param llh [IN] llog handle
+ * \param hdr [IN] llog record
+ * \param data [IN] cb data = data_update_cb
+ * \retval 0 success
+ * \retval -ve failure
+ */
+static int mdt_agent_record_update_cb(const struct lu_env *env,
+                                     struct llog_handle *llh,
+                                     struct llog_rec_hdr *hdr,
+                                     void *data)
+{
+       struct llog_agent_req_rec       *larr;
+       struct data_update_cb           *ducb;
+       int                              rc, i;
+       int                              found;
+       ENTRY;
+
+       larr = (struct llog_agent_req_rec *)hdr;
+       ducb = data;
+       found = 0;
+
+       /* check if all done */
+       if (ducb->cookies_count == ducb->cookies_done)
+               RETURN(LLOG_PROC_BREAK);
+
+       /* if record is in final state, never change */
+       /* if record is a cancel request, it cannot be canceled
+        * this is to manage the following case:
+        * when a request is canceled, we have 2 records with the
+        * the same cookie : the one to cancel and the cancel request
+        * the 1st has to be set to ARS_CANCELED and the 2nd to ARS_SUCCEED
+        */
+       if (agent_req_in_final_state(larr->arr_status) ||
+           ((larr->arr_hai.hai_action == HSMA_CANCEL) &&
+            (ducb->status == ARS_CANCELED)))
+               RETURN(0);
+
+       rc = 0;
+       for (i = 0 ; i < ducb->cookies_count ; i++) {
+               CDEBUG(D_HSM, "%s: search "LPX64", found "LPX64"\n",
+                      mdt_obd_name(ducb->mdt), ducb->cookies[i],
+                      larr->arr_hai.hai_cookie);
+               if (larr->arr_hai.hai_cookie == ducb->cookies[i]) {
+
+                       larr->arr_status = ducb->status;
+                       larr->arr_req_change = ducb->change_time;
+                       rc = mdt_agent_llog_update_rec(env, ducb->mdt, llh,
+                                                      larr);
+                       ducb->cookies_done++;
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (rc < 0)
+               CERROR("%s: mdt_agent_llog_update_rec() failed, rc = %d\n",
+                      mdt_obd_name(ducb->mdt), rc);
+
+       if (found == 1)
+               RETURN(LLOG_DEL_RECORD);
+
+       RETURN(rc);
+}
+
+/**
+ * update an entry in agent llog
+ * \param env [IN] environment
+ * \param mdt [IN] MDT device
+ * \param cookie [IN] entries to update
+ *    log cookie are returned by register
+ * \param status [IN] new status of the request
+ * \retval 0 success
+ * \retval -ve failure
+ */
+int mdt_agent_record_update(const struct lu_env *env, struct mdt_device *mdt,
+                           __u64 *cookies, int cookies_count,
+                           enum agent_req_status status)
+{
+       struct data_update_cb    ducb;
+       int                      rc;
+       ENTRY;
+
+       ducb.mdt = mdt;
+       ducb.cookies = cookies;
+       ducb.cookies_count = cookies_count;
+       ducb.cookies_done = 0;
+       ducb.status = status;
+       ducb.change_time = cfs_time_current_sec();
+
+       rc = cdt_llog_process(env, mdt, mdt_agent_record_update_cb, &ducb);
+       if (rc < 0)
+               CERROR("%s: cdt_llog_process() failed, rc=%d, cannot update "
+                      "status to %s for %d cookies, done %d\n",
+                      mdt_obd_name(mdt), rc,
+                      agent_req_status2name(status),
+                      cookies_count, ducb.cookies_done);
+       RETURN(rc);
+}
+
+/**
+ * update a llog record
+ *  cdt_llog_lock must be hold
+ * \param env [IN] environment
+ * \param mdt [IN] mdt device
+ * \param llh [IN] llog handle, must be a catalog handle
+ * \param larr [IN] record
+ * \retval 0 success
+ * \retval -ve failure
+ */
+int mdt_agent_llog_update_rec(const struct lu_env *env,
+                             struct mdt_device *mdt, struct llog_handle *llh,
+                             struct llog_agent_req_rec *larr)
+{
+       struct llog_rec_hdr      saved_hdr;
+       int                      rc;
+       ENTRY;
+
+       /* saved old record info */
+       saved_hdr = larr->arr_hdr;
+       /* add new record with updated values */
+       larr->arr_hdr.lrh_id = 0;
+       larr->arr_hdr.lrh_index = 0;
+       rc = llog_cat_add(env, llh->u.phd.phd_cat_handle, &larr->arr_hdr,
+                         NULL, NULL);
+       larr->arr_hdr = saved_hdr;
+       RETURN(rc);
+}
+
+/*
+ * Agent actions /proc seq_file methods
+ * As llog processing uses a callback for each entry, we cannot do a sequential
+ * read. To limit calls to llog_cat_process (it spawns a thread), we fill
+ * multiple record in seq_file buffer in one show call.
+ * op->start() sets the iterator up and returns the first element of sequence
+ * op->stop() shuts it down.
+ * op->next() returns the next element of sequence.
+ * op->show() prints element into the buffer.
+ * In case of error ->start() and ->next() return ERR_PTR(error)
+ * In the end of sequence they return %NULL
+ * op->show() returns 0 in case of success and negative number in case of error.
+ *
+ */
+/**
+ * seq_file iterator for agent_action entry
+ */
+#define AGENT_ACTIONS_IT_MAGIC 0x19660426
+struct agent_action_iterator {
+       int                      aai_magic;      /**< magic number */
+       struct lu_env            aai_env;        /**< lustre env for llog */
+       struct obd_device       *aai_obd;        /**< metadata device */
+       struct llog_ctxt        *aai_ctxt;       /**< llog context */
+       struct llog_handle      *aai_llh;        /**< llog handle */
+       int                      aai_index_done; /**< idx already shown */
+       int                      aai_index_cb;   /**< current idx in loop cb */
+       int                      aai_eof;        /**< all done */
+};
+
+/**
+ * seq_file method called to start access to /proc file
+ * get llog context + llog handle
+ */
+static void *mdt_agent_actions_proc_start(struct seq_file *s, loff_t *pos)
+{
+       struct agent_action_iterator    *aai = s->private;
+       int                              rc;
+       ENTRY;
+
+       LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X",
+                aai->aai_magic);
+
+       aai->aai_ctxt = llog_get_context(aai->aai_obd, LLOG_AGENT_ORIG_CTXT);
+       if (aai->aai_ctxt == NULL) {
+               CERROR("llog_get_context() failed\n");
+               RETURN(ERR_PTR(-ENOENT));
+       }
+       rc = llog_open(&aai->aai_env, aai->aai_ctxt, &aai->aai_llh, NULL,
+                      HSM_ACTIONS, LLOG_OPEN_EXISTS);
+       if (rc)
+               GOTO(err, rc);
+
+       rc = llog_init_handle(&aai->aai_env, aai->aai_llh, LLOG_F_IS_CAT, NULL);
+       if (rc)
+               GOTO(err, rc);
+
+       CDEBUG(D_HSM, "llog succesfully initialized, start from "LPD64"\n",
+              *pos);
+       /* first call = rewind */
+       if (*pos == 0) {
+               aai->aai_index_done = 0;
+               aai->aai_eof = 0;
+               *pos = 1;
+       }
+
+       RETURN(aai);
+err:
+       if (aai->aai_llh) {
+               llog_cat_close(&aai->aai_env, aai->aai_llh);
+               aai->aai_llh = NULL;
+       }
+
+       if (aai->aai_ctxt)
+               llog_ctxt_put(aai->aai_ctxt);
+
+       RETURN(ERR_PTR(rc));
+}
+
+/**
+ * seq_file method called to get next item
+ * just returns NULL at eof
+ * (seq_file buffer filling is done in llog_cat_process() callback)
+ */
+static void *mdt_agent_actions_proc_next(struct seq_file *s, void *v,
+                                        loff_t *pos)
+{
+       struct agent_action_iterator *aai = s->private;
+       ENTRY;
+
+       LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X",
+                aai->aai_magic);
+
+       CDEBUG(D_HSM, "set current="LPD64" to done=%d, eof=%d\n",
+              *pos, aai->aai_index_done, aai->aai_eof);
+       (*pos) = aai->aai_index_done;
+
+       if (aai->aai_eof)
+               RETURN(NULL);
+
+       RETURN(aai);
+}
+
+/**
+ *  llog_cat_process() callback, used to fill a seq_file buffer
+ */
+static int agent_actions_show_cb(const struct lu_env *env,
+                                struct llog_handle *llh,
+                                struct llog_rec_hdr *hdr,
+                                void *data)
+{
+       struct llog_agent_req_rec    *larr = (struct llog_agent_req_rec *)hdr;
+       struct seq_file              *s = data;
+       struct agent_action_iterator *aai;
+       int                           rc, sz;
+       char                          buf[12];
+       ENTRY;
+
+       aai = s->private;
+       LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X",
+                aai->aai_magic);
+
+       aai->aai_index_cb++;
+       /* if rec already printed => skip */
+       if (aai->aai_index_cb <= aai->aai_index_done)
+               RETURN(0);
+
+       sz = larr->arr_hai.hai_len - sizeof(larr->arr_hai);
+       rc = seq_printf(s, "lrh=[type=%X len=%d idx=%d] fid="DFID
+                       " dfid="DFID
+                       " compound/cookie="LPX64"/"LPX64
+                       " action=%s archive#=%d flags="LPX64
+                       " extent="LPX64"-"LPX64
+                       " gid="LPX64" datalen=%d status=%s"
+                       " data=[%s]\n",
+                       larr->arr_hdr.lrh_type,
+                       larr->arr_hdr.lrh_len, larr->arr_hdr.lrh_index,
+                       PFID(&larr->arr_hai.hai_fid),
+                       PFID(&larr->arr_hai.hai_dfid),
+                       larr->arr_compound_id, larr->arr_hai.hai_cookie,
+                       hsm_copytool_action2name(larr->arr_hai.hai_action),
+                       larr->arr_archive_id,
+                       larr->arr_flags,
+                       larr->arr_hai.hai_extent.offset,
+                       larr->arr_hai.hai_extent.length,
+                       larr->arr_hai.hai_gid, sz,
+                       agent_req_status2name(larr->arr_status),
+                       hai_dump_data_field(&larr->arr_hai, buf, sizeof(buf)));
+       if (rc >= 0) {
+               aai->aai_index_done++;
+               RETURN(0);
+       }
+       /* buffer is full, stop filling */
+       RETURN(LLOG_PROC_BREAK);
+}
+
+/**
+ * mdt_agent_actions_proc_show() is called at for each seq record
+ * process the llog, with a cb which fill the file_seq buffer
+ * to be faster, one show will fill multiple records
+ */
+static int mdt_agent_actions_proc_show(struct seq_file *s, void *v)
+{
+       struct agent_action_iterator    *aai = s->private;
+       int                              rc;
+       ENTRY;
+
+       LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X",
+                aai->aai_magic);
+
+       CDEBUG(D_HSM, "show from done=%d, eof=%d\n",
+              aai->aai_index_done, aai->aai_eof);
+       if (aai->aai_eof)
+               RETURN(0);
+
+       aai->aai_index_cb = 0;
+       rc = llog_cat_process(&aai->aai_env, aai->aai_llh,
+                             agent_actions_show_cb, s, 0, 0);
+       /* was all llog parsed? */
+       if (rc == 0)
+               aai->aai_eof = 1;
+       /* not enough room in buffer? */
+       if (rc == LLOG_PROC_BREAK)
+               RETURN(0);
+       /* error */
+       RETURN(rc);
+}
+
+/**
+ * seq_file method called to stop access to /proc file
+ * clean + put llog context
+ */
+static void mdt_agent_actions_proc_stop(struct seq_file *s, void *v)
+{
+       struct agent_action_iterator *aai = s->private;
+       ENTRY;
+
+       LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X",
+                aai->aai_magic);
+
+       if (aai->aai_llh) {
+               llog_cat_close(&aai->aai_env, aai->aai_llh);
+               aai->aai_llh = NULL;
+       }
+       if (aai->aai_ctxt)
+               llog_ctxt_put(aai->aai_ctxt);
+       EXIT;
+       return;
+}
+
+static const struct seq_operations mdt_agent_actions_proc_ops = {
+       .start  = mdt_agent_actions_proc_start,
+       .next   = mdt_agent_actions_proc_next,
+       .show   = mdt_agent_actions_proc_show,
+       .stop   = mdt_agent_actions_proc_stop,
+};
+
+static int lprocfs_open_agent_actions(struct inode *inode, struct file *file)
+{
+       struct agent_action_iterator    *aai;
+       struct seq_file                 *s;
+       int                              rc;
+       struct mdt_device               *mdt;
+       ENTRY;
+
+       if (LPROCFS_ENTRY_AND_CHECK(PDE(inode)))
+               RETURN(-ENOENT);
+
+       rc = seq_open(file, &mdt_agent_actions_proc_ops);
+       if (rc) {
+               LPROCFS_EXIT();
+               RETURN(rc);
+       }
+
+       OBD_ALLOC_PTR(aai);
+       if (aai == NULL)
+               GOTO(err, rc = -ENOMEM);
+
+       aai->aai_magic = AGENT_ACTIONS_IT_MAGIC;
+       rc = lu_env_init(&aai->aai_env, LCT_LOCAL);
+       if (rc)
+               GOTO(err, rc);
+
+       aai->aai_llh = NULL;
+       /* mdt is saved in proc_dir_entry->data by
+        * mdt_coordinator_procfs_init() calling lprocfs_register()
+        */
+       mdt = (struct mdt_device *)PDE(inode)->data;
+       aai->aai_obd = mdt2obd_dev(mdt);
+       s = file->private_data;
+       s->private = aai;
+
+       GOTO(out, rc = 0);
+
+err:
+       lprocfs_seq_release(inode, file);
+       if (aai && aai->aai_env.le_ses)
+               OBD_FREE_PTR(aai->aai_env.le_ses);
+       if (aai)
+               OBD_FREE_PTR(aai);
+out:
+       return rc;
+}
+
+/**
+ * lprocfs_release_agent_actions() is called at end of /proc access
+ * free alloacted ressources and call cleanup lprocfs methods
+ */
+static int lprocfs_release_agent_actions(struct inode *inode, struct file *file)
+{
+       struct seq_file                 *seq = file->private_data;
+       struct agent_action_iterator    *aai = seq->private;
+
+       if (aai) {
+               lu_env_fini(&aai->aai_env);
+               OBD_FREE_PTR(aai);
+       }
+
+       return lprocfs_seq_release(inode, file);
+}
+
+/* methods to access agent actions llog through /proc */
+const struct file_operations mdt_agent_actions_fops = {
+       .owner          = THIS_MODULE,
+       .open           = lprocfs_open_agent_actions,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = lprocfs_release_agent_actions,
+};
+
index 9b0a6d1..81b0b20 100644 (file)
@@ -75,6 +75,7 @@ static inline int req_xid_is_last(struct ptlrpc_request *req)
 }
 
 struct mdt_object;
+
 /* file data for open files on MDS */
 struct mdt_file_data {
         struct portals_handle mfd_handle; /* must be first */
@@ -85,6 +86,60 @@ struct mdt_file_data {
         struct mdt_object    *mfd_object; /* point to opened object */
 };
 
+#define CDT_NONBLOCKING_RESTORE                0x0000000000000001ULL
+#define CDT_NORETRY_ACTION             0x0000000000000002ULL
+#define CDT_POLICY_MASK                        CDT_NONBLOCKING_RESTORE | \
+                                       CDT_NORETRY_ACTION
+
+/* when adding a new policy, do not forget to update
+ * lustre/mdt/mdt_coordinator.c::hsm_policy_names[]
+ */
+#define CDT_DEFAULT_POLICY             0x0000000000000000ULL
+
+enum cdt_states { CDT_STOPPED = 0,
+                 CDT_INIT,
+                 CDT_RUNNING,
+                 CDT_DISABLE,
+                 CDT_STOPPING };
+
+/* when multiple lock are needed, the lock order is
+ * cdt_llog_lock
+ * cdt_agent_lock
+ * cdt_counter_lock
+ * cdt_restore_lock
+ * cdt_request_lock
+ */
+struct coordinator {
+       struct ptlrpc_thread    *cdt_thread;        /**< coordinator thread */
+       struct lu_env            cdt_env;           /**< coordinator lustre
+                                                    * env */
+       struct proc_dir_entry   *cdt_proc_dir;      /**< cdt /proc directory */
+       __u64                    cdt_policy;        /**< flags to defined
+                                                    * policy */
+       enum cdt_states          cdt_state;         /**< state */
+       cfs_atomic_t             cdt_compound_id;   /**< compound id counter */
+       __u64                    cdt_last_cookie;   /**< last cookie allocated */
+       struct semaphore         cdt_counter_lock;  /**< protect request
+                                                    * counter */
+       struct semaphore         cdt_llog_lock;     /**< protect llog access */
+       struct rw_semaphore      cdt_agent_lock;    /**< protect agent list */
+       struct rw_semaphore      cdt_request_lock;  /**< protect request list */
+       struct semaphore         cdt_restore_lock;  /**< protect restore list */
+       cfs_time_t               cdt_loop_period;   /**< llog scan period */
+       cfs_time_t               cdt_delay;         /**< request grace delay */
+       cfs_time_t               cdt_timeout;       /**< request timeout */
+       __u64                    cdt_max_request;   /**< max count of started
+                                                    * requests */
+       __u64                    cdt_request_count; /**< current count of
+                                                    * started requests */
+       cfs_list_t               cdt_requests;      /**< list of started
+                                                    * requests */
+       cfs_list_t               cdt_agents;        /**< list of register
+                                                    * agents */
+       cfs_list_t               cdt_restore_hdl;   /**< list of restore lock
+                                                    * handles */
+};
+
 /* mdt state flag bits */
 #define MDT_FL_CFGLOG 0
 #define MDT_FL_SYNCED 1
@@ -113,7 +168,8 @@ struct mdt_device {
                                   mo_compat_resname:1,
                                   mo_mds_capa:1,
                                   mo_oss_capa:1,
-                                  mo_cos:1;
+                                  mo_cos:1,
+                                  mo_coordinator:1;
        } mdt_opts;
         /* mdt state flags */
         unsigned long              mdt_state;
@@ -171,6 +227,8 @@ struct mdt_device {
        struct obd_export         *mdt_qmt_exp;
        /* quota master device associated with this MDT */
        struct lu_device          *mdt_qmt_dev;
+
+       struct coordinator         mdt_coordinator;
 };
 
 #define MDT_SERVICE_WATCHDOG_FACTOR    (2)
@@ -851,6 +909,21 @@ int mdt_hsm_ct_register(struct mdt_thread_info *info);
 int mdt_hsm_ct_unregister(struct mdt_thread_info *info);
 int mdt_hsm_request(struct mdt_thread_info *info);
 
+/* mdt/mdt_hsm_cdt_actions.c */
+extern const struct file_operations mdt_agent_actions_fops;
+void dump_llog_agent_req_rec(char *prefix, struct llog_agent_req_rec *larr);
+int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt,
+                    llog_cb_t cb, void *data);
+int mdt_agent_record_add(const struct lu_env *env, struct mdt_device *mdt,
+                        __u64 compound_id, __u32 archive_id,
+                        __u64 flags, struct hsm_action_item *hai);
+int mdt_agent_record_update(const struct lu_env *env,
+                           struct mdt_device *mdt, __u64 *cookies,
+                           int cookies_count, enum agent_req_status status);
+int mdt_agent_llog_update_rec(const struct lu_env *env, struct mdt_device *mdt,
+                             struct llog_handle *llh,
+                             struct llog_agent_req_rec *larr);
+
 extern struct lu_context_key       mdt_thread_key;
 /* debug issues helper starts here*/
 static inline int mdt_fail_write(const struct lu_env *env,
index 10c6225..f509874 100644 (file)
@@ -206,6 +206,23 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec)
                 break;
         }
 
+       case HSM_AGENT_REC: {
+               struct llog_agent_req_rec *arr =
+                       (struct llog_agent_req_rec *)rec;
+
+               __swab32s(&arr->arr_hai.hai_len);
+               __swab32s(&arr->arr_hai.hai_action);
+               lustre_swab_lu_fid(&arr->arr_hai.hai_fid);
+               lustre_swab_lu_fid(&arr->arr_hai.hai_dfid);
+               __swab64s(&arr->arr_hai.hai_cookie);
+               __swab64s(&arr->arr_hai.hai_extent.offset);
+               __swab64s(&arr->arr_hai.hai_extent.length);
+               __swab64s(&arr->arr_hai.hai_gid);
+               /* no swabing for opaque data */
+               /* hai_data[0]; */
+               break;
+       }
+
        case MDS_SETATTR64_REC:
        {
                struct llog_setattr64_rec *lsr =
index 748be6c..596ab6e 100644 (file)
@@ -455,28 +455,72 @@ void print_lustre_cfg(struct lustre_cfg *lcfg, int *skip)
         return;
 }
 
-void print_records(struct llog_rec_hdr **recs, int rec_number)
+static void print_logid(struct llog_logid_rec *lid)
 {
-        __u32 lopt;
-        int i, skip = 0;
-
-        for(i = 0; i < rec_number; i++) {
-                printf("#%.2d (%.3d)", le32_to_cpu(recs[i]->lrh_index),
-                       le32_to_cpu(recs[i]->lrh_len));
-
-                lopt = le32_to_cpu(recs[i]->lrh_type);
+       printf("ogen=%X name="DOSTID"\n",
+               lid->lid_id.lgl_ogen,
+               POSTID(&lid->lid_id.lgl_oi));
+}
 
-                if (recs[i]->lrh_id == CANCELLED)
-                        printf("NOT SET ");
+static void print_hsm_action(struct llog_agent_req_rec *larr)
+{
+       char    buf[12];
+       int     sz;
+
+       sz = larr->arr_hai.hai_len - sizeof(larr->arr_hai);
+       printf("lrh=[type=%X len=%d idx=%d] fid="DFID
+              " compound/cookie="LPX64"/"LPX64
+              " status=%s action=%s archive#=%d flags="LPX64
+              " create="LPU64" change="LPU64
+              " extent="LPX64"-"LPX64" gid="LPX64" datalen=%d"
+              " data=[%s]\n",
+              larr->arr_hdr.lrh_type,
+              larr->arr_hdr.lrh_len, larr->arr_hdr.lrh_index,
+              PFID(&larr->arr_hai.hai_fid),
+              larr->arr_compound_id, larr->arr_hai.hai_cookie,
+              agent_req_status2name(larr->arr_status),
+              hsm_copytool_action2name(larr->arr_hai.hai_action),
+              larr->arr_archive_id,
+              larr->arr_flags,
+              larr->arr_req_create, larr->arr_req_change,
+              larr->arr_hai.hai_extent.offset,
+              larr->arr_hai.hai_extent.length,
+              larr->arr_hai.hai_gid, sz,
+              hai_dump_data_field(&larr->arr_hai, buf, sizeof(buf)));
+}
 
-                if (lopt == OBD_CFG_REC) {
-                        struct lustre_cfg *lcfg;
-                        lcfg = (struct lustre_cfg *)((char*)(recs[i]) +
-                                                     sizeof(struct llog_rec_hdr));
-                        print_lustre_cfg(lcfg, &skip);
-                } else if (lopt == LLOG_PAD_MAGIC) {
-                        printf("padding\n");
-                } else
-                        printf("unknown type %x\n", lopt);
-        }
+void print_records(struct llog_rec_hdr **recs, int rec_number)
+{
+       __u32 lopt;
+       int i, skip = 0;
+
+       for (i = 0; i < rec_number; i++) {
+               printf("#%.2d (%.3d)", le32_to_cpu(recs[i]->lrh_index),
+                      le32_to_cpu(recs[i]->lrh_len));
+
+               lopt = le32_to_cpu(recs[i]->lrh_type);
+
+               if (recs[i]->lrh_id == CANCELLED)
+                       printf("NOT SET ");
+
+               switch (lopt) {
+               case OBD_CFG_REC:
+                       print_lustre_cfg(
+                               (struct lustre_cfg *)((char *)(recs[i]) +
+                               sizeof(struct llog_rec_hdr)), &skip);
+                       break;
+               case LLOG_PAD_MAGIC:
+                       printf("padding\n");
+                       break;
+               case LLOG_LOGID_MAGIC:
+                       print_logid((struct llog_logid_rec *)recs[i]);
+                       break;
+               case HSM_AGENT_REC:
+                       print_hsm_action((struct llog_agent_req_rec *)recs[i]);
+                       break;
+               default:
+                       printf("unknown type %x\n", lopt);
+                       break;
+               }
+       }
 }