Btrfs: pin freed blocks from the FS tree too
[linux-2.6-block.git] / fs / btrfs / disk-io.c
CommitLineData
eb60ceac
CM
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
13static int allocated_blocks = 0;
ed2ff2cb 14int cache_max = 10000;
eb60ceac 15
234b63a0 16static int check_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
eb60ceac 17{
7518a238 18 if (buf->blocknr != btrfs_header_blocknr(&buf->node.header))
9a8dd150 19 BUG();
7518a238
CM
20 if (root->node && btrfs_header_parentid(&buf->node.header) !=
21 btrfs_header_parentid(&root->node->node.header))
9a8dd150
CM
22 BUG();
23 return 0;
eb60ceac
CM
24}
25
234b63a0 26static int free_some_buffers(struct btrfs_root *root)
ed2ff2cb
CM
27{
28 struct list_head *node, *next;
234b63a0 29 struct btrfs_buffer *b;
ed2ff2cb
CM
30 if (root->cache_size < cache_max)
31 return 0;
32 list_for_each_safe(node, next, &root->cache) {
234b63a0 33 b = list_entry(node, struct btrfs_buffer, cache);
ed2ff2cb
CM
34 if (b->count == 1) {
35 BUG_ON(!list_empty(&b->dirty));
36 list_del_init(&b->cache);
234b63a0 37 btrfs_block_release(root, b);
ed2ff2cb 38 if (root->cache_size < cache_max)
77ce6846 39 break;
ed2ff2cb
CM
40 }
41 }
42 return 0;
43}
44
234b63a0 45struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr)
eb60ceac 46{
234b63a0 47 struct btrfs_buffer *buf;
eb60ceac 48 int ret;
123abc88
CM
49
50 buf = malloc(sizeof(struct btrfs_buffer) + root->blocksize);
eb60ceac
CM
51 if (!buf)
52 return buf;
53 allocated_blocks++;
54 buf->blocknr = blocknr;
ed2ff2cb
CM
55 buf->count = 2;
56 INIT_LIST_HEAD(&buf->dirty);
57 free_some_buffers(root);
eb60ceac
CM
58 radix_tree_preload(GFP_KERNEL);
59 ret = radix_tree_insert(&root->cache_radix, blocknr, buf);
60 radix_tree_preload_end();
ed2ff2cb
CM
61 list_add_tail(&buf->cache, &root->cache);
62 root->cache_size++;
eb60ceac
CM
63 if (ret) {
64 free(buf);
65 return NULL;
66 }
67 return buf;
68}
69
234b63a0 70struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr)
eb60ceac 71{
234b63a0 72 struct btrfs_buffer *buf;
9a8dd150
CM
73 buf = radix_tree_lookup(&root->cache_radix, blocknr);
74 if (buf) {
75 buf->count++;
76 } else {
77 buf = alloc_tree_block(root, blocknr);
78 if (!buf) {
79 BUG();
80 return NULL;
81 }
eb60ceac 82 }
eb60ceac
CM
83 return buf;
84}
85
234b63a0 86struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr)
eb60ceac 87{
123abc88 88 loff_t offset = blocknr * root->blocksize;
234b63a0 89 struct btrfs_buffer *buf;
eb60ceac
CM
90 int ret;
91
92 buf = radix_tree_lookup(&root->cache_radix, blocknr);
93 if (buf) {
94 buf->count++;
9a8dd150
CM
95 } else {
96 buf = alloc_tree_block(root, blocknr);
97 if (!buf)
98 return NULL;
123abc88
CM
99 ret = pread(root->fp, &buf->node, root->blocksize, offset);
100 if (ret != root->blocksize) {
9a8dd150
CM
101 free(buf);
102 return NULL;
103 }
eb60ceac 104 }
9a8dd150 105 if (check_tree_block(root, buf))
cfaa7295 106 BUG();
eb60ceac
CM
107 return buf;
108}
109
234b63a0 110int dirty_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
ed2ff2cb
CM
111{
112 if (!list_empty(&buf->dirty))
113 return 0;
114 list_add_tail(&buf->dirty, &root->trans);
115 buf->count++;
116 return 0;
117}
118
234b63a0 119int clean_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
ed2ff2cb
CM
120{
121 if (!list_empty(&buf->dirty)) {
122 list_del_init(&buf->dirty);
234b63a0 123 btrfs_block_release(root, buf);
ed2ff2cb
CM
124 }
125 return 0;
126}
127
234b63a0 128int write_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
eb60ceac
CM
129{
130 u64 blocknr = buf->blocknr;
123abc88 131 loff_t offset = blocknr * root->blocksize;
eb60ceac
CM
132 int ret;
133
7518a238 134 if (buf->blocknr != btrfs_header_blocknr(&buf->node.header))
eb60ceac 135 BUG();
123abc88
CM
136 ret = pwrite(root->fp, &buf->node, root->blocksize, offset);
137 if (ret != root->blocksize)
eb60ceac 138 return ret;
eb60ceac
CM
139 return 0;
140}
141
234b63a0 142static int __commit_transaction(struct btrfs_root *root)
ed2ff2cb 143{
234b63a0 144 struct btrfs_buffer *b;
ed2ff2cb
CM
145 int ret = 0;
146 int wret;
147 while(!list_empty(&root->trans)) {
234b63a0 148 b = list_entry(root->trans.next, struct btrfs_buffer, dirty);
ed2ff2cb
CM
149 list_del_init(&b->dirty);
150 wret = write_tree_block(root, b);
151 if (wret)
152 ret = wret;
234b63a0 153 btrfs_block_release(root, b);
ed2ff2cb
CM
154 }
155 return ret;
156}
157
3768f368
CM
158static int commit_extent_and_tree_roots(struct btrfs_root *tree_root,
159 struct btrfs_root *extent_root)
160{
161 int ret;
162 u64 old_extent_block;
163
164 while(1) {
165 old_extent_block = btrfs_root_blocknr(&extent_root->root_item);
166 if (old_extent_block == extent_root->node->blocknr)
167 break;
168 btrfs_set_root_blocknr(&extent_root->root_item,
169 extent_root->node->blocknr);
170 ret = btrfs_update_root(tree_root,
171 &extent_root->root_key,
172 &extent_root->root_item);
173 BUG_ON(ret);
174 }
175 __commit_transaction(extent_root);
176 __commit_transaction(tree_root);
177 return 0;
178}
179
234b63a0
CM
180int btrfs_commit_transaction(struct btrfs_root *root,
181 struct btrfs_super_block *s)
ed2ff2cb 182{
a28ec197 183 int ret = 0;
3768f368
CM
184 struct btrfs_buffer *snap = root->commit_root;
185 struct btrfs_key snap_key;
a28ec197 186
ed2ff2cb 187 ret = __commit_transaction(root);
ed2ff2cb 188 BUG_ON(ret);
3768f368
CM
189
190 if (root->commit_root == root->node)
191 return 0;
192
193 memcpy(&snap_key, &root->root_key, sizeof(snap_key));
194 root->root_key.offset++;
195
196 btrfs_set_root_blocknr(&root->root_item, root->node->blocknr);
197 ret = btrfs_insert_root(root->tree_root, &root->root_key,
198 &root->root_item);
199 BUG_ON(ret);
200
201 ret = commit_extent_and_tree_roots(root->tree_root, root->extent_root);
202 BUG_ON(ret);
203
a28ec197 204 write_ctree_super(root, s);
3768f368
CM
205 btrfs_finish_extent_commit(root->extent_root);
206 btrfs_finish_extent_commit(root->tree_root);
207
208 root->commit_root = root->node;
209 root->node->count++;
210 ret = btrfs_drop_snapshot(root, snap);
211 BUG_ON(ret);
212
213 ret = btrfs_del_root(root->tree_root, &snap_key);
214 BUG_ON(ret);
215
ed2ff2cb
CM
216 return ret;
217}
218
123abc88
CM
219static int __setup_root(struct btrfs_super_block *super,
220 struct btrfs_root *root, u64 objectid, int fp)
d97e63b6 221{
ed2ff2cb
CM
222 INIT_LIST_HEAD(&root->trans);
223 INIT_LIST_HEAD(&root->cache);
a28ec197 224 root->cache_size = 0;
d97e63b6 225 root->fp = fp;
cfaa7295 226 root->node = NULL;
a28ec197 227 root->commit_root = NULL;
123abc88
CM
228 root->blocksize = btrfs_super_blocksize(super);
229 root->ref_cows = 0;
a28ec197 230 memset(&root->current_insert, 0, sizeof(root->current_insert));
0579da42 231 memset(&root->last_insert, 0, sizeof(root->last_insert));
3768f368
CM
232 memset(&root->root_key, 0, sizeof(root->root_key));
233 memset(&root->root_item, 0, sizeof(root->root_item));
234 return 0;
235}
236
123abc88
CM
237static int find_and_setup_root(struct btrfs_super_block *super,
238 struct btrfs_root *tree_root, u64 objectid,
239 struct btrfs_root *root, int fp)
3768f368
CM
240{
241 int ret;
242
123abc88 243 __setup_root(super, root, objectid, fp);
3768f368
CM
244 ret = btrfs_find_last_root(tree_root, objectid,
245 &root->root_item, &root->root_key);
246 BUG_ON(ret);
247
248 root->node = read_tree_block(root,
249 btrfs_root_blocknr(&root->root_item));
3768f368 250 BUG_ON(!root->node);
d97e63b6
CM
251 return 0;
252}
253
234b63a0 254struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super)
eb60ceac 255{
234b63a0
CM
256 struct btrfs_root *root = malloc(sizeof(struct btrfs_root));
257 struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root));
3768f368 258 struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root));
eb60ceac 259 int fp;
eb60ceac
CM
260 int ret;
261
3768f368
CM
262 root->extent_root = extent_root;
263 root->tree_root = tree_root;
264
265 extent_root->extent_root = extent_root;
266 extent_root->tree_root = tree_root;
267
268 tree_root->extent_root = extent_root;
269 tree_root->tree_root = tree_root;
270
c673024a 271 fp = open(filename, O_CREAT | O_RDWR, 0600);
eb60ceac
CM
272 if (fp < 0) {
273 free(root);
274 return NULL;
275 }
9a8dd150 276 INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL);
a28ec197
CM
277 INIT_RADIX_TREE(&root->pinned_radix, GFP_KERNEL);
278 INIT_RADIX_TREE(&extent_root->pinned_radix, GFP_KERNEL);
9a8dd150 279 INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL);
3768f368
CM
280 INIT_RADIX_TREE(&tree_root->pinned_radix, GFP_KERNEL);
281 INIT_RADIX_TREE(&tree_root->cache_radix, GFP_KERNEL);
282
234b63a0 283 ret = pread(fp, super, sizeof(struct btrfs_super_block),
123abc88 284 BTRFS_SUPER_INFO_OFFSET);
3768f368 285 if (ret == 0 || btrfs_super_root(super) == 0) {
5c680ed6 286 printf("making new FS!\n");
123abc88 287 ret = mkfs(fp, 0, 1024);
d97e63b6
CM
288 if (ret)
289 return NULL;
234b63a0 290 ret = pread(fp, super, sizeof(struct btrfs_super_block),
123abc88 291 BTRFS_SUPER_INFO_OFFSET);
234b63a0 292 if (ret != sizeof(struct btrfs_super_block))
d97e63b6
CM
293 return NULL;
294 }
295 BUG_ON(ret < 0);
3768f368 296
123abc88 297 __setup_root(super, tree_root, BTRFS_ROOT_TREE_OBJECTID, fp);
3768f368
CM
298 tree_root->node = read_tree_block(tree_root, btrfs_super_root(super));
299 BUG_ON(!tree_root->node);
300
123abc88 301 ret = find_and_setup_root(super, tree_root, BTRFS_EXTENT_TREE_OBJECTID,
3768f368
CM
302 extent_root, fp);
303 BUG_ON(ret);
304
123abc88 305 ret = find_and_setup_root(super, tree_root, BTRFS_FS_TREE_OBJECTID,
3768f368
CM
306 root, fp);
307 BUG_ON(ret);
308
a28ec197
CM
309 root->commit_root = root->node;
310 root->node->count++;
3768f368 311 root->ref_cows = 1;
eb60ceac
CM
312 return root;
313}
314
234b63a0 315int write_ctree_super(struct btrfs_root *root, struct btrfs_super_block *s)
eb60ceac
CM
316{
317 int ret;
3768f368 318 btrfs_set_super_root(s, root->tree_root->node->blocknr);
234b63a0 319 ret = pwrite(root->fp, s, sizeof(*s),
123abc88 320 BTRFS_SUPER_INFO_OFFSET);
cfaa7295
CM
321 if (ret != sizeof(*s)) {
322 fprintf(stderr, "failed to write new super block err %d\n", ret);
eb60ceac 323 return ret;
cfaa7295
CM
324 }
325 return 0;
326}
327
234b63a0 328static int drop_cache(struct btrfs_root *root)
ed2ff2cb
CM
329{
330 while(!list_empty(&root->cache)) {
234b63a0
CM
331 struct btrfs_buffer *b = list_entry(root->cache.next,
332 struct btrfs_buffer, cache);
ed2ff2cb 333 list_del_init(&b->cache);
234b63a0 334 btrfs_block_release(root, b);
ed2ff2cb
CM
335 }
336 return 0;
337}
234b63a0 338int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s)
cfaa7295 339{
3768f368 340 int ret;
234b63a0 341 btrfs_commit_transaction(root, s);
3768f368
CM
342 ret = commit_extent_and_tree_roots(root->tree_root, root->extent_root);
343 BUG_ON(ret);
a28ec197 344 write_ctree_super(root, s);
ed2ff2cb 345 drop_cache(root->extent_root);
3768f368 346 drop_cache(root->tree_root);
ed2ff2cb
CM
347 drop_cache(root);
348 BUG_ON(!list_empty(&root->trans));
349 BUG_ON(!list_empty(&root->extent_root->trans));
3768f368 350 BUG_ON(!list_empty(&root->tree_root->trans));
ed2ff2cb 351
cfaa7295
CM
352 close(root->fp);
353 if (root->node)
234b63a0 354 btrfs_block_release(root, root->node);
cfaa7295 355 if (root->extent_root->node)
234b63a0 356 btrfs_block_release(root->extent_root, root->extent_root->node);
3768f368
CM
357 if (root->tree_root->node)
358 btrfs_block_release(root->tree_root, root->tree_root->node);
234b63a0 359 btrfs_block_release(root, root->commit_root);
cfaa7295
CM
360 free(root);
361 printf("on close %d blocks are allocated\n", allocated_blocks);
eb60ceac
CM
362 return 0;
363}
364
234b63a0 365void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf)
eb60ceac
CM
366{
367 buf->count--;
cfaa7295
CM
368 if (buf->count < 0)
369 BUG();
eb60ceac 370 if (buf->count == 0) {
02217ed2
CM
371 BUG_ON(!list_empty(&buf->cache));
372 BUG_ON(!list_empty(&buf->dirty));
eb60ceac
CM
373 if (!radix_tree_lookup(&root->cache_radix, buf->blocknr))
374 BUG();
375 radix_tree_delete(&root->cache_radix, buf->blocknr);
376 memset(buf, 0, sizeof(*buf));
377 free(buf);
378 BUG_ON(allocated_blocks == 0);
379 allocated_blocks--;
ed2ff2cb
CM
380 BUG_ON(root->cache_size == 0);
381 root->cache_size--;
eb60ceac
CM
382 }
383}
384