Commit d6a0967c authored by Linus Torvalds's avatar Linus Torvalds

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
parents fb385003 ceab36ed
...@@ -265,10 +265,6 @@ static int caching_kthread(void *data) ...@@ -265,10 +265,6 @@ static int caching_kthread(void *data)
atomic_inc(&block_group->space_info->caching_threads); atomic_inc(&block_group->space_info->caching_threads);
last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); 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 * 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 * extent for the extent root while also trying to search the extent
...@@ -282,6 +278,10 @@ again: ...@@ -282,6 +278,10 @@ again:
key.objectid = last; key.objectid = last;
key.offset = 0; key.offset = 0;
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); 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); ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0);
if (ret < 0) if (ret < 0)
goto err; goto err;
...@@ -304,6 +304,19 @@ again: ...@@ -304,6 +304,19 @@ again:
if (need_resched() || if (need_resched() ||
btrfs_transaction_in_commit(fs_info)) { 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); btrfs_release_path(fs_info->extent_root, path);
up_read(&fs_info->extent_commit_sem); up_read(&fs_info->extent_commit_sem);
schedule_timeout(1); schedule_timeout(1);
......
...@@ -414,11 +414,29 @@ static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_gro ...@@ -414,11 +414,29 @@ static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_gro
u64 *offset, u64 *bytes) u64 *offset, u64 *bytes)
{ {
u64 end; u64 end;
u64 search_start, search_bytes;
int ret;
again: again:
end = bitmap_info->offset + end = bitmap_info->offset +
(u64)(BITS_PER_BITMAP * block_group->sectorsize) - 1; (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) { if (*offset > bitmap_info->offset && *offset + *bytes > end) {
bitmap_clear_bits(block_group, bitmap_info, *offset, bitmap_clear_bits(block_group, bitmap_info, *offset,
end - *offset + 1); end - *offset + 1);
...@@ -430,6 +448,7 @@ again: ...@@ -430,6 +448,7 @@ again:
} }
if (*bytes) { if (*bytes) {
struct rb_node *next = rb_next(&bitmap_info->offset_index);
if (!bitmap_info->bytes) { if (!bitmap_info->bytes) {
unlink_free_space(block_group, bitmap_info); unlink_free_space(block_group, bitmap_info);
kfree(bitmap_info->bitmap); kfree(bitmap_info->bitmap);
...@@ -438,16 +457,36 @@ again: ...@@ -438,16 +457,36 @@ again:
recalculate_thresholds(block_group); recalculate_thresholds(block_group);
} }
bitmap_info = tree_search_offset(block_group, /*
offset_to_bitmap(block_group, * no entry after this bitmap, but we still have bytes to
*offset), * remove, so something has gone wrong.
1, 0); */
if (!bitmap_info) if (!next)
return -EINVAL; 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) if (!bitmap_info->bitmap)
return -EAGAIN; 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; goto again;
} else if (!bitmap_info->bytes) { } else if (!bitmap_info->bytes) {
unlink_free_space(block_group, bitmap_info); unlink_free_space(block_group, bitmap_info);
...@@ -644,8 +683,17 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, ...@@ -644,8 +683,17 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
again: again:
info = tree_search_offset(block_group, offset, 0, 0); info = tree_search_offset(block_group, offset, 0, 0);
if (!info) { 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)) { 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, ...@@ -957,8 +1005,15 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group,
if (cluster->block_group != block_group) if (cluster->block_group != block_group)
goto out; 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) if (!entry || !entry->bitmap)
goto out; goto out;
......
...@@ -4785,8 +4785,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -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 * 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 * we don't add too much work to the end of the transaction
*/ */
if (new_inode && old_inode && S_ISREG(old_inode->i_mode) && if (new_inode && S_ISREG(old_inode->i_mode) && new_inode->i_size &&
new_inode->i_size &&
old_inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) old_inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT)
filemap_flush(old_inode->i_mapping); filemap_flush(old_inode->i_mapping);
......
...@@ -2553,8 +2553,13 @@ int relocate_inode_pages(struct inode *inode, u64 start, u64 len) ...@@ -2553,8 +2553,13 @@ int relocate_inode_pages(struct inode *inode, u64 start, u64 len)
last_index = (start + len - 1) >> PAGE_CACHE_SHIFT; last_index = (start + len - 1) >> PAGE_CACHE_SHIFT;
/* make sure the dirty trick played by the caller work */ /* make sure the dirty trick played by the caller work */
ret = invalidate_inode_pages2_range(inode->i_mapping, while (1) {
first_index, last_index); ret = invalidate_inode_pages2_range(inode->i_mapping,
first_index, last_index);
if (ret != -EBUSY)
break;
schedule_timeout(HZ/10);
}
if (ret) if (ret)
goto out_unlock; goto out_unlock;
......
...@@ -208,7 +208,7 @@ int btrfs_zlib_compress_pages(struct address_space *mapping, ...@@ -208,7 +208,7 @@ int btrfs_zlib_compress_pages(struct address_space *mapping,
*total_in = 0; *total_in = 0;
workspace = find_zlib_workspace(); workspace = find_zlib_workspace();
if (!workspace) if (IS_ERR(workspace))
return -1; return -1;
if (Z_OK != zlib_deflateInit(&workspace->def_strm, 3)) { if (Z_OK != zlib_deflateInit(&workspace->def_strm, 3)) {
...@@ -366,7 +366,7 @@ int btrfs_zlib_decompress_biovec(struct page **pages_in, ...@@ -366,7 +366,7 @@ int btrfs_zlib_decompress_biovec(struct page **pages_in,
char *kaddr; char *kaddr;
workspace = find_zlib_workspace(); workspace = find_zlib_workspace();
if (!workspace) if (IS_ERR(workspace))
return -ENOMEM; return -ENOMEM;
data_in = kmap(pages_in[page_in_index]); data_in = kmap(pages_in[page_in_index]);
...@@ -547,7 +547,7 @@ int btrfs_zlib_decompress(unsigned char *data_in, ...@@ -547,7 +547,7 @@ int btrfs_zlib_decompress(unsigned char *data_in,
return -ENOMEM; return -ENOMEM;
workspace = find_zlib_workspace(); workspace = find_zlib_workspace();
if (!workspace) if (IS_ERR(workspace))
return -ENOMEM; return -ENOMEM;
workspace->inf_strm.next_in = data_in; workspace->inf_strm.next_in = data_in;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment