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> 1241e6d2a8SJohannes Thumshirn #include <crypto/hash.h> 1358176a96SJosef Bacik 14bae45de0SChris Mason #include "ctree.h" 15dfb79ddbSDennis Zhou #include "discard.h" 16bae45de0SChris Mason #include "disk-io.h" 177573df55SOmar Sandoval #include "send.h" 18bae45de0SChris Mason #include "transaction.h" 19079b72bcSJeff Mahoney #include "sysfs.h" 2029e5be24SJeff Mahoney #include "volumes.h" 218719aaaeSJosef Bacik #include "space-info.h" 22aac0023cSJosef Bacik #include "block-group.h" 2349e5fb46SQu Wenruo #include "qgroup.h" 24*19fc516aSStefan Roesch #include "misc.h" 25079b72bcSJeff Mahoney 26e7849e33SAnand Jain /* 27e7849e33SAnand Jain * Structure name Path 28e7849e33SAnand Jain * -------------------------------------------------------------------------- 29e7849e33SAnand Jain * btrfs_supported_static_feature_attrs /sys/fs/btrfs/features 30e7849e33SAnand Jain * btrfs_supported_feature_attrs /sys/fs/btrfs/features and 31e7849e33SAnand Jain * /sys/fs/btrfs/<uuid>/features 32e7849e33SAnand Jain * btrfs_attrs /sys/fs/btrfs/<uuid> 33e7849e33SAnand Jain * devid_attrs /sys/fs/btrfs/<uuid>/devinfo/<devid> 34e7849e33SAnand Jain * allocation_attrs /sys/fs/btrfs/<uuid>/allocation 35e7849e33SAnand Jain * qgroup_attrs /sys/fs/btrfs/<uuid>/qgroups/<level>_<qgroupid> 36e7849e33SAnand Jain * space_info_attrs /sys/fs/btrfs/<uuid>/allocation/<bg-type> 37e7849e33SAnand Jain * raid_attrs /sys/fs/btrfs/<uuid>/allocation/<bg-type>/<bg-profile> 38e7849e33SAnand Jain * 39e7849e33SAnand Jain * When built with BTRFS_CONFIG_DEBUG: 40e7849e33SAnand Jain * 41e7849e33SAnand Jain * btrfs_debug_feature_attrs /sys/fs/btrfs/debug 42e7849e33SAnand Jain * btrfs_debug_mount_attrs /sys/fs/btrfs/<uuid>/debug 43e7849e33SAnand Jain * discard_debug_attrs /sys/fs/btrfs/<uuid>/debug/discard 44e7849e33SAnand Jain */ 45e7849e33SAnand Jain 469188db61SDavid Sterba struct btrfs_feature_attr { 479188db61SDavid Sterba struct kobj_attribute kobj_attr; 489188db61SDavid Sterba enum btrfs_feature_set feature_set; 499188db61SDavid Sterba u64 feature_bit; 509188db61SDavid Sterba }; 519188db61SDavid Sterba 529188db61SDavid Sterba /* For raid type sysfs entries */ 539188db61SDavid Sterba struct raid_kobject { 549188db61SDavid Sterba u64 flags; 559188db61SDavid Sterba struct kobject kobj; 569188db61SDavid Sterba }; 579188db61SDavid Sterba 589188db61SDavid Sterba #define __INIT_KOBJ_ATTR(_name, _mode, _show, _store) \ 599188db61SDavid Sterba { \ 609188db61SDavid Sterba .attr = { .name = __stringify(_name), .mode = _mode }, \ 619188db61SDavid Sterba .show = _show, \ 629188db61SDavid Sterba .store = _store, \ 639188db61SDavid Sterba } 649188db61SDavid Sterba 659188db61SDavid Sterba #define BTRFS_ATTR_RW(_prefix, _name, _show, _store) \ 669188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 679188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0644, _show, _store) 689188db61SDavid Sterba 699188db61SDavid Sterba #define BTRFS_ATTR(_prefix, _name, _show) \ 709188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 719188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0444, _show, NULL) 729188db61SDavid Sterba 739188db61SDavid Sterba #define BTRFS_ATTR_PTR(_prefix, _name) \ 749188db61SDavid Sterba (&btrfs_attr_##_prefix##_##_name.attr) 759188db61SDavid Sterba 769188db61SDavid Sterba #define BTRFS_FEAT_ATTR(_name, _feature_set, _feature_prefix, _feature_bit) \ 779188db61SDavid Sterba static struct btrfs_feature_attr btrfs_attr_features_##_name = { \ 789188db61SDavid Sterba .kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO, \ 799188db61SDavid Sterba btrfs_feature_attr_show, \ 809188db61SDavid Sterba btrfs_feature_attr_store), \ 819188db61SDavid Sterba .feature_set = _feature_set, \ 829188db61SDavid Sterba .feature_bit = _feature_prefix ##_## _feature_bit, \ 839188db61SDavid Sterba } 849188db61SDavid Sterba #define BTRFS_FEAT_ATTR_PTR(_name) \ 859188db61SDavid Sterba (&btrfs_attr_features_##_name.kobj_attr.attr) 869188db61SDavid Sterba 879188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT(name, feature) \ 889188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT, BTRFS_FEATURE_COMPAT, feature) 899188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT_RO(name, feature) \ 909188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT_RO, BTRFS_FEATURE_COMPAT_RO, feature) 919188db61SDavid Sterba #define BTRFS_FEAT_ATTR_INCOMPAT(name, feature) \ 929188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_INCOMPAT, BTRFS_FEATURE_INCOMPAT, feature) 939188db61SDavid Sterba 94510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); 952e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj); 96*19fc516aSStefan Roesch static struct kobject *get_btrfs_kobj(struct kobject *kobj); 975ac1d209SJeff Mahoney 988f52316cSDavid Sterba static struct btrfs_feature_attr *to_btrfs_feature_attr(struct kobj_attribute *a) 998f52316cSDavid Sterba { 1008f52316cSDavid Sterba return container_of(a, struct btrfs_feature_attr, kobj_attr); 1018f52316cSDavid Sterba } 1028f52316cSDavid Sterba 1038f52316cSDavid Sterba static struct kobj_attribute *attr_to_btrfs_attr(struct attribute *attr) 1048f52316cSDavid Sterba { 1058f52316cSDavid Sterba return container_of(attr, struct kobj_attribute, attr); 1068f52316cSDavid Sterba } 1078f52316cSDavid Sterba 1088f52316cSDavid Sterba static struct btrfs_feature_attr *attr_to_btrfs_feature_attr( 1098f52316cSDavid Sterba struct attribute *attr) 1108f52316cSDavid Sterba { 1118f52316cSDavid Sterba return to_btrfs_feature_attr(attr_to_btrfs_attr(attr)); 1128f52316cSDavid Sterba } 1138f52316cSDavid Sterba 114510d7360SJeff Mahoney static u64 get_features(struct btrfs_fs_info *fs_info, 115510d7360SJeff Mahoney enum btrfs_feature_set set) 1165ac1d209SJeff Mahoney { 117510d7360SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 118510d7360SJeff Mahoney if (set == FEAT_COMPAT) 119510d7360SJeff Mahoney return btrfs_super_compat_flags(disk_super); 120510d7360SJeff Mahoney else if (set == FEAT_COMPAT_RO) 121510d7360SJeff Mahoney return btrfs_super_compat_ro_flags(disk_super); 122510d7360SJeff Mahoney else 123510d7360SJeff Mahoney return btrfs_super_incompat_flags(disk_super); 1245ac1d209SJeff Mahoney } 1255ac1d209SJeff Mahoney 126ba631941SJeff Mahoney static void set_features(struct btrfs_fs_info *fs_info, 127ba631941SJeff Mahoney enum btrfs_feature_set set, u64 features) 128ba631941SJeff Mahoney { 129ba631941SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 130ba631941SJeff Mahoney if (set == FEAT_COMPAT) 131ba631941SJeff Mahoney btrfs_set_super_compat_flags(disk_super, features); 132ba631941SJeff Mahoney else if (set == FEAT_COMPAT_RO) 133ba631941SJeff Mahoney btrfs_set_super_compat_ro_flags(disk_super, features); 134ba631941SJeff Mahoney else 135ba631941SJeff Mahoney btrfs_set_super_incompat_flags(disk_super, features); 136ba631941SJeff Mahoney } 137ba631941SJeff Mahoney 138ba631941SJeff Mahoney static int can_modify_feature(struct btrfs_feature_attr *fa) 139ba631941SJeff Mahoney { 140ba631941SJeff Mahoney int val = 0; 141ba631941SJeff Mahoney u64 set, clear; 142ba631941SJeff Mahoney switch (fa->feature_set) { 143ba631941SJeff Mahoney case FEAT_COMPAT: 144ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 145ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 146ba631941SJeff Mahoney break; 147ba631941SJeff Mahoney case FEAT_COMPAT_RO: 148ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 149ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 150ba631941SJeff Mahoney break; 151ba631941SJeff Mahoney case FEAT_INCOMPAT: 152ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 153ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 154ba631941SJeff Mahoney break; 155ba631941SJeff Mahoney default: 15662e85577SJeff Mahoney pr_warn("btrfs: sysfs: unknown feature set %d\n", 157cc37bb04SDavid Sterba fa->feature_set); 158cc37bb04SDavid Sterba return 0; 159ba631941SJeff Mahoney } 160ba631941SJeff Mahoney 161ba631941SJeff Mahoney if (set & fa->feature_bit) 162ba631941SJeff Mahoney val |= 1; 163ba631941SJeff Mahoney if (clear & fa->feature_bit) 164ba631941SJeff Mahoney val |= 2; 165ba631941SJeff Mahoney 166ba631941SJeff Mahoney return val; 167ba631941SJeff Mahoney } 168ba631941SJeff Mahoney 169079b72bcSJeff Mahoney static ssize_t btrfs_feature_attr_show(struct kobject *kobj, 170079b72bcSJeff Mahoney struct kobj_attribute *a, char *buf) 171079b72bcSJeff Mahoney { 172510d7360SJeff Mahoney int val = 0; 173510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 174510d7360SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 175ba631941SJeff Mahoney if (fs_info) { 176510d7360SJeff Mahoney u64 features = get_features(fs_info, fa->feature_set); 177510d7360SJeff Mahoney if (features & fa->feature_bit) 178510d7360SJeff Mahoney val = 1; 179ba631941SJeff Mahoney } else 180ba631941SJeff Mahoney val = can_modify_feature(fa); 181510d7360SJeff Mahoney 182020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 183510d7360SJeff Mahoney } 184510d7360SJeff Mahoney 185ba631941SJeff Mahoney static ssize_t btrfs_feature_attr_store(struct kobject *kobj, 186ba631941SJeff Mahoney struct kobj_attribute *a, 187ba631941SJeff Mahoney const char *buf, size_t count) 188ba631941SJeff Mahoney { 189ba631941SJeff Mahoney struct btrfs_fs_info *fs_info; 190ba631941SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 191ba631941SJeff Mahoney u64 features, set, clear; 192ba631941SJeff Mahoney unsigned long val; 193ba631941SJeff Mahoney int ret; 194ba631941SJeff Mahoney 195ba631941SJeff Mahoney fs_info = to_fs_info(kobj); 196ba631941SJeff Mahoney if (!fs_info) 197ba631941SJeff Mahoney return -EPERM; 198ba631941SJeff Mahoney 199bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 200ee611138SDavid Sterba return -EROFS; 201ee611138SDavid Sterba 202ba631941SJeff Mahoney ret = kstrtoul(skip_spaces(buf), 0, &val); 203ba631941SJeff Mahoney if (ret) 204ba631941SJeff Mahoney return ret; 205ba631941SJeff Mahoney 206ba631941SJeff Mahoney if (fa->feature_set == FEAT_COMPAT) { 207ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 208ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 209ba631941SJeff Mahoney } else if (fa->feature_set == FEAT_COMPAT_RO) { 210ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 211ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 212ba631941SJeff Mahoney } else { 213ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 214ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 215ba631941SJeff Mahoney } 216ba631941SJeff Mahoney 217ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 218ba631941SJeff Mahoney 219ba631941SJeff Mahoney /* Nothing to do */ 220ba631941SJeff Mahoney if ((val && (features & fa->feature_bit)) || 221ba631941SJeff Mahoney (!val && !(features & fa->feature_bit))) 222ba631941SJeff Mahoney return count; 223ba631941SJeff Mahoney 224ba631941SJeff Mahoney if ((val && !(set & fa->feature_bit)) || 225ba631941SJeff Mahoney (!val && !(clear & fa->feature_bit))) { 226ba631941SJeff Mahoney btrfs_info(fs_info, 227ba631941SJeff Mahoney "%sabling feature %s on mounted fs is not supported.", 228ba631941SJeff Mahoney val ? "En" : "Dis", fa->kobj_attr.attr.name); 229ba631941SJeff Mahoney return -EPERM; 230ba631941SJeff Mahoney } 231ba631941SJeff Mahoney 232ba631941SJeff Mahoney btrfs_info(fs_info, "%s %s feature flag", 233ba631941SJeff Mahoney val ? "Setting" : "Clearing", fa->kobj_attr.attr.name); 234ba631941SJeff Mahoney 235ba631941SJeff Mahoney spin_lock(&fs_info->super_lock); 236ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 237ba631941SJeff Mahoney if (val) 238ba631941SJeff Mahoney features |= fa->feature_bit; 239ba631941SJeff Mahoney else 240ba631941SJeff Mahoney features &= ~fa->feature_bit; 241ba631941SJeff Mahoney set_features(fs_info, fa->feature_set, features); 242ba631941SJeff Mahoney spin_unlock(&fs_info->super_lock); 243ba631941SJeff Mahoney 2440eae2747SDavid Sterba /* 2450eae2747SDavid Sterba * We don't want to do full transaction commit from inside sysfs 2460eae2747SDavid Sterba */ 2470eae2747SDavid Sterba btrfs_set_pending(fs_info, COMMIT); 2480eae2747SDavid Sterba wake_up_process(fs_info->transaction_kthread); 249ba631941SJeff Mahoney 250ba631941SJeff Mahoney return count; 251ba631941SJeff Mahoney } 252ba631941SJeff Mahoney 253510d7360SJeff Mahoney static umode_t btrfs_feature_visible(struct kobject *kobj, 254510d7360SJeff Mahoney struct attribute *attr, int unused) 255510d7360SJeff Mahoney { 256510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 257510d7360SJeff Mahoney umode_t mode = attr->mode; 258510d7360SJeff Mahoney 259510d7360SJeff Mahoney if (fs_info) { 260510d7360SJeff Mahoney struct btrfs_feature_attr *fa; 261510d7360SJeff Mahoney u64 features; 262510d7360SJeff Mahoney 263510d7360SJeff Mahoney fa = attr_to_btrfs_feature_attr(attr); 264510d7360SJeff Mahoney features = get_features(fs_info, fa->feature_set); 265510d7360SJeff Mahoney 266ba631941SJeff Mahoney if (can_modify_feature(fa)) 267ba631941SJeff Mahoney mode |= S_IWUSR; 268ba631941SJeff Mahoney else if (!(features & fa->feature_bit)) 269510d7360SJeff Mahoney mode = 0; 270510d7360SJeff Mahoney } 271510d7360SJeff Mahoney 272510d7360SJeff Mahoney return mode; 273079b72bcSJeff Mahoney } 274079b72bcSJeff Mahoney 275079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_backref, MIXED_BACKREF); 276079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL); 277079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS); 278079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO); 2795c1aab1dSNick Terrell BTRFS_FEAT_ATTR_INCOMPAT(compress_zstd, COMPRESS_ZSTD); 280079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(big_metadata, BIG_METADATA); 281079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF); 282079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56); 283079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA); 284c736c095SDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES); 28556f20f40SNikolay Borisov BTRFS_FEAT_ATTR_INCOMPAT(metadata_uuid, METADATA_UUID); 2863b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE); 287cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(raid1c34, RAID1C34); 2887b3d5a90SNaohiro Aota #ifdef CONFIG_BTRFS_DEBUG 2892c7d2a23SJosef Bacik /* Remove once support for zoned allocation is feature complete */ 2907b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_INCOMPAT(zoned, ZONED); 2912c7d2a23SJosef Bacik /* Remove once support for extent tree v2 is feature complete */ 2922c7d2a23SJosef Bacik BTRFS_FEAT_ATTR_INCOMPAT(extent_tree_v2, EXTENT_TREE_V2); 2937b3d5a90SNaohiro Aota #endif 29414605409SBoris Burkov #ifdef CONFIG_FS_VERITY 29514605409SBoris Burkov BTRFS_FEAT_ATTR_COMPAT_RO(verity, VERITY); 29614605409SBoris Burkov #endif 297079b72bcSJeff Mahoney 298e7849e33SAnand Jain /* 299e7849e33SAnand Jain * Features which depend on feature bits and may differ between each fs. 300e7849e33SAnand Jain * 301143823cfSDavid Sterba * /sys/fs/btrfs/features - all available features implemented by this version 302e7849e33SAnand Jain * /sys/fs/btrfs/UUID/features - features of the fs which are enabled or 303e7849e33SAnand Jain * can be changed on a mounted filesystem. 304e7849e33SAnand Jain */ 305079b72bcSJeff Mahoney static struct attribute *btrfs_supported_feature_attrs[] = { 306079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_backref), 307079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(default_subvol), 308079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_groups), 309079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(compress_lzo), 3105c1aab1dSNick Terrell BTRFS_FEAT_ATTR_PTR(compress_zstd), 311079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(big_metadata), 312079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(extended_iref), 313079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(raid56), 314079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(skinny_metadata), 315c736c095SDavid Sterba BTRFS_FEAT_ATTR_PTR(no_holes), 31656f20f40SNikolay Borisov BTRFS_FEAT_ATTR_PTR(metadata_uuid), 3173b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_PTR(free_space_tree), 318cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_PTR(raid1c34), 3197b3d5a90SNaohiro Aota #ifdef CONFIG_BTRFS_DEBUG 3207b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_PTR(zoned), 3212c7d2a23SJosef Bacik BTRFS_FEAT_ATTR_PTR(extent_tree_v2), 3227b3d5a90SNaohiro Aota #endif 32314605409SBoris Burkov #ifdef CONFIG_FS_VERITY 32414605409SBoris Burkov BTRFS_FEAT_ATTR_PTR(verity), 32514605409SBoris Burkov #endif 326079b72bcSJeff Mahoney NULL 327079b72bcSJeff Mahoney }; 328079b72bcSJeff Mahoney 329079b72bcSJeff Mahoney static const struct attribute_group btrfs_feature_attr_group = { 330079b72bcSJeff Mahoney .name = "features", 331510d7360SJeff Mahoney .is_visible = btrfs_feature_visible, 332079b72bcSJeff Mahoney .attrs = btrfs_supported_feature_attrs, 333079b72bcSJeff Mahoney }; 33458176a96SJosef Bacik 335f902bd3aSMisono Tomohiro static ssize_t rmdir_subvol_show(struct kobject *kobj, 336f902bd3aSMisono Tomohiro struct kobj_attribute *ka, char *buf) 337f902bd3aSMisono Tomohiro { 338020e5277SAnand Jain return sysfs_emit(buf, "0\n"); 339f902bd3aSMisono Tomohiro } 340f902bd3aSMisono Tomohiro BTRFS_ATTR(static_feature, rmdir_subvol, rmdir_subvol_show); 341f902bd3aSMisono Tomohiro 342f7cea56cSDavid Sterba static ssize_t supported_checksums_show(struct kobject *kobj, 343f7cea56cSDavid Sterba struct kobj_attribute *a, char *buf) 344f7cea56cSDavid Sterba { 345f7cea56cSDavid Sterba ssize_t ret = 0; 346f7cea56cSDavid Sterba int i; 347f7cea56cSDavid Sterba 348f7cea56cSDavid Sterba for (i = 0; i < btrfs_get_num_csums(); i++) { 349f7cea56cSDavid Sterba /* 350f7cea56cSDavid Sterba * This "trick" only works as long as 'enum btrfs_csum_type' has 351f7cea56cSDavid Sterba * no holes in it 352f7cea56cSDavid Sterba */ 353020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i == 0 ? "" : " "), 354020e5277SAnand Jain btrfs_super_csum_name(i)); 355f7cea56cSDavid Sterba 356f7cea56cSDavid Sterba } 357f7cea56cSDavid Sterba 358020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 359f7cea56cSDavid Sterba return ret; 360f7cea56cSDavid Sterba } 361f7cea56cSDavid Sterba BTRFS_ATTR(static_feature, supported_checksums, supported_checksums_show); 362f7cea56cSDavid Sterba 3637573df55SOmar Sandoval static ssize_t send_stream_version_show(struct kobject *kobj, 3647573df55SOmar Sandoval struct kobj_attribute *ka, char *buf) 3657573df55SOmar Sandoval { 366020e5277SAnand Jain return sysfs_emit(buf, "%d\n", BTRFS_SEND_STREAM_VERSION); 3677573df55SOmar Sandoval } 3687573df55SOmar Sandoval BTRFS_ATTR(static_feature, send_stream_version, send_stream_version_show); 3697573df55SOmar Sandoval 370ceafe3ccSJosef Bacik static const char *rescue_opts[] = { 371ceafe3ccSJosef Bacik "usebackuproot", 372ceafe3ccSJosef Bacik "nologreplay", 37342437a63SJosef Bacik "ignorebadroots", 374882dbe0cSJosef Bacik "ignoredatacsums", 3759037d3cbSJosef Bacik "all", 376ceafe3ccSJosef Bacik }; 377ceafe3ccSJosef Bacik 378ceafe3ccSJosef Bacik static ssize_t supported_rescue_options_show(struct kobject *kobj, 379ceafe3ccSJosef Bacik struct kobj_attribute *a, 380ceafe3ccSJosef Bacik char *buf) 381ceafe3ccSJosef Bacik { 382ceafe3ccSJosef Bacik ssize_t ret = 0; 383ceafe3ccSJosef Bacik int i; 384ceafe3ccSJosef Bacik 385ceafe3ccSJosef Bacik for (i = 0; i < ARRAY_SIZE(rescue_opts); i++) 386020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i ? " " : ""), rescue_opts[i]); 387020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 388ceafe3ccSJosef Bacik return ret; 389ceafe3ccSJosef Bacik } 390ceafe3ccSJosef Bacik BTRFS_ATTR(static_feature, supported_rescue_options, 391ceafe3ccSJosef Bacik supported_rescue_options_show); 392ceafe3ccSJosef Bacik 393fc57ad8dSQu Wenruo static ssize_t supported_sectorsizes_show(struct kobject *kobj, 394fc57ad8dSQu Wenruo struct kobj_attribute *a, 395fc57ad8dSQu Wenruo char *buf) 396fc57ad8dSQu Wenruo { 397fc57ad8dSQu Wenruo ssize_t ret = 0; 398fc57ad8dSQu Wenruo 3991a42daabSQu Wenruo /* An artificial limit to only support 4K and PAGE_SIZE */ 4001a42daabSQu Wenruo if (PAGE_SIZE > SZ_4K) 401020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%u ", SZ_4K); 402020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%lu\n", PAGE_SIZE); 403fc57ad8dSQu Wenruo 404fc57ad8dSQu Wenruo return ret; 405fc57ad8dSQu Wenruo } 406fc57ad8dSQu Wenruo BTRFS_ATTR(static_feature, supported_sectorsizes, 407fc57ad8dSQu Wenruo supported_sectorsizes_show); 408fc57ad8dSQu Wenruo 409e7849e33SAnand Jain /* 410e7849e33SAnand Jain * Features which only depend on kernel version. 411e7849e33SAnand Jain * 412e7849e33SAnand Jain * These are listed in /sys/fs/btrfs/features along with 413e7849e33SAnand Jain * btrfs_supported_feature_attrs. 414e7849e33SAnand Jain */ 415f902bd3aSMisono Tomohiro static struct attribute *btrfs_supported_static_feature_attrs[] = { 416f902bd3aSMisono Tomohiro BTRFS_ATTR_PTR(static_feature, rmdir_subvol), 417f7cea56cSDavid Sterba BTRFS_ATTR_PTR(static_feature, supported_checksums), 4187573df55SOmar Sandoval BTRFS_ATTR_PTR(static_feature, send_stream_version), 419ceafe3ccSJosef Bacik BTRFS_ATTR_PTR(static_feature, supported_rescue_options), 420fc57ad8dSQu Wenruo BTRFS_ATTR_PTR(static_feature, supported_sectorsizes), 421f902bd3aSMisono Tomohiro NULL 422f902bd3aSMisono Tomohiro }; 423f902bd3aSMisono Tomohiro 424f902bd3aSMisono Tomohiro static const struct attribute_group btrfs_static_feature_attr_group = { 425f902bd3aSMisono Tomohiro .name = "features", 426f902bd3aSMisono Tomohiro .attrs = btrfs_supported_static_feature_attrs, 427f902bd3aSMisono Tomohiro }; 428f902bd3aSMisono Tomohiro 4296e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 4306e369febSDavid Sterba 4316e369febSDavid Sterba /* 432e4faab84SDennis Zhou * Discard statistics and tunables 433e4faab84SDennis Zhou */ 434dfb79ddbSDennis Zhou #define discard_to_fs_info(_kobj) to_fs_info((_kobj)->parent->parent) 435dfb79ddbSDennis Zhou 4365dc7c10bSDennis Zhou static ssize_t btrfs_discardable_bytes_show(struct kobject *kobj, 4375dc7c10bSDennis Zhou struct kobj_attribute *a, 4385dc7c10bSDennis Zhou char *buf) 4395dc7c10bSDennis Zhou { 4405dc7c10bSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4415dc7c10bSDennis Zhou 442020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4435dc7c10bSDennis Zhou atomic64_read(&fs_info->discard_ctl.discardable_bytes)); 4445dc7c10bSDennis Zhou } 4455dc7c10bSDennis Zhou BTRFS_ATTR(discard, discardable_bytes, btrfs_discardable_bytes_show); 4465dc7c10bSDennis Zhou 447dfb79ddbSDennis Zhou static ssize_t btrfs_discardable_extents_show(struct kobject *kobj, 448dfb79ddbSDennis Zhou struct kobj_attribute *a, 449dfb79ddbSDennis Zhou char *buf) 450dfb79ddbSDennis Zhou { 451dfb79ddbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 452dfb79ddbSDennis Zhou 453020e5277SAnand Jain return sysfs_emit(buf, "%d\n", 454dfb79ddbSDennis Zhou atomic_read(&fs_info->discard_ctl.discardable_extents)); 455dfb79ddbSDennis Zhou } 456dfb79ddbSDennis Zhou BTRFS_ATTR(discard, discardable_extents, btrfs_discardable_extents_show); 457dfb79ddbSDennis Zhou 4589ddf648fSDennis Zhou static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj, 4599ddf648fSDennis Zhou struct kobj_attribute *a, 4609ddf648fSDennis Zhou char *buf) 4619ddf648fSDennis Zhou { 4629ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4639ddf648fSDennis Zhou 464020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4659ddf648fSDennis Zhou fs_info->discard_ctl.discard_bitmap_bytes); 4669ddf648fSDennis Zhou } 4679ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bitmap_bytes, btrfs_discard_bitmap_bytes_show); 4689ddf648fSDennis Zhou 4699ddf648fSDennis Zhou static ssize_t btrfs_discard_bytes_saved_show(struct kobject *kobj, 4709ddf648fSDennis Zhou struct kobj_attribute *a, 4719ddf648fSDennis Zhou char *buf) 4729ddf648fSDennis Zhou { 4739ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4749ddf648fSDennis Zhou 475020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4769ddf648fSDennis Zhou atomic64_read(&fs_info->discard_ctl.discard_bytes_saved)); 4779ddf648fSDennis Zhou } 4789ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bytes_saved, btrfs_discard_bytes_saved_show); 4799ddf648fSDennis Zhou 4809ddf648fSDennis Zhou static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj, 4819ddf648fSDennis Zhou struct kobj_attribute *a, 4829ddf648fSDennis Zhou char *buf) 4839ddf648fSDennis Zhou { 4849ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4859ddf648fSDennis Zhou 486020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4879ddf648fSDennis Zhou fs_info->discard_ctl.discard_extent_bytes); 4889ddf648fSDennis Zhou } 4899ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_extent_bytes, btrfs_discard_extent_bytes_show); 4909ddf648fSDennis Zhou 491a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_show(struct kobject *kobj, 492a2309300SDennis Zhou struct kobj_attribute *a, 493a2309300SDennis Zhou char *buf) 494a2309300SDennis Zhou { 495a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 496a2309300SDennis Zhou 497020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 498a2309300SDennis Zhou READ_ONCE(fs_info->discard_ctl.iops_limit)); 499a2309300SDennis Zhou } 500a2309300SDennis Zhou 501a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_store(struct kobject *kobj, 502a2309300SDennis Zhou struct kobj_attribute *a, 503a2309300SDennis Zhou const char *buf, size_t len) 504a2309300SDennis Zhou { 505a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 506a2309300SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 507a2309300SDennis Zhou u32 iops_limit; 508a2309300SDennis Zhou int ret; 509a2309300SDennis Zhou 510a2309300SDennis Zhou ret = kstrtou32(buf, 10, &iops_limit); 511a2309300SDennis Zhou if (ret) 512a2309300SDennis Zhou return -EINVAL; 513a2309300SDennis Zhou 514a2309300SDennis Zhou WRITE_ONCE(discard_ctl->iops_limit, iops_limit); 5153e48d8d2SPavel Begunkov btrfs_discard_calc_delay(discard_ctl); 5163e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 517a2309300SDennis Zhou return len; 518a2309300SDennis Zhou } 519a2309300SDennis Zhou BTRFS_ATTR_RW(discard, iops_limit, btrfs_discard_iops_limit_show, 520a2309300SDennis Zhou btrfs_discard_iops_limit_store); 521a2309300SDennis Zhou 522e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_show(struct kobject *kobj, 523e93591bbSDennis Zhou struct kobj_attribute *a, 524e93591bbSDennis Zhou char *buf) 525e93591bbSDennis Zhou { 526e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 527e93591bbSDennis Zhou 528020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 529e93591bbSDennis Zhou READ_ONCE(fs_info->discard_ctl.kbps_limit)); 530e93591bbSDennis Zhou } 531e93591bbSDennis Zhou 532e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_store(struct kobject *kobj, 533e93591bbSDennis Zhou struct kobj_attribute *a, 534e93591bbSDennis Zhou const char *buf, size_t len) 535e93591bbSDennis Zhou { 536e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 537e93591bbSDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 538e93591bbSDennis Zhou u32 kbps_limit; 539e93591bbSDennis Zhou int ret; 540e93591bbSDennis Zhou 541e93591bbSDennis Zhou ret = kstrtou32(buf, 10, &kbps_limit); 542e93591bbSDennis Zhou if (ret) 543e93591bbSDennis Zhou return -EINVAL; 544e93591bbSDennis Zhou 545e93591bbSDennis Zhou WRITE_ONCE(discard_ctl->kbps_limit, kbps_limit); 5463e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 547e93591bbSDennis Zhou return len; 548e93591bbSDennis Zhou } 549e93591bbSDennis Zhou BTRFS_ATTR_RW(discard, kbps_limit, btrfs_discard_kbps_limit_show, 550e93591bbSDennis Zhou btrfs_discard_kbps_limit_store); 551e93591bbSDennis Zhou 55219b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_show(struct kobject *kobj, 55319b2a2c7SDennis Zhou struct kobj_attribute *a, 55419b2a2c7SDennis Zhou char *buf) 55519b2a2c7SDennis Zhou { 55619b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 55719b2a2c7SDennis Zhou 558020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 55919b2a2c7SDennis Zhou READ_ONCE(fs_info->discard_ctl.max_discard_size)); 56019b2a2c7SDennis Zhou } 56119b2a2c7SDennis Zhou 56219b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_store(struct kobject *kobj, 56319b2a2c7SDennis Zhou struct kobj_attribute *a, 56419b2a2c7SDennis Zhou const char *buf, size_t len) 56519b2a2c7SDennis Zhou { 56619b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 56719b2a2c7SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 56819b2a2c7SDennis Zhou u64 max_discard_size; 56919b2a2c7SDennis Zhou int ret; 57019b2a2c7SDennis Zhou 57119b2a2c7SDennis Zhou ret = kstrtou64(buf, 10, &max_discard_size); 57219b2a2c7SDennis Zhou if (ret) 57319b2a2c7SDennis Zhou return -EINVAL; 57419b2a2c7SDennis Zhou 57519b2a2c7SDennis Zhou WRITE_ONCE(discard_ctl->max_discard_size, max_discard_size); 57619b2a2c7SDennis Zhou 57719b2a2c7SDennis Zhou return len; 57819b2a2c7SDennis Zhou } 57919b2a2c7SDennis Zhou BTRFS_ATTR_RW(discard, max_discard_size, btrfs_discard_max_discard_size_show, 58019b2a2c7SDennis Zhou btrfs_discard_max_discard_size_store); 58119b2a2c7SDennis Zhou 582e7849e33SAnand Jain /* 583e7849e33SAnand Jain * Per-filesystem debugging of discard (when mounted with discard=async). 584e7849e33SAnand Jain * 585e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/debug/discard/ 586e7849e33SAnand Jain */ 587e4faab84SDennis Zhou static const struct attribute *discard_debug_attrs[] = { 5885dc7c10bSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_bytes), 589dfb79ddbSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_extents), 5909ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bitmap_bytes), 5919ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bytes_saved), 5929ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_extent_bytes), 593a2309300SDennis Zhou BTRFS_ATTR_PTR(discard, iops_limit), 594e93591bbSDennis Zhou BTRFS_ATTR_PTR(discard, kbps_limit), 59519b2a2c7SDennis Zhou BTRFS_ATTR_PTR(discard, max_discard_size), 596e4faab84SDennis Zhou NULL, 597e4faab84SDennis Zhou }; 598e4faab84SDennis Zhou 599e4faab84SDennis Zhou /* 600e7849e33SAnand Jain * Per-filesystem runtime debugging exported via sysfs. 6016e369febSDavid Sterba * 602e7849e33SAnand Jain * Path: /sys/fs/btrfs/UUID/debug/ 6036e369febSDavid Sterba */ 60493945cb4SDennis Zhou static const struct attribute *btrfs_debug_mount_attrs[] = { 60593945cb4SDennis Zhou NULL, 60693945cb4SDennis Zhou }; 60793945cb4SDennis Zhou 608e7849e33SAnand Jain /* 609e7849e33SAnand Jain * Runtime debugging exported via sysfs, applies to all mounted filesystems. 610e7849e33SAnand Jain * 611e7849e33SAnand Jain * Path: /sys/fs/btrfs/debug 612e7849e33SAnand Jain */ 6136e369febSDavid Sterba static struct attribute *btrfs_debug_feature_attrs[] = { 6146e369febSDavid Sterba NULL 6156e369febSDavid Sterba }; 6166e369febSDavid Sterba 6176e369febSDavid Sterba static const struct attribute_group btrfs_debug_feature_attr_group = { 6186e369febSDavid Sterba .name = "debug", 6196e369febSDavid Sterba .attrs = btrfs_debug_feature_attrs, 6206e369febSDavid Sterba }; 6216e369febSDavid Sterba 6226e369febSDavid Sterba #endif 6236e369febSDavid Sterba 6246ab0a202SJeff Mahoney static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf) 6256ab0a202SJeff Mahoney { 6266ab0a202SJeff Mahoney u64 val; 6276ab0a202SJeff Mahoney if (lock) 6286ab0a202SJeff Mahoney spin_lock(lock); 6296ab0a202SJeff Mahoney val = *value_ptr; 6306ab0a202SJeff Mahoney if (lock) 6316ab0a202SJeff Mahoney spin_unlock(lock); 632020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6336ab0a202SJeff Mahoney } 6346ab0a202SJeff Mahoney 6356ab0a202SJeff Mahoney static ssize_t global_rsv_size_show(struct kobject *kobj, 6366ab0a202SJeff Mahoney struct kobj_attribute *ka, char *buf) 6376ab0a202SJeff Mahoney { 6386ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6396ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6406ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf); 6416ab0a202SJeff Mahoney } 642a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_size, global_rsv_size_show); 6436ab0a202SJeff Mahoney 6446ab0a202SJeff Mahoney static ssize_t global_rsv_reserved_show(struct kobject *kobj, 6456ab0a202SJeff Mahoney struct kobj_attribute *a, char *buf) 6466ab0a202SJeff Mahoney { 6476ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6486ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6496ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf); 6506ab0a202SJeff Mahoney } 651a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_reserved, global_rsv_reserved_show); 6526ab0a202SJeff Mahoney 6536ab0a202SJeff Mahoney #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj) 654c1895442SJeff Mahoney #define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj) 6556ab0a202SJeff Mahoney 6566ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6576ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf); 658a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, total_bytes, raid_bytes_show); 659a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, used_bytes, raid_bytes_show); 6606ab0a202SJeff Mahoney 6616ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6626ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf) 6636ab0a202SJeff Mahoney 6646ab0a202SJeff Mahoney { 6656ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj->parent); 66632da5386SDavid Sterba struct btrfs_block_group *block_group; 66775cb379dSJeff Mahoney int index = btrfs_bg_flags_to_raid_index(to_raid_kobj(kobj)->flags); 6686ab0a202SJeff Mahoney u64 val = 0; 6696ab0a202SJeff Mahoney 6706ab0a202SJeff Mahoney down_read(&sinfo->groups_sem); 6716ab0a202SJeff Mahoney list_for_each_entry(block_group, &sinfo->block_groups[index], list) { 672a969f4ccSHans van Kranenburg if (&attr->attr == BTRFS_ATTR_PTR(raid, total_bytes)) 673b3470b5dSDavid Sterba val += block_group->length; 6746ab0a202SJeff Mahoney else 675bf38be65SDavid Sterba val += block_group->used; 6766ab0a202SJeff Mahoney } 6776ab0a202SJeff Mahoney up_read(&sinfo->groups_sem); 678020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6796ab0a202SJeff Mahoney } 6806ab0a202SJeff Mahoney 681e7849e33SAnand Jain /* 682e7849e33SAnand Jain * Allocation information about block group profiles. 683e7849e33SAnand Jain * 684e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/<bg-profile>/ 685e7849e33SAnand Jain */ 6867c7e3014SKimberly Brown static struct attribute *raid_attrs[] = { 687a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, total_bytes), 688a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, used_bytes), 6896ab0a202SJeff Mahoney NULL 6906ab0a202SJeff Mahoney }; 6917c7e3014SKimberly Brown ATTRIBUTE_GROUPS(raid); 6926ab0a202SJeff Mahoney 6936ab0a202SJeff Mahoney static void release_raid_kobj(struct kobject *kobj) 6946ab0a202SJeff Mahoney { 695c1895442SJeff Mahoney kfree(to_raid_kobj(kobj)); 6966ab0a202SJeff Mahoney } 6976ab0a202SJeff Mahoney 698536ea45cSDavid Sterba static struct kobj_type btrfs_raid_ktype = { 6996ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 7006ab0a202SJeff Mahoney .release = release_raid_kobj, 7017c7e3014SKimberly Brown .default_groups = raid_groups, 7026ab0a202SJeff Mahoney }; 7036ab0a202SJeff Mahoney 7046ab0a202SJeff Mahoney #define SPACE_INFO_ATTR(field) \ 7056ab0a202SJeff Mahoney static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \ 7066ab0a202SJeff Mahoney struct kobj_attribute *a, \ 7076ab0a202SJeff Mahoney char *buf) \ 7086ab0a202SJeff Mahoney { \ 7096ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); \ 7106ab0a202SJeff Mahoney return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \ 7116ab0a202SJeff Mahoney } \ 712a969f4ccSHans van Kranenburg BTRFS_ATTR(space_info, field, btrfs_space_info_show_##field) 7136ab0a202SJeff Mahoney 714*19fc516aSStefan Roesch static ssize_t btrfs_chunk_size_show(struct kobject *kobj, 715*19fc516aSStefan Roesch struct kobj_attribute *a, char *buf) 716*19fc516aSStefan Roesch { 717*19fc516aSStefan Roesch struct btrfs_space_info *sinfo = to_space_info(kobj); 718*19fc516aSStefan Roesch 719*19fc516aSStefan Roesch return sysfs_emit(buf, "%llu\n", READ_ONCE(sinfo->chunk_size)); 720*19fc516aSStefan Roesch } 721*19fc516aSStefan Roesch 722*19fc516aSStefan Roesch /* 723*19fc516aSStefan Roesch * Store new chunk size in space info. Can be called on a read-only filesystem. 724*19fc516aSStefan Roesch * 725*19fc516aSStefan Roesch * If the new chunk size value is larger than 10% of free space it is reduced 726*19fc516aSStefan Roesch * to match that limit. Alignment must be to 256M and the system chunk size 727*19fc516aSStefan Roesch * cannot be set. 728*19fc516aSStefan Roesch */ 729*19fc516aSStefan Roesch static ssize_t btrfs_chunk_size_store(struct kobject *kobj, 730*19fc516aSStefan Roesch struct kobj_attribute *a, 731*19fc516aSStefan Roesch const char *buf, size_t len) 732*19fc516aSStefan Roesch { 733*19fc516aSStefan Roesch struct btrfs_space_info *space_info = to_space_info(kobj); 734*19fc516aSStefan Roesch struct btrfs_fs_info *fs_info = to_fs_info(get_btrfs_kobj(kobj)); 735*19fc516aSStefan Roesch char *retptr; 736*19fc516aSStefan Roesch u64 val; 737*19fc516aSStefan Roesch 738*19fc516aSStefan Roesch if (!capable(CAP_SYS_ADMIN)) 739*19fc516aSStefan Roesch return -EPERM; 740*19fc516aSStefan Roesch 741*19fc516aSStefan Roesch if (!fs_info->fs_devices) 742*19fc516aSStefan Roesch return -EINVAL; 743*19fc516aSStefan Roesch 744*19fc516aSStefan Roesch if (btrfs_is_zoned(fs_info)) 745*19fc516aSStefan Roesch return -EINVAL; 746*19fc516aSStefan Roesch 747*19fc516aSStefan Roesch /* System block type must not be changed. */ 748*19fc516aSStefan Roesch if (space_info->flags & BTRFS_BLOCK_GROUP_SYSTEM) 749*19fc516aSStefan Roesch return -EPERM; 750*19fc516aSStefan Roesch 751*19fc516aSStefan Roesch val = memparse(buf, &retptr); 752*19fc516aSStefan Roesch /* There could be trailing '\n', also catch any typos after the value */ 753*19fc516aSStefan Roesch retptr = skip_spaces(retptr); 754*19fc516aSStefan Roesch if (*retptr != 0 || val == 0) 755*19fc516aSStefan Roesch return -EINVAL; 756*19fc516aSStefan Roesch 757*19fc516aSStefan Roesch val = min(val, BTRFS_MAX_DATA_CHUNK_SIZE); 758*19fc516aSStefan Roesch 759*19fc516aSStefan Roesch /* Limit stripe size to 10% of available space. */ 760*19fc516aSStefan Roesch val = min(div_factor(fs_info->fs_devices->total_rw_bytes, 1), val); 761*19fc516aSStefan Roesch 762*19fc516aSStefan Roesch /* Must be multiple of 256M. */ 763*19fc516aSStefan Roesch val &= ~((u64)SZ_256M - 1); 764*19fc516aSStefan Roesch 765*19fc516aSStefan Roesch /* Must be at least 256M. */ 766*19fc516aSStefan Roesch if (val < SZ_256M) 767*19fc516aSStefan Roesch return -EINVAL; 768*19fc516aSStefan Roesch 769*19fc516aSStefan Roesch btrfs_update_space_info_chunk_size(space_info, val); 770*19fc516aSStefan Roesch 771*19fc516aSStefan Roesch return len; 772*19fc516aSStefan Roesch } 773*19fc516aSStefan Roesch 7746ab0a202SJeff Mahoney SPACE_INFO_ATTR(flags); 7756ab0a202SJeff Mahoney SPACE_INFO_ATTR(total_bytes); 7766ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_used); 7776ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_pinned); 7786ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_reserved); 7796ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_may_use); 780c1fd5c30SWang Xiaoguang SPACE_INFO_ATTR(bytes_readonly); 781169e0da9SNaohiro Aota SPACE_INFO_ATTR(bytes_zone_unusable); 7826ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_used); 7836ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_total); 784*19fc516aSStefan Roesch BTRFS_ATTR_RW(space_info, chunk_size, btrfs_chunk_size_show, btrfs_chunk_size_store); 7856ab0a202SJeff Mahoney 786bb5a098dSJosef Bacik static ssize_t btrfs_sinfo_bg_reclaim_threshold_show(struct kobject *kobj, 787bb5a098dSJosef Bacik struct kobj_attribute *a, 788bb5a098dSJosef Bacik char *buf) 789bb5a098dSJosef Bacik { 790bb5a098dSJosef Bacik struct btrfs_space_info *space_info = to_space_info(kobj); 791bb5a098dSJosef Bacik ssize_t ret; 792bb5a098dSJosef Bacik 793bb5a098dSJosef Bacik ret = sysfs_emit(buf, "%d\n", READ_ONCE(space_info->bg_reclaim_threshold)); 794bb5a098dSJosef Bacik 795bb5a098dSJosef Bacik return ret; 796bb5a098dSJosef Bacik } 797bb5a098dSJosef Bacik 798bb5a098dSJosef Bacik static ssize_t btrfs_sinfo_bg_reclaim_threshold_store(struct kobject *kobj, 799bb5a098dSJosef Bacik struct kobj_attribute *a, 800bb5a098dSJosef Bacik const char *buf, size_t len) 801bb5a098dSJosef Bacik { 802bb5a098dSJosef Bacik struct btrfs_space_info *space_info = to_space_info(kobj); 803bb5a098dSJosef Bacik int thresh; 804bb5a098dSJosef Bacik int ret; 805bb5a098dSJosef Bacik 806bb5a098dSJosef Bacik ret = kstrtoint(buf, 10, &thresh); 807bb5a098dSJosef Bacik if (ret) 808bb5a098dSJosef Bacik return ret; 809bb5a098dSJosef Bacik 810ef972e7bSJosef Bacik if (thresh < 0 || thresh > 100) 811bb5a098dSJosef Bacik return -EINVAL; 812bb5a098dSJosef Bacik 813bb5a098dSJosef Bacik WRITE_ONCE(space_info->bg_reclaim_threshold, thresh); 814bb5a098dSJosef Bacik 815bb5a098dSJosef Bacik return len; 816bb5a098dSJosef Bacik } 817bb5a098dSJosef Bacik 818bb5a098dSJosef Bacik BTRFS_ATTR_RW(space_info, bg_reclaim_threshold, 819bb5a098dSJosef Bacik btrfs_sinfo_bg_reclaim_threshold_show, 820bb5a098dSJosef Bacik btrfs_sinfo_bg_reclaim_threshold_store); 821bb5a098dSJosef Bacik 822e7849e33SAnand Jain /* 823e7849e33SAnand Jain * Allocation information about block group types. 824e7849e33SAnand Jain * 825e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/ 826e7849e33SAnand Jain */ 8276ab0a202SJeff Mahoney static struct attribute *space_info_attrs[] = { 828a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, flags), 829a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, total_bytes), 830a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_used), 831a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_pinned), 832a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_reserved), 833a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_may_use), 834a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_readonly), 835169e0da9SNaohiro Aota BTRFS_ATTR_PTR(space_info, bytes_zone_unusable), 836a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_used), 837a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_total), 838bb5a098dSJosef Bacik BTRFS_ATTR_PTR(space_info, bg_reclaim_threshold), 839*19fc516aSStefan Roesch BTRFS_ATTR_PTR(space_info, chunk_size), 8406ab0a202SJeff Mahoney NULL, 8416ab0a202SJeff Mahoney }; 8427c7e3014SKimberly Brown ATTRIBUTE_GROUPS(space_info); 8436ab0a202SJeff Mahoney 8446ab0a202SJeff Mahoney static void space_info_release(struct kobject *kobj) 8456ab0a202SJeff Mahoney { 8466ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); 8476ab0a202SJeff Mahoney kfree(sinfo); 8486ab0a202SJeff Mahoney } 8496ab0a202SJeff Mahoney 85027992d01SDavid Sterba static struct kobj_type space_info_ktype = { 8516ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 8526ab0a202SJeff Mahoney .release = space_info_release, 8537c7e3014SKimberly Brown .default_groups = space_info_groups, 8546ab0a202SJeff Mahoney }; 8556ab0a202SJeff Mahoney 856e7849e33SAnand Jain /* 857e7849e33SAnand Jain * Allocation information about block groups. 858e7849e33SAnand Jain * 859e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/ 860e7849e33SAnand Jain */ 8616ab0a202SJeff Mahoney static const struct attribute *allocation_attrs[] = { 862a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_reserved), 863a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_size), 8646ab0a202SJeff Mahoney NULL, 8656ab0a202SJeff Mahoney }; 8666ab0a202SJeff Mahoney 867f8ba9c11SJeff Mahoney static ssize_t btrfs_label_show(struct kobject *kobj, 868f8ba9c11SJeff Mahoney struct kobj_attribute *a, char *buf) 869f8ba9c11SJeff Mahoney { 870f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 87148fcc3ffSSatoru Takeuchi char *label = fs_info->super_copy->label; 872ee17fc80SDavid Sterba ssize_t ret; 873ee17fc80SDavid Sterba 874ee17fc80SDavid Sterba spin_lock(&fs_info->super_lock); 875020e5277SAnand Jain ret = sysfs_emit(buf, label[0] ? "%s\n" : "%s", label); 876ee17fc80SDavid Sterba spin_unlock(&fs_info->super_lock); 877ee17fc80SDavid Sterba 878ee17fc80SDavid Sterba return ret; 879f8ba9c11SJeff Mahoney } 880f8ba9c11SJeff Mahoney 881f8ba9c11SJeff Mahoney static ssize_t btrfs_label_store(struct kobject *kobj, 882f8ba9c11SJeff Mahoney struct kobj_attribute *a, 883f8ba9c11SJeff Mahoney const char *buf, size_t len) 884f8ba9c11SJeff Mahoney { 885f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 88648fcc3ffSSatoru Takeuchi size_t p_len; 887f8ba9c11SJeff Mahoney 88866ac9fe7SDavid Sterba if (!fs_info) 88966ac9fe7SDavid Sterba return -EPERM; 89066ac9fe7SDavid Sterba 891bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 89279aec2b8SAnand Jain return -EROFS; 89379aec2b8SAnand Jain 89448fcc3ffSSatoru Takeuchi /* 89548fcc3ffSSatoru Takeuchi * p_len is the len until the first occurrence of either 89648fcc3ffSSatoru Takeuchi * '\n' or '\0' 89748fcc3ffSSatoru Takeuchi */ 89848fcc3ffSSatoru Takeuchi p_len = strcspn(buf, "\n"); 89948fcc3ffSSatoru Takeuchi 90048fcc3ffSSatoru Takeuchi if (p_len >= BTRFS_LABEL_SIZE) 901f8ba9c11SJeff Mahoney return -EINVAL; 902f8ba9c11SJeff Mahoney 903a6f69dc8SDavid Sterba spin_lock(&fs_info->super_lock); 90448fcc3ffSSatoru Takeuchi memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE); 90548fcc3ffSSatoru Takeuchi memcpy(fs_info->super_copy->label, buf, p_len); 906a6f69dc8SDavid Sterba spin_unlock(&fs_info->super_lock); 907f8ba9c11SJeff Mahoney 908a6f69dc8SDavid Sterba /* 909a6f69dc8SDavid Sterba * We don't want to do full transaction commit from inside sysfs 910a6f69dc8SDavid Sterba */ 911a6f69dc8SDavid Sterba btrfs_set_pending(fs_info, COMMIT); 912a6f69dc8SDavid Sterba wake_up_process(fs_info->transaction_kthread); 913a6f69dc8SDavid Sterba 914f8ba9c11SJeff Mahoney return len; 915f8ba9c11SJeff Mahoney } 916a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, label, btrfs_label_show, btrfs_label_store); 917f8ba9c11SJeff Mahoney 918df93589aSDavid Sterba static ssize_t btrfs_nodesize_show(struct kobject *kobj, 919df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 920df93589aSDavid Sterba { 921df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 922df93589aSDavid Sterba 923020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->nodesize); 924df93589aSDavid Sterba } 925df93589aSDavid Sterba 926a969f4ccSHans van Kranenburg BTRFS_ATTR(, nodesize, btrfs_nodesize_show); 927df93589aSDavid Sterba 928df93589aSDavid Sterba static ssize_t btrfs_sectorsize_show(struct kobject *kobj, 929df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 930df93589aSDavid Sterba { 931df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 932df93589aSDavid Sterba 933020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 934df93589aSDavid Sterba } 935df93589aSDavid Sterba 936a969f4ccSHans van Kranenburg BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show); 937df93589aSDavid Sterba 938df93589aSDavid Sterba static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, 939df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 940df93589aSDavid Sterba { 941df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 942df93589aSDavid Sterba 943020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 944df93589aSDavid Sterba } 945df93589aSDavid Sterba 946a969f4ccSHans van Kranenburg BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show); 947df93589aSDavid Sterba 9482723480aSSargun Dhillon static ssize_t quota_override_show(struct kobject *kobj, 9492723480aSSargun Dhillon struct kobj_attribute *a, char *buf) 9502723480aSSargun Dhillon { 9512723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 9522723480aSSargun Dhillon int quota_override; 9532723480aSSargun Dhillon 9542723480aSSargun Dhillon quota_override = test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 955020e5277SAnand Jain return sysfs_emit(buf, "%d\n", quota_override); 9562723480aSSargun Dhillon } 9572723480aSSargun Dhillon 9582723480aSSargun Dhillon static ssize_t quota_override_store(struct kobject *kobj, 9592723480aSSargun Dhillon struct kobj_attribute *a, 9602723480aSSargun Dhillon const char *buf, size_t len) 9612723480aSSargun Dhillon { 9622723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 9632723480aSSargun Dhillon unsigned long knob; 9642723480aSSargun Dhillon int err; 9652723480aSSargun Dhillon 9662723480aSSargun Dhillon if (!fs_info) 9672723480aSSargun Dhillon return -EPERM; 9682723480aSSargun Dhillon 9692723480aSSargun Dhillon if (!capable(CAP_SYS_RESOURCE)) 9702723480aSSargun Dhillon return -EPERM; 9712723480aSSargun Dhillon 9722723480aSSargun Dhillon err = kstrtoul(buf, 10, &knob); 9732723480aSSargun Dhillon if (err) 9742723480aSSargun Dhillon return err; 9752723480aSSargun Dhillon if (knob > 1) 9762723480aSSargun Dhillon return -EINVAL; 9772723480aSSargun Dhillon 9782723480aSSargun Dhillon if (knob) 9792723480aSSargun Dhillon set_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 9802723480aSSargun Dhillon else 9812723480aSSargun Dhillon clear_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 9822723480aSSargun Dhillon 9832723480aSSargun Dhillon return len; 9842723480aSSargun Dhillon } 9852723480aSSargun Dhillon 986a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, quota_override, quota_override_show, quota_override_store); 9872723480aSSargun Dhillon 98856f20f40SNikolay Borisov static ssize_t btrfs_metadata_uuid_show(struct kobject *kobj, 98956f20f40SNikolay Borisov struct kobj_attribute *a, char *buf) 99056f20f40SNikolay Borisov { 99156f20f40SNikolay Borisov struct btrfs_fs_info *fs_info = to_fs_info(kobj); 99256f20f40SNikolay Borisov 993020e5277SAnand Jain return sysfs_emit(buf, "%pU\n", fs_info->fs_devices->metadata_uuid); 99456f20f40SNikolay Borisov } 99556f20f40SNikolay Borisov 99656f20f40SNikolay Borisov BTRFS_ATTR(, metadata_uuid, btrfs_metadata_uuid_show); 99756f20f40SNikolay Borisov 99841e6d2a8SJohannes Thumshirn static ssize_t btrfs_checksum_show(struct kobject *kobj, 99941e6d2a8SJohannes Thumshirn struct kobj_attribute *a, char *buf) 100041e6d2a8SJohannes Thumshirn { 100141e6d2a8SJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 100241e6d2a8SJohannes Thumshirn u16 csum_type = btrfs_super_csum_type(fs_info->super_copy); 100341e6d2a8SJohannes Thumshirn 1004020e5277SAnand Jain return sysfs_emit(buf, "%s (%s)\n", 100541e6d2a8SJohannes Thumshirn btrfs_super_csum_name(csum_type), 100641e6d2a8SJohannes Thumshirn crypto_shash_driver_name(fs_info->csum_shash)); 100741e6d2a8SJohannes Thumshirn } 100841e6d2a8SJohannes Thumshirn 100941e6d2a8SJohannes Thumshirn BTRFS_ATTR(, checksum, btrfs_checksum_show); 101041e6d2a8SJohannes Thumshirn 101166a2823cSGoldwyn Rodrigues static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj, 101266a2823cSGoldwyn Rodrigues struct kobj_attribute *a, char *buf) 101366a2823cSGoldwyn Rodrigues { 101466a2823cSGoldwyn Rodrigues struct btrfs_fs_info *fs_info = to_fs_info(kobj); 101566a2823cSGoldwyn Rodrigues const char *str; 101666a2823cSGoldwyn Rodrigues 101766a2823cSGoldwyn Rodrigues switch (READ_ONCE(fs_info->exclusive_operation)) { 101866a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_NONE: 101966a2823cSGoldwyn Rodrigues str = "none\n"; 102066a2823cSGoldwyn Rodrigues break; 102166a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_BALANCE: 102266a2823cSGoldwyn Rodrigues str = "balance\n"; 102366a2823cSGoldwyn Rodrigues break; 10243e1ad196SDavid Sterba case BTRFS_EXCLOP_BALANCE_PAUSED: 10253e1ad196SDavid Sterba str = "balance paused\n"; 10263e1ad196SDavid Sterba break; 102766a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_ADD: 102866a2823cSGoldwyn Rodrigues str = "device add\n"; 102966a2823cSGoldwyn Rodrigues break; 103066a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REMOVE: 103166a2823cSGoldwyn Rodrigues str = "device remove\n"; 103266a2823cSGoldwyn Rodrigues break; 103366a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REPLACE: 103466a2823cSGoldwyn Rodrigues str = "device replace\n"; 103566a2823cSGoldwyn Rodrigues break; 103666a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_RESIZE: 103766a2823cSGoldwyn Rodrigues str = "resize\n"; 103866a2823cSGoldwyn Rodrigues break; 103966a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_SWAP_ACTIVATE: 104066a2823cSGoldwyn Rodrigues str = "swap activate\n"; 104166a2823cSGoldwyn Rodrigues break; 104266a2823cSGoldwyn Rodrigues default: 104366a2823cSGoldwyn Rodrigues str = "UNKNOWN\n"; 104466a2823cSGoldwyn Rodrigues break; 104566a2823cSGoldwyn Rodrigues } 1046020e5277SAnand Jain return sysfs_emit(buf, "%s", str); 104766a2823cSGoldwyn Rodrigues } 104866a2823cSGoldwyn Rodrigues BTRFS_ATTR(, exclusive_operation, btrfs_exclusive_operation_show); 104966a2823cSGoldwyn Rodrigues 1050089c8b05SAnand Jain static ssize_t btrfs_generation_show(struct kobject *kobj, 1051089c8b05SAnand Jain struct kobj_attribute *a, char *buf) 1052089c8b05SAnand Jain { 1053089c8b05SAnand Jain struct btrfs_fs_info *fs_info = to_fs_info(kobj); 1054089c8b05SAnand Jain 1055020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", fs_info->generation); 1056089c8b05SAnand Jain } 1057089c8b05SAnand Jain BTRFS_ATTR(, generation, btrfs_generation_show); 1058089c8b05SAnand Jain 1059aaefed20SAnand Jain /* 1060aaefed20SAnand Jain * Look for an exact string @string in @buffer with possible leading or 1061aaefed20SAnand Jain * trailing whitespace 1062aaefed20SAnand Jain */ 1063aaefed20SAnand Jain static bool strmatch(const char *buffer, const char *string) 1064aaefed20SAnand Jain { 1065aaefed20SAnand Jain const size_t len = strlen(string); 1066aaefed20SAnand Jain 1067aaefed20SAnand Jain /* Skip leading whitespace */ 1068aaefed20SAnand Jain buffer = skip_spaces(buffer); 1069aaefed20SAnand Jain 1070aaefed20SAnand Jain /* Match entire string, check if the rest is whitespace or empty */ 1071aaefed20SAnand Jain if (strncmp(string, buffer, len) == 0 && 1072aaefed20SAnand Jain strlen(skip_spaces(buffer + len)) == 0) 1073aaefed20SAnand Jain return true; 1074aaefed20SAnand Jain 1075aaefed20SAnand Jain return false; 1076aaefed20SAnand Jain } 1077aaefed20SAnand Jain 10783d8cc17aSAnand Jain static const char * const btrfs_read_policy_name[] = { "pid" }; 10793d8cc17aSAnand Jain 10803d8cc17aSAnand Jain static ssize_t btrfs_read_policy_show(struct kobject *kobj, 10813d8cc17aSAnand Jain struct kobj_attribute *a, char *buf) 10823d8cc17aSAnand Jain { 10833d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 10843d8cc17aSAnand Jain ssize_t ret = 0; 10853d8cc17aSAnand Jain int i; 10863d8cc17aSAnand Jain 10873d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 10883d8cc17aSAnand Jain if (fs_devices->read_policy == i) 10893d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s[%s]", 10903d8cc17aSAnand Jain (ret == 0 ? "" : " "), 10913d8cc17aSAnand Jain btrfs_read_policy_name[i]); 10923d8cc17aSAnand Jain else 10933d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s", 10943d8cc17aSAnand Jain (ret == 0 ? "" : " "), 10953d8cc17aSAnand Jain btrfs_read_policy_name[i]); 10963d8cc17aSAnand Jain } 10973d8cc17aSAnand Jain 10983d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); 10993d8cc17aSAnand Jain 11003d8cc17aSAnand Jain return ret; 11013d8cc17aSAnand Jain } 11023d8cc17aSAnand Jain 11033d8cc17aSAnand Jain static ssize_t btrfs_read_policy_store(struct kobject *kobj, 11043d8cc17aSAnand Jain struct kobj_attribute *a, 11053d8cc17aSAnand Jain const char *buf, size_t len) 11063d8cc17aSAnand Jain { 11073d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 11083d8cc17aSAnand Jain int i; 11093d8cc17aSAnand Jain 11103d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 11113d8cc17aSAnand Jain if (strmatch(buf, btrfs_read_policy_name[i])) { 11123d8cc17aSAnand Jain if (i != fs_devices->read_policy) { 11133d8cc17aSAnand Jain fs_devices->read_policy = i; 11143d8cc17aSAnand Jain btrfs_info(fs_devices->fs_info, 11153d8cc17aSAnand Jain "read policy set to '%s'", 11163d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11173d8cc17aSAnand Jain } 11183d8cc17aSAnand Jain return len; 11193d8cc17aSAnand Jain } 11203d8cc17aSAnand Jain } 11213d8cc17aSAnand Jain 11223d8cc17aSAnand Jain return -EINVAL; 11233d8cc17aSAnand Jain } 11243d8cc17aSAnand Jain BTRFS_ATTR_RW(, read_policy, btrfs_read_policy_show, btrfs_read_policy_store); 11253d8cc17aSAnand Jain 112618bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_show(struct kobject *kobj, 112718bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 112818bb8bbfSJohannes Thumshirn char *buf) 112918bb8bbfSJohannes Thumshirn { 113018bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 113118bb8bbfSJohannes Thumshirn ssize_t ret; 113218bb8bbfSJohannes Thumshirn 1133020e5277SAnand Jain ret = sysfs_emit(buf, "%d\n", READ_ONCE(fs_info->bg_reclaim_threshold)); 113418bb8bbfSJohannes Thumshirn 113518bb8bbfSJohannes Thumshirn return ret; 113618bb8bbfSJohannes Thumshirn } 113718bb8bbfSJohannes Thumshirn 113818bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_store(struct kobject *kobj, 113918bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 114018bb8bbfSJohannes Thumshirn const char *buf, size_t len) 114118bb8bbfSJohannes Thumshirn { 114218bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 114318bb8bbfSJohannes Thumshirn int thresh; 114418bb8bbfSJohannes Thumshirn int ret; 114518bb8bbfSJohannes Thumshirn 114618bb8bbfSJohannes Thumshirn ret = kstrtoint(buf, 10, &thresh); 114718bb8bbfSJohannes Thumshirn if (ret) 114818bb8bbfSJohannes Thumshirn return ret; 114918bb8bbfSJohannes Thumshirn 115077233c2dSJohannes Thumshirn if (thresh != 0 && (thresh <= 50 || thresh > 100)) 115118bb8bbfSJohannes Thumshirn return -EINVAL; 115218bb8bbfSJohannes Thumshirn 115377233c2dSJohannes Thumshirn WRITE_ONCE(fs_info->bg_reclaim_threshold, thresh); 115418bb8bbfSJohannes Thumshirn 115518bb8bbfSJohannes Thumshirn return len; 115618bb8bbfSJohannes Thumshirn } 115718bb8bbfSJohannes Thumshirn BTRFS_ATTR_RW(, bg_reclaim_threshold, btrfs_bg_reclaim_threshold_show, 115818bb8bbfSJohannes Thumshirn btrfs_bg_reclaim_threshold_store); 115918bb8bbfSJohannes Thumshirn 1160e7849e33SAnand Jain /* 1161e7849e33SAnand Jain * Per-filesystem information and stats. 1162e7849e33SAnand Jain * 1163e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/ 1164e7849e33SAnand Jain */ 11650dd2906fSAnand Jain static const struct attribute *btrfs_attrs[] = { 1166a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, label), 1167a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, nodesize), 1168a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, sectorsize), 1169a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, clone_alignment), 1170a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, quota_override), 117156f20f40SNikolay Borisov BTRFS_ATTR_PTR(, metadata_uuid), 117241e6d2a8SJohannes Thumshirn BTRFS_ATTR_PTR(, checksum), 117366a2823cSGoldwyn Rodrigues BTRFS_ATTR_PTR(, exclusive_operation), 1174089c8b05SAnand Jain BTRFS_ATTR_PTR(, generation), 11753d8cc17aSAnand Jain BTRFS_ATTR_PTR(, read_policy), 117618bb8bbfSJohannes Thumshirn BTRFS_ATTR_PTR(, bg_reclaim_threshold), 1177f8ba9c11SJeff Mahoney NULL, 1178f8ba9c11SJeff Mahoney }; 1179f8ba9c11SJeff Mahoney 1180c1b7e474SAnand Jain static void btrfs_release_fsid_kobj(struct kobject *kobj) 1181510d7360SJeff Mahoney { 11822e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj); 1183248d200dSAnand Jain 1184c1b7e474SAnand Jain memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject)); 11852e7910d6SAnand Jain complete(&fs_devs->kobj_unregister); 1186510d7360SJeff Mahoney } 1187510d7360SJeff Mahoney 1188510d7360SJeff Mahoney static struct kobj_type btrfs_ktype = { 1189510d7360SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 1190c1b7e474SAnand Jain .release = btrfs_release_fsid_kobj, 1191510d7360SJeff Mahoney }; 1192510d7360SJeff Mahoney 11932e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj) 11942e7910d6SAnand Jain { 11952e7910d6SAnand Jain if (kobj->ktype != &btrfs_ktype) 11962e7910d6SAnand Jain return NULL; 1197c1b7e474SAnand Jain return container_of(kobj, struct btrfs_fs_devices, fsid_kobj); 11982e7910d6SAnand Jain } 11992e7910d6SAnand Jain 1200510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj) 1201510d7360SJeff Mahoney { 1202510d7360SJeff Mahoney if (kobj->ktype != &btrfs_ktype) 1203510d7360SJeff Mahoney return NULL; 12042e7910d6SAnand Jain return to_fs_devs(kobj)->fs_info; 1205510d7360SJeff Mahoney } 120658176a96SJosef Bacik 1207*19fc516aSStefan Roesch static struct kobject *get_btrfs_kobj(struct kobject *kobj) 1208*19fc516aSStefan Roesch { 1209*19fc516aSStefan Roesch while (kobj) { 1210*19fc516aSStefan Roesch if (kobj->ktype == &btrfs_ktype) 1211*19fc516aSStefan Roesch return kobj; 1212*19fc516aSStefan Roesch kobj = kobj->parent; 1213*19fc516aSStefan Roesch } 1214*19fc516aSStefan Roesch return NULL; 1215*19fc516aSStefan Roesch } 1216*19fc516aSStefan Roesch 1217e453d989SJeff Mahoney #define NUM_FEATURE_BITS 64 12186c52157fSTomohiro Misono #define BTRFS_FEATURE_NAME_MAX 13 12196c52157fSTomohiro Misono static char btrfs_unknown_feature_names[FEAT_MAX][NUM_FEATURE_BITS][BTRFS_FEATURE_NAME_MAX]; 12206c52157fSTomohiro Misono static struct btrfs_feature_attr btrfs_feature_attrs[FEAT_MAX][NUM_FEATURE_BITS]; 1221e453d989SJeff Mahoney 1222a55e65b8SDavid Sterba static_assert(ARRAY_SIZE(btrfs_unknown_feature_names) == 1223a55e65b8SDavid Sterba ARRAY_SIZE(btrfs_feature_attrs)); 1224a55e65b8SDavid Sterba static_assert(ARRAY_SIZE(btrfs_unknown_feature_names[0]) == 1225a55e65b8SDavid Sterba ARRAY_SIZE(btrfs_feature_attrs[0])); 1226a55e65b8SDavid Sterba 12276c52157fSTomohiro Misono static const u64 supported_feature_masks[FEAT_MAX] = { 1228e453d989SJeff Mahoney [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP, 1229e453d989SJeff Mahoney [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP, 1230e453d989SJeff Mahoney [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP, 1231e453d989SJeff Mahoney }; 1232e453d989SJeff Mahoney 1233e453d989SJeff Mahoney static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add) 12345ac1d209SJeff Mahoney { 1235e453d989SJeff Mahoney int set; 1236e453d989SJeff Mahoney 1237e453d989SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 1238e453d989SJeff Mahoney int i; 1239e453d989SJeff Mahoney struct attribute *attrs[2]; 1240e453d989SJeff Mahoney struct attribute_group agroup = { 1241e453d989SJeff Mahoney .name = "features", 1242e453d989SJeff Mahoney .attrs = attrs, 1243e453d989SJeff Mahoney }; 1244e453d989SJeff Mahoney u64 features = get_features(fs_info, set); 1245e453d989SJeff Mahoney features &= ~supported_feature_masks[set]; 1246e453d989SJeff Mahoney 1247e453d989SJeff Mahoney if (!features) 1248e453d989SJeff Mahoney continue; 1249e453d989SJeff Mahoney 1250e453d989SJeff Mahoney attrs[1] = NULL; 1251e453d989SJeff Mahoney for (i = 0; i < NUM_FEATURE_BITS; i++) { 1252e453d989SJeff Mahoney struct btrfs_feature_attr *fa; 1253e453d989SJeff Mahoney 1254e453d989SJeff Mahoney if (!(features & (1ULL << i))) 1255e453d989SJeff Mahoney continue; 1256e453d989SJeff Mahoney 1257e453d989SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 1258e453d989SJeff Mahoney attrs[0] = &fa->kobj_attr.attr; 1259e453d989SJeff Mahoney if (add) { 1260e453d989SJeff Mahoney int ret; 1261c1b7e474SAnand Jain ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj, 1262e453d989SJeff Mahoney &agroup); 1263e453d989SJeff Mahoney if (ret) 1264e453d989SJeff Mahoney return ret; 1265e453d989SJeff Mahoney } else 1266c1b7e474SAnand Jain sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj, 1267e453d989SJeff Mahoney &agroup); 1268e453d989SJeff Mahoney } 1269e453d989SJeff Mahoney 1270e453d989SJeff Mahoney } 1271e453d989SJeff Mahoney return 0; 1272e453d989SJeff Mahoney } 1273e453d989SJeff Mahoney 12742e3e1281SAnand Jain static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 1275e453d989SJeff Mahoney { 1276a013d141SAnand Jain if (fs_devs->devinfo_kobj) { 1277a013d141SAnand Jain kobject_del(fs_devs->devinfo_kobj); 1278a013d141SAnand Jain kobject_put(fs_devs->devinfo_kobj); 1279a013d141SAnand Jain fs_devs->devinfo_kobj = NULL; 1280a013d141SAnand Jain } 1281a013d141SAnand Jain 1282b5501504SAnand Jain if (fs_devs->devices_kobj) { 1283b5501504SAnand Jain kobject_del(fs_devs->devices_kobj); 1284b5501504SAnand Jain kobject_put(fs_devs->devices_kobj); 1285b5501504SAnand Jain fs_devs->devices_kobj = NULL; 1286aaf13305SAnand Jain } 1287aaf13305SAnand Jain 1288c1b7e474SAnand Jain if (fs_devs->fsid_kobj.state_initialized) { 1289c1b7e474SAnand Jain kobject_del(&fs_devs->fsid_kobj); 1290c1b7e474SAnand Jain kobject_put(&fs_devs->fsid_kobj); 12912e7910d6SAnand Jain wait_for_completion(&fs_devs->kobj_unregister); 12925ac1d209SJeff Mahoney } 1293f90fc547SAnand Jain } 12945ac1d209SJeff Mahoney 12952e3e1281SAnand Jain /* when fs_devs is NULL it will remove all fsid kobject */ 12961d1c1be3SAnand Jain void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 12972e3e1281SAnand Jain { 12982e3e1281SAnand Jain struct list_head *fs_uuids = btrfs_get_fs_uuids(); 12992e3e1281SAnand Jain 13002e3e1281SAnand Jain if (fs_devs) { 13012e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 13022e3e1281SAnand Jain return; 13032e3e1281SAnand Jain } 13042e3e1281SAnand Jain 1305c4babc5eSAnand Jain list_for_each_entry(fs_devs, fs_uuids, fs_list) { 13062e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 13072e3e1281SAnand Jain } 13082e3e1281SAnand Jain } 13092e3e1281SAnand Jain 131053f8a74cSAnand Jain static void btrfs_sysfs_remove_fs_devices(struct btrfs_fs_devices *fs_devices) 131153f8a74cSAnand Jain { 131253f8a74cSAnand Jain struct btrfs_device *device; 131330b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 131453f8a74cSAnand Jain 131553f8a74cSAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) 131653f8a74cSAnand Jain btrfs_sysfs_remove_device(device); 131730b0e4e0SAnand Jain 131830b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 131930b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) 132030b0e4e0SAnand Jain btrfs_sysfs_remove_device(device); 132130b0e4e0SAnand Jain } 132253f8a74cSAnand Jain } 132353f8a74cSAnand Jain 13246618a59bSAnand Jain void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info) 1325e453d989SJeff Mahoney { 13263092c68fSNikolay Borisov struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 13273092c68fSNikolay Borisov 13283092c68fSNikolay Borisov sysfs_remove_link(fsid_kobj, "bdi"); 13293092c68fSNikolay Borisov 1330e453d989SJeff Mahoney if (fs_info->space_info_kobj) { 1331e453d989SJeff Mahoney sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); 1332e453d989SJeff Mahoney kobject_del(fs_info->space_info_kobj); 1333e453d989SJeff Mahoney kobject_put(fs_info->space_info_kobj); 1334e453d989SJeff Mahoney } 133571e8978eSDennis Zhou #ifdef CONFIG_BTRFS_DEBUG 1336e4faab84SDennis Zhou if (fs_info->discard_debug_kobj) { 1337e4faab84SDennis Zhou sysfs_remove_files(fs_info->discard_debug_kobj, 1338e4faab84SDennis Zhou discard_debug_attrs); 1339e4faab84SDennis Zhou kobject_del(fs_info->discard_debug_kobj); 1340e4faab84SDennis Zhou kobject_put(fs_info->discard_debug_kobj); 1341e4faab84SDennis Zhou } 134293945cb4SDennis Zhou if (fs_info->debug_kobj) { 134393945cb4SDennis Zhou sysfs_remove_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 134493945cb4SDennis Zhou kobject_del(fs_info->debug_kobj); 134593945cb4SDennis Zhou kobject_put(fs_info->debug_kobj); 134693945cb4SDennis Zhou } 134771e8978eSDennis Zhou #endif 1348e453d989SJeff Mahoney addrm_unknown_feature_attrs(fs_info, false); 13493092c68fSNikolay Borisov sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 13503092c68fSNikolay Borisov sysfs_remove_files(fsid_kobj, btrfs_attrs); 135153f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_info->fs_devices); 1352e453d989SJeff Mahoney } 1353e453d989SJeff Mahoney 1354f10152bcSDavid Sterba static const char * const btrfs_feature_set_names[FEAT_MAX] = { 135579da4fa4SJeff Mahoney [FEAT_COMPAT] = "compat", 135679da4fa4SJeff Mahoney [FEAT_COMPAT_RO] = "compat_ro", 135779da4fa4SJeff Mahoney [FEAT_INCOMPAT] = "incompat", 135879da4fa4SJeff Mahoney }; 135979da4fa4SJeff Mahoney 13609e6df7ceSDavid Sterba const char *btrfs_feature_set_name(enum btrfs_feature_set set) 1361f10152bcSDavid Sterba { 1362f10152bcSDavid Sterba return btrfs_feature_set_names[set]; 1363f10152bcSDavid Sterba } 1364f10152bcSDavid Sterba 13653b02a68aSJeff Mahoney char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) 13663b02a68aSJeff Mahoney { 13673b02a68aSJeff Mahoney size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */ 13683b02a68aSJeff Mahoney int len = 0; 13693b02a68aSJeff Mahoney int i; 13703b02a68aSJeff Mahoney char *str; 13713b02a68aSJeff Mahoney 13723b02a68aSJeff Mahoney str = kmalloc(bufsize, GFP_KERNEL); 13733b02a68aSJeff Mahoney if (!str) 13743b02a68aSJeff Mahoney return str; 13753b02a68aSJeff Mahoney 13763b02a68aSJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 13773b02a68aSJeff Mahoney const char *name; 13783b02a68aSJeff Mahoney 13793b02a68aSJeff Mahoney if (!(flags & (1ULL << i))) 13803b02a68aSJeff Mahoney continue; 13813b02a68aSJeff Mahoney 13823b02a68aSJeff Mahoney name = btrfs_feature_attrs[set][i].kobj_attr.attr.name; 1383abdd9febSTakashi Iwai len += scnprintf(str + len, bufsize - len, "%s%s", 13843b02a68aSJeff Mahoney len ? "," : "", name); 13853b02a68aSJeff Mahoney } 13863b02a68aSJeff Mahoney 13873b02a68aSJeff Mahoney return str; 13883b02a68aSJeff Mahoney } 13893b02a68aSJeff Mahoney 139079da4fa4SJeff Mahoney static void init_feature_attrs(void) 139179da4fa4SJeff Mahoney { 139279da4fa4SJeff Mahoney struct btrfs_feature_attr *fa; 139379da4fa4SJeff Mahoney int set, i; 139479da4fa4SJeff Mahoney 13953b02a68aSJeff Mahoney memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs)); 13963b02a68aSJeff Mahoney memset(btrfs_unknown_feature_names, 0, 13973b02a68aSJeff Mahoney sizeof(btrfs_unknown_feature_names)); 13983b02a68aSJeff Mahoney 139979da4fa4SJeff Mahoney for (i = 0; btrfs_supported_feature_attrs[i]; i++) { 140079da4fa4SJeff Mahoney struct btrfs_feature_attr *sfa; 140179da4fa4SJeff Mahoney struct attribute *a = btrfs_supported_feature_attrs[i]; 14023b02a68aSJeff Mahoney int bit; 140379da4fa4SJeff Mahoney sfa = attr_to_btrfs_feature_attr(a); 14043b02a68aSJeff Mahoney bit = ilog2(sfa->feature_bit); 14053b02a68aSJeff Mahoney fa = &btrfs_feature_attrs[sfa->feature_set][bit]; 140679da4fa4SJeff Mahoney 140779da4fa4SJeff Mahoney fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name; 140879da4fa4SJeff Mahoney } 140979da4fa4SJeff Mahoney 141079da4fa4SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 141179da4fa4SJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 141279da4fa4SJeff Mahoney char *name = btrfs_unknown_feature_names[set][i]; 141379da4fa4SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 141479da4fa4SJeff Mahoney 141579da4fa4SJeff Mahoney if (fa->kobj_attr.attr.name) 141679da4fa4SJeff Mahoney continue; 141779da4fa4SJeff Mahoney 14186c52157fSTomohiro Misono snprintf(name, BTRFS_FEATURE_NAME_MAX, "%s:%u", 141979da4fa4SJeff Mahoney btrfs_feature_set_names[set], i); 142079da4fa4SJeff Mahoney 142179da4fa4SJeff Mahoney fa->kobj_attr.attr.name = name; 142279da4fa4SJeff Mahoney fa->kobj_attr.attr.mode = S_IRUGO; 142379da4fa4SJeff Mahoney fa->feature_set = set; 142479da4fa4SJeff Mahoney fa->feature_bit = 1ULL << i; 142579da4fa4SJeff Mahoney } 142679da4fa4SJeff Mahoney } 142779da4fa4SJeff Mahoney } 142879da4fa4SJeff Mahoney 142932a9991fSDavid Sterba /* 143032a9991fSDavid Sterba * Create a sysfs entry for a given block group type at path 143132a9991fSDavid Sterba * /sys/fs/btrfs/UUID/allocation/data/TYPE 143232a9991fSDavid Sterba */ 143332da5386SDavid Sterba void btrfs_sysfs_add_block_group_type(struct btrfs_block_group *cache) 143432a9991fSDavid Sterba { 143532a9991fSDavid Sterba struct btrfs_fs_info *fs_info = cache->fs_info; 143632a9991fSDavid Sterba struct btrfs_space_info *space_info = cache->space_info; 143732a9991fSDavid Sterba struct raid_kobject *rkobj; 143832a9991fSDavid Sterba const int index = btrfs_bg_flags_to_raid_index(cache->flags); 143932a9991fSDavid Sterba unsigned int nofs_flag; 144032a9991fSDavid Sterba int ret; 144132a9991fSDavid Sterba 144232a9991fSDavid Sterba /* 144332a9991fSDavid Sterba * Setup a NOFS context because kobject_add(), deep in its call chain, 144432a9991fSDavid Sterba * does GFP_KERNEL allocations, and we are often called in a context 144532a9991fSDavid Sterba * where if reclaim is triggered we can deadlock (we are either holding 144632a9991fSDavid Sterba * a transaction handle or some lock required for a transaction 144732a9991fSDavid Sterba * commit). 144832a9991fSDavid Sterba */ 144932a9991fSDavid Sterba nofs_flag = memalloc_nofs_save(); 145032a9991fSDavid Sterba 145132a9991fSDavid Sterba rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS); 145232a9991fSDavid Sterba if (!rkobj) { 145332a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 145432a9991fSDavid Sterba btrfs_warn(cache->fs_info, 145532a9991fSDavid Sterba "couldn't alloc memory for raid level kobject"); 145632a9991fSDavid Sterba return; 145732a9991fSDavid Sterba } 145832a9991fSDavid Sterba 145932a9991fSDavid Sterba rkobj->flags = cache->flags; 146032a9991fSDavid Sterba kobject_init(&rkobj->kobj, &btrfs_raid_ktype); 146149ea112dSJosef Bacik 146249ea112dSJosef Bacik /* 146349ea112dSJosef Bacik * We call this either on mount, or if we've created a block group for a 146449ea112dSJosef Bacik * new index type while running (i.e. when restriping). The running 146549ea112dSJosef Bacik * case is tricky because we could race with other threads, so we need 146649ea112dSJosef Bacik * to have this check to make sure we didn't already init the kobject. 146749ea112dSJosef Bacik * 146849ea112dSJosef Bacik * We don't have to protect on the free side because it only happens on 146949ea112dSJosef Bacik * unmount. 147049ea112dSJosef Bacik */ 147149ea112dSJosef Bacik spin_lock(&space_info->lock); 147249ea112dSJosef Bacik if (space_info->block_group_kobjs[index]) { 147349ea112dSJosef Bacik spin_unlock(&space_info->lock); 147449ea112dSJosef Bacik kobject_put(&rkobj->kobj); 147549ea112dSJosef Bacik return; 147649ea112dSJosef Bacik } else { 147749ea112dSJosef Bacik space_info->block_group_kobjs[index] = &rkobj->kobj; 147849ea112dSJosef Bacik } 147949ea112dSJosef Bacik spin_unlock(&space_info->lock); 148049ea112dSJosef Bacik 148132a9991fSDavid Sterba ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s", 148232a9991fSDavid Sterba btrfs_bg_type_to_raid_name(rkobj->flags)); 148332a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 148432a9991fSDavid Sterba if (ret) { 148549ea112dSJosef Bacik spin_lock(&space_info->lock); 148649ea112dSJosef Bacik space_info->block_group_kobjs[index] = NULL; 148749ea112dSJosef Bacik spin_unlock(&space_info->lock); 148832a9991fSDavid Sterba kobject_put(&rkobj->kobj); 148932a9991fSDavid Sterba btrfs_warn(fs_info, 149032a9991fSDavid Sterba "failed to add kobject for block cache, ignoring"); 149132a9991fSDavid Sterba return; 149232a9991fSDavid Sterba } 149332a9991fSDavid Sterba } 149432a9991fSDavid Sterba 1495b5865babSDavid Sterba /* 1496b5865babSDavid Sterba * Remove sysfs directories for all block group types of a given space info and 1497b5865babSDavid Sterba * the space info as well 1498b5865babSDavid Sterba */ 1499b5865babSDavid Sterba void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info) 1500b5865babSDavid Sterba { 1501b5865babSDavid Sterba int i; 1502b5865babSDavid Sterba 1503b5865babSDavid Sterba for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { 1504b5865babSDavid Sterba struct kobject *kobj; 1505b5865babSDavid Sterba 1506b5865babSDavid Sterba kobj = space_info->block_group_kobjs[i]; 1507b5865babSDavid Sterba space_info->block_group_kobjs[i] = NULL; 1508b5865babSDavid Sterba if (kobj) { 1509b5865babSDavid Sterba kobject_del(kobj); 1510b5865babSDavid Sterba kobject_put(kobj); 1511b5865babSDavid Sterba } 1512b5865babSDavid Sterba } 1513b5865babSDavid Sterba kobject_del(&space_info->kobj); 1514b5865babSDavid Sterba kobject_put(&space_info->kobj); 1515b5865babSDavid Sterba } 1516b5865babSDavid Sterba 1517b882327aSDavid Sterba static const char *alloc_name(u64 flags) 1518b882327aSDavid Sterba { 1519b882327aSDavid Sterba switch (flags) { 1520b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA: 1521b882327aSDavid Sterba return "mixed"; 1522b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA: 1523b882327aSDavid Sterba return "metadata"; 1524b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_DATA: 1525b882327aSDavid Sterba return "data"; 1526b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_SYSTEM: 1527b882327aSDavid Sterba return "system"; 1528b882327aSDavid Sterba default: 1529b882327aSDavid Sterba WARN_ON(1); 1530b882327aSDavid Sterba return "invalid-combination"; 1531445d8ab5STom Rix } 1532b882327aSDavid Sterba } 1533b882327aSDavid Sterba 1534b882327aSDavid Sterba /* 1535b882327aSDavid Sterba * Create a sysfs entry for a space info type at path 1536b882327aSDavid Sterba * /sys/fs/btrfs/UUID/allocation/TYPE 1537b882327aSDavid Sterba */ 1538b882327aSDavid Sterba int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info, 1539b882327aSDavid Sterba struct btrfs_space_info *space_info) 1540b882327aSDavid Sterba { 1541b882327aSDavid Sterba int ret; 1542b882327aSDavid Sterba 1543b882327aSDavid Sterba ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, 1544b882327aSDavid Sterba fs_info->space_info_kobj, "%s", 1545b882327aSDavid Sterba alloc_name(space_info->flags)); 1546b882327aSDavid Sterba if (ret) { 1547b882327aSDavid Sterba kobject_put(&space_info->kobj); 1548b882327aSDavid Sterba return ret; 1549b882327aSDavid Sterba } 1550b882327aSDavid Sterba 1551b882327aSDavid Sterba return 0; 1552b882327aSDavid Sterba } 1553b882327aSDavid Sterba 155453f8a74cSAnand Jain void btrfs_sysfs_remove_device(struct btrfs_device *device) 155599994cdeSAnand Jain { 1556985e233eSAnand Jain struct kobject *devices_kobj; 155799994cdeSAnand Jain 1558985e233eSAnand Jain /* 1559985e233eSAnand Jain * Seed fs_devices devices_kobj aren't used, fetch kobject from the 1560985e233eSAnand Jain * fs_info::fs_devices. 1561985e233eSAnand Jain */ 1562985e233eSAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1563985e233eSAnand Jain ASSERT(devices_kobj); 156499994cdeSAnand Jain 15658d65269fSChristoph Hellwig if (device->bdev) 15668d65269fSChristoph Hellwig sysfs_remove_link(devices_kobj, bdev_kobj(device->bdev)->name); 156799994cdeSAnand Jain 1568985e233eSAnand Jain if (device->devid_kobj.state_initialized) { 1569985e233eSAnand Jain kobject_del(&device->devid_kobj); 1570985e233eSAnand Jain kobject_put(&device->devid_kobj); 1571985e233eSAnand Jain wait_for_completion(&device->kobj_unregister); 1572985e233eSAnand Jain } 1573b5ddcffaSAnand Jain } 1574668e48afSAnand Jain 1575668e48afSAnand Jain static ssize_t btrfs_devinfo_in_fs_metadata_show(struct kobject *kobj, 1576668e48afSAnand Jain struct kobj_attribute *a, 1577668e48afSAnand Jain char *buf) 1578668e48afSAnand Jain { 1579668e48afSAnand Jain int val; 1580668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1581668e48afSAnand Jain devid_kobj); 1582668e48afSAnand Jain 1583668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state); 1584668e48afSAnand Jain 1585020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1586668e48afSAnand Jain } 1587668e48afSAnand Jain BTRFS_ATTR(devid, in_fs_metadata, btrfs_devinfo_in_fs_metadata_show); 1588668e48afSAnand Jain 158925864778SAnand Jain static ssize_t btrfs_devinfo_missing_show(struct kobject *kobj, 1590668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1591668e48afSAnand Jain { 1592668e48afSAnand Jain int val; 1593668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1594668e48afSAnand Jain devid_kobj); 1595668e48afSAnand Jain 1596668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state); 1597668e48afSAnand Jain 1598020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1599668e48afSAnand Jain } 160025864778SAnand Jain BTRFS_ATTR(devid, missing, btrfs_devinfo_missing_show); 1601668e48afSAnand Jain 1602668e48afSAnand Jain static ssize_t btrfs_devinfo_replace_target_show(struct kobject *kobj, 1603668e48afSAnand Jain struct kobj_attribute *a, 1604668e48afSAnand Jain char *buf) 1605668e48afSAnand Jain { 1606668e48afSAnand Jain int val; 1607668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1608668e48afSAnand Jain devid_kobj); 1609668e48afSAnand Jain 1610668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state); 1611668e48afSAnand Jain 1612020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1613668e48afSAnand Jain } 1614668e48afSAnand Jain BTRFS_ATTR(devid, replace_target, btrfs_devinfo_replace_target_show); 1615668e48afSAnand Jain 1616eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_show(struct kobject *kobj, 1617eb3b5053SDavid Sterba struct kobj_attribute *a, 1618eb3b5053SDavid Sterba char *buf) 1619eb3b5053SDavid Sterba { 1620eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1621eb3b5053SDavid Sterba devid_kobj); 1622eb3b5053SDavid Sterba 1623020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", READ_ONCE(device->scrub_speed_max)); 1624eb3b5053SDavid Sterba } 1625eb3b5053SDavid Sterba 1626eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_store(struct kobject *kobj, 1627eb3b5053SDavid Sterba struct kobj_attribute *a, 1628eb3b5053SDavid Sterba const char *buf, size_t len) 1629eb3b5053SDavid Sterba { 1630eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1631eb3b5053SDavid Sterba devid_kobj); 1632eb3b5053SDavid Sterba char *endptr; 1633eb3b5053SDavid Sterba unsigned long long limit; 1634eb3b5053SDavid Sterba 1635eb3b5053SDavid Sterba limit = memparse(buf, &endptr); 1636eb3b5053SDavid Sterba WRITE_ONCE(device->scrub_speed_max, limit); 1637eb3b5053SDavid Sterba return len; 1638eb3b5053SDavid Sterba } 1639eb3b5053SDavid Sterba BTRFS_ATTR_RW(devid, scrub_speed_max, btrfs_devinfo_scrub_speed_max_show, 1640eb3b5053SDavid Sterba btrfs_devinfo_scrub_speed_max_store); 1641eb3b5053SDavid Sterba 1642668e48afSAnand Jain static ssize_t btrfs_devinfo_writeable_show(struct kobject *kobj, 1643668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1644668e48afSAnand Jain { 1645668e48afSAnand Jain int val; 1646668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1647668e48afSAnand Jain devid_kobj); 1648668e48afSAnand Jain 1649668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state); 1650668e48afSAnand Jain 1651020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1652668e48afSAnand Jain } 1653668e48afSAnand Jain BTRFS_ATTR(devid, writeable, btrfs_devinfo_writeable_show); 1654668e48afSAnand Jain 1655a26d60deSAnand Jain static ssize_t btrfs_devinfo_fsid_show(struct kobject *kobj, 1656a26d60deSAnand Jain struct kobj_attribute *a, char *buf) 1657a26d60deSAnand Jain { 1658a26d60deSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1659a26d60deSAnand Jain devid_kobj); 1660a26d60deSAnand Jain 1661a26d60deSAnand Jain return sysfs_emit(buf, "%pU\n", device->fs_devices->fsid); 1662a26d60deSAnand Jain } 1663a26d60deSAnand Jain BTRFS_ATTR(devid, fsid, btrfs_devinfo_fsid_show); 1664a26d60deSAnand Jain 1665da658b57SDavid Sterba static ssize_t btrfs_devinfo_error_stats_show(struct kobject *kobj, 1666da658b57SDavid Sterba struct kobj_attribute *a, char *buf) 1667da658b57SDavid Sterba { 1668da658b57SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1669da658b57SDavid Sterba devid_kobj); 1670da658b57SDavid Sterba 1671da658b57SDavid Sterba if (!device->dev_stats_valid) 1672020e5277SAnand Jain return sysfs_emit(buf, "invalid\n"); 1673da658b57SDavid Sterba 1674da658b57SDavid Sterba /* 1675da658b57SDavid Sterba * Print all at once so we get a snapshot of all values from the same 1676da658b57SDavid Sterba * time. Keep them in sync and in order of definition of 1677da658b57SDavid Sterba * btrfs_dev_stat_values. 1678da658b57SDavid Sterba */ 1679020e5277SAnand Jain return sysfs_emit(buf, 1680da658b57SDavid Sterba "write_errs %d\n" 1681da658b57SDavid Sterba "read_errs %d\n" 1682da658b57SDavid Sterba "flush_errs %d\n" 1683da658b57SDavid Sterba "corruption_errs %d\n" 1684da658b57SDavid Sterba "generation_errs %d\n", 1685da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_WRITE_ERRS), 1686da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_READ_ERRS), 1687da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_FLUSH_ERRS), 1688da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_CORRUPTION_ERRS), 1689da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_GENERATION_ERRS)); 1690da658b57SDavid Sterba } 1691da658b57SDavid Sterba BTRFS_ATTR(devid, error_stats, btrfs_devinfo_error_stats_show); 1692da658b57SDavid Sterba 1693e7849e33SAnand Jain /* 1694e7849e33SAnand Jain * Information about one device. 1695e7849e33SAnand Jain * 1696e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/devinfo/<devid>/ 1697e7849e33SAnand Jain */ 1698668e48afSAnand Jain static struct attribute *devid_attrs[] = { 1699da658b57SDavid Sterba BTRFS_ATTR_PTR(devid, error_stats), 1700a26d60deSAnand Jain BTRFS_ATTR_PTR(devid, fsid), 1701668e48afSAnand Jain BTRFS_ATTR_PTR(devid, in_fs_metadata), 1702668e48afSAnand Jain BTRFS_ATTR_PTR(devid, missing), 1703668e48afSAnand Jain BTRFS_ATTR_PTR(devid, replace_target), 1704eb3b5053SDavid Sterba BTRFS_ATTR_PTR(devid, scrub_speed_max), 1705668e48afSAnand Jain BTRFS_ATTR_PTR(devid, writeable), 1706668e48afSAnand Jain NULL 1707668e48afSAnand Jain }; 1708668e48afSAnand Jain ATTRIBUTE_GROUPS(devid); 1709668e48afSAnand Jain 1710668e48afSAnand Jain static void btrfs_release_devid_kobj(struct kobject *kobj) 1711668e48afSAnand Jain { 1712668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1713668e48afSAnand Jain devid_kobj); 1714668e48afSAnand Jain 1715668e48afSAnand Jain memset(&device->devid_kobj, 0, sizeof(struct kobject)); 1716668e48afSAnand Jain complete(&device->kobj_unregister); 1717668e48afSAnand Jain } 1718668e48afSAnand Jain 1719668e48afSAnand Jain static struct kobj_type devid_ktype = { 1720668e48afSAnand Jain .sysfs_ops = &kobj_sysfs_ops, 1721668e48afSAnand Jain .default_groups = devid_groups, 1722668e48afSAnand Jain .release = btrfs_release_devid_kobj, 1723668e48afSAnand Jain }; 1724668e48afSAnand Jain 1725cd36da2eSAnand Jain int btrfs_sysfs_add_device(struct btrfs_device *device) 172629e5be24SJeff Mahoney { 1727178a16c9SAnand Jain int ret; 1728a47bd78dSJosef Bacik unsigned int nofs_flag; 1729178a16c9SAnand Jain struct kobject *devices_kobj; 1730178a16c9SAnand Jain struct kobject *devinfo_kobj; 1731178a16c9SAnand Jain 1732178a16c9SAnand Jain /* 1733178a16c9SAnand Jain * Make sure we use the fs_info::fs_devices to fetch the kobjects even 1734178a16c9SAnand Jain * for the seed fs_devices 1735178a16c9SAnand Jain */ 1736178a16c9SAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1737178a16c9SAnand Jain devinfo_kobj = device->fs_info->fs_devices->devinfo_kobj; 1738178a16c9SAnand Jain ASSERT(devices_kobj); 1739178a16c9SAnand Jain ASSERT(devinfo_kobj); 174029e5be24SJeff Mahoney 1741a47bd78dSJosef Bacik nofs_flag = memalloc_nofs_save(); 1742f085381eSAnand Jain 1743178a16c9SAnand Jain if (device->bdev) { 17448d65269fSChristoph Hellwig struct kobject *disk_kobj = bdev_kobj(device->bdev); 174529e5be24SJeff Mahoney 1746178a16c9SAnand Jain ret = sysfs_create_link(devices_kobj, disk_kobj, disk_kobj->name); 1747178a16c9SAnand Jain if (ret) { 1748178a16c9SAnand Jain btrfs_warn(device->fs_info, 1749178a16c9SAnand Jain "creating sysfs device link for devid %llu failed: %d", 1750178a16c9SAnand Jain device->devid, ret); 1751178a16c9SAnand Jain goto out; 1752178a16c9SAnand Jain } 175329e5be24SJeff Mahoney } 175429e5be24SJeff Mahoney 1755178a16c9SAnand Jain init_completion(&device->kobj_unregister); 1756178a16c9SAnand Jain ret = kobject_init_and_add(&device->devid_kobj, &devid_ktype, 1757178a16c9SAnand Jain devinfo_kobj, "%llu", device->devid); 1758178a16c9SAnand Jain if (ret) { 1759178a16c9SAnand Jain kobject_put(&device->devid_kobj); 1760178a16c9SAnand Jain btrfs_warn(device->fs_info, 1761178a16c9SAnand Jain "devinfo init for devid %llu failed: %d", 1762178a16c9SAnand Jain device->devid, ret); 1763668e48afSAnand Jain } 1764178a16c9SAnand Jain 1765178a16c9SAnand Jain out: 1766a47bd78dSJosef Bacik memalloc_nofs_restore(nofs_flag); 1767178a16c9SAnand Jain return ret; 1768178a16c9SAnand Jain } 1769668e48afSAnand Jain 1770cd36da2eSAnand Jain static int btrfs_sysfs_add_fs_devices(struct btrfs_fs_devices *fs_devices) 1771178a16c9SAnand Jain { 1772178a16c9SAnand Jain int ret; 1773cd36da2eSAnand Jain struct btrfs_device *device; 177430b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 1775178a16c9SAnand Jain 1776178a16c9SAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) { 1777178a16c9SAnand Jain ret = btrfs_sysfs_add_device(device); 1778178a16c9SAnand Jain if (ret) 17797ad3912aSAnand Jain goto fail; 1780178a16c9SAnand Jain } 1781178a16c9SAnand Jain 178230b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 178330b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) { 178430b0e4e0SAnand Jain ret = btrfs_sysfs_add_device(device); 178530b0e4e0SAnand Jain if (ret) 17867ad3912aSAnand Jain goto fail; 178730b0e4e0SAnand Jain } 178830b0e4e0SAnand Jain } 178930b0e4e0SAnand Jain 1790178a16c9SAnand Jain return 0; 17917ad3912aSAnand Jain 17927ad3912aSAnand Jain fail: 17937ad3912aSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devices); 17947ad3912aSAnand Jain return ret; 179529e5be24SJeff Mahoney } 179629e5be24SJeff Mahoney 17975b28692eSDavid Sterba void btrfs_kobject_uevent(struct block_device *bdev, enum kobject_action action) 17985b28692eSDavid Sterba { 17995b28692eSDavid Sterba int ret; 18005b28692eSDavid Sterba 18015b28692eSDavid Sterba ret = kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, action); 18025b28692eSDavid Sterba if (ret) 18035b28692eSDavid Sterba pr_warn("BTRFS: Sending event '%d' to kobject: '%s' (%p): failed\n", 18045b28692eSDavid Sterba action, kobject_name(&disk_to_dev(bdev->bd_disk)->kobj), 18055b28692eSDavid Sterba &disk_to_dev(bdev->bd_disk)->kobj); 18065b28692eSDavid Sterba } 18075b28692eSDavid Sterba 18088e560081SNikolay Borisov void btrfs_sysfs_update_sprout_fsid(struct btrfs_fs_devices *fs_devices) 18098e560081SNikolay Borisov 1810f93c3997SDavid Sterba { 1811f93c3997SDavid Sterba char fsid_buf[BTRFS_UUID_UNPARSED_SIZE]; 1812f93c3997SDavid Sterba 1813f93c3997SDavid Sterba /* 1814f93c3997SDavid Sterba * Sprouting changes fsid of the mounted filesystem, rename the fsid 1815f93c3997SDavid Sterba * directory 1816f93c3997SDavid Sterba */ 18178e560081SNikolay Borisov snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", fs_devices->fsid); 1818f93c3997SDavid Sterba if (kobject_rename(&fs_devices->fsid_kobj, fsid_buf)) 1819f93c3997SDavid Sterba btrfs_warn(fs_devices->fs_info, 1820f93c3997SDavid Sterba "sysfs: failed to create fsid for sprout"); 1821f93c3997SDavid Sterba } 1822f93c3997SDavid Sterba 1823668e48afSAnand Jain void btrfs_sysfs_update_devid(struct btrfs_device *device) 1824668e48afSAnand Jain { 1825668e48afSAnand Jain char tmp[24]; 1826668e48afSAnand Jain 1827668e48afSAnand Jain snprintf(tmp, sizeof(tmp), "%llu", device->devid); 1828668e48afSAnand Jain 1829668e48afSAnand Jain if (kobject_rename(&device->devid_kobj, tmp)) 1830668e48afSAnand Jain btrfs_warn(device->fs_devices->fs_info, 1831668e48afSAnand Jain "sysfs: failed to update devid for %llu", 1832668e48afSAnand Jain device->devid); 1833668e48afSAnand Jain } 1834668e48afSAnand Jain 1835510d7360SJeff Mahoney /* /sys/fs/btrfs/ entry */ 1836510d7360SJeff Mahoney static struct kset *btrfs_kset; 1837510d7360SJeff Mahoney 183872059215SAnand Jain /* 1839c6761a9eSAnand Jain * Creates: 1840c6761a9eSAnand Jain * /sys/fs/btrfs/UUID 1841c6761a9eSAnand Jain * 184272059215SAnand Jain * Can be called by the device discovery thread. 184372059215SAnand Jain */ 1844c6761a9eSAnand Jain int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs) 18455ac1d209SJeff Mahoney { 18465ac1d209SJeff Mahoney int error; 18475ac1d209SJeff Mahoney 18482e7910d6SAnand Jain init_completion(&fs_devs->kobj_unregister); 1849c1b7e474SAnand Jain fs_devs->fsid_kobj.kset = btrfs_kset; 1850c6761a9eSAnand Jain error = kobject_init_and_add(&fs_devs->fsid_kobj, &btrfs_ktype, NULL, 1851c6761a9eSAnand Jain "%pU", fs_devs->fsid); 1852e3277335STobin C. Harding if (error) { 1853e3277335STobin C. Harding kobject_put(&fs_devs->fsid_kobj); 185472059215SAnand Jain return error; 185572059215SAnand Jain } 185672059215SAnand Jain 1857bc036bb3SAnand Jain fs_devs->devices_kobj = kobject_create_and_add("devices", 1858bc036bb3SAnand Jain &fs_devs->fsid_kobj); 1859bc036bb3SAnand Jain if (!fs_devs->devices_kobj) { 1860bc036bb3SAnand Jain btrfs_err(fs_devs->fs_info, 1861bc036bb3SAnand Jain "failed to init sysfs device interface"); 18621f6087e6SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1863bc036bb3SAnand Jain return -ENOMEM; 1864bc036bb3SAnand Jain } 1865bc036bb3SAnand Jain 1866a013d141SAnand Jain fs_devs->devinfo_kobj = kobject_create_and_add("devinfo", 1867a013d141SAnand Jain &fs_devs->fsid_kobj); 1868a013d141SAnand Jain if (!fs_devs->devinfo_kobj) { 1869a013d141SAnand Jain btrfs_err(fs_devs->fs_info, 1870a013d141SAnand Jain "failed to init sysfs devinfo kobject"); 1871a013d141SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1872a013d141SAnand Jain return -ENOMEM; 1873a013d141SAnand Jain } 1874a013d141SAnand Jain 1875e3277335STobin C. Harding return 0; 1876e3277335STobin C. Harding } 1877e3277335STobin C. Harding 187896f3136eSAnand Jain int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info) 187972059215SAnand Jain { 188072059215SAnand Jain int error; 18812e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = fs_info->fs_devices; 1882c1b7e474SAnand Jain struct kobject *fsid_kobj = &fs_devs->fsid_kobj; 188372059215SAnand Jain 1884cd36da2eSAnand Jain error = btrfs_sysfs_add_fs_devices(fs_devs); 1885e453d989SJeff Mahoney if (error) 1886e453d989SJeff Mahoney return error; 1887510d7360SJeff Mahoney 1888c1b7e474SAnand Jain error = sysfs_create_files(fsid_kobj, btrfs_attrs); 1889e453d989SJeff Mahoney if (error) { 189053f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devs); 1891e453d989SJeff Mahoney return error; 1892e453d989SJeff Mahoney } 189379da4fa4SJeff Mahoney 1894c1b7e474SAnand Jain error = sysfs_create_group(fsid_kobj, 18950dd2906fSAnand Jain &btrfs_feature_attr_group); 18960dd2906fSAnand Jain if (error) 18970dd2906fSAnand Jain goto failure; 18980dd2906fSAnand Jain 18996e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 190093945cb4SDennis Zhou fs_info->debug_kobj = kobject_create_and_add("debug", fsid_kobj); 190193945cb4SDennis Zhou if (!fs_info->debug_kobj) { 190293945cb4SDennis Zhou error = -ENOMEM; 190393945cb4SDennis Zhou goto failure; 190493945cb4SDennis Zhou } 190593945cb4SDennis Zhou 190693945cb4SDennis Zhou error = sysfs_create_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 19076e369febSDavid Sterba if (error) 19086e369febSDavid Sterba goto failure; 1909e4faab84SDennis Zhou 1910e4faab84SDennis Zhou /* Discard directory */ 1911e4faab84SDennis Zhou fs_info->discard_debug_kobj = kobject_create_and_add("discard", 1912e4faab84SDennis Zhou fs_info->debug_kobj); 1913e4faab84SDennis Zhou if (!fs_info->discard_debug_kobj) { 1914e4faab84SDennis Zhou error = -ENOMEM; 1915e4faab84SDennis Zhou goto failure; 1916e4faab84SDennis Zhou } 1917e4faab84SDennis Zhou 1918e4faab84SDennis Zhou error = sysfs_create_files(fs_info->discard_debug_kobj, 1919e4faab84SDennis Zhou discard_debug_attrs); 1920e4faab84SDennis Zhou if (error) 1921e4faab84SDennis Zhou goto failure; 19226e369febSDavid Sterba #endif 19236e369febSDavid Sterba 1924e453d989SJeff Mahoney error = addrm_unknown_feature_attrs(fs_info, true); 192579da4fa4SJeff Mahoney if (error) 192679da4fa4SJeff Mahoney goto failure; 192779da4fa4SJeff Mahoney 19283092c68fSNikolay Borisov error = sysfs_create_link(fsid_kobj, &fs_info->sb->s_bdi->dev->kobj, "bdi"); 19293092c68fSNikolay Borisov if (error) 19303092c68fSNikolay Borisov goto failure; 19313092c68fSNikolay Borisov 19326ab0a202SJeff Mahoney fs_info->space_info_kobj = kobject_create_and_add("allocation", 1933c1b7e474SAnand Jain fsid_kobj); 19346ab0a202SJeff Mahoney if (!fs_info->space_info_kobj) { 19356ab0a202SJeff Mahoney error = -ENOMEM; 19366ab0a202SJeff Mahoney goto failure; 19376ab0a202SJeff Mahoney } 19386ab0a202SJeff Mahoney 19396ab0a202SJeff Mahoney error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs); 19406ab0a202SJeff Mahoney if (error) 19416ab0a202SJeff Mahoney goto failure; 19426ab0a202SJeff Mahoney 194379da4fa4SJeff Mahoney return 0; 194479da4fa4SJeff Mahoney failure: 19456618a59bSAnand Jain btrfs_sysfs_remove_mounted(fs_info); 19465ac1d209SJeff Mahoney return error; 19475ac1d209SJeff Mahoney } 19485ac1d209SJeff Mahoney 194949e5fb46SQu Wenruo static inline struct btrfs_fs_info *qgroup_kobj_to_fs_info(struct kobject *kobj) 195049e5fb46SQu Wenruo { 195149e5fb46SQu Wenruo return to_fs_info(kobj->parent->parent); 195249e5fb46SQu Wenruo } 195349e5fb46SQu Wenruo 195449e5fb46SQu Wenruo #define QGROUP_ATTR(_member, _show_name) \ 195549e5fb46SQu Wenruo static ssize_t btrfs_qgroup_show_##_member(struct kobject *qgroup_kobj, \ 195649e5fb46SQu Wenruo struct kobj_attribute *a, \ 195749e5fb46SQu Wenruo char *buf) \ 195849e5fb46SQu Wenruo { \ 195949e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 196049e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 196149e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 196249e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->_member, &fs_info->qgroup_lock, buf); \ 196349e5fb46SQu Wenruo } \ 196449e5fb46SQu Wenruo BTRFS_ATTR(qgroup, _show_name, btrfs_qgroup_show_##_member) 196549e5fb46SQu Wenruo 196649e5fb46SQu Wenruo #define QGROUP_RSV_ATTR(_name, _type) \ 196749e5fb46SQu Wenruo static ssize_t btrfs_qgroup_rsv_show_##_name(struct kobject *qgroup_kobj, \ 196849e5fb46SQu Wenruo struct kobj_attribute *a, \ 196949e5fb46SQu Wenruo char *buf) \ 197049e5fb46SQu Wenruo { \ 197149e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 197249e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 197349e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 197449e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->rsv.values[_type], \ 197549e5fb46SQu Wenruo &fs_info->qgroup_lock, buf); \ 197649e5fb46SQu Wenruo } \ 197749e5fb46SQu Wenruo BTRFS_ATTR(qgroup, rsv_##_name, btrfs_qgroup_rsv_show_##_name) 197849e5fb46SQu Wenruo 197949e5fb46SQu Wenruo QGROUP_ATTR(rfer, referenced); 198049e5fb46SQu Wenruo QGROUP_ATTR(excl, exclusive); 198149e5fb46SQu Wenruo QGROUP_ATTR(max_rfer, max_referenced); 198249e5fb46SQu Wenruo QGROUP_ATTR(max_excl, max_exclusive); 198349e5fb46SQu Wenruo QGROUP_ATTR(lim_flags, limit_flags); 198449e5fb46SQu Wenruo QGROUP_RSV_ATTR(data, BTRFS_QGROUP_RSV_DATA); 198549e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_pertrans, BTRFS_QGROUP_RSV_META_PERTRANS); 198649e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_prealloc, BTRFS_QGROUP_RSV_META_PREALLOC); 198749e5fb46SQu Wenruo 1988e7849e33SAnand Jain /* 1989e7849e33SAnand Jain * Qgroup information. 1990e7849e33SAnand Jain * 1991e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/qgroups/<level>_<qgroupid>/ 1992e7849e33SAnand Jain */ 199349e5fb46SQu Wenruo static struct attribute *qgroup_attrs[] = { 199449e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, referenced), 199549e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, exclusive), 199649e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_referenced), 199749e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_exclusive), 199849e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, limit_flags), 199949e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_data), 200049e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_pertrans), 200149e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_prealloc), 200249e5fb46SQu Wenruo NULL 200349e5fb46SQu Wenruo }; 200449e5fb46SQu Wenruo ATTRIBUTE_GROUPS(qgroup); 200549e5fb46SQu Wenruo 200649e5fb46SQu Wenruo static void qgroup_release(struct kobject *kobj) 200749e5fb46SQu Wenruo { 200849e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(kobj, struct btrfs_qgroup, kobj); 200949e5fb46SQu Wenruo 201049e5fb46SQu Wenruo memset(&qgroup->kobj, 0, sizeof(*kobj)); 201149e5fb46SQu Wenruo } 201249e5fb46SQu Wenruo 201349e5fb46SQu Wenruo static struct kobj_type qgroup_ktype = { 201449e5fb46SQu Wenruo .sysfs_ops = &kobj_sysfs_ops, 201549e5fb46SQu Wenruo .release = qgroup_release, 201649e5fb46SQu Wenruo .default_groups = qgroup_groups, 201749e5fb46SQu Wenruo }; 201849e5fb46SQu Wenruo 201949e5fb46SQu Wenruo int btrfs_sysfs_add_one_qgroup(struct btrfs_fs_info *fs_info, 202049e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 202149e5fb46SQu Wenruo { 202249e5fb46SQu Wenruo struct kobject *qgroups_kobj = fs_info->qgroups_kobj; 202349e5fb46SQu Wenruo int ret; 202449e5fb46SQu Wenruo 202549e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 202649e5fb46SQu Wenruo return 0; 202749e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) 202849e5fb46SQu Wenruo return 0; 202949e5fb46SQu Wenruo if (!qgroups_kobj) 203049e5fb46SQu Wenruo return -EINVAL; 203149e5fb46SQu Wenruo 203249e5fb46SQu Wenruo ret = kobject_init_and_add(&qgroup->kobj, &qgroup_ktype, qgroups_kobj, 203349e5fb46SQu Wenruo "%hu_%llu", btrfs_qgroup_level(qgroup->qgroupid), 203449e5fb46SQu Wenruo btrfs_qgroup_subvolid(qgroup->qgroupid)); 203549e5fb46SQu Wenruo if (ret < 0) 203649e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 203749e5fb46SQu Wenruo 203849e5fb46SQu Wenruo return ret; 203949e5fb46SQu Wenruo } 204049e5fb46SQu Wenruo 204149e5fb46SQu Wenruo void btrfs_sysfs_del_qgroups(struct btrfs_fs_info *fs_info) 204249e5fb46SQu Wenruo { 204349e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 204449e5fb46SQu Wenruo struct btrfs_qgroup *next; 204549e5fb46SQu Wenruo 204649e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 204749e5fb46SQu Wenruo return; 204849e5fb46SQu Wenruo 204949e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 205049e5fb46SQu Wenruo &fs_info->qgroup_tree, node) 205149e5fb46SQu Wenruo btrfs_sysfs_del_one_qgroup(fs_info, qgroup); 205262ab2cc0SQu Wenruo if (fs_info->qgroups_kobj) { 205349e5fb46SQu Wenruo kobject_del(fs_info->qgroups_kobj); 205449e5fb46SQu Wenruo kobject_put(fs_info->qgroups_kobj); 205549e5fb46SQu Wenruo fs_info->qgroups_kobj = NULL; 205649e5fb46SQu Wenruo } 205762ab2cc0SQu Wenruo } 205849e5fb46SQu Wenruo 205949e5fb46SQu Wenruo /* Called when qgroups get initialized, thus there is no need for locking */ 206049e5fb46SQu Wenruo int btrfs_sysfs_add_qgroups(struct btrfs_fs_info *fs_info) 206149e5fb46SQu Wenruo { 206249e5fb46SQu Wenruo struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 206349e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 206449e5fb46SQu Wenruo struct btrfs_qgroup *next; 206549e5fb46SQu Wenruo int ret = 0; 206649e5fb46SQu Wenruo 206749e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 206849e5fb46SQu Wenruo return 0; 206949e5fb46SQu Wenruo 207049e5fb46SQu Wenruo ASSERT(fsid_kobj); 207149e5fb46SQu Wenruo if (fs_info->qgroups_kobj) 207249e5fb46SQu Wenruo return 0; 207349e5fb46SQu Wenruo 207449e5fb46SQu Wenruo fs_info->qgroups_kobj = kobject_create_and_add("qgroups", fsid_kobj); 207549e5fb46SQu Wenruo if (!fs_info->qgroups_kobj) { 207649e5fb46SQu Wenruo ret = -ENOMEM; 207749e5fb46SQu Wenruo goto out; 207849e5fb46SQu Wenruo } 207949e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 208049e5fb46SQu Wenruo &fs_info->qgroup_tree, node) { 208149e5fb46SQu Wenruo ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup); 208249e5fb46SQu Wenruo if (ret < 0) 208349e5fb46SQu Wenruo goto out; 208449e5fb46SQu Wenruo } 208549e5fb46SQu Wenruo 208649e5fb46SQu Wenruo out: 208749e5fb46SQu Wenruo if (ret < 0) 208849e5fb46SQu Wenruo btrfs_sysfs_del_qgroups(fs_info); 208949e5fb46SQu Wenruo return ret; 209049e5fb46SQu Wenruo } 209149e5fb46SQu Wenruo 209249e5fb46SQu Wenruo void btrfs_sysfs_del_one_qgroup(struct btrfs_fs_info *fs_info, 209349e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 209449e5fb46SQu Wenruo { 209549e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 209649e5fb46SQu Wenruo return; 209749e5fb46SQu Wenruo 209849e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) { 209949e5fb46SQu Wenruo kobject_del(&qgroup->kobj); 210049e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 210149e5fb46SQu Wenruo } 210249e5fb46SQu Wenruo } 2103444e7516SDavid Sterba 2104444e7516SDavid Sterba /* 2105444e7516SDavid Sterba * Change per-fs features in /sys/fs/btrfs/UUID/features to match current 2106444e7516SDavid Sterba * values in superblock. Call after any changes to incompat/compat_ro flags 2107444e7516SDavid Sterba */ 2108444e7516SDavid Sterba void btrfs_sysfs_feature_update(struct btrfs_fs_info *fs_info, 2109444e7516SDavid Sterba u64 bit, enum btrfs_feature_set set) 2110444e7516SDavid Sterba { 2111444e7516SDavid Sterba struct btrfs_fs_devices *fs_devs; 2112444e7516SDavid Sterba struct kobject *fsid_kobj; 211324646481SLeon Romanovsky u64 __maybe_unused features; 211424646481SLeon Romanovsky int __maybe_unused ret; 2115444e7516SDavid Sterba 2116444e7516SDavid Sterba if (!fs_info) 2117444e7516SDavid Sterba return; 2118444e7516SDavid Sterba 211924646481SLeon Romanovsky /* 212024646481SLeon Romanovsky * See 14e46e04958df74 and e410e34fad913dd, feature bit updates are not 212124646481SLeon Romanovsky * safe when called from some contexts (eg. balance) 212224646481SLeon Romanovsky */ 2123444e7516SDavid Sterba features = get_features(fs_info, set); 2124444e7516SDavid Sterba ASSERT(bit & supported_feature_masks[set]); 2125444e7516SDavid Sterba 2126444e7516SDavid Sterba fs_devs = fs_info->fs_devices; 2127444e7516SDavid Sterba fsid_kobj = &fs_devs->fsid_kobj; 2128444e7516SDavid Sterba 2129bf609206SDavid Sterba if (!fsid_kobj->state_initialized) 2130bf609206SDavid Sterba return; 2131bf609206SDavid Sterba 2132444e7516SDavid Sterba /* 2133444e7516SDavid Sterba * FIXME: this is too heavy to update just one value, ideally we'd like 2134444e7516SDavid Sterba * to use sysfs_update_group but some refactoring is needed first. 2135444e7516SDavid Sterba */ 2136444e7516SDavid Sterba sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 2137444e7516SDavid Sterba ret = sysfs_create_group(fsid_kobj, &btrfs_feature_attr_group); 2138444e7516SDavid Sterba } 2139444e7516SDavid Sterba 2140f5c29bd9SLiu Bo int __init btrfs_init_sysfs(void) 214158176a96SJosef Bacik { 2142079b72bcSJeff Mahoney int ret; 21431bae3098SDavid Sterba 2144e3fe4e71SGreg KH btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); 2145e3fe4e71SGreg KH if (!btrfs_kset) 2146e3fe4e71SGreg KH return -ENOMEM; 2147079b72bcSJeff Mahoney 21481bae3098SDavid Sterba init_feature_attrs(); 21491bae3098SDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2150001a648dSFilipe Manana if (ret) 2151001a648dSFilipe Manana goto out2; 2152f902bd3aSMisono Tomohiro ret = sysfs_merge_group(&btrfs_kset->kobj, 2153f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2154f902bd3aSMisono Tomohiro if (ret) 2155f902bd3aSMisono Tomohiro goto out_remove_group; 2156001a648dSFilipe Manana 21576e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 21586e369febSDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 21596e369febSDavid Sterba if (ret) 21606e369febSDavid Sterba goto out2; 21616e369febSDavid Sterba #endif 21626e369febSDavid Sterba 2163001a648dSFilipe Manana return 0; 2164f902bd3aSMisono Tomohiro 2165f902bd3aSMisono Tomohiro out_remove_group: 2166f902bd3aSMisono Tomohiro sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2167001a648dSFilipe Manana out2: 2168001a648dSFilipe Manana kset_unregister(btrfs_kset); 21691bae3098SDavid Sterba 21701bae3098SDavid Sterba return ret; 217158176a96SJosef Bacik } 217258176a96SJosef Bacik 2173e67c718bSDavid Sterba void __cold btrfs_exit_sysfs(void) 217458176a96SJosef Bacik { 2175f902bd3aSMisono Tomohiro sysfs_unmerge_group(&btrfs_kset->kobj, 2176f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2177079b72bcSJeff Mahoney sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 217871e8978eSDennis Zhou #ifdef CONFIG_BTRFS_DEBUG 217971e8978eSDennis Zhou sysfs_remove_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 218071e8978eSDennis Zhou #endif 2181e3fe4e71SGreg KH kset_unregister(btrfs_kset); 218258176a96SJosef Bacik } 218355d47414SChris Mason 2184