1 | /* volinfo.c 2 | --------- 3 | 4 | Dumps a lot of information about a volume to the console. 5 | 6 | $Id: volinfo.c,v 1.7 2003/09/22 09:05:18 stewart Exp $ 7 | 8 | (C)2003 Stewart Smith 9 | Distributed under the GNU Public License 10 | */ 11 | 12 | // Block Device includes 13 | #include "testkit/types.h" 14 | #include "testkit/block_dev.h" 15 | #include "testkit/bitops.h" 16 | #include "disk.h" 17 | 18 | // UNIX includes 19 | #include <stdio.h> 20 | #include <stdlib.h> 21 | #include <sys/stat.h> 22 | #include <unistd.h> 23 | #include <fcntl.h> 24 | #include <string.h> 25 | 26 | // FCFS Includes 27 | #include "super_block.h" 28 | #include "onode.h" 29 | #include "onode_index.h" 30 | #include "space_bitmap.h" 31 | 32 | void print_sb_flags(struct fcfs_sb *sb, int desired_loc) 33 | { 34 | if((sb->flags & 0x03)!=desired_loc) 35 | printf("WARNING-CORRUPT: "); 36 | if((sb->flags & 0x03) == FCFS_SBloc_start_volume) 37 | printf("This is the start of a volume\n"); 38 | else 39 | if((sb->flags & 0x03) == FCFS_SBloc_end_volume) 40 | printf("This is the End of a volume\n"); 41 | else 42 | if((sb->flags & 0x03) == FCFS_SBloc_start_ag) 43 | printf("This is the start of an Allocation Group\n"); 44 | else 45 | printf("Volume is corrupt - unknown Super Block Location\n"); 46 | 47 | printf("FLAGS: 0x%llx\n",sb->flags); 48 | 49 | if(test_bit(FCFS_FLAG_Dirty,&sb->flags)) 50 | printf("\t- Volume is Dirty\n"); 51 | if(test_bit(FCFS_FLAG_Experimental,&sb->flags)) 52 | printf("\t- Volume has been used by EXPERIMENTAL code. It's probably b0rked.\n"); 53 | if(test_bit(FCFS_FLAG_JournalMeta,&sb->flags)) 54 | printf("\t- Volume journals Meta Data\n"); 55 | if(test_bit(FCFS_FLAG_JournalData,&sb->flags)) 56 | printf("\t- Volume journals Data\n"); 57 | if(test_bit(FCFS_FLAG_Versioned,&sb->flags)) 58 | printf("\t- Volume is Versioned\n"); 59 | } 60 | 61 | int print_sb(struct fcfs_disk *disk) 62 | { 63 | struct fcfs_disk_block *block, *block2; 64 | struct fcfs_sb *sb, *sb2; 65 | 66 | 67 | block = disk_getblock(disk,0); 68 | sb = (struct fcfs_sb*)block->data; 69 | if(sb->magic1!=FCFS_SB_MAGIC1) 70 | fprintf(stderr,"WARNING: Primary SB MAGIC1 mismatch. Corrupt Volume.\n"); 71 | if(sb->magic2!=FCFS_SB_MAGIC2) 72 | fprintf(stderr,"WARNING: Primary SB MAGIC2 mismatch. Corrupt Volume.\n"); 73 | if(sb->bits!=64) 74 | fprintf(stderr,"WARNING: Weird number of filesystem base bits. Corrupt Volume.\n"); 75 | if(sb->version!=FCFS_SB_VERSION1) 76 | fprintf(stderr,"WARNING: Unknown Version of FS & SB.\n"); 77 | 78 | printf("Primary Superblock\n"); 79 | printf("------------------\n"); 80 | printf("Volume name is: %s\n",sb->name); /* FIXME: CHECK NAME!!! */ 81 | printf("MAGIC1: 0x%x\tMAGIC2: 0x%x\nVERSION: 0x%x\tBITS: %u\t LENGTH: %u bytes\n",sb->magic1,sb->magic2,sb->version,sb->bits,sb->sblength); 82 | printf("Block Size: %u\tNo. Blocks: %llu\n",sb->bsize,sb->blocksnr); 83 | 84 | // sb flags 85 | print_sb_flags(sb,FCFS_SBloc_start_volume); 86 | 87 | printf("Number of Clean Mounts: %llu\n",sb->num_mounts); 88 | printf("Number of UnClean Mounts: %llu\n",sb->num_dirtymounts); 89 | printf("Time Created: %llu\n",sb->time_created); 90 | printf("Time last cleanly mounted:%llu\n",sb->time_clean); 91 | printf("Time last dirty mounted: %llu\n",sb->time_dirtymount); 92 | 93 | printf("\n"); 94 | 95 | printf("Onode Index:\n"); 96 | printf("------------\n"); 97 | printf("ONode Index location: %llu\n",sb->onode_index_blocknr); 98 | printf("Number of onodes: %llu used, %llu available, %llu total\n", 99 | sb->onindex_used, 100 | sb->onindex_free, 101 | sb->onindex_num_onodes); 102 | printf("Next ID: %llu\tNode Size: %lu\n", 103 | sb->onindex_next_id, 104 | sb->onindex_node_size); 105 | 106 | 107 | block2 = disk_getblock(disk,disk->blocksnr-1); 108 | sb2 = (struct fcfs_sb*)block2->data; 109 | 110 | printf("\n\nChecking end of disk super block backup...\n"); 111 | 112 | if(sb2->magic1!=sb->magic1) 113 | printf("WARNING-CORRUPT: End of disk SB magic1 is incorrect 0x%x\n",sb2->magic1); 114 | if(sb2->magic2!=sb->magic2) 115 | printf("WARNING-CORRUPT: End of disk SB magic2 is incorrect 0x%x\n",sb2->magic2); 116 | if(sb2->version!=sb->version) 117 | printf("WARNING-CORRUPT: End of disk SB version differs 0x%x\n",sb2->version); 118 | if(sb2->bits!=sb->bits) 119 | printf("WARNING-CORRUPT: End of disk SB bits differ %u\n",sb2->bits); 120 | if(sb2->sblength!=sb2->sblength) 121 | printf("WARNING-CORRUPT: End of disk SB length differs %u\n",sb2->sblength); 122 | 123 | print_sb_flags(sb2,FCFS_SBloc_end_volume); 124 | 125 | if((sb2->flags & (~0x03ULL))!=(sb->flags & (~0x03ULL))) 126 | { 127 | printf("WARNING-CORRUPT: End of disk SB flags differ\n"); 128 | printf("End of Disk SB FLAGS: 0x%llx 0x%llx\n",sb2->flags, (sb2->flags & (~0x03ULL))); 129 | } 130 | 131 | if(sb2->bsize!=sb->bsize) 132 | printf("WARNING-CORRUPT: Block size differs %u vs %u\n",sb->bsize, sb2->bsize); 133 | if(sb2->blocksnr!=sb->blocksnr) 134 | printf("WARNING-CORRUPT: Number of blocks differs %llu vs %llu\n",sb->blocksnr,sb2->blocksnr); 135 | 136 | if(strcmp(sb2->name,sb->name)!=0) 137 | printf("WARNING-CORRUPT: Volume names differ.\n"); 138 | 139 | disk_freeblock(block2); 140 | 141 | disk_freeblock(block); 142 | } 143 | 144 | int print_used_blocks(struct fcfs_disk *disk) 145 | { 146 | int ag,blk; 147 | struct fcfs_disk_block *block; 148 | struct fcfs_sb *sb; 149 | 150 | block = disk_getblock(disk,0); 151 | sb = (struct fcfs_sb*)block->data; 152 | 153 | printf("Checking used blocks...\n"); 154 | printf("-----------------------"); 155 | 156 | for(ag=0;ag<sb->allocation_groupsnr;ag++) 157 | { 158 | printf("\nAG %u: ",ag); 159 | for(blk=0;blk<sb->ag_blocksnr;blk++) 160 | if(!ag_block_free(disk,ag, blk)) 161 | printf("%u,",blk); 162 | } 163 | printf("\n"); 164 | return 0; 165 | } 166 | 167 | int print_onode_index_leaf(struct fcfs_disk *disk,u64 blocknr) 168 | { 169 | struct fcfs_disk_block *block; 170 | struct fcfs_onode_index_leaf *leaf; 171 | int i; 172 | 173 | block = disk_getblock(disk,blocknr); 174 | leaf = (struct fcfs_onode_index_leaf *)block->data; 175 | 176 | if(leaf->magic1!=FCFS_ONODE_INDEX_LEAF_MAGIC1) 177 | printf("WARNING-CORRUPT: Bad onode_index_leaf MAGIC1\n"); 178 | printf("\tOnode Index LEAF: %llu in block %llu\n",leaf->id,leaf->block); 179 | printf("\tUsed: %llu/%lu\n",leaf->used,disk->sb->onindex_node_size); 180 | printf("\t key:block\n"); 181 | for(i=0;i<leaf->used;i++) 182 | printf("\t %llu:%llu\n",leaf->items[i].key, 183 | leaf->items[i].onode_blocknr); 184 | 185 | disk_freeblock(block); 186 | return 0; 187 | } 188 | 189 | int print_onode_index(struct fcfs_disk *disk) 190 | { 191 | struct fcfs_disk_block *block; 192 | struct fcfs_onode_index_node *index_node; 193 | int i; 194 | 195 | block = disk_getblock(disk,disk->sb->onode_index_blocknr); 196 | 197 | index_node = (struct fcfs_onode_index_node*)block->data; 198 | if(index_node->magic1!=FCFS_ONODE_INDEX_NODE_MAGIC1) 199 | printf("WARNING-CORRUPT: Bad onode_index_node MAGIC1\n"); 200 | printf("Onode Index Node: %llu in block %llu\n",index_node->id,index_node->block); 201 | if(disk->sb->onode_index_blocknr!=index_node->block) 202 | printf("WARNING-CORRUPT: onode_index_node->block != sb->onode_index_blocknr\n"); 203 | printf("Used: %llu/%lu\n",index_node->used,disk->sb->onindex_node_size); 204 | printf(" key:block\n"); 205 | for(i=0;i<index_node->used;i++) 206 | printf(" %llu:%llu\n",index_node->items[i].key, 207 | index_node->items[i].node_blocknr); 208 | 209 | for(i=0;i<index_node->used;i++) 210 | print_onode_index_leaf(disk,index_node->items[i].node_blocknr); 211 | 212 | disk_freeblock(block); 213 | return 0; 214 | } 215 | 216 | int main(int argc, char* argv[]) 217 | { 218 | struct block_device bdev; 219 | struct fcfs_disk *disk; 220 | struct fcfs_disk_block *block; 221 | 222 | if(argc<4) 223 | { 224 | fprintf(stderr,"FCFS Volume Info Utility (volinfo)\n"); 225 | fprintf(stderr,"----------------------------------\n"); 226 | fprintf(stderr,"$Id: volinfo.c,v 1.7 2003/09/22 09:05:18 stewart Exp $\n\n"); 227 | fprintf(stderr,"Written by: Stewart Smith (stewart@flamingspork.com)\n\n"); 228 | fprintf(stderr,"Usage:\n\t./volinfo device blocksize blockcount\n\n"); 229 | exit(0); 230 | } 231 | 232 | block_dev_init(); 233 | block_dev_new(&bdev,argv[1],atoi(argv[2]),atoi(argv[3])); 234 | disk = disk_new(&bdev); 235 | 236 | block = disk_getblock(disk,0); 237 | disk->sb = (struct fcfs_sb*)block->data; 238 | 239 | print_sb(disk); 240 | 241 | print_used_blocks(disk); 242 | 243 | print_onode_index(disk); 244 | 245 | /* Clean up and exit */ 246 | block_dev_close(&bdev); 247 | 248 | return 0; 249 | }