Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 311663
b: refs/heads/master
c: bdb7d30
h: refs/heads/master
i:
  311661: c094fc1
  311659: 42b5f47
  311655: 288790b
  311647: 5fd51f3
v: v3
  • Loading branch information
Josef Bacik authored and Chris Mason committed Jul 2, 2012
1 parent 9b961a7 commit 1d6c950
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 94 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6bf02314d9a5c29f6ec30285b9ad5361c2d4c85a
refs/heads/master: bdb7d303b33c1648514c9f9461d7513a4c05ce48
145 changes: 52 additions & 93 deletions trunk/fs/btrfs/free-space-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1542,29 +1542,26 @@ static noinline int remove_from_bitmap(struct btrfs_free_space_ctl *ctl,
end = bitmap_info->offset + (u64)(BITS_PER_BITMAP * ctl->unit) - 1;

/*
* XXX - this can go away after a few releases.
*
* since the only user of btrfs_remove_free_space is the tree logging
* stuff, and the only way to test that is under crash conditions, we
* want to have this debug stuff here just in case somethings not
* working. Search the bitmap for the space we are trying to use to
* make sure its actually there. If its not there then we need to stop
* because something has gone wrong.
* We need to search for bits in this bitmap. We could only cover some
* of the extent in this bitmap thanks to how we add space, so we need
* to search for as much as it as we can and clear that amount, and then
* go searching for the next bit.
*/
search_start = *offset;
search_bytes = *bytes;
search_bytes = ctl->unit;
search_bytes = min(search_bytes, end - search_start + 1);
ret = search_bitmap(ctl, bitmap_info, &search_start, &search_bytes);
BUG_ON(ret < 0 || search_start != *offset);

if (*offset > bitmap_info->offset && *offset + *bytes > end) {
bitmap_clear_bits(ctl, bitmap_info, *offset, end - *offset + 1);
*bytes -= end - *offset + 1;
*offset = end + 1;
} else if (*offset >= bitmap_info->offset && *offset + *bytes <= end) {
bitmap_clear_bits(ctl, bitmap_info, *offset, *bytes);
*bytes = 0;
}
/* We may have found more bits than what we need */
search_bytes = min(search_bytes, *bytes);

/* Cannot clear past the end of the bitmap */
search_bytes = min(search_bytes, end - search_start + 1);

bitmap_clear_bits(ctl, bitmap_info, search_start, search_bytes);
*offset += search_bytes;
*bytes -= search_bytes;

if (*bytes) {
struct rb_node *next = rb_next(&bitmap_info->offset_index);
Expand Down Expand Up @@ -1595,7 +1592,7 @@ static noinline int remove_from_bitmap(struct btrfs_free_space_ctl *ctl,
* everything over again.
*/
search_start = *offset;
search_bytes = *bytes;
search_bytes = ctl->unit;
ret = search_bitmap(ctl, bitmap_info, &search_start,
&search_bytes);
if (ret < 0 || search_start != *offset)
Expand Down Expand Up @@ -1878,12 +1875,14 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
{
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
struct btrfs_free_space *info;
struct btrfs_free_space *next_info = NULL;
int ret = 0;

spin_lock(&ctl->tree_lock);

again:
if (!bytes)
goto out_lock;

info = tree_search_offset(ctl, offset, 0, 0);
if (!info) {
/*
Expand All @@ -1904,88 +1903,48 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
}
}

if (info->bytes < bytes && rb_next(&info->offset_index)) {
u64 end;
next_info = rb_entry(rb_next(&info->offset_index),
struct btrfs_free_space,
offset_index);

if (next_info->bitmap)
end = next_info->offset +
BITS_PER_BITMAP * ctl->unit - 1;
else
end = next_info->offset + next_info->bytes;

if (next_info->bytes < bytes ||
next_info->offset > offset || offset > end) {
printk(KERN_CRIT "Found free space at %llu, size %llu,"
" trying to use %llu\n",
(unsigned long long)info->offset,
(unsigned long long)info->bytes,
(unsigned long long)bytes);
WARN_ON(1);
ret = -EINVAL;
goto out_lock;
}

info = next_info;
}

if (info->bytes == bytes) {
if (!info->bitmap) {
unlink_free_space(ctl, info);
if (info->bitmap) {
kfree(info->bitmap);
ctl->total_bitmaps--;
}
kmem_cache_free(btrfs_free_space_cachep, info);
ret = 0;
goto out_lock;
}

if (!info->bitmap && info->offset == offset) {
unlink_free_space(ctl, info);
info->offset += bytes;
info->bytes -= bytes;
ret = link_free_space(ctl, info);
WARN_ON(ret);
goto out_lock;
}
if (offset == info->offset) {
u64 to_free = min(bytes, info->bytes);

info->bytes -= to_free;
info->offset += to_free;
if (info->bytes) {
ret = link_free_space(ctl, info);
WARN_ON(ret);
} else {
kmem_cache_free(btrfs_free_space_cachep, info);
}

if (!info->bitmap && info->offset <= offset &&
info->offset + info->bytes >= offset + bytes) {
u64 old_start = info->offset;
/*
* we're freeing space in the middle of the info,
* this can happen during tree log replay
*
* first unlink the old info and then
* insert it again after the hole we're creating
*/
unlink_free_space(ctl, info);
if (offset + bytes < info->offset + info->bytes) {
u64 old_end = info->offset + info->bytes;
offset += to_free;
bytes -= to_free;
goto again;
} else {
u64 old_end = info->bytes + info->offset;

info->offset = offset + bytes;
info->bytes = old_end - info->offset;
info->bytes = offset - info->offset;
ret = link_free_space(ctl, info);
WARN_ON(ret);
if (ret)
goto out_lock;
} else {
/* the hole we're creating ends at the end
* of the info struct, just free the info
*/
kmem_cache_free(btrfs_free_space_cachep, info);
}
spin_unlock(&ctl->tree_lock);

/* step two, insert a new info struct to cover
* anything before the hole
*/
ret = btrfs_add_free_space(block_group, old_start,
offset - old_start);
WARN_ON(ret); /* -ENOMEM */
goto out;
/* Not enough bytes in this entry to satisfy us */
if (old_end < offset + bytes) {
bytes -= old_end - offset;
offset = old_end;
goto again;
} else if (old_end == offset + bytes) {
/* all done */
goto out_lock;
}
spin_unlock(&ctl->tree_lock);

ret = btrfs_add_free_space(block_group, offset + bytes,
old_end - (offset + bytes));
WARN_ON(ret);
goto out;
}
}

ret = remove_from_bitmap(ctl, info, &offset, &bytes);
Expand Down

0 comments on commit 1d6c950

Please sign in to comment.