/* * dump_dir_block() * */ void dump_dir_block(FILE *out, char *buf) { struct ocfs2_dir_entry *dirent; int offset = 0; int end = ocfs2_dir_trailer_blk_off(gbls.fs); struct ocfs2_dir_block_trailer *trailer = ocfs2_dir_trailer_from_block(gbls.fs, buf); struct list_dir_opts ls_opts = { .fs = gbls.fs, .out = out, }; if (!strncmp((char *)trailer->db_signature, OCFS2_DIR_TRAILER_SIGNATURE, sizeof(trailer->db_signature))) dump_dir_trailer(out, trailer); else end = gbls.fs->fs_blocksize; fprintf(out, "\tEntries:\n"); while (offset < end) { dirent = (struct ocfs2_dir_entry *) (buf + offset); if (((offset + dirent->rec_len) > end) || (dirent->rec_len < 8) || ((dirent->rec_len % 4) != 0) || (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) { /* Corrupted */ return; } dump_dir_entry(dirent, 0, offset, gbls.fs->fs_blocksize, NULL, &ls_opts); offset += dirent->rec_len; } } static void dump_dx_entry(FILE *out, int i, struct ocfs2_dx_entry *dx_entry) { fprintf(out, "\t %-2d (0x%08x 0x%08x) %-13"PRIu64"\n", i, dx_entry->dx_major_hash, dx_entry->dx_minor_hash, (uint64_t)dx_entry->dx_dirent_blk); }
/* * detect_block() * */ static enum dump_block_type detect_block (char *buf) { struct ocfs2_dinode *inode; struct ocfs2_extent_block *extent; struct ocfs2_group_desc *group; struct ocfs2_dir_block_trailer *trailer; enum dump_block_type ret = DUMP_BLOCK_UNKNOWN; inode = (struct ocfs2_dinode *)buf; if (!strncmp((char *)inode->i_signature, OCFS2_INODE_SIGNATURE, sizeof(inode->i_signature))) { ret = DUMP_BLOCK_INODE; goto bail; } extent = (struct ocfs2_extent_block *)buf; if (!strncmp((char *)extent->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE, sizeof(extent->h_signature))) { ret = DUMP_BLOCK_EXTENT_BLOCK; goto bail; } group = (struct ocfs2_group_desc *)buf; if (!strncmp((char *)group->bg_signature, OCFS2_GROUP_DESC_SIGNATURE, sizeof(group->bg_signature))) { ret = DUMP_BLOCK_GROUP_DESCRIPTOR; goto bail; } trailer = ocfs2_dir_trailer_from_block(gbls.fs, buf); if (!strncmp((char *)trailer->db_signature, OCFS2_DIR_TRAILER_SIGNATURE, sizeof(trailer->db_signature))) { ret = DUMP_BLOCK_DIR_BLOCK; goto bail; } bail: return ret; } /* detect_block */
/* * 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 ; }