1 | /*
2 | mkfs.c
3 | ------
4 | $Id: mkfs.c,v 1.23 2003/11/03 19:29:16 stewart Exp $
5 | (C)2003 Stewart Smith
6 | Distributed under the GNU Public License
7 |
8 | This is the 'mkfs' utility for FCFS - the new Walnut object store.
9 | The name mkfs is kept purely 'cause it says what it does.
10 |
11 | Some data structures have been constructed out of those
12 | present in the Linux Kernel (v2.5.69). They are copyright
13 | of their respective owners.
14 | */
15 |
16 | #include <stdio.h>
17 | #include <stdlib.h>
18 | #include <sys/stat.h>
19 | #include <unistd.h>
20 | #include <fcntl.h>
21 | #include <string.h>
22 | #include <time.h>
23 |
24 |
25 | #include "testkit/block_dev.h"
26 | #include "testkit/types.h"
27 | #include "testkit/bitops.h"
28 | #include "disk.h"
29 |
30 | #include "super_block.h"
31 | #include "onode.h"
32 | #include "onode_index.h"
33 | #include "space_bitmap.h"
34 |
35 | #define EXPERIMENTAL
36 |
37 | u64 atou64(const char *nptr)
38 | {
39 | u64 out,i;
40 | for(out=0,i=0;nptr[i]!='\0';i++)
41 | {
42 | out*=10;
43 | out+=nptr[i]-'0';
44 | }
45 |
46 | return out;
47 | }
48 |
49 | int make_sb(void *sb_v, u32 bsize,u64 bcount, char* name)
50 | {
51 | struct fcfs_sb *sb = (struct fcfs_sb*) sb_v;
52 |
53 | sb->magic1 = FCFS_SB_MAGIC1;
54 | sb->version = FCFS_SB_VERSION1;
55 | sb->bits = 64;
56 | sb->sblength = sizeof(struct fcfs_sb);
57 | sb->flags = 0;
58 | set_bit(FCFS_FLAG_JournalMeta,&(sb->flags));
59 | #ifdef EXPERIMENTAL
60 | set_bit(FCFS_FLAG_Experimental,&(sb->flags));
61 | #endif
62 |
63 | sb->bsize = bsize;
64 | sb->blocksnr = bcount;
65 | strcpy(sb->name,name);
66 | sb->magic2 = FCFS_SB_MAGIC2;
67 |
68 | sb->time_created = time(NULL);
69 | sb->time_clean = time(NULL);
70 | sb->time_dirtymount = 0x0ULL;
71 |
72 | sb->num_mounts = 0x0ULL;
73 | sb->num_dirtymounts = 0x0ULL;
74 |
75 | /* We simply steal the number of allocation groups from XFS. :)
76 | They use 8, so we'll steal that.
77 | */
78 | sb->allocation_groupsnr = 8;
79 | sb->ag_blocksnr = bcount / sb->allocation_groupsnr;
80 |
81 | fprintf(stderr,"ALLOCATION GROUPS: 0x%x, each 0x%x\n",
82 | sb->allocation_groupsnr,
83 | sb->ag_blocksnr);
84 |
85 | sb->onindex_num_onodes = 0; /* Num onodes in index */
86 | sb->onindex_used = 0; /* Num of used inodes in index */
87 | sb->onindex_free = 0; /* Num of free onodes in index */
88 | sb->onindex_next_id = 0; /* Next ID to use */
89 |
90 | /* FIXME: Potentially do real nasty things that can't be described
91 | * in polite circles when our structs change size... */
92 | sb->onindex_node_size = ((sb->bsize - 4*sizeof(u64)) / sizeof(u64))/2;
93 | /* In number of keys */
94 |
95 | return 1; /* success, although we don't check it*/
96 | }
97 |
98 | int write_superblocks(struct fcfs_disk* disk)
99 | {
100 | struct fcfs_disk_block *block;
101 | u32 i;
102 |
103 | /* Write start of volume master SB */
104 | block = disk_getblock(disk,0);
105 |
106 | disk->sb->flags = disk->sb->flags | FCFS_SBloc_start_volume; /* start of volume*/
107 |
108 | disk_writeblock(block);
109 | disk_freeblock(block);
110 | fprintf(stderr,"SuperBlock at Block 0\n");
111 |
112 | /* Write end of volume Backup SB */
113 | block = disk_newblock(disk,disk->blocksnr-1ULL);
114 |
115 |
116 | // disk->sb->flags = disk->sb->flags & ~0x03ULL;
117 | disk->sb->flags = disk->sb->flags ^ FCFS_SBloc_start_volume; /* start of volume*/
118 | disk->sb->flags = disk->sb->flags | FCFS_SBloc_end_volume; /* end of volume*/
119 |
120 | memcpy(block->data,disk->sb,disk->bsize);
121 |
122 | disk_writeblock(block);
123 | disk_freeblock(block);
124 | fprintf(stderr,"BACKUP SuperBlock at Block 0x%llx\n",disk->blocksnr-1ULL);
125 |
126 | disk->sb->flags = disk->sb->flags ^ FCFS_SBloc_end_volume; /* end of volume*/
127 |
128 | for(i=1;i<disk->sb->allocation_groupsnr;i++)
129 | {
130 | block = disk_newblock(disk,i*disk->sb->ag_blocksnr);
131 |
132 | disk->sb->flags = disk->sb->flags | FCFS_SBloc_start_ag; /* start of ag*/
133 | memcpy(block->data,disk->sb,disk->bsize);
134 | disk_writeblock(block);
135 | disk_freeblock(block);
136 | fprintf(stderr,"BACKUP SuperBlock at Block 0x%llx (offset 0x%llx)\n",i*disk->sb->ag_blocksnr,(i*disk->sb->ag_blocksnr)*disk->bsize);
137 | }
138 | return 0;
139 | }
140 |
141 | int write_block_bitmaps(struct fcfs_disk* disk)
142 | {
143 | struct fcfs_disk_block *block;
144 | struct fcfs_block_run br;
145 | int i,j;
146 |
147 | /* Create initial empty Block Bitmap */
148 | for(i=0;i<(disk->sb->allocation_groupsnr);i++)
149 | {
150 | /* For each ag, blank one of the right size */
151 | for(j=0;j<space_bitmap_size(disk->sb,i);j++)
152 | {
153 | block = disk_newblock(disk,i*disk->sb->ag_blocksnr+2);
154 | memset(block->data,0,disk->bsize);
155 | fprintf(stderr,"BITMAP: Zeroing 0x%x (offset %x) length %u\n",
156 | i*disk->sb->ag_blocksnr+2,
157 | (i*disk->sb->ag_blocksnr+2)*disk->bsize,
158 | space_bitmap_size(disk->sb,i));
159 | disk_writeblock(block);
160 | disk_freeblock(block);
161 | }
162 | }
163 |
164 | for(i=0;i<(disk->sb->allocation_groupsnr);i++)
165 | {
166 | /* Setup our Block Run */
167 | br.allocation_group = i;
168 | br.start = 1;
169 | br.len = space_bitmap_size(disk->sb,i);
170 |
171 | space_bitmap_allocate_block(disk,i,0);
172 |
173 | for(j=0;j<space_bitmap_size(disk->sb,i);j++)
174 | space_bitmap_allocate_block(disk,i,j+1);
175 |
176 | }
177 |
178 | return 0;
179 | }
180 |
181 | int main(int argc,char* argv[])
182 | {
183 | struct block_device bdev;
184 | struct fcfs_disk *disk;
185 | struct fcfs_disk_block *block;
186 | struct fcfs_sb *sb;
187 | struct fcfs_onode_index *index;
188 | u64 bsize;
189 | u64 bcount;
190 | char* buffer;
191 | int i;
192 |
193 | if(argc<5)
194 | {
195 | fprintf(stderr,"FCFS Make Object Store Utility (mkfs)\n");
196 | fprintf(stderr,"-------------------------------------\n");
197 | fprintf(stderr,"$Id: mkfs.c,v 1.23 2003/11/03 19:29:16 stewart Exp $\n\n");
198 | fprintf(stderr,"Written by: Stewart Smith (stewart@flamingspork.com)\n\n");
199 | fprintf(stderr,"Usage:\n\t./mkfs device blocksize blockcount name [initial objects]\n\n");
200 | exit(0);
201 | }
202 |
203 | bsize = atou64(argv[2]);
204 | bcount = atou64(argv[3]);
205 |
206 | fprintf(stderr,"Going to create volume '%s' with 0x%llx blocks at 0x%llx bytes each\n\n",argv[4],bcount,bsize);
207 |
208 | block_dev_init();
209 | block_dev_new(&bdev,argv[1],bsize,bcount);
210 | disk = disk_new(&bdev);
211 |
212 | if((buffer = (char*)malloc(sizeof(char*)*bsize))==0)
213 | {
214 | fprintf(stderr,"Unable to allocate buffer\n");
215 | abort();
216 | }
217 |
218 | /* Make a new Super Block */
219 | block = disk_newblock(disk,0);
220 | sb = (struct fcfs_sb*)block->data;
221 |
222 | if(!make_sb(sb,disk->bsize,disk->blocksnr,argv[4]))
223 | {
224 | fprintf(stderr,"Make_sb failed\n");
225 | abort();
226 | }
227 |
228 | disk->sb = sb;
229 |
230 | write_superblocks(disk);
231 |
232 | write_block_bitmaps(disk);
233 |
234 | index = onode_index_new(disk);
235 | onode_index_new_root(index);
236 |
237 | for(i=5;i<argc;i++)
238 | {
239 | struct fcfs_onode1 *node;
240 | struct fcfs_block_run *onode_br;
241 | int forknr;
242 | char data[1024]; int j;
243 | FILE* a;
244 |
245 | node = onode1_new(disk);
246 | onode_br = onode_index_insert(index,node);
247 | // onode1_grow(disk,onode_br,10);
248 | // onode1_grow(disk,onode_br,20);
249 | onode1_fork_new(disk,onode_br,0x42,strlen(argv[i]),argv[i],1);
250 | forknr = onode1_fork_new(disk,onode_br,0x69,0,NULL,0);
251 | fprintf(stderr,"+++++++GOING TO GO AND WRITE %s++++++++\n",argv[5]);
252 | a = fopen(argv[i],"r");
253 | j=0;
254 | while(!feof(a))
255 | {
256 | fgets(data,1000,a);
257 | fprintf(stderr,"*******WRITING %d bytes*******\n",strlen(data));
258 | onode1_fork_write(disk,onode_br,forknr,j,(u64)strlen(data),data);
259 | j+=strlen(data);
260 | }
261 | fclose(a);
262 | }
263 |
264 | disk_freeblock(block);
265 |
266 | /* Clean up and exit */
267 | block_dev_close(&bdev);
268 |
269 | return 0;
270 | }