extent-tree.c 28.1 KB
Newer Older
1
#include <linux/module.h>
2 3 4
#include "ctree.h"
#include "disk-io.h"
#include "print-tree.h"
5
#include "transaction.h"
6

7 8 9 10 11
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
			    *orig_root, u64 num_blocks, u64 search_start, u64
			    search_end, struct btrfs_key *ins);
static int finish_current_insert(struct btrfs_trans_handle *trans, struct
				 btrfs_root *extent_root);
C
Chris Mason 已提交
12 13
static int del_pending_extents(struct btrfs_trans_handle *trans, struct
			       btrfs_root *extent_root);
14

15 16 17
struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
						 struct btrfs_block_group_cache
						 *hint, int data)
C
Chris Mason 已提交
18 19
{
	struct btrfs_block_group_cache *cache[8];
20
	struct btrfs_block_group_cache *found_group = NULL;
C
Chris Mason 已提交
21 22
	struct btrfs_fs_info *info = root->fs_info;
	u64 used;
23 24
	u64 last = 0;
	u64 hint_last;
C
Chris Mason 已提交
25 26
	int i;
	int ret;
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
	int full_search = 0;
	if (hint) {
		used = btrfs_block_group_used(&hint->item);
		if (used < (hint->key.offset * 2) / 3) {
			return hint;
		}
		radix_tree_tag_clear(&info->block_group_radix,
				     hint->key.objectid + hint->key.offset - 1,
				     BTRFS_BLOCK_GROUP_AVAIL);
		last = hint->key.objectid + hint->key.offset;
		hint_last = last;
	} else {
		hint_last = 0;
		last = 0;
	}
C
Chris Mason 已提交
42 43 44 45
	while(1) {
		ret = radix_tree_gang_lookup_tag(&info->block_group_radix,
						 (void **)cache,
						 last, ARRAY_SIZE(cache),
46
						 BTRFS_BLOCK_GROUP_AVAIL);
C
Chris Mason 已提交
47 48 49 50
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
			used = btrfs_block_group_used(&cache[i]->item);
51
			if (used < (cache[i]->key.offset * 2) / 3) {
C
Chris Mason 已提交
52
				info->block_group_cache = cache[i];
53 54
				found_group = cache[i];
				goto found;
C
Chris Mason 已提交
55
			}
56 57 58 59
			radix_tree_tag_clear(&info->block_group_radix,
					   cache[i]->key.objectid +
					   cache[i]->key.offset - 1,
					   BTRFS_BLOCK_GROUP_AVAIL);
C
Chris Mason 已提交
60
			last = cache[i]->key.objectid +
61
				cache[i]->key.offset;
C
Chris Mason 已提交
62 63
		}
	}
64 65
	last = hint_last;
again:
C
Chris Mason 已提交
66 67 68 69 70 71 72 73
	while(1) {
		ret = radix_tree_gang_lookup(&info->block_group_radix,
						 (void **)cache,
						 last, ARRAY_SIZE(cache));
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
			used = btrfs_block_group_used(&cache[i]->item);
74
			if (used < cache[i]->key.offset) {
C
Chris Mason 已提交
75
				info->block_group_cache = cache[i];
76 77
				found_group = cache[i];
				goto found;
C
Chris Mason 已提交
78
			}
79 80 81 82
			radix_tree_tag_clear(&info->block_group_radix,
					   cache[i]->key.objectid +
					   cache[i]->key.offset - 1,
					   BTRFS_BLOCK_GROUP_AVAIL);
C
Chris Mason 已提交
83
			last = cache[i]->key.objectid +
84
				cache[i]->key.offset;
C
Chris Mason 已提交
85 86 87
		}
	}
	info->block_group_cache = NULL;
88 89 90 91 92 93 94 95 96 97 98 99
	if (!full_search) {
		last = 0;
		full_search = 1;
		goto again;
	}
found:
	if (!found_group) {
		ret = radix_tree_gang_lookup(&info->block_group_radix,
					     (void **)&found_group, 0, 1);
		BUG_ON(ret != 1);
	}
	return found_group;
C
Chris Mason 已提交
100 101
}

C
Chris Mason 已提交
102 103 104
int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
				struct btrfs_root *root,
				u64 blocknr, u64 num_blocks)
C
Chris Mason 已提交
105
{
106
	struct btrfs_path *path;
C
Chris Mason 已提交
107
	int ret;
C
Chris Mason 已提交
108
	struct btrfs_key key;
C
Chris Mason 已提交
109 110
	struct btrfs_leaf *l;
	struct btrfs_extent_item *item;
C
Chris Mason 已提交
111
	struct btrfs_key ins;
C
Chris Mason 已提交
112
	u32 refs;
C
Chris Mason 已提交
113

114 115
	find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1,
			 &ins);
116 117 118
	path = btrfs_alloc_path();
	BUG_ON(!path);
	btrfs_init_path(path);
C
Chris Mason 已提交
119 120
	key.objectid = blocknr;
	key.flags = 0;
121
	btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
122
	key.offset = num_blocks;
123
	ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path,
124
				0, 1);
125 126
	if (ret != 0) {
printk("can't find block %Lu %Lu\n", blocknr, num_blocks);
127
		BUG();
128
	}
C
Chris Mason 已提交
129
	BUG_ON(ret != 0);
130 131
	l = btrfs_buffer_leaf(path->nodes[0]);
	item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item);
C
Chris Mason 已提交
132 133
	refs = btrfs_extent_refs(item);
	btrfs_set_extent_refs(item, refs + 1);
134
	btrfs_mark_buffer_dirty(path->nodes[0]);
135

136 137
	btrfs_release_path(root->fs_info->extent_root, path);
	btrfs_free_path(path);
138
	finish_current_insert(trans, root->fs_info->extent_root);
C
Chris Mason 已提交
139
	del_pending_extents(trans, root->fs_info->extent_root);
C
Chris Mason 已提交
140 141 142
	return 0;
}

C
Chris Mason 已提交
143 144 145
static int lookup_extent_ref(struct btrfs_trans_handle *trans,
			     struct btrfs_root *root, u64 blocknr,
			     u64 num_blocks, u32 *refs)
146
{
147
	struct btrfs_path *path;
148
	int ret;
C
Chris Mason 已提交
149
	struct btrfs_key key;
C
Chris Mason 已提交
150 151
	struct btrfs_leaf *l;
	struct btrfs_extent_item *item;
152 153 154

	path = btrfs_alloc_path();
	btrfs_init_path(path);
155
	key.objectid = blocknr;
156
	key.offset = num_blocks;
157 158
	key.flags = 0;
	btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
159
	ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path,
160
				0, 0);
161 162
	if (ret != 0)
		BUG();
163 164
	l = btrfs_buffer_leaf(path->nodes[0]);
	item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item);
C
Chris Mason 已提交
165
	*refs = btrfs_extent_refs(item);
166 167
	btrfs_release_path(root->fs_info->extent_root, path);
	btrfs_free_path(path);
168 169 170
	return 0;
}

C
Chris Mason 已提交
171 172 173
int btrfs_inc_root_ref(struct btrfs_trans_handle *trans,
		       struct btrfs_root *root)
{
C
Chris Mason 已提交
174
	return btrfs_inc_extent_ref(trans, root, bh_blocknr(root->node), 1);
C
Chris Mason 已提交
175 176
}

177
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
C
Chris Mason 已提交
178
		  struct buffer_head *buf)
C
Chris Mason 已提交
179 180
{
	u64 blocknr;
C
Chris Mason 已提交
181
	struct btrfs_node *buf_node;
182 183 184
	struct btrfs_leaf *buf_leaf;
	struct btrfs_disk_key *key;
	struct btrfs_file_extent_item *fi;
C
Chris Mason 已提交
185
	int i;
186 187
	int leaf;
	int ret;
188

189
	if (!root->ref_cows)
190
		return 0;
C
Chris Mason 已提交
191
	buf_node = btrfs_buffer_node(buf);
192 193
	leaf = btrfs_is_leaf(buf_node);
	buf_leaf = btrfs_buffer_leaf(buf);
C
Chris Mason 已提交
194
	for (i = 0; i < btrfs_header_nritems(&buf_node->header); i++) {
195 196 197 198 199 200
		if (leaf) {
			key = &buf_leaf->items[i].key;
			if (btrfs_disk_key_type(key) != BTRFS_EXTENT_DATA_KEY)
				continue;
			fi = btrfs_item_ptr(buf_leaf, i,
					    struct btrfs_file_extent_item);
201 202 203
			if (btrfs_file_extent_type(fi) ==
			    BTRFS_FILE_EXTENT_INLINE)
				continue;
C
Chris Mason 已提交
204
			ret = btrfs_inc_extent_ref(trans, root,
205 206 207 208 209
				    btrfs_file_extent_disk_blocknr(fi),
				    btrfs_file_extent_disk_num_blocks(fi));
			BUG_ON(ret);
		} else {
			blocknr = btrfs_node_blockptr(buf_node, i);
C
Chris Mason 已提交
210
			ret = btrfs_inc_extent_ref(trans, root, blocknr, 1);
211 212
			BUG_ON(ret);
		}
C
Chris Mason 已提交
213 214 215 216
	}
	return 0;
}

C
Chris Mason 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
static int write_one_cache_group(struct btrfs_trans_handle *trans,
				 struct btrfs_root *root,
				 struct btrfs_path *path,
				 struct btrfs_block_group_cache *cache)
{
	int ret;
	int pending_ret;
	struct btrfs_root *extent_root = root->fs_info->extent_root;
	struct btrfs_block_group_item *bi;
	struct btrfs_key ins;

	find_free_extent(trans, extent_root, 0, 0, (u64)-1, &ins);
	ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1);
	BUG_ON(ret);
	bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
			    struct btrfs_block_group_item);
	memcpy(bi, &cache->item, sizeof(*bi));
	mark_buffer_dirty(path->nodes[0]);
	btrfs_release_path(extent_root, path);

	finish_current_insert(trans, extent_root);
	pending_ret = del_pending_extents(trans, extent_root);
	if (ret)
		return ret;
	if (pending_ret)
		return pending_ret;
	return 0;

}

int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
				    struct btrfs_root *root)
{
	struct btrfs_block_group_cache *cache[8];
	int ret;
	int err = 0;
	int werr = 0;
	struct radix_tree_root *radix = &root->fs_info->block_group_radix;
	int i;
	struct btrfs_path *path;

	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;

	while(1) {
		ret = radix_tree_gang_lookup_tag(radix, (void **)cache,
						 0, ARRAY_SIZE(cache),
						 BTRFS_BLOCK_GROUP_DIRTY);
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
			radix_tree_tag_clear(radix, cache[i]->key.objectid +
					     cache[i]->key.offset - 1,
					     BTRFS_BLOCK_GROUP_DIRTY);
			err = write_one_cache_group(trans, root,
						    path, cache[i]);
			if (err)
				werr = err;
276
			cache[i]->last_alloc = cache[i]->first_free;
C
Chris Mason 已提交
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
		}
	}
	btrfs_free_path(path);
	return werr;
}

static int update_block_group(struct btrfs_trans_handle *trans,
			      struct btrfs_root *root,
			      u64 blocknr, u64 num, int alloc)
{
	struct btrfs_block_group_cache *cache;
	struct btrfs_fs_info *info = root->fs_info;
	u64 total = num;
	u64 old_val;
	u64 block_in_group;
	int ret;
	while(total) {
		ret = radix_tree_gang_lookup(&info->block_group_radix,
					     (void **)&cache, blocknr, 1);
C
Chris Mason 已提交
296 297 298
		if (!ret) {
			printk(KERN_CRIT "blocknr %Lu lookup failed\n",
			       blocknr);
C
Chris Mason 已提交
299
			return -1;
C
Chris Mason 已提交
300
		}
C
Chris Mason 已提交
301 302 303 304 305 306 307 308 309 310
		block_in_group = blocknr - cache->key.objectid;
		WARN_ON(block_in_group > cache->key.offset);
		radix_tree_tag_set(&info->block_group_radix,
				   cache->key.objectid + cache->key.offset - 1,
				   BTRFS_BLOCK_GROUP_DIRTY);

		old_val = btrfs_block_group_used(&cache->item);
		num = min(total, cache->key.offset - block_in_group);
		total -= num;
		blocknr += num;
C
Chris Mason 已提交
311
		if (alloc) {
C
Chris Mason 已提交
312
			old_val += num;
C
Chris Mason 已提交
313 314 315
			if (blocknr > cache->last_alloc)
				cache->last_alloc = blocknr;
		} else {
C
Chris Mason 已提交
316
			old_val -= num;
C
Chris Mason 已提交
317 318 319
			if (blocknr < cache->first_free)
				cache->first_free = blocknr;
		}
C
Chris Mason 已提交
320 321 322 323 324
		btrfs_set_block_group_used(&cache->item, old_val);
	}
	return 0;
}

325 326
int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
			       btrfs_root *root)
327
{
C
Chris Mason 已提交
328
	unsigned long gang[8];
329
	u64 first = 0;
330 331
	int ret;
	int i;
C
Chris Mason 已提交
332
	struct radix_tree_root *pinned_radix = &root->fs_info->pinned_radix;
333 334

	while(1) {
C
Chris Mason 已提交
335 336
		ret = find_first_radix_bit(pinned_radix, gang,
					   ARRAY_SIZE(gang));
337 338
		if (!ret)
			break;
339
		if (!first)
C
Chris Mason 已提交
340
			first = gang[0];
341
		for (i = 0; i < ret; i++) {
C
Chris Mason 已提交
342
			clear_radix_bit(pinned_radix, gang[i]);
343
		}
344 345 346 347
	}
	return 0;
}

348 349
static int finish_current_insert(struct btrfs_trans_handle *trans, struct
				 btrfs_root *extent_root)
C
Chris Mason 已提交
350
{
C
Chris Mason 已提交
351
	struct btrfs_key ins;
C
Chris Mason 已提交
352
	struct btrfs_extent_item extent_item;
C
Chris Mason 已提交
353 354
	int i;
	int ret;
355 356
	u64 super_blocks_used;
	struct btrfs_fs_info *info = extent_root->fs_info;
C
Chris Mason 已提交
357

C
Chris Mason 已提交
358
	btrfs_set_extent_refs(&extent_item, 1);
C
Chris Mason 已提交
359 360
	ins.offset = 1;
	ins.flags = 0;
361
	btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY);
362
	btrfs_set_extent_owner(&extent_item, extent_root->root_key.objectid);
C
Chris Mason 已提交
363

364 365
	for (i = 0; i < extent_root->fs_info->extent_tree_insert_nr; i++) {
		ins.objectid = extent_root->fs_info->extent_tree_insert[i];
366 367 368
		super_blocks_used = btrfs_super_blocks_used(info->disk_super);
		btrfs_set_super_blocks_used(info->disk_super,
					    super_blocks_used + 1);
369 370
		ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item,
					sizeof(extent_item));
C
Chris Mason 已提交
371 372
		BUG_ON(ret);
	}
373 374
	extent_root->fs_info->extent_tree_insert_nr = 0;
	extent_root->fs_info->extent_tree_prealloc_nr = 0;
C
Chris Mason 已提交
375 376 377
	return 0;
}

C
Chris Mason 已提交
378
static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
C
Chris Mason 已提交
379 380
{
	int err;
C
Chris Mason 已提交
381
	struct btrfs_header *header;
C
Chris Mason 已提交
382 383
	struct buffer_head *bh;

C
Chris Mason 已提交
384
	if (!pending) {
385
		bh = btrfs_find_tree_block(root, blocknr);
C
Chris Mason 已提交
386 387 388 389 390 391 392 393 394 395
		if (bh) {
			if (buffer_uptodate(bh)) {
				u64 transid =
				    root->fs_info->running_transaction->transid;
				header = btrfs_buffer_header(bh);
				if (btrfs_header_generation(header) ==
				    transid) {
					btrfs_block_release(root, bh);
					return 0;
				}
C
Chris Mason 已提交
396
			}
C
Chris Mason 已提交
397
			btrfs_block_release(root, bh);
C
Chris Mason 已提交
398 399
		}
		err = set_radix_bit(&root->fs_info->pinned_radix, blocknr);
C
Chris Mason 已提交
400 401 402
	} else {
		err = set_radix_bit(&root->fs_info->pending_del_radix, blocknr);
	}
C
Chris Mason 已提交
403
	BUG_ON(err);
C
Chris Mason 已提交
404 405 406
	return 0;
}

407
/*
408
 * remove an extent from the root, returns 0 on success
409
 */
410
static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
C
Chris Mason 已提交
411
			 *root, u64 blocknr, u64 num_blocks, int pin)
412
{
413
	struct btrfs_path *path;
C
Chris Mason 已提交
414
	struct btrfs_key key;
415 416
	struct btrfs_fs_info *info = root->fs_info;
	struct btrfs_root *extent_root = info->extent_root;
417
	int ret;
C
Chris Mason 已提交
418
	struct btrfs_extent_item *ei;
C
Chris Mason 已提交
419
	struct btrfs_key ins;
C
Chris Mason 已提交
420
	u32 refs;
C
Chris Mason 已提交
421

422 423
	key.objectid = blocknr;
	key.flags = 0;
424
	btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
425 426
	key.offset = num_blocks;

427
	find_free_extent(trans, root, 0, 0, (u64)-1, &ins);
428 429 430
	path = btrfs_alloc_path();
	BUG_ON(!path);
	btrfs_init_path(path);
431

432
	ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1);
433
	if (ret) {
434
		printk("failed to find %Lu\n", key.objectid);
C
Chris Mason 已提交
435
		btrfs_print_tree(extent_root, extent_root->node);
436
		printk("failed to find %Lu\n", key.objectid);
437 438
		BUG();
	}
439
	ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
C
Chris Mason 已提交
440
			    struct btrfs_extent_item);
441
	BUG_ON(ei->refs == 0);
C
Chris Mason 已提交
442 443
	refs = btrfs_extent_refs(ei) - 1;
	btrfs_set_extent_refs(ei, refs);
444
	btrfs_mark_buffer_dirty(path->nodes[0]);
C
Chris Mason 已提交
445
	if (refs == 0) {
446
		u64 super_blocks_used;
C
Chris Mason 已提交
447 448

		if (pin) {
C
Chris Mason 已提交
449
			ret = pin_down_block(root, blocknr, 0);
C
Chris Mason 已提交
450 451 452
			BUG_ON(ret);
		}

453 454 455
		super_blocks_used = btrfs_super_blocks_used(info->disk_super);
		btrfs_set_super_blocks_used(info->disk_super,
					    super_blocks_used - num_blocks);
456
		ret = btrfs_del_item(trans, extent_root, path);
457 458
		if (ret)
			BUG();
C
Chris Mason 已提交
459 460
		ret = update_block_group(trans, root, blocknr, num_blocks, 0);
		BUG_ON(ret);
461
	}
462 463
	btrfs_release_path(extent_root, path);
	btrfs_free_path(path);
464
	finish_current_insert(trans, extent_root);
465 466 467 468 469 470 471
	return ret;
}

/*
 * find all the blocks marked as pending in the radix tree and remove
 * them from the extent map
 */
472 473
static int del_pending_extents(struct btrfs_trans_handle *trans, struct
			       btrfs_root *extent_root)
474 475
{
	int ret;
C
Chris Mason 已提交
476 477
	int wret;
	int err = 0;
C
Chris Mason 已提交
478
	unsigned long gang[4];
479
	int i;
C
Chris Mason 已提交
480 481 482 483 484
	struct radix_tree_root *pending_radix;
	struct radix_tree_root *pinned_radix;

	pending_radix = &extent_root->fs_info->pending_del_radix;
	pinned_radix = &extent_root->fs_info->pinned_radix;
485 486

	while(1) {
C
Chris Mason 已提交
487 488
		ret = find_first_radix_bit(pending_radix, gang,
					   ARRAY_SIZE(gang));
489 490 491
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
C
Chris Mason 已提交
492 493 494 495
			wret = set_radix_bit(pinned_radix, gang[i]);
			BUG_ON(wret);
			wret = clear_radix_bit(pending_radix, gang[i]);
			BUG_ON(wret);
496
			wret = __free_extent(trans, extent_root,
C
Chris Mason 已提交
497
					     gang[i], 1, 0);
C
Chris Mason 已提交
498 499
			if (wret)
				err = wret;
500 501
		}
	}
C
Chris Mason 已提交
502
	return err;
503 504 505 506 507
}

/*
 * remove an extent from the root, returns 0 on success
 */
508 509
int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, u64 blocknr, u64 num_blocks, int pin)
510
{
511
	struct btrfs_root *extent_root = root->fs_info->extent_root;
512 513
	int pending_ret;
	int ret;
514

515
	if (root == extent_root) {
C
Chris Mason 已提交
516
		pin_down_block(root, blocknr, 1);
517 518
		return 0;
	}
C
Chris Mason 已提交
519
	ret = __free_extent(trans, root, blocknr, num_blocks, pin);
C
Chris Mason 已提交
520
	pending_ret = del_pending_extents(trans, root->fs_info->extent_root);
521 522 523 524 525 526 527
	return ret ? ret : pending_ret;
}

/*
 * walks the btree of allocated extents and find a hole of a given size.
 * The key ins is changed to record the hole:
 * ins->objectid == block start
528
 * ins->flags = BTRFS_EXTENT_ITEM_KEY
529 530 531
 * ins->offset == number of blocks
 * Any available blocks before search_start are skipped.
 */
532 533 534
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
			    *orig_root, u64 num_blocks, u64 search_start, u64
			    search_end, struct btrfs_key *ins)
535
{
536
	struct btrfs_path *path;
C
Chris Mason 已提交
537
	struct btrfs_key key;
538 539 540
	int ret;
	u64 hole_size = 0;
	int slot = 0;
C
Chris Mason 已提交
541
	u64 last_block = 0;
C
Chris Mason 已提交
542
	u64 test_block;
543
	int start_found;
C
Chris Mason 已提交
544
	struct btrfs_leaf *l;
545
	struct btrfs_root * root = orig_root->fs_info->extent_root;
546
	struct btrfs_fs_info *info = root->fs_info;
547
	int total_needed = num_blocks;
548 549
	int total_found = 0;
	int fill_prealloc = 0;
C
Chris Mason 已提交
550
	int level;
551 552
	int update_block_group = 0;
	struct btrfs_block_group_cache *hint_block_group;
553

554 555 556 557
	path = btrfs_alloc_path();
	ins->flags = 0;
	btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);

C
Chris Mason 已提交
558
	level = btrfs_header_level(btrfs_buffer_header(root->node));
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
	/* find search start here */
	if (0 && search_start && num_blocks) {
		u64 used;
		ret = radix_tree_gang_lookup(&info->block_group_radix,
					     (void **)&hint_block_group,
					     search_start, 1);
		if (ret) {
			used = btrfs_block_group_used(&hint_block_group->item);
			if (used > (hint_block_group->key.offset * 9) / 10)
				search_start = 0;
			else if (search_start < hint_block_group->last_alloc)
				search_start = hint_block_group->last_alloc;
		} else {
			search_start = 0;
		}
	}
575 576 577
	if (num_blocks == 0) {
		fill_prealloc = 1;
		num_blocks = 1;
578
		total_needed = (min(level + 1, BTRFS_MAX_LEVEL) + 2) * 3;
579
	}
580 581 582 583 584 585 586 587
	if (1 || !search_start) {
		trans->block_group = btrfs_find_block_group(root,
							    trans->block_group,
							    0);
		if (trans->block_group->last_alloc > search_start)
			search_start = trans->block_group->last_alloc;
		update_block_group = 1;
	}
588
check_failed:
589
	btrfs_init_path(path);
590 591 592
	ins->objectid = search_start;
	ins->offset = 0;
	start_found = 0;
593
	ret = btrfs_search_slot(trans, root, ins, path, 0, 0);
C
Chris Mason 已提交
594 595
	if (ret < 0)
		goto error;
C
Chris Mason 已提交
596

597 598
	if (path->slots[0] > 0)
		path->slots[0]--;
599

600
	while (1) {
601 602
		l = btrfs_buffer_leaf(path->nodes[0]);
		slot = path->slots[0];
603
		if (slot >= btrfs_header_nritems(&l->header)) {
604 605 606 607
			if (fill_prealloc) {
				info->extent_tree_prealloc_nr = 0;
				total_found = 0;
			}
608
			ret = btrfs_next_leaf(root, path);
609 610
			if (ret == 0)
				continue;
C
Chris Mason 已提交
611 612
			if (ret < 0)
				goto error;
613 614
			if (!start_found) {
				ins->objectid = search_start;
615
				ins->offset = (u64)-1 - search_start;
616 617 618 619 620
				start_found = 1;
				goto check_pending;
			}
			ins->objectid = last_block > search_start ?
					last_block : search_start;
621
			ins->offset = (u64)-1 - ins->objectid;
622 623
			goto check_pending;
		}
C
Chris Mason 已提交
624
		btrfs_disk_key_to_cpu(&key, &l->items[slot].key);
C
Chris Mason 已提交
625 626
		if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY)
			goto next;
C
Chris Mason 已提交
627
		if (key.objectid >= search_start) {
628
			if (start_found) {
629 630
				if (last_block < search_start)
					last_block = search_start;
C
Chris Mason 已提交
631
				hole_size = key.objectid - last_block;
C
Chris Mason 已提交
632
				if (hole_size >= num_blocks) {
633
					ins->objectid = last_block;
C
Chris Mason 已提交
634
					ins->offset = hole_size;
635 636
					goto check_pending;
				}
637
			}
638
		}
639
		start_found = 1;
C
Chris Mason 已提交
640
		last_block = key.objectid + key.offset;
C
Chris Mason 已提交
641
next:
642
		path->slots[0]++;
643 644 645 646 647 648
	}
	// FIXME -ENOSPC
check_pending:
	/* we have to make sure we didn't find an extent that has already
	 * been allocated by the map tree or the original allocation
	 */
649
	btrfs_release_path(root, path);
650
	BUG_ON(ins->objectid < search_start);
651 652 653 654 655 656
	if (ins->objectid >= btrfs_super_total_blocks(info->disk_super)) {
		if (search_start == 0)
			return -ENOSPC;
		search_start = 0;
		goto check_failed;
	}
C
Chris Mason 已提交
657
	for (test_block = ins->objectid;
658 659
	     test_block < ins->objectid + num_blocks; test_block++) {
		if (test_radix_bit(&info->pinned_radix, test_block)) {
C
Chris Mason 已提交
660
			search_start = test_block + 1;
661 662 663
			goto check_failed;
		}
	}
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
	if (!fill_prealloc && info->extent_tree_insert_nr) {
		u64 last =
		  info->extent_tree_insert[info->extent_tree_insert_nr - 1];
		if (ins->objectid + num_blocks >
		    info->extent_tree_insert[0] &&
		    ins->objectid <= last) {
			search_start = last + 1;
			WARN_ON(1);
			goto check_failed;
		}
	}
	if (!fill_prealloc && info->extent_tree_prealloc_nr) {
		u64 first =
		  info->extent_tree_prealloc[info->extent_tree_prealloc_nr - 1];
		if (ins->objectid + num_blocks > first &&
		    ins->objectid <= info->extent_tree_prealloc[0]) {
			search_start = info->extent_tree_prealloc[0] + 1;
			WARN_ON(1);
			goto check_failed;
		}
	}
	if (fill_prealloc) {
		int nr;
		test_block = ins->objectid;
		while(test_block < ins->objectid + ins->offset &&
		      total_found < total_needed) {
			nr = total_needed - total_found - 1;
			BUG_ON(nr < 0);
C
Chris Mason 已提交
692
			info->extent_tree_prealloc[nr] = test_block;
693 694 695 696 697 698 699
			total_found++;
			test_block++;
		}
		if (total_found < total_needed) {
			search_start = test_block;
			goto check_failed;
		}
C
Chris Mason 已提交
700 701
		info->extent_tree_prealloc_nr = total_found;
	}
702 703 704 705 706 707 708
	if (update_block_group) {
		ret = radix_tree_gang_lookup(&info->block_group_radix,
					     (void **)&trans->block_group,
					     ins->objectid, 1);
		if (ret) {
			trans->block_group->last_alloc = ins->objectid;
		}
709
	}
C
Chris Mason 已提交
710
	ins->offset = num_blocks;
711
	btrfs_free_path(path);
712
	return 0;
C
Chris Mason 已提交
713
error:
714 715
	btrfs_release_path(root, path);
	btrfs_free_path(path);
C
Chris Mason 已提交
716
	return ret;
717 718 719 720 721 722 723 724
}
/*
 * finds a free extent and does all the dirty work required for allocation
 * returns the key for the extent through ins, and a tree buffer for
 * the first block of the extent through buf.
 *
 * returns 0 if everything worked, non-zero otherwise.
 */
725 726
int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
		       struct btrfs_root *root, u64 owner,
727
		       u64 num_blocks, u64 search_start,
728
		       u64 search_end, struct btrfs_key *ins)
729 730 731
{
	int ret;
	int pending_ret;
732 733 734
	u64 super_blocks_used;
	struct btrfs_fs_info *info = root->fs_info;
	struct btrfs_root *extent_root = info->extent_root;
C
Chris Mason 已提交
735
	struct btrfs_extent_item extent_item;
736
	struct btrfs_key prealloc_key;
C
Chris Mason 已提交
737

C
Chris Mason 已提交
738
	btrfs_set_extent_refs(&extent_item, 1);
739
	btrfs_set_extent_owner(&extent_item, owner);
740

C
Chris Mason 已提交
741
	if (root == extent_root) {
742 743
		int nr;
		BUG_ON(info->extent_tree_prealloc_nr == 0);
C
Chris Mason 已提交
744 745
		BUG_ON(num_blocks != 1);
		ins->offset = 1;
746 747 748 749 750
		info->extent_tree_prealloc_nr--;
		nr = info->extent_tree_prealloc_nr;
		ins->objectid = info->extent_tree_prealloc[nr];
		info->extent_tree_insert[info->extent_tree_insert_nr++] =
			ins->objectid;
C
Chris Mason 已提交
751 752 753
		ret = update_block_group(trans, root,
					 ins->objectid, ins->offset, 1);
		BUG_ON(ret);
754 755
		return 0;
	}
756
	/* do the real allocation */
757
	ret = find_free_extent(trans, root, num_blocks, search_start,
C
Chris Mason 已提交
758 759 760
			       search_end, ins);
	if (ret)
		return ret;
761

762 763 764 765 766 767
	/* then do prealloc for the extent tree */
	ret = find_free_extent(trans, root, 0, ins->objectid + ins->offset,
			       search_end, &prealloc_key);
	if (ret)
		return ret;

768 769 770
	super_blocks_used = btrfs_super_blocks_used(info->disk_super);
	btrfs_set_super_blocks_used(info->disk_super, super_blocks_used +
				    num_blocks);
771 772
	ret = btrfs_insert_item(trans, extent_root, ins, &extent_item,
				sizeof(extent_item));
C
Chris Mason 已提交
773

774
	finish_current_insert(trans, extent_root);
C
Chris Mason 已提交
775
	pending_ret = del_pending_extents(trans, extent_root);
C
Chris Mason 已提交
776 777 778 779
	if (ret)
		return ret;
	if (pending_ret)
		return pending_ret;
C
Chris Mason 已提交
780
	ret = update_block_group(trans, root, ins->objectid, ins->offset, 1);
C
Chris Mason 已提交
781
	return 0;
782 783 784 785 786 787
}

/*
 * helper function to allocate a block for a given tree
 * returns the tree buffer or NULL.
 */
C
Chris Mason 已提交
788
struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
789
					   struct btrfs_root *root, u64 hint)
790
{
C
Chris Mason 已提交
791
	struct btrfs_key ins;
792
	int ret;
C
Chris Mason 已提交
793
	struct buffer_head *buf;
794

795
	ret = btrfs_alloc_extent(trans, root, root->root_key.objectid,
796
				 1, hint, (unsigned long)-1, &ins);
797 798 799 800
	if (ret) {
		BUG();
		return NULL;
	}
C
Chris Mason 已提交
801
	BUG_ON(ret);
802
	buf = btrfs_find_create_tree_block(root, ins.objectid);
803
	set_buffer_uptodate(buf);
C
Chris Mason 已提交
804
	set_buffer_checked(buf);
805
	set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index);
806 807
	return buf;
}
808

809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
static int drop_leaf_ref(struct btrfs_trans_handle *trans,
			 struct btrfs_root *root, struct buffer_head *cur)
{
	struct btrfs_disk_key *key;
	struct btrfs_leaf *leaf;
	struct btrfs_file_extent_item *fi;
	int i;
	int nritems;
	int ret;

	BUG_ON(!btrfs_is_leaf(btrfs_buffer_node(cur)));
	leaf = btrfs_buffer_leaf(cur);
	nritems = btrfs_header_nritems(&leaf->header);
	for (i = 0; i < nritems; i++) {
		key = &leaf->items[i].key;
		if (btrfs_disk_key_type(key) != BTRFS_EXTENT_DATA_KEY)
			continue;
		fi = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item);
827 828
		if (btrfs_file_extent_type(fi) == BTRFS_FILE_EXTENT_INLINE)
			continue;
829 830 831 832 833 834 835 836 837 838 839 840 841
		/*
		 * FIXME make sure to insert a trans record that
		 * repeats the snapshot del on crash
		 */
		ret = btrfs_free_extent(trans, root,
					btrfs_file_extent_disk_blocknr(fi),
					btrfs_file_extent_disk_num_blocks(fi),
					0);
		BUG_ON(ret);
	}
	return 0;
}

C
Chris Mason 已提交
842 843 844 845
/*
 * helper function for drop_snapshot, this walks down the tree dropping ref
 * counts as it goes.
 */
846 847
static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
			  *root, struct btrfs_path *path, int *level)
C
Chris Mason 已提交
848
{
C
Chris Mason 已提交
849 850
	struct buffer_head *next;
	struct buffer_head *cur;
C
Chris Mason 已提交
851 852 853 854
	u64 blocknr;
	int ret;
	u32 refs;

855 856
	WARN_ON(*level < 0);
	WARN_ON(*level >= BTRFS_MAX_LEVEL);
C
Chris Mason 已提交
857
	ret = lookup_extent_ref(trans, root, bh_blocknr(path->nodes[*level]),
858
			       1, &refs);
C
Chris Mason 已提交
859 860 861
	BUG_ON(ret);
	if (refs > 1)
		goto out;
C
Chris Mason 已提交
862 863 864
	/*
	 * walk down to the last node level and free all the leaves
	 */
865
	while(*level >= 0) {
866 867
		WARN_ON(*level < 0);
		WARN_ON(*level >= BTRFS_MAX_LEVEL);
C
Chris Mason 已提交
868
		cur = path->nodes[*level];
C
Chris Mason 已提交
869 870
		if (btrfs_header_level(btrfs_buffer_header(cur)) != *level)
			WARN_ON(1);
871
		if (path->slots[*level] >=
C
Chris Mason 已提交
872
		    btrfs_header_nritems(btrfs_buffer_header(cur)))
C
Chris Mason 已提交
873
			break;
874 875 876 877 878
		if (*level == 0) {
			ret = drop_leaf_ref(trans, root, cur);
			BUG_ON(ret);
			break;
		}
C
Chris Mason 已提交
879 880
		blocknr = btrfs_node_blockptr(btrfs_buffer_node(cur),
					      path->slots[*level]);
C
Chris Mason 已提交
881
		ret = lookup_extent_ref(trans, root, blocknr, 1, &refs);
882 883
		BUG_ON(ret);
		if (refs != 1) {
C
Chris Mason 已提交
884
			path->slots[*level]++;
885
			ret = btrfs_free_extent(trans, root, blocknr, 1, 1);
C
Chris Mason 已提交
886 887 888 889
			BUG_ON(ret);
			continue;
		}
		next = read_tree_block(root, blocknr);
890
		WARN_ON(*level <= 0);
C
Chris Mason 已提交
891
		if (path->nodes[*level-1])
C
Chris Mason 已提交
892
			btrfs_block_release(root, path->nodes[*level-1]);
C
Chris Mason 已提交
893
		path->nodes[*level-1] = next;
C
Chris Mason 已提交
894
		*level = btrfs_header_level(btrfs_buffer_header(next));
C
Chris Mason 已提交
895 896 897
		path->slots[*level] = 0;
	}
out:
898 899
	WARN_ON(*level < 0);
	WARN_ON(*level >= BTRFS_MAX_LEVEL);
900
	ret = btrfs_free_extent(trans, root,
901
				bh_blocknr(path->nodes[*level]), 1, 1);
C
Chris Mason 已提交
902
	btrfs_block_release(root, path->nodes[*level]);
C
Chris Mason 已提交
903 904 905 906 907 908
	path->nodes[*level] = NULL;
	*level += 1;
	BUG_ON(ret);
	return 0;
}

C
Chris Mason 已提交
909 910 911 912 913
/*
 * helper for dropping snapshots.  This walks back up the tree in the path
 * to find the first node higher up where we haven't yet gone through
 * all the slots
 */
914 915
static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root
			*root, struct btrfs_path *path, int *level)
C
Chris Mason 已提交
916 917 918 919
{
	int i;
	int slot;
	int ret;
C
Chris Mason 已提交
920
	for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) {
C
Chris Mason 已提交
921
		slot = path->slots[i];
C
Chris Mason 已提交
922 923
		if (slot < btrfs_header_nritems(
		    btrfs_buffer_header(path->nodes[i])) - 1) {
C
Chris Mason 已提交
924 925 926 927
			path->slots[i]++;
			*level = i;
			return 0;
		} else {
928
			ret = btrfs_free_extent(trans, root,
929
						bh_blocknr(path->nodes[*level]),
930
						1, 1);
931
			BUG_ON(ret);
C
Chris Mason 已提交
932
			btrfs_block_release(root, path->nodes[*level]);
C
Chris Mason 已提交
933
			path->nodes[*level] = NULL;
C
Chris Mason 已提交
934 935 936 937 938 939
			*level = i + 1;
		}
	}
	return 1;
}

C
Chris Mason 已提交
940 941 942 943 944
/*
 * drop the reference count on the tree rooted at 'snap'.  This traverses
 * the tree freeing any blocks that have a ref count of zero after being
 * decremented.
 */
945
int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
C
Chris Mason 已提交
946
			*root, struct buffer_head *snap)
C
Chris Mason 已提交
947
{
948
	int ret = 0;
C
Chris Mason 已提交
949
	int wret;
C
Chris Mason 已提交
950
	int level;
951
	struct btrfs_path *path;
C
Chris Mason 已提交
952 953 954
	int i;
	int orig_level;

955 956 957
	path = btrfs_alloc_path();
	BUG_ON(!path);
	btrfs_init_path(path);
C
Chris Mason 已提交
958

C
Chris Mason 已提交
959
	level = btrfs_header_level(btrfs_buffer_header(snap));
C
Chris Mason 已提交
960
	orig_level = level;
961 962
	path->nodes[level] = snap;
	path->slots[level] = 0;
C
Chris Mason 已提交
963
	while(1) {
964
		wret = walk_down_tree(trans, root, path, &level);
C
Chris Mason 已提交
965
		if (wret > 0)
C
Chris Mason 已提交
966
			break;
C
Chris Mason 已提交
967 968 969
		if (wret < 0)
			ret = wret;

970
		wret = walk_up_tree(trans, root, path, &level);
C
Chris Mason 已提交
971
		if (wret > 0)
C
Chris Mason 已提交
972
			break;
C
Chris Mason 已提交
973 974
		if (wret < 0)
			ret = wret;
C
Chris Mason 已提交
975
		btrfs_btree_balance_dirty(root);
C
Chris Mason 已提交
976
	}
C
Chris Mason 已提交
977
	for (i = 0; i <= orig_level; i++) {
978 979
		if (path->nodes[i]) {
			btrfs_block_release(root, path->nodes[i]);
C
Chris Mason 已提交
980
		}
C
Chris Mason 已提交
981
	}
982
	btrfs_free_path(path);
C
Chris Mason 已提交
983
	return ret;
C
Chris Mason 已提交
984
}
C
Chris Mason 已提交
985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018

int btrfs_free_block_groups(struct btrfs_fs_info *info)
{
	int ret;
	struct btrfs_block_group_cache *cache[8];
	int i;

	while(1) {
		ret = radix_tree_gang_lookup(&info->block_group_radix,
					     (void **)cache, 0,
					     ARRAY_SIZE(cache));
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
			radix_tree_delete(&info->block_group_radix,
					  cache[i]->key.objectid +
					  cache[i]->key.offset - 1);
			kfree(cache[i]);
		}
	}
	return 0;
}

int btrfs_read_block_groups(struct btrfs_root *root)
{
	struct btrfs_path *path;
	int ret;
	int err = 0;
	struct btrfs_block_group_item *bi;
	struct btrfs_block_group_cache *cache;
	struct btrfs_key key;
	struct btrfs_key found_key;
	struct btrfs_leaf *leaf;
	u64 group_size_blocks = BTRFS_BLOCK_GROUP_SIZE / root->blocksize;
1019
	u64 used;
C
Chris Mason 已提交
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049

	root = root->fs_info->extent_root;
	key.objectid = 0;
	key.offset = group_size_blocks;
	key.flags = 0;
	btrfs_set_key_type(&key, BTRFS_BLOCK_GROUP_ITEM_KEY);

	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;

	while(1) {
		ret = btrfs_search_slot(NULL, root->fs_info->extent_root,
					&key, path, 0, 0);
		if (ret != 0) {
			err = ret;
			break;
		}
		leaf = btrfs_buffer_leaf(path->nodes[0]);
		btrfs_disk_key_to_cpu(&found_key,
				      &leaf->items[path->slots[0]].key);
		cache = kmalloc(sizeof(*cache), GFP_NOFS);
		if (!cache) {
			err = -1;
			break;
		}
		bi = btrfs_item_ptr(leaf, path->slots[0],
				    struct btrfs_block_group_item);
		memcpy(&cache->item, bi, sizeof(*bi));
		memcpy(&cache->key, &found_key, sizeof(found_key));
1050 1051
		cache->last_alloc = cache->key.objectid;
		cache->first_free = cache->key.objectid;
C
Chris Mason 已提交
1052 1053 1054 1055 1056 1057 1058
		key.objectid = found_key.objectid + found_key.offset;
		btrfs_release_path(root, path);
		ret = radix_tree_insert(&root->fs_info->block_group_radix,
					found_key.objectid +
					found_key.offset - 1,
					(void *)cache);
		BUG_ON(ret);
1059 1060 1061 1062 1063 1064 1065
		used = btrfs_block_group_used(bi);
		if (used < (key.offset * 2) / 3) {
			radix_tree_tag_set(&root->fs_info->block_group_radix,
					   found_key.objectid +
					   found_key.offset - 1,
					   BTRFS_BLOCK_GROUP_AVAIL);
		}
C
Chris Mason 已提交
1066 1067 1068 1069 1070 1071 1072 1073
		if (key.objectid >=
		    btrfs_super_total_blocks(root->fs_info->disk_super))
			break;
	}

	btrfs_free_path(path);
	return 0;
}