Skip to content

Commit 668e48a

Browse files
asjkdave
authored andcommitted
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 <[email protected]> Reviewed-by: David Sterba <[email protected]> [ update changelog ] Signed-off-by: David Sterba <[email protected]>
1 parent 1776ad1 commit 668e48a

File tree

4 files changed

+138
-23
lines changed

4 files changed

+138
-23
lines changed

fs/btrfs/dev-replace.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
707707

708708
/* replace the sysfs entry */
709709
btrfs_sysfs_rm_device_link(fs_info->fs_devices, src_device);
710+
btrfs_sysfs_update_devid(tgt_device);
710711
btrfs_rm_dev_replace_free_srcdev(src_device);
711712

712713
/* write back the superblocks */

fs/btrfs/sysfs.c

Lines changed: 132 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,52 +1152,149 @@ int btrfs_sysfs_rm_device_link(struct btrfs_fs_devices *fs_devices,
11521152
if (!fs_devices->devices_kobj)
11531153
return -EINVAL;
11541154

1155-
if (one_device && one_device->bdev) {
1156-
disk = one_device->bdev->bd_part;
1157-
disk_kobj = &part_to_dev(disk)->kobj;
1155+
if (one_device) {
1156+
if (one_device->bdev) {
1157+
disk = one_device->bdev->bd_part;
1158+
disk_kobj = &part_to_dev(disk)->kobj;
1159+
sysfs_remove_link(fs_devices->devices_kobj,
1160+
disk_kobj->name);
1161+
}
11581162

1159-
sysfs_remove_link(fs_devices->devices_kobj, disk_kobj->name);
1160-
}
1163+
kobject_del(&one_device->devid_kobj);
1164+
kobject_put(&one_device->devid_kobj);
1165+
1166+
wait_for_completion(&one_device->kobj_unregister);
11611167

1162-
if (one_device)
11631168
return 0;
1169+
}
11641170

1165-
list_for_each_entry(one_device,
1166-
&fs_devices->devices, dev_list) {
1167-
if (!one_device->bdev)
1168-
continue;
1169-
disk = one_device->bdev->bd_part;
1170-
disk_kobj = &part_to_dev(disk)->kobj;
1171+
list_for_each_entry(one_device, &fs_devices->devices, dev_list) {
1172+
1173+
if (one_device->bdev) {
1174+
disk = one_device->bdev->bd_part;
1175+
disk_kobj = &part_to_dev(disk)->kobj;
1176+
sysfs_remove_link(fs_devices->devices_kobj,
1177+
disk_kobj->name);
1178+
}
1179+
kobject_del(&one_device->devid_kobj);
1180+
kobject_put(&one_device->devid_kobj);
11711181

1172-
sysfs_remove_link(fs_devices->devices_kobj, disk_kobj->name);
1182+
wait_for_completion(&one_device->kobj_unregister);
11731183
}
11741184

11751185
return 0;
11761186
}
11771187

1188+
static ssize_t btrfs_devinfo_in_fs_metadata_show(struct kobject *kobj,
1189+
struct kobj_attribute *a,
1190+
char *buf)
1191+
{
1192+
int val;
1193+
struct btrfs_device *device = container_of(kobj, struct btrfs_device,
1194+
devid_kobj);
1195+
1196+
val = !!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
1197+
1198+
return snprintf(buf, PAGE_SIZE, "%d\n", val);
1199+
}
1200+
BTRFS_ATTR(devid, in_fs_metadata, btrfs_devinfo_in_fs_metadata_show);
1201+
1202+
static ssize_t btrfs_sysfs_missing_show(struct kobject *kobj,
1203+
struct kobj_attribute *a, char *buf)
1204+
{
1205+
int val;
1206+
struct btrfs_device *device = container_of(kobj, struct btrfs_device,
1207+
devid_kobj);
1208+
1209+
val = !!test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state);
1210+
1211+
return snprintf(buf, PAGE_SIZE, "%d\n", val);
1212+
}
1213+
BTRFS_ATTR(devid, missing, btrfs_sysfs_missing_show);
1214+
1215+
static ssize_t btrfs_devinfo_replace_target_show(struct kobject *kobj,
1216+
struct kobj_attribute *a,
1217+
char *buf)
1218+
{
1219+
int val;
1220+
struct btrfs_device *device = container_of(kobj, struct btrfs_device,
1221+
devid_kobj);
1222+
1223+
val = !!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state);
1224+
1225+
return snprintf(buf, PAGE_SIZE, "%d\n", val);
1226+
}
1227+
BTRFS_ATTR(devid, replace_target, btrfs_devinfo_replace_target_show);
1228+
1229+
static ssize_t btrfs_devinfo_writeable_show(struct kobject *kobj,
1230+
struct kobj_attribute *a, char *buf)
1231+
{
1232+
int val;
1233+
struct btrfs_device *device = container_of(kobj, struct btrfs_device,
1234+
devid_kobj);
1235+
1236+
val = !!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
1237+
1238+
return snprintf(buf, PAGE_SIZE, "%d\n", val);
1239+
}
1240+
BTRFS_ATTR(devid, writeable, btrfs_devinfo_writeable_show);
1241+
1242+
static struct attribute *devid_attrs[] = {
1243+
BTRFS_ATTR_PTR(devid, in_fs_metadata),
1244+
BTRFS_ATTR_PTR(devid, missing),
1245+
BTRFS_ATTR_PTR(devid, replace_target),
1246+
BTRFS_ATTR_PTR(devid, writeable),
1247+
NULL
1248+
};
1249+
ATTRIBUTE_GROUPS(devid);
1250+
1251+
static void btrfs_release_devid_kobj(struct kobject *kobj)
1252+
{
1253+
struct btrfs_device *device = container_of(kobj, struct btrfs_device,
1254+
devid_kobj);
1255+
1256+
memset(&device->devid_kobj, 0, sizeof(struct kobject));
1257+
complete(&device->kobj_unregister);
1258+
}
1259+
1260+
static struct kobj_type devid_ktype = {
1261+
.sysfs_ops = &kobj_sysfs_ops,
1262+
.default_groups = devid_groups,
1263+
.release = btrfs_release_devid_kobj,
1264+
};
1265+
11781266
int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices,
11791267
struct btrfs_device *one_device)
11801268
{
11811269
int error = 0;
11821270
struct btrfs_device *dev;
11831271

11841272
list_for_each_entry(dev, &fs_devices->devices, dev_list) {
1185-
struct hd_struct *disk;
1186-
struct kobject *disk_kobj;
1187-
1188-
if (!dev->bdev)
1189-
continue;
11901273

11911274
if (one_device && one_device != dev)
11921275
continue;
11931276

1194-
disk = dev->bdev->bd_part;
1195-
disk_kobj = &part_to_dev(disk)->kobj;
1277+
if (dev->bdev) {
1278+
struct hd_struct *disk;
1279+
struct kobject *disk_kobj;
1280+
1281+
disk = dev->bdev->bd_part;
1282+
disk_kobj = &part_to_dev(disk)->kobj;
1283+
1284+
error = sysfs_create_link(fs_devices->devices_kobj,
1285+
disk_kobj, disk_kobj->name);
1286+
if (error)
1287+
break;
1288+
}
11961289

1197-
error = sysfs_create_link(fs_devices->devices_kobj,
1198-
disk_kobj, disk_kobj->name);
1199-
if (error)
1290+
init_completion(&dev->kobj_unregister);
1291+
error = kobject_init_and_add(&dev->devid_kobj, &devid_ktype,
1292+
fs_devices->devices_kobj, "%llu",
1293+
dev->devid);
1294+
if (error) {
1295+
kobject_put(&dev->devid_kobj);
12001296
break;
1297+
}
12011298
}
12021299

12031300
return error;
@@ -1229,6 +1326,18 @@ void btrfs_sysfs_update_sprout_fsid(struct btrfs_fs_devices *fs_devices,
12291326
"sysfs: failed to create fsid for sprout");
12301327
}
12311328

1329+
void btrfs_sysfs_update_devid(struct btrfs_device *device)
1330+
{
1331+
char tmp[24];
1332+
1333+
snprintf(tmp, sizeof(tmp), "%llu", device->devid);
1334+
1335+
if (kobject_rename(&device->devid_kobj, tmp))
1336+
btrfs_warn(device->fs_devices->fs_info,
1337+
"sysfs: failed to update devid for %llu",
1338+
device->devid);
1339+
}
1340+
12321341
/* /sys/fs/btrfs/ entry */
12331342
static struct kset *btrfs_kset;
12341343

fs/btrfs/sysfs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ void btrfs_sysfs_add_block_group_type(struct btrfs_block_group *cache);
3434
int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info,
3535
struct btrfs_space_info *space_info);
3636
void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info);
37+
void btrfs_sysfs_update_devid(struct btrfs_device *device);
3738

3839
#endif

fs/btrfs/volumes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ struct btrfs_device {
136136
atomic_t dev_stat_values[BTRFS_DEV_STAT_VALUES_MAX];
137137

138138
struct extent_io_tree alloc_state;
139+
140+
struct completion kobj_unregister;
141+
/* For sysfs/FSID/devinfo/devid/ */
142+
struct kobject devid_kobj;
139143
};
140144

141145
/*

0 commit comments

Comments
 (0)