@@ -1518,7 +1518,61 @@ static ssize_t btrfs_devinfo_type_show(struct kobject *kobj,
return scnprintf(buf, PAGE_SIZE, "0x%08llx\n", device->type);
}
-BTRFS_ATTR(devid, type, btrfs_devinfo_type_show);
+
+static ssize_t btrfs_devinfo_type_store(struct kobject *kobj,
+ struct kobj_attribute *a,
+ const char *buf, size_t len)
+{
+ struct btrfs_fs_info *fs_info;
+ struct btrfs_root *root;
+ struct btrfs_device *device;
+ int ret;
+ struct btrfs_trans_handle *trans;
+
+ u64 type, prev_type;
+
+ device = container_of(kobj, struct btrfs_device, devid_kobj);
+ fs_info = device->fs_info;
+ if (!fs_info)
+ return -EPERM;
+
+ root = fs_info->chunk_root;
+ if (sb_rdonly(fs_info->sb))
+ return -EROFS;
+
+ ret = kstrtou64(buf, 0, &type);
+ if (ret < 0)
+ return -EINVAL;
+
+ /* for now, allow to touch only the 'allocation hint' bits */
+ if (type & ~((1 << BTRFS_DEV_ALLOCATION_MASK_BIT_COUNT) - 1))
+ return -EINVAL;
+
+ trans = btrfs_start_transaction(root, 1);
+ if (IS_ERR(trans))
+ return PTR_ERR(trans);
+
+ prev_type = device->type;
+ device->type = type;
+
+ ret = btrfs_update_device(trans, device);
+
+ if (ret < 0) {
+ btrfs_abort_transaction(trans, ret);
+ btrfs_end_transaction(trans);
+ goto abort;
+ }
+
+ ret = btrfs_commit_transaction(trans);
+ if (ret < 0)
+ goto abort;
+
+ return len;
+abort:
+ device->type = prev_type;
+ return ret;
+}
+BTRFS_ATTR_RW(devid, type, btrfs_devinfo_type_show, btrfs_devinfo_type_store);
static struct attribute *devid_attrs[] = {
BTRFS_ATTR_PTR(devid, error_stats),
@@ -2836,7 +2836,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
return ret;
}
-static noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
+noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
struct btrfs_device *device)
{
int ret;
@@ -608,5 +608,6 @@ int btrfs_bg_type_to_factor(u64 flags);
const char *btrfs_bg_type_to_raid_name(u64 flags);
int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info);
int btrfs_repair_one_zone(struct btrfs_fs_info *fs_info, u64 logical);
-
+int btrfs_update_device(struct btrfs_trans_handle *trans,
+ struct btrfs_device *device);
#endif
From: Goffredo Baroncelli <kreijack@inwind.it> --- fs/btrfs/sysfs.c | 56 +++++++++++++++++++++++++++++++++++++++++++++- fs/btrfs/volumes.c | 2 +- fs/btrfs/volumes.h | 3 ++- 3 files changed, 58 insertions(+), 3 deletions(-)