diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/Makefile | 3 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 129 | ||||
| -rw-r--r-- | fs/btrfs/debug-tree.c | 9 | ||||
| -rw-r--r-- | fs/btrfs/dir-test.c | 91 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 176 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 105 | ||||
| -rw-r--r-- | fs/btrfs/file-item.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/inode-map.c | 136 | ||||
| -rw-r--r-- | fs/btrfs/mkfs.c | 44 | ||||
| -rw-r--r-- | fs/btrfs/print-tree.c | 13 | ||||
| -rw-r--r-- | fs/btrfs/quick-test.c | 3 |
11 files changed, 542 insertions, 173 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index 7953b41848c1..636c63efde6f 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile | |||
| @@ -3,7 +3,8 @@ CFLAGS = -g -Wall -Werror | |||
| 3 | headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h \ | 3 | headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h \ |
| 4 | transaction.h | 4 | transaction.h |
| 5 | objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o \ | 5 | objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o \ |
| 6 | root-tree.o dir-item.o hash.o file-item.o inode-item.o | 6 | root-tree.o dir-item.o hash.o file-item.o inode-item.o \ |
| 7 | inode-map.o \ | ||
| 7 | 8 | ||
| 8 | # if you don't have sparse installed, use ls instead | 9 | # if you don't have sparse installed, use ls instead |
| 9 | CHECKFLAGS=-D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \ | 10 | CHECKFLAGS=-D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \ |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 68f0af39777f..68e3da274f17 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -10,7 +10,8 @@ struct btrfs_trans_handle; | |||
| 10 | 10 | ||
| 11 | #define BTRFS_ROOT_TREE_OBJECTID 1 | 11 | #define BTRFS_ROOT_TREE_OBJECTID 1 |
| 12 | #define BTRFS_EXTENT_TREE_OBJECTID 2 | 12 | #define BTRFS_EXTENT_TREE_OBJECTID 2 |
| 13 | #define BTRFS_FS_TREE_OBJECTID 3 | 13 | #define BTRFS_INODE_MAP_OBJECTID 3 |
| 14 | #define BTRFS_FS_TREE_OBJECTID 4 | ||
| 14 | 15 | ||
| 15 | /* | 16 | /* |
| 16 | * the key defines the order in the tree, and so it also defines (optimal) | 17 | * the key defines the order in the tree, and so it also defines (optimal) |
| @@ -178,31 +179,65 @@ struct btrfs_root_item { | |||
| 178 | __le64 block_limit; | 179 | __le64 block_limit; |
| 179 | __le64 blocks_used; | 180 | __le64 blocks_used; |
| 180 | __le32 refs; | 181 | __le32 refs; |
| 181 | }; | 182 | } __attribute__ ((__packed__)); |
| 182 | 183 | ||
| 183 | /* | 184 | struct btrfs_file_extent_item { |
| 184 | * in ram representation of the tree. extent_root is used for all allocations | 185 | /* |
| 185 | * and for the extent tree extent_root root. current_insert is used | 186 | * disk space consumed by the extent, checksum blocks are included |
| 186 | * only for the extent tree. | 187 | * in these numbers |
| 187 | */ | 188 | */ |
| 188 | struct btrfs_root { | 189 | __le64 disk_blocknr; |
| 189 | struct btrfs_buffer *node; | 190 | __le64 disk_num_blocks; |
| 190 | struct btrfs_buffer *commit_root; | 191 | /* |
| 192 | * the logical offset in file bytes (no csums) | ||
| 193 | * this extent record is for. This allows a file extent to point | ||
| 194 | * into the middle of an existing extent on disk, sharing it | ||
| 195 | * between two snapshots (useful if some bytes in the middle of the | ||
| 196 | * extent have changed | ||
| 197 | */ | ||
| 198 | __le64 offset; | ||
| 199 | /* | ||
| 200 | * the logical number of file blocks (no csums included) | ||
| 201 | */ | ||
| 202 | __le64 num_blocks; | ||
| 203 | } __attribute__ ((__packed__)); | ||
| 204 | |||
| 205 | struct btrfs_inode_map_item { | ||
| 206 | struct btrfs_disk_key key; | ||
| 207 | } __attribute__ ((__packed__)); | ||
| 208 | |||
| 209 | struct btrfs_fs_info { | ||
| 210 | struct btrfs_root *fs_root; | ||
| 191 | struct btrfs_root *extent_root; | 211 | struct btrfs_root *extent_root; |
| 192 | struct btrfs_root *tree_root; | 212 | struct btrfs_root *tree_root; |
| 213 | struct btrfs_root *inode_root; | ||
| 193 | struct btrfs_key current_insert; | 214 | struct btrfs_key current_insert; |
| 194 | struct btrfs_key last_insert; | 215 | struct btrfs_key last_insert; |
| 195 | int fp; | ||
| 196 | struct radix_tree_root cache_radix; | 216 | struct radix_tree_root cache_radix; |
| 197 | struct radix_tree_root pinned_radix; | 217 | struct radix_tree_root pinned_radix; |
| 198 | struct list_head trans; | 218 | struct list_head trans; |
| 199 | struct list_head cache; | 219 | struct list_head cache; |
| 220 | u64 last_inode_alloc; | ||
| 221 | u64 last_inode_alloc_dirid; | ||
| 200 | int cache_size; | 222 | int cache_size; |
| 201 | int ref_cows; | 223 | int fp; |
| 224 | struct btrfs_trans_handle *running_transaction; | ||
| 225 | }; | ||
| 226 | |||
| 227 | /* | ||
| 228 | * in ram representation of the tree. extent_root is used for all allocations | ||
| 229 | * and for the extent tree extent_root root. current_insert is used | ||
| 230 | * only for the extent tree. | ||
| 231 | */ | ||
| 232 | struct btrfs_root { | ||
| 233 | struct btrfs_buffer *node; | ||
| 234 | struct btrfs_buffer *commit_root; | ||
| 202 | struct btrfs_root_item root_item; | 235 | struct btrfs_root_item root_item; |
| 203 | struct btrfs_key root_key; | 236 | struct btrfs_key root_key; |
| 237 | struct btrfs_fs_info *fs_info; | ||
| 204 | u32 blocksize; | 238 | u32 blocksize; |
| 205 | struct btrfs_trans_handle *running_transaction; | 239 | int ref_cows; |
| 240 | u32 type; | ||
| 206 | }; | 241 | }; |
| 207 | 242 | ||
| 208 | /* the lower bits in the key flags defines the item type */ | 243 | /* the lower bits in the key flags defines the item type */ |
| @@ -240,11 +275,17 @@ struct btrfs_root { | |||
| 240 | * are used, and how many references there are to each block | 275 | * are used, and how many references there are to each block |
| 241 | */ | 276 | */ |
| 242 | #define BTRFS_EXTENT_ITEM_KEY 6 | 277 | #define BTRFS_EXTENT_ITEM_KEY 6 |
| 278 | |||
| 279 | /* | ||
| 280 | * the inode map records which inode numbers are in use and where | ||
| 281 | * they actually live on disk | ||
| 282 | */ | ||
| 283 | #define BTRFS_INODE_MAP_ITEM_KEY 7 | ||
| 243 | /* | 284 | /* |
| 244 | * string items are for debugging. They just store a short string of | 285 | * string items are for debugging. They just store a short string of |
| 245 | * data in the FS | 286 | * data in the FS |
| 246 | */ | 287 | */ |
| 247 | #define BTRFS_STRING_ITEM_KEY 7 | 288 | #define BTRFS_STRING_ITEM_KEY 8 |
| 248 | 289 | ||
| 249 | static inline u64 btrfs_inode_generation(struct btrfs_inode_item *i) | 290 | static inline u64 btrfs_inode_generation(struct btrfs_inode_item *i) |
| 250 | { | 291 | { |
| @@ -654,6 +695,57 @@ static inline u8 *btrfs_leaf_data(struct btrfs_leaf *l) | |||
| 654 | { | 695 | { |
| 655 | return (u8 *)l->items; | 696 | return (u8 *)l->items; |
| 656 | } | 697 | } |
| 698 | |||
| 699 | static inline u64 btrfs_file_extent_disk_blocknr(struct btrfs_file_extent_item | ||
| 700 | *e) | ||
| 701 | { | ||
| 702 | return le64_to_cpu(e->disk_blocknr); | ||
| 703 | } | ||
| 704 | |||
| 705 | static inline void btrfs_set_file_extent_disk_blocknr(struct | ||
| 706 | btrfs_file_extent_item | ||
| 707 | *e, u64 val) | ||
| 708 | { | ||
| 709 | e->disk_blocknr = cpu_to_le64(val); | ||
| 710 | } | ||
| 711 | |||
| 712 | static inline u64 btrfs_file_extent_disk_num_blocks(struct | ||
| 713 | btrfs_file_extent_item *e) | ||
| 714 | { | ||
| 715 | return le64_to_cpu(e->disk_num_blocks); | ||
| 716 | } | ||
| 717 | |||
| 718 | static inline void btrfs_set_file_extent_disk_num_blocks(struct | ||
| 719 | btrfs_file_extent_item | ||
| 720 | *e, u64 val) | ||
| 721 | { | ||
| 722 | e->disk_num_blocks = cpu_to_le64(val); | ||
| 723 | } | ||
| 724 | |||
| 725 | static inline u64 btrfs_file_extent_offset(struct btrfs_file_extent_item *e) | ||
| 726 | { | ||
| 727 | return le64_to_cpu(e->offset); | ||
| 728 | } | ||
| 729 | |||
| 730 | static inline void btrfs_set_file_extent_offset(struct btrfs_file_extent_item | ||
| 731 | *e, u64 val) | ||
| 732 | { | ||
| 733 | e->offset = cpu_to_le64(val); | ||
| 734 | } | ||
| 735 | |||
| 736 | static inline u64 btrfs_file_extent_num_blocks(struct btrfs_file_extent_item | ||
| 737 | *e) | ||
| 738 | { | ||
| 739 | return le64_to_cpu(e->num_blocks); | ||
| 740 | } | ||
| 741 | |||
| 742 | static inline void btrfs_set_file_extent_num_blocks(struct | ||
| 743 | btrfs_file_extent_item *e, | ||
| 744 | u64 val) | ||
| 745 | { | ||
| 746 | e->num_blocks = cpu_to_le64(val); | ||
| 747 | } | ||
| 748 | |||
| 657 | /* helper function to cast into the data area of the leaf. */ | 749 | /* helper function to cast into the data area of the leaf. */ |
| 658 | #define btrfs_item_ptr(leaf, slot, type) \ | 750 | #define btrfs_item_ptr(leaf, slot, type) \ |
| 659 | ((type *)(btrfs_leaf_data(leaf) + \ | 751 | ((type *)(btrfs_leaf_data(leaf) + \ |
| @@ -701,4 +793,13 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 701 | int name_len, int mod); | 793 | int name_len, int mod); |
| 702 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, | 794 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, |
| 703 | char *name, int name_len); | 795 | char *name, int name_len); |
| 796 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | ||
| 797 | struct btrfs_root *fs_root, | ||
| 798 | u64 dirid, u64 *objectid); | ||
| 799 | int btrfs_insert_inode_map(struct btrfs_trans_handle *trans, | ||
| 800 | struct btrfs_root *root, | ||
| 801 | u64 objectid, struct btrfs_key *location); | ||
| 802 | int btrfs_lookup_inode_map(struct btrfs_trans_handle *trans, | ||
| 803 | struct btrfs_root *root, struct btrfs_path *path, | ||
| 804 | u64 objectid, int mod); | ||
| 704 | #endif | 805 | #endif |
diff --git a/fs/btrfs/debug-tree.c b/fs/btrfs/debug-tree.c index 91dea7a0a476..d9f36efc3dd1 100644 --- a/fs/btrfs/debug-tree.c +++ b/fs/btrfs/debug-tree.c | |||
| @@ -15,8 +15,13 @@ int main(int ac, char **av) { | |||
| 15 | printf("fs tree\n"); | 15 | printf("fs tree\n"); |
| 16 | btrfs_print_tree(root, root->node); | 16 | btrfs_print_tree(root, root->node); |
| 17 | printf("map tree\n"); | 17 | printf("map tree\n"); |
| 18 | btrfs_print_tree(root->extent_root, root->extent_root->node); | 18 | btrfs_print_tree(root->fs_info->extent_root, |
| 19 | root->fs_info->extent_root->node); | ||
| 20 | printf("inode tree\n"); | ||
| 21 | btrfs_print_tree(root->fs_info->inode_root, | ||
| 22 | root->fs_info->inode_root->node); | ||
| 19 | printf("root tree\n"); | 23 | printf("root tree\n"); |
| 20 | btrfs_print_tree(root->tree_root, root->tree_root->node); | 24 | btrfs_print_tree(root->fs_info->tree_root, |
| 25 | root->fs_info->tree_root->node); | ||
| 21 | return 0; | 26 | return 0; |
| 22 | } | 27 | } |
diff --git a/fs/btrfs/dir-test.c b/fs/btrfs/dir-test.c index e908c0c588cc..56f06c3ba573 100644 --- a/fs/btrfs/dir-test.c +++ b/fs/btrfs/dir-test.c | |||
| @@ -45,13 +45,26 @@ static int ins_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 45 | int ret; | 45 | int ret; |
| 46 | char buf[128]; | 46 | char buf[128]; |
| 47 | unsigned long oid; | 47 | unsigned long oid; |
| 48 | u64 objectid; | ||
| 48 | struct btrfs_path path; | 49 | struct btrfs_path path; |
| 50 | struct btrfs_key inode_map; | ||
| 49 | 51 | ||
| 50 | find_num(radix, &oid, 0); | 52 | find_num(radix, &oid, 0); |
| 51 | sprintf(buf, "str-%lu", oid); | 53 | sprintf(buf, "str-%lu", oid); |
| 52 | 54 | ||
| 55 | ret = btrfs_find_free_objectid(trans, root, dir_oid + 1, &objectid); | ||
| 56 | if (ret) | ||
| 57 | goto error; | ||
| 58 | |||
| 59 | inode_map.objectid = objectid; | ||
| 60 | inode_map.flags = 0; | ||
| 61 | inode_map.offset = 0; | ||
| 62 | |||
| 63 | ret = btrfs_insert_inode_map(trans, root, objectid, &inode_map); | ||
| 64 | if (ret) | ||
| 65 | goto error; | ||
| 53 | ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf), dir_oid, | 66 | ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf), dir_oid, |
| 54 | file_oid, 1); | 67 | objectid, 1); |
| 55 | if (ret) | 68 | if (ret) |
| 56 | goto error; | 69 | goto error; |
| 57 | 70 | ||
| @@ -120,6 +133,53 @@ static int insert_dup(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 120 | return 0; | 133 | return 0; |
| 121 | } | 134 | } |
| 122 | 135 | ||
| 136 | static int del_dir_item(struct btrfs_trans_handle *trans, | ||
| 137 | struct btrfs_root *root, | ||
| 138 | struct radix_tree_root *radix, | ||
| 139 | unsigned long radix_index, | ||
| 140 | struct btrfs_path *path) | ||
| 141 | { | ||
| 142 | int ret; | ||
| 143 | unsigned long *ptr; | ||
| 144 | u64 file_objectid; | ||
| 145 | struct btrfs_dir_item *di; | ||
| 146 | struct btrfs_path map_path; | ||
| 147 | |||
| 148 | /* find the inode number of the file */ | ||
| 149 | di = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0], | ||
| 150 | struct btrfs_dir_item); | ||
| 151 | file_objectid = btrfs_dir_objectid(di); | ||
| 152 | |||
| 153 | /* delete the directory item */ | ||
| 154 | ret = btrfs_del_item(trans, root, path); | ||
| 155 | if (ret) | ||
| 156 | goto out; | ||
| 157 | |||
| 158 | /* delete the inode mapping */ | ||
| 159 | btrfs_init_path(&map_path); | ||
| 160 | ret = btrfs_lookup_inode_map(trans, root, &map_path, file_objectid, -1); | ||
| 161 | if (ret) | ||
| 162 | goto out_release; | ||
| 163 | ret = btrfs_del_item(trans, root->fs_info->inode_root, &map_path); | ||
| 164 | if (ret) | ||
| 165 | goto out_release; | ||
| 166 | |||
| 167 | if (root->fs_info->last_inode_alloc > file_objectid) | ||
| 168 | root->fs_info->last_inode_alloc = file_objectid; | ||
| 169 | btrfs_release_path(root, &map_path); | ||
| 170 | ptr = radix_tree_delete(radix, radix_index); | ||
| 171 | if (!ptr) { | ||
| 172 | ret = -5555; | ||
| 173 | goto out; | ||
| 174 | } | ||
| 175 | return 0; | ||
| 176 | out_release: | ||
| 177 | btrfs_release_path(root, &map_path); | ||
| 178 | out: | ||
| 179 | printf("failed to delete %lu %d\n", radix_index, ret); | ||
| 180 | return -1; | ||
| 181 | } | ||
| 182 | |||
| 123 | static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 183 | static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 124 | struct radix_tree_root *radix) | 184 | struct radix_tree_root *radix) |
| 125 | { | 185 | { |
| @@ -127,7 +187,6 @@ static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 127 | char buf[128]; | 187 | char buf[128]; |
| 128 | unsigned long oid; | 188 | unsigned long oid; |
| 129 | struct btrfs_path path; | 189 | struct btrfs_path path; |
| 130 | unsigned long *ptr; | ||
| 131 | 190 | ||
| 132 | ret = find_num(radix, &oid, 1); | 191 | ret = find_num(radix, &oid, 1); |
| 133 | if (ret < 0) | 192 | if (ret < 0) |
| @@ -138,19 +197,14 @@ static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 138 | strlen(buf), -1); | 197 | strlen(buf), -1); |
| 139 | if (ret) | 198 | if (ret) |
| 140 | goto out_release; | 199 | goto out_release; |
| 141 | ret = btrfs_del_item(trans, root, &path); | 200 | |
| 201 | ret = del_dir_item(trans, root, radix, oid, &path); | ||
| 142 | if (ret) | 202 | if (ret) |
| 143 | goto out_release; | 203 | goto out_release; |
| 144 | btrfs_release_path(root, &path); | 204 | btrfs_release_path(root, &path); |
| 145 | ptr = radix_tree_delete(radix, oid); | 205 | return ret; |
| 146 | if (!ptr) { | ||
| 147 | ret = -5555; | ||
| 148 | goto out; | ||
| 149 | } | ||
| 150 | return 0; | ||
| 151 | out_release: | 206 | out_release: |
| 152 | btrfs_release_path(root, &path); | 207 | btrfs_release_path(root, &path); |
| 153 | out: | ||
| 154 | printf("failed to delete %lu %d\n", oid, ret); | 208 | printf("failed to delete %lu %d\n", oid, ret); |
| 155 | return -1; | 209 | return -1; |
| 156 | } | 210 | } |
| @@ -162,6 +216,8 @@ static int lookup_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 162 | char buf[128]; | 216 | char buf[128]; |
| 163 | int ret; | 217 | int ret; |
| 164 | unsigned long oid; | 218 | unsigned long oid; |
| 219 | u64 objectid; | ||
| 220 | struct btrfs_dir_item *di; | ||
| 165 | 221 | ||
| 166 | ret = find_num(radix, &oid, 1); | 222 | ret = find_num(radix, &oid, 1); |
| 167 | if (ret < 0) | 223 | if (ret < 0) |
| @@ -170,6 +226,14 @@ static int lookup_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 170 | btrfs_init_path(&path); | 226 | btrfs_init_path(&path); |
| 171 | ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf, | 227 | ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf, |
| 172 | strlen(buf), 0); | 228 | strlen(buf), 0); |
| 229 | if (!ret) { | ||
| 230 | di = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], | ||
| 231 | struct btrfs_dir_item); | ||
| 232 | objectid = btrfs_dir_objectid(di); | ||
| 233 | btrfs_release_path(root, &path); | ||
| 234 | btrfs_init_path(&path); | ||
| 235 | ret = btrfs_lookup_inode_map(trans, root, &path, objectid, 0); | ||
| 236 | } | ||
| 173 | btrfs_release_path(root, &path); | 237 | btrfs_release_path(root, &path); |
| 174 | if (ret) { | 238 | if (ret) { |
| 175 | printf("unable to find key %lu\n", oid); | 239 | printf("unable to find key %lu\n", oid); |
| @@ -210,7 +274,6 @@ static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 210 | u32 found_len; | 274 | u32 found_len; |
| 211 | int ret; | 275 | int ret; |
| 212 | int slot; | 276 | int slot; |
| 213 | int *ptr; | ||
| 214 | int count = 0; | 277 | int count = 0; |
| 215 | char buf[128]; | 278 | char buf[128]; |
| 216 | struct btrfs_dir_item *di; | 279 | struct btrfs_dir_item *di; |
| @@ -241,7 +304,7 @@ static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 241 | BUG_ON(found_len > 128); | 304 | BUG_ON(found_len > 128); |
| 242 | buf[found_len] = '\0'; | 305 | buf[found_len] = '\0'; |
| 243 | found = atoi(buf + 4); | 306 | found = atoi(buf + 4); |
| 244 | ret = btrfs_del_item(trans, root, &path); | 307 | ret = del_dir_item(trans, root, radix, found, &path); |
| 245 | count++; | 308 | count++; |
| 246 | if (ret) { | 309 | if (ret) { |
| 247 | fprintf(stderr, | 310 | fprintf(stderr, |
| @@ -250,14 +313,10 @@ static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 250 | return -1; | 313 | return -1; |
| 251 | } | 314 | } |
| 252 | btrfs_release_path(root, &path); | 315 | btrfs_release_path(root, &path); |
| 253 | ptr = radix_tree_delete(radix, found); | ||
| 254 | if (!ptr) | ||
| 255 | goto error; | ||
| 256 | if (!keep_running) | 316 | if (!keep_running) |
| 257 | break; | 317 | break; |
| 258 | } | 318 | } |
| 259 | return 0; | 319 | return 0; |
| 260 | error: | ||
| 261 | fprintf(stderr, "failed to delete from the radix %lu\n", found); | 320 | fprintf(stderr, "failed to delete from the radix %lu\n", found); |
| 262 | return -1; | 321 | return -1; |
| 263 | } | 322 | } |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 25ce07908ee3..1849a99690c8 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -28,15 +28,15 @@ static int free_some_buffers(struct btrfs_root *root) | |||
| 28 | { | 28 | { |
| 29 | struct list_head *node, *next; | 29 | struct list_head *node, *next; |
| 30 | struct btrfs_buffer *b; | 30 | struct btrfs_buffer *b; |
| 31 | if (root->cache_size < cache_max) | 31 | if (root->fs_info->cache_size < cache_max) |
| 32 | return 0; | 32 | return 0; |
| 33 | list_for_each_safe(node, next, &root->cache) { | 33 | list_for_each_safe(node, next, &root->fs_info->cache) { |
| 34 | b = list_entry(node, struct btrfs_buffer, cache); | 34 | b = list_entry(node, struct btrfs_buffer, cache); |
| 35 | if (b->count == 1) { | 35 | if (b->count == 1) { |
| 36 | BUG_ON(!list_empty(&b->dirty)); | 36 | BUG_ON(!list_empty(&b->dirty)); |
| 37 | list_del_init(&b->cache); | 37 | list_del_init(&b->cache); |
| 38 | btrfs_block_release(root, b); | 38 | btrfs_block_release(root, b); |
| 39 | if (root->cache_size < cache_max) | 39 | if (root->fs_info->cache_size < cache_max) |
| 40 | break; | 40 | break; |
| 41 | } | 41 | } |
| 42 | } | 42 | } |
| @@ -57,10 +57,10 @@ struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr) | |||
| 57 | INIT_LIST_HEAD(&buf->dirty); | 57 | INIT_LIST_HEAD(&buf->dirty); |
| 58 | free_some_buffers(root); | 58 | free_some_buffers(root); |
| 59 | radix_tree_preload(GFP_KERNEL); | 59 | radix_tree_preload(GFP_KERNEL); |
| 60 | ret = radix_tree_insert(&root->cache_radix, blocknr, buf); | 60 | ret = radix_tree_insert(&root->fs_info->cache_radix, blocknr, buf); |
| 61 | radix_tree_preload_end(); | 61 | radix_tree_preload_end(); |
| 62 | list_add_tail(&buf->cache, &root->cache); | 62 | list_add_tail(&buf->cache, &root->fs_info->cache); |
| 63 | root->cache_size++; | 63 | root->fs_info->cache_size++; |
| 64 | if (ret) { | 64 | if (ret) { |
| 65 | free(buf); | 65 | free(buf); |
| 66 | return NULL; | 66 | return NULL; |
| @@ -71,7 +71,7 @@ struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr) | |||
| 71 | struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr) | 71 | struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr) |
| 72 | { | 72 | { |
| 73 | struct btrfs_buffer *buf; | 73 | struct btrfs_buffer *buf; |
| 74 | buf = radix_tree_lookup(&root->cache_radix, blocknr); | 74 | buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr); |
| 75 | if (buf) { | 75 | if (buf) { |
| 76 | buf->count++; | 76 | buf->count++; |
| 77 | } else { | 77 | } else { |
| @@ -90,14 +90,15 @@ struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr) | |||
| 90 | struct btrfs_buffer *buf; | 90 | struct btrfs_buffer *buf; |
| 91 | int ret; | 91 | int ret; |
| 92 | 92 | ||
| 93 | buf = radix_tree_lookup(&root->cache_radix, blocknr); | 93 | buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr); |
| 94 | if (buf) { | 94 | if (buf) { |
| 95 | buf->count++; | 95 | buf->count++; |
| 96 | } else { | 96 | } else { |
| 97 | buf = alloc_tree_block(root, blocknr); | 97 | buf = alloc_tree_block(root, blocknr); |
| 98 | if (!buf) | 98 | if (!buf) |
| 99 | return NULL; | 99 | return NULL; |
| 100 | ret = pread(root->fp, &buf->node, root->blocksize, offset); | 100 | ret = pread(root->fs_info->fp, &buf->node, root->blocksize, |
| 101 | offset); | ||
| 101 | if (ret != root->blocksize) { | 102 | if (ret != root->blocksize) { |
| 102 | free(buf); | 103 | free(buf); |
| 103 | return NULL; | 104 | return NULL; |
| @@ -113,7 +114,7 @@ int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 113 | { | 114 | { |
| 114 | if (!list_empty(&buf->dirty)) | 115 | if (!list_empty(&buf->dirty)) |
| 115 | return 0; | 116 | return 0; |
| 116 | list_add_tail(&buf->dirty, &root->trans); | 117 | list_add_tail(&buf->dirty, &root->fs_info->trans); |
| 117 | buf->count++; | 118 | buf->count++; |
| 118 | return 0; | 119 | return 0; |
| 119 | } | 120 | } |
| @@ -137,7 +138,7 @@ int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 137 | 138 | ||
| 138 | if (buf->blocknr != btrfs_header_blocknr(&buf->node.header)) | 139 | if (buf->blocknr != btrfs_header_blocknr(&buf->node.header)) |
| 139 | BUG(); | 140 | BUG(); |
| 140 | ret = pwrite(root->fp, &buf->node, root->blocksize, offset); | 141 | ret = pwrite(root->fs_info->fp, &buf->node, root->blocksize, offset); |
| 141 | if (ret != root->blocksize) | 142 | if (ret != root->blocksize) |
| 142 | return ret; | 143 | return ret; |
| 143 | return 0; | 144 | return 0; |
| @@ -149,8 +150,9 @@ static int __commit_transaction(struct btrfs_trans_handle *trans, struct | |||
| 149 | struct btrfs_buffer *b; | 150 | struct btrfs_buffer *b; |
| 150 | int ret = 0; | 151 | int ret = 0; |
| 151 | int wret; | 152 | int wret; |
| 152 | while(!list_empty(&root->trans)) { | 153 | while(!list_empty(&root->fs_info->trans)) { |
| 153 | b = list_entry(root->trans.next, struct btrfs_buffer, dirty); | 154 | b = list_entry(root->fs_info->trans.next, struct btrfs_buffer, |
| 155 | dirty); | ||
| 154 | list_del_init(&b->dirty); | 156 | list_del_init(&b->dirty); |
| 155 | wret = write_tree_block(trans, root, b); | 157 | wret = write_tree_block(trans, root, b); |
| 156 | if (wret) | 158 | if (wret) |
| @@ -160,13 +162,21 @@ static int __commit_transaction(struct btrfs_trans_handle *trans, struct | |||
| 160 | return ret; | 162 | return ret; |
| 161 | } | 163 | } |
| 162 | 164 | ||
| 163 | static int commit_extent_and_tree_roots(struct btrfs_trans_handle *trans, | 165 | static int commit_tree_roots(struct btrfs_trans_handle *trans, |
| 164 | struct btrfs_root *tree_root, struct | 166 | struct btrfs_fs_info *fs_info) |
| 165 | btrfs_root *extent_root) | ||
| 166 | { | 167 | { |
| 167 | int ret; | 168 | int ret; |
| 168 | u64 old_extent_block; | 169 | u64 old_extent_block; |
| 169 | 170 | struct btrfs_root *tree_root = fs_info->tree_root; | |
| 171 | struct btrfs_root *extent_root = fs_info->extent_root; | ||
| 172 | struct btrfs_root *inode_root = fs_info->inode_root; | ||
| 173 | |||
| 174 | btrfs_set_root_blocknr(&inode_root->root_item, | ||
| 175 | inode_root->node->blocknr); | ||
| 176 | ret = btrfs_update_root(trans, tree_root, | ||
| 177 | &inode_root->root_key, | ||
| 178 | &inode_root->root_item); | ||
| 179 | BUG_ON(ret); | ||
| 170 | while(1) { | 180 | while(1) { |
| 171 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); | 181 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); |
| 172 | if (old_extent_block == extent_root->node->blocknr) | 182 | if (old_extent_block == extent_root->node->blocknr) |
| @@ -178,8 +188,6 @@ static int commit_extent_and_tree_roots(struct btrfs_trans_handle *trans, | |||
| 178 | &extent_root->root_item); | 188 | &extent_root->root_item); |
| 179 | BUG_ON(ret); | 189 | BUG_ON(ret); |
| 180 | } | 190 | } |
| 181 | __commit_transaction(trans, extent_root); | ||
| 182 | __commit_transaction(trans, tree_root); | ||
| 183 | return 0; | 191 | return 0; |
| 184 | } | 192 | } |
| 185 | 193 | ||
| @@ -190,9 +198,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct | |||
| 190 | struct btrfs_buffer *snap = root->commit_root; | 198 | struct btrfs_buffer *snap = root->commit_root; |
| 191 | struct btrfs_key snap_key; | 199 | struct btrfs_key snap_key; |
| 192 | 200 | ||
| 193 | ret = __commit_transaction(trans, root); | ||
| 194 | BUG_ON(ret); | ||
| 195 | |||
| 196 | if (root->commit_root == root->node) | 201 | if (root->commit_root == root->node) |
| 197 | return 0; | 202 | return 0; |
| 198 | 203 | ||
| @@ -200,54 +205,55 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct | |||
| 200 | root->root_key.offset++; | 205 | root->root_key.offset++; |
| 201 | 206 | ||
| 202 | btrfs_set_root_blocknr(&root->root_item, root->node->blocknr); | 207 | btrfs_set_root_blocknr(&root->root_item, root->node->blocknr); |
| 203 | ret = btrfs_insert_root(trans, root->tree_root, &root->root_key, | 208 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, |
| 204 | &root->root_item); | 209 | &root->root_key, &root->root_item); |
| 210 | BUG_ON(ret); | ||
| 211 | |||
| 212 | ret = commit_tree_roots(trans, root->fs_info); | ||
| 205 | BUG_ON(ret); | 213 | BUG_ON(ret); |
| 206 | 214 | ||
| 207 | ret = commit_extent_and_tree_roots(trans, root->tree_root, | 215 | ret = __commit_transaction(trans, root); |
| 208 | root->extent_root); | ||
| 209 | BUG_ON(ret); | 216 | BUG_ON(ret); |
| 210 | 217 | ||
| 211 | write_ctree_super(trans, root, s); | 218 | write_ctree_super(trans, root, s); |
| 212 | btrfs_finish_extent_commit(trans, root->extent_root); | 219 | btrfs_finish_extent_commit(trans, root->fs_info->extent_root); |
| 213 | btrfs_finish_extent_commit(trans, root->tree_root); | 220 | btrfs_finish_extent_commit(trans, root->fs_info->tree_root); |
| 214 | 221 | ||
| 215 | root->commit_root = root->node; | 222 | root->commit_root = root->node; |
| 216 | root->node->count++; | 223 | root->node->count++; |
| 217 | ret = btrfs_drop_snapshot(trans, root, snap); | 224 | ret = btrfs_drop_snapshot(trans, root, snap); |
| 218 | BUG_ON(ret); | 225 | BUG_ON(ret); |
| 219 | 226 | ||
| 220 | ret = btrfs_del_root(trans, root->tree_root, &snap_key); | 227 | ret = btrfs_del_root(trans, root->fs_info->tree_root, &snap_key); |
| 221 | BUG_ON(ret); | 228 | BUG_ON(ret); |
| 222 | 229 | ||
| 223 | return ret; | 230 | return ret; |
| 224 | } | 231 | } |
| 225 | 232 | ||
| 226 | static int __setup_root(struct btrfs_super_block *super, | 233 | static int __setup_root(struct btrfs_super_block *super, |
| 227 | struct btrfs_root *root, u64 objectid, int fp) | 234 | struct btrfs_root *root, |
| 235 | struct btrfs_fs_info *fs_info, | ||
| 236 | u64 objectid, int fp) | ||
| 228 | { | 237 | { |
| 229 | INIT_LIST_HEAD(&root->trans); | ||
| 230 | INIT_LIST_HEAD(&root->cache); | ||
| 231 | root->cache_size = 0; | ||
| 232 | root->fp = fp; | ||
| 233 | root->node = NULL; | 238 | root->node = NULL; |
| 234 | root->commit_root = NULL; | 239 | root->commit_root = NULL; |
| 235 | root->blocksize = btrfs_super_blocksize(super); | 240 | root->blocksize = btrfs_super_blocksize(super); |
| 236 | root->ref_cows = 0; | 241 | root->ref_cows = 0; |
| 237 | memset(&root->current_insert, 0, sizeof(root->current_insert)); | 242 | root->fs_info = fs_info; |
| 238 | memset(&root->last_insert, 0, sizeof(root->last_insert)); | ||
| 239 | memset(&root->root_key, 0, sizeof(root->root_key)); | 243 | memset(&root->root_key, 0, sizeof(root->root_key)); |
| 240 | memset(&root->root_item, 0, sizeof(root->root_item)); | 244 | memset(&root->root_item, 0, sizeof(root->root_item)); |
| 241 | return 0; | 245 | return 0; |
| 242 | } | 246 | } |
| 243 | 247 | ||
| 244 | static int find_and_setup_root(struct btrfs_super_block *super, | 248 | static int find_and_setup_root(struct btrfs_super_block *super, |
| 245 | struct btrfs_root *tree_root, u64 objectid, | 249 | struct btrfs_root *tree_root, |
| 250 | struct btrfs_fs_info *fs_info, | ||
| 251 | u64 objectid, | ||
| 246 | struct btrfs_root *root, int fp) | 252 | struct btrfs_root *root, int fp) |
| 247 | { | 253 | { |
| 248 | int ret; | 254 | int ret; |
| 249 | 255 | ||
| 250 | __setup_root(super, root, objectid, fp); | 256 | __setup_root(super, root, fs_info, objectid, fp); |
| 251 | ret = btrfs_find_last_root(tree_root, objectid, | 257 | ret = btrfs_find_last_root(tree_root, objectid, |
| 252 | &root->root_item, &root->root_key); | 258 | &root->root_item, &root->root_key); |
| 253 | BUG_ON(ret); | 259 | BUG_ON(ret); |
| @@ -263,29 +269,31 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) | |||
| 263 | struct btrfs_root *root = malloc(sizeof(struct btrfs_root)); | 269 | struct btrfs_root *root = malloc(sizeof(struct btrfs_root)); |
| 264 | struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root)); | 270 | struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root)); |
| 265 | struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root)); | 271 | struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root)); |
| 272 | struct btrfs_root *inode_root = malloc(sizeof(struct btrfs_root)); | ||
| 273 | struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info)); | ||
| 266 | int fp; | 274 | int fp; |
| 267 | int ret; | 275 | int ret; |
| 268 | 276 | ||
| 269 | root->extent_root = extent_root; | ||
| 270 | root->tree_root = tree_root; | ||
| 271 | |||
| 272 | extent_root->extent_root = extent_root; | ||
| 273 | extent_root->tree_root = tree_root; | ||
| 274 | |||
| 275 | tree_root->extent_root = extent_root; | ||
| 276 | tree_root->tree_root = tree_root; | ||
| 277 | |||
| 278 | fp = open(filename, O_CREAT | O_RDWR, 0600); | 277 | fp = open(filename, O_CREAT | O_RDWR, 0600); |
| 279 | if (fp < 0) { | 278 | if (fp < 0) { |
| 280 | free(root); | 279 | free(root); |
| 281 | return NULL; | 280 | return NULL; |
| 282 | } | 281 | } |
| 283 | INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); | 282 | INIT_RADIX_TREE(&fs_info->cache_radix, GFP_KERNEL); |
| 284 | INIT_RADIX_TREE(&root->pinned_radix, GFP_KERNEL); | 283 | INIT_RADIX_TREE(&fs_info->pinned_radix, GFP_KERNEL); |
| 285 | INIT_RADIX_TREE(&extent_root->pinned_radix, GFP_KERNEL); | 284 | INIT_LIST_HEAD(&fs_info->trans); |
| 286 | INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL); | 285 | INIT_LIST_HEAD(&fs_info->cache); |
| 287 | INIT_RADIX_TREE(&tree_root->pinned_radix, GFP_KERNEL); | 286 | fs_info->cache_size = 0; |
| 288 | INIT_RADIX_TREE(&tree_root->cache_radix, GFP_KERNEL); | 287 | fs_info->fp = fp; |
| 288 | fs_info->running_transaction = NULL; | ||
| 289 | fs_info->fs_root = root; | ||
| 290 | fs_info->tree_root = tree_root; | ||
| 291 | fs_info->extent_root = extent_root; | ||
| 292 | fs_info->inode_root = inode_root; | ||
| 293 | fs_info->last_inode_alloc = 0; | ||
| 294 | fs_info->last_inode_alloc_dirid = 0; | ||
| 295 | memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert)); | ||
| 296 | memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); | ||
| 289 | 297 | ||
| 290 | ret = pread(fp, super, sizeof(struct btrfs_super_block), | 298 | ret = pread(fp, super, sizeof(struct btrfs_super_block), |
| 291 | BTRFS_SUPER_INFO_OFFSET); | 299 | BTRFS_SUPER_INFO_OFFSET); |
| @@ -301,16 +309,20 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) | |||
| 301 | } | 309 | } |
| 302 | BUG_ON(ret < 0); | 310 | BUG_ON(ret < 0); |
| 303 | 311 | ||
| 304 | __setup_root(super, tree_root, BTRFS_ROOT_TREE_OBJECTID, fp); | 312 | __setup_root(super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID, fp); |
| 305 | tree_root->node = read_tree_block(tree_root, btrfs_super_root(super)); | 313 | tree_root->node = read_tree_block(tree_root, btrfs_super_root(super)); |
| 306 | BUG_ON(!tree_root->node); | 314 | BUG_ON(!tree_root->node); |
| 307 | 315 | ||
| 308 | ret = find_and_setup_root(super, tree_root, BTRFS_EXTENT_TREE_OBJECTID, | 316 | ret = find_and_setup_root(super, tree_root, fs_info, |
| 309 | extent_root, fp); | 317 | BTRFS_EXTENT_TREE_OBJECTID, extent_root, fp); |
| 310 | BUG_ON(ret); | 318 | BUG_ON(ret); |
| 311 | 319 | ||
| 312 | ret = find_and_setup_root(super, tree_root, BTRFS_FS_TREE_OBJECTID, | 320 | ret = find_and_setup_root(super, tree_root, fs_info, |
| 313 | root, fp); | 321 | BTRFS_INODE_MAP_OBJECTID, inode_root, fp); |
| 322 | BUG_ON(ret); | ||
| 323 | |||
| 324 | ret = find_and_setup_root(super, tree_root, fs_info, | ||
| 325 | BTRFS_FS_TREE_OBJECTID, root, fp); | ||
| 314 | BUG_ON(ret); | 326 | BUG_ON(ret); |
| 315 | 327 | ||
| 316 | root->commit_root = root->node; | 328 | root->commit_root = root->node; |
| @@ -323,8 +335,8 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 323 | *root, struct btrfs_super_block *s) | 335 | *root, struct btrfs_super_block *s) |
| 324 | { | 336 | { |
| 325 | int ret; | 337 | int ret; |
| 326 | btrfs_set_super_root(s, root->tree_root->node->blocknr); | 338 | btrfs_set_super_root(s, root->fs_info->tree_root->node->blocknr); |
| 327 | ret = pwrite(root->fp, s, sizeof(*s), | 339 | ret = pwrite(root->fs_info->fp, s, sizeof(*s), |
| 328 | BTRFS_SUPER_INFO_OFFSET); | 340 | BTRFS_SUPER_INFO_OFFSET); |
| 329 | if (ret != sizeof(*s)) { | 341 | if (ret != sizeof(*s)) { |
| 330 | fprintf(stderr, "failed to write new super block err %d\n", ret); | 342 | fprintf(stderr, "failed to write new super block err %d\n", ret); |
| @@ -335,9 +347,10 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 335 | 347 | ||
| 336 | static int drop_cache(struct btrfs_root *root) | 348 | static int drop_cache(struct btrfs_root *root) |
| 337 | { | 349 | { |
| 338 | while(!list_empty(&root->cache)) { | 350 | while(!list_empty(&root->fs_info->cache)) { |
| 339 | struct btrfs_buffer *b = list_entry(root->cache.next, | 351 | struct btrfs_buffer *b = list_entry(root->fs_info->cache.next, |
| 340 | struct btrfs_buffer, cache); | 352 | struct btrfs_buffer, |
| 353 | cache); | ||
| 341 | list_del_init(&b->cache); | 354 | list_del_init(&b->cache); |
| 342 | btrfs_block_release(root, b); | 355 | btrfs_block_release(root, b); |
| 343 | } | 356 | } |
| @@ -348,26 +361,28 @@ int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) | |||
| 348 | int ret; | 361 | int ret; |
| 349 | struct btrfs_trans_handle *trans; | 362 | struct btrfs_trans_handle *trans; |
| 350 | 363 | ||
| 351 | trans = root->running_transaction; | 364 | trans = root->fs_info->running_transaction; |
| 352 | btrfs_commit_transaction(trans, root, s); | 365 | btrfs_commit_transaction(trans, root, s); |
| 353 | ret = commit_extent_and_tree_roots(trans, root->tree_root, | 366 | ret = commit_tree_roots(trans, root->fs_info); |
| 354 | root->extent_root); | 367 | BUG_ON(ret); |
| 368 | ret = __commit_transaction(trans, root); | ||
| 355 | BUG_ON(ret); | 369 | BUG_ON(ret); |
| 356 | write_ctree_super(trans, root, s); | 370 | write_ctree_super(trans, root, s); |
| 357 | drop_cache(root->extent_root); | ||
| 358 | drop_cache(root->tree_root); | ||
| 359 | drop_cache(root); | 371 | drop_cache(root); |
| 360 | BUG_ON(!list_empty(&root->trans)); | 372 | BUG_ON(!list_empty(&root->fs_info->trans)); |
| 361 | BUG_ON(!list_empty(&root->extent_root->trans)); | ||
| 362 | BUG_ON(!list_empty(&root->tree_root->trans)); | ||
| 363 | 373 | ||
| 364 | close(root->fp); | 374 | close(root->fs_info->fp); |
| 365 | if (root->node) | 375 | if (root->node) |
| 366 | btrfs_block_release(root, root->node); | 376 | btrfs_block_release(root, root->node); |
| 367 | if (root->extent_root->node) | 377 | if (root->fs_info->extent_root->node) |
| 368 | btrfs_block_release(root->extent_root, root->extent_root->node); | 378 | btrfs_block_release(root->fs_info->extent_root, |
| 369 | if (root->tree_root->node) | 379 | root->fs_info->extent_root->node); |
| 370 | btrfs_block_release(root->tree_root, root->tree_root->node); | 380 | if (root->fs_info->inode_root->node) |
| 381 | btrfs_block_release(root->fs_info->inode_root, | ||
| 382 | root->fs_info->inode_root->node); | ||
| 383 | if (root->fs_info->tree_root->node) | ||
| 384 | btrfs_block_release(root->fs_info->tree_root, | ||
| 385 | root->fs_info->tree_root->node); | ||
| 371 | btrfs_block_release(root, root->commit_root); | 386 | btrfs_block_release(root, root->commit_root); |
| 372 | free(root); | 387 | free(root); |
| 373 | printf("on close %d blocks are allocated\n", allocated_blocks); | 388 | printf("on close %d blocks are allocated\n", allocated_blocks); |
| @@ -382,15 +397,16 @@ void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf) | |||
| 382 | if (buf->count == 0) { | 397 | if (buf->count == 0) { |
| 383 | BUG_ON(!list_empty(&buf->cache)); | 398 | BUG_ON(!list_empty(&buf->cache)); |
| 384 | BUG_ON(!list_empty(&buf->dirty)); | 399 | BUG_ON(!list_empty(&buf->dirty)); |
| 385 | if (!radix_tree_lookup(&root->cache_radix, buf->blocknr)) | 400 | if (!radix_tree_lookup(&root->fs_info->cache_radix, |
| 401 | buf->blocknr)) | ||
| 386 | BUG(); | 402 | BUG(); |
| 387 | radix_tree_delete(&root->cache_radix, buf->blocknr); | 403 | radix_tree_delete(&root->fs_info->cache_radix, buf->blocknr); |
| 388 | memset(buf, 0, sizeof(*buf)); | 404 | memset(buf, 0, sizeof(*buf)); |
| 389 | free(buf); | 405 | free(buf); |
| 390 | BUG_ON(allocated_blocks == 0); | 406 | BUG_ON(allocated_blocks == 0); |
| 391 | allocated_blocks--; | 407 | allocated_blocks--; |
| 392 | BUG_ON(root->cache_size == 0); | 408 | BUG_ON(root->fs_info->cache_size == 0); |
| 393 | root->cache_size--; | 409 | root->fs_info->cache_size--; |
| 394 | } | 410 | } |
| 395 | } | 411 | } |
| 396 | 412 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c29b92d440e0..09eeeb4d9d28 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -35,13 +35,15 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 35 | struct btrfs_key ins; | 35 | struct btrfs_key ins; |
| 36 | u32 refs; | 36 | u32 refs; |
| 37 | 37 | ||
| 38 | find_free_extent(trans, root->extent_root, 0, 0, (u64)-1, &ins); | 38 | find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1, |
| 39 | &ins); | ||
| 39 | btrfs_init_path(&path); | 40 | btrfs_init_path(&path); |
| 40 | key.objectid = blocknr; | 41 | key.objectid = blocknr; |
| 41 | key.flags = 0; | 42 | key.flags = 0; |
| 42 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 43 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
| 43 | key.offset = 1; | 44 | key.offset = 1; |
| 44 | ret = btrfs_search_slot(trans, root->extent_root, &key, &path, 0, 1); | 45 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, &path, |
| 46 | 0, 1); | ||
| 45 | if (ret != 0) | 47 | if (ret != 0) |
| 46 | BUG(); | 48 | BUG(); |
| 47 | BUG_ON(ret != 0); | 49 | BUG_ON(ret != 0); |
| @@ -51,9 +53,9 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 51 | btrfs_set_extent_refs(item, refs + 1); | 53 | btrfs_set_extent_refs(item, refs + 1); |
| 52 | 54 | ||
| 53 | BUG_ON(list_empty(&path.nodes[0]->dirty)); | 55 | BUG_ON(list_empty(&path.nodes[0]->dirty)); |
| 54 | btrfs_release_path(root->extent_root, &path); | 56 | btrfs_release_path(root->fs_info->extent_root, &path); |
| 55 | finish_current_insert(trans, root->extent_root); | 57 | finish_current_insert(trans, root->fs_info->extent_root); |
| 56 | run_pending(trans, root->extent_root); | 58 | run_pending(trans, root->fs_info->extent_root); |
| 57 | return 0; | 59 | return 0; |
| 58 | } | 60 | } |
| 59 | 61 | ||
| @@ -70,13 +72,14 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 70 | key.offset = 1; | 72 | key.offset = 1; |
| 71 | key.flags = 0; | 73 | key.flags = 0; |
| 72 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 74 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
| 73 | ret = btrfs_search_slot(trans, root->extent_root, &key, &path, 0, 0); | 75 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, &path, |
| 76 | 0, 0); | ||
| 74 | if (ret != 0) | 77 | if (ret != 0) |
| 75 | BUG(); | 78 | BUG(); |
| 76 | l = &path.nodes[0]->leaf; | 79 | l = &path.nodes[0]->leaf; |
| 77 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); | 80 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); |
| 78 | *refs = btrfs_extent_refs(item); | 81 | *refs = btrfs_extent_refs(item); |
| 79 | btrfs_release_path(root->extent_root, &path); | 82 | btrfs_release_path(root->fs_info->extent_root, &path); |
| 80 | return 0; | 83 | return 0; |
| 81 | } | 84 | } |
| 82 | 85 | ||
| @@ -107,19 +110,20 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | |||
| 107 | int i; | 110 | int i; |
| 108 | 111 | ||
| 109 | while(1) { | 112 | while(1) { |
| 110 | ret = radix_tree_gang_lookup(&root->pinned_radix, | 113 | ret = radix_tree_gang_lookup(&root->fs_info->pinned_radix, |
| 111 | (void **)gang, 0, | 114 | (void **)gang, 0, |
| 112 | ARRAY_SIZE(gang)); | 115 | ARRAY_SIZE(gang)); |
| 113 | if (!ret) | 116 | if (!ret) |
| 114 | break; | 117 | break; |
| 115 | if (!first) | 118 | if (!first) |
| 116 | first = gang[0]; | 119 | first = gang[0]; |
| 117 | for (i = 0; i < ret; i++) { | 120 | for (i = 0; i < ret; i++) { |
| 118 | radix_tree_delete(&root->pinned_radix, gang[i]); | 121 | radix_tree_delete(&root->fs_info->pinned_radix, |
| 122 | gang[i]); | ||
| 119 | } | 123 | } |
| 120 | } | 124 | } |
| 121 | root->last_insert.objectid = first; | 125 | root->fs_info->last_insert.objectid = first; |
| 122 | root->last_insert.offset = 0; | 126 | root->fs_info->last_insert.offset = 0; |
| 123 | return 0; | 127 | return 0; |
| 124 | } | 128 | } |
| 125 | 129 | ||
| @@ -138,13 +142,14 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
| 138 | ins.flags = 0; | 142 | ins.flags = 0; |
| 139 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); | 143 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); |
| 140 | 144 | ||
| 141 | for (i = 0; i < extent_root->current_insert.flags; i++) { | 145 | for (i = 0; i < extent_root->fs_info->current_insert.flags; i++) { |
| 142 | ins.objectid = extent_root->current_insert.objectid + i; | 146 | ins.objectid = extent_root->fs_info->current_insert.objectid + |
| 147 | i; | ||
| 143 | ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item, | 148 | ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item, |
| 144 | sizeof(extent_item)); | 149 | sizeof(extent_item)); |
| 145 | BUG_ON(ret); | 150 | BUG_ON(ret); |
| 146 | } | 151 | } |
| 147 | extent_root->current_insert.offset = 0; | 152 | extent_root->fs_info->current_insert.offset = 0; |
| 148 | return 0; | 153 | return 0; |
| 149 | } | 154 | } |
| 150 | 155 | ||
| @@ -156,7 +161,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 156 | { | 161 | { |
| 157 | struct btrfs_path path; | 162 | struct btrfs_path path; |
| 158 | struct btrfs_key key; | 163 | struct btrfs_key key; |
| 159 | struct btrfs_root *extent_root = root->extent_root; | 164 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
| 160 | int ret; | 165 | int ret; |
| 161 | struct btrfs_extent_item *ei; | 166 | struct btrfs_extent_item *ei; |
| 162 | struct btrfs_key ins; | 167 | struct btrfs_key ins; |
| @@ -186,14 +191,16 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 186 | if (pin) { | 191 | if (pin) { |
| 187 | int err; | 192 | int err; |
| 188 | radix_tree_preload(GFP_KERNEL); | 193 | radix_tree_preload(GFP_KERNEL); |
| 189 | err = radix_tree_insert(&extent_root->pinned_radix, | 194 | err = radix_tree_insert( |
| 190 | blocknr, (void *)blocknr); | 195 | &extent_root->fs_info->pinned_radix, |
| 196 | blocknr, (void *)blocknr); | ||
| 191 | BUG_ON(err); | 197 | BUG_ON(err); |
| 192 | radix_tree_preload_end(); | 198 | radix_tree_preload_end(); |
| 193 | } | 199 | } |
| 194 | ret = btrfs_del_item(trans, extent_root, &path); | 200 | ret = btrfs_del_item(trans, extent_root, &path); |
| 195 | if (!pin && extent_root->last_insert.objectid > blocknr) | 201 | if (!pin && extent_root->fs_info->last_insert.objectid > |
| 196 | extent_root->last_insert.objectid = blocknr; | 202 | blocknr) |
| 203 | extent_root->fs_info->last_insert.objectid = blocknr; | ||
| 197 | if (ret) | 204 | if (ret) |
| 198 | BUG(); | 205 | BUG(); |
| 199 | } | 206 | } |
| @@ -214,18 +221,19 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
| 214 | int i; | 221 | int i; |
| 215 | 222 | ||
| 216 | while(1) { | 223 | while(1) { |
| 217 | ret = radix_tree_gang_lookup_tag(&extent_root->cache_radix, | 224 | ret = radix_tree_gang_lookup_tag( |
| 218 | (void **)gang, 0, | 225 | &extent_root->fs_info->cache_radix, |
| 219 | ARRAY_SIZE(gang), | 226 | (void **)gang, 0, |
| 220 | CTREE_EXTENT_PENDING_DEL); | 227 | ARRAY_SIZE(gang), |
| 228 | CTREE_EXTENT_PENDING_DEL); | ||
| 221 | if (!ret) | 229 | if (!ret) |
| 222 | break; | 230 | break; |
| 223 | for (i = 0; i < ret; i++) { | 231 | for (i = 0; i < ret; i++) { |
| 224 | ret = __free_extent(trans, extent_root, | 232 | ret = __free_extent(trans, extent_root, |
| 225 | gang[i]->blocknr, 1, 1); | 233 | gang[i]->blocknr, 1, 1); |
| 226 | radix_tree_tag_clear(&extent_root->cache_radix, | 234 | radix_tree_tag_clear(&extent_root->fs_info->cache_radix, |
| 227 | gang[i]->blocknr, | 235 | gang[i]->blocknr, |
| 228 | CTREE_EXTENT_PENDING_DEL); | 236 | CTREE_EXTENT_PENDING_DEL); |
| 229 | btrfs_block_release(extent_root, gang[i]); | 237 | btrfs_block_release(extent_root, gang[i]); |
| 230 | } | 238 | } |
| 231 | } | 239 | } |
| @@ -235,8 +243,8 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
| 235 | static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root | 243 | static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root |
| 236 | *extent_root) | 244 | *extent_root) |
| 237 | { | 245 | { |
| 238 | while(radix_tree_tagged(&extent_root->cache_radix, | 246 | while(radix_tree_tagged(&extent_root->fs_info->cache_radix, |
| 239 | CTREE_EXTENT_PENDING_DEL)) | 247 | CTREE_EXTENT_PENDING_DEL)) |
| 240 | del_pending_extents(trans, extent_root); | 248 | del_pending_extents(trans, extent_root); |
| 241 | return 0; | 249 | return 0; |
| 242 | } | 250 | } |
| @@ -248,19 +256,19 @@ static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 248 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 256 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
| 249 | *root, u64 blocknr, u64 num_blocks, int pin) | 257 | *root, u64 blocknr, u64 num_blocks, int pin) |
| 250 | { | 258 | { |
| 251 | struct btrfs_root *extent_root = root->extent_root; | 259 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
| 252 | struct btrfs_buffer *t; | 260 | struct btrfs_buffer *t; |
| 253 | int pending_ret; | 261 | int pending_ret; |
| 254 | int ret; | 262 | int ret; |
| 255 | 263 | ||
| 256 | if (root == extent_root) { | 264 | if (root == extent_root) { |
| 257 | t = find_tree_block(root, blocknr); | 265 | t = find_tree_block(root, blocknr); |
| 258 | radix_tree_tag_set(&root->cache_radix, blocknr, | 266 | radix_tree_tag_set(&root->fs_info->cache_radix, blocknr, |
| 259 | CTREE_EXTENT_PENDING_DEL); | 267 | CTREE_EXTENT_PENDING_DEL); |
| 260 | return 0; | 268 | return 0; |
| 261 | } | 269 | } |
| 262 | ret = __free_extent(trans, root, blocknr, num_blocks, pin); | 270 | ret = __free_extent(trans, root, blocknr, num_blocks, pin); |
| 263 | pending_ret = run_pending(trans, root->extent_root); | 271 | pending_ret = run_pending(trans, root->fs_info->extent_root); |
| 264 | return ret ? ret : pending_ret; | 272 | return ret ? ret : pending_ret; |
| 265 | } | 273 | } |
| 266 | 274 | ||
| @@ -285,12 +293,12 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 285 | u64 test_block; | 293 | u64 test_block; |
| 286 | int start_found; | 294 | int start_found; |
| 287 | struct btrfs_leaf *l; | 295 | struct btrfs_leaf *l; |
| 288 | struct btrfs_root * root = orig_root->extent_root; | 296 | struct btrfs_root * root = orig_root->fs_info->extent_root; |
| 289 | int total_needed = num_blocks; | 297 | int total_needed = num_blocks; |
| 290 | 298 | ||
| 291 | total_needed += (btrfs_header_level(&root->node->node.header) + 1) * 3; | 299 | total_needed += (btrfs_header_level(&root->node->node.header) + 1) * 3; |
| 292 | if (root->last_insert.objectid > search_start) | 300 | if (root->fs_info->last_insert.objectid > search_start) |
| 293 | search_start = root->last_insert.objectid; | 301 | search_start = root->fs_info->last_insert.objectid; |
| 294 | 302 | ||
| 295 | ins->flags = 0; | 303 | ins->flags = 0; |
| 296 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); | 304 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); |
| @@ -353,16 +361,17 @@ check_pending: | |||
| 353 | BUG_ON(ins->objectid < search_start); | 361 | BUG_ON(ins->objectid < search_start); |
| 354 | for (test_block = ins->objectid; | 362 | for (test_block = ins->objectid; |
| 355 | test_block < ins->objectid + total_needed; test_block++) { | 363 | test_block < ins->objectid + total_needed; test_block++) { |
| 356 | if (radix_tree_lookup(&root->pinned_radix, test_block)) { | 364 | if (radix_tree_lookup(&root->fs_info->pinned_radix, |
| 365 | test_block)) { | ||
| 357 | search_start = test_block + 1; | 366 | search_start = test_block + 1; |
| 358 | goto check_failed; | 367 | goto check_failed; |
| 359 | } | 368 | } |
| 360 | } | 369 | } |
| 361 | BUG_ON(root->current_insert.offset); | 370 | BUG_ON(root->fs_info->current_insert.offset); |
| 362 | root->current_insert.offset = total_needed - num_blocks; | 371 | root->fs_info->current_insert.offset = total_needed - num_blocks; |
| 363 | root->current_insert.objectid = ins->objectid + num_blocks; | 372 | root->fs_info->current_insert.objectid = ins->objectid + num_blocks; |
| 364 | root->current_insert.flags = 0; | 373 | root->fs_info->current_insert.flags = 0; |
| 365 | root->last_insert.objectid = ins->objectid; | 374 | root->fs_info->last_insert.objectid = ins->objectid; |
| 366 | ins->offset = num_blocks; | 375 | ins->offset = num_blocks; |
| 367 | return 0; | 376 | return 0; |
| 368 | error: | 377 | error: |
| @@ -383,20 +392,20 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 383 | { | 392 | { |
| 384 | int ret; | 393 | int ret; |
| 385 | int pending_ret; | 394 | int pending_ret; |
| 386 | struct btrfs_root *extent_root = root->extent_root; | 395 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
| 387 | struct btrfs_extent_item extent_item; | 396 | struct btrfs_extent_item extent_item; |
| 388 | 397 | ||
| 389 | btrfs_set_extent_refs(&extent_item, 1); | 398 | btrfs_set_extent_refs(&extent_item, 1); |
| 390 | btrfs_set_extent_owner(&extent_item, owner); | 399 | btrfs_set_extent_owner(&extent_item, owner); |
| 391 | 400 | ||
| 392 | if (root == extent_root) { | 401 | if (root == extent_root) { |
| 393 | BUG_ON(extent_root->current_insert.offset == 0); | 402 | BUG_ON(extent_root->fs_info->current_insert.offset == 0); |
| 394 | BUG_ON(num_blocks != 1); | 403 | BUG_ON(num_blocks != 1); |
| 395 | BUG_ON(extent_root->current_insert.flags == | 404 | BUG_ON(extent_root->fs_info->current_insert.flags == |
| 396 | extent_root->current_insert.offset); | 405 | extent_root->fs_info->current_insert.offset); |
| 397 | ins->offset = 1; | 406 | ins->offset = 1; |
| 398 | ins->objectid = extent_root->current_insert.objectid + | 407 | ins->objectid = extent_root->fs_info->current_insert.objectid + |
| 399 | extent_root->current_insert.flags++; | 408 | extent_root->fs_info->current_insert.flags++; |
| 400 | return 0; | 409 | return 0; |
| 401 | } | 410 | } |
| 402 | ret = find_free_extent(trans, root, num_blocks, search_start, | 411 | ret = find_free_extent(trans, root, num_blocks, search_start, |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index f5b36c732c5e..24cfd6d85240 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
| @@ -4,4 +4,10 @@ | |||
| 4 | #include "radix-tree.h" | 4 | #include "radix-tree.h" |
| 5 | #include "ctree.h" | 5 | #include "ctree.h" |
| 6 | #include "disk-io.h" | 6 | #include "disk-io.h" |
| 7 | #include "transaction.h" | ||
| 7 | 8 | ||
| 9 | int btrfs_create_file(struct btrfs_trans_handle *trans, | ||
| 10 | struct btrfs_root *root, u64 dirid, u64 *objectid) | ||
| 11 | { | ||
| 12 | return 0; | ||
| 13 | } | ||
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c new file mode 100644 index 000000000000..f412b3392135 --- /dev/null +++ b/fs/btrfs/inode-map.c | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <stdlib.h> | ||
| 3 | #include "kerncompat.h" | ||
| 4 | #include "radix-tree.h" | ||
| 5 | #include "ctree.h" | ||
| 6 | #include "disk-io.h" | ||
| 7 | #include "transaction.h" | ||
| 8 | |||
| 9 | /* | ||
| 10 | * walks the btree of allocated inodes and find a hole. | ||
| 11 | */ | ||
| 12 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | ||
| 13 | struct btrfs_root *fs_root, | ||
| 14 | u64 dirid, u64 *objectid) | ||
| 15 | { | ||
| 16 | struct btrfs_path path; | ||
| 17 | struct btrfs_key key; | ||
| 18 | int ret; | ||
| 19 | u64 hole_size = 0; | ||
| 20 | int slot = 0; | ||
| 21 | u64 last_ino; | ||
| 22 | int start_found; | ||
| 23 | struct btrfs_leaf *l; | ||
| 24 | struct btrfs_root *root = fs_root->fs_info->inode_root; | ||
| 25 | struct btrfs_key search_key; | ||
| 26 | u64 search_start = dirid; | ||
| 27 | |||
| 28 | if (fs_root->fs_info->last_inode_alloc_dirid == dirid) | ||
| 29 | search_start = fs_root->fs_info->last_inode_alloc; | ||
| 30 | |||
| 31 | search_key.objectid = search_start; | ||
| 32 | search_key.flags = 0; | ||
| 33 | btrfs_set_key_type(&search_key, BTRFS_INODE_MAP_ITEM_KEY); | ||
| 34 | search_key.offset = 0; | ||
| 35 | |||
| 36 | btrfs_init_path(&path); | ||
| 37 | start_found = 0; | ||
| 38 | ret = btrfs_search_slot(trans, root, &search_key, &path, 0, 0); | ||
| 39 | if (ret < 0) | ||
| 40 | goto error; | ||
| 41 | |||
| 42 | if (path.slots[0] > 0) | ||
| 43 | path.slots[0]--; | ||
| 44 | |||
| 45 | while (1) { | ||
| 46 | l = &path.nodes[0]->leaf; | ||
| 47 | slot = path.slots[0]; | ||
| 48 | if (slot >= btrfs_header_nritems(&l->header)) { | ||
| 49 | ret = btrfs_next_leaf(root, &path); | ||
| 50 | if (ret == 0) | ||
| 51 | continue; | ||
| 52 | if (ret < 0) | ||
| 53 | goto error; | ||
| 54 | if (!start_found) { | ||
| 55 | *objectid = search_start; | ||
| 56 | start_found = 1; | ||
| 57 | goto found; | ||
| 58 | } | ||
| 59 | *objectid = last_ino > search_start ? | ||
| 60 | last_ino : search_start; | ||
| 61 | goto found; | ||
| 62 | } | ||
| 63 | btrfs_disk_key_to_cpu(&key, &l->items[slot].key); | ||
| 64 | if (key.objectid >= search_start) { | ||
| 65 | if (start_found) { | ||
| 66 | if (last_ino < search_start) | ||
| 67 | last_ino = search_start; | ||
| 68 | hole_size = key.objectid - last_ino; | ||
| 69 | if (hole_size > 0) { | ||
| 70 | *objectid = last_ino; | ||
| 71 | goto found; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | } | ||
| 75 | start_found = 1; | ||
| 76 | last_ino = key.objectid + 1; | ||
| 77 | path.slots[0]++; | ||
| 78 | } | ||
| 79 | // FIXME -ENOSPC | ||
| 80 | found: | ||
| 81 | root->fs_info->last_inode_alloc = *objectid; | ||
| 82 | root->fs_info->last_inode_alloc_dirid = dirid; | ||
| 83 | btrfs_release_path(root, &path); | ||
| 84 | BUG_ON(*objectid < search_start); | ||
| 85 | return 0; | ||
| 86 | error: | ||
| 87 | btrfs_release_path(root, &path); | ||
| 88 | return ret; | ||
| 89 | } | ||
| 90 | |||
| 91 | int btrfs_insert_inode_map(struct btrfs_trans_handle *trans, | ||
| 92 | struct btrfs_root *fs_root, | ||
| 93 | u64 objectid, struct btrfs_key *location) | ||
| 94 | { | ||
| 95 | int ret = 0; | ||
| 96 | struct btrfs_path path; | ||
| 97 | struct btrfs_inode_map_item *inode_item; | ||
| 98 | struct btrfs_key key; | ||
| 99 | struct btrfs_root *inode_root = fs_root->fs_info->inode_root; | ||
| 100 | |||
| 101 | key.objectid = objectid; | ||
| 102 | key.flags = 0; | ||
| 103 | btrfs_set_key_type(&key, BTRFS_INODE_MAP_ITEM_KEY); | ||
| 104 | key.offset = 0; | ||
| 105 | btrfs_init_path(&path); | ||
| 106 | ret = btrfs_insert_empty_item(trans, inode_root, &path, &key, | ||
| 107 | sizeof(struct btrfs_inode_map_item)); | ||
| 108 | if (ret) | ||
| 109 | goto out; | ||
| 110 | |||
| 111 | inode_item = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], | ||
| 112 | struct btrfs_inode_map_item); | ||
| 113 | btrfs_cpu_key_to_disk(&inode_item->key, location); | ||
| 114 | out: | ||
| 115 | btrfs_release_path(inode_root, &path); | ||
| 116 | return ret; | ||
| 117 | } | ||
| 118 | |||
| 119 | int btrfs_lookup_inode_map(struct btrfs_trans_handle *trans, | ||
| 120 | struct btrfs_root *fs_root, struct btrfs_path *path, | ||
| 121 | u64 objectid, int mod) | ||
| 122 | { | ||
| 123 | int ret; | ||
| 124 | struct btrfs_key key; | ||
| 125 | int ins_len = mod < 0 ? -1 : 0; | ||
| 126 | int cow = mod != 0; | ||
| 127 | struct btrfs_root *inode_root = fs_root->fs_info->inode_root; | ||
| 128 | |||
| 129 | key.objectid = objectid; | ||
| 130 | key.flags = 0; | ||
| 131 | key.offset = 0; | ||
| 132 | btrfs_set_key_type(&key, BTRFS_INODE_MAP_ITEM_KEY); | ||
| 133 | ret = btrfs_search_slot(trans, inode_root, &key, path, ins_len, cow); | ||
| 134 | return ret; | ||
| 135 | } | ||
| 136 | |||
diff --git a/fs/btrfs/mkfs.c b/fs/btrfs/mkfs.c index 9aa900811c33..1cac5ab114dd 100644 --- a/fs/btrfs/mkfs.c +++ b/fs/btrfs/mkfs.c | |||
| @@ -42,7 +42,7 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) | |||
| 42 | btrfs_set_header_parentid(&empty_leaf->header, | 42 | btrfs_set_header_parentid(&empty_leaf->header, |
| 43 | BTRFS_ROOT_TREE_OBJECTID); | 43 | BTRFS_ROOT_TREE_OBJECTID); |
| 44 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 1); | 44 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 1); |
| 45 | btrfs_set_header_nritems(&empty_leaf->header, 2); | 45 | btrfs_set_header_nritems(&empty_leaf->header, 3); |
| 46 | 46 | ||
| 47 | /* create the items for the root tree */ | 47 | /* create the items for the root tree */ |
| 48 | btrfs_set_root_blocknr(&root_item, start_block + 2); | 48 | btrfs_set_root_blocknr(&root_item, start_block + 2); |
| @@ -61,17 +61,25 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) | |||
| 61 | btrfs_set_root_blocknr(&root_item, start_block + 3); | 61 | btrfs_set_root_blocknr(&root_item, start_block + 3); |
| 62 | itemoff = itemoff - sizeof(root_item); | 62 | itemoff = itemoff - sizeof(root_item); |
| 63 | btrfs_set_item_offset(&item, itemoff); | 63 | btrfs_set_item_offset(&item, itemoff); |
| 64 | btrfs_set_disk_key_objectid(&item.key, BTRFS_FS_TREE_OBJECTID); | 64 | btrfs_set_disk_key_objectid(&item.key, BTRFS_INODE_MAP_OBJECTID); |
| 65 | memcpy(empty_leaf->items + 1, &item, sizeof(item)); | 65 | memcpy(empty_leaf->items + 1, &item, sizeof(item)); |
| 66 | memcpy(btrfs_leaf_data(empty_leaf) + itemoff, | 66 | memcpy(btrfs_leaf_data(empty_leaf) + itemoff, |
| 67 | &root_item, sizeof(root_item)); | 67 | &root_item, sizeof(root_item)); |
| 68 | |||
| 69 | btrfs_set_root_blocknr(&root_item, start_block + 4); | ||
| 70 | itemoff = itemoff - sizeof(root_item); | ||
| 71 | btrfs_set_item_offset(&item, itemoff); | ||
| 72 | btrfs_set_disk_key_objectid(&item.key, BTRFS_FS_TREE_OBJECTID); | ||
| 73 | memcpy(empty_leaf->items + 2, &item, sizeof(item)); | ||
| 74 | memcpy(btrfs_leaf_data(empty_leaf) + itemoff, | ||
| 75 | &root_item, sizeof(root_item)); | ||
| 68 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 1) * blocksize); | 76 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 1) * blocksize); |
| 69 | 77 | ||
| 70 | /* create the items for the extent tree */ | 78 | /* create the items for the extent tree */ |
| 71 | btrfs_set_header_parentid(&empty_leaf->header, | 79 | btrfs_set_header_parentid(&empty_leaf->header, |
| 72 | BTRFS_EXTENT_TREE_OBJECTID); | 80 | BTRFS_EXTENT_TREE_OBJECTID); |
| 73 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 2); | 81 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 2); |
| 74 | btrfs_set_header_nritems(&empty_leaf->header, 4); | 82 | btrfs_set_header_nritems(&empty_leaf->header, 5); |
| 75 | 83 | ||
| 76 | /* item1, reserve blocks 0-16 */ | 84 | /* item1, reserve blocks 0-16 */ |
| 77 | btrfs_set_disk_key_objectid(&item.key, 0); | 85 | btrfs_set_disk_key_objectid(&item.key, 0); |
| @@ -108,12 +116,12 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) | |||
| 108 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), | 116 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), |
| 109 | &extent_item, btrfs_item_size(&item)); | 117 | &extent_item, btrfs_item_size(&item)); |
| 110 | 118 | ||
| 111 | /* item4, give block 19 to the FS root */ | 119 | /* item4, give block 19 to the inode map */ |
| 112 | btrfs_set_disk_key_objectid(&item.key, start_block + 3); | 120 | btrfs_set_disk_key_objectid(&item.key, start_block + 3); |
| 113 | btrfs_set_disk_key_offset(&item.key, 1); | 121 | btrfs_set_disk_key_offset(&item.key, 1); |
| 114 | itemoff = itemoff - sizeof(struct btrfs_extent_item); | 122 | itemoff = itemoff - sizeof(struct btrfs_extent_item); |
| 115 | btrfs_set_item_offset(&item, itemoff); | 123 | btrfs_set_item_offset(&item, itemoff); |
| 116 | btrfs_set_extent_owner(&extent_item, BTRFS_FS_TREE_OBJECTID); | 124 | btrfs_set_extent_owner(&extent_item, BTRFS_INODE_MAP_OBJECTID); |
| 117 | memcpy(empty_leaf->items + 3, &item, sizeof(item)); | 125 | memcpy(empty_leaf->items + 3, &item, sizeof(item)); |
| 118 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), | 126 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), |
| 119 | &extent_item, btrfs_item_size(&item)); | 127 | &extent_item, btrfs_item_size(&item)); |
| @@ -121,12 +129,34 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) | |||
| 121 | if (ret != blocksize) | 129 | if (ret != blocksize) |
| 122 | return -1; | 130 | return -1; |
| 123 | 131 | ||
| 124 | /* finally create the FS root */ | 132 | /* item5, give block 20 to the FS root */ |
| 125 | btrfs_set_header_parentid(&empty_leaf->header, BTRFS_FS_TREE_OBJECTID); | 133 | btrfs_set_disk_key_objectid(&item.key, start_block + 4); |
| 134 | btrfs_set_disk_key_offset(&item.key, 1); | ||
| 135 | itemoff = itemoff - sizeof(struct btrfs_extent_item); | ||
| 136 | btrfs_set_item_offset(&item, itemoff); | ||
| 137 | btrfs_set_extent_owner(&extent_item, BTRFS_FS_TREE_OBJECTID); | ||
| 138 | memcpy(empty_leaf->items + 4, &item, sizeof(item)); | ||
| 139 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), | ||
| 140 | &extent_item, btrfs_item_size(&item)); | ||
| 141 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 2) * blocksize); | ||
| 142 | if (ret != blocksize) | ||
| 143 | return -1; | ||
| 144 | |||
| 145 | /* create the inode map */ | ||
| 146 | btrfs_set_header_parentid(&empty_leaf->header, | ||
| 147 | BTRFS_INODE_MAP_OBJECTID); | ||
| 126 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 3); | 148 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 3); |
| 127 | btrfs_set_header_nritems(&empty_leaf->header, 0); | 149 | btrfs_set_header_nritems(&empty_leaf->header, 0); |
| 128 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 3) * blocksize); | 150 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 3) * blocksize); |
| 129 | if (ret != blocksize) | 151 | if (ret != blocksize) |
| 130 | return -1; | 152 | return -1; |
| 153 | |||
| 154 | /* finally create the FS root */ | ||
| 155 | btrfs_set_header_parentid(&empty_leaf->header, BTRFS_FS_TREE_OBJECTID); | ||
| 156 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 4); | ||
| 157 | btrfs_set_header_nritems(&empty_leaf->header, 0); | ||
| 158 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 4) * blocksize); | ||
| 159 | if (ret != blocksize) | ||
| 160 | return -1; | ||
| 131 | return 0; | 161 | return 0; |
| 132 | } | 162 | } |
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index 0bb5c38427c9..f250e5fad773 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c | |||
| @@ -13,8 +13,8 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
| 13 | struct btrfs_extent_item *ei; | 13 | struct btrfs_extent_item *ei; |
| 14 | struct btrfs_root_item *ri; | 14 | struct btrfs_root_item *ri; |
| 15 | struct btrfs_dir_item *di; | 15 | struct btrfs_dir_item *di; |
| 16 | struct btrfs_inode_map_item *mi; | ||
| 16 | u32 type; | 17 | u32 type; |
| 17 | u32 namelen; | ||
| 18 | 18 | ||
| 19 | printf("leaf %Lu total ptrs %d free space %d\n", | 19 | printf("leaf %Lu total ptrs %d free space %d\n", |
| 20 | btrfs_header_blocknr(&l->header), nr, | 20 | btrfs_header_blocknr(&l->header), nr, |
| @@ -34,15 +34,13 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
| 34 | case BTRFS_INODE_ITEM_KEY: | 34 | case BTRFS_INODE_ITEM_KEY: |
| 35 | break; | 35 | break; |
| 36 | case BTRFS_DIR_ITEM_KEY: | 36 | case BTRFS_DIR_ITEM_KEY: |
| 37 | namelen = btrfs_item_size(l->items + i) - sizeof(*di); | ||
| 38 | di = btrfs_item_ptr(l, i, struct btrfs_dir_item); | 37 | di = btrfs_item_ptr(l, i, struct btrfs_dir_item); |
| 39 | printf("\t\tdir oid %Lu flags %u type %u\n", | 38 | printf("\t\tdir oid %Lu flags %u type %u\n", |
| 40 | btrfs_dir_objectid(di), | 39 | btrfs_dir_objectid(di), |
| 41 | btrfs_dir_flags(di), | 40 | btrfs_dir_flags(di), |
| 42 | btrfs_dir_type(di)); | 41 | btrfs_dir_type(di)); |
| 43 | printf("\t\tname %.*s\n", | 42 | printf("\t\tname %.*s\n", |
| 44 | namelen, (char *)(di + 1)); | 43 | btrfs_dir_name_len(di),(char *)(di + 1)); |
| 45 | |||
| 46 | break; | 44 | break; |
| 47 | case BTRFS_ROOT_ITEM_KEY: | 45 | case BTRFS_ROOT_ITEM_KEY: |
| 48 | ri = btrfs_item_ptr(l, i, struct btrfs_root_item); | 46 | ri = btrfs_item_ptr(l, i, struct btrfs_root_item); |
| @@ -54,6 +52,13 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
| 54 | printf("\t\textent data refs %u owner %Lu\n", | 52 | printf("\t\textent data refs %u owner %Lu\n", |
| 55 | btrfs_extent_refs(ei), btrfs_extent_owner(ei)); | 53 | btrfs_extent_refs(ei), btrfs_extent_owner(ei)); |
| 56 | break; | 54 | break; |
| 55 | case BTRFS_INODE_MAP_ITEM_KEY: | ||
| 56 | mi = btrfs_item_ptr(l, i, struct btrfs_inode_map_item); | ||
| 57 | printf("\t\tinode map key %Lu %u %Lu\n", | ||
| 58 | btrfs_disk_key_objectid(&mi->key), | ||
| 59 | btrfs_disk_key_flags(&mi->key), | ||
| 60 | btrfs_disk_key_offset(&mi->key)); | ||
| 61 | break; | ||
| 57 | case BTRFS_STRING_ITEM_KEY: | 62 | case BTRFS_STRING_ITEM_KEY: |
| 58 | printf("\t\titem data %.*s\n", btrfs_item_size(item), | 63 | printf("\t\titem data %.*s\n", btrfs_item_size(item), |
| 59 | btrfs_leaf_data(l) + btrfs_item_offset(item)); | 64 | btrfs_leaf_data(l) + btrfs_item_offset(item)); |
diff --git a/fs/btrfs/quick-test.c b/fs/btrfs/quick-test.c index d676577185d5..ef12cf888783 100644 --- a/fs/btrfs/quick-test.c +++ b/fs/btrfs/quick-test.c | |||
| @@ -172,7 +172,8 @@ int main(int ac, char **av) { | |||
| 172 | printf("tree size is now %d\n", tree_size); | 172 | printf("tree size is now %d\n", tree_size); |
| 173 | printf("root %p commit root %p\n", root->node, root->commit_root); | 173 | printf("root %p commit root %p\n", root->node, root->commit_root); |
| 174 | printf("map tree\n"); | 174 | printf("map tree\n"); |
| 175 | btrfs_print_tree(root->extent_root, root->extent_root->node); | 175 | btrfs_print_tree(root->fs_info->extent_root, |
| 176 | root->fs_info->extent_root->node); | ||
| 176 | close_ctree(root, &super); | 177 | close_ctree(root, &super); |
| 177 | return 0; | 178 | return 0; |
| 178 | } | 179 | } |
