1c1d7c514SDavid Sterba // SPDX-License-Identifier: GPL-2.0 26cbd5570SChris Mason /* 36cbd5570SChris Mason * Copyright (C) 2007 Oracle. All rights reserved. 46cbd5570SChris Mason */ 56cbd5570SChris Mason 658176a96SJosef Bacik #include <linux/sched.h> 732a9991fSDavid Sterba #include <linux/sched/mm.h> 858176a96SJosef Bacik #include <linux/slab.h> 958176a96SJosef Bacik #include <linux/spinlock.h> 1058176a96SJosef Bacik #include <linux/completion.h> 1179da4fa4SJeff Mahoney #include <linux/bug.h> 1258176a96SJosef Bacik 13bae45de0SChris Mason #include "ctree.h" 14bae45de0SChris Mason #include "disk-io.h" 15bae45de0SChris Mason #include "transaction.h" 16079b72bcSJeff Mahoney #include "sysfs.h" 1729e5be24SJeff Mahoney #include "volumes.h" 188719aaaeSJosef Bacik #include "space-info.h" 19aac0023cSJosef Bacik #include "block-group.h" 20079b72bcSJeff Mahoney 219188db61SDavid Sterba struct btrfs_feature_attr { 229188db61SDavid Sterba struct kobj_attribute kobj_attr; 239188db61SDavid Sterba enum btrfs_feature_set feature_set; 249188db61SDavid Sterba u64 feature_bit; 259188db61SDavid Sterba }; 269188db61SDavid Sterba 279188db61SDavid Sterba /* For raid type sysfs entries */ 289188db61SDavid Sterba struct raid_kobject { 299188db61SDavid Sterba u64 flags; 309188db61SDavid Sterba struct kobject kobj; 319188db61SDavid Sterba }; 329188db61SDavid Sterba 339188db61SDavid Sterba #define __INIT_KOBJ_ATTR(_name, _mode, _show, _store) \ 349188db61SDavid Sterba { \ 359188db61SDavid Sterba .attr = { .name = __stringify(_name), .mode = _mode }, \ 369188db61SDavid Sterba .show = _show, \ 379188db61SDavid Sterba .store = _store, \ 389188db61SDavid Sterba } 399188db61SDavid Sterba 409188db61SDavid Sterba #define BTRFS_ATTR_RW(_prefix, _name, _show, _store) \ 419188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 429188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0644, _show, _store) 439188db61SDavid Sterba 449188db61SDavid Sterba #define BTRFS_ATTR(_prefix, _name, _show) \ 459188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 469188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0444, _show, NULL) 479188db61SDavid Sterba 489188db61SDavid Sterba #define BTRFS_ATTR_PTR(_prefix, _name) \ 499188db61SDavid Sterba (&btrfs_attr_##_prefix##_##_name.attr) 509188db61SDavid Sterba 519188db61SDavid Sterba #define BTRFS_FEAT_ATTR(_name, _feature_set, _feature_prefix, _feature_bit) \ 529188db61SDavid Sterba static struct btrfs_feature_attr btrfs_attr_features_##_name = { \ 539188db61SDavid Sterba .kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO, \ 549188db61SDavid Sterba btrfs_feature_attr_show, \ 559188db61SDavid Sterba btrfs_feature_attr_store), \ 569188db61SDavid Sterba .feature_set = _feature_set, \ 579188db61SDavid Sterba .feature_bit = _feature_prefix ##_## _feature_bit, \ 589188db61SDavid Sterba } 599188db61SDavid Sterba #define BTRFS_FEAT_ATTR_PTR(_name) \ 609188db61SDavid Sterba (&btrfs_attr_features_##_name.kobj_attr.attr) 619188db61SDavid Sterba 629188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT(name, feature) \ 639188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT, BTRFS_FEATURE_COMPAT, feature) 649188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT_RO(name, feature) \ 659188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT_RO, BTRFS_FEATURE_COMPAT_RO, feature) 669188db61SDavid Sterba #define BTRFS_FEAT_ATTR_INCOMPAT(name, feature) \ 679188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_INCOMPAT, BTRFS_FEATURE_INCOMPAT, feature) 689188db61SDavid Sterba 69510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); 702e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj); 715ac1d209SJeff Mahoney 728f52316cSDavid Sterba static struct btrfs_feature_attr *to_btrfs_feature_attr(struct kobj_attribute *a) 738f52316cSDavid Sterba { 748f52316cSDavid Sterba return container_of(a, struct btrfs_feature_attr, kobj_attr); 758f52316cSDavid Sterba } 768f52316cSDavid Sterba 778f52316cSDavid Sterba static struct kobj_attribute *attr_to_btrfs_attr(struct attribute *attr) 788f52316cSDavid Sterba { 798f52316cSDavid Sterba return container_of(attr, struct kobj_attribute, attr); 808f52316cSDavid Sterba } 818f52316cSDavid Sterba 828f52316cSDavid Sterba static struct btrfs_feature_attr *attr_to_btrfs_feature_attr( 838f52316cSDavid Sterba struct attribute *attr) 848f52316cSDavid Sterba { 858f52316cSDavid Sterba return to_btrfs_feature_attr(attr_to_btrfs_attr(attr)); 868f52316cSDavid Sterba } 878f52316cSDavid Sterba 88510d7360SJeff Mahoney static u64 get_features(struct btrfs_fs_info *fs_info, 89510d7360SJeff Mahoney enum btrfs_feature_set set) 905ac1d209SJeff Mahoney { 91510d7360SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 92510d7360SJeff Mahoney if (set == FEAT_COMPAT) 93510d7360SJeff Mahoney return btrfs_super_compat_flags(disk_super); 94510d7360SJeff Mahoney else if (set == FEAT_COMPAT_RO) 95510d7360SJeff Mahoney return btrfs_super_compat_ro_flags(disk_super); 96510d7360SJeff Mahoney else 97510d7360SJeff Mahoney return btrfs_super_incompat_flags(disk_super); 985ac1d209SJeff Mahoney } 995ac1d209SJeff Mahoney 100ba631941SJeff Mahoney static void set_features(struct btrfs_fs_info *fs_info, 101ba631941SJeff Mahoney enum btrfs_feature_set set, u64 features) 102ba631941SJeff Mahoney { 103ba631941SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 104ba631941SJeff Mahoney if (set == FEAT_COMPAT) 105ba631941SJeff Mahoney btrfs_set_super_compat_flags(disk_super, features); 106ba631941SJeff Mahoney else if (set == FEAT_COMPAT_RO) 107ba631941SJeff Mahoney btrfs_set_super_compat_ro_flags(disk_super, features); 108ba631941SJeff Mahoney else 109ba631941SJeff Mahoney btrfs_set_super_incompat_flags(disk_super, features); 110ba631941SJeff Mahoney } 111ba631941SJeff Mahoney 112ba631941SJeff Mahoney static int can_modify_feature(struct btrfs_feature_attr *fa) 113ba631941SJeff Mahoney { 114ba631941SJeff Mahoney int val = 0; 115ba631941SJeff Mahoney u64 set, clear; 116ba631941SJeff Mahoney switch (fa->feature_set) { 117ba631941SJeff Mahoney case FEAT_COMPAT: 118ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 119ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 120ba631941SJeff Mahoney break; 121ba631941SJeff Mahoney case FEAT_COMPAT_RO: 122ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 123ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 124ba631941SJeff Mahoney break; 125ba631941SJeff Mahoney case FEAT_INCOMPAT: 126ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 127ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 128ba631941SJeff Mahoney break; 129ba631941SJeff Mahoney default: 13062e85577SJeff Mahoney pr_warn("btrfs: sysfs: unknown feature set %d\n", 131cc37bb04SDavid Sterba fa->feature_set); 132cc37bb04SDavid Sterba return 0; 133ba631941SJeff Mahoney } 134ba631941SJeff Mahoney 135ba631941SJeff Mahoney if (set & fa->feature_bit) 136ba631941SJeff Mahoney val |= 1; 137ba631941SJeff Mahoney if (clear & fa->feature_bit) 138ba631941SJeff Mahoney val |= 2; 139ba631941SJeff Mahoney 140ba631941SJeff Mahoney return val; 141ba631941SJeff Mahoney } 142ba631941SJeff Mahoney 143079b72bcSJeff Mahoney static ssize_t btrfs_feature_attr_show(struct kobject *kobj, 144079b72bcSJeff Mahoney struct kobj_attribute *a, char *buf) 145079b72bcSJeff Mahoney { 146510d7360SJeff Mahoney int val = 0; 147510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 148510d7360SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 149ba631941SJeff Mahoney if (fs_info) { 150510d7360SJeff Mahoney u64 features = get_features(fs_info, fa->feature_set); 151510d7360SJeff Mahoney if (features & fa->feature_bit) 152510d7360SJeff Mahoney val = 1; 153ba631941SJeff Mahoney } else 154ba631941SJeff Mahoney val = can_modify_feature(fa); 155510d7360SJeff Mahoney 156510d7360SJeff Mahoney return snprintf(buf, PAGE_SIZE, "%d\n", val); 157510d7360SJeff Mahoney } 158510d7360SJeff Mahoney 159ba631941SJeff Mahoney static ssize_t btrfs_feature_attr_store(struct kobject *kobj, 160ba631941SJeff Mahoney struct kobj_attribute *a, 161ba631941SJeff Mahoney const char *buf, size_t count) 162ba631941SJeff Mahoney { 163ba631941SJeff Mahoney struct btrfs_fs_info *fs_info; 164ba631941SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 165ba631941SJeff Mahoney u64 features, set, clear; 166ba631941SJeff Mahoney unsigned long val; 167ba631941SJeff Mahoney int ret; 168ba631941SJeff Mahoney 169ba631941SJeff Mahoney fs_info = to_fs_info(kobj); 170ba631941SJeff Mahoney if (!fs_info) 171ba631941SJeff Mahoney return -EPERM; 172ba631941SJeff Mahoney 173bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 174ee611138SDavid Sterba return -EROFS; 175ee611138SDavid Sterba 176ba631941SJeff Mahoney ret = kstrtoul(skip_spaces(buf), 0, &val); 177ba631941SJeff Mahoney if (ret) 178ba631941SJeff Mahoney return ret; 179ba631941SJeff Mahoney 180ba631941SJeff Mahoney if (fa->feature_set == FEAT_COMPAT) { 181ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 182ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 183ba631941SJeff Mahoney } else if (fa->feature_set == FEAT_COMPAT_RO) { 184ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 185ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 186ba631941SJeff Mahoney } else { 187ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 188ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 189ba631941SJeff Mahoney } 190ba631941SJeff Mahoney 191ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 192ba631941SJeff Mahoney 193ba631941SJeff Mahoney /* Nothing to do */ 194ba631941SJeff Mahoney if ((val && (features & fa->feature_bit)) || 195ba631941SJeff Mahoney (!val && !(features & fa->feature_bit))) 196ba631941SJeff Mahoney return count; 197ba631941SJeff Mahoney 198ba631941SJeff Mahoney if ((val && !(set & fa->feature_bit)) || 199ba631941SJeff Mahoney (!val && !(clear & fa->feature_bit))) { 200ba631941SJeff Mahoney btrfs_info(fs_info, 201ba631941SJeff Mahoney "%sabling feature %s on mounted fs is not supported.", 202ba631941SJeff Mahoney val ? "En" : "Dis", fa->kobj_attr.attr.name); 203ba631941SJeff Mahoney return -EPERM; 204ba631941SJeff Mahoney } 205ba631941SJeff Mahoney 206ba631941SJeff Mahoney btrfs_info(fs_info, "%s %s feature flag", 207ba631941SJeff Mahoney val ? "Setting" : "Clearing", fa->kobj_attr.attr.name); 208ba631941SJeff Mahoney 209ba631941SJeff Mahoney spin_lock(&fs_info->super_lock); 210ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 211ba631941SJeff Mahoney if (val) 212ba631941SJeff Mahoney features |= fa->feature_bit; 213ba631941SJeff Mahoney else 214ba631941SJeff Mahoney features &= ~fa->feature_bit; 215ba631941SJeff Mahoney set_features(fs_info, fa->feature_set, features); 216ba631941SJeff Mahoney spin_unlock(&fs_info->super_lock); 217ba631941SJeff Mahoney 2180eae2747SDavid Sterba /* 2190eae2747SDavid Sterba * We don't want to do full transaction commit from inside sysfs 2200eae2747SDavid Sterba */ 2210eae2747SDavid Sterba btrfs_set_pending(fs_info, COMMIT); 2220eae2747SDavid Sterba wake_up_process(fs_info->transaction_kthread); 223ba631941SJeff Mahoney 224ba631941SJeff Mahoney return count; 225ba631941SJeff Mahoney } 226ba631941SJeff Mahoney 227510d7360SJeff Mahoney static umode_t btrfs_feature_visible(struct kobject *kobj, 228510d7360SJeff Mahoney struct attribute *attr, int unused) 229510d7360SJeff Mahoney { 230510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 231510d7360SJeff Mahoney umode_t mode = attr->mode; 232510d7360SJeff Mahoney 233510d7360SJeff Mahoney if (fs_info) { 234510d7360SJeff Mahoney struct btrfs_feature_attr *fa; 235510d7360SJeff Mahoney u64 features; 236510d7360SJeff Mahoney 237510d7360SJeff Mahoney fa = attr_to_btrfs_feature_attr(attr); 238510d7360SJeff Mahoney features = get_features(fs_info, fa->feature_set); 239510d7360SJeff Mahoney 240ba631941SJeff Mahoney if (can_modify_feature(fa)) 241ba631941SJeff Mahoney mode |= S_IWUSR; 242ba631941SJeff Mahoney else if (!(features & fa->feature_bit)) 243510d7360SJeff Mahoney mode = 0; 244510d7360SJeff Mahoney } 245510d7360SJeff Mahoney 246510d7360SJeff Mahoney return mode; 247079b72bcSJeff Mahoney } 248079b72bcSJeff Mahoney 249079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_backref, MIXED_BACKREF); 250079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL); 251079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS); 252079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO); 2535c1aab1dSNick Terrell BTRFS_FEAT_ATTR_INCOMPAT(compress_zstd, COMPRESS_ZSTD); 254079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(big_metadata, BIG_METADATA); 255079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF); 256079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56); 257079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA); 258c736c095SDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES); 25956f20f40SNikolay Borisov BTRFS_FEAT_ATTR_INCOMPAT(metadata_uuid, METADATA_UUID); 2603b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE); 261079b72bcSJeff Mahoney 262079b72bcSJeff Mahoney static struct attribute *btrfs_supported_feature_attrs[] = { 263079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_backref), 264079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(default_subvol), 265079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_groups), 266079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(compress_lzo), 2675c1aab1dSNick Terrell BTRFS_FEAT_ATTR_PTR(compress_zstd), 268079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(big_metadata), 269079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(extended_iref), 270079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(raid56), 271079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(skinny_metadata), 272c736c095SDavid Sterba BTRFS_FEAT_ATTR_PTR(no_holes), 27356f20f40SNikolay Borisov BTRFS_FEAT_ATTR_PTR(metadata_uuid), 2743b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_PTR(free_space_tree), 275079b72bcSJeff Mahoney NULL 276079b72bcSJeff Mahoney }; 277079b72bcSJeff Mahoney 278f902bd3aSMisono Tomohiro /* 279f902bd3aSMisono Tomohiro * Features which depend on feature bits and may differ between each fs. 280f902bd3aSMisono Tomohiro * 281f902bd3aSMisono Tomohiro * /sys/fs/btrfs/features lists all available features of this kernel while 282f902bd3aSMisono Tomohiro * /sys/fs/btrfs/UUID/features shows features of the fs which are enabled or 283f902bd3aSMisono Tomohiro * can be changed online. 284f902bd3aSMisono Tomohiro */ 285079b72bcSJeff Mahoney static const struct attribute_group btrfs_feature_attr_group = { 286079b72bcSJeff Mahoney .name = "features", 287510d7360SJeff Mahoney .is_visible = btrfs_feature_visible, 288079b72bcSJeff Mahoney .attrs = btrfs_supported_feature_attrs, 289079b72bcSJeff Mahoney }; 29058176a96SJosef Bacik 291f902bd3aSMisono Tomohiro static ssize_t rmdir_subvol_show(struct kobject *kobj, 292f902bd3aSMisono Tomohiro struct kobj_attribute *ka, char *buf) 293f902bd3aSMisono Tomohiro { 294f902bd3aSMisono Tomohiro return snprintf(buf, PAGE_SIZE, "0\n"); 295f902bd3aSMisono Tomohiro } 296f902bd3aSMisono Tomohiro BTRFS_ATTR(static_feature, rmdir_subvol, rmdir_subvol_show); 297f902bd3aSMisono Tomohiro 298f902bd3aSMisono Tomohiro static struct attribute *btrfs_supported_static_feature_attrs[] = { 299f902bd3aSMisono Tomohiro BTRFS_ATTR_PTR(static_feature, rmdir_subvol), 300f902bd3aSMisono Tomohiro NULL 301f902bd3aSMisono Tomohiro }; 302f902bd3aSMisono Tomohiro 303f902bd3aSMisono Tomohiro /* 304f902bd3aSMisono Tomohiro * Features which only depend on kernel version. 305f902bd3aSMisono Tomohiro * 306f902bd3aSMisono Tomohiro * These are listed in /sys/fs/btrfs/features along with 307f902bd3aSMisono Tomohiro * btrfs_feature_attr_group 308f902bd3aSMisono Tomohiro */ 309f902bd3aSMisono Tomohiro static const struct attribute_group btrfs_static_feature_attr_group = { 310f902bd3aSMisono Tomohiro .name = "features", 311f902bd3aSMisono Tomohiro .attrs = btrfs_supported_static_feature_attrs, 312f902bd3aSMisono Tomohiro }; 313f902bd3aSMisono Tomohiro 3146e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 3156e369febSDavid Sterba 3166e369febSDavid Sterba /* 3176e369febSDavid Sterba * Runtime debugging exported via sysfs 3186e369febSDavid Sterba * 3196e369febSDavid Sterba * /sys/fs/btrfs/debug - applies to module or all filesystems 3206e369febSDavid Sterba * /sys/fs/btrfs/UUID - applies only to the given filesystem 3216e369febSDavid Sterba */ 3226e369febSDavid Sterba static struct attribute *btrfs_debug_feature_attrs[] = { 3236e369febSDavid Sterba NULL 3246e369febSDavid Sterba }; 3256e369febSDavid Sterba 3266e369febSDavid Sterba static const struct attribute_group btrfs_debug_feature_attr_group = { 3276e369febSDavid Sterba .name = "debug", 3286e369febSDavid Sterba .attrs = btrfs_debug_feature_attrs, 3296e369febSDavid Sterba }; 3306e369febSDavid Sterba 3316e369febSDavid Sterba #endif 3326e369febSDavid Sterba 3336ab0a202SJeff Mahoney static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf) 3346ab0a202SJeff Mahoney { 3356ab0a202SJeff Mahoney u64 val; 3366ab0a202SJeff Mahoney if (lock) 3376ab0a202SJeff Mahoney spin_lock(lock); 3386ab0a202SJeff Mahoney val = *value_ptr; 3396ab0a202SJeff Mahoney if (lock) 3406ab0a202SJeff Mahoney spin_unlock(lock); 3416ab0a202SJeff Mahoney return snprintf(buf, PAGE_SIZE, "%llu\n", val); 3426ab0a202SJeff Mahoney } 3436ab0a202SJeff Mahoney 3446ab0a202SJeff Mahoney static ssize_t global_rsv_size_show(struct kobject *kobj, 3456ab0a202SJeff Mahoney struct kobj_attribute *ka, char *buf) 3466ab0a202SJeff Mahoney { 3476ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 3486ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 3496ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf); 3506ab0a202SJeff Mahoney } 351a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_size, global_rsv_size_show); 3526ab0a202SJeff Mahoney 3536ab0a202SJeff Mahoney static ssize_t global_rsv_reserved_show(struct kobject *kobj, 3546ab0a202SJeff Mahoney struct kobj_attribute *a, char *buf) 3556ab0a202SJeff Mahoney { 3566ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 3576ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 3586ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf); 3596ab0a202SJeff Mahoney } 360a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_reserved, global_rsv_reserved_show); 3616ab0a202SJeff Mahoney 3626ab0a202SJeff Mahoney #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj) 363c1895442SJeff Mahoney #define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj) 3646ab0a202SJeff Mahoney 3656ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 3666ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf); 367a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, total_bytes, raid_bytes_show); 368a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, used_bytes, raid_bytes_show); 3696ab0a202SJeff Mahoney 3706ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 3716ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf) 3726ab0a202SJeff Mahoney 3736ab0a202SJeff Mahoney { 3746ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj->parent); 3756ab0a202SJeff Mahoney struct btrfs_block_group_cache *block_group; 37675cb379dSJeff Mahoney int index = btrfs_bg_flags_to_raid_index(to_raid_kobj(kobj)->flags); 3776ab0a202SJeff Mahoney u64 val = 0; 3786ab0a202SJeff Mahoney 3796ab0a202SJeff Mahoney down_read(&sinfo->groups_sem); 3806ab0a202SJeff Mahoney list_for_each_entry(block_group, &sinfo->block_groups[index], list) { 381a969f4ccSHans van Kranenburg if (&attr->attr == BTRFS_ATTR_PTR(raid, total_bytes)) 3826ab0a202SJeff Mahoney val += block_group->key.offset; 3836ab0a202SJeff Mahoney else 3846ab0a202SJeff Mahoney val += btrfs_block_group_used(&block_group->item); 3856ab0a202SJeff Mahoney } 3866ab0a202SJeff Mahoney up_read(&sinfo->groups_sem); 3876ab0a202SJeff Mahoney return snprintf(buf, PAGE_SIZE, "%llu\n", val); 3886ab0a202SJeff Mahoney } 3896ab0a202SJeff Mahoney 3907c7e3014SKimberly Brown static struct attribute *raid_attrs[] = { 391a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, total_bytes), 392a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, used_bytes), 3936ab0a202SJeff Mahoney NULL 3946ab0a202SJeff Mahoney }; 3957c7e3014SKimberly Brown ATTRIBUTE_GROUPS(raid); 3966ab0a202SJeff Mahoney 3976ab0a202SJeff Mahoney static void release_raid_kobj(struct kobject *kobj) 3986ab0a202SJeff Mahoney { 399c1895442SJeff Mahoney kfree(to_raid_kobj(kobj)); 4006ab0a202SJeff Mahoney } 4016ab0a202SJeff Mahoney 402536ea45cSDavid Sterba static struct kobj_type btrfs_raid_ktype = { 4036ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 4046ab0a202SJeff Mahoney .release = release_raid_kobj, 4057c7e3014SKimberly Brown .default_groups = raid_groups, 4066ab0a202SJeff Mahoney }; 4076ab0a202SJeff Mahoney 4086ab0a202SJeff Mahoney #define SPACE_INFO_ATTR(field) \ 4096ab0a202SJeff Mahoney static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \ 4106ab0a202SJeff Mahoney struct kobj_attribute *a, \ 4116ab0a202SJeff Mahoney char *buf) \ 4126ab0a202SJeff Mahoney { \ 4136ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); \ 4146ab0a202SJeff Mahoney return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \ 4156ab0a202SJeff Mahoney } \ 416a969f4ccSHans van Kranenburg BTRFS_ATTR(space_info, field, btrfs_space_info_show_##field) 4176ab0a202SJeff Mahoney 4186ab0a202SJeff Mahoney static ssize_t btrfs_space_info_show_total_bytes_pinned(struct kobject *kobj, 4196ab0a202SJeff Mahoney struct kobj_attribute *a, 4206ab0a202SJeff Mahoney char *buf) 4216ab0a202SJeff Mahoney { 4226ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); 4236ab0a202SJeff Mahoney s64 val = percpu_counter_sum(&sinfo->total_bytes_pinned); 4246ab0a202SJeff Mahoney return snprintf(buf, PAGE_SIZE, "%lld\n", val); 4256ab0a202SJeff Mahoney } 4266ab0a202SJeff Mahoney 4276ab0a202SJeff Mahoney SPACE_INFO_ATTR(flags); 4286ab0a202SJeff Mahoney SPACE_INFO_ATTR(total_bytes); 4296ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_used); 4306ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_pinned); 4316ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_reserved); 4326ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_may_use); 433c1fd5c30SWang Xiaoguang SPACE_INFO_ATTR(bytes_readonly); 4346ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_used); 4356ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_total); 436a969f4ccSHans van Kranenburg BTRFS_ATTR(space_info, total_bytes_pinned, 437a969f4ccSHans van Kranenburg btrfs_space_info_show_total_bytes_pinned); 4386ab0a202SJeff Mahoney 4396ab0a202SJeff Mahoney static struct attribute *space_info_attrs[] = { 440a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, flags), 441a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, total_bytes), 442a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_used), 443a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_pinned), 444a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_reserved), 445a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_may_use), 446a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_readonly), 447a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_used), 448a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_total), 449a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, total_bytes_pinned), 4506ab0a202SJeff Mahoney NULL, 4516ab0a202SJeff Mahoney }; 4527c7e3014SKimberly Brown ATTRIBUTE_GROUPS(space_info); 4536ab0a202SJeff Mahoney 4546ab0a202SJeff Mahoney static void space_info_release(struct kobject *kobj) 4556ab0a202SJeff Mahoney { 4566ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); 4576ab0a202SJeff Mahoney percpu_counter_destroy(&sinfo->total_bytes_pinned); 4586ab0a202SJeff Mahoney kfree(sinfo); 4596ab0a202SJeff Mahoney } 4606ab0a202SJeff Mahoney 46127992d01SDavid Sterba static struct kobj_type space_info_ktype = { 4626ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 4636ab0a202SJeff Mahoney .release = space_info_release, 4647c7e3014SKimberly Brown .default_groups = space_info_groups, 4656ab0a202SJeff Mahoney }; 4666ab0a202SJeff Mahoney 4676ab0a202SJeff Mahoney static const struct attribute *allocation_attrs[] = { 468a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_reserved), 469a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_size), 4706ab0a202SJeff Mahoney NULL, 4716ab0a202SJeff Mahoney }; 4726ab0a202SJeff Mahoney 473f8ba9c11SJeff Mahoney static ssize_t btrfs_label_show(struct kobject *kobj, 474f8ba9c11SJeff Mahoney struct kobj_attribute *a, char *buf) 475f8ba9c11SJeff Mahoney { 476f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 47748fcc3ffSSatoru Takeuchi char *label = fs_info->super_copy->label; 478ee17fc80SDavid Sterba ssize_t ret; 479ee17fc80SDavid Sterba 480ee17fc80SDavid Sterba spin_lock(&fs_info->super_lock); 481ee17fc80SDavid Sterba ret = snprintf(buf, PAGE_SIZE, label[0] ? "%s\n" : "%s", label); 482ee17fc80SDavid Sterba spin_unlock(&fs_info->super_lock); 483ee17fc80SDavid Sterba 484ee17fc80SDavid Sterba return ret; 485f8ba9c11SJeff Mahoney } 486f8ba9c11SJeff Mahoney 487f8ba9c11SJeff Mahoney static ssize_t btrfs_label_store(struct kobject *kobj, 488f8ba9c11SJeff Mahoney struct kobj_attribute *a, 489f8ba9c11SJeff Mahoney const char *buf, size_t len) 490f8ba9c11SJeff Mahoney { 491f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 49248fcc3ffSSatoru Takeuchi size_t p_len; 493f8ba9c11SJeff Mahoney 49466ac9fe7SDavid Sterba if (!fs_info) 49566ac9fe7SDavid Sterba return -EPERM; 49666ac9fe7SDavid Sterba 497bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 49879aec2b8SAnand Jain return -EROFS; 49979aec2b8SAnand Jain 50048fcc3ffSSatoru Takeuchi /* 50148fcc3ffSSatoru Takeuchi * p_len is the len until the first occurrence of either 50248fcc3ffSSatoru Takeuchi * '\n' or '\0' 50348fcc3ffSSatoru Takeuchi */ 50448fcc3ffSSatoru Takeuchi p_len = strcspn(buf, "\n"); 50548fcc3ffSSatoru Takeuchi 50648fcc3ffSSatoru Takeuchi if (p_len >= BTRFS_LABEL_SIZE) 507f8ba9c11SJeff Mahoney return -EINVAL; 508f8ba9c11SJeff Mahoney 509a6f69dc8SDavid Sterba spin_lock(&fs_info->super_lock); 51048fcc3ffSSatoru Takeuchi memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE); 51148fcc3ffSSatoru Takeuchi memcpy(fs_info->super_copy->label, buf, p_len); 512a6f69dc8SDavid Sterba spin_unlock(&fs_info->super_lock); 513f8ba9c11SJeff Mahoney 514a6f69dc8SDavid Sterba /* 515a6f69dc8SDavid Sterba * We don't want to do full transaction commit from inside sysfs 516a6f69dc8SDavid Sterba */ 517a6f69dc8SDavid Sterba btrfs_set_pending(fs_info, COMMIT); 518a6f69dc8SDavid Sterba wake_up_process(fs_info->transaction_kthread); 519a6f69dc8SDavid Sterba 520f8ba9c11SJeff Mahoney return len; 521f8ba9c11SJeff Mahoney } 522a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, label, btrfs_label_show, btrfs_label_store); 523f8ba9c11SJeff Mahoney 524df93589aSDavid Sterba static ssize_t btrfs_nodesize_show(struct kobject *kobj, 525df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 526df93589aSDavid Sterba { 527df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 528df93589aSDavid Sterba 529093e037cSDavid Sterba return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->nodesize); 530df93589aSDavid Sterba } 531df93589aSDavid Sterba 532a969f4ccSHans van Kranenburg BTRFS_ATTR(, nodesize, btrfs_nodesize_show); 533df93589aSDavid Sterba 534df93589aSDavid Sterba static ssize_t btrfs_sectorsize_show(struct kobject *kobj, 535df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 536df93589aSDavid Sterba { 537df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 538df93589aSDavid Sterba 539093e037cSDavid Sterba return snprintf(buf, PAGE_SIZE, "%u\n", 540093e037cSDavid Sterba fs_info->super_copy->sectorsize); 541df93589aSDavid Sterba } 542df93589aSDavid Sterba 543a969f4ccSHans van Kranenburg BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show); 544df93589aSDavid Sterba 545df93589aSDavid Sterba static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, 546df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 547df93589aSDavid Sterba { 548df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 549df93589aSDavid Sterba 550093e037cSDavid Sterba return snprintf(buf, PAGE_SIZE, "%u\n", 551093e037cSDavid Sterba fs_info->super_copy->sectorsize); 552df93589aSDavid Sterba } 553df93589aSDavid Sterba 554a969f4ccSHans van Kranenburg BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show); 555df93589aSDavid Sterba 5562723480aSSargun Dhillon static ssize_t quota_override_show(struct kobject *kobj, 5572723480aSSargun Dhillon struct kobj_attribute *a, char *buf) 5582723480aSSargun Dhillon { 5592723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 5602723480aSSargun Dhillon int quota_override; 5612723480aSSargun Dhillon 5622723480aSSargun Dhillon quota_override = test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 5632723480aSSargun Dhillon return snprintf(buf, PAGE_SIZE, "%d\n", quota_override); 5642723480aSSargun Dhillon } 5652723480aSSargun Dhillon 5662723480aSSargun Dhillon static ssize_t quota_override_store(struct kobject *kobj, 5672723480aSSargun Dhillon struct kobj_attribute *a, 5682723480aSSargun Dhillon const char *buf, size_t len) 5692723480aSSargun Dhillon { 5702723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 5712723480aSSargun Dhillon unsigned long knob; 5722723480aSSargun Dhillon int err; 5732723480aSSargun Dhillon 5742723480aSSargun Dhillon if (!fs_info) 5752723480aSSargun Dhillon return -EPERM; 5762723480aSSargun Dhillon 5772723480aSSargun Dhillon if (!capable(CAP_SYS_RESOURCE)) 5782723480aSSargun Dhillon return -EPERM; 5792723480aSSargun Dhillon 5802723480aSSargun Dhillon err = kstrtoul(buf, 10, &knob); 5812723480aSSargun Dhillon if (err) 5822723480aSSargun Dhillon return err; 5832723480aSSargun Dhillon if (knob > 1) 5842723480aSSargun Dhillon return -EINVAL; 5852723480aSSargun Dhillon 5862723480aSSargun Dhillon if (knob) 5872723480aSSargun Dhillon set_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 5882723480aSSargun Dhillon else 5892723480aSSargun Dhillon clear_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 5902723480aSSargun Dhillon 5912723480aSSargun Dhillon return len; 5922723480aSSargun Dhillon } 5932723480aSSargun Dhillon 594a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, quota_override, quota_override_show, quota_override_store); 5952723480aSSargun Dhillon 59656f20f40SNikolay Borisov static ssize_t btrfs_metadata_uuid_show(struct kobject *kobj, 59756f20f40SNikolay Borisov struct kobj_attribute *a, char *buf) 59856f20f40SNikolay Borisov { 59956f20f40SNikolay Borisov struct btrfs_fs_info *fs_info = to_fs_info(kobj); 60056f20f40SNikolay Borisov 60156f20f40SNikolay Borisov return snprintf(buf, PAGE_SIZE, "%pU\n", 60256f20f40SNikolay Borisov fs_info->fs_devices->metadata_uuid); 60356f20f40SNikolay Borisov } 60456f20f40SNikolay Borisov 60556f20f40SNikolay Borisov BTRFS_ATTR(, metadata_uuid, btrfs_metadata_uuid_show); 60656f20f40SNikolay Borisov 6070dd2906fSAnand Jain static const struct attribute *btrfs_attrs[] = { 608a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, label), 609a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, nodesize), 610a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, sectorsize), 611a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, clone_alignment), 612a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, quota_override), 61356f20f40SNikolay Borisov BTRFS_ATTR_PTR(, metadata_uuid), 614f8ba9c11SJeff Mahoney NULL, 615f8ba9c11SJeff Mahoney }; 616f8ba9c11SJeff Mahoney 617c1b7e474SAnand Jain static void btrfs_release_fsid_kobj(struct kobject *kobj) 618510d7360SJeff Mahoney { 6192e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj); 620248d200dSAnand Jain 621c1b7e474SAnand Jain memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject)); 6222e7910d6SAnand Jain complete(&fs_devs->kobj_unregister); 623510d7360SJeff Mahoney } 624510d7360SJeff Mahoney 625510d7360SJeff Mahoney static struct kobj_type btrfs_ktype = { 626510d7360SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 627c1b7e474SAnand Jain .release = btrfs_release_fsid_kobj, 628510d7360SJeff Mahoney }; 629510d7360SJeff Mahoney 6302e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj) 6312e7910d6SAnand Jain { 6322e7910d6SAnand Jain if (kobj->ktype != &btrfs_ktype) 6332e7910d6SAnand Jain return NULL; 634c1b7e474SAnand Jain return container_of(kobj, struct btrfs_fs_devices, fsid_kobj); 6352e7910d6SAnand Jain } 6362e7910d6SAnand Jain 637510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj) 638510d7360SJeff Mahoney { 639510d7360SJeff Mahoney if (kobj->ktype != &btrfs_ktype) 640510d7360SJeff Mahoney return NULL; 6412e7910d6SAnand Jain return to_fs_devs(kobj)->fs_info; 642510d7360SJeff Mahoney } 64358176a96SJosef Bacik 644e453d989SJeff Mahoney #define NUM_FEATURE_BITS 64 6456c52157fSTomohiro Misono #define BTRFS_FEATURE_NAME_MAX 13 6466c52157fSTomohiro Misono static char btrfs_unknown_feature_names[FEAT_MAX][NUM_FEATURE_BITS][BTRFS_FEATURE_NAME_MAX]; 6476c52157fSTomohiro Misono static struct btrfs_feature_attr btrfs_feature_attrs[FEAT_MAX][NUM_FEATURE_BITS]; 648e453d989SJeff Mahoney 6496c52157fSTomohiro Misono static const u64 supported_feature_masks[FEAT_MAX] = { 650e453d989SJeff Mahoney [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP, 651e453d989SJeff Mahoney [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP, 652e453d989SJeff Mahoney [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP, 653e453d989SJeff Mahoney }; 654e453d989SJeff Mahoney 655e453d989SJeff Mahoney static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add) 6565ac1d209SJeff Mahoney { 657e453d989SJeff Mahoney int set; 658e453d989SJeff Mahoney 659e453d989SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 660e453d989SJeff Mahoney int i; 661e453d989SJeff Mahoney struct attribute *attrs[2]; 662e453d989SJeff Mahoney struct attribute_group agroup = { 663e453d989SJeff Mahoney .name = "features", 664e453d989SJeff Mahoney .attrs = attrs, 665e453d989SJeff Mahoney }; 666e453d989SJeff Mahoney u64 features = get_features(fs_info, set); 667e453d989SJeff Mahoney features &= ~supported_feature_masks[set]; 668e453d989SJeff Mahoney 669e453d989SJeff Mahoney if (!features) 670e453d989SJeff Mahoney continue; 671e453d989SJeff Mahoney 672e453d989SJeff Mahoney attrs[1] = NULL; 673e453d989SJeff Mahoney for (i = 0; i < NUM_FEATURE_BITS; i++) { 674e453d989SJeff Mahoney struct btrfs_feature_attr *fa; 675e453d989SJeff Mahoney 676e453d989SJeff Mahoney if (!(features & (1ULL << i))) 677e453d989SJeff Mahoney continue; 678e453d989SJeff Mahoney 679e453d989SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 680e453d989SJeff Mahoney attrs[0] = &fa->kobj_attr.attr; 681e453d989SJeff Mahoney if (add) { 682e453d989SJeff Mahoney int ret; 683c1b7e474SAnand Jain ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj, 684e453d989SJeff Mahoney &agroup); 685e453d989SJeff Mahoney if (ret) 686e453d989SJeff Mahoney return ret; 687e453d989SJeff Mahoney } else 688c1b7e474SAnand Jain sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj, 689e453d989SJeff Mahoney &agroup); 690e453d989SJeff Mahoney } 691e453d989SJeff Mahoney 692e453d989SJeff Mahoney } 693e453d989SJeff Mahoney return 0; 694e453d989SJeff Mahoney } 695e453d989SJeff Mahoney 6962e3e1281SAnand Jain static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 697e453d989SJeff Mahoney { 6982e7910d6SAnand Jain if (fs_devs->device_dir_kobj) { 6992e7910d6SAnand Jain kobject_del(fs_devs->device_dir_kobj); 7002e7910d6SAnand Jain kobject_put(fs_devs->device_dir_kobj); 7012e7910d6SAnand Jain fs_devs->device_dir_kobj = NULL; 702aaf13305SAnand Jain } 703aaf13305SAnand Jain 704c1b7e474SAnand Jain if (fs_devs->fsid_kobj.state_initialized) { 705c1b7e474SAnand Jain kobject_del(&fs_devs->fsid_kobj); 706c1b7e474SAnand Jain kobject_put(&fs_devs->fsid_kobj); 7072e7910d6SAnand Jain wait_for_completion(&fs_devs->kobj_unregister); 7085ac1d209SJeff Mahoney } 709f90fc547SAnand Jain } 7105ac1d209SJeff Mahoney 7112e3e1281SAnand Jain /* when fs_devs is NULL it will remove all fsid kobject */ 7121d1c1be3SAnand Jain void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 7132e3e1281SAnand Jain { 7142e3e1281SAnand Jain struct list_head *fs_uuids = btrfs_get_fs_uuids(); 7152e3e1281SAnand Jain 7162e3e1281SAnand Jain if (fs_devs) { 7172e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 7182e3e1281SAnand Jain return; 7192e3e1281SAnand Jain } 7202e3e1281SAnand Jain 721c4babc5eSAnand Jain list_for_each_entry(fs_devs, fs_uuids, fs_list) { 7222e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 7232e3e1281SAnand Jain } 7242e3e1281SAnand Jain } 7252e3e1281SAnand Jain 7266618a59bSAnand Jain void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info) 727e453d989SJeff Mahoney { 7285a13f430SAnand Jain btrfs_reset_fs_info_ptr(fs_info); 7295a13f430SAnand Jain 730e453d989SJeff Mahoney if (fs_info->space_info_kobj) { 731e453d989SJeff Mahoney sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); 732e453d989SJeff Mahoney kobject_del(fs_info->space_info_kobj); 733e453d989SJeff Mahoney kobject_put(fs_info->space_info_kobj); 734e453d989SJeff Mahoney } 735e453d989SJeff Mahoney addrm_unknown_feature_attrs(fs_info, false); 736c1b7e474SAnand Jain sysfs_remove_group(&fs_info->fs_devices->fsid_kobj, &btrfs_feature_attr_group); 737c1b7e474SAnand Jain sysfs_remove_files(&fs_info->fs_devices->fsid_kobj, btrfs_attrs); 73832576040SAnand Jain btrfs_sysfs_rm_device_link(fs_info->fs_devices, NULL); 739e453d989SJeff Mahoney } 740e453d989SJeff Mahoney 741f10152bcSDavid Sterba static const char * const btrfs_feature_set_names[FEAT_MAX] = { 74279da4fa4SJeff Mahoney [FEAT_COMPAT] = "compat", 74379da4fa4SJeff Mahoney [FEAT_COMPAT_RO] = "compat_ro", 74479da4fa4SJeff Mahoney [FEAT_INCOMPAT] = "incompat", 74579da4fa4SJeff Mahoney }; 74679da4fa4SJeff Mahoney 747f10152bcSDavid Sterba const char * const btrfs_feature_set_name(enum btrfs_feature_set set) 748f10152bcSDavid Sterba { 749f10152bcSDavid Sterba return btrfs_feature_set_names[set]; 750f10152bcSDavid Sterba } 751f10152bcSDavid Sterba 7523b02a68aSJeff Mahoney char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) 7533b02a68aSJeff Mahoney { 7543b02a68aSJeff Mahoney size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */ 7553b02a68aSJeff Mahoney int len = 0; 7563b02a68aSJeff Mahoney int i; 7573b02a68aSJeff Mahoney char *str; 7583b02a68aSJeff Mahoney 7593b02a68aSJeff Mahoney str = kmalloc(bufsize, GFP_KERNEL); 7603b02a68aSJeff Mahoney if (!str) 7613b02a68aSJeff Mahoney return str; 7623b02a68aSJeff Mahoney 7633b02a68aSJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 7643b02a68aSJeff Mahoney const char *name; 7653b02a68aSJeff Mahoney 7663b02a68aSJeff Mahoney if (!(flags & (1ULL << i))) 7673b02a68aSJeff Mahoney continue; 7683b02a68aSJeff Mahoney 7693b02a68aSJeff Mahoney name = btrfs_feature_attrs[set][i].kobj_attr.attr.name; 7703b02a68aSJeff Mahoney len += snprintf(str + len, bufsize - len, "%s%s", 7713b02a68aSJeff Mahoney len ? "," : "", name); 7723b02a68aSJeff Mahoney } 7733b02a68aSJeff Mahoney 7743b02a68aSJeff Mahoney return str; 7753b02a68aSJeff Mahoney } 7763b02a68aSJeff Mahoney 77779da4fa4SJeff Mahoney static void init_feature_attrs(void) 77879da4fa4SJeff Mahoney { 77979da4fa4SJeff Mahoney struct btrfs_feature_attr *fa; 78079da4fa4SJeff Mahoney int set, i; 78179da4fa4SJeff Mahoney 78279da4fa4SJeff Mahoney BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names) != 78379da4fa4SJeff Mahoney ARRAY_SIZE(btrfs_feature_attrs)); 78479da4fa4SJeff Mahoney BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names[0]) != 78579da4fa4SJeff Mahoney ARRAY_SIZE(btrfs_feature_attrs[0])); 78679da4fa4SJeff Mahoney 7873b02a68aSJeff Mahoney memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs)); 7883b02a68aSJeff Mahoney memset(btrfs_unknown_feature_names, 0, 7893b02a68aSJeff Mahoney sizeof(btrfs_unknown_feature_names)); 7903b02a68aSJeff Mahoney 79179da4fa4SJeff Mahoney for (i = 0; btrfs_supported_feature_attrs[i]; i++) { 79279da4fa4SJeff Mahoney struct btrfs_feature_attr *sfa; 79379da4fa4SJeff Mahoney struct attribute *a = btrfs_supported_feature_attrs[i]; 7943b02a68aSJeff Mahoney int bit; 79579da4fa4SJeff Mahoney sfa = attr_to_btrfs_feature_attr(a); 7963b02a68aSJeff Mahoney bit = ilog2(sfa->feature_bit); 7973b02a68aSJeff Mahoney fa = &btrfs_feature_attrs[sfa->feature_set][bit]; 79879da4fa4SJeff Mahoney 79979da4fa4SJeff Mahoney fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name; 80079da4fa4SJeff Mahoney } 80179da4fa4SJeff Mahoney 80279da4fa4SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 80379da4fa4SJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 80479da4fa4SJeff Mahoney char *name = btrfs_unknown_feature_names[set][i]; 80579da4fa4SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 80679da4fa4SJeff Mahoney 80779da4fa4SJeff Mahoney if (fa->kobj_attr.attr.name) 80879da4fa4SJeff Mahoney continue; 80979da4fa4SJeff Mahoney 8106c52157fSTomohiro Misono snprintf(name, BTRFS_FEATURE_NAME_MAX, "%s:%u", 81179da4fa4SJeff Mahoney btrfs_feature_set_names[set], i); 81279da4fa4SJeff Mahoney 81379da4fa4SJeff Mahoney fa->kobj_attr.attr.name = name; 81479da4fa4SJeff Mahoney fa->kobj_attr.attr.mode = S_IRUGO; 81579da4fa4SJeff Mahoney fa->feature_set = set; 81679da4fa4SJeff Mahoney fa->feature_bit = 1ULL << i; 81779da4fa4SJeff Mahoney } 81879da4fa4SJeff Mahoney } 81979da4fa4SJeff Mahoney } 82079da4fa4SJeff Mahoney 82132a9991fSDavid Sterba /* 82232a9991fSDavid Sterba * Create a sysfs entry for a given block group type at path 82332a9991fSDavid Sterba * /sys/fs/btrfs/UUID/allocation/data/TYPE 82432a9991fSDavid Sterba */ 82532a9991fSDavid Sterba void btrfs_sysfs_add_block_group_type(struct btrfs_block_group_cache *cache) 82632a9991fSDavid Sterba { 82732a9991fSDavid Sterba struct btrfs_fs_info *fs_info = cache->fs_info; 82832a9991fSDavid Sterba struct btrfs_space_info *space_info = cache->space_info; 82932a9991fSDavid Sterba struct raid_kobject *rkobj; 83032a9991fSDavid Sterba const int index = btrfs_bg_flags_to_raid_index(cache->flags); 83132a9991fSDavid Sterba unsigned int nofs_flag; 83232a9991fSDavid Sterba int ret; 83332a9991fSDavid Sterba 83432a9991fSDavid Sterba /* 83532a9991fSDavid Sterba * Setup a NOFS context because kobject_add(), deep in its call chain, 83632a9991fSDavid Sterba * does GFP_KERNEL allocations, and we are often called in a context 83732a9991fSDavid Sterba * where if reclaim is triggered we can deadlock (we are either holding 83832a9991fSDavid Sterba * a transaction handle or some lock required for a transaction 83932a9991fSDavid Sterba * commit). 84032a9991fSDavid Sterba */ 84132a9991fSDavid Sterba nofs_flag = memalloc_nofs_save(); 84232a9991fSDavid Sterba 84332a9991fSDavid Sterba rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS); 84432a9991fSDavid Sterba if (!rkobj) { 84532a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 84632a9991fSDavid Sterba btrfs_warn(cache->fs_info, 84732a9991fSDavid Sterba "couldn't alloc memory for raid level kobject"); 84832a9991fSDavid Sterba return; 84932a9991fSDavid Sterba } 85032a9991fSDavid Sterba 85132a9991fSDavid Sterba rkobj->flags = cache->flags; 85232a9991fSDavid Sterba kobject_init(&rkobj->kobj, &btrfs_raid_ktype); 85332a9991fSDavid Sterba ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s", 85432a9991fSDavid Sterba btrfs_bg_type_to_raid_name(rkobj->flags)); 85532a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 85632a9991fSDavid Sterba if (ret) { 85732a9991fSDavid Sterba kobject_put(&rkobj->kobj); 85832a9991fSDavid Sterba btrfs_warn(fs_info, 85932a9991fSDavid Sterba "failed to add kobject for block cache, ignoring"); 86032a9991fSDavid Sterba return; 86132a9991fSDavid Sterba } 86232a9991fSDavid Sterba 86332a9991fSDavid Sterba space_info->block_group_kobjs[index] = &rkobj->kobj; 86432a9991fSDavid Sterba } 86532a9991fSDavid Sterba 866b5865babSDavid Sterba /* 867b5865babSDavid Sterba * Remove sysfs directories for all block group types of a given space info and 868b5865babSDavid Sterba * the space info as well 869b5865babSDavid Sterba */ 870b5865babSDavid Sterba void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info) 871b5865babSDavid Sterba { 872b5865babSDavid Sterba int i; 873b5865babSDavid Sterba 874b5865babSDavid Sterba for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { 875b5865babSDavid Sterba struct kobject *kobj; 876b5865babSDavid Sterba 877b5865babSDavid Sterba kobj = space_info->block_group_kobjs[i]; 878b5865babSDavid Sterba space_info->block_group_kobjs[i] = NULL; 879b5865babSDavid Sterba if (kobj) { 880b5865babSDavid Sterba kobject_del(kobj); 881b5865babSDavid Sterba kobject_put(kobj); 882b5865babSDavid Sterba } 883b5865babSDavid Sterba } 884b5865babSDavid Sterba kobject_del(&space_info->kobj); 885b5865babSDavid Sterba kobject_put(&space_info->kobj); 886b5865babSDavid Sterba } 887b5865babSDavid Sterba 888b882327aSDavid Sterba static const char *alloc_name(u64 flags) 889b882327aSDavid Sterba { 890b882327aSDavid Sterba switch (flags) { 891b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA: 892b882327aSDavid Sterba return "mixed"; 893b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA: 894b882327aSDavid Sterba return "metadata"; 895b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_DATA: 896b882327aSDavid Sterba return "data"; 897b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_SYSTEM: 898b882327aSDavid Sterba return "system"; 899b882327aSDavid Sterba default: 900b882327aSDavid Sterba WARN_ON(1); 901b882327aSDavid Sterba return "invalid-combination"; 902b882327aSDavid Sterba }; 903b882327aSDavid Sterba } 904b882327aSDavid Sterba 905b882327aSDavid Sterba /* 906b882327aSDavid Sterba * Create a sysfs entry for a space info type at path 907b882327aSDavid Sterba * /sys/fs/btrfs/UUID/allocation/TYPE 908b882327aSDavid Sterba */ 909b882327aSDavid Sterba int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info, 910b882327aSDavid Sterba struct btrfs_space_info *space_info) 911b882327aSDavid Sterba { 912b882327aSDavid Sterba int ret; 913b882327aSDavid Sterba 914b882327aSDavid Sterba ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, 915b882327aSDavid Sterba fs_info->space_info_kobj, "%s", 916b882327aSDavid Sterba alloc_name(space_info->flags)); 917b882327aSDavid Sterba if (ret) { 918b882327aSDavid Sterba kobject_put(&space_info->kobj); 919b882327aSDavid Sterba return ret; 920b882327aSDavid Sterba } 921b882327aSDavid Sterba 922b882327aSDavid Sterba return 0; 923b882327aSDavid Sterba } 924b882327aSDavid Sterba 925e7e1aa9cSAnand Jain /* when one_device is NULL, it removes all device links */ 926e7e1aa9cSAnand Jain 92732576040SAnand Jain int btrfs_sysfs_rm_device_link(struct btrfs_fs_devices *fs_devices, 92899994cdeSAnand Jain struct btrfs_device *one_device) 92999994cdeSAnand Jain { 93099994cdeSAnand Jain struct hd_struct *disk; 93199994cdeSAnand Jain struct kobject *disk_kobj; 93299994cdeSAnand Jain 9336c14a164SAnand Jain if (!fs_devices->device_dir_kobj) 93499994cdeSAnand Jain return -EINVAL; 93599994cdeSAnand Jain 93687fa3bb0SLiu Bo if (one_device && one_device->bdev) { 93799994cdeSAnand Jain disk = one_device->bdev->bd_part; 93899994cdeSAnand Jain disk_kobj = &part_to_dev(disk)->kobj; 93999994cdeSAnand Jain 9406c14a164SAnand Jain sysfs_remove_link(fs_devices->device_dir_kobj, 94199994cdeSAnand Jain disk_kobj->name); 94299994cdeSAnand Jain } 94399994cdeSAnand Jain 944e7e1aa9cSAnand Jain if (one_device) 945e7e1aa9cSAnand Jain return 0; 946e7e1aa9cSAnand Jain 947e7e1aa9cSAnand Jain list_for_each_entry(one_device, 9486c14a164SAnand Jain &fs_devices->devices, dev_list) { 949e7e1aa9cSAnand Jain if (!one_device->bdev) 950e7e1aa9cSAnand Jain continue; 951e7e1aa9cSAnand Jain disk = one_device->bdev->bd_part; 952e7e1aa9cSAnand Jain disk_kobj = &part_to_dev(disk)->kobj; 953e7e1aa9cSAnand Jain 9546c14a164SAnand Jain sysfs_remove_link(fs_devices->device_dir_kobj, 955e7e1aa9cSAnand Jain disk_kobj->name); 956e7e1aa9cSAnand Jain } 957e7e1aa9cSAnand Jain 95899994cdeSAnand Jain return 0; 95999994cdeSAnand Jain } 96099994cdeSAnand Jain 9612e7910d6SAnand Jain int btrfs_sysfs_add_device(struct btrfs_fs_devices *fs_devs) 96200c921c2SAnand Jain { 9632e7910d6SAnand Jain if (!fs_devs->device_dir_kobj) 9642e7910d6SAnand Jain fs_devs->device_dir_kobj = kobject_create_and_add("devices", 965c1b7e474SAnand Jain &fs_devs->fsid_kobj); 96600c921c2SAnand Jain 9672e7910d6SAnand Jain if (!fs_devs->device_dir_kobj) 96800c921c2SAnand Jain return -ENOMEM; 96900c921c2SAnand Jain 97000c921c2SAnand Jain return 0; 97100c921c2SAnand Jain } 97200c921c2SAnand Jain 973e3bd6973SAnand Jain int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices, 9740d39376aSAnand Jain struct btrfs_device *one_device) 97529e5be24SJeff Mahoney { 97629e5be24SJeff Mahoney int error = 0; 97729e5be24SJeff Mahoney struct btrfs_device *dev; 97829e5be24SJeff Mahoney 97929e5be24SJeff Mahoney list_for_each_entry(dev, &fs_devices->devices, dev_list) { 980f085381eSAnand Jain struct hd_struct *disk; 981f085381eSAnand Jain struct kobject *disk_kobj; 982f085381eSAnand Jain 983f085381eSAnand Jain if (!dev->bdev) 984f085381eSAnand Jain continue; 985f085381eSAnand Jain 9860d39376aSAnand Jain if (one_device && one_device != dev) 9870d39376aSAnand Jain continue; 9880d39376aSAnand Jain 989f085381eSAnand Jain disk = dev->bdev->bd_part; 990f085381eSAnand Jain disk_kobj = &part_to_dev(disk)->kobj; 99129e5be24SJeff Mahoney 9922e7910d6SAnand Jain error = sysfs_create_link(fs_devices->device_dir_kobj, 99329e5be24SJeff Mahoney disk_kobj, disk_kobj->name); 99429e5be24SJeff Mahoney if (error) 99529e5be24SJeff Mahoney break; 99629e5be24SJeff Mahoney } 99729e5be24SJeff Mahoney 99829e5be24SJeff Mahoney return error; 99929e5be24SJeff Mahoney } 100029e5be24SJeff Mahoney 10015b28692eSDavid Sterba void btrfs_kobject_uevent(struct block_device *bdev, enum kobject_action action) 10025b28692eSDavid Sterba { 10035b28692eSDavid Sterba int ret; 10045b28692eSDavid Sterba 10055b28692eSDavid Sterba ret = kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, action); 10065b28692eSDavid Sterba if (ret) 10075b28692eSDavid Sterba pr_warn("BTRFS: Sending event '%d' to kobject: '%s' (%p): failed\n", 10085b28692eSDavid Sterba action, kobject_name(&disk_to_dev(bdev->bd_disk)->kobj), 10095b28692eSDavid Sterba &disk_to_dev(bdev->bd_disk)->kobj); 10105b28692eSDavid Sterba } 10115b28692eSDavid Sterba 1012f93c3997SDavid Sterba void btrfs_sysfs_update_sprout_fsid(struct btrfs_fs_devices *fs_devices, 1013f93c3997SDavid Sterba const u8 *fsid) 1014f93c3997SDavid Sterba { 1015f93c3997SDavid Sterba char fsid_buf[BTRFS_UUID_UNPARSED_SIZE]; 1016f93c3997SDavid Sterba 1017f93c3997SDavid Sterba /* 1018f93c3997SDavid Sterba * Sprouting changes fsid of the mounted filesystem, rename the fsid 1019f93c3997SDavid Sterba * directory 1020f93c3997SDavid Sterba */ 1021f93c3997SDavid Sterba snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", fsid); 1022f93c3997SDavid Sterba if (kobject_rename(&fs_devices->fsid_kobj, fsid_buf)) 1023f93c3997SDavid Sterba btrfs_warn(fs_devices->fs_info, 1024f93c3997SDavid Sterba "sysfs: failed to create fsid for sprout"); 1025f93c3997SDavid Sterba } 1026f93c3997SDavid Sterba 1027510d7360SJeff Mahoney /* /sys/fs/btrfs/ entry */ 1028510d7360SJeff Mahoney static struct kset *btrfs_kset; 1029510d7360SJeff Mahoney 103072059215SAnand Jain /* 103172059215SAnand Jain * Can be called by the device discovery thread. 103272059215SAnand Jain * And parent can be specified for seed device 103372059215SAnand Jain */ 10340c10e2d4SAnand Jain int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs, 103572059215SAnand Jain struct kobject *parent) 10365ac1d209SJeff Mahoney { 10375ac1d209SJeff Mahoney int error; 10385ac1d209SJeff Mahoney 10392e7910d6SAnand Jain init_completion(&fs_devs->kobj_unregister); 1040c1b7e474SAnand Jain fs_devs->fsid_kobj.kset = btrfs_kset; 1041c1b7e474SAnand Jain error = kobject_init_and_add(&fs_devs->fsid_kobj, 104224bd69cbSAnand Jain &btrfs_ktype, parent, "%pU", fs_devs->fsid); 1043e3277335STobin C. Harding if (error) { 1044e3277335STobin C. Harding kobject_put(&fs_devs->fsid_kobj); 104572059215SAnand Jain return error; 104672059215SAnand Jain } 104772059215SAnand Jain 1048e3277335STobin C. Harding return 0; 1049e3277335STobin C. Harding } 1050e3277335STobin C. Harding 105196f3136eSAnand Jain int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info) 105272059215SAnand Jain { 105372059215SAnand Jain int error; 10542e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = fs_info->fs_devices; 1055c1b7e474SAnand Jain struct kobject *fsid_kobj = &fs_devs->fsid_kobj; 105672059215SAnand Jain 10575a13f430SAnand Jain btrfs_set_fs_info_ptr(fs_info); 10585a13f430SAnand Jain 1059e3bd6973SAnand Jain error = btrfs_sysfs_add_device_link(fs_devs, NULL); 1060e453d989SJeff Mahoney if (error) 1061e453d989SJeff Mahoney return error; 1062510d7360SJeff Mahoney 1063c1b7e474SAnand Jain error = sysfs_create_files(fsid_kobj, btrfs_attrs); 1064e453d989SJeff Mahoney if (error) { 106532576040SAnand Jain btrfs_sysfs_rm_device_link(fs_devs, NULL); 1066e453d989SJeff Mahoney return error; 1067e453d989SJeff Mahoney } 106879da4fa4SJeff Mahoney 1069c1b7e474SAnand Jain error = sysfs_create_group(fsid_kobj, 10700dd2906fSAnand Jain &btrfs_feature_attr_group); 10710dd2906fSAnand Jain if (error) 10720dd2906fSAnand Jain goto failure; 10730dd2906fSAnand Jain 10746e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 10756e369febSDavid Sterba error = sysfs_create_group(fsid_kobj, 10766e369febSDavid Sterba &btrfs_debug_feature_attr_group); 10776e369febSDavid Sterba if (error) 10786e369febSDavid Sterba goto failure; 10796e369febSDavid Sterba #endif 10806e369febSDavid Sterba 1081e453d989SJeff Mahoney error = addrm_unknown_feature_attrs(fs_info, true); 108279da4fa4SJeff Mahoney if (error) 108379da4fa4SJeff Mahoney goto failure; 108479da4fa4SJeff Mahoney 10856ab0a202SJeff Mahoney fs_info->space_info_kobj = kobject_create_and_add("allocation", 1086c1b7e474SAnand Jain fsid_kobj); 10876ab0a202SJeff Mahoney if (!fs_info->space_info_kobj) { 10886ab0a202SJeff Mahoney error = -ENOMEM; 10896ab0a202SJeff Mahoney goto failure; 10906ab0a202SJeff Mahoney } 10916ab0a202SJeff Mahoney 10926ab0a202SJeff Mahoney error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs); 10936ab0a202SJeff Mahoney if (error) 10946ab0a202SJeff Mahoney goto failure; 10956ab0a202SJeff Mahoney 109679da4fa4SJeff Mahoney return 0; 109779da4fa4SJeff Mahoney failure: 10986618a59bSAnand Jain btrfs_sysfs_remove_mounted(fs_info); 10995ac1d209SJeff Mahoney return error; 11005ac1d209SJeff Mahoney } 11015ac1d209SJeff Mahoney 1102444e7516SDavid Sterba 1103444e7516SDavid Sterba /* 1104444e7516SDavid Sterba * Change per-fs features in /sys/fs/btrfs/UUID/features to match current 1105444e7516SDavid Sterba * values in superblock. Call after any changes to incompat/compat_ro flags 1106444e7516SDavid Sterba */ 1107444e7516SDavid Sterba void btrfs_sysfs_feature_update(struct btrfs_fs_info *fs_info, 1108444e7516SDavid Sterba u64 bit, enum btrfs_feature_set set) 1109444e7516SDavid Sterba { 1110444e7516SDavid Sterba struct btrfs_fs_devices *fs_devs; 1111444e7516SDavid Sterba struct kobject *fsid_kobj; 1112444e7516SDavid Sterba u64 features; 1113444e7516SDavid Sterba int ret; 1114444e7516SDavid Sterba 1115444e7516SDavid Sterba if (!fs_info) 1116444e7516SDavid Sterba return; 1117444e7516SDavid Sterba 1118444e7516SDavid Sterba features = get_features(fs_info, set); 1119444e7516SDavid Sterba ASSERT(bit & supported_feature_masks[set]); 1120444e7516SDavid Sterba 1121444e7516SDavid Sterba fs_devs = fs_info->fs_devices; 1122444e7516SDavid Sterba fsid_kobj = &fs_devs->fsid_kobj; 1123444e7516SDavid Sterba 1124bf609206SDavid Sterba if (!fsid_kobj->state_initialized) 1125bf609206SDavid Sterba return; 1126bf609206SDavid Sterba 1127444e7516SDavid Sterba /* 1128444e7516SDavid Sterba * FIXME: this is too heavy to update just one value, ideally we'd like 1129444e7516SDavid Sterba * to use sysfs_update_group but some refactoring is needed first. 1130444e7516SDavid Sterba */ 1131444e7516SDavid Sterba sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 1132444e7516SDavid Sterba ret = sysfs_create_group(fsid_kobj, &btrfs_feature_attr_group); 1133444e7516SDavid Sterba } 1134444e7516SDavid Sterba 1135f5c29bd9SLiu Bo int __init btrfs_init_sysfs(void) 113658176a96SJosef Bacik { 1137079b72bcSJeff Mahoney int ret; 11381bae3098SDavid Sterba 1139e3fe4e71SGreg KH btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); 1140e3fe4e71SGreg KH if (!btrfs_kset) 1141e3fe4e71SGreg KH return -ENOMEM; 1142079b72bcSJeff Mahoney 11431bae3098SDavid Sterba init_feature_attrs(); 11441bae3098SDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 1145001a648dSFilipe Manana if (ret) 1146001a648dSFilipe Manana goto out2; 1147f902bd3aSMisono Tomohiro ret = sysfs_merge_group(&btrfs_kset->kobj, 1148f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 1149f902bd3aSMisono Tomohiro if (ret) 1150f902bd3aSMisono Tomohiro goto out_remove_group; 1151001a648dSFilipe Manana 11526e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 11536e369febSDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 11546e369febSDavid Sterba if (ret) 11556e369febSDavid Sterba goto out2; 11566e369febSDavid Sterba #endif 11576e369febSDavid Sterba 1158001a648dSFilipe Manana return 0; 1159f902bd3aSMisono Tomohiro 1160f902bd3aSMisono Tomohiro out_remove_group: 1161f902bd3aSMisono Tomohiro sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 1162001a648dSFilipe Manana out2: 1163001a648dSFilipe Manana kset_unregister(btrfs_kset); 11641bae3098SDavid Sterba 11651bae3098SDavid Sterba return ret; 116658176a96SJosef Bacik } 116758176a96SJosef Bacik 1168e67c718bSDavid Sterba void __cold btrfs_exit_sysfs(void) 116958176a96SJosef Bacik { 1170f902bd3aSMisono Tomohiro sysfs_unmerge_group(&btrfs_kset->kobj, 1171f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 1172079b72bcSJeff Mahoney sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 1173e3fe4e71SGreg KH kset_unregister(btrfs_kset); 117458176a96SJosef Bacik } 117555d47414SChris Mason 1176