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