Chris Mason | 06ed4b3 | 2007-02-20 16:41:09 -0500 | [diff] [blame] | 1 | #define _XOPEN_SOURCE 500 |
| 2 | #include <stdio.h> |
| 3 | #include <stdlib.h> |
| 4 | #include <sys/types.h> |
| 5 | #include <sys/stat.h> |
| 6 | #include <fcntl.h> |
| 7 | #include <unistd.h> |
| 8 | #include "kerncompat.h" |
| 9 | #include "radix-tree.h" |
| 10 | #include "ctree.h" |
| 11 | #include "disk-io.h" |
| 12 | |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 13 | int mkfs(int fd, u64 num_blocks, u32 blocksize) |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 14 | { |
| 15 | struct btrfs_super_block super; |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 16 | struct btrfs_leaf *empty_leaf; |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 17 | struct btrfs_root_item root_item; |
| 18 | struct btrfs_item item; |
| 19 | struct btrfs_extent_item extent_item; |
| 20 | char *block; |
| 21 | int ret; |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 22 | u32 itemoff; |
| 23 | u32 start_block = BTRFS_SUPER_INFO_OFFSET / blocksize; |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 24 | |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 25 | btrfs_set_super_blocknr(&super, start_block); |
| 26 | btrfs_set_super_root(&super, start_block + 1); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 27 | strcpy((char *)(&super.magic), BTRFS_MAGIC); |
| 28 | btrfs_set_super_blocksize(&super, blocksize); |
| 29 | btrfs_set_super_total_blocks(&super, num_blocks); |
| 30 | btrfs_set_super_blocks_used(&super, 0); |
| 31 | |
| 32 | block = malloc(blocksize); |
| 33 | memset(block, 0, blocksize); |
| 34 | BUG_ON(sizeof(super) > blocksize); |
| 35 | memcpy(block, &super, sizeof(super)); |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 36 | ret = pwrite(fd, block, blocksize, BTRFS_SUPER_INFO_OFFSET); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 37 | BUG_ON(ret != blocksize); |
| 38 | |
| 39 | /* create the tree of root objects */ |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 40 | empty_leaf = malloc(blocksize); |
| 41 | memset(empty_leaf, 0, blocksize); |
| 42 | btrfs_set_header_parentid(&empty_leaf->header, |
| 43 | BTRFS_ROOT_TREE_OBJECTID); |
| 44 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 1); |
| 45 | btrfs_set_header_nritems(&empty_leaf->header, 2); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 46 | |
| 47 | /* create the items for the root tree */ |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 48 | btrfs_set_root_blocknr(&root_item, start_block + 2); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 49 | btrfs_set_root_refs(&root_item, 1); |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 50 | itemoff = __BTRFS_LEAF_DATA_SIZE(blocksize) - sizeof(root_item); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 51 | btrfs_set_item_offset(&item, itemoff); |
| 52 | btrfs_set_item_size(&item, sizeof(root_item)); |
| 53 | btrfs_set_key_objectid(&item.key, BTRFS_EXTENT_TREE_OBJECTID); |
| 54 | btrfs_set_key_offset(&item.key, 0); |
| 55 | btrfs_set_key_flags(&item.key, 0); |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 56 | memcpy(empty_leaf->items, &item, sizeof(item)); |
| 57 | memcpy(btrfs_leaf_data(empty_leaf) + itemoff, |
| 58 | &root_item, sizeof(root_item)); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 59 | |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 60 | btrfs_set_root_blocknr(&root_item, start_block + 3); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 61 | itemoff = itemoff - sizeof(root_item); |
| 62 | btrfs_set_item_offset(&item, itemoff); |
| 63 | btrfs_set_key_objectid(&item.key, BTRFS_FS_TREE_OBJECTID); |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 64 | memcpy(empty_leaf->items + 1, &item, sizeof(item)); |
| 65 | memcpy(btrfs_leaf_data(empty_leaf) + itemoff, |
| 66 | &root_item, sizeof(root_item)); |
| 67 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 1) * blocksize); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 68 | |
| 69 | /* create the items for the extent tree */ |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 70 | btrfs_set_header_parentid(&empty_leaf->header, |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 71 | BTRFS_EXTENT_TREE_OBJECTID); |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 72 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 2); |
| 73 | btrfs_set_header_nritems(&empty_leaf->header, 4); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 74 | |
| 75 | /* item1, reserve blocks 0-16 */ |
| 76 | btrfs_set_key_objectid(&item.key, 0); |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 77 | btrfs_set_key_offset(&item.key, start_block + 1); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 78 | btrfs_set_key_flags(&item.key, 0); |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 79 | itemoff = __BTRFS_LEAF_DATA_SIZE(blocksize) - |
| 80 | sizeof(struct btrfs_extent_item); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 81 | btrfs_set_item_offset(&item, itemoff); |
| 82 | btrfs_set_item_size(&item, sizeof(struct btrfs_extent_item)); |
| 83 | btrfs_set_extent_refs(&extent_item, 1); |
| 84 | btrfs_set_extent_owner(&extent_item, 0); |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 85 | memcpy(empty_leaf->items, &item, sizeof(item)); |
| 86 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), |
| 87 | &extent_item, btrfs_item_size(&item)); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 88 | |
| 89 | /* item2, give block 17 to the root */ |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 90 | btrfs_set_key_objectid(&item.key, start_block + 1); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 91 | btrfs_set_key_offset(&item.key, 1); |
| 92 | itemoff = itemoff - sizeof(struct btrfs_extent_item); |
| 93 | btrfs_set_item_offset(&item, itemoff); |
| 94 | btrfs_set_extent_owner(&extent_item, BTRFS_ROOT_TREE_OBJECTID); |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 95 | memcpy(empty_leaf->items + 1, &item, sizeof(item)); |
| 96 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), |
| 97 | &extent_item, btrfs_item_size(&item)); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 98 | |
| 99 | /* item3, give block 18 to the extent root */ |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 100 | btrfs_set_key_objectid(&item.key, start_block + 2); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 101 | btrfs_set_key_offset(&item.key, 1); |
| 102 | itemoff = itemoff - sizeof(struct btrfs_extent_item); |
| 103 | btrfs_set_item_offset(&item, itemoff); |
| 104 | btrfs_set_extent_owner(&extent_item, BTRFS_EXTENT_TREE_OBJECTID); |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 105 | memcpy(empty_leaf->items + 2, &item, sizeof(item)); |
| 106 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), |
| 107 | &extent_item, btrfs_item_size(&item)); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 108 | |
| 109 | /* item4, give block 19 to the FS root */ |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 110 | btrfs_set_key_objectid(&item.key, start_block + 3); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 111 | btrfs_set_key_offset(&item.key, 1); |
| 112 | itemoff = itemoff - sizeof(struct btrfs_extent_item); |
| 113 | btrfs_set_item_offset(&item, itemoff); |
| 114 | btrfs_set_extent_owner(&extent_item, BTRFS_FS_TREE_OBJECTID); |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 115 | memcpy(empty_leaf->items + 3, &item, sizeof(item)); |
| 116 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), |
| 117 | &extent_item, btrfs_item_size(&item)); |
| 118 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 2) * blocksize); |
| 119 | if (ret != blocksize) |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 120 | return -1; |
| 121 | |
| 122 | /* finally create the FS root */ |
Chris Mason | 123abc8 | 2007-03-14 14:14:43 -0400 | [diff] [blame] | 123 | btrfs_set_header_parentid(&empty_leaf->header, BTRFS_FS_TREE_OBJECTID); |
| 124 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 3); |
| 125 | btrfs_set_header_nritems(&empty_leaf->header, 0); |
| 126 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 3) * blocksize); |
| 127 | if (ret != blocksize) |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 128 | return -1; |
| 129 | return 0; |
| 130 | } |