Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d6a0967c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 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
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -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);
+64 −9
Original line number Diff line number Diff line
@@ -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);
@@ -643,10 +682,19 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,

again:
	info = tree_search_offset(block_group, offset, 0, 0);
	if (!info) {
		/*
		 * 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)) {
		u64 end;
@@ -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;

+1 −2
Original line number Diff line number Diff line
@@ -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);

+7 −2
Original line number Diff line number Diff line
@@ -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 */
	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;

+3 −3
Original line number Diff line number Diff line
@@ -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;