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 | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 13 | int mkfs(int fd, u64 num_blocks, u16 blocksize) |
| 14 | { |
| 15 | struct btrfs_super_block super; |
| 16 | struct btrfs_leaf empty_leaf; |
| 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; |
| 22 | u16 itemoff; |
| 23 | |
| 24 | btrfs_set_super_blocknr(&super, 16); |
| 25 | btrfs_set_super_root(&super, 17); |
| 26 | strcpy((char *)(&super.magic), BTRFS_MAGIC); |
| 27 | btrfs_set_super_blocksize(&super, blocksize); |
| 28 | btrfs_set_super_total_blocks(&super, num_blocks); |
| 29 | btrfs_set_super_blocks_used(&super, 0); |
| 30 | |
| 31 | block = malloc(blocksize); |
| 32 | memset(block, 0, blocksize); |
| 33 | BUG_ON(sizeof(super) > blocksize); |
| 34 | memcpy(block, &super, sizeof(super)); |
| 35 | ret = pwrite(fd, block, blocksize, BTRFS_SUPER_INFO_OFFSET(blocksize)); |
| 36 | BUG_ON(ret != blocksize); |
| 37 | |
| 38 | /* create the tree of root objects */ |
| 39 | memset(&empty_leaf, 0, sizeof(empty_leaf)); |
| 40 | btrfs_set_header_parentid(&empty_leaf.header, BTRFS_ROOT_TREE_OBJECTID); |
| 41 | btrfs_set_header_blocknr(&empty_leaf.header, 17); |
| 42 | btrfs_set_header_nritems(&empty_leaf.header, 2); |
| 43 | |
| 44 | /* create the items for the root tree */ |
| 45 | btrfs_set_root_blocknr(&root_item, 18); |
| 46 | btrfs_set_root_refs(&root_item, 1); |
| 47 | itemoff = LEAF_DATA_SIZE - sizeof(root_item); |
| 48 | btrfs_set_item_offset(&item, itemoff); |
| 49 | btrfs_set_item_size(&item, sizeof(root_item)); |
| 50 | btrfs_set_key_objectid(&item.key, BTRFS_EXTENT_TREE_OBJECTID); |
| 51 | btrfs_set_key_offset(&item.key, 0); |
| 52 | btrfs_set_key_flags(&item.key, 0); |
| 53 | memcpy(empty_leaf.items, &item, sizeof(item)); |
| 54 | memcpy(empty_leaf.data + itemoff, &root_item, sizeof(root_item)); |
| 55 | |
| 56 | btrfs_set_root_blocknr(&root_item, 19); |
| 57 | itemoff = itemoff - sizeof(root_item); |
| 58 | btrfs_set_item_offset(&item, itemoff); |
| 59 | btrfs_set_key_objectid(&item.key, BTRFS_FS_TREE_OBJECTID); |
| 60 | memcpy(empty_leaf.items + 1, &item, sizeof(item)); |
| 61 | memcpy(empty_leaf.data + itemoff, &root_item, sizeof(root_item)); |
| 62 | ret = pwrite(fd, &empty_leaf, blocksize, 17 * blocksize); |
| 63 | |
| 64 | /* create the items for the extent tree */ |
| 65 | btrfs_set_header_parentid(&empty_leaf.header, |
| 66 | BTRFS_EXTENT_TREE_OBJECTID); |
| 67 | btrfs_set_header_blocknr(&empty_leaf.header, 18); |
| 68 | btrfs_set_header_nritems(&empty_leaf.header, 4); |
| 69 | |
| 70 | /* item1, reserve blocks 0-16 */ |
| 71 | btrfs_set_key_objectid(&item.key, 0); |
| 72 | btrfs_set_key_offset(&item.key, 17); |
| 73 | btrfs_set_key_flags(&item.key, 0); |
| 74 | itemoff = LEAF_DATA_SIZE - sizeof(struct btrfs_extent_item); |
| 75 | btrfs_set_item_offset(&item, itemoff); |
| 76 | btrfs_set_item_size(&item, sizeof(struct btrfs_extent_item)); |
| 77 | btrfs_set_extent_refs(&extent_item, 1); |
| 78 | btrfs_set_extent_owner(&extent_item, 0); |
| 79 | memcpy(empty_leaf.items, &item, sizeof(item)); |
| 80 | memcpy(empty_leaf.data + btrfs_item_offset(&item), &extent_item, |
| 81 | btrfs_item_size(&item)); |
| 82 | |
| 83 | /* item2, give block 17 to the root */ |
| 84 | btrfs_set_key_objectid(&item.key, 17); |
| 85 | btrfs_set_key_offset(&item.key, 1); |
| 86 | itemoff = itemoff - sizeof(struct btrfs_extent_item); |
| 87 | btrfs_set_item_offset(&item, itemoff); |
| 88 | btrfs_set_extent_owner(&extent_item, BTRFS_ROOT_TREE_OBJECTID); |
| 89 | memcpy(empty_leaf.items + 1, &item, sizeof(item)); |
| 90 | memcpy(empty_leaf.data + btrfs_item_offset(&item), &extent_item, |
| 91 | btrfs_item_size(&item)); |
| 92 | |
| 93 | /* item3, give block 18 to the extent root */ |
| 94 | btrfs_set_key_objectid(&item.key, 18); |
| 95 | btrfs_set_key_offset(&item.key, 1); |
| 96 | itemoff = itemoff - sizeof(struct btrfs_extent_item); |
| 97 | btrfs_set_item_offset(&item, itemoff); |
| 98 | btrfs_set_extent_owner(&extent_item, BTRFS_EXTENT_TREE_OBJECTID); |
| 99 | memcpy(empty_leaf.items + 2, &item, sizeof(item)); |
| 100 | memcpy(empty_leaf.data + btrfs_item_offset(&item), &extent_item, |
| 101 | btrfs_item_size(&item)); |
| 102 | |
| 103 | /* item4, give block 19 to the FS root */ |
| 104 | btrfs_set_key_objectid(&item.key, 19); |
| 105 | btrfs_set_key_offset(&item.key, 1); |
| 106 | itemoff = itemoff - sizeof(struct btrfs_extent_item); |
| 107 | btrfs_set_item_offset(&item, itemoff); |
| 108 | btrfs_set_extent_owner(&extent_item, BTRFS_FS_TREE_OBJECTID); |
| 109 | memcpy(empty_leaf.items + 3, &item, sizeof(item)); |
| 110 | memcpy(empty_leaf.data + btrfs_item_offset(&item), &extent_item, |
| 111 | btrfs_item_size(&item)); |
| 112 | ret = pwrite(fd, &empty_leaf, blocksize, 18 * blocksize); |
| 113 | if (ret != sizeof(empty_leaf)) |
| 114 | return -1; |
| 115 | |
| 116 | /* finally create the FS root */ |
| 117 | btrfs_set_header_parentid(&empty_leaf.header, BTRFS_FS_TREE_OBJECTID); |
| 118 | btrfs_set_header_blocknr(&empty_leaf.header, 19); |
| 119 | btrfs_set_header_nritems(&empty_leaf.header, 0); |
| 120 | ret = pwrite(fd, &empty_leaf, blocksize, 19 * blocksize); |
| 121 | if (ret != sizeof(empty_leaf)) |
| 122 | return -1; |
| 123 | return 0; |
| 124 | } |
| 125 | |
| 126 | #if 0 |
Chris Mason | 06ed4b3 | 2007-02-20 16:41:09 -0500 | [diff] [blame] | 127 | int mkfs(int fd) |
| 128 | { |
Chris Mason | 234b63a | 2007-03-13 10:46:10 -0400 | [diff] [blame] | 129 | struct btrfs_root_info info[2]; |
| 130 | struct btrfs_leaf empty_leaf; |
Chris Mason | 0783fcf | 2007-03-12 20:12:07 -0400 | [diff] [blame] | 131 | struct btrfs_item item; |
Chris Mason | 234b63a | 2007-03-13 10:46:10 -0400 | [diff] [blame] | 132 | struct btrfs_extent_item extent_item; |
Chris Mason | 06ed4b3 | 2007-02-20 16:41:09 -0500 | [diff] [blame] | 133 | int ret; |
| 134 | |
Chris Mason | cfaa729 | 2007-02-21 17:04:57 -0500 | [diff] [blame] | 135 | /* setup the super block area */ |
Chris Mason | 06ed4b3 | 2007-02-20 16:41:09 -0500 | [diff] [blame] | 136 | memset(info, 0, sizeof(info)); |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 137 | btrfs_set_root_blocknr(info, 16); |
| 138 | btrfs_set_root_objectid(info, 1); |
| 139 | btrfs_set_root_tree_root(info, 17); |
Chris Mason | 06ed4b3 | 2007-02-20 16:41:09 -0500 | [diff] [blame] | 140 | |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 141 | btrfs_set_root_blocknr(info + 1, 16); |
| 142 | btrfs_set_root_objectid(info + 1, 2); |
| 143 | btrfs_set_root_tree_root(info + 1, 18); |
| 144 | |
Chris Mason | 06ed4b3 | 2007-02-20 16:41:09 -0500 | [diff] [blame] | 145 | ret = pwrite(fd, info, sizeof(info), |
Chris Mason | 234b63a | 2007-03-13 10:46:10 -0400 | [diff] [blame] | 146 | BTRFS_SUPER_INFO_OFFSET(BTRFS_BLOCKSIZE)); |
Chris Mason | 06ed4b3 | 2007-02-20 16:41:09 -0500 | [diff] [blame] | 147 | if (ret != sizeof(info)) |
| 148 | return -1; |
Chris Mason | cfaa729 | 2007-02-21 17:04:57 -0500 | [diff] [blame] | 149 | |
| 150 | /* create leaves for the tree root and extent root */ |
Chris Mason | 06ed4b3 | 2007-02-20 16:41:09 -0500 | [diff] [blame] | 151 | memset(&empty_leaf, 0, sizeof(empty_leaf)); |
Chris Mason | 7518a23 | 2007-03-12 12:01:18 -0400 | [diff] [blame] | 152 | btrfs_set_header_parentid(&empty_leaf.header, 1); |
| 153 | btrfs_set_header_blocknr(&empty_leaf.header, 17); |
Chris Mason | 234b63a | 2007-03-13 10:46:10 -0400 | [diff] [blame] | 154 | ret = pwrite(fd, &empty_leaf, sizeof(empty_leaf), 17 * BTRFS_BLOCKSIZE); |
Chris Mason | 06ed4b3 | 2007-02-20 16:41:09 -0500 | [diff] [blame] | 155 | if (ret != sizeof(empty_leaf)) |
| 156 | return -1; |
| 157 | |
Chris Mason | 7518a23 | 2007-03-12 12:01:18 -0400 | [diff] [blame] | 158 | btrfs_set_header_parentid(&empty_leaf.header, 2); |
| 159 | btrfs_set_header_blocknr(&empty_leaf.header, 18); |
| 160 | btrfs_set_header_nritems(&empty_leaf.header, 3); |
Chris Mason | 9a8dd15 | 2007-02-23 08:38:36 -0500 | [diff] [blame] | 161 | |
| 162 | /* item1, reserve blocks 0-16 */ |
Chris Mason | 0783fcf | 2007-03-12 20:12:07 -0400 | [diff] [blame] | 163 | btrfs_set_key_objectid(&item.key, 0); |
| 164 | btrfs_set_key_offset(&item.key, 17); |
| 165 | btrfs_set_key_flags(&item.key, 0); |
Chris Mason | 234b63a | 2007-03-13 10:46:10 -0400 | [diff] [blame] | 166 | btrfs_set_item_offset(&item, LEAF_DATA_SIZE - |
| 167 | sizeof(struct btrfs_extent_item)); |
| 168 | btrfs_set_item_size(&item, sizeof(struct btrfs_extent_item)); |
Chris Mason | cf27e1e | 2007-03-13 09:49:06 -0400 | [diff] [blame] | 169 | btrfs_set_extent_refs(&extent_item, 1); |
| 170 | btrfs_set_extent_owner(&extent_item, 0); |
Chris Mason | 06ed4b3 | 2007-02-20 16:41:09 -0500 | [diff] [blame] | 171 | memcpy(empty_leaf.items, &item, sizeof(item)); |
Chris Mason | 0783fcf | 2007-03-12 20:12:07 -0400 | [diff] [blame] | 172 | memcpy(empty_leaf.data + btrfs_item_offset(&item), &extent_item, |
| 173 | btrfs_item_size(&item)); |
Chris Mason | 9a8dd15 | 2007-02-23 08:38:36 -0500 | [diff] [blame] | 174 | |
| 175 | /* item2, give block 17 to the root */ |
Chris Mason | 0783fcf | 2007-03-12 20:12:07 -0400 | [diff] [blame] | 176 | btrfs_set_key_objectid(&item.key, 17); |
| 177 | btrfs_set_key_offset(&item.key, 1); |
Chris Mason | 234b63a | 2007-03-13 10:46:10 -0400 | [diff] [blame] | 178 | btrfs_set_item_offset(&item, LEAF_DATA_SIZE - |
| 179 | sizeof(struct btrfs_extent_item) * 2); |
Chris Mason | cf27e1e | 2007-03-13 09:49:06 -0400 | [diff] [blame] | 180 | btrfs_set_extent_owner(&extent_item, 1); |
Chris Mason | 06ed4b3 | 2007-02-20 16:41:09 -0500 | [diff] [blame] | 181 | memcpy(empty_leaf.items + 1, &item, sizeof(item)); |
Chris Mason | 0783fcf | 2007-03-12 20:12:07 -0400 | [diff] [blame] | 182 | memcpy(empty_leaf.data + btrfs_item_offset(&item), &extent_item, |
| 183 | btrfs_item_size(&item)); |
Chris Mason | 9a8dd15 | 2007-02-23 08:38:36 -0500 | [diff] [blame] | 184 | |
| 185 | /* item3, give block 18 for the extent root */ |
Chris Mason | 0783fcf | 2007-03-12 20:12:07 -0400 | [diff] [blame] | 186 | btrfs_set_key_objectid(&item.key, 18); |
| 187 | btrfs_set_key_offset(&item.key, 1); |
Chris Mason | 234b63a | 2007-03-13 10:46:10 -0400 | [diff] [blame] | 188 | btrfs_set_item_offset(&item, LEAF_DATA_SIZE - |
| 189 | sizeof(struct btrfs_extent_item) * 3); |
Chris Mason | cf27e1e | 2007-03-13 09:49:06 -0400 | [diff] [blame] | 190 | btrfs_set_extent_owner(&extent_item, 2); |
Chris Mason | 9a8dd15 | 2007-02-23 08:38:36 -0500 | [diff] [blame] | 191 | memcpy(empty_leaf.items + 2, &item, sizeof(item)); |
Chris Mason | 0783fcf | 2007-03-12 20:12:07 -0400 | [diff] [blame] | 192 | memcpy(empty_leaf.data + btrfs_item_offset(&item), &extent_item, |
| 193 | btrfs_item_size(&item)); |
Chris Mason | 234b63a | 2007-03-13 10:46:10 -0400 | [diff] [blame] | 194 | ret = pwrite(fd, &empty_leaf, sizeof(empty_leaf), 18 * BTRFS_BLOCKSIZE); |
Chris Mason | 06ed4b3 | 2007-02-20 16:41:09 -0500 | [diff] [blame] | 195 | if (ret != sizeof(empty_leaf)) |
| 196 | return -1; |
| 197 | return 0; |
| 198 | } |
Chris Mason | 3768f36 | 2007-03-13 16:47:54 -0400 | [diff] [blame] | 199 | #endif |