/* * dump_jbd_metadata() * */ void dump_jbd_metadata(FILE *out, enum ocfs2_block_type type, char *buf, uint64_t blknum) { struct ocfs2_dir_block_trailer *trailer; struct ocfs2_xattr_block *xb; struct ocfs2_xattr_header *xh; struct ocfs2_refcount_block *rb; struct ocfs2_dx_root_block *dx_root; struct ocfs2_dx_leaf *dx_leaf; struct ocfs2_dinode *di; struct ocfs2_extent_block *eb; fprintf(out, "\tBlock %"PRIu64": ", blknum); switch (type) { case OCFS2_BLOCK_INODE: case OCFS2_BLOCK_SUPERBLOCK: fprintf(out, "Inode\n"); di = (struct ocfs2_dinode *)buf; ocfs2_swap_inode_to_cpu(gbls.fs, di); dump_inode(out, di); if (di->i_flags & OCFS2_LOCAL_ALLOC_FL) dump_local_alloc(out, &(di->id2.i_lab)); else if (di->i_flags & OCFS2_CHAIN_FL) dump_chain_list(out, &(di->id2.i_chain)); else if (S_ISLNK(di->i_mode) && !di->i_clusters) dump_fast_symlink(out, (char *)di->id2.i_symlink); else if (di->i_flags & OCFS2_DEALLOC_FL) dump_truncate_log(out, &(di->id2.i_dealloc)); else if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL)) dump_extent_list(out, &(di->id2.i_list)); fprintf(out, "\n"); break; case OCFS2_BLOCK_EXTENT_BLOCK: fprintf(out, "Extent\n"); eb = (struct ocfs2_extent_block *)buf; ocfs2_swap_extent_block_to_cpu(gbls.fs, eb); dump_extent_block(out, eb); dump_extent_list(out, &(eb->h_list)); fprintf(out, "\n"); break; case OCFS2_BLOCK_GROUP_DESCRIPTOR: fprintf(out, "Group\n"); ocfs2_swap_group_desc_to_cpu(gbls.fs, (struct ocfs2_group_desc *)buf); dump_group_descriptor(out, (struct ocfs2_group_desc *)buf, 0); fprintf(out, "\n"); break; case OCFS2_BLOCK_DIR_BLOCK: fprintf(out, "Dirblock\n"); /* * We know there's a trailer, because that's how it * was detected */ ocfs2_swap_dir_entries_to_cpu(buf, ocfs2_dir_trailer_blk_off(gbls.fs)); trailer = ocfs2_dir_trailer_from_block(gbls.fs, buf); ocfs2_swap_dir_trailer(trailer); dump_dir_block(out, buf); fprintf(out, "\n"); break; case OCFS2_BLOCK_XATTR: fprintf(out, "Xattr\n"); xb = (struct ocfs2_xattr_block *)buf; ocfs2_swap_xattr_block_to_cpu(gbls.fs, xb); if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) { xh = &xb->xb_attrs.xb_header; dump_xattr(out, xh); } fprintf(out, "\n"); break; case OCFS2_BLOCK_REFCOUNT: fprintf(out, "Refcount\n"); rb = (struct ocfs2_refcount_block *)buf; ocfs2_swap_refcount_block_to_cpu(gbls.fs, rb); dump_refcount_block(out, rb); fprintf(out, "\n"); break; case OCFS2_BLOCK_DXROOT: fprintf(out, "DxRoot\n"); dx_root = (struct ocfs2_dx_root_block *)buf; ocfs2_swap_dx_root_to_cpu(gbls.fs, dx_root); dump_dx_root(out, dx_root); fprintf(out, "\n"); break; case OCFS2_BLOCK_DXLEAF: fprintf(out, "DxLeaf\n"); dx_leaf = (struct ocfs2_dx_leaf *)buf; ocfs2_swap_dx_leaf_to_cpu(dx_leaf); dump_dx_leaf(out, dx_leaf); fprintf(out, "\n"); break; default: fprintf(out, "TODO\n\n"); break; } return ; }
errcode_t ocfs2_read_super(ocfs2_filesys *fs, uint64_t superblock, char *sb) { errcode_t ret; char *blk, *swapblk; struct ocfs2_dinode *di, *orig_super; int orig_blocksize; int blocksize = io_get_blksize(fs->fs_io); ret = ocfs2_malloc_block(fs->fs_io, &blk); if (ret) return ret; ret = ocfs2_read_blocks(fs, superblock, 1, blk); if (ret) goto out_blk; di = (struct ocfs2_dinode *)blk; ret = OCFS2_ET_BAD_MAGIC; if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE, strlen(OCFS2_SUPER_BLOCK_SIGNATURE))) goto out_blk; /* * We want to use the latest superblock to validate. We need * a local-endian copy in fs->fs_super, and the unswapped copy to * check in blk. ocfs2_validate_meta_ecc() uses fs->fs_super and * fs->fs_blocksize. */ ret = ocfs2_malloc_block(fs->fs_io, &swapblk); if (ret) goto out_blk; memcpy(swapblk, blk, blocksize); orig_super = fs->fs_super; orig_blocksize = fs->fs_blocksize; fs->fs_super = (struct ocfs2_dinode *)swapblk; fs->fs_blocksize = blocksize; ocfs2_swap_inode_to_cpu(fs, fs->fs_super); ret = ocfs2_validate_meta_ecc(fs, blk, &di->i_check); fs->fs_super = orig_super; fs->fs_blocksize = orig_blocksize; ocfs2_free(&swapblk); if (ret) goto out_blk; ocfs2_swap_inode_to_cpu(fs, di); if (!sb) fs->fs_super = di; else { memcpy(sb, blk, fs->fs_blocksize); ocfs2_free(&blk); } return 0; out_blk: ocfs2_free(&blk); return ret; }
/* * dump_block_check * */ void dump_block_check(FILE *out, struct ocfs2_block_check *bc, void *block) { struct ocfs2_block_check tmp = *bc; int crc_fail; enum ocfs2_block_type bt = ocfs2_detect_block(block); /* Swap block to little endian for compute_meta_ecc */ switch (bt) { case OCFS2_BLOCK_INODE: case OCFS2_BLOCK_SUPERBLOCK: ocfs2_swap_inode_from_cpu(gbls.fs, block); break; case OCFS2_BLOCK_EXTENT_BLOCK: ocfs2_swap_extent_block_from_cpu(gbls.fs, block); break; case OCFS2_BLOCK_GROUP_DESCRIPTOR: ocfs2_swap_group_desc_from_cpu(gbls.fs, block); break; case OCFS2_BLOCK_DIR_BLOCK: ocfs2_swap_dir_entries_from_cpu(block, gbls.fs->fs_blocksize); break; case OCFS2_BLOCK_XATTR: ocfs2_swap_xattr_block_from_cpu(gbls.fs, block); break; case OCFS2_BLOCK_REFCOUNT: ocfs2_swap_refcount_block_from_cpu(gbls.fs, block); break; case OCFS2_BLOCK_DXROOT: ocfs2_swap_dx_root_from_cpu(gbls.fs, block); break; case OCFS2_BLOCK_DXLEAF: ocfs2_swap_dx_leaf_from_cpu(block); break; default: fprintf(out, "Unable to determine block type"); return; } /* Re-compute based on what we got from disk */ ocfs2_compute_meta_ecc(gbls.fs, block, bc); /* Swap block back to CPU */ switch (bt) { case OCFS2_BLOCK_INODE: case OCFS2_BLOCK_SUPERBLOCK: ocfs2_swap_inode_to_cpu(gbls.fs, block); break; case OCFS2_BLOCK_EXTENT_BLOCK: ocfs2_swap_extent_block_to_cpu(gbls.fs, block); break; case OCFS2_BLOCK_GROUP_DESCRIPTOR: ocfs2_swap_group_desc_to_cpu(gbls.fs, block); break; case OCFS2_BLOCK_DIR_BLOCK: ocfs2_swap_dir_entries_to_cpu(block, gbls.fs->fs_blocksize); break; case OCFS2_BLOCK_XATTR: ocfs2_swap_xattr_block_to_cpu(gbls.fs, block); break; case OCFS2_BLOCK_REFCOUNT: ocfs2_swap_refcount_block_to_cpu(gbls.fs, block); break; case OCFS2_BLOCK_DXROOT: ocfs2_swap_dx_root_to_cpu(gbls.fs, block); break; case OCFS2_BLOCK_DXLEAF: ocfs2_swap_dx_leaf_to_cpu(block); break; default: break; } crc_fail = memcmp(bc, &tmp, sizeof(*bc)); fprintf(out, "\tCRC32: %.8"PRIx32" ECC: %.4"PRIx16"\n", le32_to_cpu(tmp.bc_crc32e), le16_to_cpu(tmp.bc_ecc)); if (crc_fail) fprintf(out, "\t**FAILED CHECKSUM** Computed CRC32: %.8" PRIx32" ECC: %.4"PRIx16"\n", le32_to_cpu(bc->bc_crc32e), le16_to_cpu(bc->bc_ecc)); /* Leave the block as we found it. */ *bc = tmp; }