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" 2419fc516aSStefan 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 65*22c55e3bSStefan Roesch #define BTRFS_ATTR_W(_prefix, _name, _store) \ 66*22c55e3bSStefan Roesch static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 67*22c55e3bSStefan Roesch __INIT_KOBJ_ATTR(_name, 0200, NULL, _store) 68*22c55e3bSStefan Roesch 699188db61SDavid Sterba #define BTRFS_ATTR_RW(_prefix, _name, _show, _store) \ 709188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 719188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0644, _show, _store) 729188db61SDavid Sterba 739188db61SDavid Sterba #define BTRFS_ATTR(_prefix, _name, _show) \ 749188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 759188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0444, _show, NULL) 769188db61SDavid Sterba 779188db61SDavid Sterba #define BTRFS_ATTR_PTR(_prefix, _name) \ 789188db61SDavid Sterba (&btrfs_attr_##_prefix##_##_name.attr) 799188db61SDavid Sterba 809188db61SDavid Sterba #define BTRFS_FEAT_ATTR(_name, _feature_set, _feature_prefix, _feature_bit) \ 819188db61SDavid Sterba static struct btrfs_feature_attr btrfs_attr_features_##_name = { \ 829188db61SDavid Sterba .kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO, \ 839188db61SDavid Sterba btrfs_feature_attr_show, \ 849188db61SDavid Sterba btrfs_feature_attr_store), \ 859188db61SDavid Sterba .feature_set = _feature_set, \ 869188db61SDavid Sterba .feature_bit = _feature_prefix ##_## _feature_bit, \ 879188db61SDavid Sterba } 889188db61SDavid Sterba #define BTRFS_FEAT_ATTR_PTR(_name) \ 899188db61SDavid Sterba (&btrfs_attr_features_##_name.kobj_attr.attr) 909188db61SDavid Sterba 919188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT(name, feature) \ 929188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT, BTRFS_FEATURE_COMPAT, feature) 939188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT_RO(name, feature) \ 949188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT_RO, BTRFS_FEATURE_COMPAT_RO, feature) 959188db61SDavid Sterba #define BTRFS_FEAT_ATTR_INCOMPAT(name, feature) \ 969188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_INCOMPAT, BTRFS_FEATURE_INCOMPAT, feature) 979188db61SDavid Sterba 98510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); 992e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj); 10019fc516aSStefan Roesch static struct kobject *get_btrfs_kobj(struct kobject *kobj); 1015ac1d209SJeff Mahoney 1028f52316cSDavid Sterba static struct btrfs_feature_attr *to_btrfs_feature_attr(struct kobj_attribute *a) 1038f52316cSDavid Sterba { 1048f52316cSDavid Sterba return container_of(a, struct btrfs_feature_attr, kobj_attr); 1058f52316cSDavid Sterba } 1068f52316cSDavid Sterba 1078f52316cSDavid Sterba static struct kobj_attribute *attr_to_btrfs_attr(struct attribute *attr) 1088f52316cSDavid Sterba { 1098f52316cSDavid Sterba return container_of(attr, struct kobj_attribute, attr); 1108f52316cSDavid Sterba } 1118f52316cSDavid Sterba 1128f52316cSDavid Sterba static struct btrfs_feature_attr *attr_to_btrfs_feature_attr( 1138f52316cSDavid Sterba struct attribute *attr) 1148f52316cSDavid Sterba { 1158f52316cSDavid Sterba return to_btrfs_feature_attr(attr_to_btrfs_attr(attr)); 1168f52316cSDavid Sterba } 1178f52316cSDavid Sterba 118510d7360SJeff Mahoney static u64 get_features(struct btrfs_fs_info *fs_info, 119510d7360SJeff Mahoney enum btrfs_feature_set set) 1205ac1d209SJeff Mahoney { 121510d7360SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 122510d7360SJeff Mahoney if (set == FEAT_COMPAT) 123510d7360SJeff Mahoney return btrfs_super_compat_flags(disk_super); 124510d7360SJeff Mahoney else if (set == FEAT_COMPAT_RO) 125510d7360SJeff Mahoney return btrfs_super_compat_ro_flags(disk_super); 126510d7360SJeff Mahoney else 127510d7360SJeff Mahoney return btrfs_super_incompat_flags(disk_super); 1285ac1d209SJeff Mahoney } 1295ac1d209SJeff Mahoney 130ba631941SJeff Mahoney static void set_features(struct btrfs_fs_info *fs_info, 131ba631941SJeff Mahoney enum btrfs_feature_set set, u64 features) 132ba631941SJeff Mahoney { 133ba631941SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 134ba631941SJeff Mahoney if (set == FEAT_COMPAT) 135ba631941SJeff Mahoney btrfs_set_super_compat_flags(disk_super, features); 136ba631941SJeff Mahoney else if (set == FEAT_COMPAT_RO) 137ba631941SJeff Mahoney btrfs_set_super_compat_ro_flags(disk_super, features); 138ba631941SJeff Mahoney else 139ba631941SJeff Mahoney btrfs_set_super_incompat_flags(disk_super, features); 140ba631941SJeff Mahoney } 141ba631941SJeff Mahoney 142ba631941SJeff Mahoney static int can_modify_feature(struct btrfs_feature_attr *fa) 143ba631941SJeff Mahoney { 144ba631941SJeff Mahoney int val = 0; 145ba631941SJeff Mahoney u64 set, clear; 146ba631941SJeff Mahoney switch (fa->feature_set) { 147ba631941SJeff Mahoney case FEAT_COMPAT: 148ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 149ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 150ba631941SJeff Mahoney break; 151ba631941SJeff Mahoney case FEAT_COMPAT_RO: 152ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 153ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 154ba631941SJeff Mahoney break; 155ba631941SJeff Mahoney case FEAT_INCOMPAT: 156ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 157ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 158ba631941SJeff Mahoney break; 159ba631941SJeff Mahoney default: 16062e85577SJeff Mahoney pr_warn("btrfs: sysfs: unknown feature set %d\n", 161cc37bb04SDavid Sterba fa->feature_set); 162cc37bb04SDavid Sterba return 0; 163ba631941SJeff Mahoney } 164ba631941SJeff Mahoney 165ba631941SJeff Mahoney if (set & fa->feature_bit) 166ba631941SJeff Mahoney val |= 1; 167ba631941SJeff Mahoney if (clear & fa->feature_bit) 168ba631941SJeff Mahoney val |= 2; 169ba631941SJeff Mahoney 170ba631941SJeff Mahoney return val; 171ba631941SJeff Mahoney } 172ba631941SJeff Mahoney 173079b72bcSJeff Mahoney static ssize_t btrfs_feature_attr_show(struct kobject *kobj, 174079b72bcSJeff Mahoney struct kobj_attribute *a, char *buf) 175079b72bcSJeff Mahoney { 176510d7360SJeff Mahoney int val = 0; 177510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 178510d7360SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 179ba631941SJeff Mahoney if (fs_info) { 180510d7360SJeff Mahoney u64 features = get_features(fs_info, fa->feature_set); 181510d7360SJeff Mahoney if (features & fa->feature_bit) 182510d7360SJeff Mahoney val = 1; 183ba631941SJeff Mahoney } else 184ba631941SJeff Mahoney val = can_modify_feature(fa); 185510d7360SJeff Mahoney 186020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 187510d7360SJeff Mahoney } 188510d7360SJeff Mahoney 189ba631941SJeff Mahoney static ssize_t btrfs_feature_attr_store(struct kobject *kobj, 190ba631941SJeff Mahoney struct kobj_attribute *a, 191ba631941SJeff Mahoney const char *buf, size_t count) 192ba631941SJeff Mahoney { 193ba631941SJeff Mahoney struct btrfs_fs_info *fs_info; 194ba631941SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 195ba631941SJeff Mahoney u64 features, set, clear; 196ba631941SJeff Mahoney unsigned long val; 197ba631941SJeff Mahoney int ret; 198ba631941SJeff Mahoney 199ba631941SJeff Mahoney fs_info = to_fs_info(kobj); 200ba631941SJeff Mahoney if (!fs_info) 201ba631941SJeff Mahoney return -EPERM; 202ba631941SJeff Mahoney 203bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 204ee611138SDavid Sterba return -EROFS; 205ee611138SDavid Sterba 206ba631941SJeff Mahoney ret = kstrtoul(skip_spaces(buf), 0, &val); 207ba631941SJeff Mahoney if (ret) 208ba631941SJeff Mahoney return ret; 209ba631941SJeff Mahoney 210ba631941SJeff Mahoney if (fa->feature_set == FEAT_COMPAT) { 211ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 212ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 213ba631941SJeff Mahoney } else if (fa->feature_set == FEAT_COMPAT_RO) { 214ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 215ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 216ba631941SJeff Mahoney } else { 217ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 218ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 219ba631941SJeff Mahoney } 220ba631941SJeff Mahoney 221ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 222ba631941SJeff Mahoney 223ba631941SJeff Mahoney /* Nothing to do */ 224ba631941SJeff Mahoney if ((val && (features & fa->feature_bit)) || 225ba631941SJeff Mahoney (!val && !(features & fa->feature_bit))) 226ba631941SJeff Mahoney return count; 227ba631941SJeff Mahoney 228ba631941SJeff Mahoney if ((val && !(set & fa->feature_bit)) || 229ba631941SJeff Mahoney (!val && !(clear & fa->feature_bit))) { 230ba631941SJeff Mahoney btrfs_info(fs_info, 231ba631941SJeff Mahoney "%sabling feature %s on mounted fs is not supported.", 232ba631941SJeff Mahoney val ? "En" : "Dis", fa->kobj_attr.attr.name); 233ba631941SJeff Mahoney return -EPERM; 234ba631941SJeff Mahoney } 235ba631941SJeff Mahoney 236ba631941SJeff Mahoney btrfs_info(fs_info, "%s %s feature flag", 237ba631941SJeff Mahoney val ? "Setting" : "Clearing", fa->kobj_attr.attr.name); 238ba631941SJeff Mahoney 239ba631941SJeff Mahoney spin_lock(&fs_info->super_lock); 240ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 241ba631941SJeff Mahoney if (val) 242ba631941SJeff Mahoney features |= fa->feature_bit; 243ba631941SJeff Mahoney else 244ba631941SJeff Mahoney features &= ~fa->feature_bit; 245ba631941SJeff Mahoney set_features(fs_info, fa->feature_set, features); 246ba631941SJeff Mahoney spin_unlock(&fs_info->super_lock); 247ba631941SJeff Mahoney 2480eae2747SDavid Sterba /* 2490eae2747SDavid Sterba * We don't want to do full transaction commit from inside sysfs 2500eae2747SDavid Sterba */ 2510eae2747SDavid Sterba btrfs_set_pending(fs_info, COMMIT); 2520eae2747SDavid Sterba wake_up_process(fs_info->transaction_kthread); 253ba631941SJeff Mahoney 254ba631941SJeff Mahoney return count; 255ba631941SJeff Mahoney } 256ba631941SJeff Mahoney 257510d7360SJeff Mahoney static umode_t btrfs_feature_visible(struct kobject *kobj, 258510d7360SJeff Mahoney struct attribute *attr, int unused) 259510d7360SJeff Mahoney { 260510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 261510d7360SJeff Mahoney umode_t mode = attr->mode; 262510d7360SJeff Mahoney 263510d7360SJeff Mahoney if (fs_info) { 264510d7360SJeff Mahoney struct btrfs_feature_attr *fa; 265510d7360SJeff Mahoney u64 features; 266510d7360SJeff Mahoney 267510d7360SJeff Mahoney fa = attr_to_btrfs_feature_attr(attr); 268510d7360SJeff Mahoney features = get_features(fs_info, fa->feature_set); 269510d7360SJeff Mahoney 270ba631941SJeff Mahoney if (can_modify_feature(fa)) 271ba631941SJeff Mahoney mode |= S_IWUSR; 272ba631941SJeff Mahoney else if (!(features & fa->feature_bit)) 273510d7360SJeff Mahoney mode = 0; 274510d7360SJeff Mahoney } 275510d7360SJeff Mahoney 276510d7360SJeff Mahoney return mode; 277079b72bcSJeff Mahoney } 278079b72bcSJeff Mahoney 279079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_backref, MIXED_BACKREF); 280079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL); 281079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS); 282079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO); 2835c1aab1dSNick Terrell BTRFS_FEAT_ATTR_INCOMPAT(compress_zstd, COMPRESS_ZSTD); 284079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(big_metadata, BIG_METADATA); 285079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF); 286079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56); 287079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA); 288c736c095SDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES); 28956f20f40SNikolay Borisov BTRFS_FEAT_ATTR_INCOMPAT(metadata_uuid, METADATA_UUID); 2903b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE); 291cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(raid1c34, RAID1C34); 2927b3d5a90SNaohiro Aota #ifdef CONFIG_BTRFS_DEBUG 2932c7d2a23SJosef Bacik /* Remove once support for zoned allocation is feature complete */ 2947b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_INCOMPAT(zoned, ZONED); 2952c7d2a23SJosef Bacik /* Remove once support for extent tree v2 is feature complete */ 2962c7d2a23SJosef Bacik BTRFS_FEAT_ATTR_INCOMPAT(extent_tree_v2, EXTENT_TREE_V2); 2977b3d5a90SNaohiro Aota #endif 29814605409SBoris Burkov #ifdef CONFIG_FS_VERITY 29914605409SBoris Burkov BTRFS_FEAT_ATTR_COMPAT_RO(verity, VERITY); 30014605409SBoris Burkov #endif 301079b72bcSJeff Mahoney 302e7849e33SAnand Jain /* 303e7849e33SAnand Jain * Features which depend on feature bits and may differ between each fs. 304e7849e33SAnand Jain * 305143823cfSDavid Sterba * /sys/fs/btrfs/features - all available features implemented by this version 306e7849e33SAnand Jain * /sys/fs/btrfs/UUID/features - features of the fs which are enabled or 307e7849e33SAnand Jain * can be changed on a mounted filesystem. 308e7849e33SAnand Jain */ 309079b72bcSJeff Mahoney static struct attribute *btrfs_supported_feature_attrs[] = { 310079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_backref), 311079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(default_subvol), 312079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_groups), 313079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(compress_lzo), 3145c1aab1dSNick Terrell BTRFS_FEAT_ATTR_PTR(compress_zstd), 315079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(big_metadata), 316079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(extended_iref), 317079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(raid56), 318079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(skinny_metadata), 319c736c095SDavid Sterba BTRFS_FEAT_ATTR_PTR(no_holes), 32056f20f40SNikolay Borisov BTRFS_FEAT_ATTR_PTR(metadata_uuid), 3213b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_PTR(free_space_tree), 322cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_PTR(raid1c34), 3237b3d5a90SNaohiro Aota #ifdef CONFIG_BTRFS_DEBUG 3247b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_PTR(zoned), 3252c7d2a23SJosef Bacik BTRFS_FEAT_ATTR_PTR(extent_tree_v2), 3267b3d5a90SNaohiro Aota #endif 32714605409SBoris Burkov #ifdef CONFIG_FS_VERITY 32814605409SBoris Burkov BTRFS_FEAT_ATTR_PTR(verity), 32914605409SBoris Burkov #endif 330079b72bcSJeff Mahoney NULL 331079b72bcSJeff Mahoney }; 332079b72bcSJeff Mahoney 333079b72bcSJeff Mahoney static const struct attribute_group btrfs_feature_attr_group = { 334079b72bcSJeff Mahoney .name = "features", 335510d7360SJeff Mahoney .is_visible = btrfs_feature_visible, 336079b72bcSJeff Mahoney .attrs = btrfs_supported_feature_attrs, 337079b72bcSJeff Mahoney }; 33858176a96SJosef Bacik 339f902bd3aSMisono Tomohiro static ssize_t rmdir_subvol_show(struct kobject *kobj, 340f902bd3aSMisono Tomohiro struct kobj_attribute *ka, char *buf) 341f902bd3aSMisono Tomohiro { 342020e5277SAnand Jain return sysfs_emit(buf, "0\n"); 343f902bd3aSMisono Tomohiro } 344f902bd3aSMisono Tomohiro BTRFS_ATTR(static_feature, rmdir_subvol, rmdir_subvol_show); 345f902bd3aSMisono Tomohiro 346f7cea56cSDavid Sterba static ssize_t supported_checksums_show(struct kobject *kobj, 347f7cea56cSDavid Sterba struct kobj_attribute *a, char *buf) 348f7cea56cSDavid Sterba { 349f7cea56cSDavid Sterba ssize_t ret = 0; 350f7cea56cSDavid Sterba int i; 351f7cea56cSDavid Sterba 352f7cea56cSDavid Sterba for (i = 0; i < btrfs_get_num_csums(); i++) { 353f7cea56cSDavid Sterba /* 354f7cea56cSDavid Sterba * This "trick" only works as long as 'enum btrfs_csum_type' has 355f7cea56cSDavid Sterba * no holes in it 356f7cea56cSDavid Sterba */ 357020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i == 0 ? "" : " "), 358020e5277SAnand Jain btrfs_super_csum_name(i)); 359f7cea56cSDavid Sterba 360f7cea56cSDavid Sterba } 361f7cea56cSDavid Sterba 362020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 363f7cea56cSDavid Sterba return ret; 364f7cea56cSDavid Sterba } 365f7cea56cSDavid Sterba BTRFS_ATTR(static_feature, supported_checksums, supported_checksums_show); 366f7cea56cSDavid Sterba 3677573df55SOmar Sandoval static ssize_t send_stream_version_show(struct kobject *kobj, 3687573df55SOmar Sandoval struct kobj_attribute *ka, char *buf) 3697573df55SOmar Sandoval { 370020e5277SAnand Jain return sysfs_emit(buf, "%d\n", BTRFS_SEND_STREAM_VERSION); 3717573df55SOmar Sandoval } 3727573df55SOmar Sandoval BTRFS_ATTR(static_feature, send_stream_version, send_stream_version_show); 3737573df55SOmar Sandoval 374ceafe3ccSJosef Bacik static const char *rescue_opts[] = { 375ceafe3ccSJosef Bacik "usebackuproot", 376ceafe3ccSJosef Bacik "nologreplay", 37742437a63SJosef Bacik "ignorebadroots", 378882dbe0cSJosef Bacik "ignoredatacsums", 3799037d3cbSJosef Bacik "all", 380ceafe3ccSJosef Bacik }; 381ceafe3ccSJosef Bacik 382ceafe3ccSJosef Bacik static ssize_t supported_rescue_options_show(struct kobject *kobj, 383ceafe3ccSJosef Bacik struct kobj_attribute *a, 384ceafe3ccSJosef Bacik char *buf) 385ceafe3ccSJosef Bacik { 386ceafe3ccSJosef Bacik ssize_t ret = 0; 387ceafe3ccSJosef Bacik int i; 388ceafe3ccSJosef Bacik 389ceafe3ccSJosef Bacik for (i = 0; i < ARRAY_SIZE(rescue_opts); i++) 390020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i ? " " : ""), rescue_opts[i]); 391020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 392ceafe3ccSJosef Bacik return ret; 393ceafe3ccSJosef Bacik } 394ceafe3ccSJosef Bacik BTRFS_ATTR(static_feature, supported_rescue_options, 395ceafe3ccSJosef Bacik supported_rescue_options_show); 396ceafe3ccSJosef Bacik 397fc57ad8dSQu Wenruo static ssize_t supported_sectorsizes_show(struct kobject *kobj, 398fc57ad8dSQu Wenruo struct kobj_attribute *a, 399fc57ad8dSQu Wenruo char *buf) 400fc57ad8dSQu Wenruo { 401fc57ad8dSQu Wenruo ssize_t ret = 0; 402fc57ad8dSQu Wenruo 4031a42daabSQu Wenruo /* An artificial limit to only support 4K and PAGE_SIZE */ 4041a42daabSQu Wenruo if (PAGE_SIZE > SZ_4K) 405020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%u ", SZ_4K); 406020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%lu\n", PAGE_SIZE); 407fc57ad8dSQu Wenruo 408fc57ad8dSQu Wenruo return ret; 409fc57ad8dSQu Wenruo } 410fc57ad8dSQu Wenruo BTRFS_ATTR(static_feature, supported_sectorsizes, 411fc57ad8dSQu Wenruo supported_sectorsizes_show); 412fc57ad8dSQu Wenruo 413e7849e33SAnand Jain /* 414e7849e33SAnand Jain * Features which only depend on kernel version. 415e7849e33SAnand Jain * 416e7849e33SAnand Jain * These are listed in /sys/fs/btrfs/features along with 417e7849e33SAnand Jain * btrfs_supported_feature_attrs. 418e7849e33SAnand Jain */ 419f902bd3aSMisono Tomohiro static struct attribute *btrfs_supported_static_feature_attrs[] = { 420f902bd3aSMisono Tomohiro BTRFS_ATTR_PTR(static_feature, rmdir_subvol), 421f7cea56cSDavid Sterba BTRFS_ATTR_PTR(static_feature, supported_checksums), 4227573df55SOmar Sandoval BTRFS_ATTR_PTR(static_feature, send_stream_version), 423ceafe3ccSJosef Bacik BTRFS_ATTR_PTR(static_feature, supported_rescue_options), 424fc57ad8dSQu Wenruo BTRFS_ATTR_PTR(static_feature, supported_sectorsizes), 425f902bd3aSMisono Tomohiro NULL 426f902bd3aSMisono Tomohiro }; 427f902bd3aSMisono Tomohiro 428f902bd3aSMisono Tomohiro static const struct attribute_group btrfs_static_feature_attr_group = { 429f902bd3aSMisono Tomohiro .name = "features", 430f902bd3aSMisono Tomohiro .attrs = btrfs_supported_static_feature_attrs, 431f902bd3aSMisono Tomohiro }; 432f902bd3aSMisono Tomohiro 4336e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 4346e369febSDavid Sterba 4356e369febSDavid Sterba /* 436e4faab84SDennis Zhou * Discard statistics and tunables 437e4faab84SDennis Zhou */ 438dfb79ddbSDennis Zhou #define discard_to_fs_info(_kobj) to_fs_info((_kobj)->parent->parent) 439dfb79ddbSDennis Zhou 4405dc7c10bSDennis Zhou static ssize_t btrfs_discardable_bytes_show(struct kobject *kobj, 4415dc7c10bSDennis Zhou struct kobj_attribute *a, 4425dc7c10bSDennis Zhou char *buf) 4435dc7c10bSDennis Zhou { 4445dc7c10bSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4455dc7c10bSDennis Zhou 446020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4475dc7c10bSDennis Zhou atomic64_read(&fs_info->discard_ctl.discardable_bytes)); 4485dc7c10bSDennis Zhou } 4495dc7c10bSDennis Zhou BTRFS_ATTR(discard, discardable_bytes, btrfs_discardable_bytes_show); 4505dc7c10bSDennis Zhou 451dfb79ddbSDennis Zhou static ssize_t btrfs_discardable_extents_show(struct kobject *kobj, 452dfb79ddbSDennis Zhou struct kobj_attribute *a, 453dfb79ddbSDennis Zhou char *buf) 454dfb79ddbSDennis Zhou { 455dfb79ddbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 456dfb79ddbSDennis Zhou 457020e5277SAnand Jain return sysfs_emit(buf, "%d\n", 458dfb79ddbSDennis Zhou atomic_read(&fs_info->discard_ctl.discardable_extents)); 459dfb79ddbSDennis Zhou } 460dfb79ddbSDennis Zhou BTRFS_ATTR(discard, discardable_extents, btrfs_discardable_extents_show); 461dfb79ddbSDennis Zhou 4629ddf648fSDennis Zhou static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj, 4639ddf648fSDennis Zhou struct kobj_attribute *a, 4649ddf648fSDennis Zhou char *buf) 4659ddf648fSDennis Zhou { 4669ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4679ddf648fSDennis Zhou 468020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4699ddf648fSDennis Zhou fs_info->discard_ctl.discard_bitmap_bytes); 4709ddf648fSDennis Zhou } 4719ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bitmap_bytes, btrfs_discard_bitmap_bytes_show); 4729ddf648fSDennis Zhou 4739ddf648fSDennis Zhou static ssize_t btrfs_discard_bytes_saved_show(struct kobject *kobj, 4749ddf648fSDennis Zhou struct kobj_attribute *a, 4759ddf648fSDennis Zhou char *buf) 4769ddf648fSDennis Zhou { 4779ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4789ddf648fSDennis Zhou 479020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4809ddf648fSDennis Zhou atomic64_read(&fs_info->discard_ctl.discard_bytes_saved)); 4819ddf648fSDennis Zhou } 4829ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bytes_saved, btrfs_discard_bytes_saved_show); 4839ddf648fSDennis Zhou 4849ddf648fSDennis Zhou static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj, 4859ddf648fSDennis Zhou struct kobj_attribute *a, 4869ddf648fSDennis Zhou char *buf) 4879ddf648fSDennis Zhou { 4889ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4899ddf648fSDennis Zhou 490020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4919ddf648fSDennis Zhou fs_info->discard_ctl.discard_extent_bytes); 4929ddf648fSDennis Zhou } 4939ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_extent_bytes, btrfs_discard_extent_bytes_show); 4949ddf648fSDennis Zhou 495a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_show(struct kobject *kobj, 496a2309300SDennis Zhou struct kobj_attribute *a, 497a2309300SDennis Zhou char *buf) 498a2309300SDennis Zhou { 499a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 500a2309300SDennis Zhou 501020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 502a2309300SDennis Zhou READ_ONCE(fs_info->discard_ctl.iops_limit)); 503a2309300SDennis Zhou } 504a2309300SDennis Zhou 505a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_store(struct kobject *kobj, 506a2309300SDennis Zhou struct kobj_attribute *a, 507a2309300SDennis Zhou const char *buf, size_t len) 508a2309300SDennis Zhou { 509a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 510a2309300SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 511a2309300SDennis Zhou u32 iops_limit; 512a2309300SDennis Zhou int ret; 513a2309300SDennis Zhou 514a2309300SDennis Zhou ret = kstrtou32(buf, 10, &iops_limit); 515a2309300SDennis Zhou if (ret) 516a2309300SDennis Zhou return -EINVAL; 517a2309300SDennis Zhou 518a2309300SDennis Zhou WRITE_ONCE(discard_ctl->iops_limit, iops_limit); 5193e48d8d2SPavel Begunkov btrfs_discard_calc_delay(discard_ctl); 5203e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 521a2309300SDennis Zhou return len; 522a2309300SDennis Zhou } 523a2309300SDennis Zhou BTRFS_ATTR_RW(discard, iops_limit, btrfs_discard_iops_limit_show, 524a2309300SDennis Zhou btrfs_discard_iops_limit_store); 525a2309300SDennis Zhou 526e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_show(struct kobject *kobj, 527e93591bbSDennis Zhou struct kobj_attribute *a, 528e93591bbSDennis Zhou char *buf) 529e93591bbSDennis Zhou { 530e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 531e93591bbSDennis Zhou 532020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 533e93591bbSDennis Zhou READ_ONCE(fs_info->discard_ctl.kbps_limit)); 534e93591bbSDennis Zhou } 535e93591bbSDennis Zhou 536e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_store(struct kobject *kobj, 537e93591bbSDennis Zhou struct kobj_attribute *a, 538e93591bbSDennis Zhou const char *buf, size_t len) 539e93591bbSDennis Zhou { 540e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 541e93591bbSDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 542e93591bbSDennis Zhou u32 kbps_limit; 543e93591bbSDennis Zhou int ret; 544e93591bbSDennis Zhou 545e93591bbSDennis Zhou ret = kstrtou32(buf, 10, &kbps_limit); 546e93591bbSDennis Zhou if (ret) 547e93591bbSDennis Zhou return -EINVAL; 548e93591bbSDennis Zhou 549e93591bbSDennis Zhou WRITE_ONCE(discard_ctl->kbps_limit, kbps_limit); 5503e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 551e93591bbSDennis Zhou return len; 552e93591bbSDennis Zhou } 553e93591bbSDennis Zhou BTRFS_ATTR_RW(discard, kbps_limit, btrfs_discard_kbps_limit_show, 554e93591bbSDennis Zhou btrfs_discard_kbps_limit_store); 555e93591bbSDennis Zhou 55619b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_show(struct kobject *kobj, 55719b2a2c7SDennis Zhou struct kobj_attribute *a, 55819b2a2c7SDennis Zhou char *buf) 55919b2a2c7SDennis Zhou { 56019b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 56119b2a2c7SDennis Zhou 562020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 56319b2a2c7SDennis Zhou READ_ONCE(fs_info->discard_ctl.max_discard_size)); 56419b2a2c7SDennis Zhou } 56519b2a2c7SDennis Zhou 56619b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_store(struct kobject *kobj, 56719b2a2c7SDennis Zhou struct kobj_attribute *a, 56819b2a2c7SDennis Zhou const char *buf, size_t len) 56919b2a2c7SDennis Zhou { 57019b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 57119b2a2c7SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 57219b2a2c7SDennis Zhou u64 max_discard_size; 57319b2a2c7SDennis Zhou int ret; 57419b2a2c7SDennis Zhou 57519b2a2c7SDennis Zhou ret = kstrtou64(buf, 10, &max_discard_size); 57619b2a2c7SDennis Zhou if (ret) 57719b2a2c7SDennis Zhou return -EINVAL; 57819b2a2c7SDennis Zhou 57919b2a2c7SDennis Zhou WRITE_ONCE(discard_ctl->max_discard_size, max_discard_size); 58019b2a2c7SDennis Zhou 58119b2a2c7SDennis Zhou return len; 58219b2a2c7SDennis Zhou } 58319b2a2c7SDennis Zhou BTRFS_ATTR_RW(discard, max_discard_size, btrfs_discard_max_discard_size_show, 58419b2a2c7SDennis Zhou btrfs_discard_max_discard_size_store); 58519b2a2c7SDennis Zhou 586e7849e33SAnand Jain /* 587e7849e33SAnand Jain * Per-filesystem debugging of discard (when mounted with discard=async). 588e7849e33SAnand Jain * 589e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/debug/discard/ 590e7849e33SAnand Jain */ 591e4faab84SDennis Zhou static const struct attribute *discard_debug_attrs[] = { 5925dc7c10bSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_bytes), 593dfb79ddbSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_extents), 5949ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bitmap_bytes), 5959ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bytes_saved), 5969ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_extent_bytes), 597a2309300SDennis Zhou BTRFS_ATTR_PTR(discard, iops_limit), 598e93591bbSDennis Zhou BTRFS_ATTR_PTR(discard, kbps_limit), 59919b2a2c7SDennis Zhou BTRFS_ATTR_PTR(discard, max_discard_size), 600e4faab84SDennis Zhou NULL, 601e4faab84SDennis Zhou }; 602e4faab84SDennis Zhou 603e4faab84SDennis Zhou /* 604e7849e33SAnand Jain * Per-filesystem runtime debugging exported via sysfs. 6056e369febSDavid Sterba * 606e7849e33SAnand Jain * Path: /sys/fs/btrfs/UUID/debug/ 6076e369febSDavid Sterba */ 60893945cb4SDennis Zhou static const struct attribute *btrfs_debug_mount_attrs[] = { 60993945cb4SDennis Zhou NULL, 61093945cb4SDennis Zhou }; 61193945cb4SDennis Zhou 612e7849e33SAnand Jain /* 613e7849e33SAnand Jain * Runtime debugging exported via sysfs, applies to all mounted filesystems. 614e7849e33SAnand Jain * 615e7849e33SAnand Jain * Path: /sys/fs/btrfs/debug 616e7849e33SAnand Jain */ 6176e369febSDavid Sterba static struct attribute *btrfs_debug_feature_attrs[] = { 6186e369febSDavid Sterba NULL 6196e369febSDavid Sterba }; 6206e369febSDavid Sterba 6216e369febSDavid Sterba static const struct attribute_group btrfs_debug_feature_attr_group = { 6226e369febSDavid Sterba .name = "debug", 6236e369febSDavid Sterba .attrs = btrfs_debug_feature_attrs, 6246e369febSDavid Sterba }; 6256e369febSDavid Sterba 6266e369febSDavid Sterba #endif 6276e369febSDavid Sterba 6286ab0a202SJeff Mahoney static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf) 6296ab0a202SJeff Mahoney { 6306ab0a202SJeff Mahoney u64 val; 6316ab0a202SJeff Mahoney if (lock) 6326ab0a202SJeff Mahoney spin_lock(lock); 6336ab0a202SJeff Mahoney val = *value_ptr; 6346ab0a202SJeff Mahoney if (lock) 6356ab0a202SJeff Mahoney spin_unlock(lock); 636020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6376ab0a202SJeff Mahoney } 6386ab0a202SJeff Mahoney 6396ab0a202SJeff Mahoney static ssize_t global_rsv_size_show(struct kobject *kobj, 6406ab0a202SJeff Mahoney struct kobj_attribute *ka, char *buf) 6416ab0a202SJeff Mahoney { 6426ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6436ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6446ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf); 6456ab0a202SJeff Mahoney } 646a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_size, global_rsv_size_show); 6476ab0a202SJeff Mahoney 6486ab0a202SJeff Mahoney static ssize_t global_rsv_reserved_show(struct kobject *kobj, 6496ab0a202SJeff Mahoney struct kobj_attribute *a, char *buf) 6506ab0a202SJeff Mahoney { 6516ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6526ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6536ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf); 6546ab0a202SJeff Mahoney } 655a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_reserved, global_rsv_reserved_show); 6566ab0a202SJeff Mahoney 6576ab0a202SJeff Mahoney #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj) 658c1895442SJeff Mahoney #define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj) 6596ab0a202SJeff Mahoney 6606ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6616ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf); 662a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, total_bytes, raid_bytes_show); 663a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, used_bytes, raid_bytes_show); 6646ab0a202SJeff Mahoney 6656ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6666ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf) 6676ab0a202SJeff Mahoney 6686ab0a202SJeff Mahoney { 6696ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj->parent); 67032da5386SDavid Sterba struct btrfs_block_group *block_group; 67175cb379dSJeff Mahoney int index = btrfs_bg_flags_to_raid_index(to_raid_kobj(kobj)->flags); 6726ab0a202SJeff Mahoney u64 val = 0; 6736ab0a202SJeff Mahoney 6746ab0a202SJeff Mahoney down_read(&sinfo->groups_sem); 6756ab0a202SJeff Mahoney list_for_each_entry(block_group, &sinfo->block_groups[index], list) { 676a969f4ccSHans van Kranenburg if (&attr->attr == BTRFS_ATTR_PTR(raid, total_bytes)) 677b3470b5dSDavid Sterba val += block_group->length; 6786ab0a202SJeff Mahoney else 679bf38be65SDavid Sterba val += block_group->used; 6806ab0a202SJeff Mahoney } 6816ab0a202SJeff Mahoney up_read(&sinfo->groups_sem); 682020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6836ab0a202SJeff Mahoney } 6846ab0a202SJeff Mahoney 685e7849e33SAnand Jain /* 686e7849e33SAnand Jain * Allocation information about block group profiles. 687e7849e33SAnand Jain * 688e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/<bg-profile>/ 689e7849e33SAnand Jain */ 6907c7e3014SKimberly Brown static struct attribute *raid_attrs[] = { 691a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, total_bytes), 692a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, used_bytes), 6936ab0a202SJeff Mahoney NULL 6946ab0a202SJeff Mahoney }; 6957c7e3014SKimberly Brown ATTRIBUTE_GROUPS(raid); 6966ab0a202SJeff Mahoney 6976ab0a202SJeff Mahoney static void release_raid_kobj(struct kobject *kobj) 6986ab0a202SJeff Mahoney { 699c1895442SJeff Mahoney kfree(to_raid_kobj(kobj)); 7006ab0a202SJeff Mahoney } 7016ab0a202SJeff Mahoney 702536ea45cSDavid Sterba static struct kobj_type btrfs_raid_ktype = { 7036ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 7046ab0a202SJeff Mahoney .release = release_raid_kobj, 7057c7e3014SKimberly Brown .default_groups = raid_groups, 7066ab0a202SJeff Mahoney }; 7076ab0a202SJeff Mahoney 7086ab0a202SJeff Mahoney #define SPACE_INFO_ATTR(field) \ 7096ab0a202SJeff Mahoney static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \ 7106ab0a202SJeff Mahoney struct kobj_attribute *a, \ 7116ab0a202SJeff Mahoney char *buf) \ 7126ab0a202SJeff Mahoney { \ 7136ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); \ 7146ab0a202SJeff Mahoney return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \ 7156ab0a202SJeff Mahoney } \ 716a969f4ccSHans van Kranenburg BTRFS_ATTR(space_info, field, btrfs_space_info_show_##field) 7176ab0a202SJeff Mahoney 71819fc516aSStefan Roesch static ssize_t btrfs_chunk_size_show(struct kobject *kobj, 71919fc516aSStefan Roesch struct kobj_attribute *a, char *buf) 72019fc516aSStefan Roesch { 72119fc516aSStefan Roesch struct btrfs_space_info *sinfo = to_space_info(kobj); 72219fc516aSStefan Roesch 72319fc516aSStefan Roesch return sysfs_emit(buf, "%llu\n", READ_ONCE(sinfo->chunk_size)); 72419fc516aSStefan Roesch } 72519fc516aSStefan Roesch 72619fc516aSStefan Roesch /* 72719fc516aSStefan Roesch * Store new chunk size in space info. Can be called on a read-only filesystem. 72819fc516aSStefan Roesch * 72919fc516aSStefan Roesch * If the new chunk size value is larger than 10% of free space it is reduced 73019fc516aSStefan Roesch * to match that limit. Alignment must be to 256M and the system chunk size 73119fc516aSStefan Roesch * cannot be set. 73219fc516aSStefan Roesch */ 73319fc516aSStefan Roesch static ssize_t btrfs_chunk_size_store(struct kobject *kobj, 73419fc516aSStefan Roesch struct kobj_attribute *a, 73519fc516aSStefan Roesch const char *buf, size_t len) 73619fc516aSStefan Roesch { 73719fc516aSStefan Roesch struct btrfs_space_info *space_info = to_space_info(kobj); 73819fc516aSStefan Roesch struct btrfs_fs_info *fs_info = to_fs_info(get_btrfs_kobj(kobj)); 73919fc516aSStefan Roesch char *retptr; 74019fc516aSStefan Roesch u64 val; 74119fc516aSStefan Roesch 74219fc516aSStefan Roesch if (!capable(CAP_SYS_ADMIN)) 74319fc516aSStefan Roesch return -EPERM; 74419fc516aSStefan Roesch 74519fc516aSStefan Roesch if (!fs_info->fs_devices) 74619fc516aSStefan Roesch return -EINVAL; 74719fc516aSStefan Roesch 74819fc516aSStefan Roesch if (btrfs_is_zoned(fs_info)) 74919fc516aSStefan Roesch return -EINVAL; 75019fc516aSStefan Roesch 75119fc516aSStefan Roesch /* System block type must not be changed. */ 75219fc516aSStefan Roesch if (space_info->flags & BTRFS_BLOCK_GROUP_SYSTEM) 75319fc516aSStefan Roesch return -EPERM; 75419fc516aSStefan Roesch 75519fc516aSStefan Roesch val = memparse(buf, &retptr); 75619fc516aSStefan Roesch /* There could be trailing '\n', also catch any typos after the value */ 75719fc516aSStefan Roesch retptr = skip_spaces(retptr); 75819fc516aSStefan Roesch if (*retptr != 0 || val == 0) 75919fc516aSStefan Roesch return -EINVAL; 76019fc516aSStefan Roesch 76119fc516aSStefan Roesch val = min(val, BTRFS_MAX_DATA_CHUNK_SIZE); 76219fc516aSStefan Roesch 76319fc516aSStefan Roesch /* Limit stripe size to 10% of available space. */ 76419fc516aSStefan Roesch val = min(div_factor(fs_info->fs_devices->total_rw_bytes, 1), val); 76519fc516aSStefan Roesch 76619fc516aSStefan Roesch /* Must be multiple of 256M. */ 76719fc516aSStefan Roesch val &= ~((u64)SZ_256M - 1); 76819fc516aSStefan Roesch 76919fc516aSStefan Roesch /* Must be at least 256M. */ 77019fc516aSStefan Roesch if (val < SZ_256M) 77119fc516aSStefan Roesch return -EINVAL; 77219fc516aSStefan Roesch 77319fc516aSStefan Roesch btrfs_update_space_info_chunk_size(space_info, val); 77419fc516aSStefan Roesch 77519fc516aSStefan Roesch return len; 77619fc516aSStefan Roesch } 77719fc516aSStefan Roesch 778*22c55e3bSStefan Roesch #ifdef CONFIG_BTRFS_DEBUG 779*22c55e3bSStefan Roesch /* 780*22c55e3bSStefan Roesch * Request chunk allocation with current chunk size. 781*22c55e3bSStefan Roesch */ 782*22c55e3bSStefan Roesch static ssize_t btrfs_force_chunk_alloc_store(struct kobject *kobj, 783*22c55e3bSStefan Roesch struct kobj_attribute *a, 784*22c55e3bSStefan Roesch const char *buf, size_t len) 785*22c55e3bSStefan Roesch { 786*22c55e3bSStefan Roesch struct btrfs_space_info *space_info = to_space_info(kobj); 787*22c55e3bSStefan Roesch struct btrfs_fs_info *fs_info = to_fs_info(get_btrfs_kobj(kobj)); 788*22c55e3bSStefan Roesch struct btrfs_trans_handle *trans; 789*22c55e3bSStefan Roesch bool val; 790*22c55e3bSStefan Roesch int ret; 791*22c55e3bSStefan Roesch 792*22c55e3bSStefan Roesch if (!capable(CAP_SYS_ADMIN)) 793*22c55e3bSStefan Roesch return -EPERM; 794*22c55e3bSStefan Roesch 795*22c55e3bSStefan Roesch if (sb_rdonly(fs_info->sb)) 796*22c55e3bSStefan Roesch return -EROFS; 797*22c55e3bSStefan Roesch 798*22c55e3bSStefan Roesch ret = kstrtobool(buf, &val); 799*22c55e3bSStefan Roesch if (ret) 800*22c55e3bSStefan Roesch return ret; 801*22c55e3bSStefan Roesch 802*22c55e3bSStefan Roesch if (!val) 803*22c55e3bSStefan Roesch return -EINVAL; 804*22c55e3bSStefan Roesch 805*22c55e3bSStefan Roesch /* 806*22c55e3bSStefan Roesch * This is unsafe to be called from sysfs context and may cause 807*22c55e3bSStefan Roesch * unexpected problems. 808*22c55e3bSStefan Roesch */ 809*22c55e3bSStefan Roesch trans = btrfs_start_transaction(fs_info->tree_root, 0); 810*22c55e3bSStefan Roesch if (IS_ERR(trans)) 811*22c55e3bSStefan Roesch return PTR_ERR(trans); 812*22c55e3bSStefan Roesch ret = btrfs_force_chunk_alloc(trans, space_info->flags); 813*22c55e3bSStefan Roesch btrfs_end_transaction(trans); 814*22c55e3bSStefan Roesch 815*22c55e3bSStefan Roesch if (ret == 1) 816*22c55e3bSStefan Roesch return len; 817*22c55e3bSStefan Roesch 818*22c55e3bSStefan Roesch return -ENOSPC; 819*22c55e3bSStefan Roesch } 820*22c55e3bSStefan Roesch BTRFS_ATTR_W(space_info, force_chunk_alloc, btrfs_force_chunk_alloc_store); 821*22c55e3bSStefan Roesch 822*22c55e3bSStefan Roesch #endif 823*22c55e3bSStefan Roesch 8246ab0a202SJeff Mahoney SPACE_INFO_ATTR(flags); 8256ab0a202SJeff Mahoney SPACE_INFO_ATTR(total_bytes); 8266ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_used); 8276ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_pinned); 8286ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_reserved); 8296ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_may_use); 830c1fd5c30SWang Xiaoguang SPACE_INFO_ATTR(bytes_readonly); 831169e0da9SNaohiro Aota SPACE_INFO_ATTR(bytes_zone_unusable); 8326ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_used); 8336ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_total); 83419fc516aSStefan Roesch BTRFS_ATTR_RW(space_info, chunk_size, btrfs_chunk_size_show, btrfs_chunk_size_store); 8356ab0a202SJeff Mahoney 836bb5a098dSJosef Bacik static ssize_t btrfs_sinfo_bg_reclaim_threshold_show(struct kobject *kobj, 837bb5a098dSJosef Bacik struct kobj_attribute *a, 838bb5a098dSJosef Bacik char *buf) 839bb5a098dSJosef Bacik { 840bb5a098dSJosef Bacik struct btrfs_space_info *space_info = to_space_info(kobj); 841bb5a098dSJosef Bacik ssize_t ret; 842bb5a098dSJosef Bacik 843bb5a098dSJosef Bacik ret = sysfs_emit(buf, "%d\n", READ_ONCE(space_info->bg_reclaim_threshold)); 844bb5a098dSJosef Bacik 845bb5a098dSJosef Bacik return ret; 846bb5a098dSJosef Bacik } 847bb5a098dSJosef Bacik 848bb5a098dSJosef Bacik static ssize_t btrfs_sinfo_bg_reclaim_threshold_store(struct kobject *kobj, 849bb5a098dSJosef Bacik struct kobj_attribute *a, 850bb5a098dSJosef Bacik const char *buf, size_t len) 851bb5a098dSJosef Bacik { 852bb5a098dSJosef Bacik struct btrfs_space_info *space_info = to_space_info(kobj); 853bb5a098dSJosef Bacik int thresh; 854bb5a098dSJosef Bacik int ret; 855bb5a098dSJosef Bacik 856bb5a098dSJosef Bacik ret = kstrtoint(buf, 10, &thresh); 857bb5a098dSJosef Bacik if (ret) 858bb5a098dSJosef Bacik return ret; 859bb5a098dSJosef Bacik 860ef972e7bSJosef Bacik if (thresh < 0 || thresh > 100) 861bb5a098dSJosef Bacik return -EINVAL; 862bb5a098dSJosef Bacik 863bb5a098dSJosef Bacik WRITE_ONCE(space_info->bg_reclaim_threshold, thresh); 864bb5a098dSJosef Bacik 865bb5a098dSJosef Bacik return len; 866bb5a098dSJosef Bacik } 867bb5a098dSJosef Bacik 868bb5a098dSJosef Bacik BTRFS_ATTR_RW(space_info, bg_reclaim_threshold, 869bb5a098dSJosef Bacik btrfs_sinfo_bg_reclaim_threshold_show, 870bb5a098dSJosef Bacik btrfs_sinfo_bg_reclaim_threshold_store); 871bb5a098dSJosef Bacik 872e7849e33SAnand Jain /* 873e7849e33SAnand Jain * Allocation information about block group types. 874e7849e33SAnand Jain * 875e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/ 876e7849e33SAnand Jain */ 8776ab0a202SJeff Mahoney static struct attribute *space_info_attrs[] = { 878a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, flags), 879a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, total_bytes), 880a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_used), 881a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_pinned), 882a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_reserved), 883a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_may_use), 884a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_readonly), 885169e0da9SNaohiro Aota BTRFS_ATTR_PTR(space_info, bytes_zone_unusable), 886a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_used), 887a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_total), 888bb5a098dSJosef Bacik BTRFS_ATTR_PTR(space_info, bg_reclaim_threshold), 88919fc516aSStefan Roesch BTRFS_ATTR_PTR(space_info, chunk_size), 890*22c55e3bSStefan Roesch #ifdef CONFIG_BTRFS_DEBUG 891*22c55e3bSStefan Roesch BTRFS_ATTR_PTR(space_info, force_chunk_alloc), 892*22c55e3bSStefan Roesch #endif 8936ab0a202SJeff Mahoney NULL, 8946ab0a202SJeff Mahoney }; 8957c7e3014SKimberly Brown ATTRIBUTE_GROUPS(space_info); 8966ab0a202SJeff Mahoney 8976ab0a202SJeff Mahoney static void space_info_release(struct kobject *kobj) 8986ab0a202SJeff Mahoney { 8996ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); 9006ab0a202SJeff Mahoney kfree(sinfo); 9016ab0a202SJeff Mahoney } 9026ab0a202SJeff Mahoney 90327992d01SDavid Sterba static struct kobj_type space_info_ktype = { 9046ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 9056ab0a202SJeff Mahoney .release = space_info_release, 9067c7e3014SKimberly Brown .default_groups = space_info_groups, 9076ab0a202SJeff Mahoney }; 9086ab0a202SJeff Mahoney 909e7849e33SAnand Jain /* 910e7849e33SAnand Jain * Allocation information about block groups. 911e7849e33SAnand Jain * 912e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/ 913e7849e33SAnand Jain */ 9146ab0a202SJeff Mahoney static const struct attribute *allocation_attrs[] = { 915a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_reserved), 916a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_size), 9176ab0a202SJeff Mahoney NULL, 9186ab0a202SJeff Mahoney }; 9196ab0a202SJeff Mahoney 920f8ba9c11SJeff Mahoney static ssize_t btrfs_label_show(struct kobject *kobj, 921f8ba9c11SJeff Mahoney struct kobj_attribute *a, char *buf) 922f8ba9c11SJeff Mahoney { 923f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 92448fcc3ffSSatoru Takeuchi char *label = fs_info->super_copy->label; 925ee17fc80SDavid Sterba ssize_t ret; 926ee17fc80SDavid Sterba 927ee17fc80SDavid Sterba spin_lock(&fs_info->super_lock); 928020e5277SAnand Jain ret = sysfs_emit(buf, label[0] ? "%s\n" : "%s", label); 929ee17fc80SDavid Sterba spin_unlock(&fs_info->super_lock); 930ee17fc80SDavid Sterba 931ee17fc80SDavid Sterba return ret; 932f8ba9c11SJeff Mahoney } 933f8ba9c11SJeff Mahoney 934f8ba9c11SJeff Mahoney static ssize_t btrfs_label_store(struct kobject *kobj, 935f8ba9c11SJeff Mahoney struct kobj_attribute *a, 936f8ba9c11SJeff Mahoney const char *buf, size_t len) 937f8ba9c11SJeff Mahoney { 938f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 93948fcc3ffSSatoru Takeuchi size_t p_len; 940f8ba9c11SJeff Mahoney 94166ac9fe7SDavid Sterba if (!fs_info) 94266ac9fe7SDavid Sterba return -EPERM; 94366ac9fe7SDavid Sterba 944bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 94579aec2b8SAnand Jain return -EROFS; 94679aec2b8SAnand Jain 94748fcc3ffSSatoru Takeuchi /* 94848fcc3ffSSatoru Takeuchi * p_len is the len until the first occurrence of either 94948fcc3ffSSatoru Takeuchi * '\n' or '\0' 95048fcc3ffSSatoru Takeuchi */ 95148fcc3ffSSatoru Takeuchi p_len = strcspn(buf, "\n"); 95248fcc3ffSSatoru Takeuchi 95348fcc3ffSSatoru Takeuchi if (p_len >= BTRFS_LABEL_SIZE) 954f8ba9c11SJeff Mahoney return -EINVAL; 955f8ba9c11SJeff Mahoney 956a6f69dc8SDavid Sterba spin_lock(&fs_info->super_lock); 95748fcc3ffSSatoru Takeuchi memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE); 95848fcc3ffSSatoru Takeuchi memcpy(fs_info->super_copy->label, buf, p_len); 959a6f69dc8SDavid Sterba spin_unlock(&fs_info->super_lock); 960f8ba9c11SJeff Mahoney 961a6f69dc8SDavid Sterba /* 962a6f69dc8SDavid Sterba * We don't want to do full transaction commit from inside sysfs 963a6f69dc8SDavid Sterba */ 964a6f69dc8SDavid Sterba btrfs_set_pending(fs_info, COMMIT); 965a6f69dc8SDavid Sterba wake_up_process(fs_info->transaction_kthread); 966a6f69dc8SDavid Sterba 967f8ba9c11SJeff Mahoney return len; 968f8ba9c11SJeff Mahoney } 969a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, label, btrfs_label_show, btrfs_label_store); 970f8ba9c11SJeff Mahoney 971df93589aSDavid Sterba static ssize_t btrfs_nodesize_show(struct kobject *kobj, 972df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 973df93589aSDavid Sterba { 974df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 975df93589aSDavid Sterba 976020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->nodesize); 977df93589aSDavid Sterba } 978df93589aSDavid Sterba 979a969f4ccSHans van Kranenburg BTRFS_ATTR(, nodesize, btrfs_nodesize_show); 980df93589aSDavid Sterba 981df93589aSDavid Sterba static ssize_t btrfs_sectorsize_show(struct kobject *kobj, 982df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 983df93589aSDavid Sterba { 984df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 985df93589aSDavid Sterba 986020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 987df93589aSDavid Sterba } 988df93589aSDavid Sterba 989a969f4ccSHans van Kranenburg BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show); 990df93589aSDavid Sterba 991df93589aSDavid Sterba static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, 992df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 993df93589aSDavid Sterba { 994df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 995df93589aSDavid Sterba 996020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 997df93589aSDavid Sterba } 998df93589aSDavid Sterba 999a969f4ccSHans van Kranenburg BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show); 1000df93589aSDavid Sterba 10012723480aSSargun Dhillon static ssize_t quota_override_show(struct kobject *kobj, 10022723480aSSargun Dhillon struct kobj_attribute *a, char *buf) 10032723480aSSargun Dhillon { 10042723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 10052723480aSSargun Dhillon int quota_override; 10062723480aSSargun Dhillon 10072723480aSSargun Dhillon quota_override = test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 1008020e5277SAnand Jain return sysfs_emit(buf, "%d\n", quota_override); 10092723480aSSargun Dhillon } 10102723480aSSargun Dhillon 10112723480aSSargun Dhillon static ssize_t quota_override_store(struct kobject *kobj, 10122723480aSSargun Dhillon struct kobj_attribute *a, 10132723480aSSargun Dhillon const char *buf, size_t len) 10142723480aSSargun Dhillon { 10152723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 10162723480aSSargun Dhillon unsigned long knob; 10172723480aSSargun Dhillon int err; 10182723480aSSargun Dhillon 10192723480aSSargun Dhillon if (!fs_info) 10202723480aSSargun Dhillon return -EPERM; 10212723480aSSargun Dhillon 10222723480aSSargun Dhillon if (!capable(CAP_SYS_RESOURCE)) 10232723480aSSargun Dhillon return -EPERM; 10242723480aSSargun Dhillon 10252723480aSSargun Dhillon err = kstrtoul(buf, 10, &knob); 10262723480aSSargun Dhillon if (err) 10272723480aSSargun Dhillon return err; 10282723480aSSargun Dhillon if (knob > 1) 10292723480aSSargun Dhillon return -EINVAL; 10302723480aSSargun Dhillon 10312723480aSSargun Dhillon if (knob) 10322723480aSSargun Dhillon set_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 10332723480aSSargun Dhillon else 10342723480aSSargun Dhillon clear_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 10352723480aSSargun Dhillon 10362723480aSSargun Dhillon return len; 10372723480aSSargun Dhillon } 10382723480aSSargun Dhillon 1039a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, quota_override, quota_override_show, quota_override_store); 10402723480aSSargun Dhillon 104156f20f40SNikolay Borisov static ssize_t btrfs_metadata_uuid_show(struct kobject *kobj, 104256f20f40SNikolay Borisov struct kobj_attribute *a, char *buf) 104356f20f40SNikolay Borisov { 104456f20f40SNikolay Borisov struct btrfs_fs_info *fs_info = to_fs_info(kobj); 104556f20f40SNikolay Borisov 1046020e5277SAnand Jain return sysfs_emit(buf, "%pU\n", fs_info->fs_devices->metadata_uuid); 104756f20f40SNikolay Borisov } 104856f20f40SNikolay Borisov 104956f20f40SNikolay Borisov BTRFS_ATTR(, metadata_uuid, btrfs_metadata_uuid_show); 105056f20f40SNikolay Borisov 105141e6d2a8SJohannes Thumshirn static ssize_t btrfs_checksum_show(struct kobject *kobj, 105241e6d2a8SJohannes Thumshirn struct kobj_attribute *a, char *buf) 105341e6d2a8SJohannes Thumshirn { 105441e6d2a8SJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 105541e6d2a8SJohannes Thumshirn u16 csum_type = btrfs_super_csum_type(fs_info->super_copy); 105641e6d2a8SJohannes Thumshirn 1057020e5277SAnand Jain return sysfs_emit(buf, "%s (%s)\n", 105841e6d2a8SJohannes Thumshirn btrfs_super_csum_name(csum_type), 105941e6d2a8SJohannes Thumshirn crypto_shash_driver_name(fs_info->csum_shash)); 106041e6d2a8SJohannes Thumshirn } 106141e6d2a8SJohannes Thumshirn 106241e6d2a8SJohannes Thumshirn BTRFS_ATTR(, checksum, btrfs_checksum_show); 106341e6d2a8SJohannes Thumshirn 106466a2823cSGoldwyn Rodrigues static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj, 106566a2823cSGoldwyn Rodrigues struct kobj_attribute *a, char *buf) 106666a2823cSGoldwyn Rodrigues { 106766a2823cSGoldwyn Rodrigues struct btrfs_fs_info *fs_info = to_fs_info(kobj); 106866a2823cSGoldwyn Rodrigues const char *str; 106966a2823cSGoldwyn Rodrigues 107066a2823cSGoldwyn Rodrigues switch (READ_ONCE(fs_info->exclusive_operation)) { 107166a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_NONE: 107266a2823cSGoldwyn Rodrigues str = "none\n"; 107366a2823cSGoldwyn Rodrigues break; 107466a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_BALANCE: 107566a2823cSGoldwyn Rodrigues str = "balance\n"; 107666a2823cSGoldwyn Rodrigues break; 10773e1ad196SDavid Sterba case BTRFS_EXCLOP_BALANCE_PAUSED: 10783e1ad196SDavid Sterba str = "balance paused\n"; 10793e1ad196SDavid Sterba break; 108066a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_ADD: 108166a2823cSGoldwyn Rodrigues str = "device add\n"; 108266a2823cSGoldwyn Rodrigues break; 108366a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REMOVE: 108466a2823cSGoldwyn Rodrigues str = "device remove\n"; 108566a2823cSGoldwyn Rodrigues break; 108666a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REPLACE: 108766a2823cSGoldwyn Rodrigues str = "device replace\n"; 108866a2823cSGoldwyn Rodrigues break; 108966a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_RESIZE: 109066a2823cSGoldwyn Rodrigues str = "resize\n"; 109166a2823cSGoldwyn Rodrigues break; 109266a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_SWAP_ACTIVATE: 109366a2823cSGoldwyn Rodrigues str = "swap activate\n"; 109466a2823cSGoldwyn Rodrigues break; 109566a2823cSGoldwyn Rodrigues default: 109666a2823cSGoldwyn Rodrigues str = "UNKNOWN\n"; 109766a2823cSGoldwyn Rodrigues break; 109866a2823cSGoldwyn Rodrigues } 1099020e5277SAnand Jain return sysfs_emit(buf, "%s", str); 110066a2823cSGoldwyn Rodrigues } 110166a2823cSGoldwyn Rodrigues BTRFS_ATTR(, exclusive_operation, btrfs_exclusive_operation_show); 110266a2823cSGoldwyn Rodrigues 1103089c8b05SAnand Jain static ssize_t btrfs_generation_show(struct kobject *kobj, 1104089c8b05SAnand Jain struct kobj_attribute *a, char *buf) 1105089c8b05SAnand Jain { 1106089c8b05SAnand Jain struct btrfs_fs_info *fs_info = to_fs_info(kobj); 1107089c8b05SAnand Jain 1108020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", fs_info->generation); 1109089c8b05SAnand Jain } 1110089c8b05SAnand Jain BTRFS_ATTR(, generation, btrfs_generation_show); 1111089c8b05SAnand Jain 1112aaefed20SAnand Jain /* 1113aaefed20SAnand Jain * Look for an exact string @string in @buffer with possible leading or 1114aaefed20SAnand Jain * trailing whitespace 1115aaefed20SAnand Jain */ 1116aaefed20SAnand Jain static bool strmatch(const char *buffer, const char *string) 1117aaefed20SAnand Jain { 1118aaefed20SAnand Jain const size_t len = strlen(string); 1119aaefed20SAnand Jain 1120aaefed20SAnand Jain /* Skip leading whitespace */ 1121aaefed20SAnand Jain buffer = skip_spaces(buffer); 1122aaefed20SAnand Jain 1123aaefed20SAnand Jain /* Match entire string, check if the rest is whitespace or empty */ 1124aaefed20SAnand Jain if (strncmp(string, buffer, len) == 0 && 1125aaefed20SAnand Jain strlen(skip_spaces(buffer + len)) == 0) 1126aaefed20SAnand Jain return true; 1127aaefed20SAnand Jain 1128aaefed20SAnand Jain return false; 1129aaefed20SAnand Jain } 1130aaefed20SAnand Jain 11313d8cc17aSAnand Jain static const char * const btrfs_read_policy_name[] = { "pid" }; 11323d8cc17aSAnand Jain 11333d8cc17aSAnand Jain static ssize_t btrfs_read_policy_show(struct kobject *kobj, 11343d8cc17aSAnand Jain struct kobj_attribute *a, char *buf) 11353d8cc17aSAnand Jain { 11363d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 11373d8cc17aSAnand Jain ssize_t ret = 0; 11383d8cc17aSAnand Jain int i; 11393d8cc17aSAnand Jain 11403d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 11413d8cc17aSAnand Jain if (fs_devices->read_policy == i) 11423d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s[%s]", 11433d8cc17aSAnand Jain (ret == 0 ? "" : " "), 11443d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11453d8cc17aSAnand Jain else 11463d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s", 11473d8cc17aSAnand Jain (ret == 0 ? "" : " "), 11483d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11493d8cc17aSAnand Jain } 11503d8cc17aSAnand Jain 11513d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); 11523d8cc17aSAnand Jain 11533d8cc17aSAnand Jain return ret; 11543d8cc17aSAnand Jain } 11553d8cc17aSAnand Jain 11563d8cc17aSAnand Jain static ssize_t btrfs_read_policy_store(struct kobject *kobj, 11573d8cc17aSAnand Jain struct kobj_attribute *a, 11583d8cc17aSAnand Jain const char *buf, size_t len) 11593d8cc17aSAnand Jain { 11603d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 11613d8cc17aSAnand Jain int i; 11623d8cc17aSAnand Jain 11633d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 11643d8cc17aSAnand Jain if (strmatch(buf, btrfs_read_policy_name[i])) { 11653d8cc17aSAnand Jain if (i != fs_devices->read_policy) { 11663d8cc17aSAnand Jain fs_devices->read_policy = i; 11673d8cc17aSAnand Jain btrfs_info(fs_devices->fs_info, 11683d8cc17aSAnand Jain "read policy set to '%s'", 11693d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11703d8cc17aSAnand Jain } 11713d8cc17aSAnand Jain return len; 11723d8cc17aSAnand Jain } 11733d8cc17aSAnand Jain } 11743d8cc17aSAnand Jain 11753d8cc17aSAnand Jain return -EINVAL; 11763d8cc17aSAnand Jain } 11773d8cc17aSAnand Jain BTRFS_ATTR_RW(, read_policy, btrfs_read_policy_show, btrfs_read_policy_store); 11783d8cc17aSAnand Jain 117918bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_show(struct kobject *kobj, 118018bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 118118bb8bbfSJohannes Thumshirn char *buf) 118218bb8bbfSJohannes Thumshirn { 118318bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 118418bb8bbfSJohannes Thumshirn ssize_t ret; 118518bb8bbfSJohannes Thumshirn 1186020e5277SAnand Jain ret = sysfs_emit(buf, "%d\n", READ_ONCE(fs_info->bg_reclaim_threshold)); 118718bb8bbfSJohannes Thumshirn 118818bb8bbfSJohannes Thumshirn return ret; 118918bb8bbfSJohannes Thumshirn } 119018bb8bbfSJohannes Thumshirn 119118bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_store(struct kobject *kobj, 119218bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 119318bb8bbfSJohannes Thumshirn const char *buf, size_t len) 119418bb8bbfSJohannes Thumshirn { 119518bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 119618bb8bbfSJohannes Thumshirn int thresh; 119718bb8bbfSJohannes Thumshirn int ret; 119818bb8bbfSJohannes Thumshirn 119918bb8bbfSJohannes Thumshirn ret = kstrtoint(buf, 10, &thresh); 120018bb8bbfSJohannes Thumshirn if (ret) 120118bb8bbfSJohannes Thumshirn return ret; 120218bb8bbfSJohannes Thumshirn 120377233c2dSJohannes Thumshirn if (thresh != 0 && (thresh <= 50 || thresh > 100)) 120418bb8bbfSJohannes Thumshirn return -EINVAL; 120518bb8bbfSJohannes Thumshirn 120677233c2dSJohannes Thumshirn WRITE_ONCE(fs_info->bg_reclaim_threshold, thresh); 120718bb8bbfSJohannes Thumshirn 120818bb8bbfSJohannes Thumshirn return len; 120918bb8bbfSJohannes Thumshirn } 121018bb8bbfSJohannes Thumshirn BTRFS_ATTR_RW(, bg_reclaim_threshold, btrfs_bg_reclaim_threshold_show, 121118bb8bbfSJohannes Thumshirn btrfs_bg_reclaim_threshold_store); 121218bb8bbfSJohannes Thumshirn 1213e7849e33SAnand Jain /* 1214e7849e33SAnand Jain * Per-filesystem information and stats. 1215e7849e33SAnand Jain * 1216e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/ 1217e7849e33SAnand Jain */ 12180dd2906fSAnand Jain static const struct attribute *btrfs_attrs[] = { 1219a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, label), 1220a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, nodesize), 1221a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, sectorsize), 1222a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, clone_alignment), 1223a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, quota_override), 122456f20f40SNikolay Borisov BTRFS_ATTR_PTR(, metadata_uuid), 122541e6d2a8SJohannes Thumshirn BTRFS_ATTR_PTR(, checksum), 122666a2823cSGoldwyn Rodrigues BTRFS_ATTR_PTR(, exclusive_operation), 1227089c8b05SAnand Jain BTRFS_ATTR_PTR(, generation), 12283d8cc17aSAnand Jain BTRFS_ATTR_PTR(, read_policy), 122918bb8bbfSJohannes Thumshirn BTRFS_ATTR_PTR(, bg_reclaim_threshold), 1230f8ba9c11SJeff Mahoney NULL, 1231f8ba9c11SJeff Mahoney }; 1232f8ba9c11SJeff Mahoney 1233c1b7e474SAnand Jain static void btrfs_release_fsid_kobj(struct kobject *kobj) 1234510d7360SJeff Mahoney { 12352e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj); 1236248d200dSAnand Jain 1237c1b7e474SAnand Jain memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject)); 12382e7910d6SAnand Jain complete(&fs_devs->kobj_unregister); 1239510d7360SJeff Mahoney } 1240510d7360SJeff Mahoney 1241510d7360SJeff Mahoney static struct kobj_type btrfs_ktype = { 1242510d7360SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 1243c1b7e474SAnand Jain .release = btrfs_release_fsid_kobj, 1244510d7360SJeff Mahoney }; 1245510d7360SJeff Mahoney 12462e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj) 12472e7910d6SAnand Jain { 12482e7910d6SAnand Jain if (kobj->ktype != &btrfs_ktype) 12492e7910d6SAnand Jain return NULL; 1250c1b7e474SAnand Jain return container_of(kobj, struct btrfs_fs_devices, fsid_kobj); 12512e7910d6SAnand Jain } 12522e7910d6SAnand Jain 1253510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj) 1254510d7360SJeff Mahoney { 1255510d7360SJeff Mahoney if (kobj->ktype != &btrfs_ktype) 1256510d7360SJeff Mahoney return NULL; 12572e7910d6SAnand Jain return to_fs_devs(kobj)->fs_info; 1258510d7360SJeff Mahoney } 125958176a96SJosef Bacik 126019fc516aSStefan Roesch static struct kobject *get_btrfs_kobj(struct kobject *kobj) 126119fc516aSStefan Roesch { 126219fc516aSStefan Roesch while (kobj) { 126319fc516aSStefan Roesch if (kobj->ktype == &btrfs_ktype) 126419fc516aSStefan Roesch return kobj; 126519fc516aSStefan Roesch kobj = kobj->parent; 126619fc516aSStefan Roesch } 126719fc516aSStefan Roesch return NULL; 126819fc516aSStefan Roesch } 126919fc516aSStefan Roesch 1270e453d989SJeff Mahoney #define NUM_FEATURE_BITS 64 12716c52157fSTomohiro Misono #define BTRFS_FEATURE_NAME_MAX 13 12726c52157fSTomohiro Misono static char btrfs_unknown_feature_names[FEAT_MAX][NUM_FEATURE_BITS][BTRFS_FEATURE_NAME_MAX]; 12736c52157fSTomohiro Misono static struct btrfs_feature_attr btrfs_feature_attrs[FEAT_MAX][NUM_FEATURE_BITS]; 1274e453d989SJeff Mahoney 1275a55e65b8SDavid Sterba static_assert(ARRAY_SIZE(btrfs_unknown_feature_names) == 1276a55e65b8SDavid Sterba ARRAY_SIZE(btrfs_feature_attrs)); 1277a55e65b8SDavid Sterba static_assert(ARRAY_SIZE(btrfs_unknown_feature_names[0]) == 1278a55e65b8SDavid Sterba ARRAY_SIZE(btrfs_feature_attrs[0])); 1279a55e65b8SDavid Sterba 12806c52157fSTomohiro Misono static const u64 supported_feature_masks[FEAT_MAX] = { 1281e453d989SJeff Mahoney [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP, 1282e453d989SJeff Mahoney [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP, 1283e453d989SJeff Mahoney [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP, 1284e453d989SJeff Mahoney }; 1285e453d989SJeff Mahoney 1286e453d989SJeff Mahoney static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add) 12875ac1d209SJeff Mahoney { 1288e453d989SJeff Mahoney int set; 1289e453d989SJeff Mahoney 1290e453d989SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 1291e453d989SJeff Mahoney int i; 1292e453d989SJeff Mahoney struct attribute *attrs[2]; 1293e453d989SJeff Mahoney struct attribute_group agroup = { 1294e453d989SJeff Mahoney .name = "features", 1295e453d989SJeff Mahoney .attrs = attrs, 1296e453d989SJeff Mahoney }; 1297e453d989SJeff Mahoney u64 features = get_features(fs_info, set); 1298e453d989SJeff Mahoney features &= ~supported_feature_masks[set]; 1299e453d989SJeff Mahoney 1300e453d989SJeff Mahoney if (!features) 1301e453d989SJeff Mahoney continue; 1302e453d989SJeff Mahoney 1303e453d989SJeff Mahoney attrs[1] = NULL; 1304e453d989SJeff Mahoney for (i = 0; i < NUM_FEATURE_BITS; i++) { 1305e453d989SJeff Mahoney struct btrfs_feature_attr *fa; 1306e453d989SJeff Mahoney 1307e453d989SJeff Mahoney if (!(features & (1ULL << i))) 1308e453d989SJeff Mahoney continue; 1309e453d989SJeff Mahoney 1310e453d989SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 1311e453d989SJeff Mahoney attrs[0] = &fa->kobj_attr.attr; 1312e453d989SJeff Mahoney if (add) { 1313e453d989SJeff Mahoney int ret; 1314c1b7e474SAnand Jain ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj, 1315e453d989SJeff Mahoney &agroup); 1316e453d989SJeff Mahoney if (ret) 1317e453d989SJeff Mahoney return ret; 1318e453d989SJeff Mahoney } else 1319c1b7e474SAnand Jain sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj, 1320e453d989SJeff Mahoney &agroup); 1321e453d989SJeff Mahoney } 1322e453d989SJeff Mahoney 1323e453d989SJeff Mahoney } 1324e453d989SJeff Mahoney return 0; 1325e453d989SJeff Mahoney } 1326e453d989SJeff Mahoney 13272e3e1281SAnand Jain static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 1328e453d989SJeff Mahoney { 1329a013d141SAnand Jain if (fs_devs->devinfo_kobj) { 1330a013d141SAnand Jain kobject_del(fs_devs->devinfo_kobj); 1331a013d141SAnand Jain kobject_put(fs_devs->devinfo_kobj); 1332a013d141SAnand Jain fs_devs->devinfo_kobj = NULL; 1333a013d141SAnand Jain } 1334a013d141SAnand Jain 1335b5501504SAnand Jain if (fs_devs->devices_kobj) { 1336b5501504SAnand Jain kobject_del(fs_devs->devices_kobj); 1337b5501504SAnand Jain kobject_put(fs_devs->devices_kobj); 1338b5501504SAnand Jain fs_devs->devices_kobj = NULL; 1339aaf13305SAnand Jain } 1340aaf13305SAnand Jain 1341c1b7e474SAnand Jain if (fs_devs->fsid_kobj.state_initialized) { 1342c1b7e474SAnand Jain kobject_del(&fs_devs->fsid_kobj); 1343c1b7e474SAnand Jain kobject_put(&fs_devs->fsid_kobj); 13442e7910d6SAnand Jain wait_for_completion(&fs_devs->kobj_unregister); 13455ac1d209SJeff Mahoney } 1346f90fc547SAnand Jain } 13475ac1d209SJeff Mahoney 13482e3e1281SAnand Jain /* when fs_devs is NULL it will remove all fsid kobject */ 13491d1c1be3SAnand Jain void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 13502e3e1281SAnand Jain { 13512e3e1281SAnand Jain struct list_head *fs_uuids = btrfs_get_fs_uuids(); 13522e3e1281SAnand Jain 13532e3e1281SAnand Jain if (fs_devs) { 13542e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 13552e3e1281SAnand Jain return; 13562e3e1281SAnand Jain } 13572e3e1281SAnand Jain 1358c4babc5eSAnand Jain list_for_each_entry(fs_devs, fs_uuids, fs_list) { 13592e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 13602e3e1281SAnand Jain } 13612e3e1281SAnand Jain } 13622e3e1281SAnand Jain 136353f8a74cSAnand Jain static void btrfs_sysfs_remove_fs_devices(struct btrfs_fs_devices *fs_devices) 136453f8a74cSAnand Jain { 136553f8a74cSAnand Jain struct btrfs_device *device; 136630b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 136753f8a74cSAnand Jain 136853f8a74cSAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) 136953f8a74cSAnand Jain btrfs_sysfs_remove_device(device); 137030b0e4e0SAnand Jain 137130b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 137230b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) 137330b0e4e0SAnand Jain btrfs_sysfs_remove_device(device); 137430b0e4e0SAnand Jain } 137553f8a74cSAnand Jain } 137653f8a74cSAnand Jain 13776618a59bSAnand Jain void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info) 1378e453d989SJeff Mahoney { 13793092c68fSNikolay Borisov struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 13803092c68fSNikolay Borisov 13813092c68fSNikolay Borisov sysfs_remove_link(fsid_kobj, "bdi"); 13823092c68fSNikolay Borisov 1383e453d989SJeff Mahoney if (fs_info->space_info_kobj) { 1384e453d989SJeff Mahoney sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); 1385e453d989SJeff Mahoney kobject_del(fs_info->space_info_kobj); 1386e453d989SJeff Mahoney kobject_put(fs_info->space_info_kobj); 1387e453d989SJeff Mahoney } 138871e8978eSDennis Zhou #ifdef CONFIG_BTRFS_DEBUG 1389e4faab84SDennis Zhou if (fs_info->discard_debug_kobj) { 1390e4faab84SDennis Zhou sysfs_remove_files(fs_info->discard_debug_kobj, 1391e4faab84SDennis Zhou discard_debug_attrs); 1392e4faab84SDennis Zhou kobject_del(fs_info->discard_debug_kobj); 1393e4faab84SDennis Zhou kobject_put(fs_info->discard_debug_kobj); 1394e4faab84SDennis Zhou } 139593945cb4SDennis Zhou if (fs_info->debug_kobj) { 139693945cb4SDennis Zhou sysfs_remove_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 139793945cb4SDennis Zhou kobject_del(fs_info->debug_kobj); 139893945cb4SDennis Zhou kobject_put(fs_info->debug_kobj); 139993945cb4SDennis Zhou } 140071e8978eSDennis Zhou #endif 1401e453d989SJeff Mahoney addrm_unknown_feature_attrs(fs_info, false); 14023092c68fSNikolay Borisov sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 14033092c68fSNikolay Borisov sysfs_remove_files(fsid_kobj, btrfs_attrs); 140453f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_info->fs_devices); 1405e453d989SJeff Mahoney } 1406e453d989SJeff Mahoney 1407f10152bcSDavid Sterba static const char * const btrfs_feature_set_names[FEAT_MAX] = { 140879da4fa4SJeff Mahoney [FEAT_COMPAT] = "compat", 140979da4fa4SJeff Mahoney [FEAT_COMPAT_RO] = "compat_ro", 141079da4fa4SJeff Mahoney [FEAT_INCOMPAT] = "incompat", 141179da4fa4SJeff Mahoney }; 141279da4fa4SJeff Mahoney 14139e6df7ceSDavid Sterba const char *btrfs_feature_set_name(enum btrfs_feature_set set) 1414f10152bcSDavid Sterba { 1415f10152bcSDavid Sterba return btrfs_feature_set_names[set]; 1416f10152bcSDavid Sterba } 1417f10152bcSDavid Sterba 14183b02a68aSJeff Mahoney char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) 14193b02a68aSJeff Mahoney { 14203b02a68aSJeff Mahoney size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */ 14213b02a68aSJeff Mahoney int len = 0; 14223b02a68aSJeff Mahoney int i; 14233b02a68aSJeff Mahoney char *str; 14243b02a68aSJeff Mahoney 14253b02a68aSJeff Mahoney str = kmalloc(bufsize, GFP_KERNEL); 14263b02a68aSJeff Mahoney if (!str) 14273b02a68aSJeff Mahoney return str; 14283b02a68aSJeff Mahoney 14293b02a68aSJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 14303b02a68aSJeff Mahoney const char *name; 14313b02a68aSJeff Mahoney 14323b02a68aSJeff Mahoney if (!(flags & (1ULL << i))) 14333b02a68aSJeff Mahoney continue; 14343b02a68aSJeff Mahoney 14353b02a68aSJeff Mahoney name = btrfs_feature_attrs[set][i].kobj_attr.attr.name; 1436abdd9febSTakashi Iwai len += scnprintf(str + len, bufsize - len, "%s%s", 14373b02a68aSJeff Mahoney len ? "," : "", name); 14383b02a68aSJeff Mahoney } 14393b02a68aSJeff Mahoney 14403b02a68aSJeff Mahoney return str; 14413b02a68aSJeff Mahoney } 14423b02a68aSJeff Mahoney 144379da4fa4SJeff Mahoney static void init_feature_attrs(void) 144479da4fa4SJeff Mahoney { 144579da4fa4SJeff Mahoney struct btrfs_feature_attr *fa; 144679da4fa4SJeff Mahoney int set, i; 144779da4fa4SJeff Mahoney 14483b02a68aSJeff Mahoney memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs)); 14493b02a68aSJeff Mahoney memset(btrfs_unknown_feature_names, 0, 14503b02a68aSJeff Mahoney sizeof(btrfs_unknown_feature_names)); 14513b02a68aSJeff Mahoney 145279da4fa4SJeff Mahoney for (i = 0; btrfs_supported_feature_attrs[i]; i++) { 145379da4fa4SJeff Mahoney struct btrfs_feature_attr *sfa; 145479da4fa4SJeff Mahoney struct attribute *a = btrfs_supported_feature_attrs[i]; 14553b02a68aSJeff Mahoney int bit; 145679da4fa4SJeff Mahoney sfa = attr_to_btrfs_feature_attr(a); 14573b02a68aSJeff Mahoney bit = ilog2(sfa->feature_bit); 14583b02a68aSJeff Mahoney fa = &btrfs_feature_attrs[sfa->feature_set][bit]; 145979da4fa4SJeff Mahoney 146079da4fa4SJeff Mahoney fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name; 146179da4fa4SJeff Mahoney } 146279da4fa4SJeff Mahoney 146379da4fa4SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 146479da4fa4SJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 146579da4fa4SJeff Mahoney char *name = btrfs_unknown_feature_names[set][i]; 146679da4fa4SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 146779da4fa4SJeff Mahoney 146879da4fa4SJeff Mahoney if (fa->kobj_attr.attr.name) 146979da4fa4SJeff Mahoney continue; 147079da4fa4SJeff Mahoney 14716c52157fSTomohiro Misono snprintf(name, BTRFS_FEATURE_NAME_MAX, "%s:%u", 147279da4fa4SJeff Mahoney btrfs_feature_set_names[set], i); 147379da4fa4SJeff Mahoney 147479da4fa4SJeff Mahoney fa->kobj_attr.attr.name = name; 147579da4fa4SJeff Mahoney fa->kobj_attr.attr.mode = S_IRUGO; 147679da4fa4SJeff Mahoney fa->feature_set = set; 147779da4fa4SJeff Mahoney fa->feature_bit = 1ULL << i; 147879da4fa4SJeff Mahoney } 147979da4fa4SJeff Mahoney } 148079da4fa4SJeff Mahoney } 148179da4fa4SJeff Mahoney 148232a9991fSDavid Sterba /* 148332a9991fSDavid Sterba * Create a sysfs entry for a given block group type at path 148432a9991fSDavid Sterba * /sys/fs/btrfs/UUID/allocation/data/TYPE 148532a9991fSDavid Sterba */ 148632da5386SDavid Sterba void btrfs_sysfs_add_block_group_type(struct btrfs_block_group *cache) 148732a9991fSDavid Sterba { 148832a9991fSDavid Sterba struct btrfs_fs_info *fs_info = cache->fs_info; 148932a9991fSDavid Sterba struct btrfs_space_info *space_info = cache->space_info; 149032a9991fSDavid Sterba struct raid_kobject *rkobj; 149132a9991fSDavid Sterba const int index = btrfs_bg_flags_to_raid_index(cache->flags); 149232a9991fSDavid Sterba unsigned int nofs_flag; 149332a9991fSDavid Sterba int ret; 149432a9991fSDavid Sterba 149532a9991fSDavid Sterba /* 149632a9991fSDavid Sterba * Setup a NOFS context because kobject_add(), deep in its call chain, 149732a9991fSDavid Sterba * does GFP_KERNEL allocations, and we are often called in a context 149832a9991fSDavid Sterba * where if reclaim is triggered we can deadlock (we are either holding 149932a9991fSDavid Sterba * a transaction handle or some lock required for a transaction 150032a9991fSDavid Sterba * commit). 150132a9991fSDavid Sterba */ 150232a9991fSDavid Sterba nofs_flag = memalloc_nofs_save(); 150332a9991fSDavid Sterba 150432a9991fSDavid Sterba rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS); 150532a9991fSDavid Sterba if (!rkobj) { 150632a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 150732a9991fSDavid Sterba btrfs_warn(cache->fs_info, 150832a9991fSDavid Sterba "couldn't alloc memory for raid level kobject"); 150932a9991fSDavid Sterba return; 151032a9991fSDavid Sterba } 151132a9991fSDavid Sterba 151232a9991fSDavid Sterba rkobj->flags = cache->flags; 151332a9991fSDavid Sterba kobject_init(&rkobj->kobj, &btrfs_raid_ktype); 151449ea112dSJosef Bacik 151549ea112dSJosef Bacik /* 151649ea112dSJosef Bacik * We call this either on mount, or if we've created a block group for a 151749ea112dSJosef Bacik * new index type while running (i.e. when restriping). The running 151849ea112dSJosef Bacik * case is tricky because we could race with other threads, so we need 151949ea112dSJosef Bacik * to have this check to make sure we didn't already init the kobject. 152049ea112dSJosef Bacik * 152149ea112dSJosef Bacik * We don't have to protect on the free side because it only happens on 152249ea112dSJosef Bacik * unmount. 152349ea112dSJosef Bacik */ 152449ea112dSJosef Bacik spin_lock(&space_info->lock); 152549ea112dSJosef Bacik if (space_info->block_group_kobjs[index]) { 152649ea112dSJosef Bacik spin_unlock(&space_info->lock); 152749ea112dSJosef Bacik kobject_put(&rkobj->kobj); 152849ea112dSJosef Bacik return; 152949ea112dSJosef Bacik } else { 153049ea112dSJosef Bacik space_info->block_group_kobjs[index] = &rkobj->kobj; 153149ea112dSJosef Bacik } 153249ea112dSJosef Bacik spin_unlock(&space_info->lock); 153349ea112dSJosef Bacik 153432a9991fSDavid Sterba ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s", 153532a9991fSDavid Sterba btrfs_bg_type_to_raid_name(rkobj->flags)); 153632a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 153732a9991fSDavid Sterba if (ret) { 153849ea112dSJosef Bacik spin_lock(&space_info->lock); 153949ea112dSJosef Bacik space_info->block_group_kobjs[index] = NULL; 154049ea112dSJosef Bacik spin_unlock(&space_info->lock); 154132a9991fSDavid Sterba kobject_put(&rkobj->kobj); 154232a9991fSDavid Sterba btrfs_warn(fs_info, 154332a9991fSDavid Sterba "failed to add kobject for block cache, ignoring"); 154432a9991fSDavid Sterba return; 154532a9991fSDavid Sterba } 154632a9991fSDavid Sterba } 154732a9991fSDavid Sterba 1548b5865babSDavid Sterba /* 1549b5865babSDavid Sterba * Remove sysfs directories for all block group types of a given space info and 1550b5865babSDavid Sterba * the space info as well 1551b5865babSDavid Sterba */ 1552b5865babSDavid Sterba void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info) 1553b5865babSDavid Sterba { 1554b5865babSDavid Sterba int i; 1555b5865babSDavid Sterba 1556b5865babSDavid Sterba for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { 1557b5865babSDavid Sterba struct kobject *kobj; 1558b5865babSDavid Sterba 1559b5865babSDavid Sterba kobj = space_info->block_group_kobjs[i]; 1560b5865babSDavid Sterba space_info->block_group_kobjs[i] = NULL; 1561b5865babSDavid Sterba if (kobj) { 1562b5865babSDavid Sterba kobject_del(kobj); 1563b5865babSDavid Sterba kobject_put(kobj); 1564b5865babSDavid Sterba } 1565b5865babSDavid Sterba } 1566b5865babSDavid Sterba kobject_del(&space_info->kobj); 1567b5865babSDavid Sterba kobject_put(&space_info->kobj); 1568b5865babSDavid Sterba } 1569b5865babSDavid Sterba 1570b882327aSDavid Sterba static const char *alloc_name(u64 flags) 1571b882327aSDavid Sterba { 1572b882327aSDavid Sterba switch (flags) { 1573b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA: 1574b882327aSDavid Sterba return "mixed"; 1575b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA: 1576b882327aSDavid Sterba return "metadata"; 1577b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_DATA: 1578b882327aSDavid Sterba return "data"; 1579b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_SYSTEM: 1580b882327aSDavid Sterba return "system"; 1581b882327aSDavid Sterba default: 1582b882327aSDavid Sterba WARN_ON(1); 1583b882327aSDavid Sterba return "invalid-combination"; 1584445d8ab5STom Rix } 1585b882327aSDavid Sterba } 1586b882327aSDavid Sterba 1587b882327aSDavid Sterba /* 1588b882327aSDavid Sterba * Create a sysfs entry for a space info type at path 1589b882327aSDavid Sterba * /sys/fs/btrfs/UUID/allocation/TYPE 1590b882327aSDavid Sterba */ 1591b882327aSDavid Sterba int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info, 1592b882327aSDavid Sterba struct btrfs_space_info *space_info) 1593b882327aSDavid Sterba { 1594b882327aSDavid Sterba int ret; 1595b882327aSDavid Sterba 1596b882327aSDavid Sterba ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, 1597b882327aSDavid Sterba fs_info->space_info_kobj, "%s", 1598b882327aSDavid Sterba alloc_name(space_info->flags)); 1599b882327aSDavid Sterba if (ret) { 1600b882327aSDavid Sterba kobject_put(&space_info->kobj); 1601b882327aSDavid Sterba return ret; 1602b882327aSDavid Sterba } 1603b882327aSDavid Sterba 1604b882327aSDavid Sterba return 0; 1605b882327aSDavid Sterba } 1606b882327aSDavid Sterba 160753f8a74cSAnand Jain void btrfs_sysfs_remove_device(struct btrfs_device *device) 160899994cdeSAnand Jain { 1609985e233eSAnand Jain struct kobject *devices_kobj; 161099994cdeSAnand Jain 1611985e233eSAnand Jain /* 1612985e233eSAnand Jain * Seed fs_devices devices_kobj aren't used, fetch kobject from the 1613985e233eSAnand Jain * fs_info::fs_devices. 1614985e233eSAnand Jain */ 1615985e233eSAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1616985e233eSAnand Jain ASSERT(devices_kobj); 161799994cdeSAnand Jain 16188d65269fSChristoph Hellwig if (device->bdev) 16198d65269fSChristoph Hellwig sysfs_remove_link(devices_kobj, bdev_kobj(device->bdev)->name); 162099994cdeSAnand Jain 1621985e233eSAnand Jain if (device->devid_kobj.state_initialized) { 1622985e233eSAnand Jain kobject_del(&device->devid_kobj); 1623985e233eSAnand Jain kobject_put(&device->devid_kobj); 1624985e233eSAnand Jain wait_for_completion(&device->kobj_unregister); 1625985e233eSAnand Jain } 1626b5ddcffaSAnand Jain } 1627668e48afSAnand Jain 1628668e48afSAnand Jain static ssize_t btrfs_devinfo_in_fs_metadata_show(struct kobject *kobj, 1629668e48afSAnand Jain struct kobj_attribute *a, 1630668e48afSAnand Jain char *buf) 1631668e48afSAnand Jain { 1632668e48afSAnand Jain int val; 1633668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1634668e48afSAnand Jain devid_kobj); 1635668e48afSAnand Jain 1636668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state); 1637668e48afSAnand Jain 1638020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1639668e48afSAnand Jain } 1640668e48afSAnand Jain BTRFS_ATTR(devid, in_fs_metadata, btrfs_devinfo_in_fs_metadata_show); 1641668e48afSAnand Jain 164225864778SAnand Jain static ssize_t btrfs_devinfo_missing_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_MISSING, &device->dev_state); 1650668e48afSAnand Jain 1651020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1652668e48afSAnand Jain } 165325864778SAnand Jain BTRFS_ATTR(devid, missing, btrfs_devinfo_missing_show); 1654668e48afSAnand Jain 1655668e48afSAnand Jain static ssize_t btrfs_devinfo_replace_target_show(struct kobject *kobj, 1656668e48afSAnand Jain struct kobj_attribute *a, 1657668e48afSAnand Jain char *buf) 1658668e48afSAnand Jain { 1659668e48afSAnand Jain int val; 1660668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1661668e48afSAnand Jain devid_kobj); 1662668e48afSAnand Jain 1663668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state); 1664668e48afSAnand Jain 1665020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1666668e48afSAnand Jain } 1667668e48afSAnand Jain BTRFS_ATTR(devid, replace_target, btrfs_devinfo_replace_target_show); 1668668e48afSAnand Jain 1669eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_show(struct kobject *kobj, 1670eb3b5053SDavid Sterba struct kobj_attribute *a, 1671eb3b5053SDavid Sterba char *buf) 1672eb3b5053SDavid Sterba { 1673eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1674eb3b5053SDavid Sterba devid_kobj); 1675eb3b5053SDavid Sterba 1676020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", READ_ONCE(device->scrub_speed_max)); 1677eb3b5053SDavid Sterba } 1678eb3b5053SDavid Sterba 1679eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_store(struct kobject *kobj, 1680eb3b5053SDavid Sterba struct kobj_attribute *a, 1681eb3b5053SDavid Sterba const char *buf, size_t len) 1682eb3b5053SDavid Sterba { 1683eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1684eb3b5053SDavid Sterba devid_kobj); 1685eb3b5053SDavid Sterba char *endptr; 1686eb3b5053SDavid Sterba unsigned long long limit; 1687eb3b5053SDavid Sterba 1688eb3b5053SDavid Sterba limit = memparse(buf, &endptr); 1689eb3b5053SDavid Sterba WRITE_ONCE(device->scrub_speed_max, limit); 1690eb3b5053SDavid Sterba return len; 1691eb3b5053SDavid Sterba } 1692eb3b5053SDavid Sterba BTRFS_ATTR_RW(devid, scrub_speed_max, btrfs_devinfo_scrub_speed_max_show, 1693eb3b5053SDavid Sterba btrfs_devinfo_scrub_speed_max_store); 1694eb3b5053SDavid Sterba 1695668e48afSAnand Jain static ssize_t btrfs_devinfo_writeable_show(struct kobject *kobj, 1696668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1697668e48afSAnand Jain { 1698668e48afSAnand Jain int val; 1699668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1700668e48afSAnand Jain devid_kobj); 1701668e48afSAnand Jain 1702668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state); 1703668e48afSAnand Jain 1704020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1705668e48afSAnand Jain } 1706668e48afSAnand Jain BTRFS_ATTR(devid, writeable, btrfs_devinfo_writeable_show); 1707668e48afSAnand Jain 1708a26d60deSAnand Jain static ssize_t btrfs_devinfo_fsid_show(struct kobject *kobj, 1709a26d60deSAnand Jain struct kobj_attribute *a, char *buf) 1710a26d60deSAnand Jain { 1711a26d60deSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1712a26d60deSAnand Jain devid_kobj); 1713a26d60deSAnand Jain 1714a26d60deSAnand Jain return sysfs_emit(buf, "%pU\n", device->fs_devices->fsid); 1715a26d60deSAnand Jain } 1716a26d60deSAnand Jain BTRFS_ATTR(devid, fsid, btrfs_devinfo_fsid_show); 1717a26d60deSAnand Jain 1718da658b57SDavid Sterba static ssize_t btrfs_devinfo_error_stats_show(struct kobject *kobj, 1719da658b57SDavid Sterba struct kobj_attribute *a, char *buf) 1720da658b57SDavid Sterba { 1721da658b57SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1722da658b57SDavid Sterba devid_kobj); 1723da658b57SDavid Sterba 1724da658b57SDavid Sterba if (!device->dev_stats_valid) 1725020e5277SAnand Jain return sysfs_emit(buf, "invalid\n"); 1726da658b57SDavid Sterba 1727da658b57SDavid Sterba /* 1728da658b57SDavid Sterba * Print all at once so we get a snapshot of all values from the same 1729da658b57SDavid Sterba * time. Keep them in sync and in order of definition of 1730da658b57SDavid Sterba * btrfs_dev_stat_values. 1731da658b57SDavid Sterba */ 1732020e5277SAnand Jain return sysfs_emit(buf, 1733da658b57SDavid Sterba "write_errs %d\n" 1734da658b57SDavid Sterba "read_errs %d\n" 1735da658b57SDavid Sterba "flush_errs %d\n" 1736da658b57SDavid Sterba "corruption_errs %d\n" 1737da658b57SDavid Sterba "generation_errs %d\n", 1738da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_WRITE_ERRS), 1739da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_READ_ERRS), 1740da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_FLUSH_ERRS), 1741da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_CORRUPTION_ERRS), 1742da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_GENERATION_ERRS)); 1743da658b57SDavid Sterba } 1744da658b57SDavid Sterba BTRFS_ATTR(devid, error_stats, btrfs_devinfo_error_stats_show); 1745da658b57SDavid Sterba 1746e7849e33SAnand Jain /* 1747e7849e33SAnand Jain * Information about one device. 1748e7849e33SAnand Jain * 1749e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/devinfo/<devid>/ 1750e7849e33SAnand Jain */ 1751668e48afSAnand Jain static struct attribute *devid_attrs[] = { 1752da658b57SDavid Sterba BTRFS_ATTR_PTR(devid, error_stats), 1753a26d60deSAnand Jain BTRFS_ATTR_PTR(devid, fsid), 1754668e48afSAnand Jain BTRFS_ATTR_PTR(devid, in_fs_metadata), 1755668e48afSAnand Jain BTRFS_ATTR_PTR(devid, missing), 1756668e48afSAnand Jain BTRFS_ATTR_PTR(devid, replace_target), 1757eb3b5053SDavid Sterba BTRFS_ATTR_PTR(devid, scrub_speed_max), 1758668e48afSAnand Jain BTRFS_ATTR_PTR(devid, writeable), 1759668e48afSAnand Jain NULL 1760668e48afSAnand Jain }; 1761668e48afSAnand Jain ATTRIBUTE_GROUPS(devid); 1762668e48afSAnand Jain 1763668e48afSAnand Jain static void btrfs_release_devid_kobj(struct kobject *kobj) 1764668e48afSAnand Jain { 1765668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1766668e48afSAnand Jain devid_kobj); 1767668e48afSAnand Jain 1768668e48afSAnand Jain memset(&device->devid_kobj, 0, sizeof(struct kobject)); 1769668e48afSAnand Jain complete(&device->kobj_unregister); 1770668e48afSAnand Jain } 1771668e48afSAnand Jain 1772668e48afSAnand Jain static struct kobj_type devid_ktype = { 1773668e48afSAnand Jain .sysfs_ops = &kobj_sysfs_ops, 1774668e48afSAnand Jain .default_groups = devid_groups, 1775668e48afSAnand Jain .release = btrfs_release_devid_kobj, 1776668e48afSAnand Jain }; 1777668e48afSAnand Jain 1778cd36da2eSAnand Jain int btrfs_sysfs_add_device(struct btrfs_device *device) 177929e5be24SJeff Mahoney { 1780178a16c9SAnand Jain int ret; 1781a47bd78dSJosef Bacik unsigned int nofs_flag; 1782178a16c9SAnand Jain struct kobject *devices_kobj; 1783178a16c9SAnand Jain struct kobject *devinfo_kobj; 1784178a16c9SAnand Jain 1785178a16c9SAnand Jain /* 1786178a16c9SAnand Jain * Make sure we use the fs_info::fs_devices to fetch the kobjects even 1787178a16c9SAnand Jain * for the seed fs_devices 1788178a16c9SAnand Jain */ 1789178a16c9SAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1790178a16c9SAnand Jain devinfo_kobj = device->fs_info->fs_devices->devinfo_kobj; 1791178a16c9SAnand Jain ASSERT(devices_kobj); 1792178a16c9SAnand Jain ASSERT(devinfo_kobj); 179329e5be24SJeff Mahoney 1794a47bd78dSJosef Bacik nofs_flag = memalloc_nofs_save(); 1795f085381eSAnand Jain 1796178a16c9SAnand Jain if (device->bdev) { 17978d65269fSChristoph Hellwig struct kobject *disk_kobj = bdev_kobj(device->bdev); 179829e5be24SJeff Mahoney 1799178a16c9SAnand Jain ret = sysfs_create_link(devices_kobj, disk_kobj, disk_kobj->name); 1800178a16c9SAnand Jain if (ret) { 1801178a16c9SAnand Jain btrfs_warn(device->fs_info, 1802178a16c9SAnand Jain "creating sysfs device link for devid %llu failed: %d", 1803178a16c9SAnand Jain device->devid, ret); 1804178a16c9SAnand Jain goto out; 1805178a16c9SAnand Jain } 180629e5be24SJeff Mahoney } 180729e5be24SJeff Mahoney 1808178a16c9SAnand Jain init_completion(&device->kobj_unregister); 1809178a16c9SAnand Jain ret = kobject_init_and_add(&device->devid_kobj, &devid_ktype, 1810178a16c9SAnand Jain devinfo_kobj, "%llu", device->devid); 1811178a16c9SAnand Jain if (ret) { 1812178a16c9SAnand Jain kobject_put(&device->devid_kobj); 1813178a16c9SAnand Jain btrfs_warn(device->fs_info, 1814178a16c9SAnand Jain "devinfo init for devid %llu failed: %d", 1815178a16c9SAnand Jain device->devid, ret); 1816668e48afSAnand Jain } 1817178a16c9SAnand Jain 1818178a16c9SAnand Jain out: 1819a47bd78dSJosef Bacik memalloc_nofs_restore(nofs_flag); 1820178a16c9SAnand Jain return ret; 1821178a16c9SAnand Jain } 1822668e48afSAnand Jain 1823cd36da2eSAnand Jain static int btrfs_sysfs_add_fs_devices(struct btrfs_fs_devices *fs_devices) 1824178a16c9SAnand Jain { 1825178a16c9SAnand Jain int ret; 1826cd36da2eSAnand Jain struct btrfs_device *device; 182730b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 1828178a16c9SAnand Jain 1829178a16c9SAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) { 1830178a16c9SAnand Jain ret = btrfs_sysfs_add_device(device); 1831178a16c9SAnand Jain if (ret) 18327ad3912aSAnand Jain goto fail; 1833178a16c9SAnand Jain } 1834178a16c9SAnand Jain 183530b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 183630b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) { 183730b0e4e0SAnand Jain ret = btrfs_sysfs_add_device(device); 183830b0e4e0SAnand Jain if (ret) 18397ad3912aSAnand Jain goto fail; 184030b0e4e0SAnand Jain } 184130b0e4e0SAnand Jain } 184230b0e4e0SAnand Jain 1843178a16c9SAnand Jain return 0; 18447ad3912aSAnand Jain 18457ad3912aSAnand Jain fail: 18467ad3912aSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devices); 18477ad3912aSAnand Jain return ret; 184829e5be24SJeff Mahoney } 184929e5be24SJeff Mahoney 18505b28692eSDavid Sterba void btrfs_kobject_uevent(struct block_device *bdev, enum kobject_action action) 18515b28692eSDavid Sterba { 18525b28692eSDavid Sterba int ret; 18535b28692eSDavid Sterba 18545b28692eSDavid Sterba ret = kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, action); 18555b28692eSDavid Sterba if (ret) 18565b28692eSDavid Sterba pr_warn("BTRFS: Sending event '%d' to kobject: '%s' (%p): failed\n", 18575b28692eSDavid Sterba action, kobject_name(&disk_to_dev(bdev->bd_disk)->kobj), 18585b28692eSDavid Sterba &disk_to_dev(bdev->bd_disk)->kobj); 18595b28692eSDavid Sterba } 18605b28692eSDavid Sterba 18618e560081SNikolay Borisov void btrfs_sysfs_update_sprout_fsid(struct btrfs_fs_devices *fs_devices) 18628e560081SNikolay Borisov 1863f93c3997SDavid Sterba { 1864f93c3997SDavid Sterba char fsid_buf[BTRFS_UUID_UNPARSED_SIZE]; 1865f93c3997SDavid Sterba 1866f93c3997SDavid Sterba /* 1867f93c3997SDavid Sterba * Sprouting changes fsid of the mounted filesystem, rename the fsid 1868f93c3997SDavid Sterba * directory 1869f93c3997SDavid Sterba */ 18708e560081SNikolay Borisov snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", fs_devices->fsid); 1871f93c3997SDavid Sterba if (kobject_rename(&fs_devices->fsid_kobj, fsid_buf)) 1872f93c3997SDavid Sterba btrfs_warn(fs_devices->fs_info, 1873f93c3997SDavid Sterba "sysfs: failed to create fsid for sprout"); 1874f93c3997SDavid Sterba } 1875f93c3997SDavid Sterba 1876668e48afSAnand Jain void btrfs_sysfs_update_devid(struct btrfs_device *device) 1877668e48afSAnand Jain { 1878668e48afSAnand Jain char tmp[24]; 1879668e48afSAnand Jain 1880668e48afSAnand Jain snprintf(tmp, sizeof(tmp), "%llu", device->devid); 1881668e48afSAnand Jain 1882668e48afSAnand Jain if (kobject_rename(&device->devid_kobj, tmp)) 1883668e48afSAnand Jain btrfs_warn(device->fs_devices->fs_info, 1884668e48afSAnand Jain "sysfs: failed to update devid for %llu", 1885668e48afSAnand Jain device->devid); 1886668e48afSAnand Jain } 1887668e48afSAnand Jain 1888510d7360SJeff Mahoney /* /sys/fs/btrfs/ entry */ 1889510d7360SJeff Mahoney static struct kset *btrfs_kset; 1890510d7360SJeff Mahoney 189172059215SAnand Jain /* 1892c6761a9eSAnand Jain * Creates: 1893c6761a9eSAnand Jain * /sys/fs/btrfs/UUID 1894c6761a9eSAnand Jain * 189572059215SAnand Jain * Can be called by the device discovery thread. 189672059215SAnand Jain */ 1897c6761a9eSAnand Jain int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs) 18985ac1d209SJeff Mahoney { 18995ac1d209SJeff Mahoney int error; 19005ac1d209SJeff Mahoney 19012e7910d6SAnand Jain init_completion(&fs_devs->kobj_unregister); 1902c1b7e474SAnand Jain fs_devs->fsid_kobj.kset = btrfs_kset; 1903c6761a9eSAnand Jain error = kobject_init_and_add(&fs_devs->fsid_kobj, &btrfs_ktype, NULL, 1904c6761a9eSAnand Jain "%pU", fs_devs->fsid); 1905e3277335STobin C. Harding if (error) { 1906e3277335STobin C. Harding kobject_put(&fs_devs->fsid_kobj); 190772059215SAnand Jain return error; 190872059215SAnand Jain } 190972059215SAnand Jain 1910bc036bb3SAnand Jain fs_devs->devices_kobj = kobject_create_and_add("devices", 1911bc036bb3SAnand Jain &fs_devs->fsid_kobj); 1912bc036bb3SAnand Jain if (!fs_devs->devices_kobj) { 1913bc036bb3SAnand Jain btrfs_err(fs_devs->fs_info, 1914bc036bb3SAnand Jain "failed to init sysfs device interface"); 19151f6087e6SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1916bc036bb3SAnand Jain return -ENOMEM; 1917bc036bb3SAnand Jain } 1918bc036bb3SAnand Jain 1919a013d141SAnand Jain fs_devs->devinfo_kobj = kobject_create_and_add("devinfo", 1920a013d141SAnand Jain &fs_devs->fsid_kobj); 1921a013d141SAnand Jain if (!fs_devs->devinfo_kobj) { 1922a013d141SAnand Jain btrfs_err(fs_devs->fs_info, 1923a013d141SAnand Jain "failed to init sysfs devinfo kobject"); 1924a013d141SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1925a013d141SAnand Jain return -ENOMEM; 1926a013d141SAnand Jain } 1927a013d141SAnand Jain 1928e3277335STobin C. Harding return 0; 1929e3277335STobin C. Harding } 1930e3277335STobin C. Harding 193196f3136eSAnand Jain int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info) 193272059215SAnand Jain { 193372059215SAnand Jain int error; 19342e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = fs_info->fs_devices; 1935c1b7e474SAnand Jain struct kobject *fsid_kobj = &fs_devs->fsid_kobj; 193672059215SAnand Jain 1937cd36da2eSAnand Jain error = btrfs_sysfs_add_fs_devices(fs_devs); 1938e453d989SJeff Mahoney if (error) 1939e453d989SJeff Mahoney return error; 1940510d7360SJeff Mahoney 1941c1b7e474SAnand Jain error = sysfs_create_files(fsid_kobj, btrfs_attrs); 1942e453d989SJeff Mahoney if (error) { 194353f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devs); 1944e453d989SJeff Mahoney return error; 1945e453d989SJeff Mahoney } 194679da4fa4SJeff Mahoney 1947c1b7e474SAnand Jain error = sysfs_create_group(fsid_kobj, 19480dd2906fSAnand Jain &btrfs_feature_attr_group); 19490dd2906fSAnand Jain if (error) 19500dd2906fSAnand Jain goto failure; 19510dd2906fSAnand Jain 19526e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 195393945cb4SDennis Zhou fs_info->debug_kobj = kobject_create_and_add("debug", fsid_kobj); 195493945cb4SDennis Zhou if (!fs_info->debug_kobj) { 195593945cb4SDennis Zhou error = -ENOMEM; 195693945cb4SDennis Zhou goto failure; 195793945cb4SDennis Zhou } 195893945cb4SDennis Zhou 195993945cb4SDennis Zhou error = sysfs_create_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 19606e369febSDavid Sterba if (error) 19616e369febSDavid Sterba goto failure; 1962e4faab84SDennis Zhou 1963e4faab84SDennis Zhou /* Discard directory */ 1964e4faab84SDennis Zhou fs_info->discard_debug_kobj = kobject_create_and_add("discard", 1965e4faab84SDennis Zhou fs_info->debug_kobj); 1966e4faab84SDennis Zhou if (!fs_info->discard_debug_kobj) { 1967e4faab84SDennis Zhou error = -ENOMEM; 1968e4faab84SDennis Zhou goto failure; 1969e4faab84SDennis Zhou } 1970e4faab84SDennis Zhou 1971e4faab84SDennis Zhou error = sysfs_create_files(fs_info->discard_debug_kobj, 1972e4faab84SDennis Zhou discard_debug_attrs); 1973e4faab84SDennis Zhou if (error) 1974e4faab84SDennis Zhou goto failure; 19756e369febSDavid Sterba #endif 19766e369febSDavid Sterba 1977e453d989SJeff Mahoney error = addrm_unknown_feature_attrs(fs_info, true); 197879da4fa4SJeff Mahoney if (error) 197979da4fa4SJeff Mahoney goto failure; 198079da4fa4SJeff Mahoney 19813092c68fSNikolay Borisov error = sysfs_create_link(fsid_kobj, &fs_info->sb->s_bdi->dev->kobj, "bdi"); 19823092c68fSNikolay Borisov if (error) 19833092c68fSNikolay Borisov goto failure; 19843092c68fSNikolay Borisov 19856ab0a202SJeff Mahoney fs_info->space_info_kobj = kobject_create_and_add("allocation", 1986c1b7e474SAnand Jain fsid_kobj); 19876ab0a202SJeff Mahoney if (!fs_info->space_info_kobj) { 19886ab0a202SJeff Mahoney error = -ENOMEM; 19896ab0a202SJeff Mahoney goto failure; 19906ab0a202SJeff Mahoney } 19916ab0a202SJeff Mahoney 19926ab0a202SJeff Mahoney error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs); 19936ab0a202SJeff Mahoney if (error) 19946ab0a202SJeff Mahoney goto failure; 19956ab0a202SJeff Mahoney 199679da4fa4SJeff Mahoney return 0; 199779da4fa4SJeff Mahoney failure: 19986618a59bSAnand Jain btrfs_sysfs_remove_mounted(fs_info); 19995ac1d209SJeff Mahoney return error; 20005ac1d209SJeff Mahoney } 20015ac1d209SJeff Mahoney 200249e5fb46SQu Wenruo static inline struct btrfs_fs_info *qgroup_kobj_to_fs_info(struct kobject *kobj) 200349e5fb46SQu Wenruo { 200449e5fb46SQu Wenruo return to_fs_info(kobj->parent->parent); 200549e5fb46SQu Wenruo } 200649e5fb46SQu Wenruo 200749e5fb46SQu Wenruo #define QGROUP_ATTR(_member, _show_name) \ 200849e5fb46SQu Wenruo static ssize_t btrfs_qgroup_show_##_member(struct kobject *qgroup_kobj, \ 200949e5fb46SQu Wenruo struct kobj_attribute *a, \ 201049e5fb46SQu Wenruo char *buf) \ 201149e5fb46SQu Wenruo { \ 201249e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 201349e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 201449e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 201549e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->_member, &fs_info->qgroup_lock, buf); \ 201649e5fb46SQu Wenruo } \ 201749e5fb46SQu Wenruo BTRFS_ATTR(qgroup, _show_name, btrfs_qgroup_show_##_member) 201849e5fb46SQu Wenruo 201949e5fb46SQu Wenruo #define QGROUP_RSV_ATTR(_name, _type) \ 202049e5fb46SQu Wenruo static ssize_t btrfs_qgroup_rsv_show_##_name(struct kobject *qgroup_kobj, \ 202149e5fb46SQu Wenruo struct kobj_attribute *a, \ 202249e5fb46SQu Wenruo char *buf) \ 202349e5fb46SQu Wenruo { \ 202449e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 202549e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 202649e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 202749e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->rsv.values[_type], \ 202849e5fb46SQu Wenruo &fs_info->qgroup_lock, buf); \ 202949e5fb46SQu Wenruo } \ 203049e5fb46SQu Wenruo BTRFS_ATTR(qgroup, rsv_##_name, btrfs_qgroup_rsv_show_##_name) 203149e5fb46SQu Wenruo 203249e5fb46SQu Wenruo QGROUP_ATTR(rfer, referenced); 203349e5fb46SQu Wenruo QGROUP_ATTR(excl, exclusive); 203449e5fb46SQu Wenruo QGROUP_ATTR(max_rfer, max_referenced); 203549e5fb46SQu Wenruo QGROUP_ATTR(max_excl, max_exclusive); 203649e5fb46SQu Wenruo QGROUP_ATTR(lim_flags, limit_flags); 203749e5fb46SQu Wenruo QGROUP_RSV_ATTR(data, BTRFS_QGROUP_RSV_DATA); 203849e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_pertrans, BTRFS_QGROUP_RSV_META_PERTRANS); 203949e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_prealloc, BTRFS_QGROUP_RSV_META_PREALLOC); 204049e5fb46SQu Wenruo 2041e7849e33SAnand Jain /* 2042e7849e33SAnand Jain * Qgroup information. 2043e7849e33SAnand Jain * 2044e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/qgroups/<level>_<qgroupid>/ 2045e7849e33SAnand Jain */ 204649e5fb46SQu Wenruo static struct attribute *qgroup_attrs[] = { 204749e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, referenced), 204849e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, exclusive), 204949e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_referenced), 205049e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_exclusive), 205149e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, limit_flags), 205249e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_data), 205349e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_pertrans), 205449e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_prealloc), 205549e5fb46SQu Wenruo NULL 205649e5fb46SQu Wenruo }; 205749e5fb46SQu Wenruo ATTRIBUTE_GROUPS(qgroup); 205849e5fb46SQu Wenruo 205949e5fb46SQu Wenruo static void qgroup_release(struct kobject *kobj) 206049e5fb46SQu Wenruo { 206149e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(kobj, struct btrfs_qgroup, kobj); 206249e5fb46SQu Wenruo 206349e5fb46SQu Wenruo memset(&qgroup->kobj, 0, sizeof(*kobj)); 206449e5fb46SQu Wenruo } 206549e5fb46SQu Wenruo 206649e5fb46SQu Wenruo static struct kobj_type qgroup_ktype = { 206749e5fb46SQu Wenruo .sysfs_ops = &kobj_sysfs_ops, 206849e5fb46SQu Wenruo .release = qgroup_release, 206949e5fb46SQu Wenruo .default_groups = qgroup_groups, 207049e5fb46SQu Wenruo }; 207149e5fb46SQu Wenruo 207249e5fb46SQu Wenruo int btrfs_sysfs_add_one_qgroup(struct btrfs_fs_info *fs_info, 207349e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 207449e5fb46SQu Wenruo { 207549e5fb46SQu Wenruo struct kobject *qgroups_kobj = fs_info->qgroups_kobj; 207649e5fb46SQu Wenruo int ret; 207749e5fb46SQu Wenruo 207849e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 207949e5fb46SQu Wenruo return 0; 208049e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) 208149e5fb46SQu Wenruo return 0; 208249e5fb46SQu Wenruo if (!qgroups_kobj) 208349e5fb46SQu Wenruo return -EINVAL; 208449e5fb46SQu Wenruo 208549e5fb46SQu Wenruo ret = kobject_init_and_add(&qgroup->kobj, &qgroup_ktype, qgroups_kobj, 208649e5fb46SQu Wenruo "%hu_%llu", btrfs_qgroup_level(qgroup->qgroupid), 208749e5fb46SQu Wenruo btrfs_qgroup_subvolid(qgroup->qgroupid)); 208849e5fb46SQu Wenruo if (ret < 0) 208949e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 209049e5fb46SQu Wenruo 209149e5fb46SQu Wenruo return ret; 209249e5fb46SQu Wenruo } 209349e5fb46SQu Wenruo 209449e5fb46SQu Wenruo void btrfs_sysfs_del_qgroups(struct btrfs_fs_info *fs_info) 209549e5fb46SQu Wenruo { 209649e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 209749e5fb46SQu Wenruo struct btrfs_qgroup *next; 209849e5fb46SQu Wenruo 209949e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 210049e5fb46SQu Wenruo return; 210149e5fb46SQu Wenruo 210249e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 210349e5fb46SQu Wenruo &fs_info->qgroup_tree, node) 210449e5fb46SQu Wenruo btrfs_sysfs_del_one_qgroup(fs_info, qgroup); 210562ab2cc0SQu Wenruo if (fs_info->qgroups_kobj) { 210649e5fb46SQu Wenruo kobject_del(fs_info->qgroups_kobj); 210749e5fb46SQu Wenruo kobject_put(fs_info->qgroups_kobj); 210849e5fb46SQu Wenruo fs_info->qgroups_kobj = NULL; 210949e5fb46SQu Wenruo } 211062ab2cc0SQu Wenruo } 211149e5fb46SQu Wenruo 211249e5fb46SQu Wenruo /* Called when qgroups get initialized, thus there is no need for locking */ 211349e5fb46SQu Wenruo int btrfs_sysfs_add_qgroups(struct btrfs_fs_info *fs_info) 211449e5fb46SQu Wenruo { 211549e5fb46SQu Wenruo struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 211649e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 211749e5fb46SQu Wenruo struct btrfs_qgroup *next; 211849e5fb46SQu Wenruo int ret = 0; 211949e5fb46SQu Wenruo 212049e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 212149e5fb46SQu Wenruo return 0; 212249e5fb46SQu Wenruo 212349e5fb46SQu Wenruo ASSERT(fsid_kobj); 212449e5fb46SQu Wenruo if (fs_info->qgroups_kobj) 212549e5fb46SQu Wenruo return 0; 212649e5fb46SQu Wenruo 212749e5fb46SQu Wenruo fs_info->qgroups_kobj = kobject_create_and_add("qgroups", fsid_kobj); 212849e5fb46SQu Wenruo if (!fs_info->qgroups_kobj) { 212949e5fb46SQu Wenruo ret = -ENOMEM; 213049e5fb46SQu Wenruo goto out; 213149e5fb46SQu Wenruo } 213249e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 213349e5fb46SQu Wenruo &fs_info->qgroup_tree, node) { 213449e5fb46SQu Wenruo ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup); 213549e5fb46SQu Wenruo if (ret < 0) 213649e5fb46SQu Wenruo goto out; 213749e5fb46SQu Wenruo } 213849e5fb46SQu Wenruo 213949e5fb46SQu Wenruo out: 214049e5fb46SQu Wenruo if (ret < 0) 214149e5fb46SQu Wenruo btrfs_sysfs_del_qgroups(fs_info); 214249e5fb46SQu Wenruo return ret; 214349e5fb46SQu Wenruo } 214449e5fb46SQu Wenruo 214549e5fb46SQu Wenruo void btrfs_sysfs_del_one_qgroup(struct btrfs_fs_info *fs_info, 214649e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 214749e5fb46SQu Wenruo { 214849e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 214949e5fb46SQu Wenruo return; 215049e5fb46SQu Wenruo 215149e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) { 215249e5fb46SQu Wenruo kobject_del(&qgroup->kobj); 215349e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 215449e5fb46SQu Wenruo } 215549e5fb46SQu Wenruo } 2156444e7516SDavid Sterba 2157444e7516SDavid Sterba /* 2158444e7516SDavid Sterba * Change per-fs features in /sys/fs/btrfs/UUID/features to match current 2159444e7516SDavid Sterba * values in superblock. Call after any changes to incompat/compat_ro flags 2160444e7516SDavid Sterba */ 2161444e7516SDavid Sterba void btrfs_sysfs_feature_update(struct btrfs_fs_info *fs_info, 2162444e7516SDavid Sterba u64 bit, enum btrfs_feature_set set) 2163444e7516SDavid Sterba { 2164444e7516SDavid Sterba struct btrfs_fs_devices *fs_devs; 2165444e7516SDavid Sterba struct kobject *fsid_kobj; 216624646481SLeon Romanovsky u64 __maybe_unused features; 216724646481SLeon Romanovsky int __maybe_unused ret; 2168444e7516SDavid Sterba 2169444e7516SDavid Sterba if (!fs_info) 2170444e7516SDavid Sterba return; 2171444e7516SDavid Sterba 217224646481SLeon Romanovsky /* 217324646481SLeon Romanovsky * See 14e46e04958df74 and e410e34fad913dd, feature bit updates are not 217424646481SLeon Romanovsky * safe when called from some contexts (eg. balance) 217524646481SLeon Romanovsky */ 2176444e7516SDavid Sterba features = get_features(fs_info, set); 2177444e7516SDavid Sterba ASSERT(bit & supported_feature_masks[set]); 2178444e7516SDavid Sterba 2179444e7516SDavid Sterba fs_devs = fs_info->fs_devices; 2180444e7516SDavid Sterba fsid_kobj = &fs_devs->fsid_kobj; 2181444e7516SDavid Sterba 2182bf609206SDavid Sterba if (!fsid_kobj->state_initialized) 2183bf609206SDavid Sterba return; 2184bf609206SDavid Sterba 2185444e7516SDavid Sterba /* 2186444e7516SDavid Sterba * FIXME: this is too heavy to update just one value, ideally we'd like 2187444e7516SDavid Sterba * to use sysfs_update_group but some refactoring is needed first. 2188444e7516SDavid Sterba */ 2189444e7516SDavid Sterba sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 2190444e7516SDavid Sterba ret = sysfs_create_group(fsid_kobj, &btrfs_feature_attr_group); 2191444e7516SDavid Sterba } 2192444e7516SDavid Sterba 2193f5c29bd9SLiu Bo int __init btrfs_init_sysfs(void) 219458176a96SJosef Bacik { 2195079b72bcSJeff Mahoney int ret; 21961bae3098SDavid Sterba 2197e3fe4e71SGreg KH btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); 2198e3fe4e71SGreg KH if (!btrfs_kset) 2199e3fe4e71SGreg KH return -ENOMEM; 2200079b72bcSJeff Mahoney 22011bae3098SDavid Sterba init_feature_attrs(); 22021bae3098SDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2203001a648dSFilipe Manana if (ret) 2204001a648dSFilipe Manana goto out2; 2205f902bd3aSMisono Tomohiro ret = sysfs_merge_group(&btrfs_kset->kobj, 2206f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2207f902bd3aSMisono Tomohiro if (ret) 2208f902bd3aSMisono Tomohiro goto out_remove_group; 2209001a648dSFilipe Manana 22106e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 22116e369febSDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 22126e369febSDavid Sterba if (ret) 22136e369febSDavid Sterba goto out2; 22146e369febSDavid Sterba #endif 22156e369febSDavid Sterba 2216001a648dSFilipe Manana return 0; 2217f902bd3aSMisono Tomohiro 2218f902bd3aSMisono Tomohiro out_remove_group: 2219f902bd3aSMisono Tomohiro sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2220001a648dSFilipe Manana out2: 2221001a648dSFilipe Manana kset_unregister(btrfs_kset); 22221bae3098SDavid Sterba 22231bae3098SDavid Sterba return ret; 222458176a96SJosef Bacik } 222558176a96SJosef Bacik 2226e67c718bSDavid Sterba void __cold btrfs_exit_sysfs(void) 222758176a96SJosef Bacik { 2228f902bd3aSMisono Tomohiro sysfs_unmerge_group(&btrfs_kset->kobj, 2229f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2230079b72bcSJeff Mahoney sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 223171e8978eSDennis Zhou #ifdef CONFIG_BTRFS_DEBUG 223271e8978eSDennis Zhou sysfs_remove_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 223371e8978eSDennis Zhou #endif 2234e3fe4e71SGreg KH kset_unregister(btrfs_kset); 223558176a96SJosef Bacik } 223655d47414SChris Mason 2237