Commit b3f1da2a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:

 - multiple error handling fixes of unexpected conditions

 - reset block group size class once it becomes empty so that
   its class can be changed

 - error message level adjustments

 - fixes of returned error values

 - use correct block reserve for delayed refs

* tag 'for-7.0-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix invalid leaf access in btrfs_quota_enable() if ref key not found
  btrfs: fix lost error return in btrfs_find_orphan_roots()
  btrfs: fix lost return value on error in finish_verity()
  btrfs: change unaligned root messages to error level in btrfs_validate_super()
  btrfs: use the correct type to initialize block reserve for delayed refs
  btrfs: do not ASSERT() when the fs flips RO inside btrfs_repair_io_failure()
  btrfs: reset block group size class when it becomes empty
  btrfs: replace BUG() with error handling in __btrfs_balance()
  btrfs: handle unexpected exact match in btrfs_set_inode_index_count()
parents 233a0c0f ecb7c248
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -934,7 +934,6 @@ int btrfs_repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 fileoff,
	struct bio *bio = NULL;
	int ret = 0;

	ASSERT(!(fs_info->sb->s_flags & SB_RDONLY));
	BUG_ON(!mirror_num);

	/* Basic alignment checks. */
@@ -946,6 +945,13 @@ int btrfs_repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 fileoff,
	ASSERT(step <= length);
	ASSERT(is_power_of_2(step));

	/*
	 * The fs either mounted RO or hit critical errors, no need
	 * to continue repairing.
	 */
	if (unlikely(sb_rdonly(fs_info->sb)))
		return 0;

	if (btrfs_repair_one_zone(fs_info, logical))
		return 0;

+10 −0
Original line number Diff line number Diff line
@@ -3760,6 +3760,14 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans)
	return ret;
}

static void btrfs_maybe_reset_size_class(struct btrfs_block_group *bg)
{
	lockdep_assert_held(&bg->lock);
	if (btrfs_block_group_should_use_size_class(bg) &&
	    bg->used == 0 && bg->reserved == 0)
		bg->size_class = BTRFS_BG_SZ_NONE;
}

int btrfs_update_block_group(struct btrfs_trans_handle *trans,
			     u64 bytenr, u64 num_bytes, bool alloc)
{
@@ -3824,6 +3832,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
		old_val -= num_bytes;
		cache->used = old_val;
		cache->pinned += num_bytes;
		btrfs_maybe_reset_size_class(cache);
		btrfs_space_info_update_bytes_pinned(space_info, num_bytes);
		space_info->bytes_used -= num_bytes;
		space_info->disk_used -= num_bytes * factor;
@@ -3952,6 +3961,7 @@ void btrfs_free_reserved_bytes(struct btrfs_block_group *cache, u64 num_bytes,
	spin_lock(&cache->lock);
	bg_ro = cache->ro;
	cache->reserved -= num_bytes;
	btrfs_maybe_reset_size_class(cache);
	if (is_delalloc)
		cache->delalloc_bytes -= num_bytes;
	spin_unlock(&cache->lock);
+4 −3
Original line number Diff line number Diff line
@@ -276,10 +276,11 @@ u64 btrfs_block_rsv_release(struct btrfs_fs_info *fs_info,
	struct btrfs_block_rsv *target = NULL;

	/*
	 * If we are a delayed block reserve then push to the global rsv,
	 * otherwise dump into the global delayed reserve if it is not full.
	 * If we are a delayed refs block reserve then push to the global
	 * reserve, otherwise dump into the global delayed refs reserve if it is
	 * not full.
	 */
	if (block_rsv->type == BTRFS_BLOCK_RSV_DELOPS)
	if (block_rsv->type == BTRFS_BLOCK_RSV_DELREFS)
		target = global_rsv;
	else if (block_rsv != global_rsv && !btrfs_block_rsv_full(delayed_rsv))
		target = delayed_rsv;
+5 −5
Original line number Diff line number Diff line
@@ -2416,17 +2416,17 @@ int btrfs_validate_super(const struct btrfs_fs_info *fs_info,

	/* Root alignment check */
	if (!IS_ALIGNED(btrfs_super_root(sb), sectorsize)) {
		btrfs_warn(fs_info, "tree_root block unaligned: %llu",
		btrfs_err(fs_info, "tree_root block unaligned: %llu",
			  btrfs_super_root(sb));
		ret = -EINVAL;
	}
	if (!IS_ALIGNED(btrfs_super_chunk_root(sb), sectorsize)) {
		btrfs_warn(fs_info, "chunk_root block unaligned: %llu",
		btrfs_err(fs_info, "chunk_root block unaligned: %llu",
			   btrfs_super_chunk_root(sb));
		ret = -EINVAL;
	}
	if (!IS_ALIGNED(btrfs_super_log_root(sb), sectorsize)) {
		btrfs_warn(fs_info, "log_root block unaligned: %llu",
		btrfs_err(fs_info, "log_root block unaligned: %llu",
			  btrfs_super_log_root(sb));
		ret = -EINVAL;
	}
+12 −3
Original line number Diff line number Diff line
@@ -6146,9 +6146,18 @@ static int btrfs_set_inode_index_count(struct btrfs_inode *inode)
	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
	if (ret < 0)
		return ret;
	/* FIXME: we should be able to handle this */
	if (ret == 0)
		return ret;

	if (unlikely(ret == 0)) {
		/*
		 * Key with offset -1 found, there would have to exist a dir
		 * index item with such offset, but this is out of the valid
		 * range.
		 */
		btrfs_err(root->fs_info,
			  "unexpected exact match for DIR_INDEX key, inode %llu",
			  btrfs_ino(inode));
		return -EUCLEAN;
	}

	if (path->slots[0] == 0) {
		inode->index_cnt = BTRFS_DIR_START_INDEX;
Loading