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> 38fb731430SDavid Sterba * discard_attrs /sys/fs/btrfs/<uuid>/discard 39e7849e33SAnand Jain * 40e7849e33SAnand Jain * When built with BTRFS_CONFIG_DEBUG: 41e7849e33SAnand Jain * 42e7849e33SAnand Jain * btrfs_debug_feature_attrs /sys/fs/btrfs/debug 43e7849e33SAnand Jain * btrfs_debug_mount_attrs /sys/fs/btrfs/<uuid>/debug 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 6522c55e3bSStefan Roesch #define BTRFS_ATTR_W(_prefix, _name, _store) \ 6622c55e3bSStefan Roesch static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 6722c55e3bSStefan Roesch __INIT_KOBJ_ATTR(_name, 0200, NULL, _store) 6822c55e3bSStefan 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(default_subvol, DEFAULT_SUBVOL); 280079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS); 281079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO); 2825c1aab1dSNick Terrell BTRFS_FEAT_ATTR_INCOMPAT(compress_zstd, COMPRESS_ZSTD); 283079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF); 284079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56); 285079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA); 286c736c095SDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES); 28756f20f40SNikolay Borisov BTRFS_FEAT_ATTR_INCOMPAT(metadata_uuid, METADATA_UUID); 2883b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE); 2891c56ab99SQu Wenruo BTRFS_FEAT_ATTR_COMPAT_RO(block_group_tree, BLOCK_GROUP_TREE); 290cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(raid1c34, RAID1C34); 29115dcccdbSDavid Sterba #ifdef CONFIG_BLK_DEV_ZONED 2927b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_INCOMPAT(zoned, ZONED); 29315dcccdbSDavid Sterba #endif 29415dcccdbSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 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(default_subvol), 311079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_groups), 312079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(compress_lzo), 3135c1aab1dSNick Terrell BTRFS_FEAT_ATTR_PTR(compress_zstd), 314079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(extended_iref), 315079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(raid56), 316079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(skinny_metadata), 317c736c095SDavid Sterba BTRFS_FEAT_ATTR_PTR(no_holes), 31856f20f40SNikolay Borisov BTRFS_FEAT_ATTR_PTR(metadata_uuid), 3193b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_PTR(free_space_tree), 320cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_PTR(raid1c34), 3211c56ab99SQu Wenruo BTRFS_FEAT_ATTR_PTR(block_group_tree), 32215dcccdbSDavid Sterba #ifdef CONFIG_BLK_DEV_ZONED 3237b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_PTR(zoned), 32415dcccdbSDavid Sterba #endif 32515dcccdbSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 3262c7d2a23SJosef Bacik BTRFS_FEAT_ATTR_PTR(extent_tree_v2), 3277b3d5a90SNaohiro Aota #endif 32814605409SBoris Burkov #ifdef CONFIG_FS_VERITY 32914605409SBoris Burkov BTRFS_FEAT_ATTR_PTR(verity), 33014605409SBoris Burkov #endif 331079b72bcSJeff Mahoney NULL 332079b72bcSJeff Mahoney }; 333079b72bcSJeff Mahoney 334079b72bcSJeff Mahoney static const struct attribute_group btrfs_feature_attr_group = { 335079b72bcSJeff Mahoney .name = "features", 336510d7360SJeff Mahoney .is_visible = btrfs_feature_visible, 337079b72bcSJeff Mahoney .attrs = btrfs_supported_feature_attrs, 338079b72bcSJeff Mahoney }; 33958176a96SJosef Bacik 340f902bd3aSMisono Tomohiro static ssize_t rmdir_subvol_show(struct kobject *kobj, 341f902bd3aSMisono Tomohiro struct kobj_attribute *ka, char *buf) 342f902bd3aSMisono Tomohiro { 343020e5277SAnand Jain return sysfs_emit(buf, "0\n"); 344f902bd3aSMisono Tomohiro } 345f902bd3aSMisono Tomohiro BTRFS_ATTR(static_feature, rmdir_subvol, rmdir_subvol_show); 346f902bd3aSMisono Tomohiro 347f7cea56cSDavid Sterba static ssize_t supported_checksums_show(struct kobject *kobj, 348f7cea56cSDavid Sterba struct kobj_attribute *a, char *buf) 349f7cea56cSDavid Sterba { 350f7cea56cSDavid Sterba ssize_t ret = 0; 351f7cea56cSDavid Sterba int i; 352f7cea56cSDavid Sterba 353f7cea56cSDavid Sterba for (i = 0; i < btrfs_get_num_csums(); i++) { 354f7cea56cSDavid Sterba /* 355f7cea56cSDavid Sterba * This "trick" only works as long as 'enum btrfs_csum_type' has 356f7cea56cSDavid Sterba * no holes in it 357f7cea56cSDavid Sterba */ 358020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i == 0 ? "" : " "), 359020e5277SAnand Jain btrfs_super_csum_name(i)); 360f7cea56cSDavid Sterba 361f7cea56cSDavid Sterba } 362f7cea56cSDavid Sterba 363020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 364f7cea56cSDavid Sterba return ret; 365f7cea56cSDavid Sterba } 366f7cea56cSDavid Sterba BTRFS_ATTR(static_feature, supported_checksums, supported_checksums_show); 367f7cea56cSDavid Sterba 3687573df55SOmar Sandoval static ssize_t send_stream_version_show(struct kobject *kobj, 3697573df55SOmar Sandoval struct kobj_attribute *ka, char *buf) 3707573df55SOmar Sandoval { 371020e5277SAnand Jain return sysfs_emit(buf, "%d\n", BTRFS_SEND_STREAM_VERSION); 3727573df55SOmar Sandoval } 3737573df55SOmar Sandoval BTRFS_ATTR(static_feature, send_stream_version, send_stream_version_show); 3747573df55SOmar Sandoval 375ceafe3ccSJosef Bacik static const char *rescue_opts[] = { 376ceafe3ccSJosef Bacik "usebackuproot", 377ceafe3ccSJosef Bacik "nologreplay", 37842437a63SJosef Bacik "ignorebadroots", 379882dbe0cSJosef Bacik "ignoredatacsums", 3809037d3cbSJosef Bacik "all", 381ceafe3ccSJosef Bacik }; 382ceafe3ccSJosef Bacik 383ceafe3ccSJosef Bacik static ssize_t supported_rescue_options_show(struct kobject *kobj, 384ceafe3ccSJosef Bacik struct kobj_attribute *a, 385ceafe3ccSJosef Bacik char *buf) 386ceafe3ccSJosef Bacik { 387ceafe3ccSJosef Bacik ssize_t ret = 0; 388ceafe3ccSJosef Bacik int i; 389ceafe3ccSJosef Bacik 390ceafe3ccSJosef Bacik for (i = 0; i < ARRAY_SIZE(rescue_opts); i++) 391020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i ? " " : ""), rescue_opts[i]); 392020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 393ceafe3ccSJosef Bacik return ret; 394ceafe3ccSJosef Bacik } 395ceafe3ccSJosef Bacik BTRFS_ATTR(static_feature, supported_rescue_options, 396ceafe3ccSJosef Bacik supported_rescue_options_show); 397ceafe3ccSJosef Bacik 398fc57ad8dSQu Wenruo static ssize_t supported_sectorsizes_show(struct kobject *kobj, 399fc57ad8dSQu Wenruo struct kobj_attribute *a, 400fc57ad8dSQu Wenruo char *buf) 401fc57ad8dSQu Wenruo { 402fc57ad8dSQu Wenruo ssize_t ret = 0; 403fc57ad8dSQu Wenruo 4041a42daabSQu Wenruo /* An artificial limit to only support 4K and PAGE_SIZE */ 4051a42daabSQu Wenruo if (PAGE_SIZE > SZ_4K) 406020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%u ", SZ_4K); 407020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%lu\n", PAGE_SIZE); 408fc57ad8dSQu Wenruo 409fc57ad8dSQu Wenruo return ret; 410fc57ad8dSQu Wenruo } 411fc57ad8dSQu Wenruo BTRFS_ATTR(static_feature, supported_sectorsizes, 412fc57ad8dSQu Wenruo supported_sectorsizes_show); 413fc57ad8dSQu Wenruo 414e7849e33SAnand Jain /* 415e7849e33SAnand Jain * Features which only depend on kernel version. 416e7849e33SAnand Jain * 417e7849e33SAnand Jain * These are listed in /sys/fs/btrfs/features along with 418e7849e33SAnand Jain * btrfs_supported_feature_attrs. 419e7849e33SAnand Jain */ 420f902bd3aSMisono Tomohiro static struct attribute *btrfs_supported_static_feature_attrs[] = { 421f902bd3aSMisono Tomohiro BTRFS_ATTR_PTR(static_feature, rmdir_subvol), 422f7cea56cSDavid Sterba BTRFS_ATTR_PTR(static_feature, supported_checksums), 4237573df55SOmar Sandoval BTRFS_ATTR_PTR(static_feature, send_stream_version), 424ceafe3ccSJosef Bacik BTRFS_ATTR_PTR(static_feature, supported_rescue_options), 425fc57ad8dSQu Wenruo BTRFS_ATTR_PTR(static_feature, supported_sectorsizes), 426f902bd3aSMisono Tomohiro NULL 427f902bd3aSMisono Tomohiro }; 428f902bd3aSMisono Tomohiro 429f902bd3aSMisono Tomohiro static const struct attribute_group btrfs_static_feature_attr_group = { 430f902bd3aSMisono Tomohiro .name = "features", 431f902bd3aSMisono Tomohiro .attrs = btrfs_supported_static_feature_attrs, 432f902bd3aSMisono Tomohiro }; 433f902bd3aSMisono Tomohiro 4346e369febSDavid Sterba /* 435e4faab84SDennis Zhou * Discard statistics and tunables 436e4faab84SDennis Zhou */ 437fb731430SDavid Sterba #define discard_to_fs_info(_kobj) to_fs_info(get_btrfs_kobj(_kobj)) 438dfb79ddbSDennis Zhou 4395dc7c10bSDennis Zhou static ssize_t btrfs_discardable_bytes_show(struct kobject *kobj, 4405dc7c10bSDennis Zhou struct kobj_attribute *a, 4415dc7c10bSDennis Zhou char *buf) 4425dc7c10bSDennis Zhou { 4435dc7c10bSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4445dc7c10bSDennis Zhou 445020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4465dc7c10bSDennis Zhou atomic64_read(&fs_info->discard_ctl.discardable_bytes)); 4475dc7c10bSDennis Zhou } 4485dc7c10bSDennis Zhou BTRFS_ATTR(discard, discardable_bytes, btrfs_discardable_bytes_show); 4495dc7c10bSDennis Zhou 450dfb79ddbSDennis Zhou static ssize_t btrfs_discardable_extents_show(struct kobject *kobj, 451dfb79ddbSDennis Zhou struct kobj_attribute *a, 452dfb79ddbSDennis Zhou char *buf) 453dfb79ddbSDennis Zhou { 454dfb79ddbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 455dfb79ddbSDennis Zhou 456020e5277SAnand Jain return sysfs_emit(buf, "%d\n", 457dfb79ddbSDennis Zhou atomic_read(&fs_info->discard_ctl.discardable_extents)); 458dfb79ddbSDennis Zhou } 459dfb79ddbSDennis Zhou BTRFS_ATTR(discard, discardable_extents, btrfs_discardable_extents_show); 460dfb79ddbSDennis Zhou 4619ddf648fSDennis Zhou static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj, 4629ddf648fSDennis Zhou struct kobj_attribute *a, 4639ddf648fSDennis Zhou char *buf) 4649ddf648fSDennis Zhou { 4659ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4669ddf648fSDennis Zhou 467020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4689ddf648fSDennis Zhou fs_info->discard_ctl.discard_bitmap_bytes); 4699ddf648fSDennis Zhou } 4709ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bitmap_bytes, btrfs_discard_bitmap_bytes_show); 4719ddf648fSDennis Zhou 4729ddf648fSDennis Zhou static ssize_t btrfs_discard_bytes_saved_show(struct kobject *kobj, 4739ddf648fSDennis Zhou struct kobj_attribute *a, 4749ddf648fSDennis Zhou char *buf) 4759ddf648fSDennis Zhou { 4769ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4779ddf648fSDennis Zhou 478020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4799ddf648fSDennis Zhou atomic64_read(&fs_info->discard_ctl.discard_bytes_saved)); 4809ddf648fSDennis Zhou } 4819ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bytes_saved, btrfs_discard_bytes_saved_show); 4829ddf648fSDennis Zhou 4839ddf648fSDennis Zhou static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj, 4849ddf648fSDennis Zhou struct kobj_attribute *a, 4859ddf648fSDennis Zhou char *buf) 4869ddf648fSDennis Zhou { 4879ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4889ddf648fSDennis Zhou 489020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4909ddf648fSDennis Zhou fs_info->discard_ctl.discard_extent_bytes); 4919ddf648fSDennis Zhou } 4929ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_extent_bytes, btrfs_discard_extent_bytes_show); 4939ddf648fSDennis Zhou 494a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_show(struct kobject *kobj, 495a2309300SDennis Zhou struct kobj_attribute *a, 496a2309300SDennis Zhou char *buf) 497a2309300SDennis Zhou { 498a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 499a2309300SDennis Zhou 500020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 501a2309300SDennis Zhou READ_ONCE(fs_info->discard_ctl.iops_limit)); 502a2309300SDennis Zhou } 503a2309300SDennis Zhou 504a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_store(struct kobject *kobj, 505a2309300SDennis Zhou struct kobj_attribute *a, 506a2309300SDennis Zhou const char *buf, size_t len) 507a2309300SDennis Zhou { 508a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 509a2309300SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 510a2309300SDennis Zhou u32 iops_limit; 511a2309300SDennis Zhou int ret; 512a2309300SDennis Zhou 513a2309300SDennis Zhou ret = kstrtou32(buf, 10, &iops_limit); 514a2309300SDennis Zhou if (ret) 515a2309300SDennis Zhou return -EINVAL; 516a2309300SDennis Zhou 517a2309300SDennis Zhou WRITE_ONCE(discard_ctl->iops_limit, iops_limit); 5183e48d8d2SPavel Begunkov btrfs_discard_calc_delay(discard_ctl); 5193e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 520a2309300SDennis Zhou return len; 521a2309300SDennis Zhou } 522a2309300SDennis Zhou BTRFS_ATTR_RW(discard, iops_limit, btrfs_discard_iops_limit_show, 523a2309300SDennis Zhou btrfs_discard_iops_limit_store); 524a2309300SDennis Zhou 525e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_show(struct kobject *kobj, 526e93591bbSDennis Zhou struct kobj_attribute *a, 527e93591bbSDennis Zhou char *buf) 528e93591bbSDennis Zhou { 529e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 530e93591bbSDennis Zhou 531020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 532e93591bbSDennis Zhou READ_ONCE(fs_info->discard_ctl.kbps_limit)); 533e93591bbSDennis Zhou } 534e93591bbSDennis Zhou 535e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_store(struct kobject *kobj, 536e93591bbSDennis Zhou struct kobj_attribute *a, 537e93591bbSDennis Zhou const char *buf, size_t len) 538e93591bbSDennis Zhou { 539e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 540e93591bbSDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 541e93591bbSDennis Zhou u32 kbps_limit; 542e93591bbSDennis Zhou int ret; 543e93591bbSDennis Zhou 544e93591bbSDennis Zhou ret = kstrtou32(buf, 10, &kbps_limit); 545e93591bbSDennis Zhou if (ret) 546e93591bbSDennis Zhou return -EINVAL; 547e93591bbSDennis Zhou 548e93591bbSDennis Zhou WRITE_ONCE(discard_ctl->kbps_limit, kbps_limit); 5493e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 550e93591bbSDennis Zhou return len; 551e93591bbSDennis Zhou } 552e93591bbSDennis Zhou BTRFS_ATTR_RW(discard, kbps_limit, btrfs_discard_kbps_limit_show, 553e93591bbSDennis Zhou btrfs_discard_kbps_limit_store); 554e93591bbSDennis Zhou 55519b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_show(struct kobject *kobj, 55619b2a2c7SDennis Zhou struct kobj_attribute *a, 55719b2a2c7SDennis Zhou char *buf) 55819b2a2c7SDennis Zhou { 55919b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 56019b2a2c7SDennis Zhou 561020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 56219b2a2c7SDennis Zhou READ_ONCE(fs_info->discard_ctl.max_discard_size)); 56319b2a2c7SDennis Zhou } 56419b2a2c7SDennis Zhou 56519b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_store(struct kobject *kobj, 56619b2a2c7SDennis Zhou struct kobj_attribute *a, 56719b2a2c7SDennis Zhou const char *buf, size_t len) 56819b2a2c7SDennis Zhou { 56919b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 57019b2a2c7SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 57119b2a2c7SDennis Zhou u64 max_discard_size; 57219b2a2c7SDennis Zhou int ret; 57319b2a2c7SDennis Zhou 57419b2a2c7SDennis Zhou ret = kstrtou64(buf, 10, &max_discard_size); 57519b2a2c7SDennis Zhou if (ret) 57619b2a2c7SDennis Zhou return -EINVAL; 57719b2a2c7SDennis Zhou 57819b2a2c7SDennis Zhou WRITE_ONCE(discard_ctl->max_discard_size, max_discard_size); 57919b2a2c7SDennis Zhou 58019b2a2c7SDennis Zhou return len; 58119b2a2c7SDennis Zhou } 58219b2a2c7SDennis Zhou BTRFS_ATTR_RW(discard, max_discard_size, btrfs_discard_max_discard_size_show, 58319b2a2c7SDennis Zhou btrfs_discard_max_discard_size_store); 58419b2a2c7SDennis Zhou 585e7849e33SAnand Jain /* 586fb731430SDavid Sterba * Per-filesystem stats for discard (when mounted with discard=async). 587e7849e33SAnand Jain * 588fb731430SDavid Sterba * Path: /sys/fs/btrfs/<uuid>/discard/ 589e7849e33SAnand Jain */ 590fb731430SDavid Sterba static const struct attribute *discard_attrs[] = { 5915dc7c10bSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_bytes), 592dfb79ddbSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_extents), 5939ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bitmap_bytes), 5949ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bytes_saved), 5959ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_extent_bytes), 596a2309300SDennis Zhou BTRFS_ATTR_PTR(discard, iops_limit), 597e93591bbSDennis Zhou BTRFS_ATTR_PTR(discard, kbps_limit), 59819b2a2c7SDennis Zhou BTRFS_ATTR_PTR(discard, max_discard_size), 599e4faab84SDennis Zhou NULL, 600e4faab84SDennis Zhou }; 601e4faab84SDennis Zhou 602fb731430SDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 603fb731430SDavid Sterba 604e4faab84SDennis Zhou /* 605e7849e33SAnand Jain * Per-filesystem runtime debugging exported via sysfs. 6066e369febSDavid Sterba * 607e7849e33SAnand Jain * Path: /sys/fs/btrfs/UUID/debug/ 6086e369febSDavid Sterba */ 60993945cb4SDennis Zhou static const struct attribute *btrfs_debug_mount_attrs[] = { 61093945cb4SDennis Zhou NULL, 61193945cb4SDennis Zhou }; 61293945cb4SDennis Zhou 613e7849e33SAnand Jain /* 614e7849e33SAnand Jain * Runtime debugging exported via sysfs, applies to all mounted filesystems. 615e7849e33SAnand Jain * 616e7849e33SAnand Jain * Path: /sys/fs/btrfs/debug 617e7849e33SAnand Jain */ 6186e369febSDavid Sterba static struct attribute *btrfs_debug_feature_attrs[] = { 6196e369febSDavid Sterba NULL 6206e369febSDavid Sterba }; 6216e369febSDavid Sterba 6226e369febSDavid Sterba static const struct attribute_group btrfs_debug_feature_attr_group = { 6236e369febSDavid Sterba .name = "debug", 6246e369febSDavid Sterba .attrs = btrfs_debug_feature_attrs, 6256e369febSDavid Sterba }; 6266e369febSDavid Sterba 6276e369febSDavid Sterba #endif 6286e369febSDavid Sterba 6296ab0a202SJeff Mahoney static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf) 6306ab0a202SJeff Mahoney { 6316ab0a202SJeff Mahoney u64 val; 6326ab0a202SJeff Mahoney if (lock) 6336ab0a202SJeff Mahoney spin_lock(lock); 6346ab0a202SJeff Mahoney val = *value_ptr; 6356ab0a202SJeff Mahoney if (lock) 6366ab0a202SJeff Mahoney spin_unlock(lock); 637020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6386ab0a202SJeff Mahoney } 6396ab0a202SJeff Mahoney 6406ab0a202SJeff Mahoney static ssize_t global_rsv_size_show(struct kobject *kobj, 6416ab0a202SJeff Mahoney struct kobj_attribute *ka, char *buf) 6426ab0a202SJeff Mahoney { 6436ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6446ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6456ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf); 6466ab0a202SJeff Mahoney } 647a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_size, global_rsv_size_show); 6486ab0a202SJeff Mahoney 6496ab0a202SJeff Mahoney static ssize_t global_rsv_reserved_show(struct kobject *kobj, 6506ab0a202SJeff Mahoney struct kobj_attribute *a, char *buf) 6516ab0a202SJeff Mahoney { 6526ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6536ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6546ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf); 6556ab0a202SJeff Mahoney } 656a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_reserved, global_rsv_reserved_show); 6576ab0a202SJeff Mahoney 6586ab0a202SJeff Mahoney #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj) 659c1895442SJeff Mahoney #define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj) 6606ab0a202SJeff Mahoney 6616ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6626ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf); 663a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, total_bytes, raid_bytes_show); 664a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, used_bytes, raid_bytes_show); 6656ab0a202SJeff Mahoney 6666ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6676ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf) 6686ab0a202SJeff Mahoney 6696ab0a202SJeff Mahoney { 6706ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj->parent); 67132da5386SDavid Sterba struct btrfs_block_group *block_group; 67275cb379dSJeff Mahoney int index = btrfs_bg_flags_to_raid_index(to_raid_kobj(kobj)->flags); 6736ab0a202SJeff Mahoney u64 val = 0; 6746ab0a202SJeff Mahoney 6756ab0a202SJeff Mahoney down_read(&sinfo->groups_sem); 6766ab0a202SJeff Mahoney list_for_each_entry(block_group, &sinfo->block_groups[index], list) { 677a969f4ccSHans van Kranenburg if (&attr->attr == BTRFS_ATTR_PTR(raid, total_bytes)) 678b3470b5dSDavid Sterba val += block_group->length; 6796ab0a202SJeff Mahoney else 680bf38be65SDavid Sterba val += block_group->used; 6816ab0a202SJeff Mahoney } 6826ab0a202SJeff Mahoney up_read(&sinfo->groups_sem); 683020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6846ab0a202SJeff Mahoney } 6856ab0a202SJeff Mahoney 686e7849e33SAnand Jain /* 687e7849e33SAnand Jain * Allocation information about block group profiles. 688e7849e33SAnand Jain * 689e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/<bg-profile>/ 690e7849e33SAnand Jain */ 6917c7e3014SKimberly Brown static struct attribute *raid_attrs[] = { 692a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, total_bytes), 693a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, used_bytes), 6946ab0a202SJeff Mahoney NULL 6956ab0a202SJeff Mahoney }; 6967c7e3014SKimberly Brown ATTRIBUTE_GROUPS(raid); 6976ab0a202SJeff Mahoney 6986ab0a202SJeff Mahoney static void release_raid_kobj(struct kobject *kobj) 6996ab0a202SJeff Mahoney { 700c1895442SJeff Mahoney kfree(to_raid_kobj(kobj)); 7016ab0a202SJeff Mahoney } 7026ab0a202SJeff Mahoney 703536ea45cSDavid Sterba static struct kobj_type btrfs_raid_ktype = { 7046ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 7056ab0a202SJeff Mahoney .release = release_raid_kobj, 7067c7e3014SKimberly Brown .default_groups = raid_groups, 7076ab0a202SJeff Mahoney }; 7086ab0a202SJeff Mahoney 7096ab0a202SJeff Mahoney #define SPACE_INFO_ATTR(field) \ 7106ab0a202SJeff Mahoney static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \ 7116ab0a202SJeff Mahoney struct kobj_attribute *a, \ 7126ab0a202SJeff Mahoney char *buf) \ 7136ab0a202SJeff Mahoney { \ 7146ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); \ 7156ab0a202SJeff Mahoney return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \ 7166ab0a202SJeff Mahoney } \ 717a969f4ccSHans van Kranenburg BTRFS_ATTR(space_info, field, btrfs_space_info_show_##field) 7186ab0a202SJeff Mahoney 71919fc516aSStefan Roesch static ssize_t btrfs_chunk_size_show(struct kobject *kobj, 72019fc516aSStefan Roesch struct kobj_attribute *a, char *buf) 72119fc516aSStefan Roesch { 72219fc516aSStefan Roesch struct btrfs_space_info *sinfo = to_space_info(kobj); 72319fc516aSStefan Roesch 72419fc516aSStefan Roesch return sysfs_emit(buf, "%llu\n", READ_ONCE(sinfo->chunk_size)); 72519fc516aSStefan Roesch } 72619fc516aSStefan Roesch 72719fc516aSStefan Roesch /* 72819fc516aSStefan Roesch * Store new chunk size in space info. Can be called on a read-only filesystem. 72919fc516aSStefan Roesch * 73019fc516aSStefan Roesch * If the new chunk size value is larger than 10% of free space it is reduced 73119fc516aSStefan Roesch * to match that limit. Alignment must be to 256M and the system chunk size 73219fc516aSStefan Roesch * cannot be set. 73319fc516aSStefan Roesch */ 73419fc516aSStefan Roesch static ssize_t btrfs_chunk_size_store(struct kobject *kobj, 73519fc516aSStefan Roesch struct kobj_attribute *a, 73619fc516aSStefan Roesch const char *buf, size_t len) 73719fc516aSStefan Roesch { 73819fc516aSStefan Roesch struct btrfs_space_info *space_info = to_space_info(kobj); 73919fc516aSStefan Roesch struct btrfs_fs_info *fs_info = to_fs_info(get_btrfs_kobj(kobj)); 74019fc516aSStefan Roesch char *retptr; 74119fc516aSStefan Roesch u64 val; 74219fc516aSStefan Roesch 74319fc516aSStefan Roesch if (!capable(CAP_SYS_ADMIN)) 74419fc516aSStefan Roesch return -EPERM; 74519fc516aSStefan Roesch 74619fc516aSStefan Roesch if (!fs_info->fs_devices) 74719fc516aSStefan Roesch return -EINVAL; 74819fc516aSStefan Roesch 74919fc516aSStefan Roesch if (btrfs_is_zoned(fs_info)) 75019fc516aSStefan Roesch return -EINVAL; 75119fc516aSStefan Roesch 75219fc516aSStefan Roesch /* System block type must not be changed. */ 75319fc516aSStefan Roesch if (space_info->flags & BTRFS_BLOCK_GROUP_SYSTEM) 75419fc516aSStefan Roesch return -EPERM; 75519fc516aSStefan Roesch 75619fc516aSStefan Roesch val = memparse(buf, &retptr); 75719fc516aSStefan Roesch /* There could be trailing '\n', also catch any typos after the value */ 75819fc516aSStefan Roesch retptr = skip_spaces(retptr); 75919fc516aSStefan Roesch if (*retptr != 0 || val == 0) 76019fc516aSStefan Roesch return -EINVAL; 76119fc516aSStefan Roesch 76219fc516aSStefan Roesch val = min(val, BTRFS_MAX_DATA_CHUNK_SIZE); 76319fc516aSStefan Roesch 76419fc516aSStefan Roesch /* Limit stripe size to 10% of available space. */ 76519fc516aSStefan Roesch val = min(div_factor(fs_info->fs_devices->total_rw_bytes, 1), val); 76619fc516aSStefan Roesch 76719fc516aSStefan Roesch /* Must be multiple of 256M. */ 76819fc516aSStefan Roesch val &= ~((u64)SZ_256M - 1); 76919fc516aSStefan Roesch 77019fc516aSStefan Roesch /* Must be at least 256M. */ 77119fc516aSStefan Roesch if (val < SZ_256M) 77219fc516aSStefan Roesch return -EINVAL; 77319fc516aSStefan Roesch 77419fc516aSStefan Roesch btrfs_update_space_info_chunk_size(space_info, val); 77519fc516aSStefan Roesch 77619fc516aSStefan Roesch return len; 77719fc516aSStefan Roesch } 77819fc516aSStefan Roesch 77922c55e3bSStefan Roesch #ifdef CONFIG_BTRFS_DEBUG 78022c55e3bSStefan Roesch /* 78122c55e3bSStefan Roesch * Request chunk allocation with current chunk size. 78222c55e3bSStefan Roesch */ 78322c55e3bSStefan Roesch static ssize_t btrfs_force_chunk_alloc_store(struct kobject *kobj, 78422c55e3bSStefan Roesch struct kobj_attribute *a, 78522c55e3bSStefan Roesch const char *buf, size_t len) 78622c55e3bSStefan Roesch { 78722c55e3bSStefan Roesch struct btrfs_space_info *space_info = to_space_info(kobj); 78822c55e3bSStefan Roesch struct btrfs_fs_info *fs_info = to_fs_info(get_btrfs_kobj(kobj)); 78922c55e3bSStefan Roesch struct btrfs_trans_handle *trans; 79022c55e3bSStefan Roesch bool val; 79122c55e3bSStefan Roesch int ret; 79222c55e3bSStefan Roesch 79322c55e3bSStefan Roesch if (!capable(CAP_SYS_ADMIN)) 79422c55e3bSStefan Roesch return -EPERM; 79522c55e3bSStefan Roesch 79622c55e3bSStefan Roesch if (sb_rdonly(fs_info->sb)) 79722c55e3bSStefan Roesch return -EROFS; 79822c55e3bSStefan Roesch 79922c55e3bSStefan Roesch ret = kstrtobool(buf, &val); 80022c55e3bSStefan Roesch if (ret) 80122c55e3bSStefan Roesch return ret; 80222c55e3bSStefan Roesch 80322c55e3bSStefan Roesch if (!val) 80422c55e3bSStefan Roesch return -EINVAL; 80522c55e3bSStefan Roesch 80622c55e3bSStefan Roesch /* 80722c55e3bSStefan Roesch * This is unsafe to be called from sysfs context and may cause 80822c55e3bSStefan Roesch * unexpected problems. 80922c55e3bSStefan Roesch */ 81022c55e3bSStefan Roesch trans = btrfs_start_transaction(fs_info->tree_root, 0); 81122c55e3bSStefan Roesch if (IS_ERR(trans)) 81222c55e3bSStefan Roesch return PTR_ERR(trans); 81322c55e3bSStefan Roesch ret = btrfs_force_chunk_alloc(trans, space_info->flags); 81422c55e3bSStefan Roesch btrfs_end_transaction(trans); 81522c55e3bSStefan Roesch 81622c55e3bSStefan Roesch if (ret == 1) 81722c55e3bSStefan Roesch return len; 81822c55e3bSStefan Roesch 81922c55e3bSStefan Roesch return -ENOSPC; 82022c55e3bSStefan Roesch } 82122c55e3bSStefan Roesch BTRFS_ATTR_W(space_info, force_chunk_alloc, btrfs_force_chunk_alloc_store); 82222c55e3bSStefan Roesch 82322c55e3bSStefan Roesch #endif 82422c55e3bSStefan Roesch 8256ab0a202SJeff Mahoney SPACE_INFO_ATTR(flags); 8266ab0a202SJeff Mahoney SPACE_INFO_ATTR(total_bytes); 8276ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_used); 8286ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_pinned); 8296ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_reserved); 8306ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_may_use); 831c1fd5c30SWang Xiaoguang SPACE_INFO_ATTR(bytes_readonly); 832169e0da9SNaohiro Aota SPACE_INFO_ATTR(bytes_zone_unusable); 8336ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_used); 8346ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_total); 83519fc516aSStefan Roesch BTRFS_ATTR_RW(space_info, chunk_size, btrfs_chunk_size_show, btrfs_chunk_size_store); 8366ab0a202SJeff Mahoney 837bb5a098dSJosef Bacik static ssize_t btrfs_sinfo_bg_reclaim_threshold_show(struct kobject *kobj, 838bb5a098dSJosef Bacik struct kobj_attribute *a, 839bb5a098dSJosef Bacik char *buf) 840bb5a098dSJosef Bacik { 841bb5a098dSJosef Bacik struct btrfs_space_info *space_info = to_space_info(kobj); 842bb5a098dSJosef Bacik 843bd64f622Szhang songyi return sysfs_emit(buf, "%d\n", READ_ONCE(space_info->bg_reclaim_threshold)); 844bb5a098dSJosef Bacik } 845bb5a098dSJosef Bacik 846bb5a098dSJosef Bacik static ssize_t btrfs_sinfo_bg_reclaim_threshold_store(struct kobject *kobj, 847bb5a098dSJosef Bacik struct kobj_attribute *a, 848bb5a098dSJosef Bacik const char *buf, size_t len) 849bb5a098dSJosef Bacik { 850bb5a098dSJosef Bacik struct btrfs_space_info *space_info = to_space_info(kobj); 851bb5a098dSJosef Bacik int thresh; 852bb5a098dSJosef Bacik int ret; 853bb5a098dSJosef Bacik 854bb5a098dSJosef Bacik ret = kstrtoint(buf, 10, &thresh); 855bb5a098dSJosef Bacik if (ret) 856bb5a098dSJosef Bacik return ret; 857bb5a098dSJosef Bacik 858ef972e7bSJosef Bacik if (thresh < 0 || thresh > 100) 859bb5a098dSJosef Bacik return -EINVAL; 860bb5a098dSJosef Bacik 861bb5a098dSJosef Bacik WRITE_ONCE(space_info->bg_reclaim_threshold, thresh); 862bb5a098dSJosef Bacik 863bb5a098dSJosef Bacik return len; 864bb5a098dSJosef Bacik } 865bb5a098dSJosef Bacik 866bb5a098dSJosef Bacik BTRFS_ATTR_RW(space_info, bg_reclaim_threshold, 867bb5a098dSJosef Bacik btrfs_sinfo_bg_reclaim_threshold_show, 868bb5a098dSJosef Bacik btrfs_sinfo_bg_reclaim_threshold_store); 869bb5a098dSJosef Bacik 870e7849e33SAnand Jain /* 871e7849e33SAnand Jain * Allocation information about block group types. 872e7849e33SAnand Jain * 873e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/ 874e7849e33SAnand Jain */ 8756ab0a202SJeff Mahoney static struct attribute *space_info_attrs[] = { 876a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, flags), 877a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, total_bytes), 878a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_used), 879a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_pinned), 880a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_reserved), 881a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_may_use), 882a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_readonly), 883169e0da9SNaohiro Aota BTRFS_ATTR_PTR(space_info, bytes_zone_unusable), 884a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_used), 885a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_total), 886bb5a098dSJosef Bacik BTRFS_ATTR_PTR(space_info, bg_reclaim_threshold), 88719fc516aSStefan Roesch BTRFS_ATTR_PTR(space_info, chunk_size), 88822c55e3bSStefan Roesch #ifdef CONFIG_BTRFS_DEBUG 88922c55e3bSStefan Roesch BTRFS_ATTR_PTR(space_info, force_chunk_alloc), 89022c55e3bSStefan Roesch #endif 8916ab0a202SJeff Mahoney NULL, 8926ab0a202SJeff Mahoney }; 8937c7e3014SKimberly Brown ATTRIBUTE_GROUPS(space_info); 8946ab0a202SJeff Mahoney 8956ab0a202SJeff Mahoney static void space_info_release(struct kobject *kobj) 8966ab0a202SJeff Mahoney { 8976ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); 8986ab0a202SJeff Mahoney kfree(sinfo); 8996ab0a202SJeff Mahoney } 9006ab0a202SJeff Mahoney 90127992d01SDavid Sterba static struct kobj_type space_info_ktype = { 9026ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 9036ab0a202SJeff Mahoney .release = space_info_release, 9047c7e3014SKimberly Brown .default_groups = space_info_groups, 9056ab0a202SJeff Mahoney }; 9066ab0a202SJeff Mahoney 907e7849e33SAnand Jain /* 908e7849e33SAnand Jain * Allocation information about block groups. 909e7849e33SAnand Jain * 910e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/ 911e7849e33SAnand Jain */ 9126ab0a202SJeff Mahoney static const struct attribute *allocation_attrs[] = { 913a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_reserved), 914a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_size), 9156ab0a202SJeff Mahoney NULL, 9166ab0a202SJeff Mahoney }; 9176ab0a202SJeff Mahoney 918f8ba9c11SJeff Mahoney static ssize_t btrfs_label_show(struct kobject *kobj, 919f8ba9c11SJeff Mahoney struct kobj_attribute *a, char *buf) 920f8ba9c11SJeff Mahoney { 921f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 92248fcc3ffSSatoru Takeuchi char *label = fs_info->super_copy->label; 923ee17fc80SDavid Sterba ssize_t ret; 924ee17fc80SDavid Sterba 925ee17fc80SDavid Sterba spin_lock(&fs_info->super_lock); 926020e5277SAnand Jain ret = sysfs_emit(buf, label[0] ? "%s\n" : "%s", label); 927ee17fc80SDavid Sterba spin_unlock(&fs_info->super_lock); 928ee17fc80SDavid Sterba 929ee17fc80SDavid Sterba return ret; 930f8ba9c11SJeff Mahoney } 931f8ba9c11SJeff Mahoney 932f8ba9c11SJeff Mahoney static ssize_t btrfs_label_store(struct kobject *kobj, 933f8ba9c11SJeff Mahoney struct kobj_attribute *a, 934f8ba9c11SJeff Mahoney const char *buf, size_t len) 935f8ba9c11SJeff Mahoney { 936f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 93748fcc3ffSSatoru Takeuchi size_t p_len; 938f8ba9c11SJeff Mahoney 93966ac9fe7SDavid Sterba if (!fs_info) 94066ac9fe7SDavid Sterba return -EPERM; 94166ac9fe7SDavid Sterba 942bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 94379aec2b8SAnand Jain return -EROFS; 94479aec2b8SAnand Jain 94548fcc3ffSSatoru Takeuchi /* 94648fcc3ffSSatoru Takeuchi * p_len is the len until the first occurrence of either 94748fcc3ffSSatoru Takeuchi * '\n' or '\0' 94848fcc3ffSSatoru Takeuchi */ 94948fcc3ffSSatoru Takeuchi p_len = strcspn(buf, "\n"); 95048fcc3ffSSatoru Takeuchi 95148fcc3ffSSatoru Takeuchi if (p_len >= BTRFS_LABEL_SIZE) 952f8ba9c11SJeff Mahoney return -EINVAL; 953f8ba9c11SJeff Mahoney 954a6f69dc8SDavid Sterba spin_lock(&fs_info->super_lock); 95548fcc3ffSSatoru Takeuchi memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE); 95648fcc3ffSSatoru Takeuchi memcpy(fs_info->super_copy->label, buf, p_len); 957a6f69dc8SDavid Sterba spin_unlock(&fs_info->super_lock); 958f8ba9c11SJeff Mahoney 959a6f69dc8SDavid Sterba /* 960a6f69dc8SDavid Sterba * We don't want to do full transaction commit from inside sysfs 961a6f69dc8SDavid Sterba */ 962a6f69dc8SDavid Sterba btrfs_set_pending(fs_info, COMMIT); 963a6f69dc8SDavid Sterba wake_up_process(fs_info->transaction_kthread); 964a6f69dc8SDavid Sterba 965f8ba9c11SJeff Mahoney return len; 966f8ba9c11SJeff Mahoney } 967a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, label, btrfs_label_show, btrfs_label_store); 968f8ba9c11SJeff Mahoney 969df93589aSDavid Sterba static ssize_t btrfs_nodesize_show(struct kobject *kobj, 970df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 971df93589aSDavid Sterba { 972df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 973df93589aSDavid Sterba 974020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->nodesize); 975df93589aSDavid Sterba } 976df93589aSDavid Sterba 977a969f4ccSHans van Kranenburg BTRFS_ATTR(, nodesize, btrfs_nodesize_show); 978df93589aSDavid Sterba 979df93589aSDavid Sterba static ssize_t btrfs_sectorsize_show(struct kobject *kobj, 980df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 981df93589aSDavid Sterba { 982df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 983df93589aSDavid Sterba 984020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 985df93589aSDavid Sterba } 986df93589aSDavid Sterba 987a969f4ccSHans van Kranenburg BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show); 988df93589aSDavid Sterba 989140a8ff7SIoannis Angelakopoulos static ssize_t btrfs_commit_stats_show(struct kobject *kobj, 990140a8ff7SIoannis Angelakopoulos struct kobj_attribute *a, char *buf) 991140a8ff7SIoannis Angelakopoulos { 992140a8ff7SIoannis Angelakopoulos struct btrfs_fs_info *fs_info = to_fs_info(kobj); 993140a8ff7SIoannis Angelakopoulos 994140a8ff7SIoannis Angelakopoulos return sysfs_emit(buf, 995140a8ff7SIoannis Angelakopoulos "commits %llu\n" 996140a8ff7SIoannis Angelakopoulos "last_commit_ms %llu\n" 997140a8ff7SIoannis Angelakopoulos "max_commit_ms %llu\n" 998140a8ff7SIoannis Angelakopoulos "total_commit_ms %llu\n", 999140a8ff7SIoannis Angelakopoulos fs_info->commit_stats.commit_count, 1000140a8ff7SIoannis Angelakopoulos div_u64(fs_info->commit_stats.last_commit_dur, NSEC_PER_MSEC), 1001140a8ff7SIoannis Angelakopoulos div_u64(fs_info->commit_stats.max_commit_dur, NSEC_PER_MSEC), 1002140a8ff7SIoannis Angelakopoulos div_u64(fs_info->commit_stats.total_commit_dur, NSEC_PER_MSEC)); 1003140a8ff7SIoannis Angelakopoulos } 1004140a8ff7SIoannis Angelakopoulos 1005140a8ff7SIoannis Angelakopoulos static ssize_t btrfs_commit_stats_store(struct kobject *kobj, 1006140a8ff7SIoannis Angelakopoulos struct kobj_attribute *a, 1007140a8ff7SIoannis Angelakopoulos const char *buf, size_t len) 1008140a8ff7SIoannis Angelakopoulos { 1009140a8ff7SIoannis Angelakopoulos struct btrfs_fs_info *fs_info = to_fs_info(kobj); 1010140a8ff7SIoannis Angelakopoulos unsigned long val; 1011140a8ff7SIoannis Angelakopoulos int ret; 1012140a8ff7SIoannis Angelakopoulos 1013140a8ff7SIoannis Angelakopoulos if (!fs_info) 1014140a8ff7SIoannis Angelakopoulos return -EPERM; 1015140a8ff7SIoannis Angelakopoulos 1016140a8ff7SIoannis Angelakopoulos if (!capable(CAP_SYS_RESOURCE)) 1017140a8ff7SIoannis Angelakopoulos return -EPERM; 1018140a8ff7SIoannis Angelakopoulos 1019140a8ff7SIoannis Angelakopoulos ret = kstrtoul(buf, 10, &val); 1020140a8ff7SIoannis Angelakopoulos if (ret) 1021140a8ff7SIoannis Angelakopoulos return ret; 1022140a8ff7SIoannis Angelakopoulos if (val) 1023140a8ff7SIoannis Angelakopoulos return -EINVAL; 1024140a8ff7SIoannis Angelakopoulos 1025140a8ff7SIoannis Angelakopoulos WRITE_ONCE(fs_info->commit_stats.max_commit_dur, 0); 1026140a8ff7SIoannis Angelakopoulos 1027140a8ff7SIoannis Angelakopoulos return len; 1028140a8ff7SIoannis Angelakopoulos } 1029140a8ff7SIoannis Angelakopoulos BTRFS_ATTR_RW(, commit_stats, btrfs_commit_stats_show, btrfs_commit_stats_store); 1030140a8ff7SIoannis Angelakopoulos 1031df93589aSDavid Sterba static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, 1032df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 1033df93589aSDavid Sterba { 1034df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 1035df93589aSDavid Sterba 1036020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 1037df93589aSDavid Sterba } 1038df93589aSDavid Sterba 1039a969f4ccSHans van Kranenburg BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show); 1040df93589aSDavid Sterba 10412723480aSSargun Dhillon static ssize_t quota_override_show(struct kobject *kobj, 10422723480aSSargun Dhillon struct kobj_attribute *a, char *buf) 10432723480aSSargun Dhillon { 10442723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 10452723480aSSargun Dhillon int quota_override; 10462723480aSSargun Dhillon 10472723480aSSargun Dhillon quota_override = test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 1048020e5277SAnand Jain return sysfs_emit(buf, "%d\n", quota_override); 10492723480aSSargun Dhillon } 10502723480aSSargun Dhillon 10512723480aSSargun Dhillon static ssize_t quota_override_store(struct kobject *kobj, 10522723480aSSargun Dhillon struct kobj_attribute *a, 10532723480aSSargun Dhillon const char *buf, size_t len) 10542723480aSSargun Dhillon { 10552723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 10562723480aSSargun Dhillon unsigned long knob; 10572723480aSSargun Dhillon int err; 10582723480aSSargun Dhillon 10592723480aSSargun Dhillon if (!fs_info) 10602723480aSSargun Dhillon return -EPERM; 10612723480aSSargun Dhillon 10622723480aSSargun Dhillon if (!capable(CAP_SYS_RESOURCE)) 10632723480aSSargun Dhillon return -EPERM; 10642723480aSSargun Dhillon 10652723480aSSargun Dhillon err = kstrtoul(buf, 10, &knob); 10662723480aSSargun Dhillon if (err) 10672723480aSSargun Dhillon return err; 10682723480aSSargun Dhillon if (knob > 1) 10692723480aSSargun Dhillon return -EINVAL; 10702723480aSSargun Dhillon 10712723480aSSargun Dhillon if (knob) 10722723480aSSargun Dhillon set_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 10732723480aSSargun Dhillon else 10742723480aSSargun Dhillon clear_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 10752723480aSSargun Dhillon 10762723480aSSargun Dhillon return len; 10772723480aSSargun Dhillon } 10782723480aSSargun Dhillon 1079a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, quota_override, quota_override_show, quota_override_store); 10802723480aSSargun Dhillon 108156f20f40SNikolay Borisov static ssize_t btrfs_metadata_uuid_show(struct kobject *kobj, 108256f20f40SNikolay Borisov struct kobj_attribute *a, char *buf) 108356f20f40SNikolay Borisov { 108456f20f40SNikolay Borisov struct btrfs_fs_info *fs_info = to_fs_info(kobj); 108556f20f40SNikolay Borisov 1086020e5277SAnand Jain return sysfs_emit(buf, "%pU\n", fs_info->fs_devices->metadata_uuid); 108756f20f40SNikolay Borisov } 108856f20f40SNikolay Borisov 108956f20f40SNikolay Borisov BTRFS_ATTR(, metadata_uuid, btrfs_metadata_uuid_show); 109056f20f40SNikolay Borisov 109141e6d2a8SJohannes Thumshirn static ssize_t btrfs_checksum_show(struct kobject *kobj, 109241e6d2a8SJohannes Thumshirn struct kobj_attribute *a, char *buf) 109341e6d2a8SJohannes Thumshirn { 109441e6d2a8SJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 109541e6d2a8SJohannes Thumshirn u16 csum_type = btrfs_super_csum_type(fs_info->super_copy); 109641e6d2a8SJohannes Thumshirn 1097020e5277SAnand Jain return sysfs_emit(buf, "%s (%s)\n", 109841e6d2a8SJohannes Thumshirn btrfs_super_csum_name(csum_type), 109941e6d2a8SJohannes Thumshirn crypto_shash_driver_name(fs_info->csum_shash)); 110041e6d2a8SJohannes Thumshirn } 110141e6d2a8SJohannes Thumshirn 110241e6d2a8SJohannes Thumshirn BTRFS_ATTR(, checksum, btrfs_checksum_show); 110341e6d2a8SJohannes Thumshirn 110466a2823cSGoldwyn Rodrigues static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj, 110566a2823cSGoldwyn Rodrigues struct kobj_attribute *a, char *buf) 110666a2823cSGoldwyn Rodrigues { 110766a2823cSGoldwyn Rodrigues struct btrfs_fs_info *fs_info = to_fs_info(kobj); 110866a2823cSGoldwyn Rodrigues const char *str; 110966a2823cSGoldwyn Rodrigues 111066a2823cSGoldwyn Rodrigues switch (READ_ONCE(fs_info->exclusive_operation)) { 111166a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_NONE: 111266a2823cSGoldwyn Rodrigues str = "none\n"; 111366a2823cSGoldwyn Rodrigues break; 111466a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_BALANCE: 111566a2823cSGoldwyn Rodrigues str = "balance\n"; 111666a2823cSGoldwyn Rodrigues break; 11173e1ad196SDavid Sterba case BTRFS_EXCLOP_BALANCE_PAUSED: 11183e1ad196SDavid Sterba str = "balance paused\n"; 11193e1ad196SDavid Sterba break; 112066a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_ADD: 112166a2823cSGoldwyn Rodrigues str = "device add\n"; 112266a2823cSGoldwyn Rodrigues break; 112366a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REMOVE: 112466a2823cSGoldwyn Rodrigues str = "device remove\n"; 112566a2823cSGoldwyn Rodrigues break; 112666a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REPLACE: 112766a2823cSGoldwyn Rodrigues str = "device replace\n"; 112866a2823cSGoldwyn Rodrigues break; 112966a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_RESIZE: 113066a2823cSGoldwyn Rodrigues str = "resize\n"; 113166a2823cSGoldwyn Rodrigues break; 113266a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_SWAP_ACTIVATE: 113366a2823cSGoldwyn Rodrigues str = "swap activate\n"; 113466a2823cSGoldwyn Rodrigues break; 113566a2823cSGoldwyn Rodrigues default: 113666a2823cSGoldwyn Rodrigues str = "UNKNOWN\n"; 113766a2823cSGoldwyn Rodrigues break; 113866a2823cSGoldwyn Rodrigues } 1139020e5277SAnand Jain return sysfs_emit(buf, "%s", str); 114066a2823cSGoldwyn Rodrigues } 114166a2823cSGoldwyn Rodrigues BTRFS_ATTR(, exclusive_operation, btrfs_exclusive_operation_show); 114266a2823cSGoldwyn Rodrigues 1143089c8b05SAnand Jain static ssize_t btrfs_generation_show(struct kobject *kobj, 1144089c8b05SAnand Jain struct kobj_attribute *a, char *buf) 1145089c8b05SAnand Jain { 1146089c8b05SAnand Jain struct btrfs_fs_info *fs_info = to_fs_info(kobj); 1147089c8b05SAnand Jain 1148020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", fs_info->generation); 1149089c8b05SAnand Jain } 1150089c8b05SAnand Jain BTRFS_ATTR(, generation, btrfs_generation_show); 1151089c8b05SAnand Jain 11523d8cc17aSAnand Jain static const char * const btrfs_read_policy_name[] = { "pid" }; 11533d8cc17aSAnand Jain 11543d8cc17aSAnand Jain static ssize_t btrfs_read_policy_show(struct kobject *kobj, 11553d8cc17aSAnand Jain struct kobj_attribute *a, char *buf) 11563d8cc17aSAnand Jain { 11573d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 11583d8cc17aSAnand Jain ssize_t ret = 0; 11593d8cc17aSAnand Jain int i; 11603d8cc17aSAnand Jain 11613d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 11623d8cc17aSAnand Jain if (fs_devices->read_policy == i) 11633d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s[%s]", 11643d8cc17aSAnand Jain (ret == 0 ? "" : " "), 11653d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11663d8cc17aSAnand Jain else 11673d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s", 11683d8cc17aSAnand Jain (ret == 0 ? "" : " "), 11693d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11703d8cc17aSAnand Jain } 11713d8cc17aSAnand Jain 11723d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); 11733d8cc17aSAnand Jain 11743d8cc17aSAnand Jain return ret; 11753d8cc17aSAnand Jain } 11763d8cc17aSAnand Jain 11773d8cc17aSAnand Jain static ssize_t btrfs_read_policy_store(struct kobject *kobj, 11783d8cc17aSAnand Jain struct kobj_attribute *a, 11793d8cc17aSAnand Jain const char *buf, size_t len) 11803d8cc17aSAnand Jain { 11813d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 11823d8cc17aSAnand Jain int i; 11833d8cc17aSAnand Jain 11843d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 11857f298f22SDavid Sterba if (sysfs_streq(buf, btrfs_read_policy_name[i])) { 11863d8cc17aSAnand Jain if (i != fs_devices->read_policy) { 11873d8cc17aSAnand Jain fs_devices->read_policy = i; 11883d8cc17aSAnand Jain btrfs_info(fs_devices->fs_info, 11893d8cc17aSAnand Jain "read policy set to '%s'", 11903d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11913d8cc17aSAnand Jain } 11923d8cc17aSAnand Jain return len; 11933d8cc17aSAnand Jain } 11943d8cc17aSAnand Jain } 11953d8cc17aSAnand Jain 11963d8cc17aSAnand Jain return -EINVAL; 11973d8cc17aSAnand Jain } 11983d8cc17aSAnand Jain BTRFS_ATTR_RW(, read_policy, btrfs_read_policy_show, btrfs_read_policy_store); 11993d8cc17aSAnand Jain 120018bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_show(struct kobject *kobj, 120118bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 120218bb8bbfSJohannes Thumshirn char *buf) 120318bb8bbfSJohannes Thumshirn { 120418bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 120518bb8bbfSJohannes Thumshirn 1206bd64f622Szhang songyi return sysfs_emit(buf, "%d\n", READ_ONCE(fs_info->bg_reclaim_threshold)); 120718bb8bbfSJohannes Thumshirn } 120818bb8bbfSJohannes Thumshirn 120918bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_store(struct kobject *kobj, 121018bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 121118bb8bbfSJohannes Thumshirn const char *buf, size_t len) 121218bb8bbfSJohannes Thumshirn { 121318bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 121418bb8bbfSJohannes Thumshirn int thresh; 121518bb8bbfSJohannes Thumshirn int ret; 121618bb8bbfSJohannes Thumshirn 121718bb8bbfSJohannes Thumshirn ret = kstrtoint(buf, 10, &thresh); 121818bb8bbfSJohannes Thumshirn if (ret) 121918bb8bbfSJohannes Thumshirn return ret; 122018bb8bbfSJohannes Thumshirn 122177233c2dSJohannes Thumshirn if (thresh != 0 && (thresh <= 50 || thresh > 100)) 122218bb8bbfSJohannes Thumshirn return -EINVAL; 122318bb8bbfSJohannes Thumshirn 122477233c2dSJohannes Thumshirn WRITE_ONCE(fs_info->bg_reclaim_threshold, thresh); 122518bb8bbfSJohannes Thumshirn 122618bb8bbfSJohannes Thumshirn return len; 122718bb8bbfSJohannes Thumshirn } 122818bb8bbfSJohannes Thumshirn BTRFS_ATTR_RW(, bg_reclaim_threshold, btrfs_bg_reclaim_threshold_show, 122918bb8bbfSJohannes Thumshirn btrfs_bg_reclaim_threshold_store); 123018bb8bbfSJohannes Thumshirn 1231e7849e33SAnand Jain /* 1232e7849e33SAnand Jain * Per-filesystem information and stats. 1233e7849e33SAnand Jain * 1234e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/ 1235e7849e33SAnand Jain */ 12360dd2906fSAnand Jain static const struct attribute *btrfs_attrs[] = { 1237a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, label), 1238a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, nodesize), 1239a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, sectorsize), 1240a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, clone_alignment), 1241a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, quota_override), 124256f20f40SNikolay Borisov BTRFS_ATTR_PTR(, metadata_uuid), 124341e6d2a8SJohannes Thumshirn BTRFS_ATTR_PTR(, checksum), 124466a2823cSGoldwyn Rodrigues BTRFS_ATTR_PTR(, exclusive_operation), 1245089c8b05SAnand Jain BTRFS_ATTR_PTR(, generation), 12463d8cc17aSAnand Jain BTRFS_ATTR_PTR(, read_policy), 124718bb8bbfSJohannes Thumshirn BTRFS_ATTR_PTR(, bg_reclaim_threshold), 1248140a8ff7SIoannis Angelakopoulos BTRFS_ATTR_PTR(, commit_stats), 1249f8ba9c11SJeff Mahoney NULL, 1250f8ba9c11SJeff Mahoney }; 1251f8ba9c11SJeff Mahoney 1252c1b7e474SAnand Jain static void btrfs_release_fsid_kobj(struct kobject *kobj) 1253510d7360SJeff Mahoney { 12542e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj); 1255248d200dSAnand Jain 1256c1b7e474SAnand Jain memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject)); 12572e7910d6SAnand Jain complete(&fs_devs->kobj_unregister); 1258510d7360SJeff Mahoney } 1259510d7360SJeff Mahoney 1260510d7360SJeff Mahoney static struct kobj_type btrfs_ktype = { 1261510d7360SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 1262c1b7e474SAnand Jain .release = btrfs_release_fsid_kobj, 1263510d7360SJeff Mahoney }; 1264510d7360SJeff Mahoney 12652e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj) 12662e7910d6SAnand Jain { 12672e7910d6SAnand Jain if (kobj->ktype != &btrfs_ktype) 12682e7910d6SAnand Jain return NULL; 1269c1b7e474SAnand Jain return container_of(kobj, struct btrfs_fs_devices, fsid_kobj); 12702e7910d6SAnand Jain } 12712e7910d6SAnand Jain 1272510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj) 1273510d7360SJeff Mahoney { 1274510d7360SJeff Mahoney if (kobj->ktype != &btrfs_ktype) 1275510d7360SJeff Mahoney return NULL; 12762e7910d6SAnand Jain return to_fs_devs(kobj)->fs_info; 1277510d7360SJeff Mahoney } 127858176a96SJosef Bacik 127919fc516aSStefan Roesch static struct kobject *get_btrfs_kobj(struct kobject *kobj) 128019fc516aSStefan Roesch { 128119fc516aSStefan Roesch while (kobj) { 128219fc516aSStefan Roesch if (kobj->ktype == &btrfs_ktype) 128319fc516aSStefan Roesch return kobj; 128419fc516aSStefan Roesch kobj = kobj->parent; 128519fc516aSStefan Roesch } 128619fc516aSStefan Roesch return NULL; 128719fc516aSStefan Roesch } 128819fc516aSStefan Roesch 1289e453d989SJeff Mahoney #define NUM_FEATURE_BITS 64 12906c52157fSTomohiro Misono #define BTRFS_FEATURE_NAME_MAX 13 12916c52157fSTomohiro Misono static char btrfs_unknown_feature_names[FEAT_MAX][NUM_FEATURE_BITS][BTRFS_FEATURE_NAME_MAX]; 12926c52157fSTomohiro Misono static struct btrfs_feature_attr btrfs_feature_attrs[FEAT_MAX][NUM_FEATURE_BITS]; 1293e453d989SJeff Mahoney 1294a55e65b8SDavid Sterba static_assert(ARRAY_SIZE(btrfs_unknown_feature_names) == 1295a55e65b8SDavid Sterba ARRAY_SIZE(btrfs_feature_attrs)); 1296a55e65b8SDavid Sterba static_assert(ARRAY_SIZE(btrfs_unknown_feature_names[0]) == 1297a55e65b8SDavid Sterba ARRAY_SIZE(btrfs_feature_attrs[0])); 1298a55e65b8SDavid Sterba 12996c52157fSTomohiro Misono static const u64 supported_feature_masks[FEAT_MAX] = { 1300e453d989SJeff Mahoney [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP, 1301e453d989SJeff Mahoney [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP, 1302e453d989SJeff Mahoney [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP, 1303e453d989SJeff Mahoney }; 1304e453d989SJeff Mahoney 1305e453d989SJeff Mahoney static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add) 13065ac1d209SJeff Mahoney { 1307e453d989SJeff Mahoney int set; 1308e453d989SJeff Mahoney 1309e453d989SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 1310e453d989SJeff Mahoney int i; 1311e453d989SJeff Mahoney struct attribute *attrs[2]; 1312e453d989SJeff Mahoney struct attribute_group agroup = { 1313e453d989SJeff Mahoney .name = "features", 1314e453d989SJeff Mahoney .attrs = attrs, 1315e453d989SJeff Mahoney }; 1316e453d989SJeff Mahoney u64 features = get_features(fs_info, set); 1317e453d989SJeff Mahoney features &= ~supported_feature_masks[set]; 1318e453d989SJeff Mahoney 1319e453d989SJeff Mahoney if (!features) 1320e453d989SJeff Mahoney continue; 1321e453d989SJeff Mahoney 1322e453d989SJeff Mahoney attrs[1] = NULL; 1323e453d989SJeff Mahoney for (i = 0; i < NUM_FEATURE_BITS; i++) { 1324e453d989SJeff Mahoney struct btrfs_feature_attr *fa; 1325e453d989SJeff Mahoney 1326e453d989SJeff Mahoney if (!(features & (1ULL << i))) 1327e453d989SJeff Mahoney continue; 1328e453d989SJeff Mahoney 1329e453d989SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 1330e453d989SJeff Mahoney attrs[0] = &fa->kobj_attr.attr; 1331e453d989SJeff Mahoney if (add) { 1332e453d989SJeff Mahoney int ret; 1333c1b7e474SAnand Jain ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj, 1334e453d989SJeff Mahoney &agroup); 1335e453d989SJeff Mahoney if (ret) 1336e453d989SJeff Mahoney return ret; 1337e453d989SJeff Mahoney } else 1338c1b7e474SAnand Jain sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj, 1339e453d989SJeff Mahoney &agroup); 1340e453d989SJeff Mahoney } 1341e453d989SJeff Mahoney 1342e453d989SJeff Mahoney } 1343e453d989SJeff Mahoney return 0; 1344e453d989SJeff Mahoney } 1345e453d989SJeff Mahoney 13462e3e1281SAnand Jain static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 1347e453d989SJeff Mahoney { 1348a013d141SAnand Jain if (fs_devs->devinfo_kobj) { 1349a013d141SAnand Jain kobject_del(fs_devs->devinfo_kobj); 1350a013d141SAnand Jain kobject_put(fs_devs->devinfo_kobj); 1351a013d141SAnand Jain fs_devs->devinfo_kobj = NULL; 1352a013d141SAnand Jain } 1353a013d141SAnand Jain 1354b5501504SAnand Jain if (fs_devs->devices_kobj) { 1355b5501504SAnand Jain kobject_del(fs_devs->devices_kobj); 1356b5501504SAnand Jain kobject_put(fs_devs->devices_kobj); 1357b5501504SAnand Jain fs_devs->devices_kobj = NULL; 1358aaf13305SAnand Jain } 1359aaf13305SAnand Jain 1360c1b7e474SAnand Jain if (fs_devs->fsid_kobj.state_initialized) { 1361c1b7e474SAnand Jain kobject_del(&fs_devs->fsid_kobj); 1362c1b7e474SAnand Jain kobject_put(&fs_devs->fsid_kobj); 13632e7910d6SAnand Jain wait_for_completion(&fs_devs->kobj_unregister); 13645ac1d209SJeff Mahoney } 1365f90fc547SAnand Jain } 13665ac1d209SJeff Mahoney 13672e3e1281SAnand Jain /* when fs_devs is NULL it will remove all fsid kobject */ 13681d1c1be3SAnand Jain void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 13692e3e1281SAnand Jain { 13702e3e1281SAnand Jain struct list_head *fs_uuids = btrfs_get_fs_uuids(); 13712e3e1281SAnand Jain 13722e3e1281SAnand Jain if (fs_devs) { 13732e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 13742e3e1281SAnand Jain return; 13752e3e1281SAnand Jain } 13762e3e1281SAnand Jain 1377c4babc5eSAnand Jain list_for_each_entry(fs_devs, fs_uuids, fs_list) { 13782e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 13792e3e1281SAnand Jain } 13802e3e1281SAnand Jain } 13812e3e1281SAnand Jain 138253f8a74cSAnand Jain static void btrfs_sysfs_remove_fs_devices(struct btrfs_fs_devices *fs_devices) 138353f8a74cSAnand Jain { 138453f8a74cSAnand Jain struct btrfs_device *device; 138530b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 138653f8a74cSAnand Jain 138753f8a74cSAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) 138853f8a74cSAnand Jain btrfs_sysfs_remove_device(device); 138930b0e4e0SAnand Jain 139030b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 139130b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) 139230b0e4e0SAnand Jain btrfs_sysfs_remove_device(device); 139330b0e4e0SAnand Jain } 139453f8a74cSAnand Jain } 139553f8a74cSAnand Jain 13966618a59bSAnand Jain void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info) 1397e453d989SJeff Mahoney { 13983092c68fSNikolay Borisov struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 13993092c68fSNikolay Borisov 14003092c68fSNikolay Borisov sysfs_remove_link(fsid_kobj, "bdi"); 14013092c68fSNikolay Borisov 1402e453d989SJeff Mahoney if (fs_info->space_info_kobj) { 1403e453d989SJeff Mahoney sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); 1404e453d989SJeff Mahoney kobject_del(fs_info->space_info_kobj); 1405e453d989SJeff Mahoney kobject_put(fs_info->space_info_kobj); 1406e453d989SJeff Mahoney } 1407fb731430SDavid Sterba if (fs_info->discard_kobj) { 1408fb731430SDavid Sterba sysfs_remove_files(fs_info->discard_kobj, discard_attrs); 1409fb731430SDavid Sterba kobject_del(fs_info->discard_kobj); 1410fb731430SDavid Sterba kobject_put(fs_info->discard_kobj); 1411e4faab84SDennis Zhou } 1412fb731430SDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 141393945cb4SDennis Zhou if (fs_info->debug_kobj) { 141493945cb4SDennis Zhou sysfs_remove_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 141593945cb4SDennis Zhou kobject_del(fs_info->debug_kobj); 141693945cb4SDennis Zhou kobject_put(fs_info->debug_kobj); 141793945cb4SDennis Zhou } 141871e8978eSDennis Zhou #endif 1419e453d989SJeff Mahoney addrm_unknown_feature_attrs(fs_info, false); 14203092c68fSNikolay Borisov sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 14213092c68fSNikolay Borisov sysfs_remove_files(fsid_kobj, btrfs_attrs); 142253f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_info->fs_devices); 1423e453d989SJeff Mahoney } 1424e453d989SJeff Mahoney 1425f10152bcSDavid Sterba static const char * const btrfs_feature_set_names[FEAT_MAX] = { 142679da4fa4SJeff Mahoney [FEAT_COMPAT] = "compat", 142779da4fa4SJeff Mahoney [FEAT_COMPAT_RO] = "compat_ro", 142879da4fa4SJeff Mahoney [FEAT_INCOMPAT] = "incompat", 142979da4fa4SJeff Mahoney }; 143079da4fa4SJeff Mahoney 14319e6df7ceSDavid Sterba const char *btrfs_feature_set_name(enum btrfs_feature_set set) 1432f10152bcSDavid Sterba { 1433f10152bcSDavid Sterba return btrfs_feature_set_names[set]; 1434f10152bcSDavid Sterba } 1435f10152bcSDavid Sterba 14363b02a68aSJeff Mahoney char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) 14373b02a68aSJeff Mahoney { 14383b02a68aSJeff Mahoney size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */ 14393b02a68aSJeff Mahoney int len = 0; 14403b02a68aSJeff Mahoney int i; 14413b02a68aSJeff Mahoney char *str; 14423b02a68aSJeff Mahoney 14433b02a68aSJeff Mahoney str = kmalloc(bufsize, GFP_KERNEL); 14443b02a68aSJeff Mahoney if (!str) 14453b02a68aSJeff Mahoney return str; 14463b02a68aSJeff Mahoney 14473b02a68aSJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 14483b02a68aSJeff Mahoney const char *name; 14493b02a68aSJeff Mahoney 14503b02a68aSJeff Mahoney if (!(flags & (1ULL << i))) 14513b02a68aSJeff Mahoney continue; 14523b02a68aSJeff Mahoney 14533b02a68aSJeff Mahoney name = btrfs_feature_attrs[set][i].kobj_attr.attr.name; 1454abdd9febSTakashi Iwai len += scnprintf(str + len, bufsize - len, "%s%s", 14553b02a68aSJeff Mahoney len ? "," : "", name); 14563b02a68aSJeff Mahoney } 14573b02a68aSJeff Mahoney 14583b02a68aSJeff Mahoney return str; 14593b02a68aSJeff Mahoney } 14603b02a68aSJeff Mahoney 146179da4fa4SJeff Mahoney static void init_feature_attrs(void) 146279da4fa4SJeff Mahoney { 146379da4fa4SJeff Mahoney struct btrfs_feature_attr *fa; 146479da4fa4SJeff Mahoney int set, i; 146579da4fa4SJeff Mahoney 14663b02a68aSJeff Mahoney memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs)); 14673b02a68aSJeff Mahoney memset(btrfs_unknown_feature_names, 0, 14683b02a68aSJeff Mahoney sizeof(btrfs_unknown_feature_names)); 14693b02a68aSJeff Mahoney 147079da4fa4SJeff Mahoney for (i = 0; btrfs_supported_feature_attrs[i]; i++) { 147179da4fa4SJeff Mahoney struct btrfs_feature_attr *sfa; 147279da4fa4SJeff Mahoney struct attribute *a = btrfs_supported_feature_attrs[i]; 14733b02a68aSJeff Mahoney int bit; 147479da4fa4SJeff Mahoney sfa = attr_to_btrfs_feature_attr(a); 14753b02a68aSJeff Mahoney bit = ilog2(sfa->feature_bit); 14763b02a68aSJeff Mahoney fa = &btrfs_feature_attrs[sfa->feature_set][bit]; 147779da4fa4SJeff Mahoney 147879da4fa4SJeff Mahoney fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name; 147979da4fa4SJeff Mahoney } 148079da4fa4SJeff Mahoney 148179da4fa4SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 148279da4fa4SJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 148379da4fa4SJeff Mahoney char *name = btrfs_unknown_feature_names[set][i]; 148479da4fa4SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 148579da4fa4SJeff Mahoney 148679da4fa4SJeff Mahoney if (fa->kobj_attr.attr.name) 148779da4fa4SJeff Mahoney continue; 148879da4fa4SJeff Mahoney 14896c52157fSTomohiro Misono snprintf(name, BTRFS_FEATURE_NAME_MAX, "%s:%u", 149079da4fa4SJeff Mahoney btrfs_feature_set_names[set], i); 149179da4fa4SJeff Mahoney 149279da4fa4SJeff Mahoney fa->kobj_attr.attr.name = name; 149379da4fa4SJeff Mahoney fa->kobj_attr.attr.mode = S_IRUGO; 149479da4fa4SJeff Mahoney fa->feature_set = set; 149579da4fa4SJeff Mahoney fa->feature_bit = 1ULL << i; 149679da4fa4SJeff Mahoney } 149779da4fa4SJeff Mahoney } 149879da4fa4SJeff Mahoney } 149979da4fa4SJeff Mahoney 150032a9991fSDavid Sterba /* 150132a9991fSDavid Sterba * Create a sysfs entry for a given block group type at path 150232a9991fSDavid Sterba * /sys/fs/btrfs/UUID/allocation/data/TYPE 150332a9991fSDavid Sterba */ 150432da5386SDavid Sterba void btrfs_sysfs_add_block_group_type(struct btrfs_block_group *cache) 150532a9991fSDavid Sterba { 150632a9991fSDavid Sterba struct btrfs_fs_info *fs_info = cache->fs_info; 150732a9991fSDavid Sterba struct btrfs_space_info *space_info = cache->space_info; 150832a9991fSDavid Sterba struct raid_kobject *rkobj; 150932a9991fSDavid Sterba const int index = btrfs_bg_flags_to_raid_index(cache->flags); 151032a9991fSDavid Sterba unsigned int nofs_flag; 151132a9991fSDavid Sterba int ret; 151232a9991fSDavid Sterba 151332a9991fSDavid Sterba /* 151432a9991fSDavid Sterba * Setup a NOFS context because kobject_add(), deep in its call chain, 151532a9991fSDavid Sterba * does GFP_KERNEL allocations, and we are often called in a context 151632a9991fSDavid Sterba * where if reclaim is triggered we can deadlock (we are either holding 151732a9991fSDavid Sterba * a transaction handle or some lock required for a transaction 151832a9991fSDavid Sterba * commit). 151932a9991fSDavid Sterba */ 152032a9991fSDavid Sterba nofs_flag = memalloc_nofs_save(); 152132a9991fSDavid Sterba 152232a9991fSDavid Sterba rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS); 152332a9991fSDavid Sterba if (!rkobj) { 152432a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 152532a9991fSDavid Sterba btrfs_warn(cache->fs_info, 152632a9991fSDavid Sterba "couldn't alloc memory for raid level kobject"); 152732a9991fSDavid Sterba return; 152832a9991fSDavid Sterba } 152932a9991fSDavid Sterba 153032a9991fSDavid Sterba rkobj->flags = cache->flags; 153132a9991fSDavid Sterba kobject_init(&rkobj->kobj, &btrfs_raid_ktype); 153249ea112dSJosef Bacik 153349ea112dSJosef Bacik /* 153449ea112dSJosef Bacik * We call this either on mount, or if we've created a block group for a 153549ea112dSJosef Bacik * new index type while running (i.e. when restriping). The running 153649ea112dSJosef Bacik * case is tricky because we could race with other threads, so we need 153749ea112dSJosef Bacik * to have this check to make sure we didn't already init the kobject. 153849ea112dSJosef Bacik * 153949ea112dSJosef Bacik * We don't have to protect on the free side because it only happens on 154049ea112dSJosef Bacik * unmount. 154149ea112dSJosef Bacik */ 154249ea112dSJosef Bacik spin_lock(&space_info->lock); 154349ea112dSJosef Bacik if (space_info->block_group_kobjs[index]) { 154449ea112dSJosef Bacik spin_unlock(&space_info->lock); 154549ea112dSJosef Bacik kobject_put(&rkobj->kobj); 154649ea112dSJosef Bacik return; 154749ea112dSJosef Bacik } else { 154849ea112dSJosef Bacik space_info->block_group_kobjs[index] = &rkobj->kobj; 154949ea112dSJosef Bacik } 155049ea112dSJosef Bacik spin_unlock(&space_info->lock); 155149ea112dSJosef Bacik 155232a9991fSDavid Sterba ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s", 155332a9991fSDavid Sterba btrfs_bg_type_to_raid_name(rkobj->flags)); 155432a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 155532a9991fSDavid Sterba if (ret) { 155649ea112dSJosef Bacik spin_lock(&space_info->lock); 155749ea112dSJosef Bacik space_info->block_group_kobjs[index] = NULL; 155849ea112dSJosef Bacik spin_unlock(&space_info->lock); 155932a9991fSDavid Sterba kobject_put(&rkobj->kobj); 156032a9991fSDavid Sterba btrfs_warn(fs_info, 156132a9991fSDavid Sterba "failed to add kobject for block cache, ignoring"); 156232a9991fSDavid Sterba return; 156332a9991fSDavid Sterba } 156432a9991fSDavid Sterba } 156532a9991fSDavid Sterba 1566b5865babSDavid Sterba /* 1567b5865babSDavid Sterba * Remove sysfs directories for all block group types of a given space info and 1568b5865babSDavid Sterba * the space info as well 1569b5865babSDavid Sterba */ 1570b5865babSDavid Sterba void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info) 1571b5865babSDavid Sterba { 1572b5865babSDavid Sterba int i; 1573b5865babSDavid Sterba 1574b5865babSDavid Sterba for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { 1575b5865babSDavid Sterba struct kobject *kobj; 1576b5865babSDavid Sterba 1577b5865babSDavid Sterba kobj = space_info->block_group_kobjs[i]; 1578b5865babSDavid Sterba space_info->block_group_kobjs[i] = NULL; 1579b5865babSDavid Sterba if (kobj) { 1580b5865babSDavid Sterba kobject_del(kobj); 1581b5865babSDavid Sterba kobject_put(kobj); 1582b5865babSDavid Sterba } 1583b5865babSDavid Sterba } 1584b5865babSDavid Sterba kobject_del(&space_info->kobj); 1585b5865babSDavid Sterba kobject_put(&space_info->kobj); 1586b5865babSDavid Sterba } 1587b5865babSDavid Sterba 1588b882327aSDavid Sterba static const char *alloc_name(u64 flags) 1589b882327aSDavid Sterba { 1590b882327aSDavid Sterba switch (flags) { 1591b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA: 1592b882327aSDavid Sterba return "mixed"; 1593b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA: 1594b882327aSDavid Sterba return "metadata"; 1595b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_DATA: 1596b882327aSDavid Sterba return "data"; 1597b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_SYSTEM: 1598b882327aSDavid Sterba return "system"; 1599b882327aSDavid Sterba default: 1600b882327aSDavid Sterba WARN_ON(1); 1601b882327aSDavid Sterba return "invalid-combination"; 1602445d8ab5STom Rix } 1603b882327aSDavid Sterba } 1604b882327aSDavid Sterba 1605b882327aSDavid Sterba /* 1606b882327aSDavid Sterba * Create a sysfs entry for a space info type at path 1607b882327aSDavid Sterba * /sys/fs/btrfs/UUID/allocation/TYPE 1608b882327aSDavid Sterba */ 1609b882327aSDavid Sterba int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info, 1610b882327aSDavid Sterba struct btrfs_space_info *space_info) 1611b882327aSDavid Sterba { 1612b882327aSDavid Sterba int ret; 1613b882327aSDavid Sterba 1614b882327aSDavid Sterba ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, 1615b882327aSDavid Sterba fs_info->space_info_kobj, "%s", 1616b882327aSDavid Sterba alloc_name(space_info->flags)); 1617b882327aSDavid Sterba if (ret) { 1618b882327aSDavid Sterba kobject_put(&space_info->kobj); 1619b882327aSDavid Sterba return ret; 1620b882327aSDavid Sterba } 1621b882327aSDavid Sterba 1622b882327aSDavid Sterba return 0; 1623b882327aSDavid Sterba } 1624b882327aSDavid Sterba 162553f8a74cSAnand Jain void btrfs_sysfs_remove_device(struct btrfs_device *device) 162699994cdeSAnand Jain { 1627985e233eSAnand Jain struct kobject *devices_kobj; 162899994cdeSAnand Jain 1629985e233eSAnand Jain /* 1630985e233eSAnand Jain * Seed fs_devices devices_kobj aren't used, fetch kobject from the 1631985e233eSAnand Jain * fs_info::fs_devices. 1632985e233eSAnand Jain */ 1633985e233eSAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1634985e233eSAnand Jain ASSERT(devices_kobj); 163599994cdeSAnand Jain 16368d65269fSChristoph Hellwig if (device->bdev) 16378d65269fSChristoph Hellwig sysfs_remove_link(devices_kobj, bdev_kobj(device->bdev)->name); 163899994cdeSAnand Jain 1639985e233eSAnand Jain if (device->devid_kobj.state_initialized) { 1640985e233eSAnand Jain kobject_del(&device->devid_kobj); 1641985e233eSAnand Jain kobject_put(&device->devid_kobj); 1642985e233eSAnand Jain wait_for_completion(&device->kobj_unregister); 1643985e233eSAnand Jain } 1644b5ddcffaSAnand Jain } 1645668e48afSAnand Jain 1646668e48afSAnand Jain static ssize_t btrfs_devinfo_in_fs_metadata_show(struct kobject *kobj, 1647668e48afSAnand Jain struct kobj_attribute *a, 1648668e48afSAnand Jain char *buf) 1649668e48afSAnand Jain { 1650668e48afSAnand Jain int val; 1651668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1652668e48afSAnand Jain devid_kobj); 1653668e48afSAnand Jain 1654668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state); 1655668e48afSAnand Jain 1656020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1657668e48afSAnand Jain } 1658668e48afSAnand Jain BTRFS_ATTR(devid, in_fs_metadata, btrfs_devinfo_in_fs_metadata_show); 1659668e48afSAnand Jain 166025864778SAnand Jain static ssize_t btrfs_devinfo_missing_show(struct kobject *kobj, 1661668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1662668e48afSAnand Jain { 1663668e48afSAnand Jain int val; 1664668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1665668e48afSAnand Jain devid_kobj); 1666668e48afSAnand Jain 1667668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state); 1668668e48afSAnand Jain 1669020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1670668e48afSAnand Jain } 167125864778SAnand Jain BTRFS_ATTR(devid, missing, btrfs_devinfo_missing_show); 1672668e48afSAnand Jain 1673668e48afSAnand Jain static ssize_t btrfs_devinfo_replace_target_show(struct kobject *kobj, 1674668e48afSAnand Jain struct kobj_attribute *a, 1675668e48afSAnand Jain char *buf) 1676668e48afSAnand Jain { 1677668e48afSAnand Jain int val; 1678668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1679668e48afSAnand Jain devid_kobj); 1680668e48afSAnand Jain 1681668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state); 1682668e48afSAnand Jain 1683020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1684668e48afSAnand Jain } 1685668e48afSAnand Jain BTRFS_ATTR(devid, replace_target, btrfs_devinfo_replace_target_show); 1686668e48afSAnand Jain 1687eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_show(struct kobject *kobj, 1688eb3b5053SDavid Sterba struct kobj_attribute *a, 1689eb3b5053SDavid Sterba char *buf) 1690eb3b5053SDavid Sterba { 1691eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1692eb3b5053SDavid Sterba devid_kobj); 1693eb3b5053SDavid Sterba 1694020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", READ_ONCE(device->scrub_speed_max)); 1695eb3b5053SDavid Sterba } 1696eb3b5053SDavid Sterba 1697eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_store(struct kobject *kobj, 1698eb3b5053SDavid Sterba struct kobj_attribute *a, 1699eb3b5053SDavid Sterba const char *buf, size_t len) 1700eb3b5053SDavid Sterba { 1701eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1702eb3b5053SDavid Sterba devid_kobj); 1703eb3b5053SDavid Sterba char *endptr; 1704eb3b5053SDavid Sterba unsigned long long limit; 1705eb3b5053SDavid Sterba 1706eb3b5053SDavid Sterba limit = memparse(buf, &endptr); 1707eb3b5053SDavid Sterba WRITE_ONCE(device->scrub_speed_max, limit); 1708eb3b5053SDavid Sterba return len; 1709eb3b5053SDavid Sterba } 1710eb3b5053SDavid Sterba BTRFS_ATTR_RW(devid, scrub_speed_max, btrfs_devinfo_scrub_speed_max_show, 1711eb3b5053SDavid Sterba btrfs_devinfo_scrub_speed_max_store); 1712eb3b5053SDavid Sterba 1713668e48afSAnand Jain static ssize_t btrfs_devinfo_writeable_show(struct kobject *kobj, 1714668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1715668e48afSAnand Jain { 1716668e48afSAnand Jain int val; 1717668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1718668e48afSAnand Jain devid_kobj); 1719668e48afSAnand Jain 1720668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state); 1721668e48afSAnand Jain 1722020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1723668e48afSAnand Jain } 1724668e48afSAnand Jain BTRFS_ATTR(devid, writeable, btrfs_devinfo_writeable_show); 1725668e48afSAnand Jain 1726a26d60deSAnand Jain static ssize_t btrfs_devinfo_fsid_show(struct kobject *kobj, 1727a26d60deSAnand Jain struct kobj_attribute *a, char *buf) 1728a26d60deSAnand Jain { 1729a26d60deSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1730a26d60deSAnand Jain devid_kobj); 1731a26d60deSAnand Jain 1732a26d60deSAnand Jain return sysfs_emit(buf, "%pU\n", device->fs_devices->fsid); 1733a26d60deSAnand Jain } 1734a26d60deSAnand Jain BTRFS_ATTR(devid, fsid, btrfs_devinfo_fsid_show); 1735a26d60deSAnand Jain 1736da658b57SDavid Sterba static ssize_t btrfs_devinfo_error_stats_show(struct kobject *kobj, 1737da658b57SDavid Sterba struct kobj_attribute *a, char *buf) 1738da658b57SDavid Sterba { 1739da658b57SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1740da658b57SDavid Sterba devid_kobj); 1741da658b57SDavid Sterba 1742da658b57SDavid Sterba if (!device->dev_stats_valid) 1743020e5277SAnand Jain return sysfs_emit(buf, "invalid\n"); 1744da658b57SDavid Sterba 1745da658b57SDavid Sterba /* 1746da658b57SDavid Sterba * Print all at once so we get a snapshot of all values from the same 1747da658b57SDavid Sterba * time. Keep them in sync and in order of definition of 1748da658b57SDavid Sterba * btrfs_dev_stat_values. 1749da658b57SDavid Sterba */ 1750020e5277SAnand Jain return sysfs_emit(buf, 1751da658b57SDavid Sterba "write_errs %d\n" 1752da658b57SDavid Sterba "read_errs %d\n" 1753da658b57SDavid Sterba "flush_errs %d\n" 1754da658b57SDavid Sterba "corruption_errs %d\n" 1755da658b57SDavid Sterba "generation_errs %d\n", 1756da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_WRITE_ERRS), 1757da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_READ_ERRS), 1758da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_FLUSH_ERRS), 1759da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_CORRUPTION_ERRS), 1760da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_GENERATION_ERRS)); 1761da658b57SDavid Sterba } 1762da658b57SDavid Sterba BTRFS_ATTR(devid, error_stats, btrfs_devinfo_error_stats_show); 1763da658b57SDavid Sterba 1764e7849e33SAnand Jain /* 1765e7849e33SAnand Jain * Information about one device. 1766e7849e33SAnand Jain * 1767e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/devinfo/<devid>/ 1768e7849e33SAnand Jain */ 1769668e48afSAnand Jain static struct attribute *devid_attrs[] = { 1770da658b57SDavid Sterba BTRFS_ATTR_PTR(devid, error_stats), 1771a26d60deSAnand Jain BTRFS_ATTR_PTR(devid, fsid), 1772668e48afSAnand Jain BTRFS_ATTR_PTR(devid, in_fs_metadata), 1773668e48afSAnand Jain BTRFS_ATTR_PTR(devid, missing), 1774668e48afSAnand Jain BTRFS_ATTR_PTR(devid, replace_target), 1775eb3b5053SDavid Sterba BTRFS_ATTR_PTR(devid, scrub_speed_max), 1776668e48afSAnand Jain BTRFS_ATTR_PTR(devid, writeable), 1777668e48afSAnand Jain NULL 1778668e48afSAnand Jain }; 1779668e48afSAnand Jain ATTRIBUTE_GROUPS(devid); 1780668e48afSAnand Jain 1781668e48afSAnand Jain static void btrfs_release_devid_kobj(struct kobject *kobj) 1782668e48afSAnand Jain { 1783668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1784668e48afSAnand Jain devid_kobj); 1785668e48afSAnand Jain 1786668e48afSAnand Jain memset(&device->devid_kobj, 0, sizeof(struct kobject)); 1787668e48afSAnand Jain complete(&device->kobj_unregister); 1788668e48afSAnand Jain } 1789668e48afSAnand Jain 1790668e48afSAnand Jain static struct kobj_type devid_ktype = { 1791668e48afSAnand Jain .sysfs_ops = &kobj_sysfs_ops, 1792668e48afSAnand Jain .default_groups = devid_groups, 1793668e48afSAnand Jain .release = btrfs_release_devid_kobj, 1794668e48afSAnand Jain }; 1795668e48afSAnand Jain 1796cd36da2eSAnand Jain int btrfs_sysfs_add_device(struct btrfs_device *device) 179729e5be24SJeff Mahoney { 1798178a16c9SAnand Jain int ret; 1799a47bd78dSJosef Bacik unsigned int nofs_flag; 1800178a16c9SAnand Jain struct kobject *devices_kobj; 1801178a16c9SAnand Jain struct kobject *devinfo_kobj; 1802178a16c9SAnand Jain 1803178a16c9SAnand Jain /* 1804178a16c9SAnand Jain * Make sure we use the fs_info::fs_devices to fetch the kobjects even 1805178a16c9SAnand Jain * for the seed fs_devices 1806178a16c9SAnand Jain */ 1807178a16c9SAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1808178a16c9SAnand Jain devinfo_kobj = device->fs_info->fs_devices->devinfo_kobj; 1809178a16c9SAnand Jain ASSERT(devices_kobj); 1810178a16c9SAnand Jain ASSERT(devinfo_kobj); 181129e5be24SJeff Mahoney 1812a47bd78dSJosef Bacik nofs_flag = memalloc_nofs_save(); 1813f085381eSAnand Jain 1814178a16c9SAnand Jain if (device->bdev) { 18158d65269fSChristoph Hellwig struct kobject *disk_kobj = bdev_kobj(device->bdev); 181629e5be24SJeff Mahoney 1817178a16c9SAnand Jain ret = sysfs_create_link(devices_kobj, disk_kobj, disk_kobj->name); 1818178a16c9SAnand Jain if (ret) { 1819178a16c9SAnand Jain btrfs_warn(device->fs_info, 1820178a16c9SAnand Jain "creating sysfs device link for devid %llu failed: %d", 1821178a16c9SAnand Jain device->devid, ret); 1822178a16c9SAnand Jain goto out; 1823178a16c9SAnand Jain } 182429e5be24SJeff Mahoney } 182529e5be24SJeff Mahoney 1826178a16c9SAnand Jain init_completion(&device->kobj_unregister); 1827178a16c9SAnand Jain ret = kobject_init_and_add(&device->devid_kobj, &devid_ktype, 1828178a16c9SAnand Jain devinfo_kobj, "%llu", device->devid); 1829178a16c9SAnand Jain if (ret) { 1830178a16c9SAnand Jain kobject_put(&device->devid_kobj); 1831178a16c9SAnand Jain btrfs_warn(device->fs_info, 1832178a16c9SAnand Jain "devinfo init for devid %llu failed: %d", 1833178a16c9SAnand Jain device->devid, ret); 1834668e48afSAnand Jain } 1835178a16c9SAnand Jain 1836178a16c9SAnand Jain out: 1837a47bd78dSJosef Bacik memalloc_nofs_restore(nofs_flag); 1838178a16c9SAnand Jain return ret; 1839178a16c9SAnand Jain } 1840668e48afSAnand Jain 1841cd36da2eSAnand Jain static int btrfs_sysfs_add_fs_devices(struct btrfs_fs_devices *fs_devices) 1842178a16c9SAnand Jain { 1843178a16c9SAnand Jain int ret; 1844cd36da2eSAnand Jain struct btrfs_device *device; 184530b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 1846178a16c9SAnand Jain 1847178a16c9SAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) { 1848178a16c9SAnand Jain ret = btrfs_sysfs_add_device(device); 1849178a16c9SAnand Jain if (ret) 18507ad3912aSAnand Jain goto fail; 1851178a16c9SAnand Jain } 1852178a16c9SAnand Jain 185330b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 185430b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) { 185530b0e4e0SAnand Jain ret = btrfs_sysfs_add_device(device); 185630b0e4e0SAnand Jain if (ret) 18577ad3912aSAnand Jain goto fail; 185830b0e4e0SAnand Jain } 185930b0e4e0SAnand Jain } 186030b0e4e0SAnand Jain 1861178a16c9SAnand Jain return 0; 18627ad3912aSAnand Jain 18637ad3912aSAnand Jain fail: 18647ad3912aSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devices); 18657ad3912aSAnand Jain return ret; 186629e5be24SJeff Mahoney } 186729e5be24SJeff Mahoney 18685b28692eSDavid Sterba void btrfs_kobject_uevent(struct block_device *bdev, enum kobject_action action) 18695b28692eSDavid Sterba { 18705b28692eSDavid Sterba int ret; 18715b28692eSDavid Sterba 18725b28692eSDavid Sterba ret = kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, action); 18735b28692eSDavid Sterba if (ret) 18745b28692eSDavid Sterba pr_warn("BTRFS: Sending event '%d' to kobject: '%s' (%p): failed\n", 18755b28692eSDavid Sterba action, kobject_name(&disk_to_dev(bdev->bd_disk)->kobj), 18765b28692eSDavid Sterba &disk_to_dev(bdev->bd_disk)->kobj); 18775b28692eSDavid Sterba } 18785b28692eSDavid Sterba 18798e560081SNikolay Borisov void btrfs_sysfs_update_sprout_fsid(struct btrfs_fs_devices *fs_devices) 18808e560081SNikolay Borisov 1881f93c3997SDavid Sterba { 1882f93c3997SDavid Sterba char fsid_buf[BTRFS_UUID_UNPARSED_SIZE]; 1883f93c3997SDavid Sterba 1884f93c3997SDavid Sterba /* 1885f93c3997SDavid Sterba * Sprouting changes fsid of the mounted filesystem, rename the fsid 1886f93c3997SDavid Sterba * directory 1887f93c3997SDavid Sterba */ 18888e560081SNikolay Borisov snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", fs_devices->fsid); 1889f93c3997SDavid Sterba if (kobject_rename(&fs_devices->fsid_kobj, fsid_buf)) 1890f93c3997SDavid Sterba btrfs_warn(fs_devices->fs_info, 1891f93c3997SDavid Sterba "sysfs: failed to create fsid for sprout"); 1892f93c3997SDavid Sterba } 1893f93c3997SDavid Sterba 1894668e48afSAnand Jain void btrfs_sysfs_update_devid(struct btrfs_device *device) 1895668e48afSAnand Jain { 1896668e48afSAnand Jain char tmp[24]; 1897668e48afSAnand Jain 1898668e48afSAnand Jain snprintf(tmp, sizeof(tmp), "%llu", device->devid); 1899668e48afSAnand Jain 1900668e48afSAnand Jain if (kobject_rename(&device->devid_kobj, tmp)) 1901668e48afSAnand Jain btrfs_warn(device->fs_devices->fs_info, 1902668e48afSAnand Jain "sysfs: failed to update devid for %llu", 1903668e48afSAnand Jain device->devid); 1904668e48afSAnand Jain } 1905668e48afSAnand Jain 1906510d7360SJeff Mahoney /* /sys/fs/btrfs/ entry */ 1907510d7360SJeff Mahoney static struct kset *btrfs_kset; 1908510d7360SJeff Mahoney 190972059215SAnand Jain /* 1910c6761a9eSAnand Jain * Creates: 1911c6761a9eSAnand Jain * /sys/fs/btrfs/UUID 1912c6761a9eSAnand Jain * 191372059215SAnand Jain * Can be called by the device discovery thread. 191472059215SAnand Jain */ 1915c6761a9eSAnand Jain int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs) 19165ac1d209SJeff Mahoney { 19175ac1d209SJeff Mahoney int error; 19185ac1d209SJeff Mahoney 19192e7910d6SAnand Jain init_completion(&fs_devs->kobj_unregister); 1920c1b7e474SAnand Jain fs_devs->fsid_kobj.kset = btrfs_kset; 1921c6761a9eSAnand Jain error = kobject_init_and_add(&fs_devs->fsid_kobj, &btrfs_ktype, NULL, 1922c6761a9eSAnand Jain "%pU", fs_devs->fsid); 1923e3277335STobin C. Harding if (error) { 1924e3277335STobin C. Harding kobject_put(&fs_devs->fsid_kobj); 192572059215SAnand Jain return error; 192672059215SAnand Jain } 192772059215SAnand Jain 1928bc036bb3SAnand Jain fs_devs->devices_kobj = kobject_create_and_add("devices", 1929bc036bb3SAnand Jain &fs_devs->fsid_kobj); 1930bc036bb3SAnand Jain if (!fs_devs->devices_kobj) { 1931bc036bb3SAnand Jain btrfs_err(fs_devs->fs_info, 1932bc036bb3SAnand Jain "failed to init sysfs device interface"); 19331f6087e6SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1934bc036bb3SAnand Jain return -ENOMEM; 1935bc036bb3SAnand Jain } 1936bc036bb3SAnand Jain 1937a013d141SAnand Jain fs_devs->devinfo_kobj = kobject_create_and_add("devinfo", 1938a013d141SAnand Jain &fs_devs->fsid_kobj); 1939a013d141SAnand Jain if (!fs_devs->devinfo_kobj) { 1940a013d141SAnand Jain btrfs_err(fs_devs->fs_info, 1941a013d141SAnand Jain "failed to init sysfs devinfo kobject"); 1942a013d141SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1943a013d141SAnand Jain return -ENOMEM; 1944a013d141SAnand Jain } 1945a013d141SAnand Jain 1946e3277335STobin C. Harding return 0; 1947e3277335STobin C. Harding } 1948e3277335STobin C. Harding 194996f3136eSAnand Jain int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info) 195072059215SAnand Jain { 195172059215SAnand Jain int error; 19522e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = fs_info->fs_devices; 1953c1b7e474SAnand Jain struct kobject *fsid_kobj = &fs_devs->fsid_kobj; 195472059215SAnand Jain 1955cd36da2eSAnand Jain error = btrfs_sysfs_add_fs_devices(fs_devs); 1956e453d989SJeff Mahoney if (error) 1957e453d989SJeff Mahoney return error; 1958510d7360SJeff Mahoney 1959c1b7e474SAnand Jain error = sysfs_create_files(fsid_kobj, btrfs_attrs); 1960e453d989SJeff Mahoney if (error) { 196153f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devs); 1962e453d989SJeff Mahoney return error; 1963e453d989SJeff Mahoney } 196479da4fa4SJeff Mahoney 1965c1b7e474SAnand Jain error = sysfs_create_group(fsid_kobj, 19660dd2906fSAnand Jain &btrfs_feature_attr_group); 19670dd2906fSAnand Jain if (error) 19680dd2906fSAnand Jain goto failure; 19690dd2906fSAnand Jain 19706e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 197193945cb4SDennis Zhou fs_info->debug_kobj = kobject_create_and_add("debug", fsid_kobj); 197293945cb4SDennis Zhou if (!fs_info->debug_kobj) { 197393945cb4SDennis Zhou error = -ENOMEM; 197493945cb4SDennis Zhou goto failure; 197593945cb4SDennis Zhou } 197693945cb4SDennis Zhou 197793945cb4SDennis Zhou error = sysfs_create_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 19786e369febSDavid Sterba if (error) 19796e369febSDavid Sterba goto failure; 1980fb731430SDavid Sterba #endif 1981e4faab84SDennis Zhou 1982e4faab84SDennis Zhou /* Discard directory */ 1983fb731430SDavid Sterba fs_info->discard_kobj = kobject_create_and_add("discard", fsid_kobj); 1984fb731430SDavid Sterba if (!fs_info->discard_kobj) { 1985e4faab84SDennis Zhou error = -ENOMEM; 1986e4faab84SDennis Zhou goto failure; 1987e4faab84SDennis Zhou } 1988e4faab84SDennis Zhou 1989fb731430SDavid Sterba error = sysfs_create_files(fs_info->discard_kobj, discard_attrs); 1990e4faab84SDennis Zhou if (error) 1991e4faab84SDennis Zhou goto failure; 19926e369febSDavid Sterba 1993e453d989SJeff Mahoney error = addrm_unknown_feature_attrs(fs_info, true); 199479da4fa4SJeff Mahoney if (error) 199579da4fa4SJeff Mahoney goto failure; 199679da4fa4SJeff Mahoney 19973092c68fSNikolay Borisov error = sysfs_create_link(fsid_kobj, &fs_info->sb->s_bdi->dev->kobj, "bdi"); 19983092c68fSNikolay Borisov if (error) 19993092c68fSNikolay Borisov goto failure; 20003092c68fSNikolay Borisov 20016ab0a202SJeff Mahoney fs_info->space_info_kobj = kobject_create_and_add("allocation", 2002c1b7e474SAnand Jain fsid_kobj); 20036ab0a202SJeff Mahoney if (!fs_info->space_info_kobj) { 20046ab0a202SJeff Mahoney error = -ENOMEM; 20056ab0a202SJeff Mahoney goto failure; 20066ab0a202SJeff Mahoney } 20076ab0a202SJeff Mahoney 20086ab0a202SJeff Mahoney error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs); 20096ab0a202SJeff Mahoney if (error) 20106ab0a202SJeff Mahoney goto failure; 20116ab0a202SJeff Mahoney 201279da4fa4SJeff Mahoney return 0; 201379da4fa4SJeff Mahoney failure: 20146618a59bSAnand Jain btrfs_sysfs_remove_mounted(fs_info); 20155ac1d209SJeff Mahoney return error; 20165ac1d209SJeff Mahoney } 20175ac1d209SJeff Mahoney 2018*ed2e35d8SQu Wenruo static ssize_t qgroup_enabled_show(struct kobject *qgroups_kobj, 2019*ed2e35d8SQu Wenruo struct kobj_attribute *a, 2020*ed2e35d8SQu Wenruo char *buf) 2021*ed2e35d8SQu Wenruo { 2022*ed2e35d8SQu Wenruo struct btrfs_fs_info *fs_info = to_fs_info(qgroups_kobj->parent); 2023*ed2e35d8SQu Wenruo bool enabled; 2024*ed2e35d8SQu Wenruo 2025*ed2e35d8SQu Wenruo spin_lock(&fs_info->qgroup_lock); 2026*ed2e35d8SQu Wenruo enabled = fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON; 2027*ed2e35d8SQu Wenruo spin_unlock(&fs_info->qgroup_lock); 2028*ed2e35d8SQu Wenruo 2029*ed2e35d8SQu Wenruo return sysfs_emit(buf, "%d\n", enabled); 2030*ed2e35d8SQu Wenruo } 2031*ed2e35d8SQu Wenruo BTRFS_ATTR(qgroups, enabled, qgroup_enabled_show); 2032*ed2e35d8SQu Wenruo 2033*ed2e35d8SQu Wenruo static ssize_t qgroup_inconsistent_show(struct kobject *qgroups_kobj, 2034*ed2e35d8SQu Wenruo struct kobj_attribute *a, 2035*ed2e35d8SQu Wenruo char *buf) 2036*ed2e35d8SQu Wenruo { 2037*ed2e35d8SQu Wenruo struct btrfs_fs_info *fs_info = to_fs_info(qgroups_kobj->parent); 2038*ed2e35d8SQu Wenruo bool inconsistent; 2039*ed2e35d8SQu Wenruo 2040*ed2e35d8SQu Wenruo spin_lock(&fs_info->qgroup_lock); 2041*ed2e35d8SQu Wenruo inconsistent = (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT); 2042*ed2e35d8SQu Wenruo spin_unlock(&fs_info->qgroup_lock); 2043*ed2e35d8SQu Wenruo 2044*ed2e35d8SQu Wenruo return sysfs_emit(buf, "%d\n", inconsistent); 2045*ed2e35d8SQu Wenruo } 2046*ed2e35d8SQu Wenruo BTRFS_ATTR(qgroups, inconsistent, qgroup_inconsistent_show); 2047*ed2e35d8SQu Wenruo 2048*ed2e35d8SQu Wenruo /* 2049*ed2e35d8SQu Wenruo * Qgroups global info 2050*ed2e35d8SQu Wenruo * 2051*ed2e35d8SQu Wenruo * Path: /sys/fs/btrfs/<uuid>/qgroups/ 2052*ed2e35d8SQu Wenruo */ 2053*ed2e35d8SQu Wenruo static struct attribute *qgroups_attrs[] = { 2054*ed2e35d8SQu Wenruo BTRFS_ATTR_PTR(qgroups, enabled), 2055*ed2e35d8SQu Wenruo BTRFS_ATTR_PTR(qgroups, inconsistent), 2056*ed2e35d8SQu Wenruo NULL 2057*ed2e35d8SQu Wenruo }; 2058*ed2e35d8SQu Wenruo ATTRIBUTE_GROUPS(qgroups); 2059*ed2e35d8SQu Wenruo 2060*ed2e35d8SQu Wenruo static void qgroups_release(struct kobject *kobj) 2061*ed2e35d8SQu Wenruo { 2062*ed2e35d8SQu Wenruo kfree(kobj); 2063*ed2e35d8SQu Wenruo } 2064*ed2e35d8SQu Wenruo 2065*ed2e35d8SQu Wenruo static struct kobj_type qgroups_ktype = { 2066*ed2e35d8SQu Wenruo .sysfs_ops = &kobj_sysfs_ops, 2067*ed2e35d8SQu Wenruo .default_groups = qgroups_groups, 2068*ed2e35d8SQu Wenruo .release = qgroups_release, 2069*ed2e35d8SQu Wenruo }; 2070*ed2e35d8SQu Wenruo 207149e5fb46SQu Wenruo static inline struct btrfs_fs_info *qgroup_kobj_to_fs_info(struct kobject *kobj) 207249e5fb46SQu Wenruo { 207349e5fb46SQu Wenruo return to_fs_info(kobj->parent->parent); 207449e5fb46SQu Wenruo } 207549e5fb46SQu Wenruo 207649e5fb46SQu Wenruo #define QGROUP_ATTR(_member, _show_name) \ 207749e5fb46SQu Wenruo static ssize_t btrfs_qgroup_show_##_member(struct kobject *qgroup_kobj, \ 207849e5fb46SQu Wenruo struct kobj_attribute *a, \ 207949e5fb46SQu Wenruo char *buf) \ 208049e5fb46SQu Wenruo { \ 208149e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 208249e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 208349e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 208449e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->_member, &fs_info->qgroup_lock, buf); \ 208549e5fb46SQu Wenruo } \ 208649e5fb46SQu Wenruo BTRFS_ATTR(qgroup, _show_name, btrfs_qgroup_show_##_member) 208749e5fb46SQu Wenruo 208849e5fb46SQu Wenruo #define QGROUP_RSV_ATTR(_name, _type) \ 208949e5fb46SQu Wenruo static ssize_t btrfs_qgroup_rsv_show_##_name(struct kobject *qgroup_kobj, \ 209049e5fb46SQu Wenruo struct kobj_attribute *a, \ 209149e5fb46SQu Wenruo char *buf) \ 209249e5fb46SQu Wenruo { \ 209349e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 209449e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 209549e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 209649e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->rsv.values[_type], \ 209749e5fb46SQu Wenruo &fs_info->qgroup_lock, buf); \ 209849e5fb46SQu Wenruo } \ 209949e5fb46SQu Wenruo BTRFS_ATTR(qgroup, rsv_##_name, btrfs_qgroup_rsv_show_##_name) 210049e5fb46SQu Wenruo 210149e5fb46SQu Wenruo QGROUP_ATTR(rfer, referenced); 210249e5fb46SQu Wenruo QGROUP_ATTR(excl, exclusive); 210349e5fb46SQu Wenruo QGROUP_ATTR(max_rfer, max_referenced); 210449e5fb46SQu Wenruo QGROUP_ATTR(max_excl, max_exclusive); 210549e5fb46SQu Wenruo QGROUP_ATTR(lim_flags, limit_flags); 210649e5fb46SQu Wenruo QGROUP_RSV_ATTR(data, BTRFS_QGROUP_RSV_DATA); 210749e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_pertrans, BTRFS_QGROUP_RSV_META_PERTRANS); 210849e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_prealloc, BTRFS_QGROUP_RSV_META_PREALLOC); 210949e5fb46SQu Wenruo 2110e7849e33SAnand Jain /* 2111e7849e33SAnand Jain * Qgroup information. 2112e7849e33SAnand Jain * 2113e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/qgroups/<level>_<qgroupid>/ 2114e7849e33SAnand Jain */ 211549e5fb46SQu Wenruo static struct attribute *qgroup_attrs[] = { 211649e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, referenced), 211749e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, exclusive), 211849e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_referenced), 211949e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_exclusive), 212049e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, limit_flags), 212149e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_data), 212249e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_pertrans), 212349e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_prealloc), 212449e5fb46SQu Wenruo NULL 212549e5fb46SQu Wenruo }; 212649e5fb46SQu Wenruo ATTRIBUTE_GROUPS(qgroup); 212749e5fb46SQu Wenruo 212849e5fb46SQu Wenruo static void qgroup_release(struct kobject *kobj) 212949e5fb46SQu Wenruo { 213049e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(kobj, struct btrfs_qgroup, kobj); 213149e5fb46SQu Wenruo 213249e5fb46SQu Wenruo memset(&qgroup->kobj, 0, sizeof(*kobj)); 213349e5fb46SQu Wenruo } 213449e5fb46SQu Wenruo 213549e5fb46SQu Wenruo static struct kobj_type qgroup_ktype = { 213649e5fb46SQu Wenruo .sysfs_ops = &kobj_sysfs_ops, 213749e5fb46SQu Wenruo .release = qgroup_release, 213849e5fb46SQu Wenruo .default_groups = qgroup_groups, 213949e5fb46SQu Wenruo }; 214049e5fb46SQu Wenruo 214149e5fb46SQu Wenruo int btrfs_sysfs_add_one_qgroup(struct btrfs_fs_info *fs_info, 214249e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 214349e5fb46SQu Wenruo { 214449e5fb46SQu Wenruo struct kobject *qgroups_kobj = fs_info->qgroups_kobj; 214549e5fb46SQu Wenruo int ret; 214649e5fb46SQu Wenruo 214749e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 214849e5fb46SQu Wenruo return 0; 214949e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) 215049e5fb46SQu Wenruo return 0; 215149e5fb46SQu Wenruo if (!qgroups_kobj) 215249e5fb46SQu Wenruo return -EINVAL; 215349e5fb46SQu Wenruo 215449e5fb46SQu Wenruo ret = kobject_init_and_add(&qgroup->kobj, &qgroup_ktype, qgroups_kobj, 215549e5fb46SQu Wenruo "%hu_%llu", btrfs_qgroup_level(qgroup->qgroupid), 215649e5fb46SQu Wenruo btrfs_qgroup_subvolid(qgroup->qgroupid)); 215749e5fb46SQu Wenruo if (ret < 0) 215849e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 215949e5fb46SQu Wenruo 216049e5fb46SQu Wenruo return ret; 216149e5fb46SQu Wenruo } 216249e5fb46SQu Wenruo 216349e5fb46SQu Wenruo void btrfs_sysfs_del_qgroups(struct btrfs_fs_info *fs_info) 216449e5fb46SQu Wenruo { 216549e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 216649e5fb46SQu Wenruo struct btrfs_qgroup *next; 216749e5fb46SQu Wenruo 216849e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 216949e5fb46SQu Wenruo return; 217049e5fb46SQu Wenruo 217149e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 217249e5fb46SQu Wenruo &fs_info->qgroup_tree, node) 217349e5fb46SQu Wenruo btrfs_sysfs_del_one_qgroup(fs_info, qgroup); 217462ab2cc0SQu Wenruo if (fs_info->qgroups_kobj) { 217549e5fb46SQu Wenruo kobject_del(fs_info->qgroups_kobj); 217649e5fb46SQu Wenruo kobject_put(fs_info->qgroups_kobj); 217749e5fb46SQu Wenruo fs_info->qgroups_kobj = NULL; 217849e5fb46SQu Wenruo } 217962ab2cc0SQu Wenruo } 218049e5fb46SQu Wenruo 218149e5fb46SQu Wenruo /* Called when qgroups get initialized, thus there is no need for locking */ 218249e5fb46SQu Wenruo int btrfs_sysfs_add_qgroups(struct btrfs_fs_info *fs_info) 218349e5fb46SQu Wenruo { 218449e5fb46SQu Wenruo struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 218549e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 218649e5fb46SQu Wenruo struct btrfs_qgroup *next; 218749e5fb46SQu Wenruo int ret = 0; 218849e5fb46SQu Wenruo 218949e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 219049e5fb46SQu Wenruo return 0; 219149e5fb46SQu Wenruo 219249e5fb46SQu Wenruo ASSERT(fsid_kobj); 219349e5fb46SQu Wenruo if (fs_info->qgroups_kobj) 219449e5fb46SQu Wenruo return 0; 219549e5fb46SQu Wenruo 2196*ed2e35d8SQu Wenruo fs_info->qgroups_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); 2197*ed2e35d8SQu Wenruo if (!fs_info->qgroups_kobj) 2198*ed2e35d8SQu Wenruo return -ENOMEM; 2199*ed2e35d8SQu Wenruo 2200*ed2e35d8SQu Wenruo ret = kobject_init_and_add(fs_info->qgroups_kobj, &qgroups_ktype, 2201*ed2e35d8SQu Wenruo fsid_kobj, "qgroups"); 2202*ed2e35d8SQu Wenruo if (ret < 0) 220349e5fb46SQu Wenruo goto out; 2204*ed2e35d8SQu Wenruo 220549e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 220649e5fb46SQu Wenruo &fs_info->qgroup_tree, node) { 220749e5fb46SQu Wenruo ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup); 220849e5fb46SQu Wenruo if (ret < 0) 220949e5fb46SQu Wenruo goto out; 221049e5fb46SQu Wenruo } 221149e5fb46SQu Wenruo 221249e5fb46SQu Wenruo out: 221349e5fb46SQu Wenruo if (ret < 0) 221449e5fb46SQu Wenruo btrfs_sysfs_del_qgroups(fs_info); 221549e5fb46SQu Wenruo return ret; 221649e5fb46SQu Wenruo } 221749e5fb46SQu Wenruo 221849e5fb46SQu Wenruo void btrfs_sysfs_del_one_qgroup(struct btrfs_fs_info *fs_info, 221949e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 222049e5fb46SQu Wenruo { 222149e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 222249e5fb46SQu Wenruo return; 222349e5fb46SQu Wenruo 222449e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) { 222549e5fb46SQu Wenruo kobject_del(&qgroup->kobj); 222649e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 222749e5fb46SQu Wenruo } 222849e5fb46SQu Wenruo } 2229444e7516SDavid Sterba 2230444e7516SDavid Sterba /* 2231444e7516SDavid Sterba * Change per-fs features in /sys/fs/btrfs/UUID/features to match current 2232444e7516SDavid Sterba * values in superblock. Call after any changes to incompat/compat_ro flags 2233444e7516SDavid Sterba */ 2234444e7516SDavid Sterba void btrfs_sysfs_feature_update(struct btrfs_fs_info *fs_info, 2235444e7516SDavid Sterba u64 bit, enum btrfs_feature_set set) 2236444e7516SDavid Sterba { 2237444e7516SDavid Sterba struct btrfs_fs_devices *fs_devs; 2238444e7516SDavid Sterba struct kobject *fsid_kobj; 223924646481SLeon Romanovsky u64 __maybe_unused features; 224024646481SLeon Romanovsky int __maybe_unused ret; 2241444e7516SDavid Sterba 2242444e7516SDavid Sterba if (!fs_info) 2243444e7516SDavid Sterba return; 2244444e7516SDavid Sterba 224524646481SLeon Romanovsky /* 224624646481SLeon Romanovsky * See 14e46e04958df74 and e410e34fad913dd, feature bit updates are not 224724646481SLeon Romanovsky * safe when called from some contexts (eg. balance) 224824646481SLeon Romanovsky */ 2249444e7516SDavid Sterba features = get_features(fs_info, set); 2250444e7516SDavid Sterba ASSERT(bit & supported_feature_masks[set]); 2251444e7516SDavid Sterba 2252444e7516SDavid Sterba fs_devs = fs_info->fs_devices; 2253444e7516SDavid Sterba fsid_kobj = &fs_devs->fsid_kobj; 2254444e7516SDavid Sterba 2255bf609206SDavid Sterba if (!fsid_kobj->state_initialized) 2256bf609206SDavid Sterba return; 2257bf609206SDavid Sterba 2258444e7516SDavid Sterba /* 2259444e7516SDavid Sterba * FIXME: this is too heavy to update just one value, ideally we'd like 2260444e7516SDavid Sterba * to use sysfs_update_group but some refactoring is needed first. 2261444e7516SDavid Sterba */ 2262444e7516SDavid Sterba sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 2263444e7516SDavid Sterba ret = sysfs_create_group(fsid_kobj, &btrfs_feature_attr_group); 2264444e7516SDavid Sterba } 2265444e7516SDavid Sterba 2266f5c29bd9SLiu Bo int __init btrfs_init_sysfs(void) 226758176a96SJosef Bacik { 2268079b72bcSJeff Mahoney int ret; 22691bae3098SDavid Sterba 2270e3fe4e71SGreg KH btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); 2271e3fe4e71SGreg KH if (!btrfs_kset) 2272e3fe4e71SGreg KH return -ENOMEM; 2273079b72bcSJeff Mahoney 22741bae3098SDavid Sterba init_feature_attrs(); 22751bae3098SDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2276001a648dSFilipe Manana if (ret) 2277001a648dSFilipe Manana goto out2; 2278f902bd3aSMisono Tomohiro ret = sysfs_merge_group(&btrfs_kset->kobj, 2279f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2280f902bd3aSMisono Tomohiro if (ret) 2281f902bd3aSMisono Tomohiro goto out_remove_group; 2282001a648dSFilipe Manana 22836e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 22846e369febSDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 22856e369febSDavid Sterba if (ret) 22866e369febSDavid Sterba goto out2; 22876e369febSDavid Sterba #endif 22886e369febSDavid Sterba 2289001a648dSFilipe Manana return 0; 2290f902bd3aSMisono Tomohiro 2291f902bd3aSMisono Tomohiro out_remove_group: 2292f902bd3aSMisono Tomohiro sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2293001a648dSFilipe Manana out2: 2294001a648dSFilipe Manana kset_unregister(btrfs_kset); 22951bae3098SDavid Sterba 22961bae3098SDavid Sterba return ret; 229758176a96SJosef Bacik } 229858176a96SJosef Bacik 2299e67c718bSDavid Sterba void __cold btrfs_exit_sysfs(void) 230058176a96SJosef Bacik { 2301f902bd3aSMisono Tomohiro sysfs_unmerge_group(&btrfs_kset->kobj, 2302f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2303079b72bcSJeff Mahoney sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 230471e8978eSDennis Zhou #ifdef CONFIG_BTRFS_DEBUG 230571e8978eSDennis Zhou sysfs_remove_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 230671e8978eSDennis Zhou #endif 2307e3fe4e71SGreg KH kset_unregister(btrfs_kset); 230858176a96SJosef Bacik } 2309