diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-02-20 16:40:44 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-02-20 16:40:44 -0500 |
commit | d97e63b69ef21c02b67e20e41d9968b0e503572e (patch) | |
tree | 400db046be21c09f2d96f74ff98677464c45507f /fs/btrfs/disk-io.c | |
parent | 74123bd72a4e34c66e5ad95ce233dd352bebc572 (diff) |
Btrfs: early extent mapping support
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 76 |
1 files changed, 53 insertions, 23 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 8d51a07051d9..653f18aab330 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -12,25 +12,27 @@ | |||
12 | 12 | ||
13 | static int allocated_blocks = 0; | 13 | static int allocated_blocks = 0; |
14 | 14 | ||
15 | struct ctree_header { | ||
16 | u64 root_block; | ||
17 | } __attribute__ ((__packed__)); | ||
18 | |||
19 | static int get_free_block(struct ctree_root *root, u64 *block) | 15 | static int get_free_block(struct ctree_root *root, u64 *block) |
20 | { | 16 | { |
21 | struct stat st; | 17 | struct stat st; |
22 | int ret; | 18 | int ret; |
23 | 19 | ||
20 | if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks) | ||
21 | return -1; | ||
22 | |||
23 | *block = root->alloc_extent->blocknr + root->alloc_extent->num_used; | ||
24 | root->alloc_extent->num_used += 1; | ||
25 | if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks) { | ||
26 | struct alloc_extent *ae = root->alloc_extent; | ||
27 | root->alloc_extent = root->reserve_extent; | ||
28 | root->reserve_extent = ae; | ||
29 | ae->num_blocks = 0; | ||
30 | } | ||
24 | st.st_size = 0; | 31 | st.st_size = 0; |
25 | ret = fstat(root->fp, &st); | 32 | ret = fstat(root->fp, &st); |
26 | if (st.st_size > sizeof(struct ctree_header)) { | 33 | if (st.st_size < (*block + 1) * CTREE_BLOCKSIZE) |
27 | *block = (st.st_size - | 34 | ret = ftruncate(root->fp, |
28 | sizeof(struct ctree_header)) / CTREE_BLOCKSIZE; | 35 | (*block + 1) * CTREE_BLOCKSIZE); |
29 | } else { | ||
30 | *block = 0; | ||
31 | } | ||
32 | ret = ftruncate(root->fp, sizeof(struct ctree_header) + (*block + 1) * | ||
33 | CTREE_BLOCKSIZE); | ||
34 | return ret; | 36 | return ret; |
35 | } | 37 | } |
36 | 38 | ||
@@ -72,7 +74,7 @@ struct tree_buffer *alloc_free_block(struct ctree_root *root) | |||
72 | 74 | ||
73 | struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) | 75 | struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) |
74 | { | 76 | { |
75 | loff_t offset = blocknr * CTREE_BLOCKSIZE + sizeof(struct ctree_header); | 77 | loff_t offset = blocknr * CTREE_BLOCKSIZE; |
76 | struct tree_buffer *buf; | 78 | struct tree_buffer *buf; |
77 | int ret; | 79 | int ret; |
78 | 80 | ||
@@ -101,7 +103,7 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) | |||
101 | int write_tree_block(struct ctree_root *root, struct tree_buffer *buf) | 103 | int write_tree_block(struct ctree_root *root, struct tree_buffer *buf) |
102 | { | 104 | { |
103 | u64 blocknr = buf->blocknr; | 105 | u64 blocknr = buf->blocknr; |
104 | loff_t offset = blocknr * CTREE_BLOCKSIZE + sizeof(struct ctree_header); | 106 | loff_t offset = blocknr * CTREE_BLOCKSIZE; |
105 | int ret; | 107 | int ret; |
106 | 108 | ||
107 | if (buf->blocknr != buf->node.header.blocknr) | 109 | if (buf->blocknr != buf->node.header.blocknr) |
@@ -114,11 +116,32 @@ int write_tree_block(struct ctree_root *root, struct tree_buffer *buf) | |||
114 | return 0; | 116 | return 0; |
115 | } | 117 | } |
116 | 118 | ||
119 | struct ctree_super_block { | ||
120 | struct ctree_root_info root_info; | ||
121 | struct ctree_root_info extent_info; | ||
122 | } __attribute__ ((__packed__)); | ||
123 | |||
124 | static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root, | ||
125 | struct ctree_root_info *info, int fp) | ||
126 | { | ||
127 | root->fp = fp; | ||
128 | root->node = read_tree_block(root, info->tree_root); | ||
129 | root->extent_root = extent_root; | ||
130 | memcpy(&root->ai1, &info->alloc_extent, sizeof(info->alloc_extent)); | ||
131 | memcpy(&root->ai2, &info->reserve_extent, sizeof(info->reserve_extent)); | ||
132 | root->alloc_extent = &root->ai1; | ||
133 | root->reserve_extent = &root->ai2; | ||
134 | INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); | ||
135 | printf("setup done reading root %p, used %lu\n", root, root->alloc_extent->num_used); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
117 | struct ctree_root *open_ctree(char *filename) | 139 | struct ctree_root *open_ctree(char *filename) |
118 | { | 140 | { |
119 | struct ctree_root *root = malloc(sizeof(struct ctree_root)); | 141 | struct ctree_root *root = malloc(sizeof(struct ctree_root)); |
142 | struct ctree_root *extent_root = malloc(sizeof(struct ctree_root)); | ||
143 | struct ctree_super_block super; | ||
120 | int fp; | 144 | int fp; |
121 | u64 root_block; | ||
122 | int ret; | 145 | int ret; |
123 | 146 | ||
124 | fp = open(filename, O_CREAT | O_RDWR); | 147 | fp = open(filename, O_CREAT | O_RDWR); |
@@ -126,14 +149,20 @@ struct ctree_root *open_ctree(char *filename) | |||
126 | free(root); | 149 | free(root); |
127 | return NULL; | 150 | return NULL; |
128 | } | 151 | } |
129 | root->fp = fp; | 152 | ret = pread(fp, &super, sizeof(struct ctree_super_block), |
130 | INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); | 153 | CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); |
131 | ret = pread(fp, &root_block, sizeof(u64), 0); | 154 | if (ret == 0) { |
132 | if (ret == sizeof(u64)) { | 155 | ret = mkfs(fp); |
133 | printf("reading root node at block %lu\n", root_block); | 156 | if (ret) |
134 | root->node = read_tree_block(root, root_block); | 157 | return NULL; |
135 | } else | 158 | ret = pread(fp, &super, sizeof(struct ctree_super_block), |
136 | root->node = NULL; | 159 | CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); |
160 | if (ret != sizeof(struct ctree_super_block)) | ||
161 | return NULL; | ||
162 | } | ||
163 | BUG_ON(ret < 0); | ||
164 | __setup_root(root, extent_root, &super.root_info, fp); | ||
165 | __setup_root(extent_root, extent_root, &super.extent_info, fp); | ||
137 | return root; | 166 | return root; |
138 | } | 167 | } |
139 | 168 | ||
@@ -160,6 +189,7 @@ int update_root_block(struct ctree_root *root) | |||
160 | 189 | ||
161 | void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) | 190 | void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) |
162 | { | 191 | { |
192 | return; | ||
163 | buf->count--; | 193 | buf->count--; |
164 | if (buf->count == 0) { | 194 | if (buf->count == 0) { |
165 | if (!radix_tree_lookup(&root->cache_radix, buf->blocknr)) | 195 | if (!radix_tree_lookup(&root->cache_radix, buf->blocknr)) |