Remove the last radix tree (block_group_cache)
[platform/upstream/btrfs-progs.git] / mkfs.c
1 /*
2  * Copyright (C) 2007 Oracle.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License v2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public
14  * License along with this program; if not, write to the
15  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16  * Boston, MA 021110-1307, USA.
17  */
18
19 #define _XOPEN_SOURCE 500
20 #ifndef __CHECKER__
21 #include <sys/ioctl.h>
22 #include <sys/mount.h>
23 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <uuid/uuid.h>
31 #include <linux/fs.h>
32 #include "kerncompat.h"
33 #include "ctree.h"
34 #include "disk-io.h"
35 #include "transaction.h"
36
37 #ifdef __CHECKER__
38 #define BLKGETSIZE64 0
39 static inline int ioctl(int fd, int define, u64 *size) { return 0; }
40 #endif
41
42 static int __make_root_dir(struct btrfs_trans_handle *trans,
43                            struct btrfs_root *root, u64 objectid)
44 {
45         int ret;
46         char buf[8];
47         struct btrfs_key inode_map;
48         struct btrfs_inode_item inode_item;
49
50         buf[0] = '.';
51         buf[1] = '.';
52
53         inode_map.objectid = objectid;
54         btrfs_set_key_type(&inode_map, BTRFS_INODE_ITEM_KEY);
55         inode_map.offset = 0;
56
57         memset(&inode_item, 0, sizeof(inode_item));
58         btrfs_set_inode_generation(&inode_item, root->fs_info->generation);
59         btrfs_set_inode_size(&inode_item, 6);
60         btrfs_set_inode_nlink(&inode_item, 1);
61         btrfs_set_inode_nblocks(&inode_item, 1);
62         btrfs_set_inode_mode(&inode_item, S_IFDIR | 0555);
63
64         if (root->fs_info->tree_root == root)
65                 btrfs_set_super_root_dir(root->fs_info->disk_super, objectid);
66
67         ret = btrfs_insert_inode(trans, root, objectid, &inode_item);
68         if (ret)
69                 goto error;
70         ret = btrfs_insert_dir_item(trans, root, buf, 1, objectid,
71                                     &inode_map, BTRFS_FT_DIR);
72         if (ret)
73                 goto error;
74         ret = btrfs_insert_dir_item(trans, root, buf, 2, objectid,
75                                     &inode_map, BTRFS_FT_DIR);
76         if (ret)
77                 goto error;
78         btrfs_set_root_dirid(&root->root_item, objectid);
79         ret = 0;
80 error:
81         return ret;
82 }
83
84 static int make_block_groups(struct btrfs_trans_handle *trans,
85                              struct btrfs_root *root)
86 {
87         u64 group_size;
88         u64 total_bytes;
89         u64 cur_start;
90         int ret;
91         u64 nr = 0;
92         struct btrfs_block_group_cache *cache;
93         struct cache_tree *bg_cache = &root->fs_info->block_group_cache;
94
95         root = root->fs_info->extent_root;
96
97         /* first we bootstrap the things into cache */
98         group_size = BTRFS_BLOCK_GROUP_SIZE;
99         cache = malloc(sizeof(*cache));
100         cache->key.objectid = 0;
101         cache->key.offset = group_size;
102         cache->cache.start = 0;
103         cache->cache.size = group_size;
104         btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY);
105
106         memset(&cache->item, 0, sizeof(cache->item));
107         btrfs_set_block_group_used(&cache->item,
108                            btrfs_super_bytes_used(root->fs_info->disk_super));
109         ret = insert_existing_cache_extent(bg_cache, &cache->cache);
110         BUG_ON(ret);
111
112         total_bytes = btrfs_super_total_bytes(root->fs_info->disk_super);
113         cur_start = group_size;
114         while(cur_start < total_bytes) {
115                 cache = malloc(sizeof(*cache));
116                 cache->key.objectid = cur_start;
117                 cache->key.offset = group_size;
118                 cache->cache.start = cur_start;
119                 cache->cache.size = group_size;
120                 btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY);
121                 memset(&cache->item, 0, sizeof(cache->item));
122                 if (nr % 3)
123                         cache->item.flags |= BTRFS_BLOCK_GROUP_DATA;
124
125                 ret = insert_existing_cache_extent(bg_cache, &cache->cache);
126                 BUG_ON(ret);
127                 cur_start += group_size;
128                 nr++;
129         }
130         /* then insert all the items */
131         cur_start = 0;
132         while(cur_start < total_bytes) {
133                 struct cache_extent *ce;
134                 ce = find_first_cache_extent(bg_cache, cur_start);
135                 BUG_ON(!ce);
136                 cache = container_of(ce, struct btrfs_block_group_cache,
137                                         cache);
138                 ret = btrfs_insert_block_group(trans, root, &cache->key,
139                                                &cache->item);
140                 BUG_ON(ret);
141                 cur_start += group_size;
142         }
143         return 0;
144 }
145
146 static int make_root_dir(int fd) {
147         struct btrfs_root *root;
148         struct btrfs_super_block super;
149         struct btrfs_trans_handle *trans;
150         int ret;
151         struct btrfs_key location;
152
153         root = open_ctree_fd(fd, &super);
154
155         if (!root) {
156                 fprintf(stderr, "ctree init failed\n");
157                 return -1;
158         }
159         trans = btrfs_start_transaction(root, 1);
160         ret = make_block_groups(trans, root);
161         ret = __make_root_dir(trans, root->fs_info->tree_root,
162                               BTRFS_ROOT_TREE_DIR_OBJECTID);
163         if (ret)
164                 goto err;
165         ret = __make_root_dir(trans, root, BTRFS_FIRST_FREE_OBJECTID);
166         if (ret)
167                 goto err;
168         memcpy(&location, &root->fs_info->fs_root->root_key, sizeof(location));
169         location.offset = (u64)-1;
170         ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root,
171                         "default", 7,
172                         btrfs_super_root_dir(root->fs_info->disk_super),
173                         &location, BTRFS_FT_DIR);
174         if (ret)
175                 goto err;
176         btrfs_commit_transaction(trans, root, root->fs_info->disk_super);
177         ret = close_ctree(root, &super);
178 err:
179         return ret;
180 }
181
182 int mkfs(int fd, char *pathname, u64 num_bytes, u32 nodesize, u32 leafsize,
183          u32 sectorsize)
184 {
185         struct btrfs_super_block super;
186         struct btrfs_leaf *empty_leaf;
187         struct btrfs_root_item root_item;
188         struct btrfs_item item;
189         struct btrfs_extent_item extent_item;
190         struct btrfs_inode_item *inode_item;
191         char *block;
192         int ret;
193         u32 itemoff;
194         u32 start_block = BTRFS_SUPER_INFO_OFFSET;
195         u32 first_free = BTRFS_SUPER_INFO_OFFSET + sectorsize;
196
197         btrfs_set_super_generation(&super, 1);
198         btrfs_set_super_bytenr(&super, start_block);
199         btrfs_set_super_root_level(&super, 0);
200         btrfs_set_super_root(&super, first_free);
201         strcpy((char *)(&super.magic), BTRFS_MAGIC);
202
203 printf("blocksize is %d\n", leafsize);
204         btrfs_set_super_sectorsize(&super, sectorsize);
205         btrfs_set_super_leafsize(&super, leafsize);
206         btrfs_set_super_nodesize(&super, nodesize);
207
208         num_bytes = (num_bytes / sectorsize) * sectorsize;
209         btrfs_set_super_total_bytes(&super, num_bytes);
210         btrfs_set_super_bytes_used(&super, start_block + 3 * leafsize +
211                                    sectorsize);
212         uuid_generate(super.fsid);
213
214         block = malloc(sectorsize);
215         memset(block, 0, sectorsize);
216         BUG_ON(sizeof(super) > sectorsize);
217         memcpy(block, &super, sizeof(super));
218         ret = pwrite(fd, block, sectorsize, BTRFS_SUPER_INFO_OFFSET);
219         BUG_ON(ret != sectorsize);
220
221         /* create the tree of root objects */
222         empty_leaf = malloc(leafsize);
223         memset(empty_leaf, 0, leafsize);
224         btrfs_set_header_bytenr(&empty_leaf->header, first_free);
225         btrfs_set_header_nritems(&empty_leaf->header, 2);
226         btrfs_set_header_generation(&empty_leaf->header, 0);
227         btrfs_set_header_owner(&empty_leaf->header, BTRFS_ROOT_TREE_OBJECTID);
228         memcpy(empty_leaf->header.fsid, super.fsid,
229                sizeof(empty_leaf->header.fsid));
230
231         /* create the items for the root tree */
232         inode_item = &root_item.inode;
233         memset(inode_item, 0, sizeof(*inode_item));
234         btrfs_set_inode_generation(inode_item, 1);
235         btrfs_set_inode_size(inode_item, 3);
236         btrfs_set_inode_nlink(inode_item, 1);
237         btrfs_set_inode_nblocks(inode_item, 1);
238         btrfs_set_inode_mode(inode_item, S_IFDIR | 0755);
239
240         // memset(&root_item, 0, sizeof(root_item));
241         btrfs_set_root_dirid(&root_item, 0);
242         btrfs_set_root_refs(&root_item, 1);
243         btrfs_set_disk_key_offset(&item.key, 0);
244         btrfs_set_item_size(&item, sizeof(root_item));
245         btrfs_set_disk_key_type(&item.key, BTRFS_ROOT_ITEM_KEY);
246
247         itemoff = __BTRFS_LEAF_DATA_SIZE(leafsize) - sizeof(root_item);
248         btrfs_set_root_bytenr(&root_item, first_free + leafsize);
249         root_item.level = 0;
250         btrfs_set_item_offset(&item, itemoff);
251         btrfs_set_disk_key_objectid(&item.key, BTRFS_EXTENT_TREE_OBJECTID);
252         memcpy(empty_leaf->items, &item, sizeof(item));
253         memcpy(btrfs_leaf_data(empty_leaf) + itemoff,
254                 &root_item, sizeof(root_item));
255
256         btrfs_set_root_bytenr(&root_item, first_free + leafsize * 2);
257         btrfs_set_root_bytes_used(&root_item, 1);
258         itemoff = itemoff - sizeof(root_item);
259         btrfs_set_item_offset(&item, itemoff);
260         btrfs_set_disk_key_objectid(&item.key, BTRFS_FS_TREE_OBJECTID);
261         memcpy(empty_leaf->items + 1, &item, sizeof(item));
262         memcpy(btrfs_leaf_data(empty_leaf) + itemoff,
263                 &root_item, sizeof(root_item));
264         ret = pwrite(fd, empty_leaf, leafsize, first_free);
265
266         /* create the items for the extent tree */
267         btrfs_set_header_bytenr(&empty_leaf->header, first_free + leafsize);
268         btrfs_set_header_nritems(&empty_leaf->header, 4);
269
270         /* item1, reserve blocks 0-16 */
271         btrfs_set_disk_key_objectid(&item.key, 0);
272         btrfs_set_disk_key_offset(&item.key, first_free);
273         btrfs_set_disk_key_type(&item.key, 0);
274         btrfs_set_disk_key_type(&item.key, BTRFS_EXTENT_ITEM_KEY);
275         itemoff = __BTRFS_LEAF_DATA_SIZE(leafsize) -
276                         sizeof(struct btrfs_extent_item);
277         btrfs_set_item_offset(&item, itemoff);
278         btrfs_set_item_size(&item, sizeof(struct btrfs_extent_item));
279         btrfs_set_extent_refs(&extent_item, 1);
280         btrfs_set_extent_owner(&extent_item, BTRFS_ROOT_TREE_OBJECTID);
281         memcpy(empty_leaf->items, &item, sizeof(item));
282         memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item),
283                 &extent_item, btrfs_item_size(&item));
284
285         /* item2, give block 17 to the root */
286         btrfs_set_disk_key_objectid(&item.key, first_free);
287         btrfs_set_disk_key_offset(&item.key, leafsize);
288         itemoff = itemoff - sizeof(struct btrfs_extent_item);
289         btrfs_set_item_offset(&item, itemoff);
290         memcpy(empty_leaf->items + 1, &item, sizeof(item));
291         memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item),
292                 &extent_item, btrfs_item_size(&item));
293
294         /* item3, give block 18 to the extent root */
295         btrfs_set_disk_key_objectid(&item.key, first_free + leafsize);
296         btrfs_set_disk_key_offset(&item.key, leafsize);
297         itemoff = itemoff - sizeof(struct btrfs_extent_item);
298         btrfs_set_item_offset(&item, itemoff);
299         memcpy(empty_leaf->items + 2, &item, sizeof(item));
300         memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item),
301                 &extent_item, btrfs_item_size(&item));
302
303         /* item4, give block 19 to the FS root */
304         btrfs_set_disk_key_objectid(&item.key, first_free + leafsize * 2);
305         btrfs_set_disk_key_offset(&item.key, leafsize);
306         itemoff = itemoff - sizeof(struct btrfs_extent_item);
307         btrfs_set_item_offset(&item, itemoff);
308         memcpy(empty_leaf->items + 3, &item, sizeof(item));
309         memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item),
310                 &extent_item, btrfs_item_size(&item));
311         ret = pwrite(fd, empty_leaf, leafsize, first_free + leafsize);
312         if (ret != leafsize)
313                 return -1;
314
315         /* finally create the FS root */
316         btrfs_set_header_bytenr(&empty_leaf->header, first_free + leafsize * 2);
317         btrfs_set_header_nritems(&empty_leaf->header, 0);
318         ret = pwrite(fd, empty_leaf, leafsize, first_free + leafsize * 2);
319         if (ret != leafsize)
320                 return -1;
321         return 0;
322 }
323
324 u64 device_size(int fd, struct stat *st)
325 {
326         u64 size;
327         if (S_ISREG(st->st_mode)) {
328                 return st->st_size;
329         }
330         if (!S_ISBLK(st->st_mode)) {
331                 return 0;
332         }
333         if (ioctl(fd, BLKGETSIZE64, &size) >= 0) {
334                 return size;
335         }
336         return 0;
337 }
338
339 static void print_usage(void)
340 {
341         fprintf(stderr, "usage: mkfs.btrfs [ -l leafsize ] [ -n nodesize] dev [ blocks ]\n");
342         exit(1);
343 }
344
345 int main(int ac, char **av)
346 {
347         char *file;
348         u64 block_count = 0;
349         int fd;
350         struct stat st;
351         int ret;
352         int i;
353         u32 leafsize = 8 * 1024;
354         u32 sectorsize = 4096;
355         u32 nodesize = 8 * 1024;
356         char *buf = malloc(sectorsize);
357         char *realpath_name;
358
359         while(1) {
360                 int c;
361                 c = getopt(ac, av, "l:n:");
362                 if (c < 0)
363                         break;
364                 switch(c) {
365                         case 'l':
366                                 leafsize = atol(optarg);
367                                 break;
368                         case 'n':
369                                 nodesize = atol(optarg);
370                                 break;
371                         default:
372                                 print_usage();
373                 }
374         }
375         if (leafsize < sectorsize || (leafsize & (sectorsize - 1))) {
376                 fprintf(stderr, "Illegal leafsize %u\n", leafsize);
377                 exit(1);
378         }
379         if (nodesize < sectorsize || (nodesize & (sectorsize - 1))) {
380                 fprintf(stderr, "Illegal nodesize %u\n", nodesize);
381                 exit(1);
382         }
383         ac = ac - optind;
384         if (ac >= 1) {
385                 file = av[optind];
386                 if (ac == 2) {
387                         block_count = atol(av[optind + 1]);
388                         if (!block_count) {
389                                 fprintf(stderr, "error finding block count\n");
390                                 exit(1);
391                         }
392                 }
393         } else {
394                 print_usage();
395         }
396         fd = open(file, O_RDWR);
397         if (fd < 0) {
398                 fprintf(stderr, "unable to open %s\n", file);
399                 exit(1);
400         }
401         ret = fstat(fd, &st);
402         if (ret < 0) {
403                 fprintf(stderr, "unable to stat %s\n", file);
404                 exit(1);
405         }
406         if (block_count == 0) {
407                 block_count = device_size(fd, &st);
408                 if (block_count == 0) {
409                         fprintf(stderr, "unable to find %s size\n", file);
410                         exit(1);
411                 }
412                 block_count /= sectorsize;
413         }
414         if (block_count < 256) {
415                 fprintf(stderr, "device %s is too small\n", file);
416                 exit(1);
417         }
418         block_count = block_count * sectorsize;
419         memset(buf, 0, sectorsize);
420         for(i = 0; i < 64; i++) {
421                 ret = write(fd, buf, sectorsize);
422                 if (ret != sectorsize) {
423                         fprintf(stderr, "unable to zero fill device\n");
424                         exit(1);
425                 }
426         }
427         realpath_name = realpath(file, NULL);
428         ret = mkfs(fd, realpath_name, block_count, nodesize, leafsize,
429                    sectorsize);
430         if (ret) {
431                 fprintf(stderr, "error during mkfs %d\n", ret);
432                 exit(1);
433         }
434         ret = make_root_dir(fd);
435         if (ret) {
436                 fprintf(stderr, "failed to setup the root directory\n");
437                 exit(1);
438         }
439         printf("fs created on %s nodesize %u leafsize %u sectorsize %u bytes %llu\n",
440                file, nodesize, leafsize, sectorsize,
441                (unsigned long long)block_count);
442         return 0;
443 }
444