aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c79
1 files changed, 45 insertions, 34 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 653f18aab330..2f71ccf1c3cb 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -15,7 +15,7 @@ static int allocated_blocks = 0;
15static int get_free_block(struct ctree_root *root, u64 *block) 15static int get_free_block(struct ctree_root *root, u64 *block)
16{ 16{
17 struct stat st; 17 struct stat st;
18 int ret; 18 int ret = 0;
19 19
20 if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks) 20 if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks)
21 return -1; 21 return -1;
@@ -30,9 +30,14 @@ static int get_free_block(struct ctree_root *root, u64 *block)
30 } 30 }
31 st.st_size = 0; 31 st.st_size = 0;
32 ret = fstat(root->fp, &st); 32 ret = fstat(root->fp, &st);
33 if (st.st_size < (*block + 1) * CTREE_BLOCKSIZE) 33 if (st.st_size < (*block + 1) * CTREE_BLOCKSIZE) {
34 ret = ftruncate(root->fp, 34 ret = ftruncate(root->fp,
35 (*block + 1) * CTREE_BLOCKSIZE); 35 (*block + 1) * CTREE_BLOCKSIZE);
36 if (ret) {
37 perror("ftruncate");
38 exit(1);
39 }
40 }
36 return ret; 41 return ret;
37} 42}
38 43
@@ -81,11 +86,7 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr)
81 buf = radix_tree_lookup(&root->cache_radix, blocknr); 86 buf = radix_tree_lookup(&root->cache_radix, blocknr);
82 if (buf) { 87 if (buf) {
83 buf->count++; 88 buf->count++;
84 if (buf->blocknr != blocknr) 89 goto test;
85 BUG();
86 if (buf->blocknr != buf->node.header.blocknr)
87 BUG();
88 return buf;
89 } 90 }
90 buf = alloc_tree_block(root, blocknr); 91 buf = alloc_tree_block(root, blocknr);
91 if (!buf) 92 if (!buf)
@@ -95,8 +96,11 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr)
95 free(buf); 96 free(buf);
96 return NULL; 97 return NULL;
97 } 98 }
99test:
98 if (buf->blocknr != buf->node.header.blocknr) 100 if (buf->blocknr != buf->node.header.blocknr)
99 BUG(); 101 BUG();
102 if (root->node && buf->node.header.parentid != root->node->node.header.parentid)
103 BUG();
100 return buf; 104 return buf;
101} 105}
102 106
@@ -111,36 +115,30 @@ int write_tree_block(struct ctree_root *root, struct tree_buffer *buf)
111 ret = pwrite(root->fp, &buf->node, CTREE_BLOCKSIZE, offset); 115 ret = pwrite(root->fp, &buf->node, CTREE_BLOCKSIZE, offset);
112 if (ret != CTREE_BLOCKSIZE) 116 if (ret != CTREE_BLOCKSIZE)
113 return ret; 117 return ret;
114 if (buf == root->node)
115 return update_root_block(root);
116 return 0; 118 return 0;
117} 119}
118 120
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, 121static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root,
125 struct ctree_root_info *info, int fp) 122 struct ctree_root_info *info, int fp)
126{ 123{
124 INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL);
127 root->fp = fp; 125 root->fp = fp;
126 root->node = NULL;
128 root->node = read_tree_block(root, info->tree_root); 127 root->node = read_tree_block(root, info->tree_root);
129 root->extent_root = extent_root; 128 root->extent_root = extent_root;
130 memcpy(&root->ai1, &info->alloc_extent, sizeof(info->alloc_extent)); 129 memcpy(&root->ai1, &info->alloc_extent, sizeof(info->alloc_extent));
131 memcpy(&root->ai2, &info->reserve_extent, sizeof(info->reserve_extent)); 130 memcpy(&root->ai2, &info->reserve_extent, sizeof(info->reserve_extent));
132 root->alloc_extent = &root->ai1; 131 root->alloc_extent = &root->ai1;
133 root->reserve_extent = &root->ai2; 132 root->reserve_extent = &root->ai2;
134 INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); 133 printf("setup done reading root %p, used %lu available %lu\n", root, root->alloc_extent->num_used, root->alloc_extent->num_blocks);
135 printf("setup done reading root %p, used %lu\n", root, root->alloc_extent->num_used); 134 printf("setup done reading root %p, reserve used %lu available %lu\n", root, root->reserve_extent->num_used, root->reserve_extent->num_blocks);
136 return 0; 135 return 0;
137} 136}
138 137
139struct ctree_root *open_ctree(char *filename) 138struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
140{ 139{
141 struct ctree_root *root = malloc(sizeof(struct ctree_root)); 140 struct ctree_root *root = malloc(sizeof(struct ctree_root));
142 struct ctree_root *extent_root = malloc(sizeof(struct ctree_root)); 141 struct ctree_root *extent_root = malloc(sizeof(struct ctree_root));
143 struct ctree_super_block super;
144 int fp; 142 int fp;
145 int ret; 143 int ret;
146 144
@@ -149,48 +147,61 @@ struct ctree_root *open_ctree(char *filename)
149 free(root); 147 free(root);
150 return NULL; 148 return NULL;
151 } 149 }
152 ret = pread(fp, &super, sizeof(struct ctree_super_block), 150 ret = pread(fp, super, sizeof(struct ctree_super_block),
153 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); 151 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
154 if (ret == 0) { 152 if (ret == 0) {
155 ret = mkfs(fp); 153 ret = mkfs(fp);
156 if (ret) 154 if (ret)
157 return NULL; 155 return NULL;
158 ret = pread(fp, &super, sizeof(struct ctree_super_block), 156 ret = pread(fp, super, sizeof(struct ctree_super_block),
159 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); 157 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
160 if (ret != sizeof(struct ctree_super_block)) 158 if (ret != sizeof(struct ctree_super_block))
161 return NULL; 159 return NULL;
162 } 160 }
163 BUG_ON(ret < 0); 161 BUG_ON(ret < 0);
164 __setup_root(root, extent_root, &super.root_info, fp); 162 __setup_root(root, extent_root, &super->root_info, fp);
165 __setup_root(extent_root, extent_root, &super.extent_info, fp); 163 __setup_root(extent_root, extent_root, &super->extent_info, fp);
166 return root; 164 return root;
167} 165}
168 166
169int close_ctree(struct ctree_root *root) 167static int __update_root(struct ctree_root *root, struct ctree_root_info *info)
170{ 168{
171 close(root->fp); 169 info->tree_root = root->node->blocknr;
172 if (root->node) 170 memcpy(&info->alloc_extent, root->alloc_extent, sizeof(struct alloc_extent));
173 tree_block_release(root, root->node); 171 memcpy(&info->reserve_extent, root->reserve_extent, sizeof(struct alloc_extent));
174 free(root);
175 printf("on close %d blocks are allocated\n", allocated_blocks);
176 return 0; 172 return 0;
177} 173}
178 174
179int update_root_block(struct ctree_root *root) 175int write_ctree_super(struct ctree_root *root, struct ctree_super_block *s)
180{ 176{
181 int ret; 177 int ret;
182 u64 root_block = root->node->blocknr; 178 __update_root(root, &s->root_info);
183 179 __update_root(root->extent_root, &s->extent_info);
184 ret = pwrite(root->fp, &root_block, sizeof(u64), 0); 180 ret = pwrite(root->fp, s, sizeof(*s), CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
185 if (ret != sizeof(u64)) 181 if (ret != sizeof(*s)) {
182 fprintf(stderr, "failed to write new super block err %d\n", ret);
186 return ret; 183 return ret;
184 }
185 return 0;
186}
187
188int close_ctree(struct ctree_root *root)
189{
190 close(root->fp);
191 if (root->node)
192 tree_block_release(root, root->node);
193 if (root->extent_root->node)
194 tree_block_release(root->extent_root, root->extent_root->node);
195 free(root);
196 printf("on close %d blocks are allocated\n", allocated_blocks);
187 return 0; 197 return 0;
188} 198}
189 199
190void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) 200void tree_block_release(struct ctree_root *root, struct tree_buffer *buf)
191{ 201{
192 return;
193 buf->count--; 202 buf->count--;
203 if (buf->count < 0)
204 BUG();
194 if (buf->count == 0) { 205 if (buf->count == 0) {
195 if (!radix_tree_lookup(&root->cache_radix, buf->blocknr)) 206 if (!radix_tree_lookup(&root->cache_radix, buf->blocknr))
196 BUG(); 207 BUG();