Commit ae195ca1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:
 "First batch of fixes. Among them there are two updates to sysfs and
  ioctl which are not strictly fixes but are used for testing so there's
  no reason to delay them.

   - fix block group item corruption after inserting new block group

   - fix extent map logging bit not cleared for split maps after
     dropping range

   - fix calculation of unusable block group space reporting bogus
     values due to 32/64b division

   - fix unnecessary increment of read error stat on write error

   - improve error handling in inode update

   - export per-device fsid in DEV_INFO ioctl to distinguish seeding
     devices, needed for testing

   - allocator size classes:
      - fix potential dead lock in size class loading logic
      - print sysfs stats for the allocation classes"

* tag 'for-6.3-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix block group item corruption after inserting new block group
  btrfs: fix extent map logging bit not cleared for split maps after dropping range
  btrfs: fix percent calculation for bg reclaim message
  btrfs: fix unnecessary increment of read error stat on write error
  btrfs: handle btrfs_del_item errors in __btrfs_update_delayed_inode
  btrfs: ioctl: return device fsid from DEV_INFO ioctl
  btrfs: fix potential dead lock in size class loading logic
  btrfs: sysfs: add size class stats
parents f331c5de 675dfe12
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -287,7 +287,7 @@ static void btrfs_log_dev_io_error(struct bio *bio, struct btrfs_device *dev)

	if (btrfs_op(bio) == BTRFS_MAP_WRITE)
		btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
	if (!(bio->bi_opf & REQ_RAHEAD))
	else if (!(bio->bi_opf & REQ_RAHEAD))
		btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_READ_ERRS);
	if (bio->bi_opf & REQ_PREFLUSH)
		btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_FLUSH_ERRS);
+30 −28
Original line number Diff line number Diff line
@@ -558,14 +558,15 @@ u64 add_new_free_space(struct btrfs_block_group *block_group, u64 start, u64 end
static int sample_block_group_extent_item(struct btrfs_caching_control *caching_ctl,
					  struct btrfs_block_group *block_group,
					  int index, int max_index,
					  struct btrfs_key *key)
					  struct btrfs_key *found_key)
{
	struct btrfs_fs_info *fs_info = block_group->fs_info;
	struct btrfs_root *extent_root;
	int ret = 0;
	u64 search_offset;
	u64 search_end = block_group->start + block_group->length;
	struct btrfs_path *path;
	struct btrfs_key search_key;
	int ret = 0;

	ASSERT(index >= 0);
	ASSERT(index <= max_index);
@@ -585,37 +586,24 @@ static int sample_block_group_extent_item(struct btrfs_caching_control *caching_
	path->reada = READA_FORWARD;

	search_offset = index * div_u64(block_group->length, max_index);
	key->objectid = block_group->start + search_offset;
	key->type = BTRFS_EXTENT_ITEM_KEY;
	key->offset = 0;
	search_key.objectid = block_group->start + search_offset;
	search_key.type = BTRFS_EXTENT_ITEM_KEY;
	search_key.offset = 0;

	while (1) {
		ret = btrfs_search_forward(extent_root, key, path, 0);
		if (ret != 0)
			goto out;
	btrfs_for_each_slot(extent_root, &search_key, found_key, path, ret) {
		/* Success; sampled an extent item in the block group */
		if (key->type == BTRFS_EXTENT_ITEM_KEY &&
		    key->objectid >= block_group->start &&
		    key->objectid + key->offset <= search_end)
			goto out;
		if (found_key->type == BTRFS_EXTENT_ITEM_KEY &&
		    found_key->objectid >= block_group->start &&
		    found_key->objectid + found_key->offset <= search_end)
			break;

		/* We can't possibly find a valid extent item anymore */
		if (key->objectid >= search_end) {
		if (found_key->objectid >= search_end) {
			ret = 1;
			break;
		}
		if (key->type < BTRFS_EXTENT_ITEM_KEY)
			key->type = BTRFS_EXTENT_ITEM_KEY;
		else
			key->objectid++;
		btrfs_release_path(path);
		up_read(&fs_info->commit_root_sem);
		mutex_unlock(&caching_ctl->mutex);
		cond_resched();
		mutex_lock(&caching_ctl->mutex);
		down_read(&fs_info->commit_root_sem);
	}
out:

	lockdep_assert_held(&caching_ctl->mutex);
	lockdep_assert_held_read(&fs_info->commit_root_sem);
	btrfs_free_path(path);
@@ -659,6 +647,7 @@ static int sample_block_group_extent_item(struct btrfs_caching_control *caching_
static int load_block_group_size_class(struct btrfs_caching_control *caching_ctl,
				       struct btrfs_block_group *block_group)
{
	struct btrfs_fs_info *fs_info = block_group->fs_info;
	struct btrfs_key key;
	int i;
	u64 min_size = block_group->length;
@@ -668,6 +657,8 @@ static int load_block_group_size_class(struct btrfs_caching_control *caching_ctl
	if (!btrfs_block_group_should_use_size_class(block_group))
		return 0;

	lockdep_assert_held(&caching_ctl->mutex);
	lockdep_assert_held_read(&fs_info->commit_root_sem);
	for (i = 0; i < 5; ++i) {
		ret = sample_block_group_extent_item(caching_ctl, block_group, i, 5, &key);
		if (ret < 0)
@@ -682,7 +673,6 @@ static int load_block_group_size_class(struct btrfs_caching_control *caching_ctl
		block_group->size_class = size_class;
		spin_unlock(&block_group->lock);
	}

out:
	return ret;
}
@@ -1836,7 +1826,8 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)

		btrfs_info(fs_info,
			"reclaiming chunk %llu with %llu%% used %llu%% unusable",
				bg->start, div_u64(bg->used * 100, bg->length),
				bg->start,
				div64_u64(bg->used * 100, bg->length),
				div64_u64(zone_unusable * 100, bg->length));
		trace_btrfs_reclaim_block_group(bg);
		ret = btrfs_relocate_chunk(fs_info, bg->start);
@@ -2493,18 +2484,29 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans,
	struct btrfs_block_group_item bgi;
	struct btrfs_root *root = btrfs_block_group_root(fs_info);
	struct btrfs_key key;
	u64 old_commit_used;
	int ret;

	spin_lock(&block_group->lock);
	btrfs_set_stack_block_group_used(&bgi, block_group->used);
	btrfs_set_stack_block_group_chunk_objectid(&bgi,
						   block_group->global_root_id);
	btrfs_set_stack_block_group_flags(&bgi, block_group->flags);
	old_commit_used = block_group->commit_used;
	block_group->commit_used = block_group->used;
	key.objectid = block_group->start;
	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
	key.offset = block_group->length;
	spin_unlock(&block_group->lock);

	return btrfs_insert_item(trans, root, &key, &bgi, sizeof(bgi));
	ret = btrfs_insert_item(trans, root, &key, &bgi, sizeof(bgi));
	if (ret < 0) {
		spin_lock(&block_group->lock);
		block_group->commit_used = old_commit_used;
		spin_unlock(&block_group->lock);
	}

	return ret;
}

static int insert_dev_extent(struct btrfs_trans_handle *trans,
+1 −1
Original line number Diff line number Diff line
@@ -1048,7 +1048,7 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans,
	 * so there is only one iref. The case that several irefs are
	 * in the same item doesn't exist.
	 */
	btrfs_del_item(trans, root, path);
	ret = btrfs_del_item(trans, root, path);
out:
	btrfs_release_delayed_iref(node);
	btrfs_release_path(path);
+6 −1
Original line number Diff line number Diff line
@@ -763,7 +763,13 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end,
			goto next;
		}

		flags = em->flags;
		clear_bit(EXTENT_FLAG_PINNED, &em->flags);
		/*
		 * In case we split the extent map, we want to preserve the
		 * EXTENT_FLAG_LOGGING flag on our extent map, but we don't want
		 * it on the new extent maps.
		 */
		clear_bit(EXTENT_FLAG_LOGGING, &flags);
		modified = !list_empty(&em->list);

@@ -774,7 +780,6 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end,
		if (em->start >= start && em_end <= end)
			goto remove_em;

		flags = em->flags;
		gen = em->generation;
		compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags);

+1 −0
Original line number Diff line number Diff line
@@ -2859,6 +2859,7 @@ static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info,
	di_args->bytes_used = btrfs_device_get_bytes_used(dev);
	di_args->total_bytes = btrfs_device_get_total_bytes(dev);
	memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid));
	memcpy(di_args->fsid, dev->fs_devices->fsid, BTRFS_UUID_SIZE);
	if (dev->name)
		strscpy(di_args->path, btrfs_dev_name(dev), sizeof(di_args->path));
	else
Loading