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