diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-02-23 08:38:36 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-02-23 08:38:36 -0500 |
commit | 9a8dd1502de6aa683ae46cf0397e9b6e636416fb (patch) | |
tree | 2422c1c316fe97014d8972431dbbe3f91a28853a /fs/btrfs/disk-io.c | |
parent | 5c680ed620c2b69cf751aecf1a5e03ce2c89c7f3 (diff) |
Btrfs: Block sized tree extents and extent deletion
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 | 90 |
1 files changed, 31 insertions, 59 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a696a4278ac5..14955e440773 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -12,33 +12,13 @@ | |||
12 | 12 | ||
13 | static int allocated_blocks = 0; | 13 | static int allocated_blocks = 0; |
14 | 14 | ||
15 | static int get_free_block(struct ctree_root *root, u64 *block) | 15 | static int check_tree_block(struct ctree_root *root, struct tree_buffer *buf) |
16 | { | 16 | { |
17 | struct stat st; | 17 | if (buf->blocknr != buf->node.header.blocknr) |
18 | int ret = 0; | 18 | BUG(); |
19 | 19 | if (root->node && buf->node.header.parentid != root->node->node.header.parentid) | |
20 | if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks) | 20 | BUG(); |
21 | return -1; | 21 | return 0; |
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 | } | ||
31 | st.st_size = 0; | ||
32 | ret = fstat(root->fp, &st); | ||
33 | if (st.st_size < (*block + 1) * CTREE_BLOCKSIZE) { | ||
34 | ret = ftruncate(root->fp, | ||
35 | (*block + 1) * CTREE_BLOCKSIZE); | ||
36 | if (ret) { | ||
37 | perror("ftruncate"); | ||
38 | exit(1); | ||
39 | } | ||
40 | } | ||
41 | return ret; | ||
42 | } | 22 | } |
43 | 23 | ||
44 | struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr) | 24 | struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr) |
@@ -61,22 +41,23 @@ struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr) | |||
61 | return buf; | 41 | return buf; |
62 | } | 42 | } |
63 | 43 | ||
64 | struct tree_buffer *alloc_free_block(struct ctree_root *root) | 44 | struct tree_buffer *find_tree_block(struct ctree_root *root, u64 blocknr) |
65 | { | 45 | { |
66 | u64 free_block; | 46 | struct tree_buffer *buf; |
67 | int ret; | 47 | buf = radix_tree_lookup(&root->cache_radix, blocknr); |
68 | struct tree_buffer * buf; | 48 | if (buf) { |
69 | ret = get_free_block(root, &free_block); | 49 | buf->count++; |
70 | if (ret) { | 50 | } else { |
71 | BUG(); | 51 | buf = alloc_tree_block(root, blocknr); |
72 | return NULL; | 52 | if (!buf) { |
53 | BUG(); | ||
54 | return NULL; | ||
55 | } | ||
73 | } | 56 | } |
74 | buf = alloc_tree_block(root, free_block); | ||
75 | if (!buf) | ||
76 | BUG(); | ||
77 | return buf; | 57 | return buf; |
78 | } | 58 | } |
79 | 59 | ||
60 | |||
80 | struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) | 61 | struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) |
81 | { | 62 | { |
82 | loff_t offset = blocknr * CTREE_BLOCKSIZE; | 63 | loff_t offset = blocknr * CTREE_BLOCKSIZE; |
@@ -86,20 +67,17 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) | |||
86 | buf = radix_tree_lookup(&root->cache_radix, blocknr); | 67 | buf = radix_tree_lookup(&root->cache_radix, blocknr); |
87 | if (buf) { | 68 | if (buf) { |
88 | buf->count++; | 69 | buf->count++; |
89 | goto test; | 70 | } else { |
90 | } | 71 | buf = alloc_tree_block(root, blocknr); |
91 | buf = alloc_tree_block(root, blocknr); | 72 | if (!buf) |
92 | if (!buf) | 73 | return NULL; |
93 | return NULL; | 74 | ret = pread(root->fp, &buf->node, CTREE_BLOCKSIZE, offset); |
94 | ret = pread(root->fp, &buf->node, CTREE_BLOCKSIZE, offset); | 75 | if (ret != CTREE_BLOCKSIZE) { |
95 | if (ret != CTREE_BLOCKSIZE) { | 76 | free(buf); |
96 | free(buf); | 77 | return NULL; |
97 | return NULL; | 78 | } |
98 | } | 79 | } |
99 | test: | 80 | if (check_tree_block(root, buf)) |
100 | if (buf->blocknr != buf->node.header.blocknr) | ||
101 | BUG(); | ||
102 | if (root->node && buf->node.header.parentid != root->node->node.header.parentid) | ||
103 | BUG(); | 81 | BUG(); |
104 | return buf; | 82 | return buf; |
105 | } | 83 | } |
@@ -121,17 +99,10 @@ int write_tree_block(struct ctree_root *root, struct tree_buffer *buf) | |||
121 | static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root, | 99 | static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root, |
122 | struct ctree_root_info *info, int fp) | 100 | struct ctree_root_info *info, int fp) |
123 | { | 101 | { |
124 | INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); | ||
125 | root->fp = fp; | 102 | root->fp = fp; |
126 | root->node = NULL; | 103 | root->node = NULL; |
127 | root->node = read_tree_block(root, info->tree_root); | 104 | root->node = read_tree_block(root, info->tree_root); |
128 | root->extent_root = extent_root; | 105 | root->extent_root = extent_root; |
129 | memcpy(&root->ai1, &info->alloc_extent, sizeof(info->alloc_extent)); | ||
130 | memcpy(&root->ai2, &info->reserve_extent, sizeof(info->reserve_extent)); | ||
131 | root->alloc_extent = &root->ai1; | ||
132 | root->reserve_extent = &root->ai2; | ||
133 | printf("setup done reading root %p, used %lu available %lu\n", root, root->alloc_extent->num_used, root->alloc_extent->num_blocks); | ||
134 | printf("setup done reading root %p, reserve used %lu available %lu\n", root, root->reserve_extent->num_used, root->reserve_extent->num_blocks); | ||
135 | return 0; | 106 | return 0; |
136 | } | 107 | } |
137 | 108 | ||
@@ -147,6 +118,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super) | |||
147 | free(root); | 118 | free(root); |
148 | return NULL; | 119 | return NULL; |
149 | } | 120 | } |
121 | INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); | ||
122 | INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL); | ||
150 | ret = pread(fp, super, sizeof(struct ctree_super_block), | 123 | ret = pread(fp, super, sizeof(struct ctree_super_block), |
151 | CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); | 124 | CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); |
152 | if (ret == 0 || super->root_info.tree_root == 0) { | 125 | if (ret == 0 || super->root_info.tree_root == 0) { |
@@ -168,8 +141,6 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super) | |||
168 | static int __update_root(struct ctree_root *root, struct ctree_root_info *info) | 141 | static int __update_root(struct ctree_root *root, struct ctree_root_info *info) |
169 | { | 142 | { |
170 | info->tree_root = root->node->blocknr; | 143 | info->tree_root = root->node->blocknr; |
171 | memcpy(&info->alloc_extent, root->alloc_extent, sizeof(struct alloc_extent)); | ||
172 | memcpy(&info->reserve_extent, root->reserve_extent, sizeof(struct alloc_extent)); | ||
173 | return 0; | 144 | return 0; |
174 | } | 145 | } |
175 | 146 | ||
@@ -201,6 +172,7 @@ int close_ctree(struct ctree_root *root) | |||
201 | void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) | 172 | void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) |
202 | { | 173 | { |
203 | buf->count--; | 174 | buf->count--; |
175 | write_tree_block(root, buf); | ||
204 | if (buf->count < 0) | 176 | if (buf->count < 0) |
205 | BUG(); | 177 | BUG(); |
206 | if (buf->count == 0) { | 178 | if (buf->count == 0) { |