extent-tree.c (e089f05c18ab36ed5fa7e2319052e03ab800d518) extent-tree.c (9f5fae2fe6dc35b46bf56183f11398451851cb3f)
1#include <stdio.h>
2#include <stdlib.h>
3#include "kerncompat.h"
4#include "radix-tree.h"
5#include "ctree.h"
6#include "disk-io.h"
7#include "print-tree.h"
8#include "transaction.h"

--- 21 unchanged lines hidden (view full) ---

30 struct btrfs_path path;
31 int ret;
32 struct btrfs_key key;
33 struct btrfs_leaf *l;
34 struct btrfs_extent_item *item;
35 struct btrfs_key ins;
36 u32 refs;
37
1#include <stdio.h>
2#include <stdlib.h>
3#include "kerncompat.h"
4#include "radix-tree.h"
5#include "ctree.h"
6#include "disk-io.h"
7#include "print-tree.h"
8#include "transaction.h"

--- 21 unchanged lines hidden (view full) ---

30 struct btrfs_path path;
31 int ret;
32 struct btrfs_key key;
33 struct btrfs_leaf *l;
34 struct btrfs_extent_item *item;
35 struct btrfs_key ins;
36 u32 refs;
37
38 find_free_extent(trans, root->extent_root, 0, 0, (u64)-1, &ins);
38 find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1,
39 &ins);
39 btrfs_init_path(&path);
40 key.objectid = blocknr;
41 key.flags = 0;
42 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
43 key.offset = 1;
40 btrfs_init_path(&path);
41 key.objectid = blocknr;
42 key.flags = 0;
43 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
44 key.offset = 1;
44 ret = btrfs_search_slot(trans, root->extent_root, &key, &path, 0, 1);
45 ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, &path,
46 0, 1);
45 if (ret != 0)
46 BUG();
47 BUG_ON(ret != 0);
48 l = &path.nodes[0]->leaf;
49 item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item);
50 refs = btrfs_extent_refs(item);
51 btrfs_set_extent_refs(item, refs + 1);
52
53 BUG_ON(list_empty(&path.nodes[0]->dirty));
47 if (ret != 0)
48 BUG();
49 BUG_ON(ret != 0);
50 l = &path.nodes[0]->leaf;
51 item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item);
52 refs = btrfs_extent_refs(item);
53 btrfs_set_extent_refs(item, refs + 1);
54
55 BUG_ON(list_empty(&path.nodes[0]->dirty));
54 btrfs_release_path(root->extent_root, &path);
55 finish_current_insert(trans, root->extent_root);
56 run_pending(trans, root->extent_root);
56 btrfs_release_path(root->fs_info->extent_root, &path);
57 finish_current_insert(trans, root->fs_info->extent_root);
58 run_pending(trans, root->fs_info->extent_root);
57 return 0;
58}
59
60static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
61 *root, u64 blocknr, u32 *refs)
62{
63 struct btrfs_path path;
64 int ret;
65 struct btrfs_key key;
66 struct btrfs_leaf *l;
67 struct btrfs_extent_item *item;
68 btrfs_init_path(&path);
69 key.objectid = blocknr;
70 key.offset = 1;
71 key.flags = 0;
72 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
59 return 0;
60}
61
62static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
63 *root, u64 blocknr, u32 *refs)
64{
65 struct btrfs_path path;
66 int ret;
67 struct btrfs_key key;
68 struct btrfs_leaf *l;
69 struct btrfs_extent_item *item;
70 btrfs_init_path(&path);
71 key.objectid = blocknr;
72 key.offset = 1;
73 key.flags = 0;
74 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
73 ret = btrfs_search_slot(trans, root->extent_root, &key, &path, 0, 0);
75 ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, &path,
76 0, 0);
74 if (ret != 0)
75 BUG();
76 l = &path.nodes[0]->leaf;
77 item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item);
78 *refs = btrfs_extent_refs(item);
77 if (ret != 0)
78 BUG();
79 l = &path.nodes[0]->leaf;
80 item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item);
81 *refs = btrfs_extent_refs(item);
79 btrfs_release_path(root->extent_root, &path);
82 btrfs_release_path(root->fs_info->extent_root, &path);
80 return 0;
81}
82
83int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
84 struct btrfs_buffer *buf)
85{
86 u64 blocknr;
87 int i;

--- 14 unchanged lines hidden (view full) ---

102 btrfs_root *root)
103{
104 unsigned long gang[8];
105 u64 first = 0;
106 int ret;
107 int i;
108
109 while(1) {
83 return 0;
84}
85
86int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
87 struct btrfs_buffer *buf)
88{
89 u64 blocknr;
90 int i;

--- 14 unchanged lines hidden (view full) ---

105 btrfs_root *root)
106{
107 unsigned long gang[8];
108 u64 first = 0;
109 int ret;
110 int i;
111
112 while(1) {
110 ret = radix_tree_gang_lookup(&root->pinned_radix,
111 (void **)gang, 0,
112 ARRAY_SIZE(gang));
113 ret = radix_tree_gang_lookup(&root->fs_info->pinned_radix,
114 (void **)gang, 0,
115 ARRAY_SIZE(gang));
113 if (!ret)
114 break;
115 if (!first)
116 first = gang[0];
117 for (i = 0; i < ret; i++) {
116 if (!ret)
117 break;
118 if (!first)
119 first = gang[0];
120 for (i = 0; i < ret; i++) {
118 radix_tree_delete(&root->pinned_radix, gang[i]);
121 radix_tree_delete(&root->fs_info->pinned_radix,
122 gang[i]);
119 }
120 }
123 }
124 }
121 root->last_insert.objectid = first;
122 root->last_insert.offset = 0;
125 root->fs_info->last_insert.objectid = first;
126 root->fs_info->last_insert.offset = 0;
123 return 0;
124}
125
126static int finish_current_insert(struct btrfs_trans_handle *trans, struct
127 btrfs_root *extent_root)
128{
129 struct btrfs_key ins;
130 struct btrfs_extent_item extent_item;
131 int i;
132 int ret;
133
134 btrfs_set_extent_refs(&extent_item, 1);
135 btrfs_set_extent_owner(&extent_item,
136 btrfs_header_parentid(&extent_root->node->node.header));
137 ins.offset = 1;
138 ins.flags = 0;
139 btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY);
140
127 return 0;
128}
129
130static int finish_current_insert(struct btrfs_trans_handle *trans, struct
131 btrfs_root *extent_root)
132{
133 struct btrfs_key ins;
134 struct btrfs_extent_item extent_item;
135 int i;
136 int ret;
137
138 btrfs_set_extent_refs(&extent_item, 1);
139 btrfs_set_extent_owner(&extent_item,
140 btrfs_header_parentid(&extent_root->node->node.header));
141 ins.offset = 1;
142 ins.flags = 0;
143 btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY);
144
141 for (i = 0; i < extent_root->current_insert.flags; i++) {
142 ins.objectid = extent_root->current_insert.objectid + i;
145 for (i = 0; i < extent_root->fs_info->current_insert.flags; i++) {
146 ins.objectid = extent_root->fs_info->current_insert.objectid +
147 i;
143 ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item,
144 sizeof(extent_item));
145 BUG_ON(ret);
146 }
148 ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item,
149 sizeof(extent_item));
150 BUG_ON(ret);
151 }
147 extent_root->current_insert.offset = 0;
152 extent_root->fs_info->current_insert.offset = 0;
148 return 0;
149}
150
151/*
152 * remove an extent from the root, returns 0 on success
153 */
154static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
155 *root, u64 blocknr, u64 num_blocks, int pin)
156{
157 struct btrfs_path path;
158 struct btrfs_key key;
153 return 0;
154}
155
156/*
157 * remove an extent from the root, returns 0 on success
158 */
159static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
160 *root, u64 blocknr, u64 num_blocks, int pin)
161{
162 struct btrfs_path path;
163 struct btrfs_key key;
159 struct btrfs_root *extent_root = root->extent_root;
164 struct btrfs_root *extent_root = root->fs_info->extent_root;
160 int ret;
161 struct btrfs_extent_item *ei;
162 struct btrfs_key ins;
163 u32 refs;
164
165 BUG_ON(pin && num_blocks != 1);
166 key.objectid = blocknr;
167 key.flags = 0;

--- 13 unchanged lines hidden (view full) ---

181 struct btrfs_extent_item);
182 BUG_ON(ei->refs == 0);
183 refs = btrfs_extent_refs(ei) - 1;
184 btrfs_set_extent_refs(ei, refs);
185 if (refs == 0) {
186 if (pin) {
187 int err;
188 radix_tree_preload(GFP_KERNEL);
165 int ret;
166 struct btrfs_extent_item *ei;
167 struct btrfs_key ins;
168 u32 refs;
169
170 BUG_ON(pin && num_blocks != 1);
171 key.objectid = blocknr;
172 key.flags = 0;

--- 13 unchanged lines hidden (view full) ---

186 struct btrfs_extent_item);
187 BUG_ON(ei->refs == 0);
188 refs = btrfs_extent_refs(ei) - 1;
189 btrfs_set_extent_refs(ei, refs);
190 if (refs == 0) {
191 if (pin) {
192 int err;
193 radix_tree_preload(GFP_KERNEL);
189 err = radix_tree_insert(&extent_root->pinned_radix,
190 blocknr, (void *)blocknr);
194 err = radix_tree_insert(
195 &extent_root->fs_info->pinned_radix,
196 blocknr, (void *)blocknr);
191 BUG_ON(err);
192 radix_tree_preload_end();
193 }
194 ret = btrfs_del_item(trans, extent_root, &path);
197 BUG_ON(err);
198 radix_tree_preload_end();
199 }
200 ret = btrfs_del_item(trans, extent_root, &path);
195 if (!pin && extent_root->last_insert.objectid > blocknr)
196 extent_root->last_insert.objectid = blocknr;
201 if (!pin && extent_root->fs_info->last_insert.objectid >
202 blocknr)
203 extent_root->fs_info->last_insert.objectid = blocknr;
197 if (ret)
198 BUG();
199 }
200 btrfs_release_path(extent_root, &path);
201 finish_current_insert(trans, extent_root);
202 return ret;
203}
204

--- 4 unchanged lines hidden (view full) ---

209static int del_pending_extents(struct btrfs_trans_handle *trans, struct
210 btrfs_root *extent_root)
211{
212 int ret;
213 struct btrfs_buffer *gang[4];
214 int i;
215
216 while(1) {
204 if (ret)
205 BUG();
206 }
207 btrfs_release_path(extent_root, &path);
208 finish_current_insert(trans, extent_root);
209 return ret;
210}
211

--- 4 unchanged lines hidden (view full) ---

216static int del_pending_extents(struct btrfs_trans_handle *trans, struct
217 btrfs_root *extent_root)
218{
219 int ret;
220 struct btrfs_buffer *gang[4];
221 int i;
222
223 while(1) {
217 ret = radix_tree_gang_lookup_tag(&extent_root->cache_radix,
218 (void **)gang, 0,
219 ARRAY_SIZE(gang),
220 CTREE_EXTENT_PENDING_DEL);
224 ret = radix_tree_gang_lookup_tag(
225 &extent_root->fs_info->cache_radix,
226 (void **)gang, 0,
227 ARRAY_SIZE(gang),
228 CTREE_EXTENT_PENDING_DEL);
221 if (!ret)
222 break;
223 for (i = 0; i < ret; i++) {
224 ret = __free_extent(trans, extent_root,
225 gang[i]->blocknr, 1, 1);
229 if (!ret)
230 break;
231 for (i = 0; i < ret; i++) {
232 ret = __free_extent(trans, extent_root,
233 gang[i]->blocknr, 1, 1);
226 radix_tree_tag_clear(&extent_root->cache_radix,
227 gang[i]->blocknr,
228 CTREE_EXTENT_PENDING_DEL);
234 radix_tree_tag_clear(&extent_root->fs_info->cache_radix,
235 gang[i]->blocknr,
236 CTREE_EXTENT_PENDING_DEL);
229 btrfs_block_release(extent_root, gang[i]);
230 }
231 }
232 return 0;
233}
234
235static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root
236 *extent_root)
237{
237 btrfs_block_release(extent_root, gang[i]);
238 }
239 }
240 return 0;
241}
242
243static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root
244 *extent_root)
245{
238 while(radix_tree_tagged(&extent_root->cache_radix,
239 CTREE_EXTENT_PENDING_DEL))
246 while(radix_tree_tagged(&extent_root->fs_info->cache_radix,
247 CTREE_EXTENT_PENDING_DEL))
240 del_pending_extents(trans, extent_root);
241 return 0;
242}
243
244
245/*
246 * remove an extent from the root, returns 0 on success
247 */
248int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
249 *root, u64 blocknr, u64 num_blocks, int pin)
250{
248 del_pending_extents(trans, extent_root);
249 return 0;
250}
251
252
253/*
254 * remove an extent from the root, returns 0 on success
255 */
256int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
257 *root, u64 blocknr, u64 num_blocks, int pin)
258{
251 struct btrfs_root *extent_root = root->extent_root;
259 struct btrfs_root *extent_root = root->fs_info->extent_root;
252 struct btrfs_buffer *t;
253 int pending_ret;
254 int ret;
255
256 if (root == extent_root) {
257 t = find_tree_block(root, blocknr);
260 struct btrfs_buffer *t;
261 int pending_ret;
262 int ret;
263
264 if (root == extent_root) {
265 t = find_tree_block(root, blocknr);
258 radix_tree_tag_set(&root->cache_radix, blocknr,
266 radix_tree_tag_set(&root->fs_info->cache_radix, blocknr,
259 CTREE_EXTENT_PENDING_DEL);
260 return 0;
261 }
262 ret = __free_extent(trans, root, blocknr, num_blocks, pin);
267 CTREE_EXTENT_PENDING_DEL);
268 return 0;
269 }
270 ret = __free_extent(trans, root, blocknr, num_blocks, pin);
263 pending_ret = run_pending(trans, root->extent_root);
271 pending_ret = run_pending(trans, root->fs_info->extent_root);
264 return ret ? ret : pending_ret;
265}
266
267/*
268 * walks the btree of allocated extents and find a hole of a given size.
269 * The key ins is changed to record the hole:
270 * ins->objectid == block start
271 * ins->flags = BTRFS_EXTENT_ITEM_KEY

--- 8 unchanged lines hidden (view full) ---

280 struct btrfs_key key;
281 int ret;
282 u64 hole_size = 0;
283 int slot = 0;
284 u64 last_block;
285 u64 test_block;
286 int start_found;
287 struct btrfs_leaf *l;
272 return ret ? ret : pending_ret;
273}
274
275/*
276 * walks the btree of allocated extents and find a hole of a given size.
277 * The key ins is changed to record the hole:
278 * ins->objectid == block start
279 * ins->flags = BTRFS_EXTENT_ITEM_KEY

--- 8 unchanged lines hidden (view full) ---

288 struct btrfs_key key;
289 int ret;
290 u64 hole_size = 0;
291 int slot = 0;
292 u64 last_block;
293 u64 test_block;
294 int start_found;
295 struct btrfs_leaf *l;
288 struct btrfs_root * root = orig_root->extent_root;
296 struct btrfs_root * root = orig_root->fs_info->extent_root;
289 int total_needed = num_blocks;
290
291 total_needed += (btrfs_header_level(&root->node->node.header) + 1) * 3;
297 int total_needed = num_blocks;
298
299 total_needed += (btrfs_header_level(&root->node->node.header) + 1) * 3;
292 if (root->last_insert.objectid > search_start)
293 search_start = root->last_insert.objectid;
300 if (root->fs_info->last_insert.objectid > search_start)
301 search_start = root->fs_info->last_insert.objectid;
294
295 ins->flags = 0;
296 btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
297
298check_failed:
299 btrfs_init_path(&path);
300 ins->objectid = search_start;
301 ins->offset = 0;

--- 46 unchanged lines hidden (view full) ---

348check_pending:
349 /* we have to make sure we didn't find an extent that has already
350 * been allocated by the map tree or the original allocation
351 */
352 btrfs_release_path(root, &path);
353 BUG_ON(ins->objectid < search_start);
354 for (test_block = ins->objectid;
355 test_block < ins->objectid + total_needed; test_block++) {
302
303 ins->flags = 0;
304 btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
305
306check_failed:
307 btrfs_init_path(&path);
308 ins->objectid = search_start;
309 ins->offset = 0;

--- 46 unchanged lines hidden (view full) ---

356check_pending:
357 /* we have to make sure we didn't find an extent that has already
358 * been allocated by the map tree or the original allocation
359 */
360 btrfs_release_path(root, &path);
361 BUG_ON(ins->objectid < search_start);
362 for (test_block = ins->objectid;
363 test_block < ins->objectid + total_needed; test_block++) {
356 if (radix_tree_lookup(&root->pinned_radix, test_block)) {
364 if (radix_tree_lookup(&root->fs_info->pinned_radix,
365 test_block)) {
357 search_start = test_block + 1;
358 goto check_failed;
359 }
360 }
366 search_start = test_block + 1;
367 goto check_failed;
368 }
369 }
361 BUG_ON(root->current_insert.offset);
362 root->current_insert.offset = total_needed - num_blocks;
363 root->current_insert.objectid = ins->objectid + num_blocks;
364 root->current_insert.flags = 0;
365 root->last_insert.objectid = ins->objectid;
370 BUG_ON(root->fs_info->current_insert.offset);
371 root->fs_info->current_insert.offset = total_needed - num_blocks;
372 root->fs_info->current_insert.objectid = ins->objectid + num_blocks;
373 root->fs_info->current_insert.flags = 0;
374 root->fs_info->last_insert.objectid = ins->objectid;
366 ins->offset = num_blocks;
367 return 0;
368error:
369 btrfs_release_path(root, &path);
370 return ret;
371}
372
373/*

--- 4 unchanged lines hidden (view full) ---

378 * returns 0 if everything worked, non-zero otherwise.
379 */
380static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
381 *root, u64 num_blocks, u64 search_start, u64
382 search_end, u64 owner, struct btrfs_key *ins)
383{
384 int ret;
385 int pending_ret;
375 ins->offset = num_blocks;
376 return 0;
377error:
378 btrfs_release_path(root, &path);
379 return ret;
380}
381
382/*

--- 4 unchanged lines hidden (view full) ---

387 * returns 0 if everything worked, non-zero otherwise.
388 */
389static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
390 *root, u64 num_blocks, u64 search_start, u64
391 search_end, u64 owner, struct btrfs_key *ins)
392{
393 int ret;
394 int pending_ret;
386 struct btrfs_root *extent_root = root->extent_root;
395 struct btrfs_root *extent_root = root->fs_info->extent_root;
387 struct btrfs_extent_item extent_item;
388
389 btrfs_set_extent_refs(&extent_item, 1);
390 btrfs_set_extent_owner(&extent_item, owner);
391
392 if (root == extent_root) {
396 struct btrfs_extent_item extent_item;
397
398 btrfs_set_extent_refs(&extent_item, 1);
399 btrfs_set_extent_owner(&extent_item, owner);
400
401 if (root == extent_root) {
393 BUG_ON(extent_root->current_insert.offset == 0);
402 BUG_ON(extent_root->fs_info->current_insert.offset == 0);
394 BUG_ON(num_blocks != 1);
403 BUG_ON(num_blocks != 1);
395 BUG_ON(extent_root->current_insert.flags ==
396 extent_root->current_insert.offset);
404 BUG_ON(extent_root->fs_info->current_insert.flags ==
405 extent_root->fs_info->current_insert.offset);
397 ins->offset = 1;
406 ins->offset = 1;
398 ins->objectid = extent_root->current_insert.objectid +
399 extent_root->current_insert.flags++;
407 ins->objectid = extent_root->fs_info->current_insert.objectid +
408 extent_root->fs_info->current_insert.flags++;
400 return 0;
401 }
402 ret = find_free_extent(trans, root, num_blocks, search_start,
403 search_end, ins);
404 if (ret)
405 return ret;
406
407 ret = btrfs_insert_item(trans, extent_root, ins, &extent_item,

--- 158 unchanged lines hidden ---
409 return 0;
410 }
411 ret = find_free_extent(trans, root, num_blocks, search_start,
412 search_end, ins);
413 if (ret)
414 return ret;
415
416 ret = btrfs_insert_item(trans, extent_root, ins, &extent_item,

--- 158 unchanged lines hidden ---