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> 139b569ea0SJosef Bacik #include "messages.h" 14bae45de0SChris Mason #include "ctree.h" 15dfb79ddbSDennis Zhou #include "discard.h" 16bae45de0SChris Mason #include "disk-io.h" 177573df55SOmar Sandoval #include "send.h" 18bae45de0SChris Mason #include "transaction.h" 19079b72bcSJeff Mahoney #include "sysfs.h" 2029e5be24SJeff Mahoney #include "volumes.h" 218719aaaeSJosef Bacik #include "space-info.h" 22aac0023cSJosef Bacik #include "block-group.h" 2349e5fb46SQu Wenruo #include "qgroup.h" 2419fc516aSStefan Roesch #include "misc.h" 25ec8eb376SJosef Bacik #include "fs.h" 26079b72bcSJeff Mahoney 27e7849e33SAnand Jain /* 28e7849e33SAnand Jain * Structure name Path 29e7849e33SAnand Jain * -------------------------------------------------------------------------- 30e7849e33SAnand Jain * btrfs_supported_static_feature_attrs /sys/fs/btrfs/features 31e7849e33SAnand Jain * btrfs_supported_feature_attrs /sys/fs/btrfs/features and 32e7849e33SAnand Jain * /sys/fs/btrfs/<uuid>/features 33e7849e33SAnand Jain * btrfs_attrs /sys/fs/btrfs/<uuid> 34e7849e33SAnand Jain * devid_attrs /sys/fs/btrfs/<uuid>/devinfo/<devid> 35e7849e33SAnand Jain * allocation_attrs /sys/fs/btrfs/<uuid>/allocation 36e7849e33SAnand Jain * qgroup_attrs /sys/fs/btrfs/<uuid>/qgroups/<level>_<qgroupid> 37e7849e33SAnand Jain * space_info_attrs /sys/fs/btrfs/<uuid>/allocation/<bg-type> 38e7849e33SAnand Jain * raid_attrs /sys/fs/btrfs/<uuid>/allocation/<bg-type>/<bg-profile> 39fb731430SDavid Sterba * discard_attrs /sys/fs/btrfs/<uuid>/discard 40e7849e33SAnand Jain * 41e7849e33SAnand Jain * When built with BTRFS_CONFIG_DEBUG: 42e7849e33SAnand Jain * 43e7849e33SAnand Jain * btrfs_debug_feature_attrs /sys/fs/btrfs/debug 44e7849e33SAnand Jain * btrfs_debug_mount_attrs /sys/fs/btrfs/<uuid>/debug 45e7849e33SAnand Jain */ 46e7849e33SAnand Jain 479188db61SDavid Sterba struct btrfs_feature_attr { 489188db61SDavid Sterba struct kobj_attribute kobj_attr; 499188db61SDavid Sterba enum btrfs_feature_set feature_set; 509188db61SDavid Sterba u64 feature_bit; 519188db61SDavid Sterba }; 529188db61SDavid Sterba 539188db61SDavid Sterba /* For raid type sysfs entries */ 549188db61SDavid Sterba struct raid_kobject { 559188db61SDavid Sterba u64 flags; 569188db61SDavid Sterba struct kobject kobj; 579188db61SDavid Sterba }; 589188db61SDavid Sterba 599188db61SDavid Sterba #define __INIT_KOBJ_ATTR(_name, _mode, _show, _store) \ 609188db61SDavid Sterba { \ 619188db61SDavid Sterba .attr = { .name = __stringify(_name), .mode = _mode }, \ 629188db61SDavid Sterba .show = _show, \ 639188db61SDavid Sterba .store = _store, \ 649188db61SDavid Sterba } 659188db61SDavid Sterba 6622c55e3bSStefan Roesch #define BTRFS_ATTR_W(_prefix, _name, _store) \ 6722c55e3bSStefan Roesch static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 6822c55e3bSStefan Roesch __INIT_KOBJ_ATTR(_name, 0200, NULL, _store) 6922c55e3bSStefan Roesch 709188db61SDavid Sterba #define BTRFS_ATTR_RW(_prefix, _name, _show, _store) \ 719188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 729188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0644, _show, _store) 739188db61SDavid Sterba 749188db61SDavid Sterba #define BTRFS_ATTR(_prefix, _name, _show) \ 759188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 769188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0444, _show, NULL) 779188db61SDavid Sterba 789188db61SDavid Sterba #define BTRFS_ATTR_PTR(_prefix, _name) \ 799188db61SDavid Sterba (&btrfs_attr_##_prefix##_##_name.attr) 809188db61SDavid Sterba 819188db61SDavid Sterba #define BTRFS_FEAT_ATTR(_name, _feature_set, _feature_prefix, _feature_bit) \ 829188db61SDavid Sterba static struct btrfs_feature_attr btrfs_attr_features_##_name = { \ 839188db61SDavid Sterba .kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO, \ 849188db61SDavid Sterba btrfs_feature_attr_show, \ 859188db61SDavid Sterba btrfs_feature_attr_store), \ 869188db61SDavid Sterba .feature_set = _feature_set, \ 879188db61SDavid Sterba .feature_bit = _feature_prefix ##_## _feature_bit, \ 889188db61SDavid Sterba } 899188db61SDavid Sterba #define BTRFS_FEAT_ATTR_PTR(_name) \ 909188db61SDavid Sterba (&btrfs_attr_features_##_name.kobj_attr.attr) 919188db61SDavid Sterba 929188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT(name, feature) \ 939188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT, BTRFS_FEATURE_COMPAT, feature) 949188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT_RO(name, feature) \ 959188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT_RO, BTRFS_FEATURE_COMPAT_RO, feature) 969188db61SDavid Sterba #define BTRFS_FEAT_ATTR_INCOMPAT(name, feature) \ 979188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_INCOMPAT, BTRFS_FEATURE_INCOMPAT, feature) 989188db61SDavid Sterba 99510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); 1002e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj); 10119fc516aSStefan Roesch static struct kobject *get_btrfs_kobj(struct kobject *kobj); 1025ac1d209SJeff Mahoney 1038f52316cSDavid Sterba static struct btrfs_feature_attr *to_btrfs_feature_attr(struct kobj_attribute *a) 1048f52316cSDavid Sterba { 1058f52316cSDavid Sterba return container_of(a, struct btrfs_feature_attr, kobj_attr); 1068f52316cSDavid Sterba } 1078f52316cSDavid Sterba 1088f52316cSDavid Sterba static struct kobj_attribute *attr_to_btrfs_attr(struct attribute *attr) 1098f52316cSDavid Sterba { 1108f52316cSDavid Sterba return container_of(attr, struct kobj_attribute, attr); 1118f52316cSDavid Sterba } 1128f52316cSDavid Sterba 1138f52316cSDavid Sterba static struct btrfs_feature_attr *attr_to_btrfs_feature_attr( 1148f52316cSDavid Sterba struct attribute *attr) 1158f52316cSDavid Sterba { 1168f52316cSDavid Sterba return to_btrfs_feature_attr(attr_to_btrfs_attr(attr)); 1178f52316cSDavid Sterba } 1188f52316cSDavid Sterba 119510d7360SJeff Mahoney static u64 get_features(struct btrfs_fs_info *fs_info, 120510d7360SJeff Mahoney enum btrfs_feature_set set) 1215ac1d209SJeff Mahoney { 122510d7360SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 123510d7360SJeff Mahoney if (set == FEAT_COMPAT) 124510d7360SJeff Mahoney return btrfs_super_compat_flags(disk_super); 125510d7360SJeff Mahoney else if (set == FEAT_COMPAT_RO) 126510d7360SJeff Mahoney return btrfs_super_compat_ro_flags(disk_super); 127510d7360SJeff Mahoney else 128510d7360SJeff Mahoney return btrfs_super_incompat_flags(disk_super); 1295ac1d209SJeff Mahoney } 1305ac1d209SJeff Mahoney 131ba631941SJeff Mahoney static void set_features(struct btrfs_fs_info *fs_info, 132ba631941SJeff Mahoney enum btrfs_feature_set set, u64 features) 133ba631941SJeff Mahoney { 134ba631941SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 135ba631941SJeff Mahoney if (set == FEAT_COMPAT) 136ba631941SJeff Mahoney btrfs_set_super_compat_flags(disk_super, features); 137ba631941SJeff Mahoney else if (set == FEAT_COMPAT_RO) 138ba631941SJeff Mahoney btrfs_set_super_compat_ro_flags(disk_super, features); 139ba631941SJeff Mahoney else 140ba631941SJeff Mahoney btrfs_set_super_incompat_flags(disk_super, features); 141ba631941SJeff Mahoney } 142ba631941SJeff Mahoney 143ba631941SJeff Mahoney static int can_modify_feature(struct btrfs_feature_attr *fa) 144ba631941SJeff Mahoney { 145ba631941SJeff Mahoney int val = 0; 146ba631941SJeff Mahoney u64 set, clear; 147ba631941SJeff Mahoney switch (fa->feature_set) { 148ba631941SJeff Mahoney case FEAT_COMPAT: 149ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 150ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 151ba631941SJeff Mahoney break; 152ba631941SJeff Mahoney case FEAT_COMPAT_RO: 153ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 154ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 155ba631941SJeff Mahoney break; 156ba631941SJeff Mahoney case FEAT_INCOMPAT: 157ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 158ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 159ba631941SJeff Mahoney break; 160ba631941SJeff Mahoney default: 16162e85577SJeff Mahoney pr_warn("btrfs: sysfs: unknown feature set %d\n", 162cc37bb04SDavid Sterba fa->feature_set); 163cc37bb04SDavid Sterba return 0; 164ba631941SJeff Mahoney } 165ba631941SJeff Mahoney 166ba631941SJeff Mahoney if (set & fa->feature_bit) 167ba631941SJeff Mahoney val |= 1; 168ba631941SJeff Mahoney if (clear & fa->feature_bit) 169ba631941SJeff Mahoney val |= 2; 170ba631941SJeff Mahoney 171ba631941SJeff Mahoney return val; 172ba631941SJeff Mahoney } 173ba631941SJeff Mahoney 174079b72bcSJeff Mahoney static ssize_t btrfs_feature_attr_show(struct kobject *kobj, 175079b72bcSJeff Mahoney struct kobj_attribute *a, char *buf) 176079b72bcSJeff Mahoney { 177510d7360SJeff Mahoney int val = 0; 178510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 179510d7360SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 180ba631941SJeff Mahoney if (fs_info) { 181510d7360SJeff Mahoney u64 features = get_features(fs_info, fa->feature_set); 182510d7360SJeff Mahoney if (features & fa->feature_bit) 183510d7360SJeff Mahoney val = 1; 184ba631941SJeff Mahoney } else 185ba631941SJeff Mahoney val = can_modify_feature(fa); 186510d7360SJeff Mahoney 187020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 188510d7360SJeff Mahoney } 189510d7360SJeff Mahoney 190ba631941SJeff Mahoney static ssize_t btrfs_feature_attr_store(struct kobject *kobj, 191ba631941SJeff Mahoney struct kobj_attribute *a, 192ba631941SJeff Mahoney const char *buf, size_t count) 193ba631941SJeff Mahoney { 194ba631941SJeff Mahoney struct btrfs_fs_info *fs_info; 195ba631941SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 196ba631941SJeff Mahoney u64 features, set, clear; 197ba631941SJeff Mahoney unsigned long val; 198ba631941SJeff Mahoney int ret; 199ba631941SJeff Mahoney 200ba631941SJeff Mahoney fs_info = to_fs_info(kobj); 201ba631941SJeff Mahoney if (!fs_info) 202ba631941SJeff Mahoney return -EPERM; 203ba631941SJeff Mahoney 204bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 205ee611138SDavid Sterba return -EROFS; 206ee611138SDavid Sterba 207ba631941SJeff Mahoney ret = kstrtoul(skip_spaces(buf), 0, &val); 208ba631941SJeff Mahoney if (ret) 209ba631941SJeff Mahoney return ret; 210ba631941SJeff Mahoney 211ba631941SJeff Mahoney if (fa->feature_set == FEAT_COMPAT) { 212ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 213ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 214ba631941SJeff Mahoney } else if (fa->feature_set == FEAT_COMPAT_RO) { 215ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 216ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 217ba631941SJeff Mahoney } else { 218ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 219ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 220ba631941SJeff Mahoney } 221ba631941SJeff Mahoney 222ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 223ba631941SJeff Mahoney 224ba631941SJeff Mahoney /* Nothing to do */ 225ba631941SJeff Mahoney if ((val && (features & fa->feature_bit)) || 226ba631941SJeff Mahoney (!val && !(features & fa->feature_bit))) 227ba631941SJeff Mahoney return count; 228ba631941SJeff Mahoney 229ba631941SJeff Mahoney if ((val && !(set & fa->feature_bit)) || 230ba631941SJeff Mahoney (!val && !(clear & fa->feature_bit))) { 231ba631941SJeff Mahoney btrfs_info(fs_info, 232ba631941SJeff Mahoney "%sabling feature %s on mounted fs is not supported.", 233ba631941SJeff Mahoney val ? "En" : "Dis", fa->kobj_attr.attr.name); 234ba631941SJeff Mahoney return -EPERM; 235ba631941SJeff Mahoney } 236ba631941SJeff Mahoney 237ba631941SJeff Mahoney btrfs_info(fs_info, "%s %s feature flag", 238ba631941SJeff Mahoney val ? "Setting" : "Clearing", fa->kobj_attr.attr.name); 239ba631941SJeff Mahoney 240ba631941SJeff Mahoney spin_lock(&fs_info->super_lock); 241ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 242ba631941SJeff Mahoney if (val) 243ba631941SJeff Mahoney features |= fa->feature_bit; 244ba631941SJeff Mahoney else 245ba631941SJeff Mahoney features &= ~fa->feature_bit; 246ba631941SJeff Mahoney set_features(fs_info, fa->feature_set, features); 247ba631941SJeff Mahoney spin_unlock(&fs_info->super_lock); 248ba631941SJeff Mahoney 2490eae2747SDavid Sterba /* 2500eae2747SDavid Sterba * We don't want to do full transaction commit from inside sysfs 2510eae2747SDavid Sterba */ 252*c52cc7b7SJosef Bacik set_bit(BTRFS_FS_NEED_TRANS_COMMIT, &fs_info->flags); 2530eae2747SDavid Sterba wake_up_process(fs_info->transaction_kthread); 254ba631941SJeff Mahoney 255ba631941SJeff Mahoney return count; 256ba631941SJeff Mahoney } 257ba631941SJeff Mahoney 258510d7360SJeff Mahoney static umode_t btrfs_feature_visible(struct kobject *kobj, 259510d7360SJeff Mahoney struct attribute *attr, int unused) 260510d7360SJeff Mahoney { 261510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 262510d7360SJeff Mahoney umode_t mode = attr->mode; 263510d7360SJeff Mahoney 264510d7360SJeff Mahoney if (fs_info) { 265510d7360SJeff Mahoney struct btrfs_feature_attr *fa; 266510d7360SJeff Mahoney u64 features; 267510d7360SJeff Mahoney 268510d7360SJeff Mahoney fa = attr_to_btrfs_feature_attr(attr); 269510d7360SJeff Mahoney features = get_features(fs_info, fa->feature_set); 270510d7360SJeff Mahoney 271ba631941SJeff Mahoney if (can_modify_feature(fa)) 272ba631941SJeff Mahoney mode |= S_IWUSR; 273ba631941SJeff Mahoney else if (!(features & fa->feature_bit)) 274510d7360SJeff Mahoney mode = 0; 275510d7360SJeff Mahoney } 276510d7360SJeff Mahoney 277510d7360SJeff Mahoney return mode; 278079b72bcSJeff Mahoney } 279079b72bcSJeff Mahoney 280079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL); 281079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS); 282079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO); 2835c1aab1dSNick Terrell BTRFS_FEAT_ATTR_INCOMPAT(compress_zstd, COMPRESS_ZSTD); 284079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF); 285079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56); 286079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA); 287c736c095SDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES); 28856f20f40SNikolay Borisov BTRFS_FEAT_ATTR_INCOMPAT(metadata_uuid, METADATA_UUID); 2893b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE); 2901c56ab99SQu Wenruo BTRFS_FEAT_ATTR_COMPAT_RO(block_group_tree, BLOCK_GROUP_TREE); 291cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(raid1c34, RAID1C34); 29215dcccdbSDavid Sterba #ifdef CONFIG_BLK_DEV_ZONED 2937b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_INCOMPAT(zoned, ZONED); 29415dcccdbSDavid Sterba #endif 29515dcccdbSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 2962c7d2a23SJosef Bacik /* Remove once support for extent tree v2 is feature complete */ 2972c7d2a23SJosef Bacik BTRFS_FEAT_ATTR_INCOMPAT(extent_tree_v2, EXTENT_TREE_V2); 2987b3d5a90SNaohiro Aota #endif 29914605409SBoris Burkov #ifdef CONFIG_FS_VERITY 30014605409SBoris Burkov BTRFS_FEAT_ATTR_COMPAT_RO(verity, VERITY); 30114605409SBoris Burkov #endif 302079b72bcSJeff Mahoney 303e7849e33SAnand Jain /* 304e7849e33SAnand Jain * Features which depend on feature bits and may differ between each fs. 305e7849e33SAnand Jain * 306143823cfSDavid Sterba * /sys/fs/btrfs/features - all available features implemented by this version 307e7849e33SAnand Jain * /sys/fs/btrfs/UUID/features - features of the fs which are enabled or 308e7849e33SAnand Jain * can be changed on a mounted filesystem. 309e7849e33SAnand Jain */ 310079b72bcSJeff Mahoney static struct attribute *btrfs_supported_feature_attrs[] = { 311079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(default_subvol), 312079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_groups), 313079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(compress_lzo), 3145c1aab1dSNick Terrell BTRFS_FEAT_ATTR_PTR(compress_zstd), 315079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(extended_iref), 316079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(raid56), 317079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(skinny_metadata), 318c736c095SDavid Sterba BTRFS_FEAT_ATTR_PTR(no_holes), 31956f20f40SNikolay Borisov BTRFS_FEAT_ATTR_PTR(metadata_uuid), 3203b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_PTR(free_space_tree), 321cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_PTR(raid1c34), 3221c56ab99SQu Wenruo BTRFS_FEAT_ATTR_PTR(block_group_tree), 32315dcccdbSDavid Sterba #ifdef CONFIG_BLK_DEV_ZONED 3247b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_PTR(zoned), 32515dcccdbSDavid Sterba #endif 32615dcccdbSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 3272c7d2a23SJosef Bacik BTRFS_FEAT_ATTR_PTR(extent_tree_v2), 3287b3d5a90SNaohiro Aota #endif 32914605409SBoris Burkov #ifdef CONFIG_FS_VERITY 33014605409SBoris Burkov BTRFS_FEAT_ATTR_PTR(verity), 33114605409SBoris Burkov #endif 332079b72bcSJeff Mahoney NULL 333079b72bcSJeff Mahoney }; 334079b72bcSJeff Mahoney 335079b72bcSJeff Mahoney static const struct attribute_group btrfs_feature_attr_group = { 336079b72bcSJeff Mahoney .name = "features", 337510d7360SJeff Mahoney .is_visible = btrfs_feature_visible, 338079b72bcSJeff Mahoney .attrs = btrfs_supported_feature_attrs, 339079b72bcSJeff Mahoney }; 34058176a96SJosef Bacik 341f902bd3aSMisono Tomohiro static ssize_t rmdir_subvol_show(struct kobject *kobj, 342f902bd3aSMisono Tomohiro struct kobj_attribute *ka, char *buf) 343f902bd3aSMisono Tomohiro { 344020e5277SAnand Jain return sysfs_emit(buf, "0\n"); 345f902bd3aSMisono Tomohiro } 346f902bd3aSMisono Tomohiro BTRFS_ATTR(static_feature, rmdir_subvol, rmdir_subvol_show); 347f902bd3aSMisono Tomohiro 348f7cea56cSDavid Sterba static ssize_t supported_checksums_show(struct kobject *kobj, 349f7cea56cSDavid Sterba struct kobj_attribute *a, char *buf) 350f7cea56cSDavid Sterba { 351f7cea56cSDavid Sterba ssize_t ret = 0; 352f7cea56cSDavid Sterba int i; 353f7cea56cSDavid Sterba 354f7cea56cSDavid Sterba for (i = 0; i < btrfs_get_num_csums(); i++) { 355f7cea56cSDavid Sterba /* 356f7cea56cSDavid Sterba * This "trick" only works as long as 'enum btrfs_csum_type' has 357f7cea56cSDavid Sterba * no holes in it 358f7cea56cSDavid Sterba */ 359020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i == 0 ? "" : " "), 360020e5277SAnand Jain btrfs_super_csum_name(i)); 361f7cea56cSDavid Sterba 362f7cea56cSDavid Sterba } 363f7cea56cSDavid Sterba 364020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 365f7cea56cSDavid Sterba return ret; 366f7cea56cSDavid Sterba } 367f7cea56cSDavid Sterba BTRFS_ATTR(static_feature, supported_checksums, supported_checksums_show); 368f7cea56cSDavid Sterba 3697573df55SOmar Sandoval static ssize_t send_stream_version_show(struct kobject *kobj, 3707573df55SOmar Sandoval struct kobj_attribute *ka, char *buf) 3717573df55SOmar Sandoval { 372020e5277SAnand Jain return sysfs_emit(buf, "%d\n", BTRFS_SEND_STREAM_VERSION); 3737573df55SOmar Sandoval } 3747573df55SOmar Sandoval BTRFS_ATTR(static_feature, send_stream_version, send_stream_version_show); 3757573df55SOmar Sandoval 376ceafe3ccSJosef Bacik static const char *rescue_opts[] = { 377ceafe3ccSJosef Bacik "usebackuproot", 378ceafe3ccSJosef Bacik "nologreplay", 37942437a63SJosef Bacik "ignorebadroots", 380882dbe0cSJosef Bacik "ignoredatacsums", 3819037d3cbSJosef Bacik "all", 382ceafe3ccSJosef Bacik }; 383ceafe3ccSJosef Bacik 384ceafe3ccSJosef Bacik static ssize_t supported_rescue_options_show(struct kobject *kobj, 385ceafe3ccSJosef Bacik struct kobj_attribute *a, 386ceafe3ccSJosef Bacik char *buf) 387ceafe3ccSJosef Bacik { 388ceafe3ccSJosef Bacik ssize_t ret = 0; 389ceafe3ccSJosef Bacik int i; 390ceafe3ccSJosef Bacik 391ceafe3ccSJosef Bacik for (i = 0; i < ARRAY_SIZE(rescue_opts); i++) 392020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i ? " " : ""), rescue_opts[i]); 393020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 394ceafe3ccSJosef Bacik return ret; 395ceafe3ccSJosef Bacik } 396ceafe3ccSJosef Bacik BTRFS_ATTR(static_feature, supported_rescue_options, 397ceafe3ccSJosef Bacik supported_rescue_options_show); 398ceafe3ccSJosef Bacik 399fc57ad8dSQu Wenruo static ssize_t supported_sectorsizes_show(struct kobject *kobj, 400fc57ad8dSQu Wenruo struct kobj_attribute *a, 401fc57ad8dSQu Wenruo char *buf) 402fc57ad8dSQu Wenruo { 403fc57ad8dSQu Wenruo ssize_t ret = 0; 404fc57ad8dSQu Wenruo 4051a42daabSQu Wenruo /* An artificial limit to only support 4K and PAGE_SIZE */ 4061a42daabSQu Wenruo if (PAGE_SIZE > SZ_4K) 407020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%u ", SZ_4K); 408020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%lu\n", PAGE_SIZE); 409fc57ad8dSQu Wenruo 410fc57ad8dSQu Wenruo return ret; 411fc57ad8dSQu Wenruo } 412fc57ad8dSQu Wenruo BTRFS_ATTR(static_feature, supported_sectorsizes, 413fc57ad8dSQu Wenruo supported_sectorsizes_show); 414fc57ad8dSQu Wenruo 415e7849e33SAnand Jain /* 416e7849e33SAnand Jain * Features which only depend on kernel version. 417e7849e33SAnand Jain * 418e7849e33SAnand Jain * These are listed in /sys/fs/btrfs/features along with 419e7849e33SAnand Jain * btrfs_supported_feature_attrs. 420e7849e33SAnand Jain */ 421f902bd3aSMisono Tomohiro static struct attribute *btrfs_supported_static_feature_attrs[] = { 422f902bd3aSMisono Tomohiro BTRFS_ATTR_PTR(static_feature, rmdir_subvol), 423f7cea56cSDavid Sterba BTRFS_ATTR_PTR(static_feature, supported_checksums), 4247573df55SOmar Sandoval BTRFS_ATTR_PTR(static_feature, send_stream_version), 425ceafe3ccSJosef Bacik BTRFS_ATTR_PTR(static_feature, supported_rescue_options), 426fc57ad8dSQu Wenruo BTRFS_ATTR_PTR(static_feature, supported_sectorsizes), 427f902bd3aSMisono Tomohiro NULL 428f902bd3aSMisono Tomohiro }; 429f902bd3aSMisono Tomohiro 430f902bd3aSMisono Tomohiro static const struct attribute_group btrfs_static_feature_attr_group = { 431f902bd3aSMisono Tomohiro .name = "features", 432f902bd3aSMisono Tomohiro .attrs = btrfs_supported_static_feature_attrs, 433f902bd3aSMisono Tomohiro }; 434f902bd3aSMisono Tomohiro 4356e369febSDavid Sterba /* 436e4faab84SDennis Zhou * Discard statistics and tunables 437e4faab84SDennis Zhou */ 438fb731430SDavid Sterba #define discard_to_fs_info(_kobj) to_fs_info(get_btrfs_kobj(_kobj)) 439dfb79ddbSDennis Zhou 4405dc7c10bSDennis Zhou static ssize_t btrfs_discardable_bytes_show(struct kobject *kobj, 4415dc7c10bSDennis Zhou struct kobj_attribute *a, 4425dc7c10bSDennis Zhou char *buf) 4435dc7c10bSDennis Zhou { 4445dc7c10bSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4455dc7c10bSDennis Zhou 446020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4475dc7c10bSDennis Zhou atomic64_read(&fs_info->discard_ctl.discardable_bytes)); 4485dc7c10bSDennis Zhou } 4495dc7c10bSDennis Zhou BTRFS_ATTR(discard, discardable_bytes, btrfs_discardable_bytes_show); 4505dc7c10bSDennis Zhou 451dfb79ddbSDennis Zhou static ssize_t btrfs_discardable_extents_show(struct kobject *kobj, 452dfb79ddbSDennis Zhou struct kobj_attribute *a, 453dfb79ddbSDennis Zhou char *buf) 454dfb79ddbSDennis Zhou { 455dfb79ddbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 456dfb79ddbSDennis Zhou 457020e5277SAnand Jain return sysfs_emit(buf, "%d\n", 458dfb79ddbSDennis Zhou atomic_read(&fs_info->discard_ctl.discardable_extents)); 459dfb79ddbSDennis Zhou } 460dfb79ddbSDennis Zhou BTRFS_ATTR(discard, discardable_extents, btrfs_discardable_extents_show); 461dfb79ddbSDennis Zhou 4629ddf648fSDennis Zhou static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj, 4639ddf648fSDennis Zhou struct kobj_attribute *a, 4649ddf648fSDennis Zhou char *buf) 4659ddf648fSDennis Zhou { 4669ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4679ddf648fSDennis Zhou 468020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4699ddf648fSDennis Zhou fs_info->discard_ctl.discard_bitmap_bytes); 4709ddf648fSDennis Zhou } 4719ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bitmap_bytes, btrfs_discard_bitmap_bytes_show); 4729ddf648fSDennis Zhou 4739ddf648fSDennis Zhou static ssize_t btrfs_discard_bytes_saved_show(struct kobject *kobj, 4749ddf648fSDennis Zhou struct kobj_attribute *a, 4759ddf648fSDennis Zhou char *buf) 4769ddf648fSDennis Zhou { 4779ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4789ddf648fSDennis Zhou 479020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4809ddf648fSDennis Zhou atomic64_read(&fs_info->discard_ctl.discard_bytes_saved)); 4819ddf648fSDennis Zhou } 4829ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bytes_saved, btrfs_discard_bytes_saved_show); 4839ddf648fSDennis Zhou 4849ddf648fSDennis Zhou static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj, 4859ddf648fSDennis Zhou struct kobj_attribute *a, 4869ddf648fSDennis Zhou char *buf) 4879ddf648fSDennis Zhou { 4889ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4899ddf648fSDennis Zhou 490020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4919ddf648fSDennis Zhou fs_info->discard_ctl.discard_extent_bytes); 4929ddf648fSDennis Zhou } 4939ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_extent_bytes, btrfs_discard_extent_bytes_show); 4949ddf648fSDennis Zhou 495a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_show(struct kobject *kobj, 496a2309300SDennis Zhou struct kobj_attribute *a, 497a2309300SDennis Zhou char *buf) 498a2309300SDennis Zhou { 499a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 500a2309300SDennis Zhou 501020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 502a2309300SDennis Zhou READ_ONCE(fs_info->discard_ctl.iops_limit)); 503a2309300SDennis Zhou } 504a2309300SDennis Zhou 505a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_store(struct kobject *kobj, 506a2309300SDennis Zhou struct kobj_attribute *a, 507a2309300SDennis Zhou const char *buf, size_t len) 508a2309300SDennis Zhou { 509a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 510a2309300SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 511a2309300SDennis Zhou u32 iops_limit; 512a2309300SDennis Zhou int ret; 513a2309300SDennis Zhou 514a2309300SDennis Zhou ret = kstrtou32(buf, 10, &iops_limit); 515a2309300SDennis Zhou if (ret) 516a2309300SDennis Zhou return -EINVAL; 517a2309300SDennis Zhou 518a2309300SDennis Zhou WRITE_ONCE(discard_ctl->iops_limit, iops_limit); 5193e48d8d2SPavel Begunkov btrfs_discard_calc_delay(discard_ctl); 5203e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 521a2309300SDennis Zhou return len; 522a2309300SDennis Zhou } 523a2309300SDennis Zhou BTRFS_ATTR_RW(discard, iops_limit, btrfs_discard_iops_limit_show, 524a2309300SDennis Zhou btrfs_discard_iops_limit_store); 525a2309300SDennis Zhou 526e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_show(struct kobject *kobj, 527e93591bbSDennis Zhou struct kobj_attribute *a, 528e93591bbSDennis Zhou char *buf) 529e93591bbSDennis Zhou { 530e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 531e93591bbSDennis Zhou 532020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 533e93591bbSDennis Zhou READ_ONCE(fs_info->discard_ctl.kbps_limit)); 534e93591bbSDennis Zhou } 535e93591bbSDennis Zhou 536e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_store(struct kobject *kobj, 537e93591bbSDennis Zhou struct kobj_attribute *a, 538e93591bbSDennis Zhou const char *buf, size_t len) 539e93591bbSDennis Zhou { 540e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 541e93591bbSDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 542e93591bbSDennis Zhou u32 kbps_limit; 543e93591bbSDennis Zhou int ret; 544e93591bbSDennis Zhou 545e93591bbSDennis Zhou ret = kstrtou32(buf, 10, &kbps_limit); 546e93591bbSDennis Zhou if (ret) 547e93591bbSDennis Zhou return -EINVAL; 548e93591bbSDennis Zhou 549e93591bbSDennis Zhou WRITE_ONCE(discard_ctl->kbps_limit, kbps_limit); 5503e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 551e93591bbSDennis Zhou return len; 552e93591bbSDennis Zhou } 553e93591bbSDennis Zhou BTRFS_ATTR_RW(discard, kbps_limit, btrfs_discard_kbps_limit_show, 554e93591bbSDennis Zhou btrfs_discard_kbps_limit_store); 555e93591bbSDennis Zhou 55619b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_show(struct kobject *kobj, 55719b2a2c7SDennis Zhou struct kobj_attribute *a, 55819b2a2c7SDennis Zhou char *buf) 55919b2a2c7SDennis Zhou { 56019b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 56119b2a2c7SDennis Zhou 562020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 56319b2a2c7SDennis Zhou READ_ONCE(fs_info->discard_ctl.max_discard_size)); 56419b2a2c7SDennis Zhou } 56519b2a2c7SDennis Zhou 56619b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_store(struct kobject *kobj, 56719b2a2c7SDennis Zhou struct kobj_attribute *a, 56819b2a2c7SDennis Zhou const char *buf, size_t len) 56919b2a2c7SDennis Zhou { 57019b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 57119b2a2c7SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 57219b2a2c7SDennis Zhou u64 max_discard_size; 57319b2a2c7SDennis Zhou int ret; 57419b2a2c7SDennis Zhou 57519b2a2c7SDennis Zhou ret = kstrtou64(buf, 10, &max_discard_size); 57619b2a2c7SDennis Zhou if (ret) 57719b2a2c7SDennis Zhou return -EINVAL; 57819b2a2c7SDennis Zhou 57919b2a2c7SDennis Zhou WRITE_ONCE(discard_ctl->max_discard_size, max_discard_size); 58019b2a2c7SDennis Zhou 58119b2a2c7SDennis Zhou return len; 58219b2a2c7SDennis Zhou } 58319b2a2c7SDennis Zhou BTRFS_ATTR_RW(discard, max_discard_size, btrfs_discard_max_discard_size_show, 58419b2a2c7SDennis Zhou btrfs_discard_max_discard_size_store); 58519b2a2c7SDennis Zhou 586e7849e33SAnand Jain /* 587fb731430SDavid Sterba * Per-filesystem stats for discard (when mounted with discard=async). 588e7849e33SAnand Jain * 589fb731430SDavid Sterba * Path: /sys/fs/btrfs/<uuid>/discard/ 590e7849e33SAnand Jain */ 591fb731430SDavid Sterba static const struct attribute *discard_attrs[] = { 5925dc7c10bSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_bytes), 593dfb79ddbSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_extents), 5949ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bitmap_bytes), 5959ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bytes_saved), 5969ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_extent_bytes), 597a2309300SDennis Zhou BTRFS_ATTR_PTR(discard, iops_limit), 598e93591bbSDennis Zhou BTRFS_ATTR_PTR(discard, kbps_limit), 59919b2a2c7SDennis Zhou BTRFS_ATTR_PTR(discard, max_discard_size), 600e4faab84SDennis Zhou NULL, 601e4faab84SDennis Zhou }; 602e4faab84SDennis Zhou 603fb731430SDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 604fb731430SDavid Sterba 605e4faab84SDennis Zhou /* 606e7849e33SAnand Jain * Per-filesystem runtime debugging exported via sysfs. 6076e369febSDavid Sterba * 608e7849e33SAnand Jain * Path: /sys/fs/btrfs/UUID/debug/ 6096e369febSDavid Sterba */ 61093945cb4SDennis Zhou static const struct attribute *btrfs_debug_mount_attrs[] = { 61193945cb4SDennis Zhou NULL, 61293945cb4SDennis Zhou }; 61393945cb4SDennis Zhou 614e7849e33SAnand Jain /* 615e7849e33SAnand Jain * Runtime debugging exported via sysfs, applies to all mounted filesystems. 616e7849e33SAnand Jain * 617e7849e33SAnand Jain * Path: /sys/fs/btrfs/debug 618e7849e33SAnand Jain */ 6196e369febSDavid Sterba static struct attribute *btrfs_debug_feature_attrs[] = { 6206e369febSDavid Sterba NULL 6216e369febSDavid Sterba }; 6226e369febSDavid Sterba 6236e369febSDavid Sterba static const struct attribute_group btrfs_debug_feature_attr_group = { 6246e369febSDavid Sterba .name = "debug", 6256e369febSDavid Sterba .attrs = btrfs_debug_feature_attrs, 6266e369febSDavid Sterba }; 6276e369febSDavid Sterba 6286e369febSDavid Sterba #endif 6296e369febSDavid Sterba 6306ab0a202SJeff Mahoney static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf) 6316ab0a202SJeff Mahoney { 6326ab0a202SJeff Mahoney u64 val; 6336ab0a202SJeff Mahoney if (lock) 6346ab0a202SJeff Mahoney spin_lock(lock); 6356ab0a202SJeff Mahoney val = *value_ptr; 6366ab0a202SJeff Mahoney if (lock) 6376ab0a202SJeff Mahoney spin_unlock(lock); 638020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6396ab0a202SJeff Mahoney } 6406ab0a202SJeff Mahoney 6416ab0a202SJeff Mahoney static ssize_t global_rsv_size_show(struct kobject *kobj, 6426ab0a202SJeff Mahoney struct kobj_attribute *ka, char *buf) 6436ab0a202SJeff Mahoney { 6446ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6456ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6466ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf); 6476ab0a202SJeff Mahoney } 648a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_size, global_rsv_size_show); 6496ab0a202SJeff Mahoney 6506ab0a202SJeff Mahoney static ssize_t global_rsv_reserved_show(struct kobject *kobj, 6516ab0a202SJeff Mahoney struct kobj_attribute *a, char *buf) 6526ab0a202SJeff Mahoney { 6536ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6546ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6556ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf); 6566ab0a202SJeff Mahoney } 657a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_reserved, global_rsv_reserved_show); 6586ab0a202SJeff Mahoney 6596ab0a202SJeff Mahoney #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj) 660c1895442SJeff Mahoney #define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj) 6616ab0a202SJeff Mahoney 6626ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6636ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf); 664a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, total_bytes, raid_bytes_show); 665a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, used_bytes, raid_bytes_show); 6666ab0a202SJeff Mahoney 6676ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6686ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf) 6696ab0a202SJeff Mahoney 6706ab0a202SJeff Mahoney { 6716ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj->parent); 67232da5386SDavid Sterba struct btrfs_block_group *block_group; 67375cb379dSJeff Mahoney int index = btrfs_bg_flags_to_raid_index(to_raid_kobj(kobj)->flags); 6746ab0a202SJeff Mahoney u64 val = 0; 6756ab0a202SJeff Mahoney 6766ab0a202SJeff Mahoney down_read(&sinfo->groups_sem); 6776ab0a202SJeff Mahoney list_for_each_entry(block_group, &sinfo->block_groups[index], list) { 678a969f4ccSHans van Kranenburg if (&attr->attr == BTRFS_ATTR_PTR(raid, total_bytes)) 679b3470b5dSDavid Sterba val += block_group->length; 6806ab0a202SJeff Mahoney else 681bf38be65SDavid Sterba val += block_group->used; 6826ab0a202SJeff Mahoney } 6836ab0a202SJeff Mahoney up_read(&sinfo->groups_sem); 684020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6856ab0a202SJeff Mahoney } 6866ab0a202SJeff Mahoney 687e7849e33SAnand Jain /* 688e7849e33SAnand Jain * Allocation information about block group profiles. 689e7849e33SAnand Jain * 690e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/<bg-profile>/ 691e7849e33SAnand Jain */ 6927c7e3014SKimberly Brown static struct attribute *raid_attrs[] = { 693a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, total_bytes), 694a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, used_bytes), 6956ab0a202SJeff Mahoney NULL 6966ab0a202SJeff Mahoney }; 6977c7e3014SKimberly Brown ATTRIBUTE_GROUPS(raid); 6986ab0a202SJeff Mahoney 6996ab0a202SJeff Mahoney static void release_raid_kobj(struct kobject *kobj) 7006ab0a202SJeff Mahoney { 701c1895442SJeff Mahoney kfree(to_raid_kobj(kobj)); 7026ab0a202SJeff Mahoney } 7036ab0a202SJeff Mahoney 704536ea45cSDavid Sterba static struct kobj_type btrfs_raid_ktype = { 7056ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 7066ab0a202SJeff Mahoney .release = release_raid_kobj, 7077c7e3014SKimberly Brown .default_groups = raid_groups, 7086ab0a202SJeff Mahoney }; 7096ab0a202SJeff Mahoney 7106ab0a202SJeff Mahoney #define SPACE_INFO_ATTR(field) \ 7116ab0a202SJeff Mahoney static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \ 7126ab0a202SJeff Mahoney struct kobj_attribute *a, \ 7136ab0a202SJeff Mahoney char *buf) \ 7146ab0a202SJeff Mahoney { \ 7156ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); \ 7166ab0a202SJeff Mahoney return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \ 7176ab0a202SJeff Mahoney } \ 718a969f4ccSHans van Kranenburg BTRFS_ATTR(space_info, field, btrfs_space_info_show_##field) 7196ab0a202SJeff Mahoney 72019fc516aSStefan Roesch static ssize_t btrfs_chunk_size_show(struct kobject *kobj, 72119fc516aSStefan Roesch struct kobj_attribute *a, char *buf) 72219fc516aSStefan Roesch { 72319fc516aSStefan Roesch struct btrfs_space_info *sinfo = to_space_info(kobj); 72419fc516aSStefan Roesch 72519fc516aSStefan Roesch return sysfs_emit(buf, "%llu\n", READ_ONCE(sinfo->chunk_size)); 72619fc516aSStefan Roesch } 72719fc516aSStefan Roesch 72819fc516aSStefan Roesch /* 72919fc516aSStefan Roesch * Store new chunk size in space info. Can be called on a read-only filesystem. 73019fc516aSStefan Roesch * 73119fc516aSStefan Roesch * If the new chunk size value is larger than 10% of free space it is reduced 73219fc516aSStefan Roesch * to match that limit. Alignment must be to 256M and the system chunk size 73319fc516aSStefan Roesch * cannot be set. 73419fc516aSStefan Roesch */ 73519fc516aSStefan Roesch static ssize_t btrfs_chunk_size_store(struct kobject *kobj, 73619fc516aSStefan Roesch struct kobj_attribute *a, 73719fc516aSStefan Roesch const char *buf, size_t len) 73819fc516aSStefan Roesch { 73919fc516aSStefan Roesch struct btrfs_space_info *space_info = to_space_info(kobj); 74019fc516aSStefan Roesch struct btrfs_fs_info *fs_info = to_fs_info(get_btrfs_kobj(kobj)); 74119fc516aSStefan Roesch char *retptr; 74219fc516aSStefan Roesch u64 val; 74319fc516aSStefan Roesch 74419fc516aSStefan Roesch if (!capable(CAP_SYS_ADMIN)) 74519fc516aSStefan Roesch return -EPERM; 74619fc516aSStefan Roesch 74719fc516aSStefan Roesch if (!fs_info->fs_devices) 74819fc516aSStefan Roesch return -EINVAL; 74919fc516aSStefan Roesch 75019fc516aSStefan Roesch if (btrfs_is_zoned(fs_info)) 75119fc516aSStefan Roesch return -EINVAL; 75219fc516aSStefan Roesch 75319fc516aSStefan Roesch /* System block type must not be changed. */ 75419fc516aSStefan Roesch if (space_info->flags & BTRFS_BLOCK_GROUP_SYSTEM) 75519fc516aSStefan Roesch return -EPERM; 75619fc516aSStefan Roesch 75719fc516aSStefan Roesch val = memparse(buf, &retptr); 75819fc516aSStefan Roesch /* There could be trailing '\n', also catch any typos after the value */ 75919fc516aSStefan Roesch retptr = skip_spaces(retptr); 76019fc516aSStefan Roesch if (*retptr != 0 || val == 0) 76119fc516aSStefan Roesch return -EINVAL; 76219fc516aSStefan Roesch 76319fc516aSStefan Roesch val = min(val, BTRFS_MAX_DATA_CHUNK_SIZE); 76419fc516aSStefan Roesch 76519fc516aSStefan Roesch /* Limit stripe size to 10% of available space. */ 76619fc516aSStefan Roesch val = min(div_factor(fs_info->fs_devices->total_rw_bytes, 1), val); 76719fc516aSStefan Roesch 76819fc516aSStefan Roesch /* Must be multiple of 256M. */ 76919fc516aSStefan Roesch val &= ~((u64)SZ_256M - 1); 77019fc516aSStefan Roesch 77119fc516aSStefan Roesch /* Must be at least 256M. */ 77219fc516aSStefan Roesch if (val < SZ_256M) 77319fc516aSStefan Roesch return -EINVAL; 77419fc516aSStefan Roesch 77519fc516aSStefan Roesch btrfs_update_space_info_chunk_size(space_info, val); 77619fc516aSStefan Roesch 77719fc516aSStefan Roesch return len; 77819fc516aSStefan Roesch } 77919fc516aSStefan Roesch 78022c55e3bSStefan Roesch #ifdef CONFIG_BTRFS_DEBUG 78122c55e3bSStefan Roesch /* 78222c55e3bSStefan Roesch * Request chunk allocation with current chunk size. 78322c55e3bSStefan Roesch */ 78422c55e3bSStefan Roesch static ssize_t btrfs_force_chunk_alloc_store(struct kobject *kobj, 78522c55e3bSStefan Roesch struct kobj_attribute *a, 78622c55e3bSStefan Roesch const char *buf, size_t len) 78722c55e3bSStefan Roesch { 78822c55e3bSStefan Roesch struct btrfs_space_info *space_info = to_space_info(kobj); 78922c55e3bSStefan Roesch struct btrfs_fs_info *fs_info = to_fs_info(get_btrfs_kobj(kobj)); 79022c55e3bSStefan Roesch struct btrfs_trans_handle *trans; 79122c55e3bSStefan Roesch bool val; 79222c55e3bSStefan Roesch int ret; 79322c55e3bSStefan Roesch 79422c55e3bSStefan Roesch if (!capable(CAP_SYS_ADMIN)) 79522c55e3bSStefan Roesch return -EPERM; 79622c55e3bSStefan Roesch 79722c55e3bSStefan Roesch if (sb_rdonly(fs_info->sb)) 79822c55e3bSStefan Roesch return -EROFS; 79922c55e3bSStefan Roesch 80022c55e3bSStefan Roesch ret = kstrtobool(buf, &val); 80122c55e3bSStefan Roesch if (ret) 80222c55e3bSStefan Roesch return ret; 80322c55e3bSStefan Roesch 80422c55e3bSStefan Roesch if (!val) 80522c55e3bSStefan Roesch return -EINVAL; 80622c55e3bSStefan Roesch 80722c55e3bSStefan Roesch /* 80822c55e3bSStefan Roesch * This is unsafe to be called from sysfs context and may cause 80922c55e3bSStefan Roesch * unexpected problems. 81022c55e3bSStefan Roesch */ 81122c55e3bSStefan Roesch trans = btrfs_start_transaction(fs_info->tree_root, 0); 81222c55e3bSStefan Roesch if (IS_ERR(trans)) 81322c55e3bSStefan Roesch return PTR_ERR(trans); 81422c55e3bSStefan Roesch ret = btrfs_force_chunk_alloc(trans, space_info->flags); 81522c55e3bSStefan Roesch btrfs_end_transaction(trans); 81622c55e3bSStefan Roesch 81722c55e3bSStefan Roesch if (ret == 1) 81822c55e3bSStefan Roesch return len; 81922c55e3bSStefan Roesch 82022c55e3bSStefan Roesch return -ENOSPC; 82122c55e3bSStefan Roesch } 82222c55e3bSStefan Roesch BTRFS_ATTR_W(space_info, force_chunk_alloc, btrfs_force_chunk_alloc_store); 82322c55e3bSStefan Roesch 82422c55e3bSStefan Roesch #endif 82522c55e3bSStefan Roesch 8266ab0a202SJeff Mahoney SPACE_INFO_ATTR(flags); 8276ab0a202SJeff Mahoney SPACE_INFO_ATTR(total_bytes); 8286ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_used); 8296ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_pinned); 8306ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_reserved); 8316ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_may_use); 832c1fd5c30SWang Xiaoguang SPACE_INFO_ATTR(bytes_readonly); 833169e0da9SNaohiro Aota SPACE_INFO_ATTR(bytes_zone_unusable); 8346ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_used); 8356ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_total); 83619fc516aSStefan Roesch BTRFS_ATTR_RW(space_info, chunk_size, btrfs_chunk_size_show, btrfs_chunk_size_store); 8376ab0a202SJeff Mahoney 838bb5a098dSJosef Bacik static ssize_t btrfs_sinfo_bg_reclaim_threshold_show(struct kobject *kobj, 839bb5a098dSJosef Bacik struct kobj_attribute *a, 840bb5a098dSJosef Bacik char *buf) 841bb5a098dSJosef Bacik { 842bb5a098dSJosef Bacik struct btrfs_space_info *space_info = to_space_info(kobj); 843bb5a098dSJosef Bacik 844bd64f622Szhang songyi return sysfs_emit(buf, "%d\n", READ_ONCE(space_info->bg_reclaim_threshold)); 845bb5a098dSJosef Bacik } 846bb5a098dSJosef Bacik 847bb5a098dSJosef Bacik static ssize_t btrfs_sinfo_bg_reclaim_threshold_store(struct kobject *kobj, 848bb5a098dSJosef Bacik struct kobj_attribute *a, 849bb5a098dSJosef Bacik const char *buf, size_t len) 850bb5a098dSJosef Bacik { 851bb5a098dSJosef Bacik struct btrfs_space_info *space_info = to_space_info(kobj); 852bb5a098dSJosef Bacik int thresh; 853bb5a098dSJosef Bacik int ret; 854bb5a098dSJosef Bacik 855bb5a098dSJosef Bacik ret = kstrtoint(buf, 10, &thresh); 856bb5a098dSJosef Bacik if (ret) 857bb5a098dSJosef Bacik return ret; 858bb5a098dSJosef Bacik 859ef972e7bSJosef Bacik if (thresh < 0 || thresh > 100) 860bb5a098dSJosef Bacik return -EINVAL; 861bb5a098dSJosef Bacik 862bb5a098dSJosef Bacik WRITE_ONCE(space_info->bg_reclaim_threshold, thresh); 863bb5a098dSJosef Bacik 864bb5a098dSJosef Bacik return len; 865bb5a098dSJosef Bacik } 866bb5a098dSJosef Bacik 867bb5a098dSJosef Bacik BTRFS_ATTR_RW(space_info, bg_reclaim_threshold, 868bb5a098dSJosef Bacik btrfs_sinfo_bg_reclaim_threshold_show, 869bb5a098dSJosef Bacik btrfs_sinfo_bg_reclaim_threshold_store); 870bb5a098dSJosef Bacik 871e7849e33SAnand Jain /* 872e7849e33SAnand Jain * Allocation information about block group types. 873e7849e33SAnand Jain * 874e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/ 875e7849e33SAnand Jain */ 8766ab0a202SJeff Mahoney static struct attribute *space_info_attrs[] = { 877a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, flags), 878a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, total_bytes), 879a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_used), 880a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_pinned), 881a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_reserved), 882a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_may_use), 883a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_readonly), 884169e0da9SNaohiro Aota BTRFS_ATTR_PTR(space_info, bytes_zone_unusable), 885a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_used), 886a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_total), 887bb5a098dSJosef Bacik BTRFS_ATTR_PTR(space_info, bg_reclaim_threshold), 88819fc516aSStefan Roesch BTRFS_ATTR_PTR(space_info, chunk_size), 88922c55e3bSStefan Roesch #ifdef CONFIG_BTRFS_DEBUG 89022c55e3bSStefan Roesch BTRFS_ATTR_PTR(space_info, force_chunk_alloc), 89122c55e3bSStefan Roesch #endif 8926ab0a202SJeff Mahoney NULL, 8936ab0a202SJeff Mahoney }; 8947c7e3014SKimberly Brown ATTRIBUTE_GROUPS(space_info); 8956ab0a202SJeff Mahoney 8966ab0a202SJeff Mahoney static void space_info_release(struct kobject *kobj) 8976ab0a202SJeff Mahoney { 8986ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); 8996ab0a202SJeff Mahoney kfree(sinfo); 9006ab0a202SJeff Mahoney } 9016ab0a202SJeff Mahoney 90227992d01SDavid Sterba static struct kobj_type space_info_ktype = { 9036ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 9046ab0a202SJeff Mahoney .release = space_info_release, 9057c7e3014SKimberly Brown .default_groups = space_info_groups, 9066ab0a202SJeff Mahoney }; 9076ab0a202SJeff Mahoney 908e7849e33SAnand Jain /* 909e7849e33SAnand Jain * Allocation information about block groups. 910e7849e33SAnand Jain * 911e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/ 912e7849e33SAnand Jain */ 9136ab0a202SJeff Mahoney static const struct attribute *allocation_attrs[] = { 914a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_reserved), 915a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_size), 9166ab0a202SJeff Mahoney NULL, 9176ab0a202SJeff Mahoney }; 9186ab0a202SJeff Mahoney 919f8ba9c11SJeff Mahoney static ssize_t btrfs_label_show(struct kobject *kobj, 920f8ba9c11SJeff Mahoney struct kobj_attribute *a, char *buf) 921f8ba9c11SJeff Mahoney { 922f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 92348fcc3ffSSatoru Takeuchi char *label = fs_info->super_copy->label; 924ee17fc80SDavid Sterba ssize_t ret; 925ee17fc80SDavid Sterba 926ee17fc80SDavid Sterba spin_lock(&fs_info->super_lock); 927020e5277SAnand Jain ret = sysfs_emit(buf, label[0] ? "%s\n" : "%s", label); 928ee17fc80SDavid Sterba spin_unlock(&fs_info->super_lock); 929ee17fc80SDavid Sterba 930ee17fc80SDavid Sterba return ret; 931f8ba9c11SJeff Mahoney } 932f8ba9c11SJeff Mahoney 933f8ba9c11SJeff Mahoney static ssize_t btrfs_label_store(struct kobject *kobj, 934f8ba9c11SJeff Mahoney struct kobj_attribute *a, 935f8ba9c11SJeff Mahoney const char *buf, size_t len) 936f8ba9c11SJeff Mahoney { 937f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 93848fcc3ffSSatoru Takeuchi size_t p_len; 939f8ba9c11SJeff Mahoney 94066ac9fe7SDavid Sterba if (!fs_info) 94166ac9fe7SDavid Sterba return -EPERM; 94266ac9fe7SDavid Sterba 943bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 94479aec2b8SAnand Jain return -EROFS; 94579aec2b8SAnand Jain 94648fcc3ffSSatoru Takeuchi /* 94748fcc3ffSSatoru Takeuchi * p_len is the len until the first occurrence of either 94848fcc3ffSSatoru Takeuchi * '\n' or '\0' 94948fcc3ffSSatoru Takeuchi */ 95048fcc3ffSSatoru Takeuchi p_len = strcspn(buf, "\n"); 95148fcc3ffSSatoru Takeuchi 95248fcc3ffSSatoru Takeuchi if (p_len >= BTRFS_LABEL_SIZE) 953f8ba9c11SJeff Mahoney return -EINVAL; 954f8ba9c11SJeff Mahoney 955a6f69dc8SDavid Sterba spin_lock(&fs_info->super_lock); 95648fcc3ffSSatoru Takeuchi memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE); 95748fcc3ffSSatoru Takeuchi memcpy(fs_info->super_copy->label, buf, p_len); 958a6f69dc8SDavid Sterba spin_unlock(&fs_info->super_lock); 959f8ba9c11SJeff Mahoney 960a6f69dc8SDavid Sterba /* 961a6f69dc8SDavid Sterba * We don't want to do full transaction commit from inside sysfs 962a6f69dc8SDavid Sterba */ 963*c52cc7b7SJosef Bacik set_bit(BTRFS_FS_NEED_TRANS_COMMIT, &fs_info->flags); 964a6f69dc8SDavid Sterba wake_up_process(fs_info->transaction_kthread); 965a6f69dc8SDavid Sterba 966f8ba9c11SJeff Mahoney return len; 967f8ba9c11SJeff Mahoney } 968a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, label, btrfs_label_show, btrfs_label_store); 969f8ba9c11SJeff Mahoney 970df93589aSDavid Sterba static ssize_t btrfs_nodesize_show(struct kobject *kobj, 971df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 972df93589aSDavid Sterba { 973df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 974df93589aSDavid Sterba 975020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->nodesize); 976df93589aSDavid Sterba } 977df93589aSDavid Sterba 978a969f4ccSHans van Kranenburg BTRFS_ATTR(, nodesize, btrfs_nodesize_show); 979df93589aSDavid Sterba 980df93589aSDavid Sterba static ssize_t btrfs_sectorsize_show(struct kobject *kobj, 981df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 982df93589aSDavid Sterba { 983df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 984df93589aSDavid Sterba 985020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 986df93589aSDavid Sterba } 987df93589aSDavid Sterba 988a969f4ccSHans van Kranenburg BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show); 989df93589aSDavid Sterba 990140a8ff7SIoannis Angelakopoulos static ssize_t btrfs_commit_stats_show(struct kobject *kobj, 991140a8ff7SIoannis Angelakopoulos struct kobj_attribute *a, char *buf) 992140a8ff7SIoannis Angelakopoulos { 993140a8ff7SIoannis Angelakopoulos struct btrfs_fs_info *fs_info = to_fs_info(kobj); 994140a8ff7SIoannis Angelakopoulos 995140a8ff7SIoannis Angelakopoulos return sysfs_emit(buf, 996140a8ff7SIoannis Angelakopoulos "commits %llu\n" 997140a8ff7SIoannis Angelakopoulos "last_commit_ms %llu\n" 998140a8ff7SIoannis Angelakopoulos "max_commit_ms %llu\n" 999140a8ff7SIoannis Angelakopoulos "total_commit_ms %llu\n", 1000140a8ff7SIoannis Angelakopoulos fs_info->commit_stats.commit_count, 1001140a8ff7SIoannis Angelakopoulos div_u64(fs_info->commit_stats.last_commit_dur, NSEC_PER_MSEC), 1002140a8ff7SIoannis Angelakopoulos div_u64(fs_info->commit_stats.max_commit_dur, NSEC_PER_MSEC), 1003140a8ff7SIoannis Angelakopoulos div_u64(fs_info->commit_stats.total_commit_dur, NSEC_PER_MSEC)); 1004140a8ff7SIoannis Angelakopoulos } 1005140a8ff7SIoannis Angelakopoulos 1006140a8ff7SIoannis Angelakopoulos static ssize_t btrfs_commit_stats_store(struct kobject *kobj, 1007140a8ff7SIoannis Angelakopoulos struct kobj_attribute *a, 1008140a8ff7SIoannis Angelakopoulos const char *buf, size_t len) 1009140a8ff7SIoannis Angelakopoulos { 1010140a8ff7SIoannis Angelakopoulos struct btrfs_fs_info *fs_info = to_fs_info(kobj); 1011140a8ff7SIoannis Angelakopoulos unsigned long val; 1012140a8ff7SIoannis Angelakopoulos int ret; 1013140a8ff7SIoannis Angelakopoulos 1014140a8ff7SIoannis Angelakopoulos if (!fs_info) 1015140a8ff7SIoannis Angelakopoulos return -EPERM; 1016140a8ff7SIoannis Angelakopoulos 1017140a8ff7SIoannis Angelakopoulos if (!capable(CAP_SYS_RESOURCE)) 1018140a8ff7SIoannis Angelakopoulos return -EPERM; 1019140a8ff7SIoannis Angelakopoulos 1020140a8ff7SIoannis Angelakopoulos ret = kstrtoul(buf, 10, &val); 1021140a8ff7SIoannis Angelakopoulos if (ret) 1022140a8ff7SIoannis Angelakopoulos return ret; 1023140a8ff7SIoannis Angelakopoulos if (val) 1024140a8ff7SIoannis Angelakopoulos return -EINVAL; 1025140a8ff7SIoannis Angelakopoulos 1026140a8ff7SIoannis Angelakopoulos WRITE_ONCE(fs_info->commit_stats.max_commit_dur, 0); 1027140a8ff7SIoannis Angelakopoulos 1028140a8ff7SIoannis Angelakopoulos return len; 1029140a8ff7SIoannis Angelakopoulos } 1030140a8ff7SIoannis Angelakopoulos BTRFS_ATTR_RW(, commit_stats, btrfs_commit_stats_show, btrfs_commit_stats_store); 1031140a8ff7SIoannis Angelakopoulos 1032df93589aSDavid Sterba static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, 1033df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 1034df93589aSDavid Sterba { 1035df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 1036df93589aSDavid Sterba 1037020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 1038df93589aSDavid Sterba } 1039df93589aSDavid Sterba 1040a969f4ccSHans van Kranenburg BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show); 1041df93589aSDavid Sterba 10422723480aSSargun Dhillon static ssize_t quota_override_show(struct kobject *kobj, 10432723480aSSargun Dhillon struct kobj_attribute *a, char *buf) 10442723480aSSargun Dhillon { 10452723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 10462723480aSSargun Dhillon int quota_override; 10472723480aSSargun Dhillon 10482723480aSSargun Dhillon quota_override = test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 1049020e5277SAnand Jain return sysfs_emit(buf, "%d\n", quota_override); 10502723480aSSargun Dhillon } 10512723480aSSargun Dhillon 10522723480aSSargun Dhillon static ssize_t quota_override_store(struct kobject *kobj, 10532723480aSSargun Dhillon struct kobj_attribute *a, 10542723480aSSargun Dhillon const char *buf, size_t len) 10552723480aSSargun Dhillon { 10562723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 10572723480aSSargun Dhillon unsigned long knob; 10582723480aSSargun Dhillon int err; 10592723480aSSargun Dhillon 10602723480aSSargun Dhillon if (!fs_info) 10612723480aSSargun Dhillon return -EPERM; 10622723480aSSargun Dhillon 10632723480aSSargun Dhillon if (!capable(CAP_SYS_RESOURCE)) 10642723480aSSargun Dhillon return -EPERM; 10652723480aSSargun Dhillon 10662723480aSSargun Dhillon err = kstrtoul(buf, 10, &knob); 10672723480aSSargun Dhillon if (err) 10682723480aSSargun Dhillon return err; 10692723480aSSargun Dhillon if (knob > 1) 10702723480aSSargun Dhillon return -EINVAL; 10712723480aSSargun Dhillon 10722723480aSSargun Dhillon if (knob) 10732723480aSSargun Dhillon set_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 10742723480aSSargun Dhillon else 10752723480aSSargun Dhillon clear_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 10762723480aSSargun Dhillon 10772723480aSSargun Dhillon return len; 10782723480aSSargun Dhillon } 10792723480aSSargun Dhillon 1080a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, quota_override, quota_override_show, quota_override_store); 10812723480aSSargun Dhillon 108256f20f40SNikolay Borisov static ssize_t btrfs_metadata_uuid_show(struct kobject *kobj, 108356f20f40SNikolay Borisov struct kobj_attribute *a, char *buf) 108456f20f40SNikolay Borisov { 108556f20f40SNikolay Borisov struct btrfs_fs_info *fs_info = to_fs_info(kobj); 108656f20f40SNikolay Borisov 1087020e5277SAnand Jain return sysfs_emit(buf, "%pU\n", fs_info->fs_devices->metadata_uuid); 108856f20f40SNikolay Borisov } 108956f20f40SNikolay Borisov 109056f20f40SNikolay Borisov BTRFS_ATTR(, metadata_uuid, btrfs_metadata_uuid_show); 109156f20f40SNikolay Borisov 109241e6d2a8SJohannes Thumshirn static ssize_t btrfs_checksum_show(struct kobject *kobj, 109341e6d2a8SJohannes Thumshirn struct kobj_attribute *a, char *buf) 109441e6d2a8SJohannes Thumshirn { 109541e6d2a8SJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 109641e6d2a8SJohannes Thumshirn u16 csum_type = btrfs_super_csum_type(fs_info->super_copy); 109741e6d2a8SJohannes Thumshirn 1098020e5277SAnand Jain return sysfs_emit(buf, "%s (%s)\n", 109941e6d2a8SJohannes Thumshirn btrfs_super_csum_name(csum_type), 110041e6d2a8SJohannes Thumshirn crypto_shash_driver_name(fs_info->csum_shash)); 110141e6d2a8SJohannes Thumshirn } 110241e6d2a8SJohannes Thumshirn 110341e6d2a8SJohannes Thumshirn BTRFS_ATTR(, checksum, btrfs_checksum_show); 110441e6d2a8SJohannes Thumshirn 110566a2823cSGoldwyn Rodrigues static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj, 110666a2823cSGoldwyn Rodrigues struct kobj_attribute *a, char *buf) 110766a2823cSGoldwyn Rodrigues { 110866a2823cSGoldwyn Rodrigues struct btrfs_fs_info *fs_info = to_fs_info(kobj); 110966a2823cSGoldwyn Rodrigues const char *str; 111066a2823cSGoldwyn Rodrigues 111166a2823cSGoldwyn Rodrigues switch (READ_ONCE(fs_info->exclusive_operation)) { 111266a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_NONE: 111366a2823cSGoldwyn Rodrigues str = "none\n"; 111466a2823cSGoldwyn Rodrigues break; 111566a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_BALANCE: 111666a2823cSGoldwyn Rodrigues str = "balance\n"; 111766a2823cSGoldwyn Rodrigues break; 11183e1ad196SDavid Sterba case BTRFS_EXCLOP_BALANCE_PAUSED: 11193e1ad196SDavid Sterba str = "balance paused\n"; 11203e1ad196SDavid Sterba break; 112166a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_ADD: 112266a2823cSGoldwyn Rodrigues str = "device add\n"; 112366a2823cSGoldwyn Rodrigues break; 112466a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REMOVE: 112566a2823cSGoldwyn Rodrigues str = "device remove\n"; 112666a2823cSGoldwyn Rodrigues break; 112766a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REPLACE: 112866a2823cSGoldwyn Rodrigues str = "device replace\n"; 112966a2823cSGoldwyn Rodrigues break; 113066a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_RESIZE: 113166a2823cSGoldwyn Rodrigues str = "resize\n"; 113266a2823cSGoldwyn Rodrigues break; 113366a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_SWAP_ACTIVATE: 113466a2823cSGoldwyn Rodrigues str = "swap activate\n"; 113566a2823cSGoldwyn Rodrigues break; 113666a2823cSGoldwyn Rodrigues default: 113766a2823cSGoldwyn Rodrigues str = "UNKNOWN\n"; 113866a2823cSGoldwyn Rodrigues break; 113966a2823cSGoldwyn Rodrigues } 1140020e5277SAnand Jain return sysfs_emit(buf, "%s", str); 114166a2823cSGoldwyn Rodrigues } 114266a2823cSGoldwyn Rodrigues BTRFS_ATTR(, exclusive_operation, btrfs_exclusive_operation_show); 114366a2823cSGoldwyn Rodrigues 1144089c8b05SAnand Jain static ssize_t btrfs_generation_show(struct kobject *kobj, 1145089c8b05SAnand Jain struct kobj_attribute *a, char *buf) 1146089c8b05SAnand Jain { 1147089c8b05SAnand Jain struct btrfs_fs_info *fs_info = to_fs_info(kobj); 1148089c8b05SAnand Jain 1149020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", fs_info->generation); 1150089c8b05SAnand Jain } 1151089c8b05SAnand Jain BTRFS_ATTR(, generation, btrfs_generation_show); 1152089c8b05SAnand Jain 11533d8cc17aSAnand Jain static const char * const btrfs_read_policy_name[] = { "pid" }; 11543d8cc17aSAnand Jain 11553d8cc17aSAnand Jain static ssize_t btrfs_read_policy_show(struct kobject *kobj, 11563d8cc17aSAnand Jain struct kobj_attribute *a, char *buf) 11573d8cc17aSAnand Jain { 11583d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 11593d8cc17aSAnand Jain ssize_t ret = 0; 11603d8cc17aSAnand Jain int i; 11613d8cc17aSAnand Jain 11623d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 11633d8cc17aSAnand Jain if (fs_devices->read_policy == i) 1164467761f9SDavid Sterba ret += sysfs_emit_at(buf, ret, "%s[%s]", 11653d8cc17aSAnand Jain (ret == 0 ? "" : " "), 11663d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11673d8cc17aSAnand Jain else 1168467761f9SDavid Sterba ret += sysfs_emit_at(buf, ret, "%s%s", 11693d8cc17aSAnand Jain (ret == 0 ? "" : " "), 11703d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11713d8cc17aSAnand Jain } 11723d8cc17aSAnand Jain 1173467761f9SDavid Sterba ret += sysfs_emit_at(buf, ret, "\n"); 11743d8cc17aSAnand Jain 11753d8cc17aSAnand Jain return ret; 11763d8cc17aSAnand Jain } 11773d8cc17aSAnand Jain 11783d8cc17aSAnand Jain static ssize_t btrfs_read_policy_store(struct kobject *kobj, 11793d8cc17aSAnand Jain struct kobj_attribute *a, 11803d8cc17aSAnand Jain const char *buf, size_t len) 11813d8cc17aSAnand Jain { 11823d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 11833d8cc17aSAnand Jain int i; 11843d8cc17aSAnand Jain 11853d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 11867f298f22SDavid Sterba if (sysfs_streq(buf, btrfs_read_policy_name[i])) { 11873d8cc17aSAnand Jain if (i != fs_devices->read_policy) { 11883d8cc17aSAnand Jain fs_devices->read_policy = i; 11893d8cc17aSAnand Jain btrfs_info(fs_devices->fs_info, 11903d8cc17aSAnand Jain "read policy set to '%s'", 11913d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11923d8cc17aSAnand Jain } 11933d8cc17aSAnand Jain return len; 11943d8cc17aSAnand Jain } 11953d8cc17aSAnand Jain } 11963d8cc17aSAnand Jain 11973d8cc17aSAnand Jain return -EINVAL; 11983d8cc17aSAnand Jain } 11993d8cc17aSAnand Jain BTRFS_ATTR_RW(, read_policy, btrfs_read_policy_show, btrfs_read_policy_store); 12003d8cc17aSAnand Jain 120118bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_show(struct kobject *kobj, 120218bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 120318bb8bbfSJohannes Thumshirn char *buf) 120418bb8bbfSJohannes Thumshirn { 120518bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 120618bb8bbfSJohannes Thumshirn 1207bd64f622Szhang songyi return sysfs_emit(buf, "%d\n", READ_ONCE(fs_info->bg_reclaim_threshold)); 120818bb8bbfSJohannes Thumshirn } 120918bb8bbfSJohannes Thumshirn 121018bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_store(struct kobject *kobj, 121118bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 121218bb8bbfSJohannes Thumshirn const char *buf, size_t len) 121318bb8bbfSJohannes Thumshirn { 121418bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 121518bb8bbfSJohannes Thumshirn int thresh; 121618bb8bbfSJohannes Thumshirn int ret; 121718bb8bbfSJohannes Thumshirn 121818bb8bbfSJohannes Thumshirn ret = kstrtoint(buf, 10, &thresh); 121918bb8bbfSJohannes Thumshirn if (ret) 122018bb8bbfSJohannes Thumshirn return ret; 122118bb8bbfSJohannes Thumshirn 122277233c2dSJohannes Thumshirn if (thresh != 0 && (thresh <= 50 || thresh > 100)) 122318bb8bbfSJohannes Thumshirn return -EINVAL; 122418bb8bbfSJohannes Thumshirn 122577233c2dSJohannes Thumshirn WRITE_ONCE(fs_info->bg_reclaim_threshold, thresh); 122618bb8bbfSJohannes Thumshirn 122718bb8bbfSJohannes Thumshirn return len; 122818bb8bbfSJohannes Thumshirn } 122918bb8bbfSJohannes Thumshirn BTRFS_ATTR_RW(, bg_reclaim_threshold, btrfs_bg_reclaim_threshold_show, 123018bb8bbfSJohannes Thumshirn btrfs_bg_reclaim_threshold_store); 123118bb8bbfSJohannes Thumshirn 1232e7849e33SAnand Jain /* 1233e7849e33SAnand Jain * Per-filesystem information and stats. 1234e7849e33SAnand Jain * 1235e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/ 1236e7849e33SAnand Jain */ 12370dd2906fSAnand Jain static const struct attribute *btrfs_attrs[] = { 1238a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, label), 1239a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, nodesize), 1240a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, sectorsize), 1241a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, clone_alignment), 1242a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, quota_override), 124356f20f40SNikolay Borisov BTRFS_ATTR_PTR(, metadata_uuid), 124441e6d2a8SJohannes Thumshirn BTRFS_ATTR_PTR(, checksum), 124566a2823cSGoldwyn Rodrigues BTRFS_ATTR_PTR(, exclusive_operation), 1246089c8b05SAnand Jain BTRFS_ATTR_PTR(, generation), 12473d8cc17aSAnand Jain BTRFS_ATTR_PTR(, read_policy), 124818bb8bbfSJohannes Thumshirn BTRFS_ATTR_PTR(, bg_reclaim_threshold), 1249140a8ff7SIoannis Angelakopoulos BTRFS_ATTR_PTR(, commit_stats), 1250f8ba9c11SJeff Mahoney NULL, 1251f8ba9c11SJeff Mahoney }; 1252f8ba9c11SJeff Mahoney 1253c1b7e474SAnand Jain static void btrfs_release_fsid_kobj(struct kobject *kobj) 1254510d7360SJeff Mahoney { 12552e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj); 1256248d200dSAnand Jain 1257c1b7e474SAnand Jain memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject)); 12582e7910d6SAnand Jain complete(&fs_devs->kobj_unregister); 1259510d7360SJeff Mahoney } 1260510d7360SJeff Mahoney 1261510d7360SJeff Mahoney static struct kobj_type btrfs_ktype = { 1262510d7360SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 1263c1b7e474SAnand Jain .release = btrfs_release_fsid_kobj, 1264510d7360SJeff Mahoney }; 1265510d7360SJeff Mahoney 12662e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj) 12672e7910d6SAnand Jain { 12682e7910d6SAnand Jain if (kobj->ktype != &btrfs_ktype) 12692e7910d6SAnand Jain return NULL; 1270c1b7e474SAnand Jain return container_of(kobj, struct btrfs_fs_devices, fsid_kobj); 12712e7910d6SAnand Jain } 12722e7910d6SAnand Jain 1273510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj) 1274510d7360SJeff Mahoney { 1275510d7360SJeff Mahoney if (kobj->ktype != &btrfs_ktype) 1276510d7360SJeff Mahoney return NULL; 12772e7910d6SAnand Jain return to_fs_devs(kobj)->fs_info; 1278510d7360SJeff Mahoney } 127958176a96SJosef Bacik 128019fc516aSStefan Roesch static struct kobject *get_btrfs_kobj(struct kobject *kobj) 128119fc516aSStefan Roesch { 128219fc516aSStefan Roesch while (kobj) { 128319fc516aSStefan Roesch if (kobj->ktype == &btrfs_ktype) 128419fc516aSStefan Roesch return kobj; 128519fc516aSStefan Roesch kobj = kobj->parent; 128619fc516aSStefan Roesch } 128719fc516aSStefan Roesch return NULL; 128819fc516aSStefan Roesch } 128919fc516aSStefan Roesch 1290e453d989SJeff Mahoney #define NUM_FEATURE_BITS 64 12916c52157fSTomohiro Misono #define BTRFS_FEATURE_NAME_MAX 13 12926c52157fSTomohiro Misono static char btrfs_unknown_feature_names[FEAT_MAX][NUM_FEATURE_BITS][BTRFS_FEATURE_NAME_MAX]; 12936c52157fSTomohiro Misono static struct btrfs_feature_attr btrfs_feature_attrs[FEAT_MAX][NUM_FEATURE_BITS]; 1294e453d989SJeff Mahoney 1295a55e65b8SDavid Sterba static_assert(ARRAY_SIZE(btrfs_unknown_feature_names) == 1296a55e65b8SDavid Sterba ARRAY_SIZE(btrfs_feature_attrs)); 1297a55e65b8SDavid Sterba static_assert(ARRAY_SIZE(btrfs_unknown_feature_names[0]) == 1298a55e65b8SDavid Sterba ARRAY_SIZE(btrfs_feature_attrs[0])); 1299a55e65b8SDavid Sterba 13006c52157fSTomohiro Misono static const u64 supported_feature_masks[FEAT_MAX] = { 1301e453d989SJeff Mahoney [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP, 1302e453d989SJeff Mahoney [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP, 1303e453d989SJeff Mahoney [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP, 1304e453d989SJeff Mahoney }; 1305e453d989SJeff Mahoney 1306e453d989SJeff Mahoney static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add) 13075ac1d209SJeff Mahoney { 1308e453d989SJeff Mahoney int set; 1309e453d989SJeff Mahoney 1310e453d989SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 1311e453d989SJeff Mahoney int i; 1312e453d989SJeff Mahoney struct attribute *attrs[2]; 1313e453d989SJeff Mahoney struct attribute_group agroup = { 1314e453d989SJeff Mahoney .name = "features", 1315e453d989SJeff Mahoney .attrs = attrs, 1316e453d989SJeff Mahoney }; 1317e453d989SJeff Mahoney u64 features = get_features(fs_info, set); 1318e453d989SJeff Mahoney features &= ~supported_feature_masks[set]; 1319e453d989SJeff Mahoney 1320e453d989SJeff Mahoney if (!features) 1321e453d989SJeff Mahoney continue; 1322e453d989SJeff Mahoney 1323e453d989SJeff Mahoney attrs[1] = NULL; 1324e453d989SJeff Mahoney for (i = 0; i < NUM_FEATURE_BITS; i++) { 1325e453d989SJeff Mahoney struct btrfs_feature_attr *fa; 1326e453d989SJeff Mahoney 1327e453d989SJeff Mahoney if (!(features & (1ULL << i))) 1328e453d989SJeff Mahoney continue; 1329e453d989SJeff Mahoney 1330e453d989SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 1331e453d989SJeff Mahoney attrs[0] = &fa->kobj_attr.attr; 1332e453d989SJeff Mahoney if (add) { 1333e453d989SJeff Mahoney int ret; 1334c1b7e474SAnand Jain ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj, 1335e453d989SJeff Mahoney &agroup); 1336e453d989SJeff Mahoney if (ret) 1337e453d989SJeff Mahoney return ret; 1338e453d989SJeff Mahoney } else 1339c1b7e474SAnand Jain sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj, 1340e453d989SJeff Mahoney &agroup); 1341e453d989SJeff Mahoney } 1342e453d989SJeff Mahoney 1343e453d989SJeff Mahoney } 1344e453d989SJeff Mahoney return 0; 1345e453d989SJeff Mahoney } 1346e453d989SJeff Mahoney 13472e3e1281SAnand Jain static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 1348e453d989SJeff Mahoney { 1349a013d141SAnand Jain if (fs_devs->devinfo_kobj) { 1350a013d141SAnand Jain kobject_del(fs_devs->devinfo_kobj); 1351a013d141SAnand Jain kobject_put(fs_devs->devinfo_kobj); 1352a013d141SAnand Jain fs_devs->devinfo_kobj = NULL; 1353a013d141SAnand Jain } 1354a013d141SAnand Jain 1355b5501504SAnand Jain if (fs_devs->devices_kobj) { 1356b5501504SAnand Jain kobject_del(fs_devs->devices_kobj); 1357b5501504SAnand Jain kobject_put(fs_devs->devices_kobj); 1358b5501504SAnand Jain fs_devs->devices_kobj = NULL; 1359aaf13305SAnand Jain } 1360aaf13305SAnand Jain 1361c1b7e474SAnand Jain if (fs_devs->fsid_kobj.state_initialized) { 1362c1b7e474SAnand Jain kobject_del(&fs_devs->fsid_kobj); 1363c1b7e474SAnand Jain kobject_put(&fs_devs->fsid_kobj); 13642e7910d6SAnand Jain wait_for_completion(&fs_devs->kobj_unregister); 13655ac1d209SJeff Mahoney } 1366f90fc547SAnand Jain } 13675ac1d209SJeff Mahoney 13682e3e1281SAnand Jain /* when fs_devs is NULL it will remove all fsid kobject */ 13691d1c1be3SAnand Jain void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 13702e3e1281SAnand Jain { 13712e3e1281SAnand Jain struct list_head *fs_uuids = btrfs_get_fs_uuids(); 13722e3e1281SAnand Jain 13732e3e1281SAnand Jain if (fs_devs) { 13742e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 13752e3e1281SAnand Jain return; 13762e3e1281SAnand Jain } 13772e3e1281SAnand Jain 1378c4babc5eSAnand Jain list_for_each_entry(fs_devs, fs_uuids, fs_list) { 13792e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 13802e3e1281SAnand Jain } 13812e3e1281SAnand Jain } 13822e3e1281SAnand Jain 138353f8a74cSAnand Jain static void btrfs_sysfs_remove_fs_devices(struct btrfs_fs_devices *fs_devices) 138453f8a74cSAnand Jain { 138553f8a74cSAnand Jain struct btrfs_device *device; 138630b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 138753f8a74cSAnand Jain 138853f8a74cSAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) 138953f8a74cSAnand Jain btrfs_sysfs_remove_device(device); 139030b0e4e0SAnand Jain 139130b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 139230b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) 139330b0e4e0SAnand Jain btrfs_sysfs_remove_device(device); 139430b0e4e0SAnand Jain } 139553f8a74cSAnand Jain } 139653f8a74cSAnand Jain 13976618a59bSAnand Jain void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info) 1398e453d989SJeff Mahoney { 13993092c68fSNikolay Borisov struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 14003092c68fSNikolay Borisov 14013092c68fSNikolay Borisov sysfs_remove_link(fsid_kobj, "bdi"); 14023092c68fSNikolay Borisov 1403e453d989SJeff Mahoney if (fs_info->space_info_kobj) { 1404e453d989SJeff Mahoney sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); 1405e453d989SJeff Mahoney kobject_del(fs_info->space_info_kobj); 1406e453d989SJeff Mahoney kobject_put(fs_info->space_info_kobj); 1407e453d989SJeff Mahoney } 1408fb731430SDavid Sterba if (fs_info->discard_kobj) { 1409fb731430SDavid Sterba sysfs_remove_files(fs_info->discard_kobj, discard_attrs); 1410fb731430SDavid Sterba kobject_del(fs_info->discard_kobj); 1411fb731430SDavid Sterba kobject_put(fs_info->discard_kobj); 1412e4faab84SDennis Zhou } 1413fb731430SDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 141493945cb4SDennis Zhou if (fs_info->debug_kobj) { 141593945cb4SDennis Zhou sysfs_remove_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 141693945cb4SDennis Zhou kobject_del(fs_info->debug_kobj); 141793945cb4SDennis Zhou kobject_put(fs_info->debug_kobj); 141893945cb4SDennis Zhou } 141971e8978eSDennis Zhou #endif 1420e453d989SJeff Mahoney addrm_unknown_feature_attrs(fs_info, false); 14213092c68fSNikolay Borisov sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 14223092c68fSNikolay Borisov sysfs_remove_files(fsid_kobj, btrfs_attrs); 142353f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_info->fs_devices); 1424e453d989SJeff Mahoney } 1425e453d989SJeff Mahoney 1426f10152bcSDavid Sterba static const char * const btrfs_feature_set_names[FEAT_MAX] = { 142779da4fa4SJeff Mahoney [FEAT_COMPAT] = "compat", 142879da4fa4SJeff Mahoney [FEAT_COMPAT_RO] = "compat_ro", 142979da4fa4SJeff Mahoney [FEAT_INCOMPAT] = "incompat", 143079da4fa4SJeff Mahoney }; 143179da4fa4SJeff Mahoney 14329e6df7ceSDavid Sterba const char *btrfs_feature_set_name(enum btrfs_feature_set set) 1433f10152bcSDavid Sterba { 1434f10152bcSDavid Sterba return btrfs_feature_set_names[set]; 1435f10152bcSDavid Sterba } 1436f10152bcSDavid Sterba 14373b02a68aSJeff Mahoney char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) 14383b02a68aSJeff Mahoney { 14393b02a68aSJeff Mahoney size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */ 14403b02a68aSJeff Mahoney int len = 0; 14413b02a68aSJeff Mahoney int i; 14423b02a68aSJeff Mahoney char *str; 14433b02a68aSJeff Mahoney 14443b02a68aSJeff Mahoney str = kmalloc(bufsize, GFP_KERNEL); 14453b02a68aSJeff Mahoney if (!str) 14463b02a68aSJeff Mahoney return str; 14473b02a68aSJeff Mahoney 14483b02a68aSJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 14493b02a68aSJeff Mahoney const char *name; 14503b02a68aSJeff Mahoney 14513b02a68aSJeff Mahoney if (!(flags & (1ULL << i))) 14523b02a68aSJeff Mahoney continue; 14533b02a68aSJeff Mahoney 14543b02a68aSJeff Mahoney name = btrfs_feature_attrs[set][i].kobj_attr.attr.name; 1455abdd9febSTakashi Iwai len += scnprintf(str + len, bufsize - len, "%s%s", 14563b02a68aSJeff Mahoney len ? "," : "", name); 14573b02a68aSJeff Mahoney } 14583b02a68aSJeff Mahoney 14593b02a68aSJeff Mahoney return str; 14603b02a68aSJeff Mahoney } 14613b02a68aSJeff Mahoney 146279da4fa4SJeff Mahoney static void init_feature_attrs(void) 146379da4fa4SJeff Mahoney { 146479da4fa4SJeff Mahoney struct btrfs_feature_attr *fa; 146579da4fa4SJeff Mahoney int set, i; 146679da4fa4SJeff Mahoney 14673b02a68aSJeff Mahoney memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs)); 14683b02a68aSJeff Mahoney memset(btrfs_unknown_feature_names, 0, 14693b02a68aSJeff Mahoney sizeof(btrfs_unknown_feature_names)); 14703b02a68aSJeff Mahoney 147179da4fa4SJeff Mahoney for (i = 0; btrfs_supported_feature_attrs[i]; i++) { 147279da4fa4SJeff Mahoney struct btrfs_feature_attr *sfa; 147379da4fa4SJeff Mahoney struct attribute *a = btrfs_supported_feature_attrs[i]; 14743b02a68aSJeff Mahoney int bit; 147579da4fa4SJeff Mahoney sfa = attr_to_btrfs_feature_attr(a); 14763b02a68aSJeff Mahoney bit = ilog2(sfa->feature_bit); 14773b02a68aSJeff Mahoney fa = &btrfs_feature_attrs[sfa->feature_set][bit]; 147879da4fa4SJeff Mahoney 147979da4fa4SJeff Mahoney fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name; 148079da4fa4SJeff Mahoney } 148179da4fa4SJeff Mahoney 148279da4fa4SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 148379da4fa4SJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 148479da4fa4SJeff Mahoney char *name = btrfs_unknown_feature_names[set][i]; 148579da4fa4SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 148679da4fa4SJeff Mahoney 148779da4fa4SJeff Mahoney if (fa->kobj_attr.attr.name) 148879da4fa4SJeff Mahoney continue; 148979da4fa4SJeff Mahoney 14906c52157fSTomohiro Misono snprintf(name, BTRFS_FEATURE_NAME_MAX, "%s:%u", 149179da4fa4SJeff Mahoney btrfs_feature_set_names[set], i); 149279da4fa4SJeff Mahoney 149379da4fa4SJeff Mahoney fa->kobj_attr.attr.name = name; 149479da4fa4SJeff Mahoney fa->kobj_attr.attr.mode = S_IRUGO; 149579da4fa4SJeff Mahoney fa->feature_set = set; 149679da4fa4SJeff Mahoney fa->feature_bit = 1ULL << i; 149779da4fa4SJeff Mahoney } 149879da4fa4SJeff Mahoney } 149979da4fa4SJeff Mahoney } 150079da4fa4SJeff Mahoney 150132a9991fSDavid Sterba /* 150232a9991fSDavid Sterba * Create a sysfs entry for a given block group type at path 150332a9991fSDavid Sterba * /sys/fs/btrfs/UUID/allocation/data/TYPE 150432a9991fSDavid Sterba */ 150532da5386SDavid Sterba void btrfs_sysfs_add_block_group_type(struct btrfs_block_group *cache) 150632a9991fSDavid Sterba { 150732a9991fSDavid Sterba struct btrfs_fs_info *fs_info = cache->fs_info; 150832a9991fSDavid Sterba struct btrfs_space_info *space_info = cache->space_info; 150932a9991fSDavid Sterba struct raid_kobject *rkobj; 151032a9991fSDavid Sterba const int index = btrfs_bg_flags_to_raid_index(cache->flags); 151132a9991fSDavid Sterba unsigned int nofs_flag; 151232a9991fSDavid Sterba int ret; 151332a9991fSDavid Sterba 151432a9991fSDavid Sterba /* 151532a9991fSDavid Sterba * Setup a NOFS context because kobject_add(), deep in its call chain, 151632a9991fSDavid Sterba * does GFP_KERNEL allocations, and we are often called in a context 151732a9991fSDavid Sterba * where if reclaim is triggered we can deadlock (we are either holding 151832a9991fSDavid Sterba * a transaction handle or some lock required for a transaction 151932a9991fSDavid Sterba * commit). 152032a9991fSDavid Sterba */ 152132a9991fSDavid Sterba nofs_flag = memalloc_nofs_save(); 152232a9991fSDavid Sterba 152332a9991fSDavid Sterba rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS); 152432a9991fSDavid Sterba if (!rkobj) { 152532a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 152632a9991fSDavid Sterba btrfs_warn(cache->fs_info, 152732a9991fSDavid Sterba "couldn't alloc memory for raid level kobject"); 152832a9991fSDavid Sterba return; 152932a9991fSDavid Sterba } 153032a9991fSDavid Sterba 153132a9991fSDavid Sterba rkobj->flags = cache->flags; 153232a9991fSDavid Sterba kobject_init(&rkobj->kobj, &btrfs_raid_ktype); 153349ea112dSJosef Bacik 153449ea112dSJosef Bacik /* 153549ea112dSJosef Bacik * We call this either on mount, or if we've created a block group for a 153649ea112dSJosef Bacik * new index type while running (i.e. when restriping). The running 153749ea112dSJosef Bacik * case is tricky because we could race with other threads, so we need 153849ea112dSJosef Bacik * to have this check to make sure we didn't already init the kobject. 153949ea112dSJosef Bacik * 154049ea112dSJosef Bacik * We don't have to protect on the free side because it only happens on 154149ea112dSJosef Bacik * unmount. 154249ea112dSJosef Bacik */ 154349ea112dSJosef Bacik spin_lock(&space_info->lock); 154449ea112dSJosef Bacik if (space_info->block_group_kobjs[index]) { 154549ea112dSJosef Bacik spin_unlock(&space_info->lock); 154649ea112dSJosef Bacik kobject_put(&rkobj->kobj); 154749ea112dSJosef Bacik return; 154849ea112dSJosef Bacik } else { 154949ea112dSJosef Bacik space_info->block_group_kobjs[index] = &rkobj->kobj; 155049ea112dSJosef Bacik } 155149ea112dSJosef Bacik spin_unlock(&space_info->lock); 155249ea112dSJosef Bacik 155332a9991fSDavid Sterba ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s", 155432a9991fSDavid Sterba btrfs_bg_type_to_raid_name(rkobj->flags)); 155532a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 155632a9991fSDavid Sterba if (ret) { 155749ea112dSJosef Bacik spin_lock(&space_info->lock); 155849ea112dSJosef Bacik space_info->block_group_kobjs[index] = NULL; 155949ea112dSJosef Bacik spin_unlock(&space_info->lock); 156032a9991fSDavid Sterba kobject_put(&rkobj->kobj); 156132a9991fSDavid Sterba btrfs_warn(fs_info, 156232a9991fSDavid Sterba "failed to add kobject for block cache, ignoring"); 156332a9991fSDavid Sterba return; 156432a9991fSDavid Sterba } 156532a9991fSDavid Sterba } 156632a9991fSDavid Sterba 1567b5865babSDavid Sterba /* 1568b5865babSDavid Sterba * Remove sysfs directories for all block group types of a given space info and 1569b5865babSDavid Sterba * the space info as well 1570b5865babSDavid Sterba */ 1571b5865babSDavid Sterba void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info) 1572b5865babSDavid Sterba { 1573b5865babSDavid Sterba int i; 1574b5865babSDavid Sterba 1575b5865babSDavid Sterba for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { 1576b5865babSDavid Sterba struct kobject *kobj; 1577b5865babSDavid Sterba 1578b5865babSDavid Sterba kobj = space_info->block_group_kobjs[i]; 1579b5865babSDavid Sterba space_info->block_group_kobjs[i] = NULL; 1580b5865babSDavid Sterba if (kobj) { 1581b5865babSDavid Sterba kobject_del(kobj); 1582b5865babSDavid Sterba kobject_put(kobj); 1583b5865babSDavid Sterba } 1584b5865babSDavid Sterba } 1585b5865babSDavid Sterba kobject_del(&space_info->kobj); 1586b5865babSDavid Sterba kobject_put(&space_info->kobj); 1587b5865babSDavid Sterba } 1588b5865babSDavid Sterba 1589b882327aSDavid Sterba static const char *alloc_name(u64 flags) 1590b882327aSDavid Sterba { 1591b882327aSDavid Sterba switch (flags) { 1592b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA: 1593b882327aSDavid Sterba return "mixed"; 1594b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA: 1595b882327aSDavid Sterba return "metadata"; 1596b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_DATA: 1597b882327aSDavid Sterba return "data"; 1598b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_SYSTEM: 1599b882327aSDavid Sterba return "system"; 1600b882327aSDavid Sterba default: 1601b882327aSDavid Sterba WARN_ON(1); 1602b882327aSDavid Sterba return "invalid-combination"; 1603445d8ab5STom Rix } 1604b882327aSDavid Sterba } 1605b882327aSDavid Sterba 1606b882327aSDavid Sterba /* 1607b882327aSDavid Sterba * Create a sysfs entry for a space info type at path 1608b882327aSDavid Sterba * /sys/fs/btrfs/UUID/allocation/TYPE 1609b882327aSDavid Sterba */ 1610b882327aSDavid Sterba int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info, 1611b882327aSDavid Sterba struct btrfs_space_info *space_info) 1612b882327aSDavid Sterba { 1613b882327aSDavid Sterba int ret; 1614b882327aSDavid Sterba 1615b882327aSDavid Sterba ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, 1616b882327aSDavid Sterba fs_info->space_info_kobj, "%s", 1617b882327aSDavid Sterba alloc_name(space_info->flags)); 1618b882327aSDavid Sterba if (ret) { 1619b882327aSDavid Sterba kobject_put(&space_info->kobj); 1620b882327aSDavid Sterba return ret; 1621b882327aSDavid Sterba } 1622b882327aSDavid Sterba 1623b882327aSDavid Sterba return 0; 1624b882327aSDavid Sterba } 1625b882327aSDavid Sterba 162653f8a74cSAnand Jain void btrfs_sysfs_remove_device(struct btrfs_device *device) 162799994cdeSAnand Jain { 1628985e233eSAnand Jain struct kobject *devices_kobj; 162999994cdeSAnand Jain 1630985e233eSAnand Jain /* 1631985e233eSAnand Jain * Seed fs_devices devices_kobj aren't used, fetch kobject from the 1632985e233eSAnand Jain * fs_info::fs_devices. 1633985e233eSAnand Jain */ 1634985e233eSAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1635985e233eSAnand Jain ASSERT(devices_kobj); 163699994cdeSAnand Jain 16378d65269fSChristoph Hellwig if (device->bdev) 16388d65269fSChristoph Hellwig sysfs_remove_link(devices_kobj, bdev_kobj(device->bdev)->name); 163999994cdeSAnand Jain 1640985e233eSAnand Jain if (device->devid_kobj.state_initialized) { 1641985e233eSAnand Jain kobject_del(&device->devid_kobj); 1642985e233eSAnand Jain kobject_put(&device->devid_kobj); 1643985e233eSAnand Jain wait_for_completion(&device->kobj_unregister); 1644985e233eSAnand Jain } 1645b5ddcffaSAnand Jain } 1646668e48afSAnand Jain 1647668e48afSAnand Jain static ssize_t btrfs_devinfo_in_fs_metadata_show(struct kobject *kobj, 1648668e48afSAnand Jain struct kobj_attribute *a, 1649668e48afSAnand Jain char *buf) 1650668e48afSAnand Jain { 1651668e48afSAnand Jain int val; 1652668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1653668e48afSAnand Jain devid_kobj); 1654668e48afSAnand Jain 1655668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state); 1656668e48afSAnand Jain 1657020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1658668e48afSAnand Jain } 1659668e48afSAnand Jain BTRFS_ATTR(devid, in_fs_metadata, btrfs_devinfo_in_fs_metadata_show); 1660668e48afSAnand Jain 166125864778SAnand Jain static ssize_t btrfs_devinfo_missing_show(struct kobject *kobj, 1662668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1663668e48afSAnand Jain { 1664668e48afSAnand Jain int val; 1665668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1666668e48afSAnand Jain devid_kobj); 1667668e48afSAnand Jain 1668668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state); 1669668e48afSAnand Jain 1670020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1671668e48afSAnand Jain } 167225864778SAnand Jain BTRFS_ATTR(devid, missing, btrfs_devinfo_missing_show); 1673668e48afSAnand Jain 1674668e48afSAnand Jain static ssize_t btrfs_devinfo_replace_target_show(struct kobject *kobj, 1675668e48afSAnand Jain struct kobj_attribute *a, 1676668e48afSAnand Jain char *buf) 1677668e48afSAnand Jain { 1678668e48afSAnand Jain int val; 1679668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1680668e48afSAnand Jain devid_kobj); 1681668e48afSAnand Jain 1682668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state); 1683668e48afSAnand Jain 1684020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1685668e48afSAnand Jain } 1686668e48afSAnand Jain BTRFS_ATTR(devid, replace_target, btrfs_devinfo_replace_target_show); 1687668e48afSAnand Jain 1688eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_show(struct kobject *kobj, 1689eb3b5053SDavid Sterba struct kobj_attribute *a, 1690eb3b5053SDavid Sterba char *buf) 1691eb3b5053SDavid Sterba { 1692eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1693eb3b5053SDavid Sterba devid_kobj); 1694eb3b5053SDavid Sterba 1695020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", READ_ONCE(device->scrub_speed_max)); 1696eb3b5053SDavid Sterba } 1697eb3b5053SDavid Sterba 1698eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_store(struct kobject *kobj, 1699eb3b5053SDavid Sterba struct kobj_attribute *a, 1700eb3b5053SDavid Sterba const char *buf, size_t len) 1701eb3b5053SDavid Sterba { 1702eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1703eb3b5053SDavid Sterba devid_kobj); 1704eb3b5053SDavid Sterba char *endptr; 1705eb3b5053SDavid Sterba unsigned long long limit; 1706eb3b5053SDavid Sterba 1707eb3b5053SDavid Sterba limit = memparse(buf, &endptr); 1708eb3b5053SDavid Sterba WRITE_ONCE(device->scrub_speed_max, limit); 1709eb3b5053SDavid Sterba return len; 1710eb3b5053SDavid Sterba } 1711eb3b5053SDavid Sterba BTRFS_ATTR_RW(devid, scrub_speed_max, btrfs_devinfo_scrub_speed_max_show, 1712eb3b5053SDavid Sterba btrfs_devinfo_scrub_speed_max_store); 1713eb3b5053SDavid Sterba 1714668e48afSAnand Jain static ssize_t btrfs_devinfo_writeable_show(struct kobject *kobj, 1715668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1716668e48afSAnand Jain { 1717668e48afSAnand Jain int val; 1718668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1719668e48afSAnand Jain devid_kobj); 1720668e48afSAnand Jain 1721668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state); 1722668e48afSAnand Jain 1723020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1724668e48afSAnand Jain } 1725668e48afSAnand Jain BTRFS_ATTR(devid, writeable, btrfs_devinfo_writeable_show); 1726668e48afSAnand Jain 1727a26d60deSAnand Jain static ssize_t btrfs_devinfo_fsid_show(struct kobject *kobj, 1728a26d60deSAnand Jain struct kobj_attribute *a, char *buf) 1729a26d60deSAnand Jain { 1730a26d60deSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1731a26d60deSAnand Jain devid_kobj); 1732a26d60deSAnand Jain 1733a26d60deSAnand Jain return sysfs_emit(buf, "%pU\n", device->fs_devices->fsid); 1734a26d60deSAnand Jain } 1735a26d60deSAnand Jain BTRFS_ATTR(devid, fsid, btrfs_devinfo_fsid_show); 1736a26d60deSAnand Jain 1737da658b57SDavid Sterba static ssize_t btrfs_devinfo_error_stats_show(struct kobject *kobj, 1738da658b57SDavid Sterba struct kobj_attribute *a, char *buf) 1739da658b57SDavid Sterba { 1740da658b57SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1741da658b57SDavid Sterba devid_kobj); 1742da658b57SDavid Sterba 1743da658b57SDavid Sterba if (!device->dev_stats_valid) 1744020e5277SAnand Jain return sysfs_emit(buf, "invalid\n"); 1745da658b57SDavid Sterba 1746da658b57SDavid Sterba /* 1747da658b57SDavid Sterba * Print all at once so we get a snapshot of all values from the same 1748da658b57SDavid Sterba * time. Keep them in sync and in order of definition of 1749da658b57SDavid Sterba * btrfs_dev_stat_values. 1750da658b57SDavid Sterba */ 1751020e5277SAnand Jain return sysfs_emit(buf, 1752da658b57SDavid Sterba "write_errs %d\n" 1753da658b57SDavid Sterba "read_errs %d\n" 1754da658b57SDavid Sterba "flush_errs %d\n" 1755da658b57SDavid Sterba "corruption_errs %d\n" 1756da658b57SDavid Sterba "generation_errs %d\n", 1757da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_WRITE_ERRS), 1758da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_READ_ERRS), 1759da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_FLUSH_ERRS), 1760da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_CORRUPTION_ERRS), 1761da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_GENERATION_ERRS)); 1762da658b57SDavid Sterba } 1763da658b57SDavid Sterba BTRFS_ATTR(devid, error_stats, btrfs_devinfo_error_stats_show); 1764da658b57SDavid Sterba 1765e7849e33SAnand Jain /* 1766e7849e33SAnand Jain * Information about one device. 1767e7849e33SAnand Jain * 1768e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/devinfo/<devid>/ 1769e7849e33SAnand Jain */ 1770668e48afSAnand Jain static struct attribute *devid_attrs[] = { 1771da658b57SDavid Sterba BTRFS_ATTR_PTR(devid, error_stats), 1772a26d60deSAnand Jain BTRFS_ATTR_PTR(devid, fsid), 1773668e48afSAnand Jain BTRFS_ATTR_PTR(devid, in_fs_metadata), 1774668e48afSAnand Jain BTRFS_ATTR_PTR(devid, missing), 1775668e48afSAnand Jain BTRFS_ATTR_PTR(devid, replace_target), 1776eb3b5053SDavid Sterba BTRFS_ATTR_PTR(devid, scrub_speed_max), 1777668e48afSAnand Jain BTRFS_ATTR_PTR(devid, writeable), 1778668e48afSAnand Jain NULL 1779668e48afSAnand Jain }; 1780668e48afSAnand Jain ATTRIBUTE_GROUPS(devid); 1781668e48afSAnand Jain 1782668e48afSAnand Jain static void btrfs_release_devid_kobj(struct kobject *kobj) 1783668e48afSAnand Jain { 1784668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1785668e48afSAnand Jain devid_kobj); 1786668e48afSAnand Jain 1787668e48afSAnand Jain memset(&device->devid_kobj, 0, sizeof(struct kobject)); 1788668e48afSAnand Jain complete(&device->kobj_unregister); 1789668e48afSAnand Jain } 1790668e48afSAnand Jain 1791668e48afSAnand Jain static struct kobj_type devid_ktype = { 1792668e48afSAnand Jain .sysfs_ops = &kobj_sysfs_ops, 1793668e48afSAnand Jain .default_groups = devid_groups, 1794668e48afSAnand Jain .release = btrfs_release_devid_kobj, 1795668e48afSAnand Jain }; 1796668e48afSAnand Jain 1797cd36da2eSAnand Jain int btrfs_sysfs_add_device(struct btrfs_device *device) 179829e5be24SJeff Mahoney { 1799178a16c9SAnand Jain int ret; 1800a47bd78dSJosef Bacik unsigned int nofs_flag; 1801178a16c9SAnand Jain struct kobject *devices_kobj; 1802178a16c9SAnand Jain struct kobject *devinfo_kobj; 1803178a16c9SAnand Jain 1804178a16c9SAnand Jain /* 1805178a16c9SAnand Jain * Make sure we use the fs_info::fs_devices to fetch the kobjects even 1806178a16c9SAnand Jain * for the seed fs_devices 1807178a16c9SAnand Jain */ 1808178a16c9SAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1809178a16c9SAnand Jain devinfo_kobj = device->fs_info->fs_devices->devinfo_kobj; 1810178a16c9SAnand Jain ASSERT(devices_kobj); 1811178a16c9SAnand Jain ASSERT(devinfo_kobj); 181229e5be24SJeff Mahoney 1813a47bd78dSJosef Bacik nofs_flag = memalloc_nofs_save(); 1814f085381eSAnand Jain 1815178a16c9SAnand Jain if (device->bdev) { 18168d65269fSChristoph Hellwig struct kobject *disk_kobj = bdev_kobj(device->bdev); 181729e5be24SJeff Mahoney 1818178a16c9SAnand Jain ret = sysfs_create_link(devices_kobj, disk_kobj, disk_kobj->name); 1819178a16c9SAnand Jain if (ret) { 1820178a16c9SAnand Jain btrfs_warn(device->fs_info, 1821178a16c9SAnand Jain "creating sysfs device link for devid %llu failed: %d", 1822178a16c9SAnand Jain device->devid, ret); 1823178a16c9SAnand Jain goto out; 1824178a16c9SAnand Jain } 182529e5be24SJeff Mahoney } 182629e5be24SJeff Mahoney 1827178a16c9SAnand Jain init_completion(&device->kobj_unregister); 1828178a16c9SAnand Jain ret = kobject_init_and_add(&device->devid_kobj, &devid_ktype, 1829178a16c9SAnand Jain devinfo_kobj, "%llu", device->devid); 1830178a16c9SAnand Jain if (ret) { 1831178a16c9SAnand Jain kobject_put(&device->devid_kobj); 1832178a16c9SAnand Jain btrfs_warn(device->fs_info, 1833178a16c9SAnand Jain "devinfo init for devid %llu failed: %d", 1834178a16c9SAnand Jain device->devid, ret); 1835668e48afSAnand Jain } 1836178a16c9SAnand Jain 1837178a16c9SAnand Jain out: 1838a47bd78dSJosef Bacik memalloc_nofs_restore(nofs_flag); 1839178a16c9SAnand Jain return ret; 1840178a16c9SAnand Jain } 1841668e48afSAnand Jain 1842cd36da2eSAnand Jain static int btrfs_sysfs_add_fs_devices(struct btrfs_fs_devices *fs_devices) 1843178a16c9SAnand Jain { 1844178a16c9SAnand Jain int ret; 1845cd36da2eSAnand Jain struct btrfs_device *device; 184630b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 1847178a16c9SAnand Jain 1848178a16c9SAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) { 1849178a16c9SAnand Jain ret = btrfs_sysfs_add_device(device); 1850178a16c9SAnand Jain if (ret) 18517ad3912aSAnand Jain goto fail; 1852178a16c9SAnand Jain } 1853178a16c9SAnand Jain 185430b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 185530b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) { 185630b0e4e0SAnand Jain ret = btrfs_sysfs_add_device(device); 185730b0e4e0SAnand Jain if (ret) 18587ad3912aSAnand Jain goto fail; 185930b0e4e0SAnand Jain } 186030b0e4e0SAnand Jain } 186130b0e4e0SAnand Jain 1862178a16c9SAnand Jain return 0; 18637ad3912aSAnand Jain 18647ad3912aSAnand Jain fail: 18657ad3912aSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devices); 18667ad3912aSAnand Jain return ret; 186729e5be24SJeff Mahoney } 186829e5be24SJeff Mahoney 18695b28692eSDavid Sterba void btrfs_kobject_uevent(struct block_device *bdev, enum kobject_action action) 18705b28692eSDavid Sterba { 18715b28692eSDavid Sterba int ret; 18725b28692eSDavid Sterba 18735b28692eSDavid Sterba ret = kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, action); 18745b28692eSDavid Sterba if (ret) 18755b28692eSDavid Sterba pr_warn("BTRFS: Sending event '%d' to kobject: '%s' (%p): failed\n", 18765b28692eSDavid Sterba action, kobject_name(&disk_to_dev(bdev->bd_disk)->kobj), 18775b28692eSDavid Sterba &disk_to_dev(bdev->bd_disk)->kobj); 18785b28692eSDavid Sterba } 18795b28692eSDavid Sterba 18808e560081SNikolay Borisov void btrfs_sysfs_update_sprout_fsid(struct btrfs_fs_devices *fs_devices) 18818e560081SNikolay Borisov 1882f93c3997SDavid Sterba { 1883f93c3997SDavid Sterba char fsid_buf[BTRFS_UUID_UNPARSED_SIZE]; 1884f93c3997SDavid Sterba 1885f93c3997SDavid Sterba /* 1886f93c3997SDavid Sterba * Sprouting changes fsid of the mounted filesystem, rename the fsid 1887f93c3997SDavid Sterba * directory 1888f93c3997SDavid Sterba */ 18898e560081SNikolay Borisov snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", fs_devices->fsid); 1890f93c3997SDavid Sterba if (kobject_rename(&fs_devices->fsid_kobj, fsid_buf)) 1891f93c3997SDavid Sterba btrfs_warn(fs_devices->fs_info, 1892f93c3997SDavid Sterba "sysfs: failed to create fsid for sprout"); 1893f93c3997SDavid Sterba } 1894f93c3997SDavid Sterba 1895668e48afSAnand Jain void btrfs_sysfs_update_devid(struct btrfs_device *device) 1896668e48afSAnand Jain { 1897668e48afSAnand Jain char tmp[24]; 1898668e48afSAnand Jain 1899668e48afSAnand Jain snprintf(tmp, sizeof(tmp), "%llu", device->devid); 1900668e48afSAnand Jain 1901668e48afSAnand Jain if (kobject_rename(&device->devid_kobj, tmp)) 1902668e48afSAnand Jain btrfs_warn(device->fs_devices->fs_info, 1903668e48afSAnand Jain "sysfs: failed to update devid for %llu", 1904668e48afSAnand Jain device->devid); 1905668e48afSAnand Jain } 1906668e48afSAnand Jain 1907510d7360SJeff Mahoney /* /sys/fs/btrfs/ entry */ 1908510d7360SJeff Mahoney static struct kset *btrfs_kset; 1909510d7360SJeff Mahoney 191072059215SAnand Jain /* 1911c6761a9eSAnand Jain * Creates: 1912c6761a9eSAnand Jain * /sys/fs/btrfs/UUID 1913c6761a9eSAnand Jain * 191472059215SAnand Jain * Can be called by the device discovery thread. 191572059215SAnand Jain */ 1916c6761a9eSAnand Jain int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs) 19175ac1d209SJeff Mahoney { 19185ac1d209SJeff Mahoney int error; 19195ac1d209SJeff Mahoney 19202e7910d6SAnand Jain init_completion(&fs_devs->kobj_unregister); 1921c1b7e474SAnand Jain fs_devs->fsid_kobj.kset = btrfs_kset; 1922c6761a9eSAnand Jain error = kobject_init_and_add(&fs_devs->fsid_kobj, &btrfs_ktype, NULL, 1923c6761a9eSAnand Jain "%pU", fs_devs->fsid); 1924e3277335STobin C. Harding if (error) { 1925e3277335STobin C. Harding kobject_put(&fs_devs->fsid_kobj); 192672059215SAnand Jain return error; 192772059215SAnand Jain } 192872059215SAnand Jain 1929bc036bb3SAnand Jain fs_devs->devices_kobj = kobject_create_and_add("devices", 1930bc036bb3SAnand Jain &fs_devs->fsid_kobj); 1931bc036bb3SAnand Jain if (!fs_devs->devices_kobj) { 1932bc036bb3SAnand Jain btrfs_err(fs_devs->fs_info, 1933bc036bb3SAnand Jain "failed to init sysfs device interface"); 19341f6087e6SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1935bc036bb3SAnand Jain return -ENOMEM; 1936bc036bb3SAnand Jain } 1937bc036bb3SAnand Jain 1938a013d141SAnand Jain fs_devs->devinfo_kobj = kobject_create_and_add("devinfo", 1939a013d141SAnand Jain &fs_devs->fsid_kobj); 1940a013d141SAnand Jain if (!fs_devs->devinfo_kobj) { 1941a013d141SAnand Jain btrfs_err(fs_devs->fs_info, 1942a013d141SAnand Jain "failed to init sysfs devinfo kobject"); 1943a013d141SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1944a013d141SAnand Jain return -ENOMEM; 1945a013d141SAnand Jain } 1946a013d141SAnand Jain 1947e3277335STobin C. Harding return 0; 1948e3277335STobin C. Harding } 1949e3277335STobin C. Harding 195096f3136eSAnand Jain int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info) 195172059215SAnand Jain { 195272059215SAnand Jain int error; 19532e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = fs_info->fs_devices; 1954c1b7e474SAnand Jain struct kobject *fsid_kobj = &fs_devs->fsid_kobj; 195572059215SAnand Jain 1956cd36da2eSAnand Jain error = btrfs_sysfs_add_fs_devices(fs_devs); 1957e453d989SJeff Mahoney if (error) 1958e453d989SJeff Mahoney return error; 1959510d7360SJeff Mahoney 1960c1b7e474SAnand Jain error = sysfs_create_files(fsid_kobj, btrfs_attrs); 1961e453d989SJeff Mahoney if (error) { 196253f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devs); 1963e453d989SJeff Mahoney return error; 1964e453d989SJeff Mahoney } 196579da4fa4SJeff Mahoney 1966c1b7e474SAnand Jain error = sysfs_create_group(fsid_kobj, 19670dd2906fSAnand Jain &btrfs_feature_attr_group); 19680dd2906fSAnand Jain if (error) 19690dd2906fSAnand Jain goto failure; 19700dd2906fSAnand Jain 19716e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 197293945cb4SDennis Zhou fs_info->debug_kobj = kobject_create_and_add("debug", fsid_kobj); 197393945cb4SDennis Zhou if (!fs_info->debug_kobj) { 197493945cb4SDennis Zhou error = -ENOMEM; 197593945cb4SDennis Zhou goto failure; 197693945cb4SDennis Zhou } 197793945cb4SDennis Zhou 197893945cb4SDennis Zhou error = sysfs_create_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 19796e369febSDavid Sterba if (error) 19806e369febSDavid Sterba goto failure; 1981fb731430SDavid Sterba #endif 1982e4faab84SDennis Zhou 1983e4faab84SDennis Zhou /* Discard directory */ 1984fb731430SDavid Sterba fs_info->discard_kobj = kobject_create_and_add("discard", fsid_kobj); 1985fb731430SDavid Sterba if (!fs_info->discard_kobj) { 1986e4faab84SDennis Zhou error = -ENOMEM; 1987e4faab84SDennis Zhou goto failure; 1988e4faab84SDennis Zhou } 1989e4faab84SDennis Zhou 1990fb731430SDavid Sterba error = sysfs_create_files(fs_info->discard_kobj, discard_attrs); 1991e4faab84SDennis Zhou if (error) 1992e4faab84SDennis Zhou goto failure; 19936e369febSDavid Sterba 1994e453d989SJeff Mahoney error = addrm_unknown_feature_attrs(fs_info, true); 199579da4fa4SJeff Mahoney if (error) 199679da4fa4SJeff Mahoney goto failure; 199779da4fa4SJeff Mahoney 19983092c68fSNikolay Borisov error = sysfs_create_link(fsid_kobj, &fs_info->sb->s_bdi->dev->kobj, "bdi"); 19993092c68fSNikolay Borisov if (error) 20003092c68fSNikolay Borisov goto failure; 20013092c68fSNikolay Borisov 20026ab0a202SJeff Mahoney fs_info->space_info_kobj = kobject_create_and_add("allocation", 2003c1b7e474SAnand Jain fsid_kobj); 20046ab0a202SJeff Mahoney if (!fs_info->space_info_kobj) { 20056ab0a202SJeff Mahoney error = -ENOMEM; 20066ab0a202SJeff Mahoney goto failure; 20076ab0a202SJeff Mahoney } 20086ab0a202SJeff Mahoney 20096ab0a202SJeff Mahoney error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs); 20106ab0a202SJeff Mahoney if (error) 20116ab0a202SJeff Mahoney goto failure; 20126ab0a202SJeff Mahoney 201379da4fa4SJeff Mahoney return 0; 201479da4fa4SJeff Mahoney failure: 20156618a59bSAnand Jain btrfs_sysfs_remove_mounted(fs_info); 20165ac1d209SJeff Mahoney return error; 20175ac1d209SJeff Mahoney } 20185ac1d209SJeff Mahoney 2019ed2e35d8SQu Wenruo static ssize_t qgroup_enabled_show(struct kobject *qgroups_kobj, 2020ed2e35d8SQu Wenruo struct kobj_attribute *a, 2021ed2e35d8SQu Wenruo char *buf) 2022ed2e35d8SQu Wenruo { 2023ed2e35d8SQu Wenruo struct btrfs_fs_info *fs_info = to_fs_info(qgroups_kobj->parent); 2024ed2e35d8SQu Wenruo bool enabled; 2025ed2e35d8SQu Wenruo 2026ed2e35d8SQu Wenruo spin_lock(&fs_info->qgroup_lock); 2027ed2e35d8SQu Wenruo enabled = fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON; 2028ed2e35d8SQu Wenruo spin_unlock(&fs_info->qgroup_lock); 2029ed2e35d8SQu Wenruo 2030ed2e35d8SQu Wenruo return sysfs_emit(buf, "%d\n", enabled); 2031ed2e35d8SQu Wenruo } 2032ed2e35d8SQu Wenruo BTRFS_ATTR(qgroups, enabled, qgroup_enabled_show); 2033ed2e35d8SQu Wenruo 2034ed2e35d8SQu Wenruo static ssize_t qgroup_inconsistent_show(struct kobject *qgroups_kobj, 2035ed2e35d8SQu Wenruo struct kobj_attribute *a, 2036ed2e35d8SQu Wenruo char *buf) 2037ed2e35d8SQu Wenruo { 2038ed2e35d8SQu Wenruo struct btrfs_fs_info *fs_info = to_fs_info(qgroups_kobj->parent); 2039ed2e35d8SQu Wenruo bool inconsistent; 2040ed2e35d8SQu Wenruo 2041ed2e35d8SQu Wenruo spin_lock(&fs_info->qgroup_lock); 2042ed2e35d8SQu Wenruo inconsistent = (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT); 2043ed2e35d8SQu Wenruo spin_unlock(&fs_info->qgroup_lock); 2044ed2e35d8SQu Wenruo 2045ed2e35d8SQu Wenruo return sysfs_emit(buf, "%d\n", inconsistent); 2046ed2e35d8SQu Wenruo } 2047ed2e35d8SQu Wenruo BTRFS_ATTR(qgroups, inconsistent, qgroup_inconsistent_show); 2048ed2e35d8SQu Wenruo 2049011b46c3SQu Wenruo static ssize_t qgroup_drop_subtree_thres_show(struct kobject *qgroups_kobj, 2050011b46c3SQu Wenruo struct kobj_attribute *a, 2051011b46c3SQu Wenruo char *buf) 2052011b46c3SQu Wenruo { 2053011b46c3SQu Wenruo struct btrfs_fs_info *fs_info = to_fs_info(qgroups_kobj->parent); 2054011b46c3SQu Wenruo u8 result; 2055011b46c3SQu Wenruo 2056011b46c3SQu Wenruo spin_lock(&fs_info->qgroup_lock); 2057011b46c3SQu Wenruo result = fs_info->qgroup_drop_subtree_thres; 2058011b46c3SQu Wenruo spin_unlock(&fs_info->qgroup_lock); 2059011b46c3SQu Wenruo 2060011b46c3SQu Wenruo return sysfs_emit(buf, "%d\n", result); 2061011b46c3SQu Wenruo } 2062011b46c3SQu Wenruo 2063011b46c3SQu Wenruo static ssize_t qgroup_drop_subtree_thres_store(struct kobject *qgroups_kobj, 2064011b46c3SQu Wenruo struct kobj_attribute *a, 2065011b46c3SQu Wenruo const char *buf, size_t len) 2066011b46c3SQu Wenruo { 2067011b46c3SQu Wenruo struct btrfs_fs_info *fs_info = to_fs_info(qgroups_kobj->parent); 2068011b46c3SQu Wenruo u8 new_thres; 2069011b46c3SQu Wenruo int ret; 2070011b46c3SQu Wenruo 2071011b46c3SQu Wenruo ret = kstrtou8(buf, 10, &new_thres); 2072011b46c3SQu Wenruo if (ret) 2073011b46c3SQu Wenruo return -EINVAL; 2074011b46c3SQu Wenruo 2075011b46c3SQu Wenruo if (new_thres > BTRFS_MAX_LEVEL) 2076011b46c3SQu Wenruo return -EINVAL; 2077011b46c3SQu Wenruo 2078011b46c3SQu Wenruo spin_lock(&fs_info->qgroup_lock); 2079011b46c3SQu Wenruo fs_info->qgroup_drop_subtree_thres = new_thres; 2080011b46c3SQu Wenruo spin_unlock(&fs_info->qgroup_lock); 2081011b46c3SQu Wenruo 2082011b46c3SQu Wenruo return len; 2083011b46c3SQu Wenruo } 2084011b46c3SQu Wenruo BTRFS_ATTR_RW(qgroups, drop_subtree_threshold, qgroup_drop_subtree_thres_show, 2085011b46c3SQu Wenruo qgroup_drop_subtree_thres_store); 2086011b46c3SQu Wenruo 2087ed2e35d8SQu Wenruo /* 2088ed2e35d8SQu Wenruo * Qgroups global info 2089ed2e35d8SQu Wenruo * 2090ed2e35d8SQu Wenruo * Path: /sys/fs/btrfs/<uuid>/qgroups/ 2091ed2e35d8SQu Wenruo */ 2092ed2e35d8SQu Wenruo static struct attribute *qgroups_attrs[] = { 2093ed2e35d8SQu Wenruo BTRFS_ATTR_PTR(qgroups, enabled), 2094ed2e35d8SQu Wenruo BTRFS_ATTR_PTR(qgroups, inconsistent), 2095011b46c3SQu Wenruo BTRFS_ATTR_PTR(qgroups, drop_subtree_threshold), 2096ed2e35d8SQu Wenruo NULL 2097ed2e35d8SQu Wenruo }; 2098ed2e35d8SQu Wenruo ATTRIBUTE_GROUPS(qgroups); 2099ed2e35d8SQu Wenruo 2100ed2e35d8SQu Wenruo static void qgroups_release(struct kobject *kobj) 2101ed2e35d8SQu Wenruo { 2102ed2e35d8SQu Wenruo kfree(kobj); 2103ed2e35d8SQu Wenruo } 2104ed2e35d8SQu Wenruo 2105ed2e35d8SQu Wenruo static struct kobj_type qgroups_ktype = { 2106ed2e35d8SQu Wenruo .sysfs_ops = &kobj_sysfs_ops, 2107ed2e35d8SQu Wenruo .default_groups = qgroups_groups, 2108ed2e35d8SQu Wenruo .release = qgroups_release, 2109ed2e35d8SQu Wenruo }; 2110ed2e35d8SQu Wenruo 211149e5fb46SQu Wenruo static inline struct btrfs_fs_info *qgroup_kobj_to_fs_info(struct kobject *kobj) 211249e5fb46SQu Wenruo { 211349e5fb46SQu Wenruo return to_fs_info(kobj->parent->parent); 211449e5fb46SQu Wenruo } 211549e5fb46SQu Wenruo 211649e5fb46SQu Wenruo #define QGROUP_ATTR(_member, _show_name) \ 211749e5fb46SQu Wenruo static ssize_t btrfs_qgroup_show_##_member(struct kobject *qgroup_kobj, \ 211849e5fb46SQu Wenruo struct kobj_attribute *a, \ 211949e5fb46SQu Wenruo char *buf) \ 212049e5fb46SQu Wenruo { \ 212149e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 212249e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 212349e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 212449e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->_member, &fs_info->qgroup_lock, buf); \ 212549e5fb46SQu Wenruo } \ 212649e5fb46SQu Wenruo BTRFS_ATTR(qgroup, _show_name, btrfs_qgroup_show_##_member) 212749e5fb46SQu Wenruo 212849e5fb46SQu Wenruo #define QGROUP_RSV_ATTR(_name, _type) \ 212949e5fb46SQu Wenruo static ssize_t btrfs_qgroup_rsv_show_##_name(struct kobject *qgroup_kobj, \ 213049e5fb46SQu Wenruo struct kobj_attribute *a, \ 213149e5fb46SQu Wenruo char *buf) \ 213249e5fb46SQu Wenruo { \ 213349e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 213449e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 213549e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 213649e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->rsv.values[_type], \ 213749e5fb46SQu Wenruo &fs_info->qgroup_lock, buf); \ 213849e5fb46SQu Wenruo } \ 213949e5fb46SQu Wenruo BTRFS_ATTR(qgroup, rsv_##_name, btrfs_qgroup_rsv_show_##_name) 214049e5fb46SQu Wenruo 214149e5fb46SQu Wenruo QGROUP_ATTR(rfer, referenced); 214249e5fb46SQu Wenruo QGROUP_ATTR(excl, exclusive); 214349e5fb46SQu Wenruo QGROUP_ATTR(max_rfer, max_referenced); 214449e5fb46SQu Wenruo QGROUP_ATTR(max_excl, max_exclusive); 214549e5fb46SQu Wenruo QGROUP_ATTR(lim_flags, limit_flags); 214649e5fb46SQu Wenruo QGROUP_RSV_ATTR(data, BTRFS_QGROUP_RSV_DATA); 214749e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_pertrans, BTRFS_QGROUP_RSV_META_PERTRANS); 214849e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_prealloc, BTRFS_QGROUP_RSV_META_PREALLOC); 214949e5fb46SQu Wenruo 2150e7849e33SAnand Jain /* 2151e7849e33SAnand Jain * Qgroup information. 2152e7849e33SAnand Jain * 2153e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/qgroups/<level>_<qgroupid>/ 2154e7849e33SAnand Jain */ 215549e5fb46SQu Wenruo static struct attribute *qgroup_attrs[] = { 215649e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, referenced), 215749e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, exclusive), 215849e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_referenced), 215949e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_exclusive), 216049e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, limit_flags), 216149e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_data), 216249e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_pertrans), 216349e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_prealloc), 216449e5fb46SQu Wenruo NULL 216549e5fb46SQu Wenruo }; 216649e5fb46SQu Wenruo ATTRIBUTE_GROUPS(qgroup); 216749e5fb46SQu Wenruo 216849e5fb46SQu Wenruo static void qgroup_release(struct kobject *kobj) 216949e5fb46SQu Wenruo { 217049e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(kobj, struct btrfs_qgroup, kobj); 217149e5fb46SQu Wenruo 217249e5fb46SQu Wenruo memset(&qgroup->kobj, 0, sizeof(*kobj)); 217349e5fb46SQu Wenruo } 217449e5fb46SQu Wenruo 217549e5fb46SQu Wenruo static struct kobj_type qgroup_ktype = { 217649e5fb46SQu Wenruo .sysfs_ops = &kobj_sysfs_ops, 217749e5fb46SQu Wenruo .release = qgroup_release, 217849e5fb46SQu Wenruo .default_groups = qgroup_groups, 217949e5fb46SQu Wenruo }; 218049e5fb46SQu Wenruo 218149e5fb46SQu Wenruo int btrfs_sysfs_add_one_qgroup(struct btrfs_fs_info *fs_info, 218249e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 218349e5fb46SQu Wenruo { 218449e5fb46SQu Wenruo struct kobject *qgroups_kobj = fs_info->qgroups_kobj; 218549e5fb46SQu Wenruo int ret; 218649e5fb46SQu Wenruo 218749e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 218849e5fb46SQu Wenruo return 0; 218949e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) 219049e5fb46SQu Wenruo return 0; 219149e5fb46SQu Wenruo if (!qgroups_kobj) 219249e5fb46SQu Wenruo return -EINVAL; 219349e5fb46SQu Wenruo 219449e5fb46SQu Wenruo ret = kobject_init_and_add(&qgroup->kobj, &qgroup_ktype, qgroups_kobj, 219549e5fb46SQu Wenruo "%hu_%llu", btrfs_qgroup_level(qgroup->qgroupid), 219649e5fb46SQu Wenruo btrfs_qgroup_subvolid(qgroup->qgroupid)); 219749e5fb46SQu Wenruo if (ret < 0) 219849e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 219949e5fb46SQu Wenruo 220049e5fb46SQu Wenruo return ret; 220149e5fb46SQu Wenruo } 220249e5fb46SQu Wenruo 220349e5fb46SQu Wenruo void btrfs_sysfs_del_qgroups(struct btrfs_fs_info *fs_info) 220449e5fb46SQu Wenruo { 220549e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 220649e5fb46SQu Wenruo struct btrfs_qgroup *next; 220749e5fb46SQu Wenruo 220849e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 220949e5fb46SQu Wenruo return; 221049e5fb46SQu Wenruo 221149e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 221249e5fb46SQu Wenruo &fs_info->qgroup_tree, node) 221349e5fb46SQu Wenruo btrfs_sysfs_del_one_qgroup(fs_info, qgroup); 221462ab2cc0SQu Wenruo if (fs_info->qgroups_kobj) { 221549e5fb46SQu Wenruo kobject_del(fs_info->qgroups_kobj); 221649e5fb46SQu Wenruo kobject_put(fs_info->qgroups_kobj); 221749e5fb46SQu Wenruo fs_info->qgroups_kobj = NULL; 221849e5fb46SQu Wenruo } 221962ab2cc0SQu Wenruo } 222049e5fb46SQu Wenruo 222149e5fb46SQu Wenruo /* Called when qgroups get initialized, thus there is no need for locking */ 222249e5fb46SQu Wenruo int btrfs_sysfs_add_qgroups(struct btrfs_fs_info *fs_info) 222349e5fb46SQu Wenruo { 222449e5fb46SQu Wenruo struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 222549e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 222649e5fb46SQu Wenruo struct btrfs_qgroup *next; 222749e5fb46SQu Wenruo int ret = 0; 222849e5fb46SQu Wenruo 222949e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 223049e5fb46SQu Wenruo return 0; 223149e5fb46SQu Wenruo 223249e5fb46SQu Wenruo ASSERT(fsid_kobj); 223349e5fb46SQu Wenruo if (fs_info->qgroups_kobj) 223449e5fb46SQu Wenruo return 0; 223549e5fb46SQu Wenruo 2236ed2e35d8SQu Wenruo fs_info->qgroups_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); 2237ed2e35d8SQu Wenruo if (!fs_info->qgroups_kobj) 2238ed2e35d8SQu Wenruo return -ENOMEM; 2239ed2e35d8SQu Wenruo 2240ed2e35d8SQu Wenruo ret = kobject_init_and_add(fs_info->qgroups_kobj, &qgroups_ktype, 2241ed2e35d8SQu Wenruo fsid_kobj, "qgroups"); 2242ed2e35d8SQu Wenruo if (ret < 0) 224349e5fb46SQu Wenruo goto out; 2244ed2e35d8SQu Wenruo 224549e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 224649e5fb46SQu Wenruo &fs_info->qgroup_tree, node) { 224749e5fb46SQu Wenruo ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup); 224849e5fb46SQu Wenruo if (ret < 0) 224949e5fb46SQu Wenruo goto out; 225049e5fb46SQu Wenruo } 225149e5fb46SQu Wenruo 225249e5fb46SQu Wenruo out: 225349e5fb46SQu Wenruo if (ret < 0) 225449e5fb46SQu Wenruo btrfs_sysfs_del_qgroups(fs_info); 225549e5fb46SQu Wenruo return ret; 225649e5fb46SQu Wenruo } 225749e5fb46SQu Wenruo 225849e5fb46SQu Wenruo void btrfs_sysfs_del_one_qgroup(struct btrfs_fs_info *fs_info, 225949e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 226049e5fb46SQu Wenruo { 226149e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 226249e5fb46SQu Wenruo return; 226349e5fb46SQu Wenruo 226449e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) { 226549e5fb46SQu Wenruo kobject_del(&qgroup->kobj); 226649e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 226749e5fb46SQu Wenruo } 226849e5fb46SQu Wenruo } 2269444e7516SDavid Sterba 2270444e7516SDavid Sterba /* 2271444e7516SDavid Sterba * Change per-fs features in /sys/fs/btrfs/UUID/features to match current 2272444e7516SDavid Sterba * values in superblock. Call after any changes to incompat/compat_ro flags 2273444e7516SDavid Sterba */ 2274444e7516SDavid Sterba void btrfs_sysfs_feature_update(struct btrfs_fs_info *fs_info, 2275444e7516SDavid Sterba u64 bit, enum btrfs_feature_set set) 2276444e7516SDavid Sterba { 2277444e7516SDavid Sterba struct btrfs_fs_devices *fs_devs; 2278444e7516SDavid Sterba struct kobject *fsid_kobj; 227924646481SLeon Romanovsky u64 __maybe_unused features; 228024646481SLeon Romanovsky int __maybe_unused ret; 2281444e7516SDavid Sterba 2282444e7516SDavid Sterba if (!fs_info) 2283444e7516SDavid Sterba return; 2284444e7516SDavid Sterba 228524646481SLeon Romanovsky /* 228624646481SLeon Romanovsky * See 14e46e04958df74 and e410e34fad913dd, feature bit updates are not 228724646481SLeon Romanovsky * safe when called from some contexts (eg. balance) 228824646481SLeon Romanovsky */ 2289444e7516SDavid Sterba features = get_features(fs_info, set); 2290444e7516SDavid Sterba ASSERT(bit & supported_feature_masks[set]); 2291444e7516SDavid Sterba 2292444e7516SDavid Sterba fs_devs = fs_info->fs_devices; 2293444e7516SDavid Sterba fsid_kobj = &fs_devs->fsid_kobj; 2294444e7516SDavid Sterba 2295bf609206SDavid Sterba if (!fsid_kobj->state_initialized) 2296bf609206SDavid Sterba return; 2297bf609206SDavid Sterba 2298444e7516SDavid Sterba /* 2299444e7516SDavid Sterba * FIXME: this is too heavy to update just one value, ideally we'd like 2300444e7516SDavid Sterba * to use sysfs_update_group but some refactoring is needed first. 2301444e7516SDavid Sterba */ 2302444e7516SDavid Sterba sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 2303444e7516SDavid Sterba ret = sysfs_create_group(fsid_kobj, &btrfs_feature_attr_group); 2304444e7516SDavid Sterba } 2305444e7516SDavid Sterba 2306f5c29bd9SLiu Bo int __init btrfs_init_sysfs(void) 230758176a96SJosef Bacik { 2308079b72bcSJeff Mahoney int ret; 23091bae3098SDavid Sterba 2310e3fe4e71SGreg KH btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); 2311e3fe4e71SGreg KH if (!btrfs_kset) 2312e3fe4e71SGreg KH return -ENOMEM; 2313079b72bcSJeff Mahoney 23141bae3098SDavid Sterba init_feature_attrs(); 23151bae3098SDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2316001a648dSFilipe Manana if (ret) 2317001a648dSFilipe Manana goto out2; 2318f902bd3aSMisono Tomohiro ret = sysfs_merge_group(&btrfs_kset->kobj, 2319f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2320f902bd3aSMisono Tomohiro if (ret) 2321f902bd3aSMisono Tomohiro goto out_remove_group; 2322001a648dSFilipe Manana 23236e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 23246e369febSDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 2325ffdbb44fSZhen Lei if (ret) { 2326ffdbb44fSZhen Lei sysfs_unmerge_group(&btrfs_kset->kobj, 2327ffdbb44fSZhen Lei &btrfs_static_feature_attr_group); 2328ffdbb44fSZhen Lei goto out_remove_group; 2329ffdbb44fSZhen Lei } 23306e369febSDavid Sterba #endif 23316e369febSDavid Sterba 2332001a648dSFilipe Manana return 0; 2333f902bd3aSMisono Tomohiro 2334f902bd3aSMisono Tomohiro out_remove_group: 2335f902bd3aSMisono Tomohiro sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2336001a648dSFilipe Manana out2: 2337001a648dSFilipe Manana kset_unregister(btrfs_kset); 23381bae3098SDavid Sterba 23391bae3098SDavid Sterba return ret; 234058176a96SJosef Bacik } 234158176a96SJosef Bacik 2342e67c718bSDavid Sterba void __cold btrfs_exit_sysfs(void) 234358176a96SJosef Bacik { 2344f902bd3aSMisono Tomohiro sysfs_unmerge_group(&btrfs_kset->kobj, 2345f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2346079b72bcSJeff Mahoney sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 234771e8978eSDennis Zhou #ifdef CONFIG_BTRFS_DEBUG 234871e8978eSDennis Zhou sysfs_remove_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 234971e8978eSDennis Zhou #endif 2350e3fe4e71SGreg KH kset_unregister(btrfs_kset); 235158176a96SJosef Bacik } 2352