1 /* 2 * Copyright (C) 2007 Oracle. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public 6 * License v2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public 14 * License along with this program; if not, write to the 15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16 * Boston, MA 021110-1307, USA. 17 */ 18 19 #include <linux/sched.h> 20 #include <linux/slab.h> 21 #include <linux/spinlock.h> 22 #include <linux/completion.h> 23 #include <linux/buffer_head.h> 24 #include <linux/kobject.h> 25 #include <linux/bug.h> 26 #include <linux/genhd.h> 27 28 #include "ctree.h" 29 #include "disk-io.h" 30 #include "transaction.h" 31 #include "sysfs.h" 32 #include "volumes.h" 33 34 static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); 35 36 static u64 get_features(struct btrfs_fs_info *fs_info, 37 enum btrfs_feature_set set) 38 { 39 struct btrfs_super_block *disk_super = fs_info->super_copy; 40 if (set == FEAT_COMPAT) 41 return btrfs_super_compat_flags(disk_super); 42 else if (set == FEAT_COMPAT_RO) 43 return btrfs_super_compat_ro_flags(disk_super); 44 else 45 return btrfs_super_incompat_flags(disk_super); 46 } 47 48 static void set_features(struct btrfs_fs_info *fs_info, 49 enum btrfs_feature_set set, u64 features) 50 { 51 struct btrfs_super_block *disk_super = fs_info->super_copy; 52 if (set == FEAT_COMPAT) 53 btrfs_set_super_compat_flags(disk_super, features); 54 else if (set == FEAT_COMPAT_RO) 55 btrfs_set_super_compat_ro_flags(disk_super, features); 56 else 57 btrfs_set_super_incompat_flags(disk_super, features); 58 } 59 60 static int can_modify_feature(struct btrfs_feature_attr *fa) 61 { 62 int val = 0; 63 u64 set, clear; 64 switch (fa->feature_set) { 65 case FEAT_COMPAT: 66 set = BTRFS_FEATURE_COMPAT_SAFE_SET; 67 clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 68 break; 69 case FEAT_COMPAT_RO: 70 set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 71 clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 72 break; 73 case FEAT_INCOMPAT: 74 set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 75 clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 76 break; 77 default: 78 printk(KERN_WARNING "btrfs: sysfs: unknown feature set %d\n", 79 fa->feature_set); 80 return 0; 81 } 82 83 if (set & fa->feature_bit) 84 val |= 1; 85 if (clear & fa->feature_bit) 86 val |= 2; 87 88 return val; 89 } 90 91 static ssize_t btrfs_feature_attr_show(struct kobject *kobj, 92 struct kobj_attribute *a, char *buf) 93 { 94 int val = 0; 95 struct btrfs_fs_info *fs_info = to_fs_info(kobj); 96 struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 97 if (fs_info) { 98 u64 features = get_features(fs_info, fa->feature_set); 99 if (features & fa->feature_bit) 100 val = 1; 101 } else 102 val = can_modify_feature(fa); 103 104 return snprintf(buf, PAGE_SIZE, "%d\n", val); 105 } 106 107 static ssize_t btrfs_feature_attr_store(struct kobject *kobj, 108 struct kobj_attribute *a, 109 const char *buf, size_t count) 110 { 111 struct btrfs_fs_info *fs_info; 112 struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 113 struct btrfs_trans_handle *trans; 114 u64 features, set, clear; 115 unsigned long val; 116 int ret; 117 118 fs_info = to_fs_info(kobj); 119 if (!fs_info) 120 return -EPERM; 121 122 ret = kstrtoul(skip_spaces(buf), 0, &val); 123 if (ret) 124 return ret; 125 126 if (fa->feature_set == FEAT_COMPAT) { 127 set = BTRFS_FEATURE_COMPAT_SAFE_SET; 128 clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 129 } else if (fa->feature_set == FEAT_COMPAT_RO) { 130 set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 131 clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 132 } else { 133 set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 134 clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 135 } 136 137 features = get_features(fs_info, fa->feature_set); 138 139 /* Nothing to do */ 140 if ((val && (features & fa->feature_bit)) || 141 (!val && !(features & fa->feature_bit))) 142 return count; 143 144 if ((val && !(set & fa->feature_bit)) || 145 (!val && !(clear & fa->feature_bit))) { 146 btrfs_info(fs_info, 147 "%sabling feature %s on mounted fs is not supported.", 148 val ? "En" : "Dis", fa->kobj_attr.attr.name); 149 return -EPERM; 150 } 151 152 btrfs_info(fs_info, "%s %s feature flag", 153 val ? "Setting" : "Clearing", fa->kobj_attr.attr.name); 154 155 trans = btrfs_start_transaction(fs_info->fs_root, 0); 156 if (IS_ERR(trans)) 157 return PTR_ERR(trans); 158 159 spin_lock(&fs_info->super_lock); 160 features = get_features(fs_info, fa->feature_set); 161 if (val) 162 features |= fa->feature_bit; 163 else 164 features &= ~fa->feature_bit; 165 set_features(fs_info, fa->feature_set, features); 166 spin_unlock(&fs_info->super_lock); 167 168 ret = btrfs_commit_transaction(trans, fs_info->fs_root); 169 if (ret) 170 return ret; 171 172 return count; 173 } 174 175 static umode_t btrfs_feature_visible(struct kobject *kobj, 176 struct attribute *attr, int unused) 177 { 178 struct btrfs_fs_info *fs_info = to_fs_info(kobj); 179 umode_t mode = attr->mode; 180 181 if (fs_info) { 182 struct btrfs_feature_attr *fa; 183 u64 features; 184 185 fa = attr_to_btrfs_feature_attr(attr); 186 features = get_features(fs_info, fa->feature_set); 187 188 if (can_modify_feature(fa)) 189 mode |= S_IWUSR; 190 else if (!(features & fa->feature_bit)) 191 mode = 0; 192 } 193 194 return mode; 195 } 196 197 BTRFS_FEAT_ATTR_INCOMPAT(mixed_backref, MIXED_BACKREF); 198 BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL); 199 BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS); 200 BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO); 201 BTRFS_FEAT_ATTR_INCOMPAT(big_metadata, BIG_METADATA); 202 BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF); 203 BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56); 204 BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA); 205 BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES); 206 207 static struct attribute *btrfs_supported_feature_attrs[] = { 208 BTRFS_FEAT_ATTR_PTR(mixed_backref), 209 BTRFS_FEAT_ATTR_PTR(default_subvol), 210 BTRFS_FEAT_ATTR_PTR(mixed_groups), 211 BTRFS_FEAT_ATTR_PTR(compress_lzo), 212 BTRFS_FEAT_ATTR_PTR(big_metadata), 213 BTRFS_FEAT_ATTR_PTR(extended_iref), 214 BTRFS_FEAT_ATTR_PTR(raid56), 215 BTRFS_FEAT_ATTR_PTR(skinny_metadata), 216 BTRFS_FEAT_ATTR_PTR(no_holes), 217 NULL 218 }; 219 220 static const struct attribute_group btrfs_feature_attr_group = { 221 .name = "features", 222 .is_visible = btrfs_feature_visible, 223 .attrs = btrfs_supported_feature_attrs, 224 }; 225 226 static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf) 227 { 228 u64 val; 229 if (lock) 230 spin_lock(lock); 231 val = *value_ptr; 232 if (lock) 233 spin_unlock(lock); 234 return snprintf(buf, PAGE_SIZE, "%llu\n", val); 235 } 236 237 static ssize_t global_rsv_size_show(struct kobject *kobj, 238 struct kobj_attribute *ka, char *buf) 239 { 240 struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 241 struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 242 return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf); 243 } 244 BTRFS_ATTR(global_rsv_size, 0444, global_rsv_size_show); 245 246 static ssize_t global_rsv_reserved_show(struct kobject *kobj, 247 struct kobj_attribute *a, char *buf) 248 { 249 struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 250 struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 251 return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf); 252 } 253 BTRFS_ATTR(global_rsv_reserved, 0444, global_rsv_reserved_show); 254 255 #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj) 256 257 static ssize_t raid_bytes_show(struct kobject *kobj, 258 struct kobj_attribute *attr, char *buf); 259 BTRFS_RAID_ATTR(total_bytes, raid_bytes_show); 260 BTRFS_RAID_ATTR(used_bytes, raid_bytes_show); 261 262 static ssize_t raid_bytes_show(struct kobject *kobj, 263 struct kobj_attribute *attr, char *buf) 264 265 { 266 struct btrfs_space_info *sinfo = to_space_info(kobj->parent); 267 struct btrfs_block_group_cache *block_group; 268 int index = kobj - sinfo->block_group_kobjs; 269 u64 val = 0; 270 271 down_read(&sinfo->groups_sem); 272 list_for_each_entry(block_group, &sinfo->block_groups[index], list) { 273 if (&attr->attr == BTRFS_RAID_ATTR_PTR(total_bytes)) 274 val += block_group->key.offset; 275 else 276 val += btrfs_block_group_used(&block_group->item); 277 } 278 up_read(&sinfo->groups_sem); 279 return snprintf(buf, PAGE_SIZE, "%llu\n", val); 280 } 281 282 static struct attribute *raid_attributes[] = { 283 BTRFS_RAID_ATTR_PTR(total_bytes), 284 BTRFS_RAID_ATTR_PTR(used_bytes), 285 NULL 286 }; 287 288 static void release_raid_kobj(struct kobject *kobj) 289 { 290 kobject_put(kobj->parent); 291 } 292 293 struct kobj_type btrfs_raid_ktype = { 294 .sysfs_ops = &kobj_sysfs_ops, 295 .release = release_raid_kobj, 296 .default_attrs = raid_attributes, 297 }; 298 299 #define SPACE_INFO_ATTR(field) \ 300 static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \ 301 struct kobj_attribute *a, \ 302 char *buf) \ 303 { \ 304 struct btrfs_space_info *sinfo = to_space_info(kobj); \ 305 return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \ 306 } \ 307 BTRFS_ATTR(field, 0444, btrfs_space_info_show_##field) 308 309 static ssize_t btrfs_space_info_show_total_bytes_pinned(struct kobject *kobj, 310 struct kobj_attribute *a, 311 char *buf) 312 { 313 struct btrfs_space_info *sinfo = to_space_info(kobj); 314 s64 val = percpu_counter_sum(&sinfo->total_bytes_pinned); 315 return snprintf(buf, PAGE_SIZE, "%lld\n", val); 316 } 317 318 SPACE_INFO_ATTR(flags); 319 SPACE_INFO_ATTR(total_bytes); 320 SPACE_INFO_ATTR(bytes_used); 321 SPACE_INFO_ATTR(bytes_pinned); 322 SPACE_INFO_ATTR(bytes_reserved); 323 SPACE_INFO_ATTR(bytes_may_use); 324 SPACE_INFO_ATTR(disk_used); 325 SPACE_INFO_ATTR(disk_total); 326 BTRFS_ATTR(total_bytes_pinned, 0444, btrfs_space_info_show_total_bytes_pinned); 327 328 static struct attribute *space_info_attrs[] = { 329 BTRFS_ATTR_PTR(flags), 330 BTRFS_ATTR_PTR(total_bytes), 331 BTRFS_ATTR_PTR(bytes_used), 332 BTRFS_ATTR_PTR(bytes_pinned), 333 BTRFS_ATTR_PTR(bytes_reserved), 334 BTRFS_ATTR_PTR(bytes_may_use), 335 BTRFS_ATTR_PTR(disk_used), 336 BTRFS_ATTR_PTR(disk_total), 337 BTRFS_ATTR_PTR(total_bytes_pinned), 338 NULL, 339 }; 340 341 static void space_info_release(struct kobject *kobj) 342 { 343 struct btrfs_space_info *sinfo = to_space_info(kobj); 344 percpu_counter_destroy(&sinfo->total_bytes_pinned); 345 kfree(sinfo); 346 } 347 348 struct kobj_type space_info_ktype = { 349 .sysfs_ops = &kobj_sysfs_ops, 350 .release = space_info_release, 351 .default_attrs = space_info_attrs, 352 }; 353 354 static const struct attribute *allocation_attrs[] = { 355 BTRFS_ATTR_PTR(global_rsv_reserved), 356 BTRFS_ATTR_PTR(global_rsv_size), 357 NULL, 358 }; 359 360 static ssize_t btrfs_label_show(struct kobject *kobj, 361 struct kobj_attribute *a, char *buf) 362 { 363 struct btrfs_fs_info *fs_info = to_fs_info(kobj); 364 return snprintf(buf, PAGE_SIZE, "%s\n", fs_info->super_copy->label); 365 } 366 367 static ssize_t btrfs_label_store(struct kobject *kobj, 368 struct kobj_attribute *a, 369 const char *buf, size_t len) 370 { 371 struct btrfs_fs_info *fs_info = to_fs_info(kobj); 372 struct btrfs_trans_handle *trans; 373 struct btrfs_root *root = fs_info->fs_root; 374 int ret; 375 376 if (len >= BTRFS_LABEL_SIZE) { 377 pr_err("BTRFS: unable to set label with more than %d bytes\n", 378 BTRFS_LABEL_SIZE - 1); 379 return -EINVAL; 380 } 381 382 trans = btrfs_start_transaction(root, 0); 383 if (IS_ERR(trans)) 384 return PTR_ERR(trans); 385 386 spin_lock(&root->fs_info->super_lock); 387 strcpy(fs_info->super_copy->label, buf); 388 spin_unlock(&root->fs_info->super_lock); 389 ret = btrfs_commit_transaction(trans, root); 390 391 if (!ret) 392 return len; 393 394 return ret; 395 } 396 BTRFS_ATTR_RW(label, 0644, btrfs_label_show, btrfs_label_store); 397 398 static struct attribute *btrfs_attrs[] = { 399 BTRFS_ATTR_PTR(label), 400 NULL, 401 }; 402 403 static void btrfs_release_super_kobj(struct kobject *kobj) 404 { 405 struct btrfs_fs_info *fs_info = to_fs_info(kobj); 406 complete(&fs_info->kobj_unregister); 407 } 408 409 static struct kobj_type btrfs_ktype = { 410 .sysfs_ops = &kobj_sysfs_ops, 411 .release = btrfs_release_super_kobj, 412 .default_attrs = btrfs_attrs, 413 }; 414 415 static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj) 416 { 417 if (kobj->ktype != &btrfs_ktype) 418 return NULL; 419 return container_of(kobj, struct btrfs_fs_info, super_kobj); 420 } 421 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) 474 { 475 kobject_del(&fs_info->super_kobj); 476 kobject_put(&fs_info->super_kobj); 477 wait_for_completion(&fs_info->kobj_unregister); 478 } 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 494 const char * const btrfs_feature_set_names[3] = { 495 [FEAT_COMPAT] = "compat", 496 [FEAT_COMPAT_RO] = "compat_ro", 497 [FEAT_INCOMPAT] = "incompat", 498 }; 499 500 char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) 501 { 502 size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */ 503 int len = 0; 504 int i; 505 char *str; 506 507 str = kmalloc(bufsize, GFP_KERNEL); 508 if (!str) 509 return str; 510 511 for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 512 const char *name; 513 514 if (!(flags & (1ULL << i))) 515 continue; 516 517 name = btrfs_feature_attrs[set][i].kobj_attr.attr.name; 518 len += snprintf(str + len, bufsize - len, "%s%s", 519 len ? "," : "", name); 520 } 521 522 return str; 523 } 524 525 static void init_feature_attrs(void) 526 { 527 struct btrfs_feature_attr *fa; 528 int set, i; 529 530 BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names) != 531 ARRAY_SIZE(btrfs_feature_attrs)); 532 BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names[0]) != 533 ARRAY_SIZE(btrfs_feature_attrs[0])); 534 535 memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs)); 536 memset(btrfs_unknown_feature_names, 0, 537 sizeof(btrfs_unknown_feature_names)); 538 539 for (i = 0; btrfs_supported_feature_attrs[i]; i++) { 540 struct btrfs_feature_attr *sfa; 541 struct attribute *a = btrfs_supported_feature_attrs[i]; 542 int bit; 543 sfa = attr_to_btrfs_feature_attr(a); 544 bit = ilog2(sfa->feature_bit); 545 fa = &btrfs_feature_attrs[sfa->feature_set][bit]; 546 547 fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name; 548 } 549 550 for (set = 0; set < FEAT_MAX; set++) { 551 for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 552 char *name = btrfs_unknown_feature_names[set][i]; 553 fa = &btrfs_feature_attrs[set][i]; 554 555 if (fa->kobj_attr.attr.name) 556 continue; 557 558 snprintf(name, 13, "%s:%u", 559 btrfs_feature_set_names[set], i); 560 561 fa->kobj_attr.attr.name = name; 562 fa->kobj_attr.attr.mode = S_IRUGO; 563 fa->feature_set = set; 564 fa->feature_bit = 1ULL << i; 565 } 566 } 567 } 568 569 static int add_device_membership(struct btrfs_fs_info *fs_info) 570 { 571 int error = 0; 572 struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; 573 struct btrfs_device *dev; 574 575 fs_info->device_dir_kobj = kobject_create_and_add("devices", 576 &fs_info->super_kobj); 577 if (!fs_info->device_dir_kobj) 578 return -ENOMEM; 579 580 list_for_each_entry(dev, &fs_devices->devices, dev_list) { 581 struct hd_struct *disk = dev->bdev->bd_part; 582 struct kobject *disk_kobj = &part_to_dev(disk)->kobj; 583 584 error = sysfs_create_link(fs_info->device_dir_kobj, 585 disk_kobj, disk_kobj->name); 586 if (error) 587 break; 588 } 589 590 return error; 591 } 592 593 /* /sys/fs/btrfs/ entry */ 594 static struct kset *btrfs_kset; 595 596 int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info) 597 { 598 int error; 599 600 init_completion(&fs_info->kobj_unregister); 601 fs_info->super_kobj.kset = btrfs_kset; 602 error = kobject_init_and_add(&fs_info->super_kobj, &btrfs_ktype, NULL, 603 "%pU", fs_info->fsid); 604 if (error) 605 return error; 606 607 error = sysfs_create_group(&fs_info->super_kobj, 608 &btrfs_feature_attr_group); 609 if (error) { 610 __btrfs_sysfs_remove_one(fs_info); 611 return error; 612 } 613 614 error = addrm_unknown_feature_attrs(fs_info, true); 615 if (error) 616 goto failure; 617 618 error = add_device_membership(fs_info); 619 if (error) 620 goto failure; 621 622 fs_info->space_info_kobj = kobject_create_and_add("allocation", 623 &fs_info->super_kobj); 624 if (!fs_info->space_info_kobj) { 625 error = -ENOMEM; 626 goto failure; 627 } 628 629 error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs); 630 if (error) 631 goto failure; 632 633 return 0; 634 failure: 635 btrfs_sysfs_remove_one(fs_info); 636 return error; 637 } 638 639 int btrfs_init_sysfs(void) 640 { 641 int ret; 642 btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); 643 if (!btrfs_kset) 644 return -ENOMEM; 645 646 init_feature_attrs(); 647 648 ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 649 if (ret) { 650 kset_unregister(btrfs_kset); 651 return ret; 652 } 653 654 return 0; 655 } 656 657 void btrfs_exit_sysfs(void) 658 { 659 sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 660 kset_unregister(btrfs_kset); 661 } 662 663