]> git.hungrycats.org Git - linux/commitdiff
btrfs: change the DEV_ITEM 'type' field via sysfs
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 09:05:47 +0000 (04:05 -0500)
(cherry picked from commit 0aabc3870ced23a2d5771e17531f3300a96d19d0)
(cherry picked from commit 38376d7cb0cf6ad543961d935f8cb9a786157dff)
(cherry picked from commit dfd36189e7bb418ff20ae35bd0d808928171552d)

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

index 0301d231782adfbbb107497dd92cf57af5c9cc44..ce66b8d702c643eb10f88c123e2c92e1896b8b91 100644 (file)
@@ -1525,6 +1525,70 @@ static ssize_t btrfs_devinfo_error_stats_show(struct kobject *kobj,
 }
 BTRFS_ATTR(devid, error_stats, btrfs_devinfo_error_stats_show);
 
+static ssize_t btrfs_devinfo_type_show(struct kobject *kobj,
+                                           struct kobj_attribute *a, char *buf)
+{
+       struct btrfs_device *device = container_of(kobj, struct btrfs_device,
+                                                  devid_kobj);
+
+       return scnprintf(buf, PAGE_SIZE, "0x%08llx\n", device->type);
+}
+
+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 9e4e84462757ad06ad68b6b446c30149b67608f4..094c743955973f884c17a8252e0c3d0b67bd9218 100644 (file)
@@ -2812,7 +2812,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 d5cb6cdace8b8887025f95171d33436052afe22a..90503a0ebc80496adcd960e922f5e4f76dbb68e7 100644 (file)
@@ -606,5 +606,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