extent-tree.c 43.9 KB
Newer Older
C
Chris Mason 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Copyright (C) 2007 Oracle.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License v2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 021110-1307, USA.
 */

19
#include <linux/module.h>
20 21 22
#include "ctree.h"
#include "disk-io.h"
#include "print-tree.h"
23
#include "transaction.h"
24

25
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
26 27 28
			    *orig_root, u64 num_blocks, u64 search_start,
			    u64 search_end, u64 hint_block,
			    struct btrfs_key *ins, int data);
29 30
static int finish_current_insert(struct btrfs_trans_handle *trans, struct
				 btrfs_root *extent_root);
C
Chris Mason 已提交
31 32
static int del_pending_extents(struct btrfs_trans_handle *trans, struct
			       btrfs_root *extent_root);
33

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
static void reada_extent_leaves(struct btrfs_root *root,
				struct btrfs_path *path, u64 limit)
{
	struct btrfs_node *node;
	int i;
	int nritems;
	u64 item_objectid;
	u64 blocknr;
	int slot;
	int ret;

	if (!path->nodes[1])
		return;
	node = btrfs_buffer_node(path->nodes[1]);
	slot = path->slots[1] + 1;
	nritems = btrfs_header_nritems(&node->header);
	for (i = slot; i < nritems && i < slot + 8; i++) {
		item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key);
		if (item_objectid > limit)
			break;
		blocknr = btrfs_node_blockptr(node, i);
		ret = readahead_tree_block(root, blocknr);
		if (ret)
			break;
	}
}

61 62 63 64 65 66 67 68 69 70 71 72
static int cache_block_group(struct btrfs_root *root,
			     struct btrfs_block_group_cache *block_group)
{
	struct btrfs_path *path;
	int ret;
	struct btrfs_key key;
	struct btrfs_leaf *leaf;
	struct radix_tree_root *extent_radix;
	int slot;
	u64 i;
	u64 last = 0;
	u64 hole_size;
73
	u64 limit;
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
	int found = 0;

	root = root->fs_info->extent_root;
	extent_radix = &root->fs_info->extent_map_radix;

	if (block_group->cached)
		return 0;
	if (block_group->data)
		return 0;
	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;
	key.objectid = block_group->key.objectid;
	key.flags = 0;
	key.offset = 0;
	btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
	if (ret < 0)
		return ret;
	if (ret && path->slots[0] > 0)
		path->slots[0]--;
95 96
	limit = block_group->key.objectid + block_group->key.offset;
	reada_extent_leaves(root, path, limit);
97 98 99 100
	while(1) {
		leaf = btrfs_buffer_leaf(path->nodes[0]);
		slot = path->slots[0];
		if (slot >= btrfs_header_nritems(&leaf->header)) {
101
			reada_extent_leaves(root, path, limit);
102
			ret = btrfs_next_leaf(root, path);
103 104
			if (ret < 0)
				goto err;
105
			if (ret == 0) {
106
				continue;
107
			} else {
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
				if (found) {
					hole_size = block_group->key.objectid +
						block_group->key.offset - last;
				} else {
					last = block_group->key.objectid;
					hole_size = block_group->key.offset;
				}
				for (i = 0; i < hole_size; i++) {
					set_radix_bit(extent_radix,
						      last + i);
				}
				break;
			}
		}
		btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key);
		if (key.objectid >= block_group->key.objectid +
		    block_group->key.offset) {
			if (found) {
				hole_size = block_group->key.objectid +
					block_group->key.offset - last;
			} else {
				last = block_group->key.objectid;
				hole_size = block_group->key.offset;
			}
			for (i = 0; i < hole_size; i++) {
				set_radix_bit(extent_radix, last + i);
			}
			break;
		}
		if (btrfs_key_type(&key) == BTRFS_EXTENT_ITEM_KEY) {
			if (!found) {
				last = key.objectid + key.offset;
				found = 1;
			} else {
				hole_size = key.objectid - last;
				for (i = 0; i < hole_size; i++) {
					set_radix_bit(extent_radix, last + i);
				}
				last = key.objectid + key.offset;
			}
		}
		path->slots[0]++;
	}

	block_group->cached = 1;
153
err:
154 155 156 157
	btrfs_free_path(path);
	return 0;
}

158 159 160
struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
							 btrfs_fs_info *info,
							 u64 blocknr)
C
Chris Mason 已提交
161 162 163 164 165 166 167 168
{
	struct btrfs_block_group_cache *block_group;
	int ret;

	ret = radix_tree_gang_lookup(&info->block_group_radix,
				     (void **)&block_group,
				     blocknr, 1);
	if (ret) {
C
Chris Mason 已提交
169
		if (block_group->key.objectid <= blocknr && blocknr <=
C
Chris Mason 已提交
170 171 172 173 174 175 176
		    block_group->key.objectid + block_group->key.offset)
			return block_group;
	}
	ret = radix_tree_gang_lookup(&info->block_group_data_radix,
				     (void **)&block_group,
				     blocknr, 1);
	if (ret) {
C
Chris Mason 已提交
177
		if (block_group->key.objectid <= blocknr && blocknr <=
C
Chris Mason 已提交
178 179 180 181 182 183
		    block_group->key.objectid + block_group->key.offset)
			return block_group;
	}
	return NULL;
}

184 185 186
static u64 leaf_range(struct btrfs_root *root)
{
	u64 size = BTRFS_LEAF_DATA_SIZE(root);
C
Chris Mason 已提交
187 188
	do_div(size, sizeof(struct btrfs_extent_item) +
		sizeof(struct btrfs_item));
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
	return size;
}

static u64 find_search_start(struct btrfs_root *root,
			     struct btrfs_block_group_cache **cache_ret,
			     u64 search_start, int num)
{
	unsigned long gang[8];
	int ret;
	struct btrfs_block_group_cache *cache = *cache_ret;
	u64 last = max(search_start, cache->key.objectid);

	if (cache->data)
		goto out;
	if (num > 1) {
		last = max(last, cache->last_prealloc);
	}
again:
207 208 209
	ret = cache_block_group(root, cache);
	if (ret)
		goto out;
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
	while(1) {
		ret = find_first_radix_bit(&root->fs_info->extent_map_radix,
					   gang, last, ARRAY_SIZE(gang));
		if (!ret)
			goto out;
		last = gang[ret-1] + 1;
		if (num > 1) {
			if (ret != ARRAY_SIZE(gang)) {
				goto new_group;
			}
			if (gang[ret-1] - gang[0] > leaf_range(root)) {
				continue;
			}
		}
		if (gang[0] >= cache->key.objectid + cache->key.offset) {
			goto new_group;
		}
		return gang[0];
	}
out:
	return max(cache->last_alloc, search_start);

new_group:
233 234
	cache = btrfs_lookup_block_group(root->fs_info,
					 last + cache->key.offset - 1);
235 236 237 238
	if (!cache) {
		return max((*cache_ret)->last_alloc, search_start);
	}
	cache = btrfs_find_block_group(root, cache,
239
				       last + cache->key.offset - 1, 0, 0);
240 241 242 243
	*cache_ret = cache;
	goto again;
}

C
Chris Mason 已提交
244 245 246 247 248 249 250
static u64 div_factor(u64 num, int factor)
{
	num *= factor;
	do_div(num, 10);
	return num;
}

251 252
struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
						 struct btrfs_block_group_cache
C
Chris Mason 已提交
253
						 *hint, u64 search_start,
254
						 int data, int owner)
C
Chris Mason 已提交
255 256
{
	struct btrfs_block_group_cache *cache[8];
257
	struct btrfs_block_group_cache *found_group = NULL;
C
Chris Mason 已提交
258
	struct btrfs_fs_info *info = root->fs_info;
C
Chris Mason 已提交
259
	struct radix_tree_root *radix;
C
Chris Mason 已提交
260
	struct radix_tree_root *swap_radix;
C
Chris Mason 已提交
261
	u64 used;
262 263
	u64 last = 0;
	u64 hint_last;
C
Chris Mason 已提交
264 265
	int i;
	int ret;
266
	int full_search = 0;
267
	int factor = 8;
C
Chris Mason 已提交
268
	int data_swap = 0;
269 270 271

	if (!owner)
		factor = 5;
C
Chris Mason 已提交
272

C
Chris Mason 已提交
273
	if (data) {
C
Chris Mason 已提交
274
		radix = &info->block_group_data_radix;
C
Chris Mason 已提交
275 276
		swap_radix = &info->block_group_radix;
	} else {
C
Chris Mason 已提交
277
		radix = &info->block_group_radix;
C
Chris Mason 已提交
278 279
		swap_radix = &info->block_group_data_radix;
	}
C
Chris Mason 已提交
280 281 282

	if (search_start) {
		struct btrfs_block_group_cache *shint;
283
		shint = btrfs_lookup_block_group(info, search_start);
C
Chris Mason 已提交
284 285 286
		if (shint->data == data) {
			used = btrfs_block_group_used(&shint->item);
			if (used + shint->pinned <
C
Chris Mason 已提交
287
			    div_factor(shint->key.offset, factor)) {
C
Chris Mason 已提交
288 289 290 291 292
				return shint;
			}
		}
	}
	if (hint && hint->data == data) {
293
		used = btrfs_block_group_used(&hint->item);
C
Chris Mason 已提交
294 295
		if (used + hint->pinned <
		    div_factor(hint->key.offset, factor)) {
296 297
			return hint;
		}
C
Chris Mason 已提交
298
		if (used >= div_factor(hint->key.offset, 8)) {
C
Chris Mason 已提交
299 300 301 302 303
			radix_tree_tag_clear(radix,
					     hint->key.objectid +
					     hint->key.offset - 1,
					     BTRFS_BLOCK_GROUP_AVAIL);
		}
304
		last = hint->key.offset * 3;
C
Chris Mason 已提交
305
		if (hint->key.objectid >= last)
306 307
			last = max(search_start + hint->key.offset - 1,
				   hint->key.objectid - last);
C
Chris Mason 已提交
308 309
		else
			last = hint->key.objectid + hint->key.offset;
310 311
		hint_last = last;
	} else {
312 313 314 315 316 317
		if (hint)
			hint_last = max(hint->key.objectid, search_start);
		else
			hint_last = search_start;

		last = hint_last;
318
	}
C
Chris Mason 已提交
319
	while(1) {
C
Chris Mason 已提交
320
		ret = radix_tree_gang_lookup_tag(radix, (void **)cache,
C
Chris Mason 已提交
321
						 last, ARRAY_SIZE(cache),
322
						 BTRFS_BLOCK_GROUP_AVAIL);
C
Chris Mason 已提交
323 324 325
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
C
Chris Mason 已提交
326 327
			last = cache[i]->key.objectid +
				cache[i]->key.offset;
C
Chris Mason 已提交
328
			used = btrfs_block_group_used(&cache[i]->item);
C
Chris Mason 已提交
329
			if (used + cache[i]->pinned <
C
Chris Mason 已提交
330
			    div_factor(cache[i]->key.offset, factor)) {
331 332
				found_group = cache[i];
				goto found;
C
Chris Mason 已提交
333
			}
C
Chris Mason 已提交
334
			if (used >= div_factor(cache[i]->key.offset, 8)) {
C
Chris Mason 已提交
335 336 337 338 339
				radix_tree_tag_clear(radix,
						     cache[i]->key.objectid +
						     cache[i]->key.offset - 1,
						     BTRFS_BLOCK_GROUP_AVAIL);
			}
C
Chris Mason 已提交
340
		}
341
		cond_resched();
C
Chris Mason 已提交
342
	}
343 344
	last = hint_last;
again:
C
Chris Mason 已提交
345
	while(1) {
C
Chris Mason 已提交
346 347
		ret = radix_tree_gang_lookup(radix, (void **)cache,
					     last, ARRAY_SIZE(cache));
C
Chris Mason 已提交
348 349 350
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
C
Chris Mason 已提交
351 352
			last = cache[i]->key.objectid +
				cache[i]->key.offset;
C
Chris Mason 已提交
353
			used = btrfs_block_group_used(&cache[i]->item);
C
Chris Mason 已提交
354
			if (used + cache[i]->pinned < cache[i]->key.offset) {
355 356
				found_group = cache[i];
				goto found;
C
Chris Mason 已提交
357
			}
C
Chris Mason 已提交
358 359 360 361 362 363
			if (used >= cache[i]->key.offset) {
				radix_tree_tag_clear(radix,
						     cache[i]->key.objectid +
						     cache[i]->key.offset - 1,
						     BTRFS_BLOCK_GROUP_AVAIL);
			}
C
Chris Mason 已提交
364
		}
365
		cond_resched();
C
Chris Mason 已提交
366
	}
367
	if (!full_search) {
C
Chris Mason 已提交
368
		last = search_start;
369 370 371
		full_search = 1;
		goto again;
	}
C
Chris Mason 已提交
372 373 374 375 376 377 378 379
	if (!data_swap) {
		struct radix_tree_root *tmp = radix;
		data_swap = 1;
		radix = swap_radix;
		swap_radix = tmp;
		last = search_start;
		goto again;
	}
380
	if (!found_group) {
C
Chris Mason 已提交
381
		ret = radix_tree_gang_lookup(radix,
382
					     (void **)&found_group, 0, 1);
C
Chris Mason 已提交
383 384 385 386 387
		if (ret == 0) {
			ret = radix_tree_gang_lookup(swap_radix,
						     (void **)&found_group,
						     0, 1);
		}
388 389
		BUG_ON(ret != 1);
	}
C
Chris Mason 已提交
390
found:
391
	return found_group;
C
Chris Mason 已提交
392 393
}

C
Chris Mason 已提交
394 395 396
int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
				struct btrfs_root *root,
				u64 blocknr, u64 num_blocks)
C
Chris Mason 已提交
397
{
398
	struct btrfs_path *path;
C
Chris Mason 已提交
399
	int ret;
C
Chris Mason 已提交
400
	struct btrfs_key key;
C
Chris Mason 已提交
401 402
	struct btrfs_leaf *l;
	struct btrfs_extent_item *item;
C
Chris Mason 已提交
403
	struct btrfs_key ins;
C
Chris Mason 已提交
404
	u32 refs;
C
Chris Mason 已提交
405

406
	path = btrfs_alloc_path();
407 408 409 410 411 412 413 414
	if (!path)
		return -ENOMEM;
	ret = find_free_extent(trans, root->fs_info->extent_root, 0, 0,
			       (u64)-1, 0, &ins, 0);
	if (ret) {
		btrfs_free_path(path);
		return ret;
	}
C
Chris Mason 已提交
415 416
	key.objectid = blocknr;
	key.flags = 0;
417
	btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
418
	key.offset = num_blocks;
419
	ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path,
420
				0, 1);
421 422
	if (ret < 0)
		return ret;
423
	if (ret != 0) {
424
		BUG();
425
	}
C
Chris Mason 已提交
426
	BUG_ON(ret != 0);
427 428
	l = btrfs_buffer_leaf(path->nodes[0]);
	item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item);
C
Chris Mason 已提交
429 430
	refs = btrfs_extent_refs(item);
	btrfs_set_extent_refs(item, refs + 1);
431
	btrfs_mark_buffer_dirty(path->nodes[0]);
432

433 434
	btrfs_release_path(root->fs_info->extent_root, path);
	btrfs_free_path(path);
435
	finish_current_insert(trans, root->fs_info->extent_root);
C
Chris Mason 已提交
436
	del_pending_extents(trans, root->fs_info->extent_root);
C
Chris Mason 已提交
437 438 439
	return 0;
}

C
Chris Mason 已提交
440 441 442
static int lookup_extent_ref(struct btrfs_trans_handle *trans,
			     struct btrfs_root *root, u64 blocknr,
			     u64 num_blocks, u32 *refs)
443
{
444
	struct btrfs_path *path;
445
	int ret;
C
Chris Mason 已提交
446
	struct btrfs_key key;
C
Chris Mason 已提交
447 448
	struct btrfs_leaf *l;
	struct btrfs_extent_item *item;
449 450

	path = btrfs_alloc_path();
451
	key.objectid = blocknr;
452
	key.offset = num_blocks;
453 454
	key.flags = 0;
	btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
455
	ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path,
456
				0, 0);
457 458
	if (ret < 0)
		goto out;
459 460
	if (ret != 0)
		BUG();
461 462
	l = btrfs_buffer_leaf(path->nodes[0]);
	item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item);
C
Chris Mason 已提交
463
	*refs = btrfs_extent_refs(item);
464
out:
465
	btrfs_free_path(path);
466 467 468
	return 0;
}

C
Chris Mason 已提交
469 470 471
int btrfs_inc_root_ref(struct btrfs_trans_handle *trans,
		       struct btrfs_root *root)
{
C
Chris Mason 已提交
472
	return btrfs_inc_extent_ref(trans, root, bh_blocknr(root->node), 1);
C
Chris Mason 已提交
473 474
}

475
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
C
Chris Mason 已提交
476
		  struct buffer_head *buf)
C
Chris Mason 已提交
477 478
{
	u64 blocknr;
C
Chris Mason 已提交
479
	struct btrfs_node *buf_node;
480 481 482
	struct btrfs_leaf *buf_leaf;
	struct btrfs_disk_key *key;
	struct btrfs_file_extent_item *fi;
C
Chris Mason 已提交
483
	int i;
484 485
	int leaf;
	int ret;
486 487
	int faili;
	int err;
488

489
	if (!root->ref_cows)
490
		return 0;
C
Chris Mason 已提交
491
	buf_node = btrfs_buffer_node(buf);
492 493
	leaf = btrfs_is_leaf(buf_node);
	buf_leaf = btrfs_buffer_leaf(buf);
C
Chris Mason 已提交
494
	for (i = 0; i < btrfs_header_nritems(&buf_node->header); i++) {
495
		if (leaf) {
C
Chris Mason 已提交
496
			u64 disk_blocknr;
497 498 499 500 501
			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);
502 503 504
			if (btrfs_file_extent_type(fi) ==
			    BTRFS_FILE_EXTENT_INLINE)
				continue;
C
Chris Mason 已提交
505 506 507 508
			disk_blocknr = btrfs_file_extent_disk_blocknr(fi);
			if (disk_blocknr == 0)
				continue;
			ret = btrfs_inc_extent_ref(trans, root, disk_blocknr,
509
				    btrfs_file_extent_disk_num_blocks(fi));
510 511 512 513
			if (ret) {
				faili = i;
				goto fail;
			}
514 515
		} else {
			blocknr = btrfs_node_blockptr(buf_node, i);
C
Chris Mason 已提交
516
			ret = btrfs_inc_extent_ref(trans, root, blocknr, 1);
517 518 519 520
			if (ret) {
				faili = i;
				goto fail;
			}
521
		}
C
Chris Mason 已提交
522 523
	}
	return 0;
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
fail:
	for (i =0; i < faili; i++) {
		if (leaf) {
			u64 disk_blocknr;
			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);
			if (btrfs_file_extent_type(fi) ==
			    BTRFS_FILE_EXTENT_INLINE)
				continue;
			disk_blocknr = btrfs_file_extent_disk_blocknr(fi);
			if (disk_blocknr == 0)
				continue;
			err = btrfs_free_extent(trans, root, disk_blocknr,
				    btrfs_file_extent_disk_num_blocks(fi), 0);
			BUG_ON(err);
		} else {
			blocknr = btrfs_node_blockptr(buf_node, i);
			err = btrfs_free_extent(trans, root, blocknr, 1, 0);
			BUG_ON(err);
		}
	}
	return ret;
C
Chris Mason 已提交
549 550
}

C
Chris Mason 已提交
551 552 553 554 555 556 557 558 559 560 561
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;

562 563 564 565
	ret = find_free_extent(trans, extent_root, 0, 0, (u64)-1, 0, &ins, 0);
	/* FIXME, set bit to recalc cache groups on next mount */
	if (ret)
		return ret;
C
Chris Mason 已提交
566
	ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1);
567 568
	if (ret < 0)
		goto fail;
C
Chris Mason 已提交
569 570 571 572 573 574
	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);
575
fail:
C
Chris Mason 已提交
576 577 578 579 580 581
	finish_current_insert(trans, extent_root);
	pending_ret = del_pending_extents(trans, extent_root);
	if (ret)
		return ret;
	if (pending_ret)
		return pending_ret;
C
Chris Mason 已提交
582 583
	if (cache->data)
		cache->last_alloc = cache->first_free;
C
Chris Mason 已提交
584 585 586 587
	return 0;

}

C
Chris Mason 已提交
588 589 590
static int write_dirty_block_radix(struct btrfs_trans_handle *trans,
				   struct btrfs_root *root,
				   struct radix_tree_root *radix)
C
Chris Mason 已提交
591 592 593 594 595 596 597
{
	struct btrfs_block_group_cache *cache[8];
	int ret;
	int err = 0;
	int werr = 0;
	int i;
	struct btrfs_path *path;
598
	unsigned long off = 0;
C
Chris Mason 已提交
599 600 601 602 603 604 605

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

	while(1) {
		ret = radix_tree_gang_lookup_tag(radix, (void **)cache,
606
						 off, ARRAY_SIZE(cache),
C
Chris Mason 已提交
607 608 609 610 611 612
						 BTRFS_BLOCK_GROUP_DIRTY);
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
			err = write_one_cache_group(trans, root,
						    path, cache[i]);
613 614 615 616 617 618
			/*
			 * if we fail to write the cache group, we want
			 * to keep it marked dirty in hopes that a later
			 * write will work
			 */
			if (err) {
C
Chris Mason 已提交
619
				werr = err;
620 621 622 623 624 625 626 627
				off = cache[i]->key.objectid +
					cache[i]->key.offset;
				continue;
			}

			radix_tree_tag_clear(radix, cache[i]->key.objectid +
					     cache[i]->key.offset - 1,
					     BTRFS_BLOCK_GROUP_DIRTY);
C
Chris Mason 已提交
628 629 630 631 632 633
		}
	}
	btrfs_free_path(path);
	return werr;
}

C
Chris Mason 已提交
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
				   struct btrfs_root *root)
{
	int ret;
	int ret2;
	ret = write_dirty_block_radix(trans, root,
				      &root->fs_info->block_group_radix);
	ret2 = write_dirty_block_radix(trans, root,
				      &root->fs_info->block_group_data_radix);
	if (ret)
		return ret;
	if (ret2)
		return ret2;
	return 0;
}

C
Chris Mason 已提交
650 651
static int update_block_group(struct btrfs_trans_handle *trans,
			      struct btrfs_root *root,
C
Chris Mason 已提交
652 653
			      u64 blocknr, u64 num, int alloc, int mark_free,
			      int data)
C
Chris Mason 已提交
654 655 656 657 658 659
{
	struct btrfs_block_group_cache *cache;
	struct btrfs_fs_info *info = root->fs_info;
	u64 total = num;
	u64 old_val;
	u64 block_in_group;
660
	u64 i;
C
Chris Mason 已提交
661
	int ret;
C
Chris Mason 已提交
662

C
Chris Mason 已提交
663
	while(total) {
664
		cache = btrfs_lookup_block_group(info, blocknr);
C
Chris Mason 已提交
665
		if (!cache) {
C
Chris Mason 已提交
666
			return -1;
C
Chris Mason 已提交
667
		}
C
Chris Mason 已提交
668 669
		block_in_group = blocknr - cache->key.objectid;
		WARN_ON(block_in_group > cache->key.offset);
C
Chris Mason 已提交
670
		radix_tree_tag_set(cache->radix, cache->key.objectid +
C
Chris Mason 已提交
671
				   cache->key.offset - 1,
C
Chris Mason 已提交
672 673 674 675
				   BTRFS_BLOCK_GROUP_DIRTY);

		old_val = btrfs_block_group_used(&cache->item);
		num = min(total, cache->key.offset - block_in_group);
C
Chris Mason 已提交
676 677 678
		if (alloc) {
			if (blocknr > cache->last_alloc)
				cache->last_alloc = blocknr;
679 680 681 682 683 684
			if (!cache->data) {
				for (i = 0; i < num; i++) {
					clear_radix_bit(&info->extent_map_radix,
						        blocknr + i);
				}
			}
C
Chris Mason 已提交
685
			if (cache->data != data &&
C
Chris Mason 已提交
686
			    old_val < (cache->key.offset >> 1)) {
C
Chris Mason 已提交
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
				cache->data = data;
				radix_tree_delete(cache->radix,
						  cache->key.objectid +
						  cache->key.offset - 1);

				if (data) {
					cache->radix =
						&info->block_group_data_radix;
					cache->item.flags |=
						BTRFS_BLOCK_GROUP_DATA;
				} else {
					cache->radix = &info->block_group_radix;
					cache->item.flags &=
						~BTRFS_BLOCK_GROUP_DATA;
				}
				ret = radix_tree_insert(cache->radix,
							cache->key.objectid +
							cache->key.offset - 1,
							(void *)cache);
			}
			old_val += num;
C
Chris Mason 已提交
708
		} else {
C
Chris Mason 已提交
709
			old_val -= num;
C
Chris Mason 已提交
710 711
			if (blocknr < cache->first_free)
				cache->first_free = blocknr;
712 713 714 715 716 717
			if (!cache->data && mark_free) {
				for (i = 0; i < num; i++) {
					set_radix_bit(&info->extent_map_radix,
						      blocknr + i);
				}
			}
C
Chris Mason 已提交
718 719
			if (old_val < (cache->key.offset >> 1) &&
			    old_val + num >= (cache->key.offset >> 1)) {
720 721 722 723 724
				radix_tree_tag_set(cache->radix,
						   cache->key.objectid +
						   cache->key.offset - 1,
						   BTRFS_BLOCK_GROUP_AVAIL);
			}
C
Chris Mason 已提交
725
		}
C
Chris Mason 已提交
726
		btrfs_set_block_group_used(&cache->item, old_val);
727 728
		total -= num;
		blocknr += num;
C
Chris Mason 已提交
729 730 731 732
	}
	return 0;
}

C
Chris Mason 已提交
733 734 735 736 737 738 739
static int try_remove_page(struct address_space *mapping, unsigned long index)
{
	int ret;
	ret = invalidate_mapping_pages(mapping, index, index);
	return ret;
}

740 741
int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
			       btrfs_root *root)
742
{
C
Chris Mason 已提交
743
	unsigned long gang[8];
C
Chris Mason 已提交
744
	struct inode *btree_inode = root->fs_info->btree_inode;
C
Chris Mason 已提交
745
	struct btrfs_block_group_cache *block_group;
746
	u64 first = 0;
747 748
	int ret;
	int i;
C
Chris Mason 已提交
749
	struct radix_tree_root *pinned_radix = &root->fs_info->pinned_radix;
750
	struct radix_tree_root *extent_radix = &root->fs_info->extent_map_radix;
751 752

	while(1) {
753
		ret = find_first_radix_bit(pinned_radix, gang, 0,
C
Chris Mason 已提交
754
					   ARRAY_SIZE(gang));
755 756
		if (!ret)
			break;
757
		if (!first)
C
Chris Mason 已提交
758
			first = gang[0];
759
		for (i = 0; i < ret; i++) {
C
Chris Mason 已提交
760
			clear_radix_bit(pinned_radix, gang[i]);
761 762
			block_group = btrfs_lookup_block_group(root->fs_info,
							       gang[i]);
C
Chris Mason 已提交
763 764 765 766 767
			if (block_group) {
				WARN_ON(block_group->pinned == 0);
				block_group->pinned--;
				if (gang[i] < block_group->last_alloc)
					block_group->last_alloc = gang[i];
768 769 770 771
				if (gang[i] < block_group->last_prealloc)
					block_group->last_prealloc = gang[i];
				if (!block_group->data)
					set_radix_bit(extent_radix, gang[i]);
C
Chris Mason 已提交
772
			}
C
Chris Mason 已提交
773 774 775
			try_remove_page(btree_inode->i_mapping,
					gang[i] << (PAGE_CACHE_SHIFT -
						    btree_inode->i_blkbits));
776
		}
777 778 779 780
	}
	return 0;
}

781 782
static int finish_current_insert(struct btrfs_trans_handle *trans, struct
				 btrfs_root *extent_root)
C
Chris Mason 已提交
783
{
C
Chris Mason 已提交
784
	struct btrfs_key ins;
C
Chris Mason 已提交
785
	struct btrfs_extent_item extent_item;
C
Chris Mason 已提交
786 787
	int i;
	int ret;
788 789
	u64 super_blocks_used;
	struct btrfs_fs_info *info = extent_root->fs_info;
C
Chris Mason 已提交
790

C
Chris Mason 已提交
791
	btrfs_set_extent_refs(&extent_item, 1);
C
Chris Mason 已提交
792 793
	ins.offset = 1;
	ins.flags = 0;
794
	btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY);
795
	btrfs_set_extent_owner(&extent_item, extent_root->root_key.objectid);
C
Chris Mason 已提交
796

797 798
	for (i = 0; i < extent_root->fs_info->extent_tree_insert_nr; i++) {
		ins.objectid = extent_root->fs_info->extent_tree_insert[i];
799 800
		super_blocks_used = btrfs_super_blocks_used(&info->super_copy);
		btrfs_set_super_blocks_used(&info->super_copy,
801
					    super_blocks_used + 1);
802 803
		ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item,
					sizeof(extent_item));
C
Chris Mason 已提交
804 805
		BUG_ON(ret);
	}
806
	extent_root->fs_info->extent_tree_insert_nr = 0;
C
Chris Mason 已提交
807 808 809
	return 0;
}

C
Chris Mason 已提交
810
static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
C
Chris Mason 已提交
811 812
{
	int err;
C
Chris Mason 已提交
813
	struct btrfs_header *header;
C
Chris Mason 已提交
814 815
	struct buffer_head *bh;

C
Chris Mason 已提交
816
	if (!pending) {
817
		bh = btrfs_find_tree_block(root, blocknr);
C
Chris Mason 已提交
818 819 820 821 822 823 824 825 826 827
		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 已提交
828
			}
C
Chris Mason 已提交
829
			btrfs_block_release(root, bh);
C
Chris Mason 已提交
830 831
		}
		err = set_radix_bit(&root->fs_info->pinned_radix, blocknr);
C
Chris Mason 已提交
832 833
		if (!err) {
			struct btrfs_block_group_cache *cache;
834 835
			cache = btrfs_lookup_block_group(root->fs_info,
							 blocknr);
C
Chris Mason 已提交
836 837 838
			if (cache)
				cache->pinned++;
		}
C
Chris Mason 已提交
839 840 841
	} else {
		err = set_radix_bit(&root->fs_info->pending_del_radix, blocknr);
	}
C
Chris Mason 已提交
842
	BUG_ON(err < 0);
C
Chris Mason 已提交
843 844 845
	return 0;
}

846
/*
847
 * remove an extent from the root, returns 0 on success
848
 */
849
static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
850 851
			 *root, u64 blocknr, u64 num_blocks, int pin,
			 int mark_free)
852
{
853
	struct btrfs_path *path;
C
Chris Mason 已提交
854
	struct btrfs_key key;
855 856
	struct btrfs_fs_info *info = root->fs_info;
	struct btrfs_root *extent_root = info->extent_root;
857
	int ret;
C
Chris Mason 已提交
858
	struct btrfs_extent_item *ei;
C
Chris Mason 已提交
859
	struct btrfs_key ins;
C
Chris Mason 已提交
860
	u32 refs;
C
Chris Mason 已提交
861

862 863
	key.objectid = blocknr;
	key.flags = 0;
864
	btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
865 866
	key.offset = num_blocks;

867
	path = btrfs_alloc_path();
868 869
	if (!path)
		return -ENOMEM;
870

871
	ret = find_free_extent(trans, root, 0, 0, (u64)-1, 0, &ins, 0);
872
	if (ret) {
873 874
		btrfs_free_path(path);
		return ret;
875
	}
876 877 878 879 880

	ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1);
	if (ret < 0)
		return ret;
	BUG_ON(ret);
881
	ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
C
Chris Mason 已提交
882
			    struct btrfs_extent_item);
883
	BUG_ON(ei->refs == 0);
C
Chris Mason 已提交
884 885
	refs = btrfs_extent_refs(ei) - 1;
	btrfs_set_extent_refs(ei, refs);
886
	btrfs_mark_buffer_dirty(path->nodes[0]);
C
Chris Mason 已提交
887
	if (refs == 0) {
888
		u64 super_blocks_used;
C
Chris Mason 已提交
889 890

		if (pin) {
C
Chris Mason 已提交
891
			ret = pin_down_block(root, blocknr, 0);
C
Chris Mason 已提交
892 893 894
			BUG_ON(ret);
		}

895 896
		super_blocks_used = btrfs_super_blocks_used(&info->super_copy);
		btrfs_set_super_blocks_used(&info->super_copy,
897
					    super_blocks_used - num_blocks);
898
		ret = btrfs_del_item(trans, extent_root, path);
899 900 901
		if (ret) {
			return ret;
		}
902
		ret = update_block_group(trans, root, blocknr, num_blocks, 0,
C
Chris Mason 已提交
903
					 mark_free, 0);
C
Chris Mason 已提交
904
		BUG_ON(ret);
905
	}
906
	btrfs_free_path(path);
907
	finish_current_insert(trans, extent_root);
908 909 910 911 912 913 914
	return ret;
}

/*
 * find all the blocks marked as pending in the radix tree and remove
 * them from the extent map
 */
915 916
static int del_pending_extents(struct btrfs_trans_handle *trans, struct
			       btrfs_root *extent_root)
917 918
{
	int ret;
C
Chris Mason 已提交
919 920
	int wret;
	int err = 0;
C
Chris Mason 已提交
921
	unsigned long gang[4];
922
	int i;
C
Chris Mason 已提交
923 924
	struct radix_tree_root *pending_radix;
	struct radix_tree_root *pinned_radix;
C
Chris Mason 已提交
925
	struct btrfs_block_group_cache *cache;
C
Chris Mason 已提交
926 927 928

	pending_radix = &extent_root->fs_info->pending_del_radix;
	pinned_radix = &extent_root->fs_info->pinned_radix;
929 930

	while(1) {
931
		ret = find_first_radix_bit(pending_radix, gang, 0,
C
Chris Mason 已提交
932
					   ARRAY_SIZE(gang));
933 934 935
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
C
Chris Mason 已提交
936
			wret = set_radix_bit(pinned_radix, gang[i]);
C
Chris Mason 已提交
937
			if (wret == 0) {
938 939
				cache =
				  btrfs_lookup_block_group(extent_root->fs_info,
C
Chris Mason 已提交
940 941 942 943 944 945 946 947 948
							   gang[i]);
				if (cache)
					cache->pinned++;
			}
			if (wret < 0) {
				printk(KERN_CRIT "set_radix_bit, err %d\n",
				       wret);
				BUG_ON(wret < 0);
			}
C
Chris Mason 已提交
949 950
			wret = clear_radix_bit(pending_radix, gang[i]);
			BUG_ON(wret);
951
			wret = __free_extent(trans, extent_root,
952
					     gang[i], 1, 0, 0);
C
Chris Mason 已提交
953 954
			if (wret)
				err = wret;
955 956
		}
	}
C
Chris Mason 已提交
957
	return err;
958 959 960 961 962
}

/*
 * remove an extent from the root, returns 0 on success
 */
963 964
int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, u64 blocknr, u64 num_blocks, int pin)
965
{
966
	struct btrfs_root *extent_root = root->fs_info->extent_root;
967 968
	int pending_ret;
	int ret;
969

970
	if (root == extent_root) {
C
Chris Mason 已提交
971
		pin_down_block(root, blocknr, 1);
972 973
		return 0;
	}
974
	ret = __free_extent(trans, root, blocknr, num_blocks, pin, pin == 0);
C
Chris Mason 已提交
975
	pending_ret = del_pending_extents(trans, root->fs_info->extent_root);
976 977 978 979 980 981 982
	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
983
 * ins->flags = BTRFS_EXTENT_ITEM_KEY
984 985 986
 * ins->offset == number of blocks
 * Any available blocks before search_start are skipped.
 */
987 988
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
			    *orig_root, u64 num_blocks, u64 search_start, u64
989 990
			    search_end, u64 hint_block,
			    struct btrfs_key *ins, int data)
991
{
992
	struct btrfs_path *path;
C
Chris Mason 已提交
993
	struct btrfs_key key;
994 995 996
	int ret;
	u64 hole_size = 0;
	int slot = 0;
C
Chris Mason 已提交
997
	u64 last_block = 0;
C
Chris Mason 已提交
998
	u64 test_block;
C
Chris Mason 已提交
999
	u64 orig_search_start = search_start;
1000
	int start_found;
C
Chris Mason 已提交
1001
	struct btrfs_leaf *l;
1002
	struct btrfs_root * root = orig_root->fs_info->extent_root;
1003
	struct btrfs_fs_info *info = root->fs_info;
1004
	int total_needed = num_blocks;
1005 1006
	int total_found = 0;
	int fill_prealloc = 0;
C
Chris Mason 已提交
1007
	int level;
C
Chris Mason 已提交
1008
	struct btrfs_block_group_cache *block_group;
C
Chris Mason 已提交
1009
	int full_scan = 0;
1010
	int wrapped = 0;
1011
	u64 limit;
1012

1013 1014 1015
	ins->flags = 0;
	btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);

C
Chris Mason 已提交
1016
	level = btrfs_header_level(btrfs_buffer_header(root->node));
1017 1018 1019
	if (num_blocks == 0) {
		fill_prealloc = 1;
		num_blocks = 1;
1020
		total_needed = (min(level + 1, BTRFS_MAX_LEVEL) + 2) * 3;
1021
	}
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
	if (fill_prealloc) {
		u64 first;
		int nr = info->extent_tree_prealloc_nr;
		first = info->extent_tree_prealloc[nr - 1];
		if (info->extent_tree_prealloc_nr >= total_needed &&
		    first >= search_start) {
			ins->objectid = info->extent_tree_prealloc[0];
			ins->offset = 1;
			return 0;
		}
		info->extent_tree_prealloc_nr = 0;
	}
C
Chris Mason 已提交
1034
	if (search_end == (u64)-1)
1035
		search_end = btrfs_super_total_blocks(&info->super_copy);
1036
	if (hint_block) {
1037
		block_group = btrfs_lookup_block_group(info, hint_block);
C
Chris Mason 已提交
1038
		block_group = btrfs_find_block_group(root, block_group,
1039
						     hint_block, data, 1);
C
Chris Mason 已提交
1040 1041 1042
	} else {
		block_group = btrfs_find_block_group(root,
						     trans->block_group, 0,
1043
						     data, 1);
C
Chris Mason 已提交
1044 1045
	}

1046 1047
	path = btrfs_alloc_path();

C
Chris Mason 已提交
1048
check_failed:
C
Chris Mason 已提交
1049
	if (!block_group->data)
1050 1051
		search_start = find_search_start(root, &block_group,
						 search_start, total_needed);
1052
	else if (!full_scan)
1053 1054
		search_start = max(block_group->last_alloc, search_start);

1055
	btrfs_init_path(path);
1056 1057 1058
	ins->objectid = search_start;
	ins->offset = 0;
	start_found = 0;
1059

1060
	ret = btrfs_search_slot(trans, root, ins, path, 0, 0);
C
Chris Mason 已提交
1061 1062
	if (ret < 0)
		goto error;
C
Chris Mason 已提交
1063

1064
	if (path->slots[0] > 0) {
1065
		path->slots[0]--;
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
	}

	l = btrfs_buffer_leaf(path->nodes[0]);
	btrfs_disk_key_to_cpu(&key, &l->items[path->slots[0]].key);
	/*
	 * a rare case, go back one key if we hit a block group item
	 * instead of an extent item
	 */
	if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY &&
	    key.objectid + key.offset >= search_start) {
		ins->objectid = key.objectid;
		ins->offset = key.offset - 1;
		btrfs_release_path(root, path);
		ret = btrfs_search_slot(trans, root, ins, path, 0, 0);
		if (ret < 0)
			goto error;

		if (path->slots[0] > 0) {
			path->slots[0]--;
		}
	}
1087

1088
	while (1) {
1089 1090
		l = btrfs_buffer_leaf(path->nodes[0]);
		slot = path->slots[0];
1091
		if (slot >= btrfs_header_nritems(&l->header)) {
1092 1093 1094 1095
			if (fill_prealloc) {
				info->extent_tree_prealloc_nr = 0;
				total_found = 0;
			}
1096 1097
			if (start_found)
				limit = last_block +
C
Chris Mason 已提交
1098
					(block_group->key.offset >> 1);
1099 1100
			else
				limit = search_start +
C
Chris Mason 已提交
1101
					(block_group->key.offset >> 1);
1102
			ret = btrfs_next_leaf(root, path);
1103 1104
			if (ret == 0)
				continue;
C
Chris Mason 已提交
1105 1106
			if (ret < 0)
				goto error;
1107 1108
			if (!start_found) {
				ins->objectid = search_start;
C
Chris Mason 已提交
1109
				ins->offset = search_end - search_start;
1110 1111 1112 1113 1114
				start_found = 1;
				goto check_pending;
			}
			ins->objectid = last_block > search_start ?
					last_block : search_start;
C
Chris Mason 已提交
1115
			ins->offset = search_end - ins->objectid;
1116 1117
			goto check_pending;
		}
1118

C
Chris Mason 已提交
1119
		btrfs_disk_key_to_cpu(&key, &l->items[slot].key);
1120 1121 1122 1123 1124 1125 1126 1127 1128
		if (key.objectid >= search_start && key.objectid > last_block &&
		    start_found) {
			if (last_block < search_start)
				last_block = search_start;
			hole_size = key.objectid - last_block;
			if (hole_size >= num_blocks) {
				ins->objectid = last_block;
				ins->offset = hole_size;
				goto check_pending;
1129
			}
1130
		}
1131 1132 1133 1134

		if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY)
			goto next;

1135
		start_found = 1;
C
Chris Mason 已提交
1136
		last_block = key.objectid + key.offset;
1137
		if (!full_scan && last_block >= block_group->key.objectid +
C
Chris Mason 已提交
1138 1139 1140 1141 1142 1143
		    block_group->key.offset) {
			btrfs_release_path(root, path);
			search_start = block_group->key.objectid +
				block_group->key.offset * 2;
			goto new_group;
		}
C
Chris Mason 已提交
1144
next:
1145
		path->slots[0]++;
1146
		cond_resched();
1147 1148 1149 1150 1151
	}
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
	 */
1152
	btrfs_release_path(root, path);
1153
	BUG_ON(ins->objectid < search_start);
1154

C
Chris Mason 已提交
1155
	if (ins->objectid + num_blocks >= search_end) {
1156 1157 1158 1159
		if (full_scan) {
			ret = -ENOSPC;
			goto error;
		}
C
Chris Mason 已提交
1160
		search_start = orig_search_start;
1161 1162 1163 1164
		if (wrapped)
			full_scan = 1;
		else
			wrapped = 1;
C
Chris Mason 已提交
1165
		goto new_group;
1166
	}
C
Chris Mason 已提交
1167
	for (test_block = ins->objectid;
1168 1169
	     test_block < ins->objectid + num_blocks; test_block++) {
		if (test_radix_bit(&info->pinned_radix, test_block)) {
C
Chris Mason 已提交
1170
			search_start = test_block + 1;
C
Chris Mason 已提交
1171
			goto new_group;
1172 1173
		}
	}
1174 1175 1176 1177 1178 1179 1180
	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;
1181
			WARN_ON(!full_scan);
C
Chris Mason 已提交
1182
			goto new_group;
1183 1184 1185 1186 1187 1188 1189 1190
		}
	}
	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;
C
Chris Mason 已提交
1191
			goto new_group;
1192 1193 1194 1195 1196
		}
	}
	if (fill_prealloc) {
		int nr;
		test_block = ins->objectid;
1197 1198 1199 1200 1201
		if (test_block - info->extent_tree_prealloc[total_needed - 1] >=
		    leaf_range(root)) {
			total_found = 0;
			info->extent_tree_prealloc_nr = total_found;
		}
1202 1203 1204 1205
		while(test_block < ins->objectid + ins->offset &&
		      total_found < total_needed) {
			nr = total_needed - total_found - 1;
			BUG_ON(nr < 0);
C
Chris Mason 已提交
1206
			info->extent_tree_prealloc[nr] = test_block;
1207 1208 1209 1210 1211
			total_found++;
			test_block++;
		}
		if (total_found < total_needed) {
			search_start = test_block;
C
Chris Mason 已提交
1212
			goto new_group;
1213
		}
C
Chris Mason 已提交
1214 1215
		info->extent_tree_prealloc_nr = total_found;
	}
1216
	if (!data) {
1217
		block_group = btrfs_lookup_block_group(info, ins->objectid);
1218 1219 1220 1221 1222 1223 1224
		if (block_group) {
			if (fill_prealloc)
				block_group->last_prealloc =
				     info->extent_tree_prealloc[total_needed-1];
			else
				trans->block_group = block_group;
		}
1225
	}
C
Chris Mason 已提交
1226
	ins->offset = num_blocks;
1227
	btrfs_free_path(path);
1228
	return 0;
C
Chris Mason 已提交
1229 1230

new_group:
C
Chris Mason 已提交
1231
	if (search_start + num_blocks >= search_end) {
C
Chris Mason 已提交
1232
		search_start = orig_search_start;
1233 1234 1235 1236 1237 1238 1239 1240
		if (full_scan) {
			ret = -ENOSPC;
			goto error;
		}
		if (wrapped)
			full_scan = 1;
		else
			wrapped = 1;
C
Chris Mason 已提交
1241
	}
1242
	block_group = btrfs_lookup_block_group(info, search_start);
1243
	cond_resched();
C
Chris Mason 已提交
1244 1245
	if (!full_scan)
		block_group = btrfs_find_block_group(root, block_group,
1246
						     search_start, data, 0);
C
Chris Mason 已提交
1247 1248
	goto check_failed;

C
Chris Mason 已提交
1249
error:
1250 1251
	btrfs_release_path(root, path);
	btrfs_free_path(path);
C
Chris Mason 已提交
1252
	return ret;
1253 1254 1255 1256 1257 1258 1259 1260
}
/*
 * 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.
 */
1261 1262
int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
		       struct btrfs_root *root, u64 owner,
1263
		       u64 num_blocks, u64 hint_block,
C
Chris Mason 已提交
1264
		       u64 search_end, struct btrfs_key *ins, int data)
1265 1266 1267
{
	int ret;
	int pending_ret;
1268
	u64 super_blocks_used;
1269
	u64 search_start = 0;
1270 1271
	struct btrfs_fs_info *info = root->fs_info;
	struct btrfs_root *extent_root = info->extent_root;
C
Chris Mason 已提交
1272
	struct btrfs_extent_item extent_item;
1273
	struct btrfs_key prealloc_key;
C
Chris Mason 已提交
1274

C
Chris Mason 已提交
1275
	btrfs_set_extent_refs(&extent_item, 1);
1276
	btrfs_set_extent_owner(&extent_item, owner);
1277

C
Chris Mason 已提交
1278
	if (root == extent_root) {
1279 1280
		int nr;
		BUG_ON(info->extent_tree_prealloc_nr == 0);
C
Chris Mason 已提交
1281 1282
		BUG_ON(num_blocks != 1);
		ins->offset = 1;
1283 1284 1285 1286 1287
		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 已提交
1288
		ret = update_block_group(trans, root,
C
Chris Mason 已提交
1289
					 ins->objectid, ins->offset, 1, 0, 0);
C
Chris Mason 已提交
1290
		BUG_ON(ret);
1291 1292
		return 0;
	}
1293 1294 1295 1296 1297 1298 1299

	/*
	 * if we're doing a data allocation, preallocate room in the
	 * extent tree first.  This way the extent tree blocks end up
	 * in the correct block group.
	 */
	if (data) {
1300
		ret = find_free_extent(trans, root, 0, 0,
1301
				       search_end, 0, &prealloc_key, 0);
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
		if (ret) {
			return ret;
		}
		if (prealloc_key.objectid + prealloc_key.offset >= search_end) {
			int nr = info->extent_tree_prealloc_nr;
			search_end = info->extent_tree_prealloc[nr - 1] - 1;
		} else {
			search_start = info->extent_tree_prealloc[0] + 1;
		}
	}
1312 1313
	if (hint_block < search_start)
		hint_block = search_start;
1314
	/* do the real allocation */
1315
	ret = find_free_extent(trans, root, num_blocks, search_start,
1316
			       search_end, hint_block, ins, data);
1317
	if (ret) {
1318 1319 1320 1321 1322 1323 1324 1325 1326
		if (search_start == 0)
			return ret;
		search_end = search_start - 1;
		search_start = 0;
		hint_block = search_start;
		ret = find_free_extent(trans, root, num_blocks, search_start,
				       search_end, hint_block, ins, data);
		if (ret)
			return ret;
1327
	}
1328

1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342
	/*
	 * if we're doing a metadata allocation, preallocate space in the
	 * extent tree second.  This way, we don't create a tiny hole
	 * in the allocation map between any unused preallocation blocks
	 * and the metadata block we're actually allocating.  On disk,
	 * it'll go:
	 * [block we've allocated], [used prealloc 1], [ unused prealloc ]
	 * The unused prealloc will get reused the next time around.
	 */
	if (!data) {
		if (ins->objectid + ins->offset >= search_end)
			search_end = ins->objectid - 1;
		else
			search_start = ins->objectid + ins->offset;
C
Chris Mason 已提交
1343

1344 1345 1346
		if (hint_block < search_start)
			hint_block = search_start;

1347
		ret = find_free_extent(trans, root, 0, search_start,
1348 1349
				       search_end, hint_block,
				       &prealloc_key, 0);
1350
		if (ret) {
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
			if (search_start == 0)
				return ret;
			search_end = search_start - 1;
			search_start = 0;
			hint_block = search_start;
			ret = find_free_extent(trans, root, 0, search_start,
					       search_end, hint_block,
					       &prealloc_key, 0);
			if (ret)
				return ret;
1361 1362
		}
	}
1363

1364 1365
	super_blocks_used = btrfs_super_blocks_used(&info->super_copy);
	btrfs_set_super_blocks_used(&info->super_copy, super_blocks_used +
1366
				    num_blocks);
1367 1368
	ret = btrfs_insert_item(trans, extent_root, ins, &extent_item,
				sizeof(extent_item));
C
Chris Mason 已提交
1369

1370
	finish_current_insert(trans, extent_root);
C
Chris Mason 已提交
1371
	pending_ret = del_pending_extents(trans, extent_root);
1372
	if (ret) {
C
Chris Mason 已提交
1373
		return ret;
1374 1375
	}
	if (pending_ret) {
C
Chris Mason 已提交
1376
		return pending_ret;
1377
	}
C
Chris Mason 已提交
1378 1379
	ret = update_block_group(trans, root, ins->objectid, ins->offset, 1, 0,
				 data);
C
Chris Mason 已提交
1380
	BUG_ON(ret);
C
Chris Mason 已提交
1381
	return 0;
1382 1383 1384 1385 1386 1387
}

/*
 * helper function to allocate a block for a given tree
 * returns the tree buffer or NULL.
 */
C
Chris Mason 已提交
1388
struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
1389
					   struct btrfs_root *root, u64 hint)
1390
{
C
Chris Mason 已提交
1391
	struct btrfs_key ins;
1392
	int ret;
C
Chris Mason 已提交
1393
	struct buffer_head *buf;
1394

1395
	ret = btrfs_alloc_extent(trans, root, root->root_key.objectid,
1396
				 1, hint, (unsigned long)-1, &ins, 0);
1397
	if (ret) {
1398 1399
		BUG_ON(ret > 0);
		return ERR_PTR(ret);
1400
	}
1401
	buf = btrfs_find_create_tree_block(root, ins.objectid);
1402 1403 1404 1405
	if (!buf) {
		btrfs_free_extent(trans, root, ins.objectid, 1, 0);
		return ERR_PTR(-ENOMEM);
	}
1406
	set_buffer_uptodate(buf);
C
Chris Mason 已提交
1407
	set_buffer_checked(buf);
1408
	set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index);
1409 1410
	return buf;
}
1411

1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
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++) {
C
Chris Mason 已提交
1426
		u64 disk_blocknr;
1427 1428 1429 1430
		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);
1431 1432
		if (btrfs_file_extent_type(fi) == BTRFS_FILE_EXTENT_INLINE)
			continue;
1433 1434 1435 1436
		/*
		 * FIXME make sure to insert a trans record that
		 * repeats the snapshot del on crash
		 */
C
Chris Mason 已提交
1437 1438 1439 1440
		disk_blocknr = btrfs_file_extent_disk_blocknr(fi);
		if (disk_blocknr == 0)
			continue;
		ret = btrfs_free_extent(trans, root, disk_blocknr,
1441 1442 1443 1444 1445 1446 1447
					btrfs_file_extent_disk_num_blocks(fi),
					0);
		BUG_ON(ret);
	}
	return 0;
}

1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469
static void reada_walk_down(struct btrfs_root *root,
			    struct btrfs_node *node)
{
	int i;
	u32 nritems;
	u64 blocknr;
	int ret;
	u32 refs;

	nritems = btrfs_header_nritems(&node->header);
	for (i = 0; i < nritems; i++) {
		blocknr = btrfs_node_blockptr(node, i);
		ret = lookup_extent_ref(NULL, root, blocknr, 1, &refs);
		BUG_ON(ret);
		if (refs != 1)
			continue;
		ret = readahead_tree_block(root, blocknr);
		if (ret)
			break;
	}
}

C
Chris Mason 已提交
1470 1471 1472 1473
/*
 * helper function for drop_snapshot, this walks down the tree dropping ref
 * counts as it goes.
 */
1474 1475
static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
			  *root, struct btrfs_path *path, int *level)
C
Chris Mason 已提交
1476
{
C
Chris Mason 已提交
1477 1478
	struct buffer_head *next;
	struct buffer_head *cur;
C
Chris Mason 已提交
1479 1480 1481 1482
	u64 blocknr;
	int ret;
	u32 refs;

1483 1484
	WARN_ON(*level < 0);
	WARN_ON(*level >= BTRFS_MAX_LEVEL);
C
Chris Mason 已提交
1485
	ret = lookup_extent_ref(trans, root, bh_blocknr(path->nodes[*level]),
1486
			       1, &refs);
C
Chris Mason 已提交
1487 1488 1489
	BUG_ON(ret);
	if (refs > 1)
		goto out;
1490

C
Chris Mason 已提交
1491 1492 1493
	/*
	 * walk down to the last node level and free all the leaves
	 */
1494
	while(*level >= 0) {
1495 1496
		WARN_ON(*level < 0);
		WARN_ON(*level >= BTRFS_MAX_LEVEL);
C
Chris Mason 已提交
1497
		cur = path->nodes[*level];
1498 1499 1500 1501

		if (*level > 0 && path->slots[*level] == 0)
			reada_walk_down(root, btrfs_buffer_node(cur));

C
Chris Mason 已提交
1502 1503
		if (btrfs_header_level(btrfs_buffer_header(cur)) != *level)
			WARN_ON(1);
1504

1505
		if (path->slots[*level] >=
C
Chris Mason 已提交
1506
		    btrfs_header_nritems(btrfs_buffer_header(cur)))
C
Chris Mason 已提交
1507
			break;
1508 1509 1510 1511 1512
		if (*level == 0) {
			ret = drop_leaf_ref(trans, root, cur);
			BUG_ON(ret);
			break;
		}
C
Chris Mason 已提交
1513 1514
		blocknr = btrfs_node_blockptr(btrfs_buffer_node(cur),
					      path->slots[*level]);
C
Chris Mason 已提交
1515
		ret = lookup_extent_ref(trans, root, blocknr, 1, &refs);
1516 1517
		BUG_ON(ret);
		if (refs != 1) {
C
Chris Mason 已提交
1518
			path->slots[*level]++;
1519
			ret = btrfs_free_extent(trans, root, blocknr, 1, 1);
C
Chris Mason 已提交
1520 1521 1522 1523
			BUG_ON(ret);
			continue;
		}
		next = read_tree_block(root, blocknr);
1524
		WARN_ON(*level <= 0);
C
Chris Mason 已提交
1525
		if (path->nodes[*level-1])
C
Chris Mason 已提交
1526
			btrfs_block_release(root, path->nodes[*level-1]);
C
Chris Mason 已提交
1527
		path->nodes[*level-1] = next;
C
Chris Mason 已提交
1528
		*level = btrfs_header_level(btrfs_buffer_header(next));
C
Chris Mason 已提交
1529 1530 1531
		path->slots[*level] = 0;
	}
out:
1532 1533
	WARN_ON(*level < 0);
	WARN_ON(*level >= BTRFS_MAX_LEVEL);
1534
	ret = btrfs_free_extent(trans, root,
1535
				bh_blocknr(path->nodes[*level]), 1, 1);
C
Chris Mason 已提交
1536
	btrfs_block_release(root, path->nodes[*level]);
C
Chris Mason 已提交
1537 1538 1539 1540 1541 1542
	path->nodes[*level] = NULL;
	*level += 1;
	BUG_ON(ret);
	return 0;
}

C
Chris Mason 已提交
1543 1544 1545 1546 1547
/*
 * 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
 */
1548 1549
static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root
			*root, struct btrfs_path *path, int *level)
C
Chris Mason 已提交
1550 1551 1552 1553
{
	int i;
	int slot;
	int ret;
C
Chris Mason 已提交
1554
	for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) {
C
Chris Mason 已提交
1555
		slot = path->slots[i];
C
Chris Mason 已提交
1556 1557
		if (slot < btrfs_header_nritems(
		    btrfs_buffer_header(path->nodes[i])) - 1) {
C
Chris Mason 已提交
1558 1559 1560 1561
			path->slots[i]++;
			*level = i;
			return 0;
		} else {
1562
			ret = btrfs_free_extent(trans, root,
1563
						bh_blocknr(path->nodes[*level]),
1564
						1, 1);
1565
			BUG_ON(ret);
C
Chris Mason 已提交
1566
			btrfs_block_release(root, path->nodes[*level]);
C
Chris Mason 已提交
1567
			path->nodes[*level] = NULL;
C
Chris Mason 已提交
1568 1569 1570 1571 1572 1573
			*level = i + 1;
		}
	}
	return 1;
}

C
Chris Mason 已提交
1574 1575 1576 1577 1578
/*
 * 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.
 */
1579
int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
C
Chris Mason 已提交
1580
			*root, struct buffer_head *snap)
C
Chris Mason 已提交
1581
{
1582
	int ret = 0;
C
Chris Mason 已提交
1583
	int wret;
C
Chris Mason 已提交
1584
	int level;
1585
	struct btrfs_path *path;
C
Chris Mason 已提交
1586 1587 1588
	int i;
	int orig_level;

1589 1590
	path = btrfs_alloc_path();
	BUG_ON(!path);
C
Chris Mason 已提交
1591

C
Chris Mason 已提交
1592
	level = btrfs_header_level(btrfs_buffer_header(snap));
C
Chris Mason 已提交
1593
	orig_level = level;
1594 1595
	path->nodes[level] = snap;
	path->slots[level] = 0;
C
Chris Mason 已提交
1596
	while(1) {
1597
		wret = walk_down_tree(trans, root, path, &level);
C
Chris Mason 已提交
1598
		if (wret > 0)
C
Chris Mason 已提交
1599
			break;
C
Chris Mason 已提交
1600 1601 1602
		if (wret < 0)
			ret = wret;

1603
		wret = walk_up_tree(trans, root, path, &level);
C
Chris Mason 已提交
1604
		if (wret > 0)
C
Chris Mason 已提交
1605
			break;
C
Chris Mason 已提交
1606 1607
		if (wret < 0)
			ret = wret;
C
Chris Mason 已提交
1608
	}
C
Chris Mason 已提交
1609
	for (i = 0; i <= orig_level; i++) {
1610 1611
		if (path->nodes[i]) {
			btrfs_block_release(root, path->nodes[i]);
C
Chris Mason 已提交
1612
		}
C
Chris Mason 已提交
1613
	}
1614
	btrfs_free_path(path);
C
Chris Mason 已提交
1615
	return ret;
C
Chris Mason 已提交
1616
}
C
Chris Mason 已提交
1617

C
Chris Mason 已提交
1618
static int free_block_group_radix(struct radix_tree_root *radix)
C
Chris Mason 已提交
1619 1620 1621 1622 1623 1624
{
	int ret;
	struct btrfs_block_group_cache *cache[8];
	int i;

	while(1) {
C
Chris Mason 已提交
1625
		ret = radix_tree_gang_lookup(radix, (void **)cache, 0,
C
Chris Mason 已提交
1626 1627 1628 1629
					     ARRAY_SIZE(cache));
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
C
Chris Mason 已提交
1630
			radix_tree_delete(radix, cache[i]->key.objectid +
C
Chris Mason 已提交
1631 1632 1633 1634 1635 1636 1637
					  cache[i]->key.offset - 1);
			kfree(cache[i]);
		}
	}
	return 0;
}

C
Chris Mason 已提交
1638 1639 1640 1641
int btrfs_free_block_groups(struct btrfs_fs_info *info)
{
	int ret;
	int ret2;
1642 1643
	unsigned long gang[16];
	int i;
C
Chris Mason 已提交
1644 1645 1646 1647 1648 1649 1650

	ret = free_block_group_radix(&info->block_group_radix);
	ret2 = free_block_group_radix(&info->block_group_data_radix);
	if (ret)
		return ret;
	if (ret2)
		return ret2;
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660

	while(1) {
		ret = find_first_radix_bit(&info->extent_map_radix,
					   gang, 0, ARRAY_SIZE(gang));
		if (!ret)
			break;
		for (i = 0; i < ret; i++) {
			clear_radix_bit(&info->extent_map_radix, gang[i]);
		}
	}
C
Chris Mason 已提交
1661 1662 1663
	return 0;
}

C
Chris Mason 已提交
1664 1665 1666 1667 1668 1669 1670
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;
C
Chris Mason 已提交
1671 1672
	struct btrfs_fs_info *info = root->fs_info;
	struct radix_tree_root *radix;
C
Chris Mason 已提交
1673 1674 1675
	struct btrfs_key key;
	struct btrfs_key found_key;
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1676
	u64 group_size_blocks;
1677
	u64 used;
C
Chris Mason 已提交
1678

C
Chris Mason 已提交
1679 1680
	group_size_blocks = BTRFS_BLOCK_GROUP_SIZE >>
		root->fs_info->sb->s_blocksize_bits;
C
Chris Mason 已提交
1681
	root = info->extent_root;
C
Chris Mason 已提交
1682 1683 1684 1685 1686 1687 1688 1689 1690 1691
	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) {
C
Chris Mason 已提交
1692
		ret = btrfs_search_slot(NULL, info->extent_root,
C
Chris Mason 已提交
1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705
					&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;
		}
C
Chris Mason 已提交
1706

C
Chris Mason 已提交
1707 1708 1709
		bi = btrfs_item_ptr(leaf, path->slots[0],
				    struct btrfs_block_group_item);
		if (bi->flags & BTRFS_BLOCK_GROUP_DATA) {
C
Chris Mason 已提交
1710
			radix = &info->block_group_data_radix;
C
Chris Mason 已提交
1711 1712
			cache->data = 1;
		} else {
C
Chris Mason 已提交
1713
			radix = &info->block_group_radix;
C
Chris Mason 已提交
1714 1715
			cache->data = 0;
		}
C
Chris Mason 已提交
1716

C
Chris Mason 已提交
1717 1718
		memcpy(&cache->item, bi, sizeof(*bi));
		memcpy(&cache->key, &found_key, sizeof(found_key));
1719 1720
		cache->last_alloc = cache->key.objectid;
		cache->first_free = cache->key.objectid;
1721
		cache->last_prealloc = cache->key.objectid;
C
Chris Mason 已提交
1722
		cache->pinned = 0;
1723 1724
		cache->cached = 0;

C
Chris Mason 已提交
1725 1726
		cache->radix = radix;

C
Chris Mason 已提交
1727 1728
		key.objectid = found_key.objectid + found_key.offset;
		btrfs_release_path(root, path);
C
Chris Mason 已提交
1729
		ret = radix_tree_insert(radix, found_key.objectid +
C
Chris Mason 已提交
1730 1731 1732
					found_key.offset - 1,
					(void *)cache);
		BUG_ON(ret);
1733
		used = btrfs_block_group_used(bi);
C
Chris Mason 已提交
1734
		if (used < div_factor(key.offset, 8)) {
C
Chris Mason 已提交
1735
			radix_tree_tag_set(radix, found_key.objectid +
1736 1737 1738
					   found_key.offset - 1,
					   BTRFS_BLOCK_GROUP_AVAIL);
		}
C
Chris Mason 已提交
1739
		if (key.objectid >=
1740
		    btrfs_super_total_blocks(&info->super_copy))
C
Chris Mason 已提交
1741 1742 1743 1744 1745 1746
			break;
	}

	btrfs_free_path(path);
	return 0;
}