@@ -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];
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(+)