diff options
Diffstat (limited to 'fs/btrfs/sysfs.c')
-rw-r--r-- | fs/btrfs/sysfs.c | 133 |
1 files changed, 73 insertions, 60 deletions
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index b535285642dc..f25deb9c132c 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c | |||
@@ -419,28 +419,84 @@ static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj) | |||
419 | return container_of(kobj, struct btrfs_fs_info, super_kobj); | 419 | return container_of(kobj, struct btrfs_fs_info, super_kobj); |
420 | } | 420 | } |
421 | 421 | ||
422 | void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info) | 422 | #define NUM_FEATURE_BITS 64 |
423 | static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13]; | ||
424 | static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS]; | ||
425 | |||
426 | static u64 supported_feature_masks[3] = { | ||
427 | [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP, | ||
428 | [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP, | ||
429 | [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP, | ||
430 | }; | ||
431 | |||
432 | static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add) | ||
433 | { | ||
434 | int set; | ||
435 | |||
436 | for (set = 0; set < FEAT_MAX; set++) { | ||
437 | int i; | ||
438 | struct attribute *attrs[2]; | ||
439 | struct attribute_group agroup = { | ||
440 | .name = "features", | ||
441 | .attrs = attrs, | ||
442 | }; | ||
443 | u64 features = get_features(fs_info, set); | ||
444 | features &= ~supported_feature_masks[set]; | ||
445 | |||
446 | if (!features) | ||
447 | continue; | ||
448 | |||
449 | attrs[1] = NULL; | ||
450 | for (i = 0; i < NUM_FEATURE_BITS; i++) { | ||
451 | struct btrfs_feature_attr *fa; | ||
452 | |||
453 | if (!(features & (1ULL << i))) | ||
454 | continue; | ||
455 | |||
456 | fa = &btrfs_feature_attrs[set][i]; | ||
457 | attrs[0] = &fa->kobj_attr.attr; | ||
458 | if (add) { | ||
459 | int ret; | ||
460 | ret = sysfs_merge_group(&fs_info->super_kobj, | ||
461 | &agroup); | ||
462 | if (ret) | ||
463 | return ret; | ||
464 | } else | ||
465 | sysfs_unmerge_group(&fs_info->super_kobj, | ||
466 | &agroup); | ||
467 | } | ||
468 | |||
469 | } | ||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static void __btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info) | ||
423 | { | 474 | { |
424 | sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); | ||
425 | kobject_del(fs_info->device_dir_kobj); | ||
426 | kobject_put(fs_info->device_dir_kobj); | ||
427 | kobject_del(fs_info->space_info_kobj); | ||
428 | kobject_put(fs_info->space_info_kobj); | ||
429 | kobject_del(&fs_info->super_kobj); | 475 | kobject_del(&fs_info->super_kobj); |
430 | kobject_put(&fs_info->super_kobj); | 476 | kobject_put(&fs_info->super_kobj); |
431 | wait_for_completion(&fs_info->kobj_unregister); | 477 | wait_for_completion(&fs_info->kobj_unregister); |
432 | } | 478 | } |
433 | 479 | ||
480 | void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info) | ||
481 | { | ||
482 | if (fs_info->space_info_kobj) { | ||
483 | sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); | ||
484 | kobject_del(fs_info->space_info_kobj); | ||
485 | kobject_put(fs_info->space_info_kobj); | ||
486 | } | ||
487 | kobject_del(fs_info->device_dir_kobj); | ||
488 | kobject_put(fs_info->device_dir_kobj); | ||
489 | addrm_unknown_feature_attrs(fs_info, false); | ||
490 | sysfs_remove_group(&fs_info->super_kobj, &btrfs_feature_attr_group); | ||
491 | __btrfs_sysfs_remove_one(fs_info); | ||
492 | } | ||
493 | |||
434 | const char * const btrfs_feature_set_names[3] = { | 494 | const char * const btrfs_feature_set_names[3] = { |
435 | [FEAT_COMPAT] = "compat", | 495 | [FEAT_COMPAT] = "compat", |
436 | [FEAT_COMPAT_RO] = "compat_ro", | 496 | [FEAT_COMPAT_RO] = "compat_ro", |
437 | [FEAT_INCOMPAT] = "incompat", | 497 | [FEAT_INCOMPAT] = "incompat", |
438 | }; | 498 | }; |
439 | 499 | ||
440 | #define NUM_FEATURE_BITS 64 | ||
441 | static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13]; | ||
442 | static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS]; | ||
443 | |||
444 | char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) | 500 | char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) |
445 | { | 501 | { |
446 | size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */ | 502 | size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */ |
@@ -510,53 +566,6 @@ static void init_feature_attrs(void) | |||
510 | } | 566 | } |
511 | } | 567 | } |
512 | 568 | ||
513 | static u64 supported_feature_masks[3] = { | ||
514 | [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP, | ||
515 | [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP, | ||
516 | [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP, | ||
517 | }; | ||
518 | |||
519 | static int add_unknown_feature_attrs(struct btrfs_fs_info *fs_info) | ||
520 | { | ||
521 | int set; | ||
522 | |||
523 | for (set = 0; set < FEAT_MAX; set++) { | ||
524 | int i, count, ret, index = 0; | ||
525 | struct attribute **attrs; | ||
526 | struct attribute_group agroup = { | ||
527 | .name = "features", | ||
528 | }; | ||
529 | u64 features = get_features(fs_info, set); | ||
530 | features &= ~supported_feature_masks[set]; | ||
531 | |||
532 | count = hweight64(features); | ||
533 | |||
534 | if (!count) | ||
535 | continue; | ||
536 | |||
537 | attrs = kcalloc(count + 1, sizeof(void *), GFP_KERNEL); | ||
538 | |||
539 | for (i = 0; i < NUM_FEATURE_BITS; i++) { | ||
540 | struct btrfs_feature_attr *fa; | ||
541 | |||
542 | if (!(features & (1ULL << i))) | ||
543 | continue; | ||
544 | |||
545 | fa = &btrfs_feature_attrs[set][i]; | ||
546 | attrs[index++] = &fa->kobj_attr.attr; | ||
547 | } | ||
548 | |||
549 | attrs[index] = NULL; | ||
550 | agroup.attrs = attrs; | ||
551 | |||
552 | ret = sysfs_merge_group(&fs_info->super_kobj, &agroup); | ||
553 | kfree(attrs); | ||
554 | if (ret) | ||
555 | return ret; | ||
556 | } | ||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | static int add_device_membership(struct btrfs_fs_info *fs_info) | 569 | static int add_device_membership(struct btrfs_fs_info *fs_info) |
561 | { | 570 | { |
562 | int error = 0; | 571 | int error = 0; |
@@ -592,13 +601,17 @@ int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info) | |||
592 | fs_info->super_kobj.kset = btrfs_kset; | 601 | fs_info->super_kobj.kset = btrfs_kset; |
593 | error = kobject_init_and_add(&fs_info->super_kobj, &btrfs_ktype, NULL, | 602 | error = kobject_init_and_add(&fs_info->super_kobj, &btrfs_ktype, NULL, |
594 | "%pU", fs_info->fsid); | 603 | "%pU", fs_info->fsid); |
604 | if (error) | ||
605 | return error; | ||
595 | 606 | ||
596 | error = sysfs_create_group(&fs_info->super_kobj, | 607 | error = sysfs_create_group(&fs_info->super_kobj, |
597 | &btrfs_feature_attr_group); | 608 | &btrfs_feature_attr_group); |
598 | if (error) | 609 | if (error) { |
599 | goto failure; | 610 | __btrfs_sysfs_remove_one(fs_info); |
611 | return error; | ||
612 | } | ||
600 | 613 | ||
601 | error = add_unknown_feature_attrs(fs_info); | 614 | error = addrm_unknown_feature_attrs(fs_info, true); |
602 | if (error) | 615 | if (error) |
603 | goto failure; | 616 | goto failure; |
604 | 617 | ||