]> git.hungrycats.org Git - linux/commitdiff
btrfs: change the DEV_ITEM 'type' field via sysfs (v8)
authorGoffredo Baroncelli <kreijack@inwind.it>
Sun, 24 Oct 2021 15:31:06 +0000 (17:31 +0200)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sun, 5 Dec 2021 08:11:07 +0000 (03:11 -0500)
(cherry picked from commit 0aabc3870ced23a2d5771e17531f3300a96d19d0)
(cherry picked from commit 38376d7cb0cf6ad543961d935f8cb9a786157dff)
(cherry picked from commit 03ef6933b0d47f8b6c041f4c32162dba57a7298f)

fs/btrfs/sysfs.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h

index a9d234d08bf26f4c287534b8b5f68b371cb54fdf..7b11e38d6145fb275ebd721329a03c8b04c9c2b9 100644 (file)
@@ -1481,7 +1481,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);
 
 /*
  * Information about one device.
index 6223b2220705b9415365e8dd5d8785bf0a8eaf1d..470fec1446304253f505278b4fcf0c22eee0e579 100644 (file)
@@ -2747,7 +2747,7 @@ error:
        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;
index 38296020d50fb91b5e26e8e2021f38b01330d19e..2c1fb70f99b0ba647fbb3e2c5b06437d1cf111bc 100644 (file)
@@ -599,4 +599,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_update_device(struct btrfs_trans_handle *trans,
+                                       struct btrfs_device *device);
 #endif