Commit 22c55e3b authored by Stefan Roesch's avatar Stefan Roesch Committed by David Sterba
Browse files

btrfs: sysfs: add force_chunk_alloc trigger to force allocation



Adds write-only trigger to force new chunk allocation for a given block
group type. It is at

  /sys/fs/btrfs/<uuid>/allocation/<type>/force_chunk_alloc

Note: this is now only for debugging and testing and is enabled with the
      CONFIG_BTRFS_DEBUG configuration option. The transaction is
      started from sysfs context and can be problematic in some cases.

Signed-off-by: default avatarStefan Roesch <shr@fb.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
[ Changes from the original submission:
  - update changelog
  - drop unnecessary error messages
  - switch value to bool and use kstrtobool
  - move BTRFS_ATTR_W definition
  - add comment for using transaction
]
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 19fc516a
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -62,6 +62,10 @@ struct raid_kobject {
	.store	= _store,						\
}

#define BTRFS_ATTR_W(_prefix, _name, _store)			        \
	static struct kobj_attribute btrfs_attr_##_prefix##_##_name =	\
			__INIT_KOBJ_ATTR(_name, 0200, NULL, _store)

#define BTRFS_ATTR_RW(_prefix, _name, _show, _store)			\
	static struct kobj_attribute btrfs_attr_##_prefix##_##_name =	\
			__INIT_KOBJ_ATTR(_name, 0644, _show, _store)
@@ -771,6 +775,52 @@ static ssize_t btrfs_chunk_size_store(struct kobject *kobj,
	return len;
}

#ifdef CONFIG_BTRFS_DEBUG
/*
 * Request chunk allocation with current chunk size.
 */
static ssize_t btrfs_force_chunk_alloc_store(struct kobject *kobj,
					     struct kobj_attribute *a,
					     const char *buf, size_t len)
{
	struct btrfs_space_info *space_info = to_space_info(kobj);
	struct btrfs_fs_info *fs_info = to_fs_info(get_btrfs_kobj(kobj));
	struct btrfs_trans_handle *trans;
	bool val;
	int ret;

	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	if (sb_rdonly(fs_info->sb))
		return -EROFS;

	ret = kstrtobool(buf, &val);
	if (ret)
		return ret;

	if (!val)
		return -EINVAL;

	/*
	 * This is unsafe to be called from sysfs context and may cause
	 * unexpected problems.
	 */
	trans = btrfs_start_transaction(fs_info->tree_root, 0);
	if (IS_ERR(trans))
		return PTR_ERR(trans);
	ret = btrfs_force_chunk_alloc(trans, space_info->flags);
	btrfs_end_transaction(trans);

	if (ret == 1)
		return len;

	return -ENOSPC;
}
BTRFS_ATTR_W(space_info, force_chunk_alloc, btrfs_force_chunk_alloc_store);

#endif

SPACE_INFO_ATTR(flags);
SPACE_INFO_ATTR(total_bytes);
SPACE_INFO_ATTR(bytes_used);
@@ -837,6 +887,9 @@ static struct attribute *space_info_attrs[] = {
	BTRFS_ATTR_PTR(space_info, disk_total),
	BTRFS_ATTR_PTR(space_info, bg_reclaim_threshold),
	BTRFS_ATTR_PTR(space_info, chunk_size),
#ifdef CONFIG_BTRFS_DEBUG
	BTRFS_ATTR_PTR(space_info, force_chunk_alloc),
#endif
	NULL,
};
ATTRIBUTE_GROUPS(space_info);