[RESEND] btrfs: add a force_chunk_alloc to space_info's sysfs
diff mbox series

Message ID 20190822190305.13673-1-josef@toxicpanda.com
State New
Headers show
Series
  • [RESEND] btrfs: add a force_chunk_alloc to space_info's sysfs
Related show

Commit Message

Josef Bacik Aug. 22, 2019, 7:03 p.m. UTC
In testing various things such as the btrfsck patch to detect over
allocation of chunks, empty block group deletion, and balance I've had
various ways to force chunk allocations for debug purposes.  Add a sysfs
file to enable forcing of chunk allocation for the owning space info in
order to enable us to add testcases in the future to test these various
features easier.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/sysfs.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

Comments

Nikolay Borisov Aug. 23, 2019, 6:35 a.m. UTC | #1
On 22.08.19 г. 22:03 ч., Josef Bacik wrote:
> In testing various things such as the btrfsck patch to detect over
> allocation of chunks, empty block group deletion, and balance I've had
> various ways to force chunk allocations for debug purposes.  Add a sysfs
> file to enable forcing of chunk allocation for the owning space info in
> order to enable us to add testcases in the future to test these various
> features easier.
> 
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

Since this is really a debugging feature I think it should be gated by
CONFIG_BTRFS_DEBUG.

<snip>
David Sterba Aug. 23, 2019, 11:32 a.m. UTC | #2
On Fri, Aug 23, 2019 at 09:35:22AM +0300, Nikolay Borisov wrote:
> 
> 
> On 22.08.19 г. 22:03 ч., Josef Bacik wrote:
> > In testing various things such as the btrfsck patch to detect over
> > allocation of chunks, empty block group deletion, and balance I've had
> > various ways to force chunk allocations for debug purposes.  Add a sysfs
> > file to enable forcing of chunk allocation for the owning space info in
> > order to enable us to add testcases in the future to test these various
> > features easier.
> > 
> > Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> 
> Since this is really a debugging feature I think it should be gated by
> CONFIG_BTRFS_DEBUG.

I did the per-fs debug directories exactly for that purpose, the patches
have been in misc-next for some time ("btrfs: sysfs: add debugging
exports").

Patch
diff mbox series

diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index f6d3c80f2e28..c290a0cd37d2 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -68,6 +68,7 @@  static struct btrfs_feature_attr btrfs_attr_features_##_name = {	     \
 
 static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj);
 static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj);
+static inline struct kobject *get_btrfs_kobj(struct kobject *kobj);
 
 static struct btrfs_feature_attr *to_btrfs_feature_attr(struct kobj_attribute *a)
 {
@@ -405,6 +406,58 @@  static struct kobj_type btrfs_raid_ktype = {
 	.default_groups = raid_groups,
 };
 
+static ssize_t btrfs_space_info_force_chunk_alloc_show(struct kobject *kobj,
+						       struct kobj_attribute *a,
+						       char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0\n");
+}
+
+static ssize_t btrfs_space_info_force_chunk_alloc(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;
+	unsigned long val;
+	int ret;
+
+	if (!fs_info) {
+		printk(KERN_ERR "couldn't get fs_info\n");
+		return -EPERM;
+	}
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (sb_rdonly(fs_info->sb))
+		return -EROFS;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	/*
+	 * We don't really care, but if we echo 0 > force it seems silly to do
+	 * anything.
+	 */
+	if (val == 0)
+		return -EINVAL;
+
+	trans = btrfs_start_transaction(fs_info->extent_root, 0);
+	if (!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_RW(space_info, force_chunk_alloc,
+	      btrfs_space_info_force_chunk_alloc_show,
+	      btrfs_space_info_force_chunk_alloc);
+
 #define SPACE_INFO_ATTR(field)						\
 static ssize_t btrfs_space_info_show_##field(struct kobject *kobj,	\
 					     struct kobj_attribute *a,	\
@@ -447,6 +500,7 @@  static struct attribute *space_info_attrs[] = {
 	BTRFS_ATTR_PTR(space_info, disk_used),
 	BTRFS_ATTR_PTR(space_info, disk_total),
 	BTRFS_ATTR_PTR(space_info, total_bytes_pinned),
+	BTRFS_ATTR_PTR(space_info, force_chunk_alloc),
 	NULL,
 };
 ATTRIBUTE_GROUPS(space_info);
@@ -641,6 +695,16 @@  static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
 	return to_fs_devs(kobj)->fs_info;
 }
 
+static inline struct kobject *get_btrfs_kobj(struct kobject *kobj)
+{
+	while (kobj) {
+		if (kobj->ktype == &btrfs_ktype)
+			return kobj;
+		kobj = kobj->parent;
+	}
+	return NULL;
+}
+
 #define NUM_FEATURE_BITS 64
 #define BTRFS_FEATURE_NAME_MAX 13
 static char btrfs_unknown_feature_names[FEAT_MAX][NUM_FEATURE_BITS][BTRFS_FEATURE_NAME_MAX];