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:
commit
d6a0967c90
|
@ -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:
|
||||||
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:
|
||||||
|
|
||||||
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
|
||||||
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:
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
* 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)
|
||||||
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,
|
||||||
*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,
|
||||||
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,
|
||||||
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;
|
||||||
|
|
Loading…
Reference in a new issue