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" 24079b72bcSJeff Mahoney 25e7849e33SAnand Jain /* 26e7849e33SAnand Jain * Structure name Path 27e7849e33SAnand Jain * -------------------------------------------------------------------------- 28e7849e33SAnand Jain * btrfs_supported_static_feature_attrs /sys/fs/btrfs/features 29e7849e33SAnand Jain * btrfs_supported_feature_attrs /sys/fs/btrfs/features and 30e7849e33SAnand Jain * /sys/fs/btrfs/<uuid>/features 31e7849e33SAnand Jain * btrfs_attrs /sys/fs/btrfs/<uuid> 32e7849e33SAnand Jain * devid_attrs /sys/fs/btrfs/<uuid>/devinfo/<devid> 33e7849e33SAnand Jain * allocation_attrs /sys/fs/btrfs/<uuid>/allocation 34e7849e33SAnand Jain * qgroup_attrs /sys/fs/btrfs/<uuid>/qgroups/<level>_<qgroupid> 35e7849e33SAnand Jain * space_info_attrs /sys/fs/btrfs/<uuid>/allocation/<bg-type> 36e7849e33SAnand Jain * raid_attrs /sys/fs/btrfs/<uuid>/allocation/<bg-type>/<bg-profile> 37e7849e33SAnand Jain * 38e7849e33SAnand Jain * When built with BTRFS_CONFIG_DEBUG: 39e7849e33SAnand Jain * 40e7849e33SAnand Jain * btrfs_debug_feature_attrs /sys/fs/btrfs/debug 41e7849e33SAnand Jain * btrfs_debug_mount_attrs /sys/fs/btrfs/<uuid>/debug 42e7849e33SAnand Jain * discard_debug_attrs /sys/fs/btrfs/<uuid>/debug/discard 43e7849e33SAnand Jain */ 44e7849e33SAnand Jain 459188db61SDavid Sterba struct btrfs_feature_attr { 469188db61SDavid Sterba struct kobj_attribute kobj_attr; 479188db61SDavid Sterba enum btrfs_feature_set feature_set; 489188db61SDavid Sterba u64 feature_bit; 499188db61SDavid Sterba }; 509188db61SDavid Sterba 519188db61SDavid Sterba /* For raid type sysfs entries */ 529188db61SDavid Sterba struct raid_kobject { 539188db61SDavid Sterba u64 flags; 549188db61SDavid Sterba struct kobject kobj; 559188db61SDavid Sterba }; 569188db61SDavid Sterba 579188db61SDavid Sterba #define __INIT_KOBJ_ATTR(_name, _mode, _show, _store) \ 589188db61SDavid Sterba { \ 599188db61SDavid Sterba .attr = { .name = __stringify(_name), .mode = _mode }, \ 609188db61SDavid Sterba .show = _show, \ 619188db61SDavid Sterba .store = _store, \ 629188db61SDavid Sterba } 639188db61SDavid Sterba 649188db61SDavid Sterba #define BTRFS_ATTR_RW(_prefix, _name, _show, _store) \ 659188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 669188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0644, _show, _store) 679188db61SDavid Sterba 689188db61SDavid Sterba #define BTRFS_ATTR(_prefix, _name, _show) \ 699188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 709188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0444, _show, NULL) 719188db61SDavid Sterba 729188db61SDavid Sterba #define BTRFS_ATTR_PTR(_prefix, _name) \ 739188db61SDavid Sterba (&btrfs_attr_##_prefix##_##_name.attr) 749188db61SDavid Sterba 759188db61SDavid Sterba #define BTRFS_FEAT_ATTR(_name, _feature_set, _feature_prefix, _feature_bit) \ 769188db61SDavid Sterba static struct btrfs_feature_attr btrfs_attr_features_##_name = { \ 779188db61SDavid Sterba .kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO, \ 789188db61SDavid Sterba btrfs_feature_attr_show, \ 799188db61SDavid Sterba btrfs_feature_attr_store), \ 809188db61SDavid Sterba .feature_set = _feature_set, \ 819188db61SDavid Sterba .feature_bit = _feature_prefix ##_## _feature_bit, \ 829188db61SDavid Sterba } 839188db61SDavid Sterba #define BTRFS_FEAT_ATTR_PTR(_name) \ 849188db61SDavid Sterba (&btrfs_attr_features_##_name.kobj_attr.attr) 859188db61SDavid Sterba 869188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT(name, feature) \ 879188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT, BTRFS_FEATURE_COMPAT, feature) 889188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT_RO(name, feature) \ 899188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT_RO, BTRFS_FEATURE_COMPAT_RO, feature) 909188db61SDavid Sterba #define BTRFS_FEAT_ATTR_INCOMPAT(name, feature) \ 919188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_INCOMPAT, BTRFS_FEATURE_INCOMPAT, feature) 929188db61SDavid Sterba 93510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); 942e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj); 955ac1d209SJeff Mahoney 968f52316cSDavid Sterba static struct btrfs_feature_attr *to_btrfs_feature_attr(struct kobj_attribute *a) 978f52316cSDavid Sterba { 988f52316cSDavid Sterba return container_of(a, struct btrfs_feature_attr, kobj_attr); 998f52316cSDavid Sterba } 1008f52316cSDavid Sterba 1018f52316cSDavid Sterba static struct kobj_attribute *attr_to_btrfs_attr(struct attribute *attr) 1028f52316cSDavid Sterba { 1038f52316cSDavid Sterba return container_of(attr, struct kobj_attribute, attr); 1048f52316cSDavid Sterba } 1058f52316cSDavid Sterba 1068f52316cSDavid Sterba static struct btrfs_feature_attr *attr_to_btrfs_feature_attr( 1078f52316cSDavid Sterba struct attribute *attr) 1088f52316cSDavid Sterba { 1098f52316cSDavid Sterba return to_btrfs_feature_attr(attr_to_btrfs_attr(attr)); 1108f52316cSDavid Sterba } 1118f52316cSDavid Sterba 112510d7360SJeff Mahoney static u64 get_features(struct btrfs_fs_info *fs_info, 113510d7360SJeff Mahoney enum btrfs_feature_set set) 1145ac1d209SJeff Mahoney { 115510d7360SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 116510d7360SJeff Mahoney if (set == FEAT_COMPAT) 117510d7360SJeff Mahoney return btrfs_super_compat_flags(disk_super); 118510d7360SJeff Mahoney else if (set == FEAT_COMPAT_RO) 119510d7360SJeff Mahoney return btrfs_super_compat_ro_flags(disk_super); 120510d7360SJeff Mahoney else 121510d7360SJeff Mahoney return btrfs_super_incompat_flags(disk_super); 1225ac1d209SJeff Mahoney } 1235ac1d209SJeff Mahoney 124ba631941SJeff Mahoney static void set_features(struct btrfs_fs_info *fs_info, 125ba631941SJeff Mahoney enum btrfs_feature_set set, u64 features) 126ba631941SJeff Mahoney { 127ba631941SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 128ba631941SJeff Mahoney if (set == FEAT_COMPAT) 129ba631941SJeff Mahoney btrfs_set_super_compat_flags(disk_super, features); 130ba631941SJeff Mahoney else if (set == FEAT_COMPAT_RO) 131ba631941SJeff Mahoney btrfs_set_super_compat_ro_flags(disk_super, features); 132ba631941SJeff Mahoney else 133ba631941SJeff Mahoney btrfs_set_super_incompat_flags(disk_super, features); 134ba631941SJeff Mahoney } 135ba631941SJeff Mahoney 136ba631941SJeff Mahoney static int can_modify_feature(struct btrfs_feature_attr *fa) 137ba631941SJeff Mahoney { 138ba631941SJeff Mahoney int val = 0; 139ba631941SJeff Mahoney u64 set, clear; 140ba631941SJeff Mahoney switch (fa->feature_set) { 141ba631941SJeff Mahoney case FEAT_COMPAT: 142ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 143ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 144ba631941SJeff Mahoney break; 145ba631941SJeff Mahoney case FEAT_COMPAT_RO: 146ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 147ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 148ba631941SJeff Mahoney break; 149ba631941SJeff Mahoney case FEAT_INCOMPAT: 150ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 151ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 152ba631941SJeff Mahoney break; 153ba631941SJeff Mahoney default: 15462e85577SJeff Mahoney pr_warn("btrfs: sysfs: unknown feature set %d\n", 155cc37bb04SDavid Sterba fa->feature_set); 156cc37bb04SDavid Sterba return 0; 157ba631941SJeff Mahoney } 158ba631941SJeff Mahoney 159ba631941SJeff Mahoney if (set & fa->feature_bit) 160ba631941SJeff Mahoney val |= 1; 161ba631941SJeff Mahoney if (clear & fa->feature_bit) 162ba631941SJeff Mahoney val |= 2; 163ba631941SJeff Mahoney 164ba631941SJeff Mahoney return val; 165ba631941SJeff Mahoney } 166ba631941SJeff Mahoney 167079b72bcSJeff Mahoney static ssize_t btrfs_feature_attr_show(struct kobject *kobj, 168079b72bcSJeff Mahoney struct kobj_attribute *a, char *buf) 169079b72bcSJeff Mahoney { 170510d7360SJeff Mahoney int val = 0; 171510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 172510d7360SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 173ba631941SJeff Mahoney if (fs_info) { 174510d7360SJeff Mahoney u64 features = get_features(fs_info, fa->feature_set); 175510d7360SJeff Mahoney if (features & fa->feature_bit) 176510d7360SJeff Mahoney val = 1; 177ba631941SJeff Mahoney } else 178ba631941SJeff Mahoney val = can_modify_feature(fa); 179510d7360SJeff Mahoney 180020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 181510d7360SJeff Mahoney } 182510d7360SJeff Mahoney 183ba631941SJeff Mahoney static ssize_t btrfs_feature_attr_store(struct kobject *kobj, 184ba631941SJeff Mahoney struct kobj_attribute *a, 185ba631941SJeff Mahoney const char *buf, size_t count) 186ba631941SJeff Mahoney { 187ba631941SJeff Mahoney struct btrfs_fs_info *fs_info; 188ba631941SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 189ba631941SJeff Mahoney u64 features, set, clear; 190ba631941SJeff Mahoney unsigned long val; 191ba631941SJeff Mahoney int ret; 192ba631941SJeff Mahoney 193ba631941SJeff Mahoney fs_info = to_fs_info(kobj); 194ba631941SJeff Mahoney if (!fs_info) 195ba631941SJeff Mahoney return -EPERM; 196ba631941SJeff Mahoney 197bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 198ee611138SDavid Sterba return -EROFS; 199ee611138SDavid Sterba 200ba631941SJeff Mahoney ret = kstrtoul(skip_spaces(buf), 0, &val); 201ba631941SJeff Mahoney if (ret) 202ba631941SJeff Mahoney return ret; 203ba631941SJeff Mahoney 204ba631941SJeff Mahoney if (fa->feature_set == FEAT_COMPAT) { 205ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 206ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 207ba631941SJeff Mahoney } else if (fa->feature_set == FEAT_COMPAT_RO) { 208ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 209ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 210ba631941SJeff Mahoney } else { 211ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 212ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 213ba631941SJeff Mahoney } 214ba631941SJeff Mahoney 215ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 216ba631941SJeff Mahoney 217ba631941SJeff Mahoney /* Nothing to do */ 218ba631941SJeff Mahoney if ((val && (features & fa->feature_bit)) || 219ba631941SJeff Mahoney (!val && !(features & fa->feature_bit))) 220ba631941SJeff Mahoney return count; 221ba631941SJeff Mahoney 222ba631941SJeff Mahoney if ((val && !(set & fa->feature_bit)) || 223ba631941SJeff Mahoney (!val && !(clear & fa->feature_bit))) { 224ba631941SJeff Mahoney btrfs_info(fs_info, 225ba631941SJeff Mahoney "%sabling feature %s on mounted fs is not supported.", 226ba631941SJeff Mahoney val ? "En" : "Dis", fa->kobj_attr.attr.name); 227ba631941SJeff Mahoney return -EPERM; 228ba631941SJeff Mahoney } 229ba631941SJeff Mahoney 230ba631941SJeff Mahoney btrfs_info(fs_info, "%s %s feature flag", 231ba631941SJeff Mahoney val ? "Setting" : "Clearing", fa->kobj_attr.attr.name); 232ba631941SJeff Mahoney 233ba631941SJeff Mahoney spin_lock(&fs_info->super_lock); 234ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 235ba631941SJeff Mahoney if (val) 236ba631941SJeff Mahoney features |= fa->feature_bit; 237ba631941SJeff Mahoney else 238ba631941SJeff Mahoney features &= ~fa->feature_bit; 239ba631941SJeff Mahoney set_features(fs_info, fa->feature_set, features); 240ba631941SJeff Mahoney spin_unlock(&fs_info->super_lock); 241ba631941SJeff Mahoney 2420eae2747SDavid Sterba /* 2430eae2747SDavid Sterba * We don't want to do full transaction commit from inside sysfs 2440eae2747SDavid Sterba */ 2450eae2747SDavid Sterba btrfs_set_pending(fs_info, COMMIT); 2460eae2747SDavid Sterba wake_up_process(fs_info->transaction_kthread); 247ba631941SJeff Mahoney 248ba631941SJeff Mahoney return count; 249ba631941SJeff Mahoney } 250ba631941SJeff Mahoney 251510d7360SJeff Mahoney static umode_t btrfs_feature_visible(struct kobject *kobj, 252510d7360SJeff Mahoney struct attribute *attr, int unused) 253510d7360SJeff Mahoney { 254510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 255510d7360SJeff Mahoney umode_t mode = attr->mode; 256510d7360SJeff Mahoney 257510d7360SJeff Mahoney if (fs_info) { 258510d7360SJeff Mahoney struct btrfs_feature_attr *fa; 259510d7360SJeff Mahoney u64 features; 260510d7360SJeff Mahoney 261510d7360SJeff Mahoney fa = attr_to_btrfs_feature_attr(attr); 262510d7360SJeff Mahoney features = get_features(fs_info, fa->feature_set); 263510d7360SJeff Mahoney 264ba631941SJeff Mahoney if (can_modify_feature(fa)) 265ba631941SJeff Mahoney mode |= S_IWUSR; 266ba631941SJeff Mahoney else if (!(features & fa->feature_bit)) 267510d7360SJeff Mahoney mode = 0; 268510d7360SJeff Mahoney } 269510d7360SJeff Mahoney 270510d7360SJeff Mahoney return mode; 271079b72bcSJeff Mahoney } 272079b72bcSJeff Mahoney 273079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_backref, MIXED_BACKREF); 274079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL); 275079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS); 276079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO); 2775c1aab1dSNick Terrell BTRFS_FEAT_ATTR_INCOMPAT(compress_zstd, COMPRESS_ZSTD); 278079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(big_metadata, BIG_METADATA); 279079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF); 280079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56); 281079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA); 282c736c095SDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES); 28356f20f40SNikolay Borisov BTRFS_FEAT_ATTR_INCOMPAT(metadata_uuid, METADATA_UUID); 2843b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE); 285cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(raid1c34, RAID1C34); 2867b3d5a90SNaohiro Aota #ifdef CONFIG_BTRFS_DEBUG 2872c7d2a23SJosef Bacik /* Remove once support for zoned allocation is feature complete */ 2887b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_INCOMPAT(zoned, ZONED); 2892c7d2a23SJosef Bacik /* Remove once support for extent tree v2 is feature complete */ 2902c7d2a23SJosef Bacik BTRFS_FEAT_ATTR_INCOMPAT(extent_tree_v2, EXTENT_TREE_V2); 2917b3d5a90SNaohiro Aota #endif 29214605409SBoris Burkov #ifdef CONFIG_FS_VERITY 29314605409SBoris Burkov BTRFS_FEAT_ATTR_COMPAT_RO(verity, VERITY); 29414605409SBoris Burkov #endif 295079b72bcSJeff Mahoney 296e7849e33SAnand Jain /* 297e7849e33SAnand Jain * Features which depend on feature bits and may differ between each fs. 298e7849e33SAnand Jain * 299e7849e33SAnand Jain * /sys/fs/btrfs/features - all available features implemeted by this version 300e7849e33SAnand Jain * /sys/fs/btrfs/UUID/features - features of the fs which are enabled or 301e7849e33SAnand Jain * can be changed on a mounted filesystem. 302e7849e33SAnand Jain */ 303079b72bcSJeff Mahoney static struct attribute *btrfs_supported_feature_attrs[] = { 304079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_backref), 305079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(default_subvol), 306079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_groups), 307079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(compress_lzo), 3085c1aab1dSNick Terrell BTRFS_FEAT_ATTR_PTR(compress_zstd), 309079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(big_metadata), 310079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(extended_iref), 311079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(raid56), 312079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(skinny_metadata), 313c736c095SDavid Sterba BTRFS_FEAT_ATTR_PTR(no_holes), 31456f20f40SNikolay Borisov BTRFS_FEAT_ATTR_PTR(metadata_uuid), 3153b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_PTR(free_space_tree), 316cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_PTR(raid1c34), 3177b3d5a90SNaohiro Aota #ifdef CONFIG_BTRFS_DEBUG 3187b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_PTR(zoned), 3192c7d2a23SJosef Bacik BTRFS_FEAT_ATTR_PTR(extent_tree_v2), 3207b3d5a90SNaohiro Aota #endif 32114605409SBoris Burkov #ifdef CONFIG_FS_VERITY 32214605409SBoris Burkov BTRFS_FEAT_ATTR_PTR(verity), 32314605409SBoris Burkov #endif 324079b72bcSJeff Mahoney NULL 325079b72bcSJeff Mahoney }; 326079b72bcSJeff Mahoney 327079b72bcSJeff Mahoney static const struct attribute_group btrfs_feature_attr_group = { 328079b72bcSJeff Mahoney .name = "features", 329510d7360SJeff Mahoney .is_visible = btrfs_feature_visible, 330079b72bcSJeff Mahoney .attrs = btrfs_supported_feature_attrs, 331079b72bcSJeff Mahoney }; 33258176a96SJosef Bacik 333f902bd3aSMisono Tomohiro static ssize_t rmdir_subvol_show(struct kobject *kobj, 334f902bd3aSMisono Tomohiro struct kobj_attribute *ka, char *buf) 335f902bd3aSMisono Tomohiro { 336020e5277SAnand Jain return sysfs_emit(buf, "0\n"); 337f902bd3aSMisono Tomohiro } 338f902bd3aSMisono Tomohiro BTRFS_ATTR(static_feature, rmdir_subvol, rmdir_subvol_show); 339f902bd3aSMisono Tomohiro 340f7cea56cSDavid Sterba static ssize_t supported_checksums_show(struct kobject *kobj, 341f7cea56cSDavid Sterba struct kobj_attribute *a, char *buf) 342f7cea56cSDavid Sterba { 343f7cea56cSDavid Sterba ssize_t ret = 0; 344f7cea56cSDavid Sterba int i; 345f7cea56cSDavid Sterba 346f7cea56cSDavid Sterba for (i = 0; i < btrfs_get_num_csums(); i++) { 347f7cea56cSDavid Sterba /* 348f7cea56cSDavid Sterba * This "trick" only works as long as 'enum btrfs_csum_type' has 349f7cea56cSDavid Sterba * no holes in it 350f7cea56cSDavid Sterba */ 351020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i == 0 ? "" : " "), 352020e5277SAnand Jain btrfs_super_csum_name(i)); 353f7cea56cSDavid Sterba 354f7cea56cSDavid Sterba } 355f7cea56cSDavid Sterba 356020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 357f7cea56cSDavid Sterba return ret; 358f7cea56cSDavid Sterba } 359f7cea56cSDavid Sterba BTRFS_ATTR(static_feature, supported_checksums, supported_checksums_show); 360f7cea56cSDavid Sterba 3617573df55SOmar Sandoval static ssize_t send_stream_version_show(struct kobject *kobj, 3627573df55SOmar Sandoval struct kobj_attribute *ka, char *buf) 3637573df55SOmar Sandoval { 364020e5277SAnand Jain return sysfs_emit(buf, "%d\n", BTRFS_SEND_STREAM_VERSION); 3657573df55SOmar Sandoval } 3667573df55SOmar Sandoval BTRFS_ATTR(static_feature, send_stream_version, send_stream_version_show); 3677573df55SOmar Sandoval 368ceafe3ccSJosef Bacik static const char *rescue_opts[] = { 369ceafe3ccSJosef Bacik "usebackuproot", 370ceafe3ccSJosef Bacik "nologreplay", 37142437a63SJosef Bacik "ignorebadroots", 372882dbe0cSJosef Bacik "ignoredatacsums", 3739037d3cbSJosef Bacik "all", 374ceafe3ccSJosef Bacik }; 375ceafe3ccSJosef Bacik 376ceafe3ccSJosef Bacik static ssize_t supported_rescue_options_show(struct kobject *kobj, 377ceafe3ccSJosef Bacik struct kobj_attribute *a, 378ceafe3ccSJosef Bacik char *buf) 379ceafe3ccSJosef Bacik { 380ceafe3ccSJosef Bacik ssize_t ret = 0; 381ceafe3ccSJosef Bacik int i; 382ceafe3ccSJosef Bacik 383ceafe3ccSJosef Bacik for (i = 0; i < ARRAY_SIZE(rescue_opts); i++) 384020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i ? " " : ""), rescue_opts[i]); 385020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 386ceafe3ccSJosef Bacik return ret; 387ceafe3ccSJosef Bacik } 388ceafe3ccSJosef Bacik BTRFS_ATTR(static_feature, supported_rescue_options, 389ceafe3ccSJosef Bacik supported_rescue_options_show); 390ceafe3ccSJosef Bacik 391fc57ad8dSQu Wenruo static ssize_t supported_sectorsizes_show(struct kobject *kobj, 392fc57ad8dSQu Wenruo struct kobj_attribute *a, 393fc57ad8dSQu Wenruo char *buf) 394fc57ad8dSQu Wenruo { 395fc57ad8dSQu Wenruo ssize_t ret = 0; 396fc57ad8dSQu Wenruo 39795ea0486SQu Wenruo /* 4K sector size is also supported with 64K page size */ 39895ea0486SQu Wenruo if (PAGE_SIZE == SZ_64K) 399020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%u ", SZ_4K); 40095ea0486SQu Wenruo 401fc57ad8dSQu Wenruo /* Only sectorsize == PAGE_SIZE is now supported */ 402020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%lu\n", PAGE_SIZE); 403fc57ad8dSQu Wenruo 404fc57ad8dSQu Wenruo return ret; 405fc57ad8dSQu Wenruo } 406fc57ad8dSQu Wenruo BTRFS_ATTR(static_feature, supported_sectorsizes, 407fc57ad8dSQu Wenruo supported_sectorsizes_show); 408fc57ad8dSQu Wenruo 409e7849e33SAnand Jain /* 410e7849e33SAnand Jain * Features which only depend on kernel version. 411e7849e33SAnand Jain * 412e7849e33SAnand Jain * These are listed in /sys/fs/btrfs/features along with 413e7849e33SAnand Jain * btrfs_supported_feature_attrs. 414e7849e33SAnand Jain */ 415f902bd3aSMisono Tomohiro static struct attribute *btrfs_supported_static_feature_attrs[] = { 416f902bd3aSMisono Tomohiro BTRFS_ATTR_PTR(static_feature, rmdir_subvol), 417f7cea56cSDavid Sterba BTRFS_ATTR_PTR(static_feature, supported_checksums), 4187573df55SOmar Sandoval BTRFS_ATTR_PTR(static_feature, send_stream_version), 419ceafe3ccSJosef Bacik BTRFS_ATTR_PTR(static_feature, supported_rescue_options), 420fc57ad8dSQu Wenruo BTRFS_ATTR_PTR(static_feature, supported_sectorsizes), 421f902bd3aSMisono Tomohiro NULL 422f902bd3aSMisono Tomohiro }; 423f902bd3aSMisono Tomohiro 424f902bd3aSMisono Tomohiro static const struct attribute_group btrfs_static_feature_attr_group = { 425f902bd3aSMisono Tomohiro .name = "features", 426f902bd3aSMisono Tomohiro .attrs = btrfs_supported_static_feature_attrs, 427f902bd3aSMisono Tomohiro }; 428f902bd3aSMisono Tomohiro 4296e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 4306e369febSDavid Sterba 4316e369febSDavid Sterba /* 432e4faab84SDennis Zhou * Discard statistics and tunables 433e4faab84SDennis Zhou */ 434dfb79ddbSDennis Zhou #define discard_to_fs_info(_kobj) to_fs_info((_kobj)->parent->parent) 435dfb79ddbSDennis Zhou 4365dc7c10bSDennis Zhou static ssize_t btrfs_discardable_bytes_show(struct kobject *kobj, 4375dc7c10bSDennis Zhou struct kobj_attribute *a, 4385dc7c10bSDennis Zhou char *buf) 4395dc7c10bSDennis Zhou { 4405dc7c10bSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4415dc7c10bSDennis Zhou 442020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4435dc7c10bSDennis Zhou atomic64_read(&fs_info->discard_ctl.discardable_bytes)); 4445dc7c10bSDennis Zhou } 4455dc7c10bSDennis Zhou BTRFS_ATTR(discard, discardable_bytes, btrfs_discardable_bytes_show); 4465dc7c10bSDennis Zhou 447dfb79ddbSDennis Zhou static ssize_t btrfs_discardable_extents_show(struct kobject *kobj, 448dfb79ddbSDennis Zhou struct kobj_attribute *a, 449dfb79ddbSDennis Zhou char *buf) 450dfb79ddbSDennis Zhou { 451dfb79ddbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 452dfb79ddbSDennis Zhou 453020e5277SAnand Jain return sysfs_emit(buf, "%d\n", 454dfb79ddbSDennis Zhou atomic_read(&fs_info->discard_ctl.discardable_extents)); 455dfb79ddbSDennis Zhou } 456dfb79ddbSDennis Zhou BTRFS_ATTR(discard, discardable_extents, btrfs_discardable_extents_show); 457dfb79ddbSDennis Zhou 4589ddf648fSDennis Zhou static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj, 4599ddf648fSDennis Zhou struct kobj_attribute *a, 4609ddf648fSDennis Zhou char *buf) 4619ddf648fSDennis Zhou { 4629ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4639ddf648fSDennis Zhou 464020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4659ddf648fSDennis Zhou fs_info->discard_ctl.discard_bitmap_bytes); 4669ddf648fSDennis Zhou } 4679ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bitmap_bytes, btrfs_discard_bitmap_bytes_show); 4689ddf648fSDennis Zhou 4699ddf648fSDennis Zhou static ssize_t btrfs_discard_bytes_saved_show(struct kobject *kobj, 4709ddf648fSDennis Zhou struct kobj_attribute *a, 4719ddf648fSDennis Zhou char *buf) 4729ddf648fSDennis Zhou { 4739ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4749ddf648fSDennis Zhou 475020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4769ddf648fSDennis Zhou atomic64_read(&fs_info->discard_ctl.discard_bytes_saved)); 4779ddf648fSDennis Zhou } 4789ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bytes_saved, btrfs_discard_bytes_saved_show); 4799ddf648fSDennis Zhou 4809ddf648fSDennis Zhou static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj, 4819ddf648fSDennis Zhou struct kobj_attribute *a, 4829ddf648fSDennis Zhou char *buf) 4839ddf648fSDennis Zhou { 4849ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4859ddf648fSDennis Zhou 486020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4879ddf648fSDennis Zhou fs_info->discard_ctl.discard_extent_bytes); 4889ddf648fSDennis Zhou } 4899ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_extent_bytes, btrfs_discard_extent_bytes_show); 4909ddf648fSDennis Zhou 491a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_show(struct kobject *kobj, 492a2309300SDennis Zhou struct kobj_attribute *a, 493a2309300SDennis Zhou char *buf) 494a2309300SDennis Zhou { 495a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 496a2309300SDennis Zhou 497020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 498a2309300SDennis Zhou READ_ONCE(fs_info->discard_ctl.iops_limit)); 499a2309300SDennis Zhou } 500a2309300SDennis Zhou 501a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_store(struct kobject *kobj, 502a2309300SDennis Zhou struct kobj_attribute *a, 503a2309300SDennis Zhou const char *buf, size_t len) 504a2309300SDennis Zhou { 505a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 506a2309300SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 507a2309300SDennis Zhou u32 iops_limit; 508a2309300SDennis Zhou int ret; 509a2309300SDennis Zhou 510a2309300SDennis Zhou ret = kstrtou32(buf, 10, &iops_limit); 511a2309300SDennis Zhou if (ret) 512a2309300SDennis Zhou return -EINVAL; 513a2309300SDennis Zhou 514a2309300SDennis Zhou WRITE_ONCE(discard_ctl->iops_limit, iops_limit); 5153e48d8d2SPavel Begunkov btrfs_discard_calc_delay(discard_ctl); 5163e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 517a2309300SDennis Zhou return len; 518a2309300SDennis Zhou } 519a2309300SDennis Zhou BTRFS_ATTR_RW(discard, iops_limit, btrfs_discard_iops_limit_show, 520a2309300SDennis Zhou btrfs_discard_iops_limit_store); 521a2309300SDennis Zhou 522e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_show(struct kobject *kobj, 523e93591bbSDennis Zhou struct kobj_attribute *a, 524e93591bbSDennis Zhou char *buf) 525e93591bbSDennis Zhou { 526e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 527e93591bbSDennis Zhou 528020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 529e93591bbSDennis Zhou READ_ONCE(fs_info->discard_ctl.kbps_limit)); 530e93591bbSDennis Zhou } 531e93591bbSDennis Zhou 532e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_store(struct kobject *kobj, 533e93591bbSDennis Zhou struct kobj_attribute *a, 534e93591bbSDennis Zhou const char *buf, size_t len) 535e93591bbSDennis Zhou { 536e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 537e93591bbSDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 538e93591bbSDennis Zhou u32 kbps_limit; 539e93591bbSDennis Zhou int ret; 540e93591bbSDennis Zhou 541e93591bbSDennis Zhou ret = kstrtou32(buf, 10, &kbps_limit); 542e93591bbSDennis Zhou if (ret) 543e93591bbSDennis Zhou return -EINVAL; 544e93591bbSDennis Zhou 545e93591bbSDennis Zhou WRITE_ONCE(discard_ctl->kbps_limit, kbps_limit); 5463e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 547e93591bbSDennis Zhou return len; 548e93591bbSDennis Zhou } 549e93591bbSDennis Zhou BTRFS_ATTR_RW(discard, kbps_limit, btrfs_discard_kbps_limit_show, 550e93591bbSDennis Zhou btrfs_discard_kbps_limit_store); 551e93591bbSDennis Zhou 55219b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_show(struct kobject *kobj, 55319b2a2c7SDennis Zhou struct kobj_attribute *a, 55419b2a2c7SDennis Zhou char *buf) 55519b2a2c7SDennis Zhou { 55619b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 55719b2a2c7SDennis Zhou 558020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 55919b2a2c7SDennis Zhou READ_ONCE(fs_info->discard_ctl.max_discard_size)); 56019b2a2c7SDennis Zhou } 56119b2a2c7SDennis Zhou 56219b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_store(struct kobject *kobj, 56319b2a2c7SDennis Zhou struct kobj_attribute *a, 56419b2a2c7SDennis Zhou const char *buf, size_t len) 56519b2a2c7SDennis Zhou { 56619b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 56719b2a2c7SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 56819b2a2c7SDennis Zhou u64 max_discard_size; 56919b2a2c7SDennis Zhou int ret; 57019b2a2c7SDennis Zhou 57119b2a2c7SDennis Zhou ret = kstrtou64(buf, 10, &max_discard_size); 57219b2a2c7SDennis Zhou if (ret) 57319b2a2c7SDennis Zhou return -EINVAL; 57419b2a2c7SDennis Zhou 57519b2a2c7SDennis Zhou WRITE_ONCE(discard_ctl->max_discard_size, max_discard_size); 57619b2a2c7SDennis Zhou 57719b2a2c7SDennis Zhou return len; 57819b2a2c7SDennis Zhou } 57919b2a2c7SDennis Zhou BTRFS_ATTR_RW(discard, max_discard_size, btrfs_discard_max_discard_size_show, 58019b2a2c7SDennis Zhou btrfs_discard_max_discard_size_store); 58119b2a2c7SDennis Zhou 582e7849e33SAnand Jain /* 583e7849e33SAnand Jain * Per-filesystem debugging of discard (when mounted with discard=async). 584e7849e33SAnand Jain * 585e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/debug/discard/ 586e7849e33SAnand Jain */ 587e4faab84SDennis Zhou static const struct attribute *discard_debug_attrs[] = { 5885dc7c10bSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_bytes), 589dfb79ddbSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_extents), 5909ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bitmap_bytes), 5919ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bytes_saved), 5929ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_extent_bytes), 593a2309300SDennis Zhou BTRFS_ATTR_PTR(discard, iops_limit), 594e93591bbSDennis Zhou BTRFS_ATTR_PTR(discard, kbps_limit), 59519b2a2c7SDennis Zhou BTRFS_ATTR_PTR(discard, max_discard_size), 596e4faab84SDennis Zhou NULL, 597e4faab84SDennis Zhou }; 598e4faab84SDennis Zhou 599e4faab84SDennis Zhou /* 600e7849e33SAnand Jain * Per-filesystem runtime debugging exported via sysfs. 6016e369febSDavid Sterba * 602e7849e33SAnand Jain * Path: /sys/fs/btrfs/UUID/debug/ 6036e369febSDavid Sterba */ 60493945cb4SDennis Zhou static const struct attribute *btrfs_debug_mount_attrs[] = { 60593945cb4SDennis Zhou NULL, 60693945cb4SDennis Zhou }; 60793945cb4SDennis Zhou 608e7849e33SAnand Jain /* 609e7849e33SAnand Jain * Runtime debugging exported via sysfs, applies to all mounted filesystems. 610e7849e33SAnand Jain * 611e7849e33SAnand Jain * Path: /sys/fs/btrfs/debug 612e7849e33SAnand Jain */ 6136e369febSDavid Sterba static struct attribute *btrfs_debug_feature_attrs[] = { 6146e369febSDavid Sterba NULL 6156e369febSDavid Sterba }; 6166e369febSDavid Sterba 6176e369febSDavid Sterba static const struct attribute_group btrfs_debug_feature_attr_group = { 6186e369febSDavid Sterba .name = "debug", 6196e369febSDavid Sterba .attrs = btrfs_debug_feature_attrs, 6206e369febSDavid Sterba }; 6216e369febSDavid Sterba 6226e369febSDavid Sterba #endif 6236e369febSDavid Sterba 6246ab0a202SJeff Mahoney static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf) 6256ab0a202SJeff Mahoney { 6266ab0a202SJeff Mahoney u64 val; 6276ab0a202SJeff Mahoney if (lock) 6286ab0a202SJeff Mahoney spin_lock(lock); 6296ab0a202SJeff Mahoney val = *value_ptr; 6306ab0a202SJeff Mahoney if (lock) 6316ab0a202SJeff Mahoney spin_unlock(lock); 632020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6336ab0a202SJeff Mahoney } 6346ab0a202SJeff Mahoney 6356ab0a202SJeff Mahoney static ssize_t global_rsv_size_show(struct kobject *kobj, 6366ab0a202SJeff Mahoney struct kobj_attribute *ka, char *buf) 6376ab0a202SJeff Mahoney { 6386ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6396ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6406ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf); 6416ab0a202SJeff Mahoney } 642a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_size, global_rsv_size_show); 6436ab0a202SJeff Mahoney 6446ab0a202SJeff Mahoney static ssize_t global_rsv_reserved_show(struct kobject *kobj, 6456ab0a202SJeff Mahoney struct kobj_attribute *a, char *buf) 6466ab0a202SJeff Mahoney { 6476ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6486ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6496ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf); 6506ab0a202SJeff Mahoney } 651a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_reserved, global_rsv_reserved_show); 6526ab0a202SJeff Mahoney 6536ab0a202SJeff Mahoney #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj) 654c1895442SJeff Mahoney #define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj) 6556ab0a202SJeff Mahoney 6566ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6576ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf); 658a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, total_bytes, raid_bytes_show); 659a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, used_bytes, raid_bytes_show); 6606ab0a202SJeff Mahoney 6616ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6626ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf) 6636ab0a202SJeff Mahoney 6646ab0a202SJeff Mahoney { 6656ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj->parent); 66632da5386SDavid Sterba struct btrfs_block_group *block_group; 66775cb379dSJeff Mahoney int index = btrfs_bg_flags_to_raid_index(to_raid_kobj(kobj)->flags); 6686ab0a202SJeff Mahoney u64 val = 0; 6696ab0a202SJeff Mahoney 6706ab0a202SJeff Mahoney down_read(&sinfo->groups_sem); 6716ab0a202SJeff Mahoney list_for_each_entry(block_group, &sinfo->block_groups[index], list) { 672a969f4ccSHans van Kranenburg if (&attr->attr == BTRFS_ATTR_PTR(raid, total_bytes)) 673b3470b5dSDavid Sterba val += block_group->length; 6746ab0a202SJeff Mahoney else 675bf38be65SDavid Sterba val += block_group->used; 6766ab0a202SJeff Mahoney } 6776ab0a202SJeff Mahoney up_read(&sinfo->groups_sem); 678020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6796ab0a202SJeff Mahoney } 6806ab0a202SJeff Mahoney 681e7849e33SAnand Jain /* 682e7849e33SAnand Jain * Allocation information about block group profiles. 683e7849e33SAnand Jain * 684e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/<bg-profile>/ 685e7849e33SAnand Jain */ 6867c7e3014SKimberly Brown static struct attribute *raid_attrs[] = { 687a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, total_bytes), 688a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, used_bytes), 6896ab0a202SJeff Mahoney NULL 6906ab0a202SJeff Mahoney }; 6917c7e3014SKimberly Brown ATTRIBUTE_GROUPS(raid); 6926ab0a202SJeff Mahoney 6936ab0a202SJeff Mahoney static void release_raid_kobj(struct kobject *kobj) 6946ab0a202SJeff Mahoney { 695c1895442SJeff Mahoney kfree(to_raid_kobj(kobj)); 6966ab0a202SJeff Mahoney } 6976ab0a202SJeff Mahoney 698536ea45cSDavid Sterba static struct kobj_type btrfs_raid_ktype = { 6996ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 7006ab0a202SJeff Mahoney .release = release_raid_kobj, 7017c7e3014SKimberly Brown .default_groups = raid_groups, 7026ab0a202SJeff Mahoney }; 7036ab0a202SJeff Mahoney 7046ab0a202SJeff Mahoney #define SPACE_INFO_ATTR(field) \ 7056ab0a202SJeff Mahoney static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \ 7066ab0a202SJeff Mahoney struct kobj_attribute *a, \ 7076ab0a202SJeff Mahoney char *buf) \ 7086ab0a202SJeff Mahoney { \ 7096ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); \ 7106ab0a202SJeff Mahoney return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \ 7116ab0a202SJeff Mahoney } \ 712a969f4ccSHans van Kranenburg BTRFS_ATTR(space_info, field, btrfs_space_info_show_##field) 7136ab0a202SJeff Mahoney 7146ab0a202SJeff Mahoney SPACE_INFO_ATTR(flags); 7156ab0a202SJeff Mahoney SPACE_INFO_ATTR(total_bytes); 7166ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_used); 7176ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_pinned); 7186ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_reserved); 7196ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_may_use); 720c1fd5c30SWang Xiaoguang SPACE_INFO_ATTR(bytes_readonly); 721169e0da9SNaohiro Aota SPACE_INFO_ATTR(bytes_zone_unusable); 7226ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_used); 7236ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_total); 7246ab0a202SJeff Mahoney 725e7849e33SAnand Jain /* 726e7849e33SAnand Jain * Allocation information about block group types. 727e7849e33SAnand Jain * 728e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/ 729e7849e33SAnand Jain */ 7306ab0a202SJeff Mahoney static struct attribute *space_info_attrs[] = { 731a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, flags), 732a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, total_bytes), 733a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_used), 734a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_pinned), 735a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_reserved), 736a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_may_use), 737a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_readonly), 738169e0da9SNaohiro Aota BTRFS_ATTR_PTR(space_info, bytes_zone_unusable), 739a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_used), 740a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_total), 7416ab0a202SJeff Mahoney NULL, 7426ab0a202SJeff Mahoney }; 7437c7e3014SKimberly Brown ATTRIBUTE_GROUPS(space_info); 7446ab0a202SJeff Mahoney 7456ab0a202SJeff Mahoney static void space_info_release(struct kobject *kobj) 7466ab0a202SJeff Mahoney { 7476ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); 7486ab0a202SJeff Mahoney kfree(sinfo); 7496ab0a202SJeff Mahoney } 7506ab0a202SJeff Mahoney 75127992d01SDavid Sterba static struct kobj_type space_info_ktype = { 7526ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 7536ab0a202SJeff Mahoney .release = space_info_release, 7547c7e3014SKimberly Brown .default_groups = space_info_groups, 7556ab0a202SJeff Mahoney }; 7566ab0a202SJeff Mahoney 757e7849e33SAnand Jain /* 758e7849e33SAnand Jain * Allocation information about block groups. 759e7849e33SAnand Jain * 760e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/ 761e7849e33SAnand Jain */ 7626ab0a202SJeff Mahoney static const struct attribute *allocation_attrs[] = { 763a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_reserved), 764a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_size), 7656ab0a202SJeff Mahoney NULL, 7666ab0a202SJeff Mahoney }; 7676ab0a202SJeff Mahoney 768f8ba9c11SJeff Mahoney static ssize_t btrfs_label_show(struct kobject *kobj, 769f8ba9c11SJeff Mahoney struct kobj_attribute *a, char *buf) 770f8ba9c11SJeff Mahoney { 771f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 77248fcc3ffSSatoru Takeuchi char *label = fs_info->super_copy->label; 773ee17fc80SDavid Sterba ssize_t ret; 774ee17fc80SDavid Sterba 775ee17fc80SDavid Sterba spin_lock(&fs_info->super_lock); 776020e5277SAnand Jain ret = sysfs_emit(buf, label[0] ? "%s\n" : "%s", label); 777ee17fc80SDavid Sterba spin_unlock(&fs_info->super_lock); 778ee17fc80SDavid Sterba 779ee17fc80SDavid Sterba return ret; 780f8ba9c11SJeff Mahoney } 781f8ba9c11SJeff Mahoney 782f8ba9c11SJeff Mahoney static ssize_t btrfs_label_store(struct kobject *kobj, 783f8ba9c11SJeff Mahoney struct kobj_attribute *a, 784f8ba9c11SJeff Mahoney const char *buf, size_t len) 785f8ba9c11SJeff Mahoney { 786f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 78748fcc3ffSSatoru Takeuchi size_t p_len; 788f8ba9c11SJeff Mahoney 78966ac9fe7SDavid Sterba if (!fs_info) 79066ac9fe7SDavid Sterba return -EPERM; 79166ac9fe7SDavid Sterba 792bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 79379aec2b8SAnand Jain return -EROFS; 79479aec2b8SAnand Jain 79548fcc3ffSSatoru Takeuchi /* 79648fcc3ffSSatoru Takeuchi * p_len is the len until the first occurrence of either 79748fcc3ffSSatoru Takeuchi * '\n' or '\0' 79848fcc3ffSSatoru Takeuchi */ 79948fcc3ffSSatoru Takeuchi p_len = strcspn(buf, "\n"); 80048fcc3ffSSatoru Takeuchi 80148fcc3ffSSatoru Takeuchi if (p_len >= BTRFS_LABEL_SIZE) 802f8ba9c11SJeff Mahoney return -EINVAL; 803f8ba9c11SJeff Mahoney 804a6f69dc8SDavid Sterba spin_lock(&fs_info->super_lock); 80548fcc3ffSSatoru Takeuchi memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE); 80648fcc3ffSSatoru Takeuchi memcpy(fs_info->super_copy->label, buf, p_len); 807a6f69dc8SDavid Sterba spin_unlock(&fs_info->super_lock); 808f8ba9c11SJeff Mahoney 809a6f69dc8SDavid Sterba /* 810a6f69dc8SDavid Sterba * We don't want to do full transaction commit from inside sysfs 811a6f69dc8SDavid Sterba */ 812a6f69dc8SDavid Sterba btrfs_set_pending(fs_info, COMMIT); 813a6f69dc8SDavid Sterba wake_up_process(fs_info->transaction_kthread); 814a6f69dc8SDavid Sterba 815f8ba9c11SJeff Mahoney return len; 816f8ba9c11SJeff Mahoney } 817a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, label, btrfs_label_show, btrfs_label_store); 818f8ba9c11SJeff Mahoney 819df93589aSDavid Sterba static ssize_t btrfs_nodesize_show(struct kobject *kobj, 820df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 821df93589aSDavid Sterba { 822df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 823df93589aSDavid Sterba 824020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->nodesize); 825df93589aSDavid Sterba } 826df93589aSDavid Sterba 827a969f4ccSHans van Kranenburg BTRFS_ATTR(, nodesize, btrfs_nodesize_show); 828df93589aSDavid Sterba 829df93589aSDavid Sterba static ssize_t btrfs_sectorsize_show(struct kobject *kobj, 830df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 831df93589aSDavid Sterba { 832df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 833df93589aSDavid Sterba 834020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 835df93589aSDavid Sterba } 836df93589aSDavid Sterba 837a969f4ccSHans van Kranenburg BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show); 838df93589aSDavid Sterba 839df93589aSDavid Sterba static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, 840df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 841df93589aSDavid Sterba { 842df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 843df93589aSDavid Sterba 844020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 845df93589aSDavid Sterba } 846df93589aSDavid Sterba 847a969f4ccSHans van Kranenburg BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show); 848df93589aSDavid Sterba 8492723480aSSargun Dhillon static ssize_t quota_override_show(struct kobject *kobj, 8502723480aSSargun Dhillon struct kobj_attribute *a, char *buf) 8512723480aSSargun Dhillon { 8522723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 8532723480aSSargun Dhillon int quota_override; 8542723480aSSargun Dhillon 8552723480aSSargun Dhillon quota_override = test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 856020e5277SAnand Jain return sysfs_emit(buf, "%d\n", quota_override); 8572723480aSSargun Dhillon } 8582723480aSSargun Dhillon 8592723480aSSargun Dhillon static ssize_t quota_override_store(struct kobject *kobj, 8602723480aSSargun Dhillon struct kobj_attribute *a, 8612723480aSSargun Dhillon const char *buf, size_t len) 8622723480aSSargun Dhillon { 8632723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 8642723480aSSargun Dhillon unsigned long knob; 8652723480aSSargun Dhillon int err; 8662723480aSSargun Dhillon 8672723480aSSargun Dhillon if (!fs_info) 8682723480aSSargun Dhillon return -EPERM; 8692723480aSSargun Dhillon 8702723480aSSargun Dhillon if (!capable(CAP_SYS_RESOURCE)) 8712723480aSSargun Dhillon return -EPERM; 8722723480aSSargun Dhillon 8732723480aSSargun Dhillon err = kstrtoul(buf, 10, &knob); 8742723480aSSargun Dhillon if (err) 8752723480aSSargun Dhillon return err; 8762723480aSSargun Dhillon if (knob > 1) 8772723480aSSargun Dhillon return -EINVAL; 8782723480aSSargun Dhillon 8792723480aSSargun Dhillon if (knob) 8802723480aSSargun Dhillon set_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 8812723480aSSargun Dhillon else 8822723480aSSargun Dhillon clear_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 8832723480aSSargun Dhillon 8842723480aSSargun Dhillon return len; 8852723480aSSargun Dhillon } 8862723480aSSargun Dhillon 887a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, quota_override, quota_override_show, quota_override_store); 8882723480aSSargun Dhillon 88956f20f40SNikolay Borisov static ssize_t btrfs_metadata_uuid_show(struct kobject *kobj, 89056f20f40SNikolay Borisov struct kobj_attribute *a, char *buf) 89156f20f40SNikolay Borisov { 89256f20f40SNikolay Borisov struct btrfs_fs_info *fs_info = to_fs_info(kobj); 89356f20f40SNikolay Borisov 894020e5277SAnand Jain return sysfs_emit(buf, "%pU\n", fs_info->fs_devices->metadata_uuid); 89556f20f40SNikolay Borisov } 89656f20f40SNikolay Borisov 89756f20f40SNikolay Borisov BTRFS_ATTR(, metadata_uuid, btrfs_metadata_uuid_show); 89856f20f40SNikolay Borisov 89941e6d2a8SJohannes Thumshirn static ssize_t btrfs_checksum_show(struct kobject *kobj, 90041e6d2a8SJohannes Thumshirn struct kobj_attribute *a, char *buf) 90141e6d2a8SJohannes Thumshirn { 90241e6d2a8SJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 90341e6d2a8SJohannes Thumshirn u16 csum_type = btrfs_super_csum_type(fs_info->super_copy); 90441e6d2a8SJohannes Thumshirn 905020e5277SAnand Jain return sysfs_emit(buf, "%s (%s)\n", 90641e6d2a8SJohannes Thumshirn btrfs_super_csum_name(csum_type), 90741e6d2a8SJohannes Thumshirn crypto_shash_driver_name(fs_info->csum_shash)); 90841e6d2a8SJohannes Thumshirn } 90941e6d2a8SJohannes Thumshirn 91041e6d2a8SJohannes Thumshirn BTRFS_ATTR(, checksum, btrfs_checksum_show); 91141e6d2a8SJohannes Thumshirn 91266a2823cSGoldwyn Rodrigues static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj, 91366a2823cSGoldwyn Rodrigues struct kobj_attribute *a, char *buf) 91466a2823cSGoldwyn Rodrigues { 91566a2823cSGoldwyn Rodrigues struct btrfs_fs_info *fs_info = to_fs_info(kobj); 91666a2823cSGoldwyn Rodrigues const char *str; 91766a2823cSGoldwyn Rodrigues 91866a2823cSGoldwyn Rodrigues switch (READ_ONCE(fs_info->exclusive_operation)) { 91966a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_NONE: 92066a2823cSGoldwyn Rodrigues str = "none\n"; 92166a2823cSGoldwyn Rodrigues break; 92266a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_BALANCE: 92366a2823cSGoldwyn Rodrigues str = "balance\n"; 92466a2823cSGoldwyn Rodrigues break; 925*3e1ad196SDavid Sterba case BTRFS_EXCLOP_BALANCE_PAUSED: 926*3e1ad196SDavid Sterba str = "balance paused\n"; 927*3e1ad196SDavid Sterba break; 92866a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_ADD: 92966a2823cSGoldwyn Rodrigues str = "device add\n"; 93066a2823cSGoldwyn Rodrigues break; 93166a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REMOVE: 93266a2823cSGoldwyn Rodrigues str = "device remove\n"; 93366a2823cSGoldwyn Rodrigues break; 93466a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REPLACE: 93566a2823cSGoldwyn Rodrigues str = "device replace\n"; 93666a2823cSGoldwyn Rodrigues break; 93766a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_RESIZE: 93866a2823cSGoldwyn Rodrigues str = "resize\n"; 93966a2823cSGoldwyn Rodrigues break; 94066a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_SWAP_ACTIVATE: 94166a2823cSGoldwyn Rodrigues str = "swap activate\n"; 94266a2823cSGoldwyn Rodrigues break; 94366a2823cSGoldwyn Rodrigues default: 94466a2823cSGoldwyn Rodrigues str = "UNKNOWN\n"; 94566a2823cSGoldwyn Rodrigues break; 94666a2823cSGoldwyn Rodrigues } 947020e5277SAnand Jain return sysfs_emit(buf, "%s", str); 94866a2823cSGoldwyn Rodrigues } 94966a2823cSGoldwyn Rodrigues BTRFS_ATTR(, exclusive_operation, btrfs_exclusive_operation_show); 95066a2823cSGoldwyn Rodrigues 951089c8b05SAnand Jain static ssize_t btrfs_generation_show(struct kobject *kobj, 952089c8b05SAnand Jain struct kobj_attribute *a, char *buf) 953089c8b05SAnand Jain { 954089c8b05SAnand Jain struct btrfs_fs_info *fs_info = to_fs_info(kobj); 955089c8b05SAnand Jain 956020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", fs_info->generation); 957089c8b05SAnand Jain } 958089c8b05SAnand Jain BTRFS_ATTR(, generation, btrfs_generation_show); 959089c8b05SAnand Jain 960aaefed20SAnand Jain /* 961aaefed20SAnand Jain * Look for an exact string @string in @buffer with possible leading or 962aaefed20SAnand Jain * trailing whitespace 963aaefed20SAnand Jain */ 964aaefed20SAnand Jain static bool strmatch(const char *buffer, const char *string) 965aaefed20SAnand Jain { 966aaefed20SAnand Jain const size_t len = strlen(string); 967aaefed20SAnand Jain 968aaefed20SAnand Jain /* Skip leading whitespace */ 969aaefed20SAnand Jain buffer = skip_spaces(buffer); 970aaefed20SAnand Jain 971aaefed20SAnand Jain /* Match entire string, check if the rest is whitespace or empty */ 972aaefed20SAnand Jain if (strncmp(string, buffer, len) == 0 && 973aaefed20SAnand Jain strlen(skip_spaces(buffer + len)) == 0) 974aaefed20SAnand Jain return true; 975aaefed20SAnand Jain 976aaefed20SAnand Jain return false; 977aaefed20SAnand Jain } 978aaefed20SAnand Jain 9793d8cc17aSAnand Jain static const char * const btrfs_read_policy_name[] = { "pid" }; 9803d8cc17aSAnand Jain 9813d8cc17aSAnand Jain static ssize_t btrfs_read_policy_show(struct kobject *kobj, 9823d8cc17aSAnand Jain struct kobj_attribute *a, char *buf) 9833d8cc17aSAnand Jain { 9843d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 9853d8cc17aSAnand Jain ssize_t ret = 0; 9863d8cc17aSAnand Jain int i; 9873d8cc17aSAnand Jain 9883d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 9893d8cc17aSAnand Jain if (fs_devices->read_policy == i) 9903d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s[%s]", 9913d8cc17aSAnand Jain (ret == 0 ? "" : " "), 9923d8cc17aSAnand Jain btrfs_read_policy_name[i]); 9933d8cc17aSAnand Jain else 9943d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s", 9953d8cc17aSAnand Jain (ret == 0 ? "" : " "), 9963d8cc17aSAnand Jain btrfs_read_policy_name[i]); 9973d8cc17aSAnand Jain } 9983d8cc17aSAnand Jain 9993d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); 10003d8cc17aSAnand Jain 10013d8cc17aSAnand Jain return ret; 10023d8cc17aSAnand Jain } 10033d8cc17aSAnand Jain 10043d8cc17aSAnand Jain static ssize_t btrfs_read_policy_store(struct kobject *kobj, 10053d8cc17aSAnand Jain struct kobj_attribute *a, 10063d8cc17aSAnand Jain const char *buf, size_t len) 10073d8cc17aSAnand Jain { 10083d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 10093d8cc17aSAnand Jain int i; 10103d8cc17aSAnand Jain 10113d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 10123d8cc17aSAnand Jain if (strmatch(buf, btrfs_read_policy_name[i])) { 10133d8cc17aSAnand Jain if (i != fs_devices->read_policy) { 10143d8cc17aSAnand Jain fs_devices->read_policy = i; 10153d8cc17aSAnand Jain btrfs_info(fs_devices->fs_info, 10163d8cc17aSAnand Jain "read policy set to '%s'", 10173d8cc17aSAnand Jain btrfs_read_policy_name[i]); 10183d8cc17aSAnand Jain } 10193d8cc17aSAnand Jain return len; 10203d8cc17aSAnand Jain } 10213d8cc17aSAnand Jain } 10223d8cc17aSAnand Jain 10233d8cc17aSAnand Jain return -EINVAL; 10243d8cc17aSAnand Jain } 10253d8cc17aSAnand Jain BTRFS_ATTR_RW(, read_policy, btrfs_read_policy_show, btrfs_read_policy_store); 10263d8cc17aSAnand Jain 102718bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_show(struct kobject *kobj, 102818bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 102918bb8bbfSJohannes Thumshirn char *buf) 103018bb8bbfSJohannes Thumshirn { 103118bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 103218bb8bbfSJohannes Thumshirn ssize_t ret; 103318bb8bbfSJohannes Thumshirn 1034020e5277SAnand Jain ret = sysfs_emit(buf, "%d\n", READ_ONCE(fs_info->bg_reclaim_threshold)); 103518bb8bbfSJohannes Thumshirn 103618bb8bbfSJohannes Thumshirn return ret; 103718bb8bbfSJohannes Thumshirn } 103818bb8bbfSJohannes Thumshirn 103918bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_store(struct kobject *kobj, 104018bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 104118bb8bbfSJohannes Thumshirn const char *buf, size_t len) 104218bb8bbfSJohannes Thumshirn { 104318bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 104418bb8bbfSJohannes Thumshirn int thresh; 104518bb8bbfSJohannes Thumshirn int ret; 104618bb8bbfSJohannes Thumshirn 104718bb8bbfSJohannes Thumshirn ret = kstrtoint(buf, 10, &thresh); 104818bb8bbfSJohannes Thumshirn if (ret) 104918bb8bbfSJohannes Thumshirn return ret; 105018bb8bbfSJohannes Thumshirn 105177233c2dSJohannes Thumshirn if (thresh != 0 && (thresh <= 50 || thresh > 100)) 105218bb8bbfSJohannes Thumshirn return -EINVAL; 105318bb8bbfSJohannes Thumshirn 105477233c2dSJohannes Thumshirn WRITE_ONCE(fs_info->bg_reclaim_threshold, thresh); 105518bb8bbfSJohannes Thumshirn 105618bb8bbfSJohannes Thumshirn return len; 105718bb8bbfSJohannes Thumshirn } 105818bb8bbfSJohannes Thumshirn BTRFS_ATTR_RW(, bg_reclaim_threshold, btrfs_bg_reclaim_threshold_show, 105918bb8bbfSJohannes Thumshirn btrfs_bg_reclaim_threshold_store); 106018bb8bbfSJohannes Thumshirn 1061e7849e33SAnand Jain /* 1062e7849e33SAnand Jain * Per-filesystem information and stats. 1063e7849e33SAnand Jain * 1064e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/ 1065e7849e33SAnand Jain */ 10660dd2906fSAnand Jain static const struct attribute *btrfs_attrs[] = { 1067a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, label), 1068a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, nodesize), 1069a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, sectorsize), 1070a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, clone_alignment), 1071a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, quota_override), 107256f20f40SNikolay Borisov BTRFS_ATTR_PTR(, metadata_uuid), 107341e6d2a8SJohannes Thumshirn BTRFS_ATTR_PTR(, checksum), 107466a2823cSGoldwyn Rodrigues BTRFS_ATTR_PTR(, exclusive_operation), 1075089c8b05SAnand Jain BTRFS_ATTR_PTR(, generation), 10763d8cc17aSAnand Jain BTRFS_ATTR_PTR(, read_policy), 107718bb8bbfSJohannes Thumshirn BTRFS_ATTR_PTR(, bg_reclaim_threshold), 1078f8ba9c11SJeff Mahoney NULL, 1079f8ba9c11SJeff Mahoney }; 1080f8ba9c11SJeff Mahoney 1081c1b7e474SAnand Jain static void btrfs_release_fsid_kobj(struct kobject *kobj) 1082510d7360SJeff Mahoney { 10832e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj); 1084248d200dSAnand Jain 1085c1b7e474SAnand Jain memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject)); 10862e7910d6SAnand Jain complete(&fs_devs->kobj_unregister); 1087510d7360SJeff Mahoney } 1088510d7360SJeff Mahoney 1089510d7360SJeff Mahoney static struct kobj_type btrfs_ktype = { 1090510d7360SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 1091c1b7e474SAnand Jain .release = btrfs_release_fsid_kobj, 1092510d7360SJeff Mahoney }; 1093510d7360SJeff Mahoney 10942e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj) 10952e7910d6SAnand Jain { 10962e7910d6SAnand Jain if (kobj->ktype != &btrfs_ktype) 10972e7910d6SAnand Jain return NULL; 1098c1b7e474SAnand Jain return container_of(kobj, struct btrfs_fs_devices, fsid_kobj); 10992e7910d6SAnand Jain } 11002e7910d6SAnand Jain 1101510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj) 1102510d7360SJeff Mahoney { 1103510d7360SJeff Mahoney if (kobj->ktype != &btrfs_ktype) 1104510d7360SJeff Mahoney return NULL; 11052e7910d6SAnand Jain return to_fs_devs(kobj)->fs_info; 1106510d7360SJeff Mahoney } 110758176a96SJosef Bacik 1108e453d989SJeff Mahoney #define NUM_FEATURE_BITS 64 11096c52157fSTomohiro Misono #define BTRFS_FEATURE_NAME_MAX 13 11106c52157fSTomohiro Misono static char btrfs_unknown_feature_names[FEAT_MAX][NUM_FEATURE_BITS][BTRFS_FEATURE_NAME_MAX]; 11116c52157fSTomohiro Misono static struct btrfs_feature_attr btrfs_feature_attrs[FEAT_MAX][NUM_FEATURE_BITS]; 1112e453d989SJeff Mahoney 1113a55e65b8SDavid Sterba static_assert(ARRAY_SIZE(btrfs_unknown_feature_names) == 1114a55e65b8SDavid Sterba ARRAY_SIZE(btrfs_feature_attrs)); 1115a55e65b8SDavid Sterba static_assert(ARRAY_SIZE(btrfs_unknown_feature_names[0]) == 1116a55e65b8SDavid Sterba ARRAY_SIZE(btrfs_feature_attrs[0])); 1117a55e65b8SDavid Sterba 11186c52157fSTomohiro Misono static const u64 supported_feature_masks[FEAT_MAX] = { 1119e453d989SJeff Mahoney [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP, 1120e453d989SJeff Mahoney [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP, 1121e453d989SJeff Mahoney [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP, 1122e453d989SJeff Mahoney }; 1123e453d989SJeff Mahoney 1124e453d989SJeff Mahoney static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add) 11255ac1d209SJeff Mahoney { 1126e453d989SJeff Mahoney int set; 1127e453d989SJeff Mahoney 1128e453d989SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 1129e453d989SJeff Mahoney int i; 1130e453d989SJeff Mahoney struct attribute *attrs[2]; 1131e453d989SJeff Mahoney struct attribute_group agroup = { 1132e453d989SJeff Mahoney .name = "features", 1133e453d989SJeff Mahoney .attrs = attrs, 1134e453d989SJeff Mahoney }; 1135e453d989SJeff Mahoney u64 features = get_features(fs_info, set); 1136e453d989SJeff Mahoney features &= ~supported_feature_masks[set]; 1137e453d989SJeff Mahoney 1138e453d989SJeff Mahoney if (!features) 1139e453d989SJeff Mahoney continue; 1140e453d989SJeff Mahoney 1141e453d989SJeff Mahoney attrs[1] = NULL; 1142e453d989SJeff Mahoney for (i = 0; i < NUM_FEATURE_BITS; i++) { 1143e453d989SJeff Mahoney struct btrfs_feature_attr *fa; 1144e453d989SJeff Mahoney 1145e453d989SJeff Mahoney if (!(features & (1ULL << i))) 1146e453d989SJeff Mahoney continue; 1147e453d989SJeff Mahoney 1148e453d989SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 1149e453d989SJeff Mahoney attrs[0] = &fa->kobj_attr.attr; 1150e453d989SJeff Mahoney if (add) { 1151e453d989SJeff Mahoney int ret; 1152c1b7e474SAnand Jain ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj, 1153e453d989SJeff Mahoney &agroup); 1154e453d989SJeff Mahoney if (ret) 1155e453d989SJeff Mahoney return ret; 1156e453d989SJeff Mahoney } else 1157c1b7e474SAnand Jain sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj, 1158e453d989SJeff Mahoney &agroup); 1159e453d989SJeff Mahoney } 1160e453d989SJeff Mahoney 1161e453d989SJeff Mahoney } 1162e453d989SJeff Mahoney return 0; 1163e453d989SJeff Mahoney } 1164e453d989SJeff Mahoney 11652e3e1281SAnand Jain static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 1166e453d989SJeff Mahoney { 1167a013d141SAnand Jain if (fs_devs->devinfo_kobj) { 1168a013d141SAnand Jain kobject_del(fs_devs->devinfo_kobj); 1169a013d141SAnand Jain kobject_put(fs_devs->devinfo_kobj); 1170a013d141SAnand Jain fs_devs->devinfo_kobj = NULL; 1171a013d141SAnand Jain } 1172a013d141SAnand Jain 1173b5501504SAnand Jain if (fs_devs->devices_kobj) { 1174b5501504SAnand Jain kobject_del(fs_devs->devices_kobj); 1175b5501504SAnand Jain kobject_put(fs_devs->devices_kobj); 1176b5501504SAnand Jain fs_devs->devices_kobj = NULL; 1177aaf13305SAnand Jain } 1178aaf13305SAnand Jain 1179c1b7e474SAnand Jain if (fs_devs->fsid_kobj.state_initialized) { 1180c1b7e474SAnand Jain kobject_del(&fs_devs->fsid_kobj); 1181c1b7e474SAnand Jain kobject_put(&fs_devs->fsid_kobj); 11822e7910d6SAnand Jain wait_for_completion(&fs_devs->kobj_unregister); 11835ac1d209SJeff Mahoney } 1184f90fc547SAnand Jain } 11855ac1d209SJeff Mahoney 11862e3e1281SAnand Jain /* when fs_devs is NULL it will remove all fsid kobject */ 11871d1c1be3SAnand Jain void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 11882e3e1281SAnand Jain { 11892e3e1281SAnand Jain struct list_head *fs_uuids = btrfs_get_fs_uuids(); 11902e3e1281SAnand Jain 11912e3e1281SAnand Jain if (fs_devs) { 11922e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 11932e3e1281SAnand Jain return; 11942e3e1281SAnand Jain } 11952e3e1281SAnand Jain 1196c4babc5eSAnand Jain list_for_each_entry(fs_devs, fs_uuids, fs_list) { 11972e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 11982e3e1281SAnand Jain } 11992e3e1281SAnand Jain } 12002e3e1281SAnand Jain 120153f8a74cSAnand Jain static void btrfs_sysfs_remove_fs_devices(struct btrfs_fs_devices *fs_devices) 120253f8a74cSAnand Jain { 120353f8a74cSAnand Jain struct btrfs_device *device; 120430b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 120553f8a74cSAnand Jain 120653f8a74cSAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) 120753f8a74cSAnand Jain btrfs_sysfs_remove_device(device); 120830b0e4e0SAnand Jain 120930b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 121030b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) 121130b0e4e0SAnand Jain btrfs_sysfs_remove_device(device); 121230b0e4e0SAnand Jain } 121353f8a74cSAnand Jain } 121453f8a74cSAnand Jain 12156618a59bSAnand Jain void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info) 1216e453d989SJeff Mahoney { 12173092c68fSNikolay Borisov struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 12183092c68fSNikolay Borisov 12193092c68fSNikolay Borisov sysfs_remove_link(fsid_kobj, "bdi"); 12203092c68fSNikolay Borisov 1221e453d989SJeff Mahoney if (fs_info->space_info_kobj) { 1222e453d989SJeff Mahoney sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); 1223e453d989SJeff Mahoney kobject_del(fs_info->space_info_kobj); 1224e453d989SJeff Mahoney kobject_put(fs_info->space_info_kobj); 1225e453d989SJeff Mahoney } 122671e8978eSDennis Zhou #ifdef CONFIG_BTRFS_DEBUG 1227e4faab84SDennis Zhou if (fs_info->discard_debug_kobj) { 1228e4faab84SDennis Zhou sysfs_remove_files(fs_info->discard_debug_kobj, 1229e4faab84SDennis Zhou discard_debug_attrs); 1230e4faab84SDennis Zhou kobject_del(fs_info->discard_debug_kobj); 1231e4faab84SDennis Zhou kobject_put(fs_info->discard_debug_kobj); 1232e4faab84SDennis Zhou } 123393945cb4SDennis Zhou if (fs_info->debug_kobj) { 123493945cb4SDennis Zhou sysfs_remove_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 123593945cb4SDennis Zhou kobject_del(fs_info->debug_kobj); 123693945cb4SDennis Zhou kobject_put(fs_info->debug_kobj); 123793945cb4SDennis Zhou } 123871e8978eSDennis Zhou #endif 1239e453d989SJeff Mahoney addrm_unknown_feature_attrs(fs_info, false); 12403092c68fSNikolay Borisov sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 12413092c68fSNikolay Borisov sysfs_remove_files(fsid_kobj, btrfs_attrs); 124253f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_info->fs_devices); 1243e453d989SJeff Mahoney } 1244e453d989SJeff Mahoney 1245f10152bcSDavid Sterba static const char * const btrfs_feature_set_names[FEAT_MAX] = { 124679da4fa4SJeff Mahoney [FEAT_COMPAT] = "compat", 124779da4fa4SJeff Mahoney [FEAT_COMPAT_RO] = "compat_ro", 124879da4fa4SJeff Mahoney [FEAT_INCOMPAT] = "incompat", 124979da4fa4SJeff Mahoney }; 125079da4fa4SJeff Mahoney 12519e6df7ceSDavid Sterba const char *btrfs_feature_set_name(enum btrfs_feature_set set) 1252f10152bcSDavid Sterba { 1253f10152bcSDavid Sterba return btrfs_feature_set_names[set]; 1254f10152bcSDavid Sterba } 1255f10152bcSDavid Sterba 12563b02a68aSJeff Mahoney char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) 12573b02a68aSJeff Mahoney { 12583b02a68aSJeff Mahoney size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */ 12593b02a68aSJeff Mahoney int len = 0; 12603b02a68aSJeff Mahoney int i; 12613b02a68aSJeff Mahoney char *str; 12623b02a68aSJeff Mahoney 12633b02a68aSJeff Mahoney str = kmalloc(bufsize, GFP_KERNEL); 12643b02a68aSJeff Mahoney if (!str) 12653b02a68aSJeff Mahoney return str; 12663b02a68aSJeff Mahoney 12673b02a68aSJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 12683b02a68aSJeff Mahoney const char *name; 12693b02a68aSJeff Mahoney 12703b02a68aSJeff Mahoney if (!(flags & (1ULL << i))) 12713b02a68aSJeff Mahoney continue; 12723b02a68aSJeff Mahoney 12733b02a68aSJeff Mahoney name = btrfs_feature_attrs[set][i].kobj_attr.attr.name; 1274abdd9febSTakashi Iwai len += scnprintf(str + len, bufsize - len, "%s%s", 12753b02a68aSJeff Mahoney len ? "," : "", name); 12763b02a68aSJeff Mahoney } 12773b02a68aSJeff Mahoney 12783b02a68aSJeff Mahoney return str; 12793b02a68aSJeff Mahoney } 12803b02a68aSJeff Mahoney 128179da4fa4SJeff Mahoney static void init_feature_attrs(void) 128279da4fa4SJeff Mahoney { 128379da4fa4SJeff Mahoney struct btrfs_feature_attr *fa; 128479da4fa4SJeff Mahoney int set, i; 128579da4fa4SJeff Mahoney 12863b02a68aSJeff Mahoney memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs)); 12873b02a68aSJeff Mahoney memset(btrfs_unknown_feature_names, 0, 12883b02a68aSJeff Mahoney sizeof(btrfs_unknown_feature_names)); 12893b02a68aSJeff Mahoney 129079da4fa4SJeff Mahoney for (i = 0; btrfs_supported_feature_attrs[i]; i++) { 129179da4fa4SJeff Mahoney struct btrfs_feature_attr *sfa; 129279da4fa4SJeff Mahoney struct attribute *a = btrfs_supported_feature_attrs[i]; 12933b02a68aSJeff Mahoney int bit; 129479da4fa4SJeff Mahoney sfa = attr_to_btrfs_feature_attr(a); 12953b02a68aSJeff Mahoney bit = ilog2(sfa->feature_bit); 12963b02a68aSJeff Mahoney fa = &btrfs_feature_attrs[sfa->feature_set][bit]; 129779da4fa4SJeff Mahoney 129879da4fa4SJeff Mahoney fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name; 129979da4fa4SJeff Mahoney } 130079da4fa4SJeff Mahoney 130179da4fa4SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 130279da4fa4SJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 130379da4fa4SJeff Mahoney char *name = btrfs_unknown_feature_names[set][i]; 130479da4fa4SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 130579da4fa4SJeff Mahoney 130679da4fa4SJeff Mahoney if (fa->kobj_attr.attr.name) 130779da4fa4SJeff Mahoney continue; 130879da4fa4SJeff Mahoney 13096c52157fSTomohiro Misono snprintf(name, BTRFS_FEATURE_NAME_MAX, "%s:%u", 131079da4fa4SJeff Mahoney btrfs_feature_set_names[set], i); 131179da4fa4SJeff Mahoney 131279da4fa4SJeff Mahoney fa->kobj_attr.attr.name = name; 131379da4fa4SJeff Mahoney fa->kobj_attr.attr.mode = S_IRUGO; 131479da4fa4SJeff Mahoney fa->feature_set = set; 131579da4fa4SJeff Mahoney fa->feature_bit = 1ULL << i; 131679da4fa4SJeff Mahoney } 131779da4fa4SJeff Mahoney } 131879da4fa4SJeff Mahoney } 131979da4fa4SJeff Mahoney 132032a9991fSDavid Sterba /* 132132a9991fSDavid Sterba * Create a sysfs entry for a given block group type at path 132232a9991fSDavid Sterba * /sys/fs/btrfs/UUID/allocation/data/TYPE 132332a9991fSDavid Sterba */ 132432da5386SDavid Sterba void btrfs_sysfs_add_block_group_type(struct btrfs_block_group *cache) 132532a9991fSDavid Sterba { 132632a9991fSDavid Sterba struct btrfs_fs_info *fs_info = cache->fs_info; 132732a9991fSDavid Sterba struct btrfs_space_info *space_info = cache->space_info; 132832a9991fSDavid Sterba struct raid_kobject *rkobj; 132932a9991fSDavid Sterba const int index = btrfs_bg_flags_to_raid_index(cache->flags); 133032a9991fSDavid Sterba unsigned int nofs_flag; 133132a9991fSDavid Sterba int ret; 133232a9991fSDavid Sterba 133332a9991fSDavid Sterba /* 133432a9991fSDavid Sterba * Setup a NOFS context because kobject_add(), deep in its call chain, 133532a9991fSDavid Sterba * does GFP_KERNEL allocations, and we are often called in a context 133632a9991fSDavid Sterba * where if reclaim is triggered we can deadlock (we are either holding 133732a9991fSDavid Sterba * a transaction handle or some lock required for a transaction 133832a9991fSDavid Sterba * commit). 133932a9991fSDavid Sterba */ 134032a9991fSDavid Sterba nofs_flag = memalloc_nofs_save(); 134132a9991fSDavid Sterba 134232a9991fSDavid Sterba rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS); 134332a9991fSDavid Sterba if (!rkobj) { 134432a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 134532a9991fSDavid Sterba btrfs_warn(cache->fs_info, 134632a9991fSDavid Sterba "couldn't alloc memory for raid level kobject"); 134732a9991fSDavid Sterba return; 134832a9991fSDavid Sterba } 134932a9991fSDavid Sterba 135032a9991fSDavid Sterba rkobj->flags = cache->flags; 135132a9991fSDavid Sterba kobject_init(&rkobj->kobj, &btrfs_raid_ktype); 135249ea112dSJosef Bacik 135349ea112dSJosef Bacik /* 135449ea112dSJosef Bacik * We call this either on mount, or if we've created a block group for a 135549ea112dSJosef Bacik * new index type while running (i.e. when restriping). The running 135649ea112dSJosef Bacik * case is tricky because we could race with other threads, so we need 135749ea112dSJosef Bacik * to have this check to make sure we didn't already init the kobject. 135849ea112dSJosef Bacik * 135949ea112dSJosef Bacik * We don't have to protect on the free side because it only happens on 136049ea112dSJosef Bacik * unmount. 136149ea112dSJosef Bacik */ 136249ea112dSJosef Bacik spin_lock(&space_info->lock); 136349ea112dSJosef Bacik if (space_info->block_group_kobjs[index]) { 136449ea112dSJosef Bacik spin_unlock(&space_info->lock); 136549ea112dSJosef Bacik kobject_put(&rkobj->kobj); 136649ea112dSJosef Bacik return; 136749ea112dSJosef Bacik } else { 136849ea112dSJosef Bacik space_info->block_group_kobjs[index] = &rkobj->kobj; 136949ea112dSJosef Bacik } 137049ea112dSJosef Bacik spin_unlock(&space_info->lock); 137149ea112dSJosef Bacik 137232a9991fSDavid Sterba ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s", 137332a9991fSDavid Sterba btrfs_bg_type_to_raid_name(rkobj->flags)); 137432a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 137532a9991fSDavid Sterba if (ret) { 137649ea112dSJosef Bacik spin_lock(&space_info->lock); 137749ea112dSJosef Bacik space_info->block_group_kobjs[index] = NULL; 137849ea112dSJosef Bacik spin_unlock(&space_info->lock); 137932a9991fSDavid Sterba kobject_put(&rkobj->kobj); 138032a9991fSDavid Sterba btrfs_warn(fs_info, 138132a9991fSDavid Sterba "failed to add kobject for block cache, ignoring"); 138232a9991fSDavid Sterba return; 138332a9991fSDavid Sterba } 138432a9991fSDavid Sterba } 138532a9991fSDavid Sterba 1386b5865babSDavid Sterba /* 1387b5865babSDavid Sterba * Remove sysfs directories for all block group types of a given space info and 1388b5865babSDavid Sterba * the space info as well 1389b5865babSDavid Sterba */ 1390b5865babSDavid Sterba void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info) 1391b5865babSDavid Sterba { 1392b5865babSDavid Sterba int i; 1393b5865babSDavid Sterba 1394b5865babSDavid Sterba for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { 1395b5865babSDavid Sterba struct kobject *kobj; 1396b5865babSDavid Sterba 1397b5865babSDavid Sterba kobj = space_info->block_group_kobjs[i]; 1398b5865babSDavid Sterba space_info->block_group_kobjs[i] = NULL; 1399b5865babSDavid Sterba if (kobj) { 1400b5865babSDavid Sterba kobject_del(kobj); 1401b5865babSDavid Sterba kobject_put(kobj); 1402b5865babSDavid Sterba } 1403b5865babSDavid Sterba } 1404b5865babSDavid Sterba kobject_del(&space_info->kobj); 1405b5865babSDavid Sterba kobject_put(&space_info->kobj); 1406b5865babSDavid Sterba } 1407b5865babSDavid Sterba 1408b882327aSDavid Sterba static const char *alloc_name(u64 flags) 1409b882327aSDavid Sterba { 1410b882327aSDavid Sterba switch (flags) { 1411b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA: 1412b882327aSDavid Sterba return "mixed"; 1413b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA: 1414b882327aSDavid Sterba return "metadata"; 1415b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_DATA: 1416b882327aSDavid Sterba return "data"; 1417b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_SYSTEM: 1418b882327aSDavid Sterba return "system"; 1419b882327aSDavid Sterba default: 1420b882327aSDavid Sterba WARN_ON(1); 1421b882327aSDavid Sterba return "invalid-combination"; 1422445d8ab5STom Rix } 1423b882327aSDavid Sterba } 1424b882327aSDavid Sterba 1425b882327aSDavid Sterba /* 1426b882327aSDavid Sterba * Create a sysfs entry for a space info type at path 1427b882327aSDavid Sterba * /sys/fs/btrfs/UUID/allocation/TYPE 1428b882327aSDavid Sterba */ 1429b882327aSDavid Sterba int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info, 1430b882327aSDavid Sterba struct btrfs_space_info *space_info) 1431b882327aSDavid Sterba { 1432b882327aSDavid Sterba int ret; 1433b882327aSDavid Sterba 1434b882327aSDavid Sterba ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, 1435b882327aSDavid Sterba fs_info->space_info_kobj, "%s", 1436b882327aSDavid Sterba alloc_name(space_info->flags)); 1437b882327aSDavid Sterba if (ret) { 1438b882327aSDavid Sterba kobject_put(&space_info->kobj); 1439b882327aSDavid Sterba return ret; 1440b882327aSDavid Sterba } 1441b882327aSDavid Sterba 1442b882327aSDavid Sterba return 0; 1443b882327aSDavid Sterba } 1444b882327aSDavid Sterba 144553f8a74cSAnand Jain void btrfs_sysfs_remove_device(struct btrfs_device *device) 144699994cdeSAnand Jain { 1447985e233eSAnand Jain struct kobject *devices_kobj; 144899994cdeSAnand Jain 1449985e233eSAnand Jain /* 1450985e233eSAnand Jain * Seed fs_devices devices_kobj aren't used, fetch kobject from the 1451985e233eSAnand Jain * fs_info::fs_devices. 1452985e233eSAnand Jain */ 1453985e233eSAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1454985e233eSAnand Jain ASSERT(devices_kobj); 145599994cdeSAnand Jain 14568d65269fSChristoph Hellwig if (device->bdev) 14578d65269fSChristoph Hellwig sysfs_remove_link(devices_kobj, bdev_kobj(device->bdev)->name); 145899994cdeSAnand Jain 1459985e233eSAnand Jain if (device->devid_kobj.state_initialized) { 1460985e233eSAnand Jain kobject_del(&device->devid_kobj); 1461985e233eSAnand Jain kobject_put(&device->devid_kobj); 1462985e233eSAnand Jain wait_for_completion(&device->kobj_unregister); 1463985e233eSAnand Jain } 1464b5ddcffaSAnand Jain } 1465668e48afSAnand Jain 1466668e48afSAnand Jain static ssize_t btrfs_devinfo_in_fs_metadata_show(struct kobject *kobj, 1467668e48afSAnand Jain struct kobj_attribute *a, 1468668e48afSAnand Jain char *buf) 1469668e48afSAnand Jain { 1470668e48afSAnand Jain int val; 1471668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1472668e48afSAnand Jain devid_kobj); 1473668e48afSAnand Jain 1474668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state); 1475668e48afSAnand Jain 1476020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1477668e48afSAnand Jain } 1478668e48afSAnand Jain BTRFS_ATTR(devid, in_fs_metadata, btrfs_devinfo_in_fs_metadata_show); 1479668e48afSAnand Jain 148025864778SAnand Jain static ssize_t btrfs_devinfo_missing_show(struct kobject *kobj, 1481668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1482668e48afSAnand Jain { 1483668e48afSAnand Jain int val; 1484668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1485668e48afSAnand Jain devid_kobj); 1486668e48afSAnand Jain 1487668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state); 1488668e48afSAnand Jain 1489020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1490668e48afSAnand Jain } 149125864778SAnand Jain BTRFS_ATTR(devid, missing, btrfs_devinfo_missing_show); 1492668e48afSAnand Jain 1493668e48afSAnand Jain static ssize_t btrfs_devinfo_replace_target_show(struct kobject *kobj, 1494668e48afSAnand Jain struct kobj_attribute *a, 1495668e48afSAnand Jain char *buf) 1496668e48afSAnand Jain { 1497668e48afSAnand Jain int val; 1498668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1499668e48afSAnand Jain devid_kobj); 1500668e48afSAnand Jain 1501668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state); 1502668e48afSAnand Jain 1503020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1504668e48afSAnand Jain } 1505668e48afSAnand Jain BTRFS_ATTR(devid, replace_target, btrfs_devinfo_replace_target_show); 1506668e48afSAnand Jain 1507eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_show(struct kobject *kobj, 1508eb3b5053SDavid Sterba struct kobj_attribute *a, 1509eb3b5053SDavid Sterba char *buf) 1510eb3b5053SDavid Sterba { 1511eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1512eb3b5053SDavid Sterba devid_kobj); 1513eb3b5053SDavid Sterba 1514020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", READ_ONCE(device->scrub_speed_max)); 1515eb3b5053SDavid Sterba } 1516eb3b5053SDavid Sterba 1517eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_store(struct kobject *kobj, 1518eb3b5053SDavid Sterba struct kobj_attribute *a, 1519eb3b5053SDavid Sterba const char *buf, size_t len) 1520eb3b5053SDavid Sterba { 1521eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1522eb3b5053SDavid Sterba devid_kobj); 1523eb3b5053SDavid Sterba char *endptr; 1524eb3b5053SDavid Sterba unsigned long long limit; 1525eb3b5053SDavid Sterba 1526eb3b5053SDavid Sterba limit = memparse(buf, &endptr); 1527eb3b5053SDavid Sterba WRITE_ONCE(device->scrub_speed_max, limit); 1528eb3b5053SDavid Sterba return len; 1529eb3b5053SDavid Sterba } 1530eb3b5053SDavid Sterba BTRFS_ATTR_RW(devid, scrub_speed_max, btrfs_devinfo_scrub_speed_max_show, 1531eb3b5053SDavid Sterba btrfs_devinfo_scrub_speed_max_store); 1532eb3b5053SDavid Sterba 1533668e48afSAnand Jain static ssize_t btrfs_devinfo_writeable_show(struct kobject *kobj, 1534668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1535668e48afSAnand Jain { 1536668e48afSAnand Jain int val; 1537668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1538668e48afSAnand Jain devid_kobj); 1539668e48afSAnand Jain 1540668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state); 1541668e48afSAnand Jain 1542020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1543668e48afSAnand Jain } 1544668e48afSAnand Jain BTRFS_ATTR(devid, writeable, btrfs_devinfo_writeable_show); 1545668e48afSAnand Jain 1546a26d60deSAnand Jain static ssize_t btrfs_devinfo_fsid_show(struct kobject *kobj, 1547a26d60deSAnand Jain struct kobj_attribute *a, char *buf) 1548a26d60deSAnand Jain { 1549a26d60deSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1550a26d60deSAnand Jain devid_kobj); 1551a26d60deSAnand Jain 1552a26d60deSAnand Jain return sysfs_emit(buf, "%pU\n", device->fs_devices->fsid); 1553a26d60deSAnand Jain } 1554a26d60deSAnand Jain BTRFS_ATTR(devid, fsid, btrfs_devinfo_fsid_show); 1555a26d60deSAnand Jain 1556da658b57SDavid Sterba static ssize_t btrfs_devinfo_error_stats_show(struct kobject *kobj, 1557da658b57SDavid Sterba struct kobj_attribute *a, char *buf) 1558da658b57SDavid Sterba { 1559da658b57SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1560da658b57SDavid Sterba devid_kobj); 1561da658b57SDavid Sterba 1562da658b57SDavid Sterba if (!device->dev_stats_valid) 1563020e5277SAnand Jain return sysfs_emit(buf, "invalid\n"); 1564da658b57SDavid Sterba 1565da658b57SDavid Sterba /* 1566da658b57SDavid Sterba * Print all at once so we get a snapshot of all values from the same 1567da658b57SDavid Sterba * time. Keep them in sync and in order of definition of 1568da658b57SDavid Sterba * btrfs_dev_stat_values. 1569da658b57SDavid Sterba */ 1570020e5277SAnand Jain return sysfs_emit(buf, 1571da658b57SDavid Sterba "write_errs %d\n" 1572da658b57SDavid Sterba "read_errs %d\n" 1573da658b57SDavid Sterba "flush_errs %d\n" 1574da658b57SDavid Sterba "corruption_errs %d\n" 1575da658b57SDavid Sterba "generation_errs %d\n", 1576da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_WRITE_ERRS), 1577da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_READ_ERRS), 1578da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_FLUSH_ERRS), 1579da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_CORRUPTION_ERRS), 1580da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_GENERATION_ERRS)); 1581da658b57SDavid Sterba } 1582da658b57SDavid Sterba BTRFS_ATTR(devid, error_stats, btrfs_devinfo_error_stats_show); 1583da658b57SDavid Sterba 1584e7849e33SAnand Jain /* 1585e7849e33SAnand Jain * Information about one device. 1586e7849e33SAnand Jain * 1587e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/devinfo/<devid>/ 1588e7849e33SAnand Jain */ 1589668e48afSAnand Jain static struct attribute *devid_attrs[] = { 1590da658b57SDavid Sterba BTRFS_ATTR_PTR(devid, error_stats), 1591a26d60deSAnand Jain BTRFS_ATTR_PTR(devid, fsid), 1592668e48afSAnand Jain BTRFS_ATTR_PTR(devid, in_fs_metadata), 1593668e48afSAnand Jain BTRFS_ATTR_PTR(devid, missing), 1594668e48afSAnand Jain BTRFS_ATTR_PTR(devid, replace_target), 1595eb3b5053SDavid Sterba BTRFS_ATTR_PTR(devid, scrub_speed_max), 1596668e48afSAnand Jain BTRFS_ATTR_PTR(devid, writeable), 1597668e48afSAnand Jain NULL 1598668e48afSAnand Jain }; 1599668e48afSAnand Jain ATTRIBUTE_GROUPS(devid); 1600668e48afSAnand Jain 1601668e48afSAnand Jain static void btrfs_release_devid_kobj(struct kobject *kobj) 1602668e48afSAnand Jain { 1603668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1604668e48afSAnand Jain devid_kobj); 1605668e48afSAnand Jain 1606668e48afSAnand Jain memset(&device->devid_kobj, 0, sizeof(struct kobject)); 1607668e48afSAnand Jain complete(&device->kobj_unregister); 1608668e48afSAnand Jain } 1609668e48afSAnand Jain 1610668e48afSAnand Jain static struct kobj_type devid_ktype = { 1611668e48afSAnand Jain .sysfs_ops = &kobj_sysfs_ops, 1612668e48afSAnand Jain .default_groups = devid_groups, 1613668e48afSAnand Jain .release = btrfs_release_devid_kobj, 1614668e48afSAnand Jain }; 1615668e48afSAnand Jain 1616cd36da2eSAnand Jain int btrfs_sysfs_add_device(struct btrfs_device *device) 161729e5be24SJeff Mahoney { 1618178a16c9SAnand Jain int ret; 1619a47bd78dSJosef Bacik unsigned int nofs_flag; 1620178a16c9SAnand Jain struct kobject *devices_kobj; 1621178a16c9SAnand Jain struct kobject *devinfo_kobj; 1622178a16c9SAnand Jain 1623178a16c9SAnand Jain /* 1624178a16c9SAnand Jain * Make sure we use the fs_info::fs_devices to fetch the kobjects even 1625178a16c9SAnand Jain * for the seed fs_devices 1626178a16c9SAnand Jain */ 1627178a16c9SAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1628178a16c9SAnand Jain devinfo_kobj = device->fs_info->fs_devices->devinfo_kobj; 1629178a16c9SAnand Jain ASSERT(devices_kobj); 1630178a16c9SAnand Jain ASSERT(devinfo_kobj); 163129e5be24SJeff Mahoney 1632a47bd78dSJosef Bacik nofs_flag = memalloc_nofs_save(); 1633f085381eSAnand Jain 1634178a16c9SAnand Jain if (device->bdev) { 16358d65269fSChristoph Hellwig struct kobject *disk_kobj = bdev_kobj(device->bdev); 163629e5be24SJeff Mahoney 1637178a16c9SAnand Jain ret = sysfs_create_link(devices_kobj, disk_kobj, disk_kobj->name); 1638178a16c9SAnand Jain if (ret) { 1639178a16c9SAnand Jain btrfs_warn(device->fs_info, 1640178a16c9SAnand Jain "creating sysfs device link for devid %llu failed: %d", 1641178a16c9SAnand Jain device->devid, ret); 1642178a16c9SAnand Jain goto out; 1643178a16c9SAnand Jain } 164429e5be24SJeff Mahoney } 164529e5be24SJeff Mahoney 1646178a16c9SAnand Jain init_completion(&device->kobj_unregister); 1647178a16c9SAnand Jain ret = kobject_init_and_add(&device->devid_kobj, &devid_ktype, 1648178a16c9SAnand Jain devinfo_kobj, "%llu", device->devid); 1649178a16c9SAnand Jain if (ret) { 1650178a16c9SAnand Jain kobject_put(&device->devid_kobj); 1651178a16c9SAnand Jain btrfs_warn(device->fs_info, 1652178a16c9SAnand Jain "devinfo init for devid %llu failed: %d", 1653178a16c9SAnand Jain device->devid, ret); 1654668e48afSAnand Jain } 1655178a16c9SAnand Jain 1656178a16c9SAnand Jain out: 1657a47bd78dSJosef Bacik memalloc_nofs_restore(nofs_flag); 1658178a16c9SAnand Jain return ret; 1659178a16c9SAnand Jain } 1660668e48afSAnand Jain 1661cd36da2eSAnand Jain static int btrfs_sysfs_add_fs_devices(struct btrfs_fs_devices *fs_devices) 1662178a16c9SAnand Jain { 1663178a16c9SAnand Jain int ret; 1664cd36da2eSAnand Jain struct btrfs_device *device; 166530b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 1666178a16c9SAnand Jain 1667178a16c9SAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) { 1668178a16c9SAnand Jain ret = btrfs_sysfs_add_device(device); 1669178a16c9SAnand Jain if (ret) 16707ad3912aSAnand Jain goto fail; 1671178a16c9SAnand Jain } 1672178a16c9SAnand Jain 167330b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 167430b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) { 167530b0e4e0SAnand Jain ret = btrfs_sysfs_add_device(device); 167630b0e4e0SAnand Jain if (ret) 16777ad3912aSAnand Jain goto fail; 167830b0e4e0SAnand Jain } 167930b0e4e0SAnand Jain } 168030b0e4e0SAnand Jain 1681178a16c9SAnand Jain return 0; 16827ad3912aSAnand Jain 16837ad3912aSAnand Jain fail: 16847ad3912aSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devices); 16857ad3912aSAnand Jain return ret; 168629e5be24SJeff Mahoney } 168729e5be24SJeff Mahoney 16885b28692eSDavid Sterba void btrfs_kobject_uevent(struct block_device *bdev, enum kobject_action action) 16895b28692eSDavid Sterba { 16905b28692eSDavid Sterba int ret; 16915b28692eSDavid Sterba 16925b28692eSDavid Sterba ret = kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, action); 16935b28692eSDavid Sterba if (ret) 16945b28692eSDavid Sterba pr_warn("BTRFS: Sending event '%d' to kobject: '%s' (%p): failed\n", 16955b28692eSDavid Sterba action, kobject_name(&disk_to_dev(bdev->bd_disk)->kobj), 16965b28692eSDavid Sterba &disk_to_dev(bdev->bd_disk)->kobj); 16975b28692eSDavid Sterba } 16985b28692eSDavid Sterba 16998e560081SNikolay Borisov void btrfs_sysfs_update_sprout_fsid(struct btrfs_fs_devices *fs_devices) 17008e560081SNikolay Borisov 1701f93c3997SDavid Sterba { 1702f93c3997SDavid Sterba char fsid_buf[BTRFS_UUID_UNPARSED_SIZE]; 1703f93c3997SDavid Sterba 1704f93c3997SDavid Sterba /* 1705f93c3997SDavid Sterba * Sprouting changes fsid of the mounted filesystem, rename the fsid 1706f93c3997SDavid Sterba * directory 1707f93c3997SDavid Sterba */ 17088e560081SNikolay Borisov snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", fs_devices->fsid); 1709f93c3997SDavid Sterba if (kobject_rename(&fs_devices->fsid_kobj, fsid_buf)) 1710f93c3997SDavid Sterba btrfs_warn(fs_devices->fs_info, 1711f93c3997SDavid Sterba "sysfs: failed to create fsid for sprout"); 1712f93c3997SDavid Sterba } 1713f93c3997SDavid Sterba 1714668e48afSAnand Jain void btrfs_sysfs_update_devid(struct btrfs_device *device) 1715668e48afSAnand Jain { 1716668e48afSAnand Jain char tmp[24]; 1717668e48afSAnand Jain 1718668e48afSAnand Jain snprintf(tmp, sizeof(tmp), "%llu", device->devid); 1719668e48afSAnand Jain 1720668e48afSAnand Jain if (kobject_rename(&device->devid_kobj, tmp)) 1721668e48afSAnand Jain btrfs_warn(device->fs_devices->fs_info, 1722668e48afSAnand Jain "sysfs: failed to update devid for %llu", 1723668e48afSAnand Jain device->devid); 1724668e48afSAnand Jain } 1725668e48afSAnand Jain 1726510d7360SJeff Mahoney /* /sys/fs/btrfs/ entry */ 1727510d7360SJeff Mahoney static struct kset *btrfs_kset; 1728510d7360SJeff Mahoney 172972059215SAnand Jain /* 1730c6761a9eSAnand Jain * Creates: 1731c6761a9eSAnand Jain * /sys/fs/btrfs/UUID 1732c6761a9eSAnand Jain * 173372059215SAnand Jain * Can be called by the device discovery thread. 173472059215SAnand Jain */ 1735c6761a9eSAnand Jain int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs) 17365ac1d209SJeff Mahoney { 17375ac1d209SJeff Mahoney int error; 17385ac1d209SJeff Mahoney 17392e7910d6SAnand Jain init_completion(&fs_devs->kobj_unregister); 1740c1b7e474SAnand Jain fs_devs->fsid_kobj.kset = btrfs_kset; 1741c6761a9eSAnand Jain error = kobject_init_and_add(&fs_devs->fsid_kobj, &btrfs_ktype, NULL, 1742c6761a9eSAnand Jain "%pU", fs_devs->fsid); 1743e3277335STobin C. Harding if (error) { 1744e3277335STobin C. Harding kobject_put(&fs_devs->fsid_kobj); 174572059215SAnand Jain return error; 174672059215SAnand Jain } 174772059215SAnand Jain 1748bc036bb3SAnand Jain fs_devs->devices_kobj = kobject_create_and_add("devices", 1749bc036bb3SAnand Jain &fs_devs->fsid_kobj); 1750bc036bb3SAnand Jain if (!fs_devs->devices_kobj) { 1751bc036bb3SAnand Jain btrfs_err(fs_devs->fs_info, 1752bc036bb3SAnand Jain "failed to init sysfs device interface"); 17531f6087e6SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1754bc036bb3SAnand Jain return -ENOMEM; 1755bc036bb3SAnand Jain } 1756bc036bb3SAnand Jain 1757a013d141SAnand Jain fs_devs->devinfo_kobj = kobject_create_and_add("devinfo", 1758a013d141SAnand Jain &fs_devs->fsid_kobj); 1759a013d141SAnand Jain if (!fs_devs->devinfo_kobj) { 1760a013d141SAnand Jain btrfs_err(fs_devs->fs_info, 1761a013d141SAnand Jain "failed to init sysfs devinfo kobject"); 1762a013d141SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1763a013d141SAnand Jain return -ENOMEM; 1764a013d141SAnand Jain } 1765a013d141SAnand Jain 1766e3277335STobin C. Harding return 0; 1767e3277335STobin C. Harding } 1768e3277335STobin C. Harding 176996f3136eSAnand Jain int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info) 177072059215SAnand Jain { 177172059215SAnand Jain int error; 17722e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = fs_info->fs_devices; 1773c1b7e474SAnand Jain struct kobject *fsid_kobj = &fs_devs->fsid_kobj; 177472059215SAnand Jain 1775cd36da2eSAnand Jain error = btrfs_sysfs_add_fs_devices(fs_devs); 1776e453d989SJeff Mahoney if (error) 1777e453d989SJeff Mahoney return error; 1778510d7360SJeff Mahoney 1779c1b7e474SAnand Jain error = sysfs_create_files(fsid_kobj, btrfs_attrs); 1780e453d989SJeff Mahoney if (error) { 178153f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devs); 1782e453d989SJeff Mahoney return error; 1783e453d989SJeff Mahoney } 178479da4fa4SJeff Mahoney 1785c1b7e474SAnand Jain error = sysfs_create_group(fsid_kobj, 17860dd2906fSAnand Jain &btrfs_feature_attr_group); 17870dd2906fSAnand Jain if (error) 17880dd2906fSAnand Jain goto failure; 17890dd2906fSAnand Jain 17906e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 179193945cb4SDennis Zhou fs_info->debug_kobj = kobject_create_and_add("debug", fsid_kobj); 179293945cb4SDennis Zhou if (!fs_info->debug_kobj) { 179393945cb4SDennis Zhou error = -ENOMEM; 179493945cb4SDennis Zhou goto failure; 179593945cb4SDennis Zhou } 179693945cb4SDennis Zhou 179793945cb4SDennis Zhou error = sysfs_create_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 17986e369febSDavid Sterba if (error) 17996e369febSDavid Sterba goto failure; 1800e4faab84SDennis Zhou 1801e4faab84SDennis Zhou /* Discard directory */ 1802e4faab84SDennis Zhou fs_info->discard_debug_kobj = kobject_create_and_add("discard", 1803e4faab84SDennis Zhou fs_info->debug_kobj); 1804e4faab84SDennis Zhou if (!fs_info->discard_debug_kobj) { 1805e4faab84SDennis Zhou error = -ENOMEM; 1806e4faab84SDennis Zhou goto failure; 1807e4faab84SDennis Zhou } 1808e4faab84SDennis Zhou 1809e4faab84SDennis Zhou error = sysfs_create_files(fs_info->discard_debug_kobj, 1810e4faab84SDennis Zhou discard_debug_attrs); 1811e4faab84SDennis Zhou if (error) 1812e4faab84SDennis Zhou goto failure; 18136e369febSDavid Sterba #endif 18146e369febSDavid Sterba 1815e453d989SJeff Mahoney error = addrm_unknown_feature_attrs(fs_info, true); 181679da4fa4SJeff Mahoney if (error) 181779da4fa4SJeff Mahoney goto failure; 181879da4fa4SJeff Mahoney 18193092c68fSNikolay Borisov error = sysfs_create_link(fsid_kobj, &fs_info->sb->s_bdi->dev->kobj, "bdi"); 18203092c68fSNikolay Borisov if (error) 18213092c68fSNikolay Borisov goto failure; 18223092c68fSNikolay Borisov 18236ab0a202SJeff Mahoney fs_info->space_info_kobj = kobject_create_and_add("allocation", 1824c1b7e474SAnand Jain fsid_kobj); 18256ab0a202SJeff Mahoney if (!fs_info->space_info_kobj) { 18266ab0a202SJeff Mahoney error = -ENOMEM; 18276ab0a202SJeff Mahoney goto failure; 18286ab0a202SJeff Mahoney } 18296ab0a202SJeff Mahoney 18306ab0a202SJeff Mahoney error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs); 18316ab0a202SJeff Mahoney if (error) 18326ab0a202SJeff Mahoney goto failure; 18336ab0a202SJeff Mahoney 183479da4fa4SJeff Mahoney return 0; 183579da4fa4SJeff Mahoney failure: 18366618a59bSAnand Jain btrfs_sysfs_remove_mounted(fs_info); 18375ac1d209SJeff Mahoney return error; 18385ac1d209SJeff Mahoney } 18395ac1d209SJeff Mahoney 184049e5fb46SQu Wenruo static inline struct btrfs_fs_info *qgroup_kobj_to_fs_info(struct kobject *kobj) 184149e5fb46SQu Wenruo { 184249e5fb46SQu Wenruo return to_fs_info(kobj->parent->parent); 184349e5fb46SQu Wenruo } 184449e5fb46SQu Wenruo 184549e5fb46SQu Wenruo #define QGROUP_ATTR(_member, _show_name) \ 184649e5fb46SQu Wenruo static ssize_t btrfs_qgroup_show_##_member(struct kobject *qgroup_kobj, \ 184749e5fb46SQu Wenruo struct kobj_attribute *a, \ 184849e5fb46SQu Wenruo char *buf) \ 184949e5fb46SQu Wenruo { \ 185049e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 185149e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 185249e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 185349e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->_member, &fs_info->qgroup_lock, buf); \ 185449e5fb46SQu Wenruo } \ 185549e5fb46SQu Wenruo BTRFS_ATTR(qgroup, _show_name, btrfs_qgroup_show_##_member) 185649e5fb46SQu Wenruo 185749e5fb46SQu Wenruo #define QGROUP_RSV_ATTR(_name, _type) \ 185849e5fb46SQu Wenruo static ssize_t btrfs_qgroup_rsv_show_##_name(struct kobject *qgroup_kobj, \ 185949e5fb46SQu Wenruo struct kobj_attribute *a, \ 186049e5fb46SQu Wenruo char *buf) \ 186149e5fb46SQu Wenruo { \ 186249e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 186349e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 186449e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 186549e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->rsv.values[_type], \ 186649e5fb46SQu Wenruo &fs_info->qgroup_lock, buf); \ 186749e5fb46SQu Wenruo } \ 186849e5fb46SQu Wenruo BTRFS_ATTR(qgroup, rsv_##_name, btrfs_qgroup_rsv_show_##_name) 186949e5fb46SQu Wenruo 187049e5fb46SQu Wenruo QGROUP_ATTR(rfer, referenced); 187149e5fb46SQu Wenruo QGROUP_ATTR(excl, exclusive); 187249e5fb46SQu Wenruo QGROUP_ATTR(max_rfer, max_referenced); 187349e5fb46SQu Wenruo QGROUP_ATTR(max_excl, max_exclusive); 187449e5fb46SQu Wenruo QGROUP_ATTR(lim_flags, limit_flags); 187549e5fb46SQu Wenruo QGROUP_RSV_ATTR(data, BTRFS_QGROUP_RSV_DATA); 187649e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_pertrans, BTRFS_QGROUP_RSV_META_PERTRANS); 187749e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_prealloc, BTRFS_QGROUP_RSV_META_PREALLOC); 187849e5fb46SQu Wenruo 1879e7849e33SAnand Jain /* 1880e7849e33SAnand Jain * Qgroup information. 1881e7849e33SAnand Jain * 1882e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/qgroups/<level>_<qgroupid>/ 1883e7849e33SAnand Jain */ 188449e5fb46SQu Wenruo static struct attribute *qgroup_attrs[] = { 188549e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, referenced), 188649e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, exclusive), 188749e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_referenced), 188849e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_exclusive), 188949e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, limit_flags), 189049e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_data), 189149e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_pertrans), 189249e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_prealloc), 189349e5fb46SQu Wenruo NULL 189449e5fb46SQu Wenruo }; 189549e5fb46SQu Wenruo ATTRIBUTE_GROUPS(qgroup); 189649e5fb46SQu Wenruo 189749e5fb46SQu Wenruo static void qgroup_release(struct kobject *kobj) 189849e5fb46SQu Wenruo { 189949e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(kobj, struct btrfs_qgroup, kobj); 190049e5fb46SQu Wenruo 190149e5fb46SQu Wenruo memset(&qgroup->kobj, 0, sizeof(*kobj)); 190249e5fb46SQu Wenruo } 190349e5fb46SQu Wenruo 190449e5fb46SQu Wenruo static struct kobj_type qgroup_ktype = { 190549e5fb46SQu Wenruo .sysfs_ops = &kobj_sysfs_ops, 190649e5fb46SQu Wenruo .release = qgroup_release, 190749e5fb46SQu Wenruo .default_groups = qgroup_groups, 190849e5fb46SQu Wenruo }; 190949e5fb46SQu Wenruo 191049e5fb46SQu Wenruo int btrfs_sysfs_add_one_qgroup(struct btrfs_fs_info *fs_info, 191149e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 191249e5fb46SQu Wenruo { 191349e5fb46SQu Wenruo struct kobject *qgroups_kobj = fs_info->qgroups_kobj; 191449e5fb46SQu Wenruo int ret; 191549e5fb46SQu Wenruo 191649e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 191749e5fb46SQu Wenruo return 0; 191849e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) 191949e5fb46SQu Wenruo return 0; 192049e5fb46SQu Wenruo if (!qgroups_kobj) 192149e5fb46SQu Wenruo return -EINVAL; 192249e5fb46SQu Wenruo 192349e5fb46SQu Wenruo ret = kobject_init_and_add(&qgroup->kobj, &qgroup_ktype, qgroups_kobj, 192449e5fb46SQu Wenruo "%hu_%llu", btrfs_qgroup_level(qgroup->qgroupid), 192549e5fb46SQu Wenruo btrfs_qgroup_subvolid(qgroup->qgroupid)); 192649e5fb46SQu Wenruo if (ret < 0) 192749e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 192849e5fb46SQu Wenruo 192949e5fb46SQu Wenruo return ret; 193049e5fb46SQu Wenruo } 193149e5fb46SQu Wenruo 193249e5fb46SQu Wenruo void btrfs_sysfs_del_qgroups(struct btrfs_fs_info *fs_info) 193349e5fb46SQu Wenruo { 193449e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 193549e5fb46SQu Wenruo struct btrfs_qgroup *next; 193649e5fb46SQu Wenruo 193749e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 193849e5fb46SQu Wenruo return; 193949e5fb46SQu Wenruo 194049e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 194149e5fb46SQu Wenruo &fs_info->qgroup_tree, node) 194249e5fb46SQu Wenruo btrfs_sysfs_del_one_qgroup(fs_info, qgroup); 194362ab2cc0SQu Wenruo if (fs_info->qgroups_kobj) { 194449e5fb46SQu Wenruo kobject_del(fs_info->qgroups_kobj); 194549e5fb46SQu Wenruo kobject_put(fs_info->qgroups_kobj); 194649e5fb46SQu Wenruo fs_info->qgroups_kobj = NULL; 194749e5fb46SQu Wenruo } 194862ab2cc0SQu Wenruo } 194949e5fb46SQu Wenruo 195049e5fb46SQu Wenruo /* Called when qgroups get initialized, thus there is no need for locking */ 195149e5fb46SQu Wenruo int btrfs_sysfs_add_qgroups(struct btrfs_fs_info *fs_info) 195249e5fb46SQu Wenruo { 195349e5fb46SQu Wenruo struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 195449e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 195549e5fb46SQu Wenruo struct btrfs_qgroup *next; 195649e5fb46SQu Wenruo int ret = 0; 195749e5fb46SQu Wenruo 195849e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 195949e5fb46SQu Wenruo return 0; 196049e5fb46SQu Wenruo 196149e5fb46SQu Wenruo ASSERT(fsid_kobj); 196249e5fb46SQu Wenruo if (fs_info->qgroups_kobj) 196349e5fb46SQu Wenruo return 0; 196449e5fb46SQu Wenruo 196549e5fb46SQu Wenruo fs_info->qgroups_kobj = kobject_create_and_add("qgroups", fsid_kobj); 196649e5fb46SQu Wenruo if (!fs_info->qgroups_kobj) { 196749e5fb46SQu Wenruo ret = -ENOMEM; 196849e5fb46SQu Wenruo goto out; 196949e5fb46SQu Wenruo } 197049e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 197149e5fb46SQu Wenruo &fs_info->qgroup_tree, node) { 197249e5fb46SQu Wenruo ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup); 197349e5fb46SQu Wenruo if (ret < 0) 197449e5fb46SQu Wenruo goto out; 197549e5fb46SQu Wenruo } 197649e5fb46SQu Wenruo 197749e5fb46SQu Wenruo out: 197849e5fb46SQu Wenruo if (ret < 0) 197949e5fb46SQu Wenruo btrfs_sysfs_del_qgroups(fs_info); 198049e5fb46SQu Wenruo return ret; 198149e5fb46SQu Wenruo } 198249e5fb46SQu Wenruo 198349e5fb46SQu Wenruo void btrfs_sysfs_del_one_qgroup(struct btrfs_fs_info *fs_info, 198449e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 198549e5fb46SQu Wenruo { 198649e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 198749e5fb46SQu Wenruo return; 198849e5fb46SQu Wenruo 198949e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) { 199049e5fb46SQu Wenruo kobject_del(&qgroup->kobj); 199149e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 199249e5fb46SQu Wenruo } 199349e5fb46SQu Wenruo } 1994444e7516SDavid Sterba 1995444e7516SDavid Sterba /* 1996444e7516SDavid Sterba * Change per-fs features in /sys/fs/btrfs/UUID/features to match current 1997444e7516SDavid Sterba * values in superblock. Call after any changes to incompat/compat_ro flags 1998444e7516SDavid Sterba */ 1999444e7516SDavid Sterba void btrfs_sysfs_feature_update(struct btrfs_fs_info *fs_info, 2000444e7516SDavid Sterba u64 bit, enum btrfs_feature_set set) 2001444e7516SDavid Sterba { 2002444e7516SDavid Sterba struct btrfs_fs_devices *fs_devs; 2003444e7516SDavid Sterba struct kobject *fsid_kobj; 200424646481SLeon Romanovsky u64 __maybe_unused features; 200524646481SLeon Romanovsky int __maybe_unused ret; 2006444e7516SDavid Sterba 2007444e7516SDavid Sterba if (!fs_info) 2008444e7516SDavid Sterba return; 2009444e7516SDavid Sterba 201024646481SLeon Romanovsky /* 201124646481SLeon Romanovsky * See 14e46e04958df74 and e410e34fad913dd, feature bit updates are not 201224646481SLeon Romanovsky * safe when called from some contexts (eg. balance) 201324646481SLeon Romanovsky */ 2014444e7516SDavid Sterba features = get_features(fs_info, set); 2015444e7516SDavid Sterba ASSERT(bit & supported_feature_masks[set]); 2016444e7516SDavid Sterba 2017444e7516SDavid Sterba fs_devs = fs_info->fs_devices; 2018444e7516SDavid Sterba fsid_kobj = &fs_devs->fsid_kobj; 2019444e7516SDavid Sterba 2020bf609206SDavid Sterba if (!fsid_kobj->state_initialized) 2021bf609206SDavid Sterba return; 2022bf609206SDavid Sterba 2023444e7516SDavid Sterba /* 2024444e7516SDavid Sterba * FIXME: this is too heavy to update just one value, ideally we'd like 2025444e7516SDavid Sterba * to use sysfs_update_group but some refactoring is needed first. 2026444e7516SDavid Sterba */ 2027444e7516SDavid Sterba sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 2028444e7516SDavid Sterba ret = sysfs_create_group(fsid_kobj, &btrfs_feature_attr_group); 2029444e7516SDavid Sterba } 2030444e7516SDavid Sterba 2031f5c29bd9SLiu Bo int __init btrfs_init_sysfs(void) 203258176a96SJosef Bacik { 2033079b72bcSJeff Mahoney int ret; 20341bae3098SDavid Sterba 2035e3fe4e71SGreg KH btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); 2036e3fe4e71SGreg KH if (!btrfs_kset) 2037e3fe4e71SGreg KH return -ENOMEM; 2038079b72bcSJeff Mahoney 20391bae3098SDavid Sterba init_feature_attrs(); 20401bae3098SDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2041001a648dSFilipe Manana if (ret) 2042001a648dSFilipe Manana goto out2; 2043f902bd3aSMisono Tomohiro ret = sysfs_merge_group(&btrfs_kset->kobj, 2044f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2045f902bd3aSMisono Tomohiro if (ret) 2046f902bd3aSMisono Tomohiro goto out_remove_group; 2047001a648dSFilipe Manana 20486e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 20496e369febSDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 20506e369febSDavid Sterba if (ret) 20516e369febSDavid Sterba goto out2; 20526e369febSDavid Sterba #endif 20536e369febSDavid Sterba 2054001a648dSFilipe Manana return 0; 2055f902bd3aSMisono Tomohiro 2056f902bd3aSMisono Tomohiro out_remove_group: 2057f902bd3aSMisono Tomohiro sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2058001a648dSFilipe Manana out2: 2059001a648dSFilipe Manana kset_unregister(btrfs_kset); 20601bae3098SDavid Sterba 20611bae3098SDavid Sterba return ret; 206258176a96SJosef Bacik } 206358176a96SJosef Bacik 2064e67c718bSDavid Sterba void __cold btrfs_exit_sysfs(void) 206558176a96SJosef Bacik { 2066f902bd3aSMisono Tomohiro sysfs_unmerge_group(&btrfs_kset->kobj, 2067f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2068079b72bcSJeff Mahoney sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 206971e8978eSDennis Zhou #ifdef CONFIG_BTRFS_DEBUG 207071e8978eSDennis Zhou sysfs_remove_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 207171e8978eSDennis Zhou #endif 2072e3fe4e71SGreg KH kset_unregister(btrfs_kset); 207358176a96SJosef Bacik } 207455d47414SChris Mason 2075