]> git.baikalelectronics.ru Git - kernel.git/commitdiff
btrfs: sysfs: add force_chunk_alloc trigger to force allocation
authorStefan Roesch <shr@fb.com>
Tue, 8 Feb 2022 19:31:22 +0000 (11:31 -0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 25 Jul 2022 15:45:32 +0000 (17:45 +0200)
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: Stefan Roesch <shr@fb.com>
Reviewed-by: David 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: David Sterba <dsterba@suse.com>
fs/btrfs/sysfs.c

index 43368db059680ed1db01084a2a6a5ccab640ea9e..a536091c3f76083f476615a36a737b47f387240c 100644 (file)
@@ -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);