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  | }