From 9962d6f84db5fd587bbe13640a9361c2872f3728 Mon Sep 17 00:00:00 2001 From: Alexander Boyko Date: Fri, 16 Apr 2021 05:57:34 -0400 Subject: [PATCH] LU-14617 utils: llog_reader updatelog support The patch adds printing UPDATE_REC for llog_reader. It is usefull for updatelog analyze. Here is an example of record [0x50001a21b:0x1233d:0x0] type:xattr_set/7 params:3 p_0:0 p_1:1 p_2:2 [0x50001a211:0x475:0x0] type:xattr_set/7 params:3 p_0:0 p_1:1 p_2:2 [0x3800182e3:0x475:0x0] type:xattr_set/7 params:3 p_0:0 p_1:1 p_2:2 [0x200032c9a:0x245:0x0] type:xattr_set/7 params:3 p_0:0 p_1:1 p_2:2 [0x200000001:0x15:0x0] type:write/12 params:2 p_0:3 p_1:4 p_0 - 12/trusted.lov p_1 - 0/ p_2 - 25972/\x0100000000000000000000000000000000000000000002000... p_3 - 25974/\x0800000000000000P\xD1AB006x0000000400EC^\x000000... p_4 - 1/ llog logic processing base on incrementing record index, the fix adds checks for it. Also adds more info from header, and drops useless - Bit X not set. Test-Parameters: trivial Signed-off-by: Alexander Boyko Change-Id: Id50de15040526dc07ae708ac5db046832706be31 Reviewed-on: https://review.whamcloud.com/43343 Tested-by: jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Alexander Zarochentsev Reviewed-by: Oleg Drokin --- lustre/utils/llog_reader.c | 170 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 164 insertions(+), 6 deletions(-) diff --git a/lustre/utils/llog_reader.c b/lustre/utils/llog_reader.c index ef59c8b..24903c8 100644 --- a/lustre/utils/llog_reader.c +++ b/lustre/utils/llog_reader.c @@ -219,7 +219,7 @@ int llog_pack_buffer(int fd, struct llog_log_hdr **llog, struct llog_rec_hdr **recs_pr = NULL; char *ptr = NULL; int count; - int i; + int i, last_idx; rc = fstat(fd, &st); if (rc < 0) { @@ -288,6 +288,7 @@ int llog_pack_buffer(int fd, struct llog_log_hdr **llog, ptr = file_buf + __le32_to_cpu((*llog)->llh_hdr.lrh_len); i = 0; + last_idx = 0; while (ptr < (file_buf + file_size)) { struct llog_rec_hdr *cur_rec; int idx; @@ -315,11 +316,20 @@ int llog_pack_buffer(int fd, struct llog_log_hdr **llog, printf("rec #%d type=%x len=%u offset %lu\n", idx, cur_rec->lrh_type, cur_rec->lrh_len, offset); } else { - printf("Bit %d of %d not set\n", idx, recs_num); cur_rec->lrh_id = CANCELLED; + if (cur_rec->lrh_type == LLOG_PAD_MAGIC && + ((offset + cur_rec->lrh_len) & 0x7) != 0) + printf("rec #%d wrong padding len=%u offset %lu to 0x%lx\n", + idx, cur_rec->lrh_len, offset, + offset + cur_rec->lrh_len); /* The header counts only set records */ i--; } + if (last_idx + 1 != idx) { + printf("Previous index is %d, current %d, offset %lu\n", + last_idx, idx, offset); + } + last_idx = idx; ptr += __le32_to_cpu(cur_rec->lrh_len); if ((ptr - file_buf) > file_size) { @@ -358,15 +368,20 @@ void llog_unpack_buffer(int fd, struct llog_log_hdr *llog_buf, void print_llog_header(struct llog_log_hdr *llog_buf) { time_t t; + unsigned int lrh_len = __le32_to_cpu(llog_buf->llh_hdr.lrh_len); + struct llog_rec_tail *tail = ((struct llog_rec_tail *)((char *)llog_buf+ + lrh_len - sizeof(llog_buf->llh_tail))); - printf("Header size : %u\n", - __le32_to_cpu(llog_buf->llh_hdr.lrh_len)); + printf("Header size : %u\t llh_size : %u\n", lrh_len, + __le32_to_cpu(llog_buf->llh_size)); t = __le64_to_cpu(llog_buf->llh_timestamp); printf("Time : %s", ctime(&t)); - printf("Number of records: %u\n", - __le32_to_cpu(llog_buf->llh_count) - 1); + printf("Number of records: %u\tcat_idx: %u\tlast_idx: %u\n", + __le32_to_cpu(llog_buf->llh_count)-1, + __le32_to_cpu(llog_buf->llh_cat_idx), + __le32_to_cpu(tail->lrt_index)); printf("Target uuid : %s\n", (char *)(&llog_buf->llh_tgtuuid)); @@ -761,6 +776,146 @@ void print_changelog_rec(struct llog_changelog_rec *rec) printf("\n"); } +static void lustre_swab_lu_fid(struct lu_fid *fid) +{ + __swab64s(&fid->f_seq); + __swab32s(&fid->f_oid); + __swab32s(&fid->f_ver); +} + +static inline size_t +update_op_size(unsigned int param_count) +{ + return offsetof(struct update_op, uop_params_off[param_count]); +} + + +static inline struct update_op * +update_op_next_op(const struct update_op *uop) +{ + return (struct update_op *)((char *)uop + + update_op_size(uop->uop_param_count)); +} + +static void lustre_swab_update_ops(struct update_ops *uops, + unsigned int op_count) +{ + unsigned int i; + unsigned int j; + + struct update_op *op = + (struct update_op *)((char *)&uops->uops_op[0]); + + for (i = 0; i < op_count; i++, op = update_op_next_op(op)) { + lustre_swab_lu_fid(&op->uop_fid); + __swab16s(&op->uop_type); + __swab16s(&op->uop_param_count); + for (j = 0; j < op->uop_param_count; j++) + __swab16s(&op->uop_params_off[j]); + } +} +static const char *update_op_str(__u16 opc) +{ + static const char *opc_str[] = { + [OUT_START] = "start", + [OUT_CREATE] = "create", + [OUT_DESTROY] = "destroy", + [OUT_REF_ADD] = "ref_add", + [OUT_REF_DEL] = "ref_del", + [OUT_ATTR_SET] = "attr_set", + [OUT_ATTR_GET] = "attr_get", + [OUT_XATTR_SET] = "xattr_set", + [OUT_XATTR_GET] = "xattr_get", + [OUT_XATTR_LIST] = "xattr_list", + [OUT_INDEX_LOOKUP] = "lookup", + [OUT_INDEX_INSERT] = "insert", + [OUT_INDEX_DELETE] = "delete", + [OUT_WRITE] = "write", + [OUT_XATTR_DEL] = "xattr_del", + [OUT_PUNCH] = "punch", + [OUT_READ] = "read", + [OUT_NOOP] = "noop", + }; + + if (opc < (sizeof(opc_str) / sizeof((opc_str)[0])) && + opc_str[opc] != NULL) + return opc_str[opc]; + else + return "unknown"; +} + +char *buf2str(void *buf, unsigned int size) +{ + const char *hex = "0123456789ABCDEF"; + char *buf_c = buf; + static char string[128]; + int i, j = 0; + bool format_hex = false; + + if (size > 0 && buf_c[size - 1] == 0) + size--; + for (i = 0; i < size; i++) { + if (buf_c[i] >= 0x20 && buf_c[i] <= 0x7E) { + string[j++] = buf_c[i]; + format_hex = false; + } else if (j < sizeof(string) - 6) { + if (!format_hex) { + string[j++] = '\\'; + string[j++] = 'x'; + format_hex = true; + } + string[j++] = hex[(buf_c[i] >> 4) & 0xF]; + string[j++] = hex[buf_c[i] & 0xF]; + } else { + break; + } + if (j == sizeof(string) - 2) + break; + } + string[j] = 0; + return string; +} + +void print_update_rec(struct llog_update_record *lur) +{ + struct update_records *rec = &lur->lur_update_rec; + unsigned int i, j, up_count, pm_count; + struct update_op *op; + struct object_update_param *pm; + + up_count = __le32_to_cpu(rec->ur_update_count); + pm_count = __le32_to_cpu(rec->ur_param_count); + printf("updatelog record master_transno:%llu batchid:%llu flags:0x%x u_index:%d u_count:%d p_count:%d\n", + __le64_to_cpu(rec->ur_master_transno), + __le64_to_cpu(rec->ur_batchid), + __le32_to_cpu(rec->ur_flags), + __le32_to_cpu(rec->ur_index), + up_count, + pm_count); + + op = (struct update_op *)((char *)&rec->ur_ops.uops_op[0] + 0); + if (op->uop_type != __le16_to_cpu(op->uop_type)) + lustre_swab_update_ops(&rec->ur_ops, up_count); + + for (i = 0; i < up_count; i++, op = update_op_next_op(op)) { + printf("\t"DFID" type:%s/%d params:%d ", + PFID(&op->uop_fid), update_op_str(op->uop_type), + op->uop_type, op->uop_param_count); + for (j = 0; j < op->uop_param_count; j++) + printf("p_%d:%d ", j, op->uop_params_off[j]); + printf("\n"); + } + pm = (struct object_update_param *) op; + for (i = 0; i < pm_count; i++) { + printf("\tp_%d - %d/%s\n", i, pm->oup_len, + buf2str(pm->oup_buf, pm->oup_len)); + pm = (struct object_update_param *)((char *)(pm + 1) + + pm->oup_len); + } + printf("\n"); + +} + static void print_records(struct llog_rec_hdr **recs, int rec_number, int is_ext) { @@ -806,6 +961,9 @@ static void print_records(struct llog_rec_hdr **recs, printf("changelog_user record id:0x%x\n", __le32_to_cpu(recs[i]->lrh_id)); break; + case UPDATE_REC: + print_update_rec((struct llog_update_record *)recs[i]); + break; default: printf("unknown type %x\n", lopt); break; -- 1.8.3.1