Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable

* git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable:
  Btrfs: fix balancing oops when invalidate_inode_pages2 returns EBUSY
  Btrfs: correct error-handling zlib error handling
  Btrfs: remove superfluous NULL pointer check in btrfs_rename()
  Btrfs: make sure the async caching thread advances the key
  Btrfs: fix btrfs_remove_from_free_space corner case
This commit is contained in:
Linus Torvalds 2009-08-07 19:03:09 -07:00
commit d6a0967c90
5 changed files with 92 additions and 20 deletions

View file

@ -265,10 +265,6 @@ static int caching_kthread(void *data)
atomic_inc(&block_group->space_info->caching_threads);
last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET);
again:
/* need to make sure the commit_root doesn't disappear */
down_read(&fs_info->extent_commit_sem);
/*
* We don't want to deadlock with somebody trying to allocate a new
* extent for the extent root while also trying to search the extent
@ -282,6 +278,10 @@ static int caching_kthread(void *data)
key.objectid = last;
key.offset = 0;
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
again:
/* need to make sure the commit_root doesn't disappear */
down_read(&fs_info->extent_commit_sem);
ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0);
if (ret < 0)
goto err;
@ -304,6 +304,19 @@ static int caching_kthread(void *data)
if (need_resched() ||
btrfs_transaction_in_commit(fs_info)) {
leaf = path->nodes[0];
/* this shouldn't happen, but if the
* leaf is empty just move on.
*/
if (btrfs_header_nritems(leaf) == 0)
break;
/*
* we need to copy the key out so that
* we are sure the next search advances
* us forward in the btree.
*/
btrfs_item_key_to_cpu(leaf, &key, 0);
btrfs_release_path(fs_info->extent_root, path);
up_read(&fs_info->extent_commit_sem);
schedule_timeout(1);

View file

@ -414,11 +414,29 @@ static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_gro
u64 *offset, u64 *bytes)
{
u64 end;
u64 search_start, search_bytes;
int ret;
again:
end = bitmap_info->offset +
(u64)(BITS_PER_BITMAP * block_group->sectorsize) - 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.
*/
search_start = *offset;
search_bytes = *bytes;
ret = search_bitmap(block_group, bitmap_info, &search_start,
&search_bytes);
BUG_ON(ret < 0 || search_start != *offset);
if (*offset > bitmap_info->offset && *offset + *bytes > end) {
bitmap_clear_bits(block_group, bitmap_info, *offset,
end - *offset + 1);
@ -430,6 +448,7 @@ static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_gro
}
if (*bytes) {
struct rb_node *next = rb_next(&bitmap_info->offset_index);
if (!bitmap_info->bytes) {
unlink_free_space(block_group, bitmap_info);
kfree(bitmap_info->bitmap);
@ -438,16 +457,36 @@ static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_gro
recalculate_thresholds(block_group);
}
bitmap_info = tree_search_offset(block_group,
offset_to_bitmap(block_group,
*offset),
1, 0);
if (!bitmap_info)
/*
* no entry after this bitmap, but we still have bytes to
* remove, so something has gone wrong.
*/
if (!next)
return -EINVAL;
bitmap_info = rb_entry(next, struct btrfs_free_space,
offset_index);
/*
* if the next entry isn't a bitmap we need to return to let the
* extent stuff do its work.
*/
if (!bitmap_info->bitmap)
return -EAGAIN;
/*
* Ok the next item is a bitmap, but it may not actually hold
* the information for the rest of this free space stuff, so
* look for it, and if we don't find it return so we can try
* everything over again.
*/
search_start = *offset;
search_bytes = *bytes;
ret = search_bitmap(block_group, bitmap_info, &search_start,
&search_bytes);
if (ret < 0 || search_start != *offset)
return -EAGAIN;
goto again;
} else if (!bitmap_info->bytes) {
unlink_free_space(block_group, bitmap_info);
@ -644,8 +683,17 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
again:
info = tree_search_offset(block_group, offset, 0, 0);
if (!info) {
WARN_ON(1);
goto out_lock;
/*
* oops didn't find an extent that matched the space we wanted
* to remove, look for a bitmap instead
*/
info = tree_search_offset(block_group,
offset_to_bitmap(block_group, offset),
1, 0);
if (!info) {
WARN_ON(1);
goto out_lock;
}
}
if (info->bytes < bytes && rb_next(&info->offset_index)) {
@ -957,8 +1005,15 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group,
if (cluster->block_group != block_group)
goto out;
entry = tree_search_offset(block_group, search_start, 0, 0);
/*
* search_start is the beginning of the bitmap, but at some point it may
* be a good idea to point to the actual start of the free area in the
* bitmap, so do the offset_to_bitmap trick anyway, and set bitmap_only
* to 1 to make sure we get the bitmap entry
*/
entry = tree_search_offset(block_group,
offset_to_bitmap(block_group, search_start),
1, 0);
if (!entry || !entry->bitmap)
goto out;

View file

@ -4785,8 +4785,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
* and the replacement file is large. Start IO on it now so
* we don't add too much work to the end of the transaction
*/
if (new_inode && old_inode && S_ISREG(old_inode->i_mode) &&
new_inode->i_size &&
if (new_inode && S_ISREG(old_inode->i_mode) && new_inode->i_size &&
old_inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT)
filemap_flush(old_inode->i_mapping);

View file

@ -2553,8 +2553,13 @@ int relocate_inode_pages(struct inode *inode, u64 start, u64 len)
last_index = (start + len - 1) >> PAGE_CACHE_SHIFT;
/* make sure the dirty trick played by the caller work */
ret = invalidate_inode_pages2_range(inode->i_mapping,
first_index, last_index);
while (1) {
ret = invalidate_inode_pages2_range(inode->i_mapping,
first_index, last_index);
if (ret != -EBUSY)
break;
schedule_timeout(HZ/10);
}
if (ret)
goto out_unlock;

View file

@ -208,7 +208,7 @@ int btrfs_zlib_compress_pages(struct address_space *mapping,
*total_in = 0;
workspace = find_zlib_workspace();
if (!workspace)
if (IS_ERR(workspace))
return -1;
if (Z_OK != zlib_deflateInit(&workspace->def_strm, 3)) {
@ -366,7 +366,7 @@ int btrfs_zlib_decompress_biovec(struct page **pages_in,
char *kaddr;
workspace = find_zlib_workspace();
if (!workspace)
if (IS_ERR(workspace))
return -ENOMEM;
data_in = kmap(pages_in[page_in_index]);
@ -547,7 +547,7 @@ int btrfs_zlib_decompress(unsigned char *data_in,
return -ENOMEM;
workspace = find_zlib_workspace();
if (!workspace)
if (IS_ERR(workspace))
return -ENOMEM;
workspace->inf_strm.next_in = data_in;