aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-02-20 16:40:44 -0500
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-02-20 16:40:44 -0500
commitd97e63b69ef21c02b67e20e41d9968b0e503572e (patch)
tree400db046be21c09f2d96f74ff98677464c45507f /fs/btrfs/disk-io.c
parent74123bd72a4e34c66e5ad95ce233dd352bebc572 (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.c76
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
13static int allocated_blocks = 0; 13static int allocated_blocks = 0;
14 14
15struct ctree_header {
16 u64 root_block;
17} __attribute__ ((__packed__));
18
19static int get_free_block(struct ctree_root *root, u64 *block) 15static 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
73struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) 75struct 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)
101int write_tree_block(struct ctree_root *root, struct tree_buffer *buf) 103int 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
119struct ctree_super_block {
120 struct ctree_root_info root_info;
121 struct ctree_root_info extent_info;
122} __attribute__ ((__packed__));
123
124static 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
117struct ctree_root *open_ctree(char *filename) 139struct 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
161void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) 190void 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))