From: Mark Tinguely Date: Mon, 14 Apr 2014 06:15:05 +0000 (+1000) Subject: logprint: handle split EFI entry X-Git-Tag: v3.2.0-rc1~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9404cb40e20025acf66fa62c9ac776d668918994;p=thirdparty%2Fxfsprogs-dev.git logprint: handle split EFI entry xfs_logprint does not correctly handle EFI entries that are split across two log buffers. xfs_efi_copy_format() falsely interrupts the truncated size of the split entry as being a corrupt entry. If the first log entry has enough information, namely the number of extents in the entry and the identifier, then display this information and a warning that this entry is truncated. Otherwise, if there is not enough information in the first log buffer, then print a message that the EFI decode was not possible. These messages are similar to split inode entries. Example of a continued entry: Oper (336): tid: f214bdb len: 44 clientid: TRANS flags: CONTINUE EFI: #regs: 1 num_extents: 2 id: 0xffff880804f63900 EFI free extent data skipped (CONTINUE set, no space) Reported-by: Michael L. Semon Signed-off-by: Mark Tinguely Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- diff --git a/logprint/log_misc.c b/logprint/log_misc.c index 45a2ed59b..928f60a52 100644 --- a/logprint/log_misc.c +++ b/logprint/log_misc.c @@ -477,13 +477,17 @@ xlog_print_trans_efd(xfs_caddr_t *ptr, uint len) int -xlog_print_trans_efi(xfs_caddr_t *ptr, uint src_len) +xlog_print_trans_efi( + xfs_caddr_t *ptr, + uint src_len, + int continued) { xfs_efi_log_format_t *src_f, *f; uint dst_len; xfs_extent_t *ex; int i; int error = 0; + int core_size = offsetof(xfs_efi_log_format_t, efi_extents); /* * memmove to ensure 8-byte alignment for the long longs in @@ -498,17 +502,29 @@ xlog_print_trans_efi(xfs_caddr_t *ptr, uint src_len) /* convert to native format */ dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t); + + if (continued && src_len < core_size) { + printf(_("EFI: Not enough data to decode further\n")); + return 1; + } + if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) { fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname); exit(1); } - if (xfs_efi_copy_format((char*)src_f, src_len, f)) { + if (xfs_efi_copy_format((char*)src_f, src_len, f, continued)) { error = 1; goto error; } printf(_("EFI: #regs: %d num_extents: %d id: 0x%llx\n"), f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id); + + if (continued) { + printf(_("EFI free extent data skipped (CONTINUE set, no space)\n")); + goto error; + } + ex = f->efi_extents; for (i=0; i < f->efi_nextents; i++) { printf("(s: 0x%llx, l: %d) ", @@ -1033,7 +1049,8 @@ xlog_print_record( } case XFS_LI_EFI: { skip = xlog_print_trans_efi(&ptr, - be32_to_cpu(op_head->oh_len)); + be32_to_cpu(op_head->oh_len), + continued); break; } case XFS_LI_EFD: { @@ -1571,7 +1588,11 @@ xfs_inode_item_format_convert(char *src_buf, uint len, xfs_inode_log_format_t *i } int -xfs_efi_copy_format(char *buf, uint len, xfs_efi_log_format_t *dst_efi_fmt) +xfs_efi_copy_format( + char *buf, + uint len, + struct xfs_efi_log_format *dst_efi_fmt, + int continued) { uint i; uint nextents = ((xfs_efi_log_format_t *)buf)->efi_nextents; @@ -1579,7 +1600,7 @@ xfs_efi_copy_format(char *buf, uint len, xfs_efi_log_format_t *dst_efi_fmt) uint len32 = sizeof(xfs_efi_log_format_32_t) + (nextents - 1) * sizeof(xfs_extent_32_t); uint len64 = sizeof(xfs_efi_log_format_64_t) + (nextents - 1) * sizeof(xfs_extent_64_t); - if (len == dst_len) { + if (len == dst_len || continued) { memcpy((char *)dst_efi_fmt, buf, len); return 0; } else if (len == len32) { diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c index 60da2722d..2b5c4beb9 100644 --- a/logprint/log_print_all.c +++ b/logprint/log_print_all.c @@ -410,7 +410,7 @@ xlog_recover_print_efi( fprintf(stderr, _("%s: xlog_recover_print_efi: malloc failed\n"), progname); exit(1); } - if (xfs_efi_copy_format((char*)src_f, src_len, f)) { + if (xfs_efi_copy_format((char*)src_f, src_len, f, 0)) { free(f); return; } diff --git a/logprint/logprint.h b/logprint/logprint.h index 933c9e6d2..228b04280 100644 --- a/logprint/logprint.h +++ b/logprint/logprint.h @@ -47,6 +47,6 @@ extern void print_stars(void); extern xfs_inode_log_format_t * xfs_inode_item_format_convert(char *, uint, xfs_inode_log_format_t *); -extern int xfs_efi_copy_format(char *, uint, xfs_efi_log_format_t *); +extern int xfs_efi_copy_format(char *, uint, xfs_efi_log_format_t *, int); #endif /* LOGPRINT_H */