From 612f27788166e2f1153cb5f2c4b4bffba9a42235 Mon Sep 17 00:00:00 2001 From: jcl Date: Mon, 3 Jun 2013 16:03:36 +0200 Subject: [PATCH] LU-3339 mdt: HSM on disk actions record 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 Change-Id: I58bdbbd52a75a841c30e4477f3cb4c942d6d2a20 Reviewed-on: http://review.whamcloud.com/6529 Tested-by: Hudson Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- lustre/include/lprocfs_status.h | 21 +- lustre/include/lustre/lustre_idl.h | 47 +++ lustre/include/lustre_disk.h | 56 ++-- lustre/include/obd.h | 33 +- lustre/mdd/mdd_device.c | 87 +++++- lustre/mdd/mdd_internal.h | 1 + lustre/mdt/Makefile.in | 1 + lustre/mdt/mdt_handler.c | 34 ++- lustre/mdt/mdt_hsm_cdt_actions.c | 608 +++++++++++++++++++++++++++++++++++++ lustre/mdt/mdt_internal.h | 75 ++++- lustre/obdclass/llog_swab.c | 17 ++ lustre/utils/llog_reader.c | 86 ++++-- 12 files changed, 975 insertions(+), 91 deletions(-) create mode 100644 lustre/mdt/mdt_hsm_cdt_actions.c diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h index 63b5174..ff60773 100644 --- a/lustre/include/lprocfs_status.h +++ b/lustre/include/lprocfs_status.h @@ -55,15 +55,15 @@ #include 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 */ diff --git a/lustre/include/lustre/lustre_idl.h b/lustre/include/lustre/lustre_idl.h index ee5406e..a2dc8ab 100644 --- a/lustre/include/lustre/lustre_idl.h +++ b/lustre/include/lustre/lustre_idl.h @@ -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; diff --git a/lustre/include/lustre_disk.h b/lustre/include/lustre_disk.h index 5081819..48406b5 100644 --- a/lustre/include/lustre_disk.h +++ b/lustre/include/lustre_disk.h @@ -53,20 +53,21 @@ /****************** 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) diff --git a/lustre/include/obd.h b/lustre/include/obd.h index 6afec97..73805a4 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -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 { diff --git a/lustre/mdd/mdd_device.c b/lustre/mdd/mdd_device.c index 6db4bb2..7d7c66f 100644 --- a/lustre/mdd/mdd_device.c +++ b/lustre/mdd/mdd_device.c @@ -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) diff --git a/lustre/mdd/mdd_internal.h b/lustre/mdd/mdd_internal.h index 4d965d9..1b37f46 100644 --- a/lustre/mdd/mdd_internal.h +++ b/lustre/mdd/mdd_internal.h @@ -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); diff --git a/lustre/mdt/Makefile.in b/lustre/mdt/Makefile.in index 3867fd4..6761762 100644 --- a/lustre/mdt/Makefile.in +++ b/lustre/mdt/Makefile.in @@ -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@ diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index d13acbb..ca2090d 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -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 index 0000000..37a4da1 --- /dev/null +++ b/lustre/mdt/mdt_hsm_cdt_actions.c @@ -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 + * Author: Aurelien Degremont + */ + +#define DEBUG_SUBSYSTEM S_MDS + +#include +#include +#include +#include +#include +#include +#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, +}; + diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h index 9b0a6d1..81b0b20 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h @@ -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, diff --git a/lustre/obdclass/llog_swab.c b/lustre/obdclass/llog_swab.c index 10c6225..f509874 100644 --- a/lustre/obdclass/llog_swab.c +++ b/lustre/obdclass/llog_swab.c @@ -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 = diff --git a/lustre/utils/llog_reader.c b/lustre/utils/llog_reader.c index 748be6c..596ab6e 100644 --- a/lustre/utils/llog_reader.c +++ b/lustre/utils/llog_reader.c @@ -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; + } + } } -- 1.8.3.1