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