mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-03-22 23:24:13 +00:00
btrfs: sysfs, add devid/dev_state kobject and device attributes
New sysfs attributes that track the filesystem status of devices, stored in the per-filesystem directory in /sys/fs/btrfs/FSID/devinfo . There's a directory for each device, with name corresponding to the numerical device id. in_fs_metadata - device is in the list of fs metadata missing - device is missing (no device node or block device) replace_target - device is target of replace writeable - writes from fs are allowed These attributes reflect the state of the device::dev_state and created at mount time. Sample output: $ pwd /sys/fs/btrfs/6e1961f1-5918-4ecc-a22f-948897b409f7/devinfo/1/ $ ls in_fs_metadata missing replace_target writeable $ cat missing 0 The output from these attributes are 0 or 1. 0 indicates unset and 1 indicates set. These attributes are readonly. It is observed that the device delete thread and sysfs read thread will not race because the delete thread calls sysfs kobject_put() which in turn waits for existing sysfs read to complete. Note for device replace devid swap: During the replace the target device temporarily assumes devid 0 before assigning the devid of the soruce device. In btrfs_dev_replace_finishing() we remove source sysfs devid using the function btrfs_sysfs_remove_devices_attr(), so after that call kobject_rename() to update the devid in the sysfs. This adds and calls btrfs_sysfs_update_devid() helper function to update the device id. Signed-off-by: Anand Jain <anand.jain@oracle.com> Reviewed-by: David Sterba <dsterba@suse.com> [ update changelog ] Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
1776ad172e
commit
668e48af7a
4 changed files with 138 additions and 23 deletions
|
@ -707,6 +707,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
||||||
|
|
||||||
/* replace the sysfs entry */
|
/* replace the sysfs entry */
|
||||||
btrfs_sysfs_rm_device_link(fs_info->fs_devices, src_device);
|
btrfs_sysfs_rm_device_link(fs_info->fs_devices, src_device);
|
||||||
|
btrfs_sysfs_update_devid(tgt_device);
|
||||||
btrfs_rm_dev_replace_free_srcdev(src_device);
|
btrfs_rm_dev_replace_free_srcdev(src_device);
|
||||||
|
|
||||||
/* write back the superblocks */
|
/* write back the superblocks */
|
||||||
|
|
155
fs/btrfs/sysfs.c
155
fs/btrfs/sysfs.c
|
@ -1152,29 +1152,117 @@ int btrfs_sysfs_rm_device_link(struct btrfs_fs_devices *fs_devices,
|
||||||
if (!fs_devices->devices_kobj)
|
if (!fs_devices->devices_kobj)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (one_device && one_device->bdev) {
|
if (one_device) {
|
||||||
disk = one_device->bdev->bd_part;
|
if (one_device->bdev) {
|
||||||
disk_kobj = &part_to_dev(disk)->kobj;
|
disk = one_device->bdev->bd_part;
|
||||||
|
disk_kobj = &part_to_dev(disk)->kobj;
|
||||||
|
sysfs_remove_link(fs_devices->devices_kobj,
|
||||||
|
disk_kobj->name);
|
||||||
|
}
|
||||||
|
|
||||||
sysfs_remove_link(fs_devices->devices_kobj, disk_kobj->name);
|
kobject_del(&one_device->devid_kobj);
|
||||||
|
kobject_put(&one_device->devid_kobj);
|
||||||
|
|
||||||
|
wait_for_completion(&one_device->kobj_unregister);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (one_device)
|
list_for_each_entry(one_device, &fs_devices->devices, dev_list) {
|
||||||
return 0;
|
|
||||||
|
|
||||||
list_for_each_entry(one_device,
|
if (one_device->bdev) {
|
||||||
&fs_devices->devices, dev_list) {
|
disk = one_device->bdev->bd_part;
|
||||||
if (!one_device->bdev)
|
disk_kobj = &part_to_dev(disk)->kobj;
|
||||||
continue;
|
sysfs_remove_link(fs_devices->devices_kobj,
|
||||||
disk = one_device->bdev->bd_part;
|
disk_kobj->name);
|
||||||
disk_kobj = &part_to_dev(disk)->kobj;
|
}
|
||||||
|
kobject_del(&one_device->devid_kobj);
|
||||||
|
kobject_put(&one_device->devid_kobj);
|
||||||
|
|
||||||
sysfs_remove_link(fs_devices->devices_kobj, disk_kobj->name);
|
wait_for_completion(&one_device->kobj_unregister);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t btrfs_devinfo_in_fs_metadata_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *a,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
struct btrfs_device *device = container_of(kobj, struct btrfs_device,
|
||||||
|
devid_kobj);
|
||||||
|
|
||||||
|
val = !!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%d\n", val);
|
||||||
|
}
|
||||||
|
BTRFS_ATTR(devid, in_fs_metadata, btrfs_devinfo_in_fs_metadata_show);
|
||||||
|
|
||||||
|
static ssize_t btrfs_sysfs_missing_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *a, char *buf)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
struct btrfs_device *device = container_of(kobj, struct btrfs_device,
|
||||||
|
devid_kobj);
|
||||||
|
|
||||||
|
val = !!test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state);
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%d\n", val);
|
||||||
|
}
|
||||||
|
BTRFS_ATTR(devid, missing, btrfs_sysfs_missing_show);
|
||||||
|
|
||||||
|
static ssize_t btrfs_devinfo_replace_target_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *a,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
struct btrfs_device *device = container_of(kobj, struct btrfs_device,
|
||||||
|
devid_kobj);
|
||||||
|
|
||||||
|
val = !!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state);
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%d\n", val);
|
||||||
|
}
|
||||||
|
BTRFS_ATTR(devid, replace_target, btrfs_devinfo_replace_target_show);
|
||||||
|
|
||||||
|
static ssize_t btrfs_devinfo_writeable_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *a, char *buf)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
struct btrfs_device *device = container_of(kobj, struct btrfs_device,
|
||||||
|
devid_kobj);
|
||||||
|
|
||||||
|
val = !!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%d\n", val);
|
||||||
|
}
|
||||||
|
BTRFS_ATTR(devid, writeable, btrfs_devinfo_writeable_show);
|
||||||
|
|
||||||
|
static struct attribute *devid_attrs[] = {
|
||||||
|
BTRFS_ATTR_PTR(devid, in_fs_metadata),
|
||||||
|
BTRFS_ATTR_PTR(devid, missing),
|
||||||
|
BTRFS_ATTR_PTR(devid, replace_target),
|
||||||
|
BTRFS_ATTR_PTR(devid, writeable),
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
ATTRIBUTE_GROUPS(devid);
|
||||||
|
|
||||||
|
static void btrfs_release_devid_kobj(struct kobject *kobj)
|
||||||
|
{
|
||||||
|
struct btrfs_device *device = container_of(kobj, struct btrfs_device,
|
||||||
|
devid_kobj);
|
||||||
|
|
||||||
|
memset(&device->devid_kobj, 0, sizeof(struct kobject));
|
||||||
|
complete(&device->kobj_unregister);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_type devid_ktype = {
|
||||||
|
.sysfs_ops = &kobj_sysfs_ops,
|
||||||
|
.default_groups = devid_groups,
|
||||||
|
.release = btrfs_release_devid_kobj,
|
||||||
|
};
|
||||||
|
|
||||||
int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices,
|
int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices,
|
||||||
struct btrfs_device *one_device)
|
struct btrfs_device *one_device)
|
||||||
{
|
{
|
||||||
|
@ -1182,22 +1270,31 @@ int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices,
|
||||||
struct btrfs_device *dev;
|
struct btrfs_device *dev;
|
||||||
|
|
||||||
list_for_each_entry(dev, &fs_devices->devices, dev_list) {
|
list_for_each_entry(dev, &fs_devices->devices, dev_list) {
|
||||||
struct hd_struct *disk;
|
|
||||||
struct kobject *disk_kobj;
|
|
||||||
|
|
||||||
if (!dev->bdev)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (one_device && one_device != dev)
|
if (one_device && one_device != dev)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
disk = dev->bdev->bd_part;
|
if (dev->bdev) {
|
||||||
disk_kobj = &part_to_dev(disk)->kobj;
|
struct hd_struct *disk;
|
||||||
|
struct kobject *disk_kobj;
|
||||||
|
|
||||||
error = sysfs_create_link(fs_devices->devices_kobj,
|
disk = dev->bdev->bd_part;
|
||||||
disk_kobj, disk_kobj->name);
|
disk_kobj = &part_to_dev(disk)->kobj;
|
||||||
if (error)
|
|
||||||
|
error = sysfs_create_link(fs_devices->devices_kobj,
|
||||||
|
disk_kobj, disk_kobj->name);
|
||||||
|
if (error)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_completion(&dev->kobj_unregister);
|
||||||
|
error = kobject_init_and_add(&dev->devid_kobj, &devid_ktype,
|
||||||
|
fs_devices->devices_kobj, "%llu",
|
||||||
|
dev->devid);
|
||||||
|
if (error) {
|
||||||
|
kobject_put(&dev->devid_kobj);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
@ -1229,6 +1326,18 @@ void btrfs_sysfs_update_sprout_fsid(struct btrfs_fs_devices *fs_devices,
|
||||||
"sysfs: failed to create fsid for sprout");
|
"sysfs: failed to create fsid for sprout");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void btrfs_sysfs_update_devid(struct btrfs_device *device)
|
||||||
|
{
|
||||||
|
char tmp[24];
|
||||||
|
|
||||||
|
snprintf(tmp, sizeof(tmp), "%llu", device->devid);
|
||||||
|
|
||||||
|
if (kobject_rename(&device->devid_kobj, tmp))
|
||||||
|
btrfs_warn(device->fs_devices->fs_info,
|
||||||
|
"sysfs: failed to update devid for %llu",
|
||||||
|
device->devid);
|
||||||
|
}
|
||||||
|
|
||||||
/* /sys/fs/btrfs/ entry */
|
/* /sys/fs/btrfs/ entry */
|
||||||
static struct kset *btrfs_kset;
|
static struct kset *btrfs_kset;
|
||||||
|
|
||||||
|
|
|
@ -34,5 +34,6 @@ void btrfs_sysfs_add_block_group_type(struct btrfs_block_group *cache);
|
||||||
int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info,
|
int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info,
|
||||||
struct btrfs_space_info *space_info);
|
struct btrfs_space_info *space_info);
|
||||||
void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info);
|
void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info);
|
||||||
|
void btrfs_sysfs_update_devid(struct btrfs_device *device);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -136,6 +136,10 @@ struct btrfs_device {
|
||||||
atomic_t dev_stat_values[BTRFS_DEV_STAT_VALUES_MAX];
|
atomic_t dev_stat_values[BTRFS_DEV_STAT_VALUES_MAX];
|
||||||
|
|
||||||
struct extent_io_tree alloc_state;
|
struct extent_io_tree alloc_state;
|
||||||
|
|
||||||
|
struct completion kobj_unregister;
|
||||||
|
/* For sysfs/FSID/devinfo/devid/ */
|
||||||
|
struct kobject devid_kobj;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Reference in a new issue