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" 2607e81dc9SJosef Bacik #include "accessors.h" 27079b72bcSJeff Mahoney 28e7849e33SAnand Jain /* 29e7849e33SAnand Jain * Structure name Path 30e7849e33SAnand Jain * -------------------------------------------------------------------------- 31e7849e33SAnand Jain * btrfs_supported_static_feature_attrs /sys/fs/btrfs/features 32e7849e33SAnand Jain * btrfs_supported_feature_attrs /sys/fs/btrfs/features and 33e7849e33SAnand Jain * /sys/fs/btrfs/<uuid>/features 34e7849e33SAnand Jain * btrfs_attrs /sys/fs/btrfs/<uuid> 35e7849e33SAnand Jain * devid_attrs /sys/fs/btrfs/<uuid>/devinfo/<devid> 36e7849e33SAnand Jain * allocation_attrs /sys/fs/btrfs/<uuid>/allocation 37e7849e33SAnand Jain * qgroup_attrs /sys/fs/btrfs/<uuid>/qgroups/<level>_<qgroupid> 38e7849e33SAnand Jain * space_info_attrs /sys/fs/btrfs/<uuid>/allocation/<bg-type> 39e7849e33SAnand Jain * raid_attrs /sys/fs/btrfs/<uuid>/allocation/<bg-type>/<bg-profile> 40fb731430SDavid Sterba * discard_attrs /sys/fs/btrfs/<uuid>/discard 41e7849e33SAnand Jain * 42e7849e33SAnand Jain * When built with BTRFS_CONFIG_DEBUG: 43e7849e33SAnand Jain * 44e7849e33SAnand Jain * btrfs_debug_feature_attrs /sys/fs/btrfs/debug 45e7849e33SAnand Jain * btrfs_debug_mount_attrs /sys/fs/btrfs/<uuid>/debug 46e7849e33SAnand Jain */ 47e7849e33SAnand Jain 489188db61SDavid Sterba struct btrfs_feature_attr { 499188db61SDavid Sterba struct kobj_attribute kobj_attr; 509188db61SDavid Sterba enum btrfs_feature_set feature_set; 519188db61SDavid Sterba u64 feature_bit; 529188db61SDavid Sterba }; 539188db61SDavid Sterba 549188db61SDavid Sterba /* For raid type sysfs entries */ 559188db61SDavid Sterba struct raid_kobject { 569188db61SDavid Sterba u64 flags; 579188db61SDavid Sterba struct kobject kobj; 589188db61SDavid Sterba }; 599188db61SDavid Sterba 609188db61SDavid Sterba #define __INIT_KOBJ_ATTR(_name, _mode, _show, _store) \ 619188db61SDavid Sterba { \ 629188db61SDavid Sterba .attr = { .name = __stringify(_name), .mode = _mode }, \ 639188db61SDavid Sterba .show = _show, \ 649188db61SDavid Sterba .store = _store, \ 659188db61SDavid Sterba } 669188db61SDavid Sterba 6722c55e3bSStefan Roesch #define BTRFS_ATTR_W(_prefix, _name, _store) \ 6822c55e3bSStefan Roesch static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 6922c55e3bSStefan Roesch __INIT_KOBJ_ATTR(_name, 0200, NULL, _store) 7022c55e3bSStefan Roesch 719188db61SDavid Sterba #define BTRFS_ATTR_RW(_prefix, _name, _show, _store) \ 729188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 739188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0644, _show, _store) 749188db61SDavid Sterba 759188db61SDavid Sterba #define BTRFS_ATTR(_prefix, _name, _show) \ 769188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 779188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0444, _show, NULL) 789188db61SDavid Sterba 799188db61SDavid Sterba #define BTRFS_ATTR_PTR(_prefix, _name) \ 809188db61SDavid Sterba (&btrfs_attr_##_prefix##_##_name.attr) 819188db61SDavid Sterba 829188db61SDavid Sterba #define BTRFS_FEAT_ATTR(_name, _feature_set, _feature_prefix, _feature_bit) \ 839188db61SDavid Sterba static struct btrfs_feature_attr btrfs_attr_features_##_name = { \ 849188db61SDavid Sterba .kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO, \ 859188db61SDavid Sterba btrfs_feature_attr_show, \ 869188db61SDavid Sterba btrfs_feature_attr_store), \ 879188db61SDavid Sterba .feature_set = _feature_set, \ 889188db61SDavid Sterba .feature_bit = _feature_prefix ##_## _feature_bit, \ 899188db61SDavid Sterba } 909188db61SDavid Sterba #define BTRFS_FEAT_ATTR_PTR(_name) \ 919188db61SDavid Sterba (&btrfs_attr_features_##_name.kobj_attr.attr) 929188db61SDavid Sterba 939188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT(name, feature) \ 949188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT, BTRFS_FEATURE_COMPAT, feature) 959188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT_RO(name, feature) \ 969188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT_RO, BTRFS_FEATURE_COMPAT_RO, feature) 979188db61SDavid Sterba #define BTRFS_FEAT_ATTR_INCOMPAT(name, feature) \ 989188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_INCOMPAT, BTRFS_FEATURE_INCOMPAT, feature) 999188db61SDavid Sterba 100510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); 1012e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj); 10219fc516aSStefan Roesch static struct kobject *get_btrfs_kobj(struct kobject *kobj); 1035ac1d209SJeff Mahoney 1048f52316cSDavid Sterba static struct btrfs_feature_attr *to_btrfs_feature_attr(struct kobj_attribute *a) 1058f52316cSDavid Sterba { 1068f52316cSDavid Sterba return container_of(a, struct btrfs_feature_attr, kobj_attr); 1078f52316cSDavid Sterba } 1088f52316cSDavid Sterba 1098f52316cSDavid Sterba static struct kobj_attribute *attr_to_btrfs_attr(struct attribute *attr) 1108f52316cSDavid Sterba { 1118f52316cSDavid Sterba return container_of(attr, struct kobj_attribute, attr); 1128f52316cSDavid Sterba } 1138f52316cSDavid Sterba 1148f52316cSDavid Sterba static struct btrfs_feature_attr *attr_to_btrfs_feature_attr( 1158f52316cSDavid Sterba struct attribute *attr) 1168f52316cSDavid Sterba { 1178f52316cSDavid Sterba return to_btrfs_feature_attr(attr_to_btrfs_attr(attr)); 1188f52316cSDavid Sterba } 1198f52316cSDavid Sterba 120510d7360SJeff Mahoney static u64 get_features(struct btrfs_fs_info *fs_info, 121510d7360SJeff Mahoney enum btrfs_feature_set set) 1225ac1d209SJeff Mahoney { 123510d7360SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 124510d7360SJeff Mahoney if (set == FEAT_COMPAT) 125510d7360SJeff Mahoney return btrfs_super_compat_flags(disk_super); 126510d7360SJeff Mahoney else if (set == FEAT_COMPAT_RO) 127510d7360SJeff Mahoney return btrfs_super_compat_ro_flags(disk_super); 128510d7360SJeff Mahoney else 129510d7360SJeff Mahoney return btrfs_super_incompat_flags(disk_super); 1305ac1d209SJeff Mahoney } 1315ac1d209SJeff Mahoney 132ba631941SJeff Mahoney static void set_features(struct btrfs_fs_info *fs_info, 133ba631941SJeff Mahoney enum btrfs_feature_set set, u64 features) 134ba631941SJeff Mahoney { 135ba631941SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 136ba631941SJeff Mahoney if (set == FEAT_COMPAT) 137ba631941SJeff Mahoney btrfs_set_super_compat_flags(disk_super, features); 138ba631941SJeff Mahoney else if (set == FEAT_COMPAT_RO) 139ba631941SJeff Mahoney btrfs_set_super_compat_ro_flags(disk_super, features); 140ba631941SJeff Mahoney else 141ba631941SJeff Mahoney btrfs_set_super_incompat_flags(disk_super, features); 142ba631941SJeff Mahoney } 143ba631941SJeff Mahoney 144ba631941SJeff Mahoney static int can_modify_feature(struct btrfs_feature_attr *fa) 145ba631941SJeff Mahoney { 146ba631941SJeff Mahoney int val = 0; 147ba631941SJeff Mahoney u64 set, clear; 148ba631941SJeff Mahoney switch (fa->feature_set) { 149ba631941SJeff Mahoney case FEAT_COMPAT: 150ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 151ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 152ba631941SJeff Mahoney break; 153ba631941SJeff Mahoney case FEAT_COMPAT_RO: 154ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 155ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 156ba631941SJeff Mahoney break; 157ba631941SJeff Mahoney case FEAT_INCOMPAT: 158ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 159ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 160ba631941SJeff Mahoney break; 161ba631941SJeff Mahoney default: 16262e85577SJeff Mahoney pr_warn("btrfs: sysfs: unknown feature set %d\n", 163cc37bb04SDavid Sterba fa->feature_set); 164cc37bb04SDavid Sterba return 0; 165ba631941SJeff Mahoney } 166ba631941SJeff Mahoney 167ba631941SJeff Mahoney if (set & fa->feature_bit) 168ba631941SJeff Mahoney val |= 1; 169ba631941SJeff Mahoney if (clear & fa->feature_bit) 170ba631941SJeff Mahoney val |= 2; 171ba631941SJeff Mahoney 172ba631941SJeff Mahoney return val; 173ba631941SJeff Mahoney } 174ba631941SJeff Mahoney 175079b72bcSJeff Mahoney static ssize_t btrfs_feature_attr_show(struct kobject *kobj, 176079b72bcSJeff Mahoney struct kobj_attribute *a, char *buf) 177079b72bcSJeff Mahoney { 178510d7360SJeff Mahoney int val = 0; 179510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 180510d7360SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 181ba631941SJeff Mahoney if (fs_info) { 182510d7360SJeff Mahoney u64 features = get_features(fs_info, fa->feature_set); 183510d7360SJeff Mahoney if (features & fa->feature_bit) 184510d7360SJeff Mahoney val = 1; 185ba631941SJeff Mahoney } else 186ba631941SJeff Mahoney val = can_modify_feature(fa); 187510d7360SJeff Mahoney 188020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 189510d7360SJeff Mahoney } 190510d7360SJeff Mahoney 191ba631941SJeff Mahoney static ssize_t btrfs_feature_attr_store(struct kobject *kobj, 192ba631941SJeff Mahoney struct kobj_attribute *a, 193ba631941SJeff Mahoney const char *buf, size_t count) 194ba631941SJeff Mahoney { 195ba631941SJeff Mahoney struct btrfs_fs_info *fs_info; 196ba631941SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 197ba631941SJeff Mahoney u64 features, set, clear; 198ba631941SJeff Mahoney unsigned long val; 199ba631941SJeff Mahoney int ret; 200ba631941SJeff Mahoney 201ba631941SJeff Mahoney fs_info = to_fs_info(kobj); 202ba631941SJeff Mahoney if (!fs_info) 203ba631941SJeff Mahoney return -EPERM; 204ba631941SJeff Mahoney 205bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 206ee611138SDavid Sterba return -EROFS; 207ee611138SDavid Sterba 208ba631941SJeff Mahoney ret = kstrtoul(skip_spaces(buf), 0, &val); 209ba631941SJeff Mahoney if (ret) 210ba631941SJeff Mahoney return ret; 211ba631941SJeff Mahoney 212ba631941SJeff Mahoney if (fa->feature_set == FEAT_COMPAT) { 213ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 214ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 215ba631941SJeff Mahoney } else if (fa->feature_set == FEAT_COMPAT_RO) { 216ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 217ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 218ba631941SJeff Mahoney } else { 219ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 220ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 221ba631941SJeff Mahoney } 222ba631941SJeff Mahoney 223ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 224ba631941SJeff Mahoney 225ba631941SJeff Mahoney /* Nothing to do */ 226ba631941SJeff Mahoney if ((val && (features & fa->feature_bit)) || 227ba631941SJeff Mahoney (!val && !(features & fa->feature_bit))) 228ba631941SJeff Mahoney return count; 229ba631941SJeff Mahoney 230ba631941SJeff Mahoney if ((val && !(set & fa->feature_bit)) || 231ba631941SJeff Mahoney (!val && !(clear & fa->feature_bit))) { 232ba631941SJeff Mahoney btrfs_info(fs_info, 233ba631941SJeff Mahoney "%sabling feature %s on mounted fs is not supported.", 234ba631941SJeff Mahoney val ? "En" : "Dis", fa->kobj_attr.attr.name); 235ba631941SJeff Mahoney return -EPERM; 236ba631941SJeff Mahoney } 237ba631941SJeff Mahoney 238ba631941SJeff Mahoney btrfs_info(fs_info, "%s %s feature flag", 239ba631941SJeff Mahoney val ? "Setting" : "Clearing", fa->kobj_attr.attr.name); 240ba631941SJeff Mahoney 241ba631941SJeff Mahoney spin_lock(&fs_info->super_lock); 242ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 243ba631941SJeff Mahoney if (val) 244ba631941SJeff Mahoney features |= fa->feature_bit; 245ba631941SJeff Mahoney else 246ba631941SJeff Mahoney features &= ~fa->feature_bit; 247ba631941SJeff Mahoney set_features(fs_info, fa->feature_set, features); 248ba631941SJeff Mahoney spin_unlock(&fs_info->super_lock); 249ba631941SJeff Mahoney 2500eae2747SDavid Sterba /* 2510eae2747SDavid Sterba * We don't want to do full transaction commit from inside sysfs 2520eae2747SDavid Sterba */ 253c52cc7b7SJosef Bacik set_bit(BTRFS_FS_NEED_TRANS_COMMIT, &fs_info->flags); 2540eae2747SDavid Sterba wake_up_process(fs_info->transaction_kthread); 255ba631941SJeff Mahoney 256ba631941SJeff Mahoney return count; 257ba631941SJeff Mahoney } 258ba631941SJeff Mahoney 259510d7360SJeff Mahoney static umode_t btrfs_feature_visible(struct kobject *kobj, 260510d7360SJeff Mahoney struct attribute *attr, int unused) 261510d7360SJeff Mahoney { 262510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 263510d7360SJeff Mahoney umode_t mode = attr->mode; 264510d7360SJeff Mahoney 265510d7360SJeff Mahoney if (fs_info) { 266510d7360SJeff Mahoney struct btrfs_feature_attr *fa; 267510d7360SJeff Mahoney u64 features; 268510d7360SJeff Mahoney 269510d7360SJeff Mahoney fa = attr_to_btrfs_feature_attr(attr); 270510d7360SJeff Mahoney features = get_features(fs_info, fa->feature_set); 271510d7360SJeff Mahoney 272ba631941SJeff Mahoney if (can_modify_feature(fa)) 273ba631941SJeff Mahoney mode |= S_IWUSR; 274ba631941SJeff Mahoney else if (!(features & fa->feature_bit)) 275510d7360SJeff Mahoney mode = 0; 276510d7360SJeff Mahoney } 277510d7360SJeff Mahoney 278510d7360SJeff Mahoney return mode; 279079b72bcSJeff Mahoney } 280079b72bcSJeff Mahoney 281079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL); 282079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS); 283079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO); 2845c1aab1dSNick Terrell BTRFS_FEAT_ATTR_INCOMPAT(compress_zstd, COMPRESS_ZSTD); 285079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF); 286079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56); 287079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA); 288c736c095SDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES); 28956f20f40SNikolay Borisov BTRFS_FEAT_ATTR_INCOMPAT(metadata_uuid, METADATA_UUID); 2903b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE); 2911c56ab99SQu Wenruo BTRFS_FEAT_ATTR_COMPAT_RO(block_group_tree, BLOCK_GROUP_TREE); 292cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(raid1c34, RAID1C34); 29315dcccdbSDavid Sterba #ifdef CONFIG_BLK_DEV_ZONED 2947b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_INCOMPAT(zoned, ZONED); 29515dcccdbSDavid Sterba #endif 29615dcccdbSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 2972c7d2a23SJosef Bacik /* Remove once support for extent tree v2 is feature complete */ 2982c7d2a23SJosef Bacik BTRFS_FEAT_ATTR_INCOMPAT(extent_tree_v2, EXTENT_TREE_V2); 2997b3d5a90SNaohiro Aota #endif 30014605409SBoris Burkov #ifdef CONFIG_FS_VERITY 30114605409SBoris Burkov BTRFS_FEAT_ATTR_COMPAT_RO(verity, VERITY); 30214605409SBoris Burkov #endif 303079b72bcSJeff Mahoney 304e7849e33SAnand Jain /* 305e7849e33SAnand Jain * Features which depend on feature bits and may differ between each fs. 306e7849e33SAnand Jain * 307143823cfSDavid Sterba * /sys/fs/btrfs/features - all available features implemented by this version 308e7849e33SAnand Jain * /sys/fs/btrfs/UUID/features - features of the fs which are enabled or 309e7849e33SAnand Jain * can be changed on a mounted filesystem. 310e7849e33SAnand Jain */ 311079b72bcSJeff Mahoney static struct attribute *btrfs_supported_feature_attrs[] = { 312079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(default_subvol), 313079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_groups), 314079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(compress_lzo), 3155c1aab1dSNick Terrell BTRFS_FEAT_ATTR_PTR(compress_zstd), 316079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(extended_iref), 317079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(raid56), 318079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(skinny_metadata), 319c736c095SDavid Sterba BTRFS_FEAT_ATTR_PTR(no_holes), 32056f20f40SNikolay Borisov BTRFS_FEAT_ATTR_PTR(metadata_uuid), 3213b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_PTR(free_space_tree), 322cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_PTR(raid1c34), 3231c56ab99SQu Wenruo BTRFS_FEAT_ATTR_PTR(block_group_tree), 32415dcccdbSDavid Sterba #ifdef CONFIG_BLK_DEV_ZONED 3257b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_PTR(zoned), 32615dcccdbSDavid Sterba #endif 32715dcccdbSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 3282c7d2a23SJosef Bacik BTRFS_FEAT_ATTR_PTR(extent_tree_v2), 3297b3d5a90SNaohiro Aota #endif 33014605409SBoris Burkov #ifdef CONFIG_FS_VERITY 33114605409SBoris Burkov BTRFS_FEAT_ATTR_PTR(verity), 33214605409SBoris Burkov #endif 333079b72bcSJeff Mahoney NULL 334079b72bcSJeff Mahoney }; 335079b72bcSJeff Mahoney 336079b72bcSJeff Mahoney static const struct attribute_group btrfs_feature_attr_group = { 337079b72bcSJeff Mahoney .name = "features", 338510d7360SJeff Mahoney .is_visible = btrfs_feature_visible, 339079b72bcSJeff Mahoney .attrs = btrfs_supported_feature_attrs, 340079b72bcSJeff Mahoney }; 34158176a96SJosef Bacik 342f902bd3aSMisono Tomohiro static ssize_t rmdir_subvol_show(struct kobject *kobj, 343f902bd3aSMisono Tomohiro struct kobj_attribute *ka, char *buf) 344f902bd3aSMisono Tomohiro { 345020e5277SAnand Jain return sysfs_emit(buf, "0\n"); 346f902bd3aSMisono Tomohiro } 347f902bd3aSMisono Tomohiro BTRFS_ATTR(static_feature, rmdir_subvol, rmdir_subvol_show); 348f902bd3aSMisono Tomohiro 349f7cea56cSDavid Sterba static ssize_t supported_checksums_show(struct kobject *kobj, 350f7cea56cSDavid Sterba struct kobj_attribute *a, char *buf) 351f7cea56cSDavid Sterba { 352f7cea56cSDavid Sterba ssize_t ret = 0; 353f7cea56cSDavid Sterba int i; 354f7cea56cSDavid Sterba 355f7cea56cSDavid Sterba for (i = 0; i < btrfs_get_num_csums(); i++) { 356f7cea56cSDavid Sterba /* 357f7cea56cSDavid Sterba * This "trick" only works as long as 'enum btrfs_csum_type' has 358f7cea56cSDavid Sterba * no holes in it 359f7cea56cSDavid Sterba */ 360020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i == 0 ? "" : " "), 361020e5277SAnand Jain btrfs_super_csum_name(i)); 362f7cea56cSDavid Sterba 363f7cea56cSDavid Sterba } 364f7cea56cSDavid Sterba 365020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 366f7cea56cSDavid Sterba return ret; 367f7cea56cSDavid Sterba } 368f7cea56cSDavid Sterba BTRFS_ATTR(static_feature, supported_checksums, supported_checksums_show); 369f7cea56cSDavid Sterba 3707573df55SOmar Sandoval static ssize_t send_stream_version_show(struct kobject *kobj, 3717573df55SOmar Sandoval struct kobj_attribute *ka, char *buf) 3727573df55SOmar Sandoval { 373020e5277SAnand Jain return sysfs_emit(buf, "%d\n", BTRFS_SEND_STREAM_VERSION); 3747573df55SOmar Sandoval } 3757573df55SOmar Sandoval BTRFS_ATTR(static_feature, send_stream_version, send_stream_version_show); 3767573df55SOmar Sandoval 377ceafe3ccSJosef Bacik static const char *rescue_opts[] = { 378ceafe3ccSJosef Bacik "usebackuproot", 379ceafe3ccSJosef Bacik "nologreplay", 38042437a63SJosef Bacik "ignorebadroots", 381882dbe0cSJosef Bacik "ignoredatacsums", 3829037d3cbSJosef Bacik "all", 383ceafe3ccSJosef Bacik }; 384ceafe3ccSJosef Bacik 385ceafe3ccSJosef Bacik static ssize_t supported_rescue_options_show(struct kobject *kobj, 386ceafe3ccSJosef Bacik struct kobj_attribute *a, 387ceafe3ccSJosef Bacik char *buf) 388ceafe3ccSJosef Bacik { 389ceafe3ccSJosef Bacik ssize_t ret = 0; 390ceafe3ccSJosef Bacik int i; 391ceafe3ccSJosef Bacik 392ceafe3ccSJosef Bacik for (i = 0; i < ARRAY_SIZE(rescue_opts); i++) 393020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i ? " " : ""), rescue_opts[i]); 394020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 395ceafe3ccSJosef Bacik return ret; 396ceafe3ccSJosef Bacik } 397ceafe3ccSJosef Bacik BTRFS_ATTR(static_feature, supported_rescue_options, 398ceafe3ccSJosef Bacik supported_rescue_options_show); 399ceafe3ccSJosef Bacik 400fc57ad8dSQu Wenruo static ssize_t supported_sectorsizes_show(struct kobject *kobj, 401fc57ad8dSQu Wenruo struct kobj_attribute *a, 402fc57ad8dSQu Wenruo char *buf) 403fc57ad8dSQu Wenruo { 404fc57ad8dSQu Wenruo ssize_t ret = 0; 405fc57ad8dSQu Wenruo 4061a42daabSQu Wenruo /* An artificial limit to only support 4K and PAGE_SIZE */ 4071a42daabSQu Wenruo if (PAGE_SIZE > SZ_4K) 408020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%u ", SZ_4K); 409020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%lu\n", PAGE_SIZE); 410fc57ad8dSQu Wenruo 411fc57ad8dSQu Wenruo return ret; 412fc57ad8dSQu Wenruo } 413fc57ad8dSQu Wenruo BTRFS_ATTR(static_feature, supported_sectorsizes, 414fc57ad8dSQu Wenruo supported_sectorsizes_show); 415fc57ad8dSQu Wenruo 416e7849e33SAnand Jain /* 417e7849e33SAnand Jain * Features which only depend on kernel version. 418e7849e33SAnand Jain * 419e7849e33SAnand Jain * These are listed in /sys/fs/btrfs/features along with 420e7849e33SAnand Jain * btrfs_supported_feature_attrs. 421e7849e33SAnand Jain */ 422f902bd3aSMisono Tomohiro static struct attribute *btrfs_supported_static_feature_attrs[] = { 423f902bd3aSMisono Tomohiro BTRFS_ATTR_PTR(static_feature, rmdir_subvol), 424f7cea56cSDavid Sterba BTRFS_ATTR_PTR(static_feature, supported_checksums), 4257573df55SOmar Sandoval BTRFS_ATTR_PTR(static_feature, send_stream_version), 426ceafe3ccSJosef Bacik BTRFS_ATTR_PTR(static_feature, supported_rescue_options), 427fc57ad8dSQu Wenruo BTRFS_ATTR_PTR(static_feature, supported_sectorsizes), 428f902bd3aSMisono Tomohiro NULL 429f902bd3aSMisono Tomohiro }; 430f902bd3aSMisono Tomohiro 431f902bd3aSMisono Tomohiro static const struct attribute_group btrfs_static_feature_attr_group = { 432f902bd3aSMisono Tomohiro .name = "features", 433f902bd3aSMisono Tomohiro .attrs = btrfs_supported_static_feature_attrs, 434f902bd3aSMisono Tomohiro }; 435f902bd3aSMisono Tomohiro 4366e369febSDavid Sterba /* 437e4faab84SDennis Zhou * Discard statistics and tunables 438e4faab84SDennis Zhou */ 439fb731430SDavid Sterba #define discard_to_fs_info(_kobj) to_fs_info(get_btrfs_kobj(_kobj)) 440dfb79ddbSDennis Zhou 4415dc7c10bSDennis Zhou static ssize_t btrfs_discardable_bytes_show(struct kobject *kobj, 4425dc7c10bSDennis Zhou struct kobj_attribute *a, 4435dc7c10bSDennis Zhou char *buf) 4445dc7c10bSDennis Zhou { 4455dc7c10bSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4465dc7c10bSDennis Zhou 447020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4485dc7c10bSDennis Zhou atomic64_read(&fs_info->discard_ctl.discardable_bytes)); 4495dc7c10bSDennis Zhou } 4505dc7c10bSDennis Zhou BTRFS_ATTR(discard, discardable_bytes, btrfs_discardable_bytes_show); 4515dc7c10bSDennis Zhou 452dfb79ddbSDennis Zhou static ssize_t btrfs_discardable_extents_show(struct kobject *kobj, 453dfb79ddbSDennis Zhou struct kobj_attribute *a, 454dfb79ddbSDennis Zhou char *buf) 455dfb79ddbSDennis Zhou { 456dfb79ddbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 457dfb79ddbSDennis Zhou 458020e5277SAnand Jain return sysfs_emit(buf, "%d\n", 459dfb79ddbSDennis Zhou atomic_read(&fs_info->discard_ctl.discardable_extents)); 460dfb79ddbSDennis Zhou } 461dfb79ddbSDennis Zhou BTRFS_ATTR(discard, discardable_extents, btrfs_discardable_extents_show); 462dfb79ddbSDennis Zhou 4639ddf648fSDennis Zhou static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj, 4649ddf648fSDennis Zhou struct kobj_attribute *a, 4659ddf648fSDennis Zhou char *buf) 4669ddf648fSDennis Zhou { 4679ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4689ddf648fSDennis Zhou 469020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4709ddf648fSDennis Zhou fs_info->discard_ctl.discard_bitmap_bytes); 4719ddf648fSDennis Zhou } 4729ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bitmap_bytes, btrfs_discard_bitmap_bytes_show); 4739ddf648fSDennis Zhou 4749ddf648fSDennis Zhou static ssize_t btrfs_discard_bytes_saved_show(struct kobject *kobj, 4759ddf648fSDennis Zhou struct kobj_attribute *a, 4769ddf648fSDennis Zhou char *buf) 4779ddf648fSDennis Zhou { 4789ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4799ddf648fSDennis Zhou 480020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4819ddf648fSDennis Zhou atomic64_read(&fs_info->discard_ctl.discard_bytes_saved)); 4829ddf648fSDennis Zhou } 4839ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bytes_saved, btrfs_discard_bytes_saved_show); 4849ddf648fSDennis Zhou 4859ddf648fSDennis Zhou static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj, 4869ddf648fSDennis Zhou struct kobj_attribute *a, 4879ddf648fSDennis Zhou char *buf) 4889ddf648fSDennis Zhou { 4899ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4909ddf648fSDennis Zhou 491020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4929ddf648fSDennis Zhou fs_info->discard_ctl.discard_extent_bytes); 4939ddf648fSDennis Zhou } 4949ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_extent_bytes, btrfs_discard_extent_bytes_show); 4959ddf648fSDennis Zhou 496a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_show(struct kobject *kobj, 497a2309300SDennis Zhou struct kobj_attribute *a, 498a2309300SDennis Zhou char *buf) 499a2309300SDennis Zhou { 500a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 501a2309300SDennis Zhou 502020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 503a2309300SDennis Zhou READ_ONCE(fs_info->discard_ctl.iops_limit)); 504a2309300SDennis Zhou } 505a2309300SDennis Zhou 506a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_store(struct kobject *kobj, 507a2309300SDennis Zhou struct kobj_attribute *a, 508a2309300SDennis Zhou const char *buf, size_t len) 509a2309300SDennis Zhou { 510a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 511a2309300SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 512a2309300SDennis Zhou u32 iops_limit; 513a2309300SDennis Zhou int ret; 514a2309300SDennis Zhou 515a2309300SDennis Zhou ret = kstrtou32(buf, 10, &iops_limit); 516a2309300SDennis Zhou if (ret) 517a2309300SDennis Zhou return -EINVAL; 518a2309300SDennis Zhou 519a2309300SDennis Zhou WRITE_ONCE(discard_ctl->iops_limit, iops_limit); 5203e48d8d2SPavel Begunkov btrfs_discard_calc_delay(discard_ctl); 5213e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 522a2309300SDennis Zhou return len; 523a2309300SDennis Zhou } 524a2309300SDennis Zhou BTRFS_ATTR_RW(discard, iops_limit, btrfs_discard_iops_limit_show, 525a2309300SDennis Zhou btrfs_discard_iops_limit_store); 526a2309300SDennis Zhou 527e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_show(struct kobject *kobj, 528e93591bbSDennis Zhou struct kobj_attribute *a, 529e93591bbSDennis Zhou char *buf) 530e93591bbSDennis Zhou { 531e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 532e93591bbSDennis Zhou 533020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 534e93591bbSDennis Zhou READ_ONCE(fs_info->discard_ctl.kbps_limit)); 535e93591bbSDennis Zhou } 536e93591bbSDennis Zhou 537e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_store(struct kobject *kobj, 538e93591bbSDennis Zhou struct kobj_attribute *a, 539e93591bbSDennis Zhou const char *buf, size_t len) 540e93591bbSDennis Zhou { 541e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 542e93591bbSDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 543e93591bbSDennis Zhou u32 kbps_limit; 544e93591bbSDennis Zhou int ret; 545e93591bbSDennis Zhou 546e93591bbSDennis Zhou ret = kstrtou32(buf, 10, &kbps_limit); 547e93591bbSDennis Zhou if (ret) 548e93591bbSDennis Zhou return -EINVAL; 549e93591bbSDennis Zhou 550e93591bbSDennis Zhou WRITE_ONCE(discard_ctl->kbps_limit, kbps_limit); 5513e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 552e93591bbSDennis Zhou return len; 553e93591bbSDennis Zhou } 554e93591bbSDennis Zhou BTRFS_ATTR_RW(discard, kbps_limit, btrfs_discard_kbps_limit_show, 555e93591bbSDennis Zhou btrfs_discard_kbps_limit_store); 556e93591bbSDennis Zhou 55719b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_show(struct kobject *kobj, 55819b2a2c7SDennis Zhou struct kobj_attribute *a, 55919b2a2c7SDennis Zhou char *buf) 56019b2a2c7SDennis Zhou { 56119b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 56219b2a2c7SDennis Zhou 563020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 56419b2a2c7SDennis Zhou READ_ONCE(fs_info->discard_ctl.max_discard_size)); 56519b2a2c7SDennis Zhou } 56619b2a2c7SDennis Zhou 56719b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_store(struct kobject *kobj, 56819b2a2c7SDennis Zhou struct kobj_attribute *a, 56919b2a2c7SDennis Zhou const char *buf, size_t len) 57019b2a2c7SDennis Zhou { 57119b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 57219b2a2c7SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 57319b2a2c7SDennis Zhou u64 max_discard_size; 57419b2a2c7SDennis Zhou int ret; 57519b2a2c7SDennis Zhou 57619b2a2c7SDennis Zhou ret = kstrtou64(buf, 10, &max_discard_size); 57719b2a2c7SDennis Zhou if (ret) 57819b2a2c7SDennis Zhou return -EINVAL; 57919b2a2c7SDennis Zhou 58019b2a2c7SDennis Zhou WRITE_ONCE(discard_ctl->max_discard_size, max_discard_size); 58119b2a2c7SDennis Zhou 58219b2a2c7SDennis Zhou return len; 58319b2a2c7SDennis Zhou } 58419b2a2c7SDennis Zhou BTRFS_ATTR_RW(discard, max_discard_size, btrfs_discard_max_discard_size_show, 58519b2a2c7SDennis Zhou btrfs_discard_max_discard_size_store); 58619b2a2c7SDennis Zhou 587e7849e33SAnand Jain /* 588fb731430SDavid Sterba * Per-filesystem stats for discard (when mounted with discard=async). 589e7849e33SAnand Jain * 590fb731430SDavid Sterba * Path: /sys/fs/btrfs/<uuid>/discard/ 591e7849e33SAnand Jain */ 592fb731430SDavid Sterba static const struct attribute *discard_attrs[] = { 5935dc7c10bSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_bytes), 594dfb79ddbSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_extents), 5959ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bitmap_bytes), 5969ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bytes_saved), 5979ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_extent_bytes), 598a2309300SDennis Zhou BTRFS_ATTR_PTR(discard, iops_limit), 599e93591bbSDennis Zhou BTRFS_ATTR_PTR(discard, kbps_limit), 60019b2a2c7SDennis Zhou BTRFS_ATTR_PTR(discard, max_discard_size), 601e4faab84SDennis Zhou NULL, 602e4faab84SDennis Zhou }; 603e4faab84SDennis Zhou 604fb731430SDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 605fb731430SDavid Sterba 606e4faab84SDennis Zhou /* 607e7849e33SAnand Jain * Per-filesystem runtime debugging exported via sysfs. 6086e369febSDavid Sterba * 609e7849e33SAnand Jain * Path: /sys/fs/btrfs/UUID/debug/ 6106e369febSDavid Sterba */ 61193945cb4SDennis Zhou static const struct attribute *btrfs_debug_mount_attrs[] = { 61293945cb4SDennis Zhou NULL, 61393945cb4SDennis Zhou }; 61493945cb4SDennis Zhou 615e7849e33SAnand Jain /* 616e7849e33SAnand Jain * Runtime debugging exported via sysfs, applies to all mounted filesystems. 617e7849e33SAnand Jain * 618e7849e33SAnand Jain * Path: /sys/fs/btrfs/debug 619e7849e33SAnand Jain */ 6206e369febSDavid Sterba static struct attribute *btrfs_debug_feature_attrs[] = { 6216e369febSDavid Sterba NULL 6226e369febSDavid Sterba }; 6236e369febSDavid Sterba 6246e369febSDavid Sterba static const struct attribute_group btrfs_debug_feature_attr_group = { 6256e369febSDavid Sterba .name = "debug", 6266e369febSDavid Sterba .attrs = btrfs_debug_feature_attrs, 6276e369febSDavid Sterba }; 6286e369febSDavid Sterba 6296e369febSDavid Sterba #endif 6306e369febSDavid Sterba 6316ab0a202SJeff Mahoney static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf) 6326ab0a202SJeff Mahoney { 6336ab0a202SJeff Mahoney u64 val; 6346ab0a202SJeff Mahoney if (lock) 6356ab0a202SJeff Mahoney spin_lock(lock); 6366ab0a202SJeff Mahoney val = *value_ptr; 6376ab0a202SJeff Mahoney if (lock) 6386ab0a202SJeff Mahoney spin_unlock(lock); 639020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6406ab0a202SJeff Mahoney } 6416ab0a202SJeff Mahoney 6426ab0a202SJeff Mahoney static ssize_t global_rsv_size_show(struct kobject *kobj, 6436ab0a202SJeff Mahoney struct kobj_attribute *ka, char *buf) 6446ab0a202SJeff Mahoney { 6456ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6466ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6476ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf); 6486ab0a202SJeff Mahoney } 649a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_size, global_rsv_size_show); 6506ab0a202SJeff Mahoney 6516ab0a202SJeff Mahoney static ssize_t global_rsv_reserved_show(struct kobject *kobj, 6526ab0a202SJeff Mahoney struct kobj_attribute *a, char *buf) 6536ab0a202SJeff Mahoney { 6546ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6556ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6566ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf); 6576ab0a202SJeff Mahoney } 658a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_reserved, global_rsv_reserved_show); 6596ab0a202SJeff Mahoney 6606ab0a202SJeff Mahoney #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj) 661c1895442SJeff Mahoney #define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj) 6626ab0a202SJeff Mahoney 6636ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6646ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf); 665a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, total_bytes, raid_bytes_show); 666a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, used_bytes, raid_bytes_show); 6676ab0a202SJeff Mahoney 6686ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6696ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf) 6706ab0a202SJeff Mahoney 6716ab0a202SJeff Mahoney { 6726ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj->parent); 67332da5386SDavid Sterba struct btrfs_block_group *block_group; 67475cb379dSJeff Mahoney int index = btrfs_bg_flags_to_raid_index(to_raid_kobj(kobj)->flags); 6756ab0a202SJeff Mahoney u64 val = 0; 6766ab0a202SJeff Mahoney 6776ab0a202SJeff Mahoney down_read(&sinfo->groups_sem); 6786ab0a202SJeff Mahoney list_for_each_entry(block_group, &sinfo->block_groups[index], list) { 679a969f4ccSHans van Kranenburg if (&attr->attr == BTRFS_ATTR_PTR(raid, total_bytes)) 680b3470b5dSDavid Sterba val += block_group->length; 6816ab0a202SJeff Mahoney else 682bf38be65SDavid Sterba val += block_group->used; 6836ab0a202SJeff Mahoney } 6846ab0a202SJeff Mahoney up_read(&sinfo->groups_sem); 685020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6866ab0a202SJeff Mahoney } 6876ab0a202SJeff Mahoney 688e7849e33SAnand Jain /* 689e7849e33SAnand Jain * Allocation information about block group profiles. 690e7849e33SAnand Jain * 691e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/<bg-profile>/ 692e7849e33SAnand Jain */ 6937c7e3014SKimberly Brown static struct attribute *raid_attrs[] = { 694a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, total_bytes), 695a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, used_bytes), 6966ab0a202SJeff Mahoney NULL 6976ab0a202SJeff Mahoney }; 6987c7e3014SKimberly Brown ATTRIBUTE_GROUPS(raid); 6996ab0a202SJeff Mahoney 7006ab0a202SJeff Mahoney static void release_raid_kobj(struct kobject *kobj) 7016ab0a202SJeff Mahoney { 702c1895442SJeff Mahoney kfree(to_raid_kobj(kobj)); 7036ab0a202SJeff Mahoney } 7046ab0a202SJeff Mahoney 705536ea45cSDavid Sterba static struct kobj_type btrfs_raid_ktype = { 7066ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 7076ab0a202SJeff Mahoney .release = release_raid_kobj, 7087c7e3014SKimberly Brown .default_groups = raid_groups, 7096ab0a202SJeff Mahoney }; 7106ab0a202SJeff Mahoney 7116ab0a202SJeff Mahoney #define SPACE_INFO_ATTR(field) \ 7126ab0a202SJeff Mahoney static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \ 7136ab0a202SJeff Mahoney struct kobj_attribute *a, \ 7146ab0a202SJeff Mahoney char *buf) \ 7156ab0a202SJeff Mahoney { \ 7166ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); \ 7176ab0a202SJeff Mahoney return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \ 7186ab0a202SJeff Mahoney } \ 719a969f4ccSHans van Kranenburg BTRFS_ATTR(space_info, field, btrfs_space_info_show_##field) 7206ab0a202SJeff Mahoney 72119fc516aSStefan Roesch static ssize_t btrfs_chunk_size_show(struct kobject *kobj, 72219fc516aSStefan Roesch struct kobj_attribute *a, char *buf) 72319fc516aSStefan Roesch { 72419fc516aSStefan Roesch struct btrfs_space_info *sinfo = to_space_info(kobj); 72519fc516aSStefan Roesch 72619fc516aSStefan Roesch return sysfs_emit(buf, "%llu\n", READ_ONCE(sinfo->chunk_size)); 72719fc516aSStefan Roesch } 72819fc516aSStefan Roesch 72919fc516aSStefan Roesch /* 73019fc516aSStefan Roesch * Store new chunk size in space info. Can be called on a read-only filesystem. 73119fc516aSStefan Roesch * 73219fc516aSStefan Roesch * If the new chunk size value is larger than 10% of free space it is reduced 73319fc516aSStefan Roesch * to match that limit. Alignment must be to 256M and the system chunk size 73419fc516aSStefan Roesch * cannot be set. 73519fc516aSStefan Roesch */ 73619fc516aSStefan Roesch static ssize_t btrfs_chunk_size_store(struct kobject *kobj, 73719fc516aSStefan Roesch struct kobj_attribute *a, 73819fc516aSStefan Roesch const char *buf, size_t len) 73919fc516aSStefan Roesch { 74019fc516aSStefan Roesch struct btrfs_space_info *space_info = to_space_info(kobj); 74119fc516aSStefan Roesch struct btrfs_fs_info *fs_info = to_fs_info(get_btrfs_kobj(kobj)); 74219fc516aSStefan Roesch char *retptr; 74319fc516aSStefan Roesch u64 val; 74419fc516aSStefan Roesch 74519fc516aSStefan Roesch if (!capable(CAP_SYS_ADMIN)) 74619fc516aSStefan Roesch return -EPERM; 74719fc516aSStefan Roesch 74819fc516aSStefan Roesch if (!fs_info->fs_devices) 74919fc516aSStefan Roesch return -EINVAL; 75019fc516aSStefan Roesch 75119fc516aSStefan Roesch if (btrfs_is_zoned(fs_info)) 75219fc516aSStefan Roesch return -EINVAL; 75319fc516aSStefan Roesch 75419fc516aSStefan Roesch /* System block type must not be changed. */ 75519fc516aSStefan Roesch if (space_info->flags & BTRFS_BLOCK_GROUP_SYSTEM) 75619fc516aSStefan Roesch return -EPERM; 75719fc516aSStefan Roesch 75819fc516aSStefan Roesch val = memparse(buf, &retptr); 75919fc516aSStefan Roesch /* There could be trailing '\n', also catch any typos after the value */ 76019fc516aSStefan Roesch retptr = skip_spaces(retptr); 76119fc516aSStefan Roesch if (*retptr != 0 || val == 0) 76219fc516aSStefan Roesch return -EINVAL; 76319fc516aSStefan Roesch 76419fc516aSStefan Roesch val = min(val, BTRFS_MAX_DATA_CHUNK_SIZE); 76519fc516aSStefan Roesch 76619fc516aSStefan Roesch /* Limit stripe size to 10% of available space. */ 767*428c8e03SDavid Sterba val = min(mult_perc(fs_info->fs_devices->total_rw_bytes, 10), val); 76819fc516aSStefan Roesch 76919fc516aSStefan Roesch /* Must be multiple of 256M. */ 77019fc516aSStefan Roesch val &= ~((u64)SZ_256M - 1); 77119fc516aSStefan Roesch 77219fc516aSStefan Roesch /* Must be at least 256M. */ 77319fc516aSStefan Roesch if (val < SZ_256M) 77419fc516aSStefan Roesch return -EINVAL; 77519fc516aSStefan Roesch 77619fc516aSStefan Roesch btrfs_update_space_info_chunk_size(space_info, val); 77719fc516aSStefan Roesch 77819fc516aSStefan Roesch return len; 77919fc516aSStefan Roesch } 78019fc516aSStefan Roesch 78122c55e3bSStefan Roesch #ifdef CONFIG_BTRFS_DEBUG 78222c55e3bSStefan Roesch /* 78322c55e3bSStefan Roesch * Request chunk allocation with current chunk size. 78422c55e3bSStefan Roesch */ 78522c55e3bSStefan Roesch static ssize_t btrfs_force_chunk_alloc_store(struct kobject *kobj, 78622c55e3bSStefan Roesch struct kobj_attribute *a, 78722c55e3bSStefan Roesch const char *buf, size_t len) 78822c55e3bSStefan Roesch { 78922c55e3bSStefan Roesch struct btrfs_space_info *space_info = to_space_info(kobj); 79022c55e3bSStefan Roesch struct btrfs_fs_info *fs_info = to_fs_info(get_btrfs_kobj(kobj)); 79122c55e3bSStefan Roesch struct btrfs_trans_handle *trans; 79222c55e3bSStefan Roesch bool val; 79322c55e3bSStefan Roesch int ret; 79422c55e3bSStefan Roesch 79522c55e3bSStefan Roesch if (!capable(CAP_SYS_ADMIN)) 79622c55e3bSStefan Roesch return -EPERM; 79722c55e3bSStefan Roesch 79822c55e3bSStefan Roesch if (sb_rdonly(fs_info->sb)) 79922c55e3bSStefan Roesch return -EROFS; 80022c55e3bSStefan Roesch 80122c55e3bSStefan Roesch ret = kstrtobool(buf, &val); 80222c55e3bSStefan Roesch if (ret) 80322c55e3bSStefan Roesch return ret; 80422c55e3bSStefan Roesch 80522c55e3bSStefan Roesch if (!val) 80622c55e3bSStefan Roesch return -EINVAL; 80722c55e3bSStefan Roesch 80822c55e3bSStefan Roesch /* 80922c55e3bSStefan Roesch * This is unsafe to be called from sysfs context and may cause 81022c55e3bSStefan Roesch * unexpected problems. 81122c55e3bSStefan Roesch */ 81222c55e3bSStefan Roesch trans = btrfs_start_transaction(fs_info->tree_root, 0); 81322c55e3bSStefan Roesch if (IS_ERR(trans)) 81422c55e3bSStefan Roesch return PTR_ERR(trans); 81522c55e3bSStefan Roesch ret = btrfs_force_chunk_alloc(trans, space_info->flags); 81622c55e3bSStefan Roesch btrfs_end_transaction(trans); 81722c55e3bSStefan Roesch 81822c55e3bSStefan Roesch if (ret == 1) 81922c55e3bSStefan Roesch return len; 82022c55e3bSStefan Roesch 82122c55e3bSStefan Roesch return -ENOSPC; 82222c55e3bSStefan Roesch } 82322c55e3bSStefan Roesch BTRFS_ATTR_W(space_info, force_chunk_alloc, btrfs_force_chunk_alloc_store); 82422c55e3bSStefan Roesch 82522c55e3bSStefan Roesch #endif 82622c55e3bSStefan Roesch 8276ab0a202SJeff Mahoney SPACE_INFO_ATTR(flags); 8286ab0a202SJeff Mahoney SPACE_INFO_ATTR(total_bytes); 8296ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_used); 8306ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_pinned); 8316ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_reserved); 8326ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_may_use); 833c1fd5c30SWang Xiaoguang SPACE_INFO_ATTR(bytes_readonly); 834169e0da9SNaohiro Aota SPACE_INFO_ATTR(bytes_zone_unusable); 8356ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_used); 8366ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_total); 83719fc516aSStefan Roesch BTRFS_ATTR_RW(space_info, chunk_size, btrfs_chunk_size_show, btrfs_chunk_size_store); 8386ab0a202SJeff Mahoney 839bb5a098dSJosef Bacik static ssize_t btrfs_sinfo_bg_reclaim_threshold_show(struct kobject *kobj, 840bb5a098dSJosef Bacik struct kobj_attribute *a, 841bb5a098dSJosef Bacik char *buf) 842bb5a098dSJosef Bacik { 843bb5a098dSJosef Bacik struct btrfs_space_info *space_info = to_space_info(kobj); 844bb5a098dSJosef Bacik 845bd64f622Szhang songyi return sysfs_emit(buf, "%d\n", READ_ONCE(space_info->bg_reclaim_threshold)); 846bb5a098dSJosef Bacik } 847bb5a098dSJosef Bacik 848bb5a098dSJosef Bacik static ssize_t btrfs_sinfo_bg_reclaim_threshold_store(struct kobject *kobj, 849bb5a098dSJosef Bacik struct kobj_attribute *a, 850bb5a098dSJosef Bacik const char *buf, size_t len) 851bb5a098dSJosef Bacik { 852bb5a098dSJosef Bacik struct btrfs_space_info *space_info = to_space_info(kobj); 853bb5a098dSJosef Bacik int thresh; 854bb5a098dSJosef Bacik int ret; 855bb5a098dSJosef Bacik 856bb5a098dSJosef Bacik ret = kstrtoint(buf, 10, &thresh); 857bb5a098dSJosef Bacik if (ret) 858bb5a098dSJosef Bacik return ret; 859bb5a098dSJosef Bacik 860ef972e7bSJosef Bacik if (thresh < 0 || thresh > 100) 861bb5a098dSJosef Bacik return -EINVAL; 862bb5a098dSJosef Bacik 863bb5a098dSJosef Bacik WRITE_ONCE(space_info->bg_reclaim_threshold, thresh); 864bb5a098dSJosef Bacik 865bb5a098dSJosef Bacik return len; 866bb5a098dSJosef Bacik } 867bb5a098dSJosef Bacik 868bb5a098dSJosef Bacik BTRFS_ATTR_RW(space_info, bg_reclaim_threshold, 869bb5a098dSJosef Bacik btrfs_sinfo_bg_reclaim_threshold_show, 870bb5a098dSJosef Bacik btrfs_sinfo_bg_reclaim_threshold_store); 871bb5a098dSJosef Bacik 872e7849e33SAnand Jain /* 873e7849e33SAnand Jain * Allocation information about block group types. 874e7849e33SAnand Jain * 875e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/ 876e7849e33SAnand Jain */ 8776ab0a202SJeff Mahoney static struct attribute *space_info_attrs[] = { 878a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, flags), 879a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, total_bytes), 880a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_used), 881a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_pinned), 882a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_reserved), 883a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_may_use), 884a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_readonly), 885169e0da9SNaohiro Aota BTRFS_ATTR_PTR(space_info, bytes_zone_unusable), 886a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_used), 887a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_total), 888bb5a098dSJosef Bacik BTRFS_ATTR_PTR(space_info, bg_reclaim_threshold), 88919fc516aSStefan Roesch BTRFS_ATTR_PTR(space_info, chunk_size), 89022c55e3bSStefan Roesch #ifdef CONFIG_BTRFS_DEBUG 89122c55e3bSStefan Roesch BTRFS_ATTR_PTR(space_info, force_chunk_alloc), 89222c55e3bSStefan Roesch #endif 8936ab0a202SJeff Mahoney NULL, 8946ab0a202SJeff Mahoney }; 8957c7e3014SKimberly Brown ATTRIBUTE_GROUPS(space_info); 8966ab0a202SJeff Mahoney 8976ab0a202SJeff Mahoney static void space_info_release(struct kobject *kobj) 8986ab0a202SJeff Mahoney { 8996ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); 9006ab0a202SJeff Mahoney kfree(sinfo); 9016ab0a202SJeff Mahoney } 9026ab0a202SJeff Mahoney 90327992d01SDavid Sterba static struct kobj_type space_info_ktype = { 9046ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 9056ab0a202SJeff Mahoney .release = space_info_release, 9067c7e3014SKimberly Brown .default_groups = space_info_groups, 9076ab0a202SJeff Mahoney }; 9086ab0a202SJeff Mahoney 909e7849e33SAnand Jain /* 910e7849e33SAnand Jain * Allocation information about block groups. 911e7849e33SAnand Jain * 912e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/ 913e7849e33SAnand Jain */ 9146ab0a202SJeff Mahoney static const struct attribute *allocation_attrs[] = { 915a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_reserved), 916a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_size), 9176ab0a202SJeff Mahoney NULL, 9186ab0a202SJeff Mahoney }; 9196ab0a202SJeff Mahoney 920f8ba9c11SJeff Mahoney static ssize_t btrfs_label_show(struct kobject *kobj, 921f8ba9c11SJeff Mahoney struct kobj_attribute *a, char *buf) 922f8ba9c11SJeff Mahoney { 923f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 92448fcc3ffSSatoru Takeuchi char *label = fs_info->super_copy->label; 925ee17fc80SDavid Sterba ssize_t ret; 926ee17fc80SDavid Sterba 927ee17fc80SDavid Sterba spin_lock(&fs_info->super_lock); 928020e5277SAnand Jain ret = sysfs_emit(buf, label[0] ? "%s\n" : "%s", label); 929ee17fc80SDavid Sterba spin_unlock(&fs_info->super_lock); 930ee17fc80SDavid Sterba 931ee17fc80SDavid Sterba return ret; 932f8ba9c11SJeff Mahoney } 933f8ba9c11SJeff Mahoney 934f8ba9c11SJeff Mahoney static ssize_t btrfs_label_store(struct kobject *kobj, 935f8ba9c11SJeff Mahoney struct kobj_attribute *a, 936f8ba9c11SJeff Mahoney const char *buf, size_t len) 937f8ba9c11SJeff Mahoney { 938f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 93948fcc3ffSSatoru Takeuchi size_t p_len; 940f8ba9c11SJeff Mahoney 94166ac9fe7SDavid Sterba if (!fs_info) 94266ac9fe7SDavid Sterba return -EPERM; 94366ac9fe7SDavid Sterba 944bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 94579aec2b8SAnand Jain return -EROFS; 94679aec2b8SAnand Jain 94748fcc3ffSSatoru Takeuchi /* 94848fcc3ffSSatoru Takeuchi * p_len is the len until the first occurrence of either 94948fcc3ffSSatoru Takeuchi * '\n' or '\0' 95048fcc3ffSSatoru Takeuchi */ 95148fcc3ffSSatoru Takeuchi p_len = strcspn(buf, "\n"); 95248fcc3ffSSatoru Takeuchi 95348fcc3ffSSatoru Takeuchi if (p_len >= BTRFS_LABEL_SIZE) 954f8ba9c11SJeff Mahoney return -EINVAL; 955f8ba9c11SJeff Mahoney 956a6f69dc8SDavid Sterba spin_lock(&fs_info->super_lock); 95748fcc3ffSSatoru Takeuchi memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE); 95848fcc3ffSSatoru Takeuchi memcpy(fs_info->super_copy->label, buf, p_len); 959a6f69dc8SDavid Sterba spin_unlock(&fs_info->super_lock); 960f8ba9c11SJeff Mahoney 961a6f69dc8SDavid Sterba /* 962a6f69dc8SDavid Sterba * We don't want to do full transaction commit from inside sysfs 963a6f69dc8SDavid Sterba */ 964c52cc7b7SJosef Bacik set_bit(BTRFS_FS_NEED_TRANS_COMMIT, &fs_info->flags); 965a6f69dc8SDavid Sterba wake_up_process(fs_info->transaction_kthread); 966a6f69dc8SDavid Sterba 967f8ba9c11SJeff Mahoney return len; 968f8ba9c11SJeff Mahoney } 969a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, label, btrfs_label_show, btrfs_label_store); 970f8ba9c11SJeff Mahoney 971df93589aSDavid Sterba static ssize_t btrfs_nodesize_show(struct kobject *kobj, 972df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 973df93589aSDavid Sterba { 974df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 975df93589aSDavid Sterba 976020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->nodesize); 977df93589aSDavid Sterba } 978df93589aSDavid Sterba 979a969f4ccSHans van Kranenburg BTRFS_ATTR(, nodesize, btrfs_nodesize_show); 980df93589aSDavid Sterba 981df93589aSDavid Sterba static ssize_t btrfs_sectorsize_show(struct kobject *kobj, 982df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 983df93589aSDavid Sterba { 984df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 985df93589aSDavid Sterba 986020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 987df93589aSDavid Sterba } 988df93589aSDavid Sterba 989a969f4ccSHans van Kranenburg BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show); 990df93589aSDavid Sterba 991140a8ff7SIoannis Angelakopoulos static ssize_t btrfs_commit_stats_show(struct kobject *kobj, 992140a8ff7SIoannis Angelakopoulos struct kobj_attribute *a, char *buf) 993140a8ff7SIoannis Angelakopoulos { 994140a8ff7SIoannis Angelakopoulos struct btrfs_fs_info *fs_info = to_fs_info(kobj); 995140a8ff7SIoannis Angelakopoulos 996140a8ff7SIoannis Angelakopoulos return sysfs_emit(buf, 997140a8ff7SIoannis Angelakopoulos "commits %llu\n" 998140a8ff7SIoannis Angelakopoulos "last_commit_ms %llu\n" 999140a8ff7SIoannis Angelakopoulos "max_commit_ms %llu\n" 1000140a8ff7SIoannis Angelakopoulos "total_commit_ms %llu\n", 1001140a8ff7SIoannis Angelakopoulos fs_info->commit_stats.commit_count, 1002140a8ff7SIoannis Angelakopoulos div_u64(fs_info->commit_stats.last_commit_dur, NSEC_PER_MSEC), 1003140a8ff7SIoannis Angelakopoulos div_u64(fs_info->commit_stats.max_commit_dur, NSEC_PER_MSEC), 1004140a8ff7SIoannis Angelakopoulos div_u64(fs_info->commit_stats.total_commit_dur, NSEC_PER_MSEC)); 1005140a8ff7SIoannis Angelakopoulos } 1006140a8ff7SIoannis Angelakopoulos 1007140a8ff7SIoannis Angelakopoulos static ssize_t btrfs_commit_stats_store(struct kobject *kobj, 1008140a8ff7SIoannis Angelakopoulos struct kobj_attribute *a, 1009140a8ff7SIoannis Angelakopoulos const char *buf, size_t len) 1010140a8ff7SIoannis Angelakopoulos { 1011140a8ff7SIoannis Angelakopoulos struct btrfs_fs_info *fs_info = to_fs_info(kobj); 1012140a8ff7SIoannis Angelakopoulos unsigned long val; 1013140a8ff7SIoannis Angelakopoulos int ret; 1014140a8ff7SIoannis Angelakopoulos 1015140a8ff7SIoannis Angelakopoulos if (!fs_info) 1016140a8ff7SIoannis Angelakopoulos return -EPERM; 1017140a8ff7SIoannis Angelakopoulos 1018140a8ff7SIoannis Angelakopoulos if (!capable(CAP_SYS_RESOURCE)) 1019140a8ff7SIoannis Angelakopoulos return -EPERM; 1020140a8ff7SIoannis Angelakopoulos 1021140a8ff7SIoannis Angelakopoulos ret = kstrtoul(buf, 10, &val); 1022140a8ff7SIoannis Angelakopoulos if (ret) 1023140a8ff7SIoannis Angelakopoulos return ret; 1024140a8ff7SIoannis Angelakopoulos if (val) 1025140a8ff7SIoannis Angelakopoulos return -EINVAL; 1026140a8ff7SIoannis Angelakopoulos 1027140a8ff7SIoannis Angelakopoulos WRITE_ONCE(fs_info->commit_stats.max_commit_dur, 0); 1028140a8ff7SIoannis Angelakopoulos 1029140a8ff7SIoannis Angelakopoulos return len; 1030140a8ff7SIoannis Angelakopoulos } 1031140a8ff7SIoannis Angelakopoulos BTRFS_ATTR_RW(, commit_stats, btrfs_commit_stats_show, btrfs_commit_stats_store); 1032140a8ff7SIoannis Angelakopoulos 1033df93589aSDavid Sterba static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, 1034df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 1035df93589aSDavid Sterba { 1036df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 1037df93589aSDavid Sterba 1038020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 1039df93589aSDavid Sterba } 1040df93589aSDavid Sterba 1041a969f4ccSHans van Kranenburg BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show); 1042df93589aSDavid Sterba 10432723480aSSargun Dhillon static ssize_t quota_override_show(struct kobject *kobj, 10442723480aSSargun Dhillon struct kobj_attribute *a, char *buf) 10452723480aSSargun Dhillon { 10462723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 10472723480aSSargun Dhillon int quota_override; 10482723480aSSargun Dhillon 10492723480aSSargun Dhillon quota_override = test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 1050020e5277SAnand Jain return sysfs_emit(buf, "%d\n", quota_override); 10512723480aSSargun Dhillon } 10522723480aSSargun Dhillon 10532723480aSSargun Dhillon static ssize_t quota_override_store(struct kobject *kobj, 10542723480aSSargun Dhillon struct kobj_attribute *a, 10552723480aSSargun Dhillon const char *buf, size_t len) 10562723480aSSargun Dhillon { 10572723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 10582723480aSSargun Dhillon unsigned long knob; 10592723480aSSargun Dhillon int err; 10602723480aSSargun Dhillon 10612723480aSSargun Dhillon if (!fs_info) 10622723480aSSargun Dhillon return -EPERM; 10632723480aSSargun Dhillon 10642723480aSSargun Dhillon if (!capable(CAP_SYS_RESOURCE)) 10652723480aSSargun Dhillon return -EPERM; 10662723480aSSargun Dhillon 10672723480aSSargun Dhillon err = kstrtoul(buf, 10, &knob); 10682723480aSSargun Dhillon if (err) 10692723480aSSargun Dhillon return err; 10702723480aSSargun Dhillon if (knob > 1) 10712723480aSSargun Dhillon return -EINVAL; 10722723480aSSargun Dhillon 10732723480aSSargun Dhillon if (knob) 10742723480aSSargun Dhillon set_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 10752723480aSSargun Dhillon else 10762723480aSSargun Dhillon clear_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 10772723480aSSargun Dhillon 10782723480aSSargun Dhillon return len; 10792723480aSSargun Dhillon } 10802723480aSSargun Dhillon 1081a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, quota_override, quota_override_show, quota_override_store); 10822723480aSSargun Dhillon 108356f20f40SNikolay Borisov static ssize_t btrfs_metadata_uuid_show(struct kobject *kobj, 108456f20f40SNikolay Borisov struct kobj_attribute *a, char *buf) 108556f20f40SNikolay Borisov { 108656f20f40SNikolay Borisov struct btrfs_fs_info *fs_info = to_fs_info(kobj); 108756f20f40SNikolay Borisov 1088020e5277SAnand Jain return sysfs_emit(buf, "%pU\n", fs_info->fs_devices->metadata_uuid); 108956f20f40SNikolay Borisov } 109056f20f40SNikolay Borisov 109156f20f40SNikolay Borisov BTRFS_ATTR(, metadata_uuid, btrfs_metadata_uuid_show); 109256f20f40SNikolay Borisov 109341e6d2a8SJohannes Thumshirn static ssize_t btrfs_checksum_show(struct kobject *kobj, 109441e6d2a8SJohannes Thumshirn struct kobj_attribute *a, char *buf) 109541e6d2a8SJohannes Thumshirn { 109641e6d2a8SJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 109741e6d2a8SJohannes Thumshirn u16 csum_type = btrfs_super_csum_type(fs_info->super_copy); 109841e6d2a8SJohannes Thumshirn 1099020e5277SAnand Jain return sysfs_emit(buf, "%s (%s)\n", 110041e6d2a8SJohannes Thumshirn btrfs_super_csum_name(csum_type), 110141e6d2a8SJohannes Thumshirn crypto_shash_driver_name(fs_info->csum_shash)); 110241e6d2a8SJohannes Thumshirn } 110341e6d2a8SJohannes Thumshirn 110441e6d2a8SJohannes Thumshirn BTRFS_ATTR(, checksum, btrfs_checksum_show); 110541e6d2a8SJohannes Thumshirn 110666a2823cSGoldwyn Rodrigues static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj, 110766a2823cSGoldwyn Rodrigues struct kobj_attribute *a, char *buf) 110866a2823cSGoldwyn Rodrigues { 110966a2823cSGoldwyn Rodrigues struct btrfs_fs_info *fs_info = to_fs_info(kobj); 111066a2823cSGoldwyn Rodrigues const char *str; 111166a2823cSGoldwyn Rodrigues 111266a2823cSGoldwyn Rodrigues switch (READ_ONCE(fs_info->exclusive_operation)) { 111366a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_NONE: 111466a2823cSGoldwyn Rodrigues str = "none\n"; 111566a2823cSGoldwyn Rodrigues break; 111666a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_BALANCE: 111766a2823cSGoldwyn Rodrigues str = "balance\n"; 111866a2823cSGoldwyn Rodrigues break; 11193e1ad196SDavid Sterba case BTRFS_EXCLOP_BALANCE_PAUSED: 11203e1ad196SDavid Sterba str = "balance paused\n"; 11213e1ad196SDavid Sterba break; 112266a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_ADD: 112366a2823cSGoldwyn Rodrigues str = "device add\n"; 112466a2823cSGoldwyn Rodrigues break; 112566a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REMOVE: 112666a2823cSGoldwyn Rodrigues str = "device remove\n"; 112766a2823cSGoldwyn Rodrigues break; 112866a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REPLACE: 112966a2823cSGoldwyn Rodrigues str = "device replace\n"; 113066a2823cSGoldwyn Rodrigues break; 113166a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_RESIZE: 113266a2823cSGoldwyn Rodrigues str = "resize\n"; 113366a2823cSGoldwyn Rodrigues break; 113466a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_SWAP_ACTIVATE: 113566a2823cSGoldwyn Rodrigues str = "swap activate\n"; 113666a2823cSGoldwyn Rodrigues break; 113766a2823cSGoldwyn Rodrigues default: 113866a2823cSGoldwyn Rodrigues str = "UNKNOWN\n"; 113966a2823cSGoldwyn Rodrigues break; 114066a2823cSGoldwyn Rodrigues } 1141020e5277SAnand Jain return sysfs_emit(buf, "%s", str); 114266a2823cSGoldwyn Rodrigues } 114366a2823cSGoldwyn Rodrigues BTRFS_ATTR(, exclusive_operation, btrfs_exclusive_operation_show); 114466a2823cSGoldwyn Rodrigues 1145089c8b05SAnand Jain static ssize_t btrfs_generation_show(struct kobject *kobj, 1146089c8b05SAnand Jain struct kobj_attribute *a, char *buf) 1147089c8b05SAnand Jain { 1148089c8b05SAnand Jain struct btrfs_fs_info *fs_info = to_fs_info(kobj); 1149089c8b05SAnand Jain 1150020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", fs_info->generation); 1151089c8b05SAnand Jain } 1152089c8b05SAnand Jain BTRFS_ATTR(, generation, btrfs_generation_show); 1153089c8b05SAnand Jain 11543d8cc17aSAnand Jain static const char * const btrfs_read_policy_name[] = { "pid" }; 11553d8cc17aSAnand Jain 11563d8cc17aSAnand Jain static ssize_t btrfs_read_policy_show(struct kobject *kobj, 11573d8cc17aSAnand Jain struct kobj_attribute *a, char *buf) 11583d8cc17aSAnand Jain { 11593d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 11603d8cc17aSAnand Jain ssize_t ret = 0; 11613d8cc17aSAnand Jain int i; 11623d8cc17aSAnand Jain 11633d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 11643d8cc17aSAnand Jain if (fs_devices->read_policy == i) 1165467761f9SDavid Sterba ret += sysfs_emit_at(buf, ret, "%s[%s]", 11663d8cc17aSAnand Jain (ret == 0 ? "" : " "), 11673d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11683d8cc17aSAnand Jain else 1169467761f9SDavid Sterba ret += sysfs_emit_at(buf, ret, "%s%s", 11703d8cc17aSAnand Jain (ret == 0 ? "" : " "), 11713d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11723d8cc17aSAnand Jain } 11733d8cc17aSAnand Jain 1174467761f9SDavid Sterba ret += sysfs_emit_at(buf, ret, "\n"); 11753d8cc17aSAnand Jain 11763d8cc17aSAnand Jain return ret; 11773d8cc17aSAnand Jain } 11783d8cc17aSAnand Jain 11793d8cc17aSAnand Jain static ssize_t btrfs_read_policy_store(struct kobject *kobj, 11803d8cc17aSAnand Jain struct kobj_attribute *a, 11813d8cc17aSAnand Jain const char *buf, size_t len) 11823d8cc17aSAnand Jain { 11833d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 11843d8cc17aSAnand Jain int i; 11853d8cc17aSAnand Jain 11863d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 11877f298f22SDavid Sterba if (sysfs_streq(buf, btrfs_read_policy_name[i])) { 11883d8cc17aSAnand Jain if (i != fs_devices->read_policy) { 11893d8cc17aSAnand Jain fs_devices->read_policy = i; 11903d8cc17aSAnand Jain btrfs_info(fs_devices->fs_info, 11913d8cc17aSAnand Jain "read policy set to '%s'", 11923d8cc17aSAnand Jain btrfs_read_policy_name[i]); 11933d8cc17aSAnand Jain } 11943d8cc17aSAnand Jain return len; 11953d8cc17aSAnand Jain } 11963d8cc17aSAnand Jain } 11973d8cc17aSAnand Jain 11983d8cc17aSAnand Jain return -EINVAL; 11993d8cc17aSAnand Jain } 12003d8cc17aSAnand Jain BTRFS_ATTR_RW(, read_policy, btrfs_read_policy_show, btrfs_read_policy_store); 12013d8cc17aSAnand Jain 120218bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_show(struct kobject *kobj, 120318bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 120418bb8bbfSJohannes Thumshirn char *buf) 120518bb8bbfSJohannes Thumshirn { 120618bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 120718bb8bbfSJohannes Thumshirn 1208bd64f622Szhang songyi return sysfs_emit(buf, "%d\n", READ_ONCE(fs_info->bg_reclaim_threshold)); 120918bb8bbfSJohannes Thumshirn } 121018bb8bbfSJohannes Thumshirn 121118bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_store(struct kobject *kobj, 121218bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 121318bb8bbfSJohannes Thumshirn const char *buf, size_t len) 121418bb8bbfSJohannes Thumshirn { 121518bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 121618bb8bbfSJohannes Thumshirn int thresh; 121718bb8bbfSJohannes Thumshirn int ret; 121818bb8bbfSJohannes Thumshirn 121918bb8bbfSJohannes Thumshirn ret = kstrtoint(buf, 10, &thresh); 122018bb8bbfSJohannes Thumshirn if (ret) 122118bb8bbfSJohannes Thumshirn return ret; 122218bb8bbfSJohannes Thumshirn 122377233c2dSJohannes Thumshirn if (thresh != 0 && (thresh <= 50 || thresh > 100)) 122418bb8bbfSJohannes Thumshirn return -EINVAL; 122518bb8bbfSJohannes Thumshirn 122677233c2dSJohannes Thumshirn WRITE_ONCE(fs_info->bg_reclaim_threshold, thresh); 122718bb8bbfSJohannes Thumshirn 122818bb8bbfSJohannes Thumshirn return len; 122918bb8bbfSJohannes Thumshirn } 123018bb8bbfSJohannes Thumshirn BTRFS_ATTR_RW(, bg_reclaim_threshold, btrfs_bg_reclaim_threshold_show, 123118bb8bbfSJohannes Thumshirn btrfs_bg_reclaim_threshold_store); 123218bb8bbfSJohannes Thumshirn 1233e7849e33SAnand Jain /* 1234e7849e33SAnand Jain * Per-filesystem information and stats. 1235e7849e33SAnand Jain * 1236e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/ 1237e7849e33SAnand Jain */ 12380dd2906fSAnand Jain static const struct attribute *btrfs_attrs[] = { 1239a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, label), 1240a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, nodesize), 1241a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, sectorsize), 1242a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, clone_alignment), 1243a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, quota_override), 124456f20f40SNikolay Borisov BTRFS_ATTR_PTR(, metadata_uuid), 124541e6d2a8SJohannes Thumshirn BTRFS_ATTR_PTR(, checksum), 124666a2823cSGoldwyn Rodrigues BTRFS_ATTR_PTR(, exclusive_operation), 1247089c8b05SAnand Jain BTRFS_ATTR_PTR(, generation), 12483d8cc17aSAnand Jain BTRFS_ATTR_PTR(, read_policy), 124918bb8bbfSJohannes Thumshirn BTRFS_ATTR_PTR(, bg_reclaim_threshold), 1250140a8ff7SIoannis Angelakopoulos BTRFS_ATTR_PTR(, commit_stats), 1251f8ba9c11SJeff Mahoney NULL, 1252f8ba9c11SJeff Mahoney }; 1253f8ba9c11SJeff Mahoney 1254c1b7e474SAnand Jain static void btrfs_release_fsid_kobj(struct kobject *kobj) 1255510d7360SJeff Mahoney { 12562e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj); 1257248d200dSAnand Jain 1258c1b7e474SAnand Jain memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject)); 12592e7910d6SAnand Jain complete(&fs_devs->kobj_unregister); 1260510d7360SJeff Mahoney } 1261510d7360SJeff Mahoney 1262510d7360SJeff Mahoney static struct kobj_type btrfs_ktype = { 1263510d7360SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 1264c1b7e474SAnand Jain .release = btrfs_release_fsid_kobj, 1265510d7360SJeff Mahoney }; 1266510d7360SJeff Mahoney 12672e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj) 12682e7910d6SAnand Jain { 12692e7910d6SAnand Jain if (kobj->ktype != &btrfs_ktype) 12702e7910d6SAnand Jain return NULL; 1271c1b7e474SAnand Jain return container_of(kobj, struct btrfs_fs_devices, fsid_kobj); 12722e7910d6SAnand Jain } 12732e7910d6SAnand Jain 1274510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj) 1275510d7360SJeff Mahoney { 1276510d7360SJeff Mahoney if (kobj->ktype != &btrfs_ktype) 1277510d7360SJeff Mahoney return NULL; 12782e7910d6SAnand Jain return to_fs_devs(kobj)->fs_info; 1279510d7360SJeff Mahoney } 128058176a96SJosef Bacik 128119fc516aSStefan Roesch static struct kobject *get_btrfs_kobj(struct kobject *kobj) 128219fc516aSStefan Roesch { 128319fc516aSStefan Roesch while (kobj) { 128419fc516aSStefan Roesch if (kobj->ktype == &btrfs_ktype) 128519fc516aSStefan Roesch return kobj; 128619fc516aSStefan Roesch kobj = kobj->parent; 128719fc516aSStefan Roesch } 128819fc516aSStefan Roesch return NULL; 128919fc516aSStefan Roesch } 129019fc516aSStefan Roesch 1291e453d989SJeff Mahoney #define NUM_FEATURE_BITS 64 12926c52157fSTomohiro Misono #define BTRFS_FEATURE_NAME_MAX 13 12936c52157fSTomohiro Misono static char btrfs_unknown_feature_names[FEAT_MAX][NUM_FEATURE_BITS][BTRFS_FEATURE_NAME_MAX]; 12946c52157fSTomohiro Misono static struct btrfs_feature_attr btrfs_feature_attrs[FEAT_MAX][NUM_FEATURE_BITS]; 1295e453d989SJeff Mahoney 1296a55e65b8SDavid Sterba static_assert(ARRAY_SIZE(btrfs_unknown_feature_names) == 1297a55e65b8SDavid Sterba ARRAY_SIZE(btrfs_feature_attrs)); 1298a55e65b8SDavid Sterba static_assert(ARRAY_SIZE(btrfs_unknown_feature_names[0]) == 1299a55e65b8SDavid Sterba ARRAY_SIZE(btrfs_feature_attrs[0])); 1300a55e65b8SDavid Sterba 13016c52157fSTomohiro Misono static const u64 supported_feature_masks[FEAT_MAX] = { 1302e453d989SJeff Mahoney [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP, 1303e453d989SJeff Mahoney [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP, 1304e453d989SJeff Mahoney [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP, 1305e453d989SJeff Mahoney }; 1306e453d989SJeff Mahoney 1307e453d989SJeff Mahoney static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add) 13085ac1d209SJeff Mahoney { 1309e453d989SJeff Mahoney int set; 1310e453d989SJeff Mahoney 1311e453d989SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 1312e453d989SJeff Mahoney int i; 1313e453d989SJeff Mahoney struct attribute *attrs[2]; 1314e453d989SJeff Mahoney struct attribute_group agroup = { 1315e453d989SJeff Mahoney .name = "features", 1316e453d989SJeff Mahoney .attrs = attrs, 1317e453d989SJeff Mahoney }; 1318e453d989SJeff Mahoney u64 features = get_features(fs_info, set); 1319e453d989SJeff Mahoney features &= ~supported_feature_masks[set]; 1320e453d989SJeff Mahoney 1321e453d989SJeff Mahoney if (!features) 1322e453d989SJeff Mahoney continue; 1323e453d989SJeff Mahoney 1324e453d989SJeff Mahoney attrs[1] = NULL; 1325e453d989SJeff Mahoney for (i = 0; i < NUM_FEATURE_BITS; i++) { 1326e453d989SJeff Mahoney struct btrfs_feature_attr *fa; 1327e453d989SJeff Mahoney 1328e453d989SJeff Mahoney if (!(features & (1ULL << i))) 1329e453d989SJeff Mahoney continue; 1330e453d989SJeff Mahoney 1331e453d989SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 1332e453d989SJeff Mahoney attrs[0] = &fa->kobj_attr.attr; 1333e453d989SJeff Mahoney if (add) { 1334e453d989SJeff Mahoney int ret; 1335c1b7e474SAnand Jain ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj, 1336e453d989SJeff Mahoney &agroup); 1337e453d989SJeff Mahoney if (ret) 1338e453d989SJeff Mahoney return ret; 1339e453d989SJeff Mahoney } else 1340c1b7e474SAnand Jain sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj, 1341e453d989SJeff Mahoney &agroup); 1342e453d989SJeff Mahoney } 1343e453d989SJeff Mahoney 1344e453d989SJeff Mahoney } 1345e453d989SJeff Mahoney return 0; 1346e453d989SJeff Mahoney } 1347e453d989SJeff Mahoney 13482e3e1281SAnand Jain static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 1349e453d989SJeff Mahoney { 1350a013d141SAnand Jain if (fs_devs->devinfo_kobj) { 1351a013d141SAnand Jain kobject_del(fs_devs->devinfo_kobj); 1352a013d141SAnand Jain kobject_put(fs_devs->devinfo_kobj); 1353a013d141SAnand Jain fs_devs->devinfo_kobj = NULL; 1354a013d141SAnand Jain } 1355a013d141SAnand Jain 1356b5501504SAnand Jain if (fs_devs->devices_kobj) { 1357b5501504SAnand Jain kobject_del(fs_devs->devices_kobj); 1358b5501504SAnand Jain kobject_put(fs_devs->devices_kobj); 1359b5501504SAnand Jain fs_devs->devices_kobj = NULL; 1360aaf13305SAnand Jain } 1361aaf13305SAnand Jain 1362c1b7e474SAnand Jain if (fs_devs->fsid_kobj.state_initialized) { 1363c1b7e474SAnand Jain kobject_del(&fs_devs->fsid_kobj); 1364c1b7e474SAnand Jain kobject_put(&fs_devs->fsid_kobj); 13652e7910d6SAnand Jain wait_for_completion(&fs_devs->kobj_unregister); 13665ac1d209SJeff Mahoney } 1367f90fc547SAnand Jain } 13685ac1d209SJeff Mahoney 13692e3e1281SAnand Jain /* when fs_devs is NULL it will remove all fsid kobject */ 13701d1c1be3SAnand Jain void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 13712e3e1281SAnand Jain { 13722e3e1281SAnand Jain struct list_head *fs_uuids = btrfs_get_fs_uuids(); 13732e3e1281SAnand Jain 13742e3e1281SAnand Jain if (fs_devs) { 13752e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 13762e3e1281SAnand Jain return; 13772e3e1281SAnand Jain } 13782e3e1281SAnand Jain 1379c4babc5eSAnand Jain list_for_each_entry(fs_devs, fs_uuids, fs_list) { 13802e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 13812e3e1281SAnand Jain } 13822e3e1281SAnand Jain } 13832e3e1281SAnand Jain 138453f8a74cSAnand Jain static void btrfs_sysfs_remove_fs_devices(struct btrfs_fs_devices *fs_devices) 138553f8a74cSAnand Jain { 138653f8a74cSAnand Jain struct btrfs_device *device; 138730b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 138853f8a74cSAnand Jain 138953f8a74cSAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) 139053f8a74cSAnand Jain btrfs_sysfs_remove_device(device); 139130b0e4e0SAnand Jain 139230b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 139330b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) 139430b0e4e0SAnand Jain btrfs_sysfs_remove_device(device); 139530b0e4e0SAnand Jain } 139653f8a74cSAnand Jain } 139753f8a74cSAnand Jain 13986618a59bSAnand Jain void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info) 1399e453d989SJeff Mahoney { 14003092c68fSNikolay Borisov struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 14013092c68fSNikolay Borisov 14023092c68fSNikolay Borisov sysfs_remove_link(fsid_kobj, "bdi"); 14033092c68fSNikolay Borisov 1404e453d989SJeff Mahoney if (fs_info->space_info_kobj) { 1405e453d989SJeff Mahoney sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); 1406e453d989SJeff Mahoney kobject_del(fs_info->space_info_kobj); 1407e453d989SJeff Mahoney kobject_put(fs_info->space_info_kobj); 1408e453d989SJeff Mahoney } 1409fb731430SDavid Sterba if (fs_info->discard_kobj) { 1410fb731430SDavid Sterba sysfs_remove_files(fs_info->discard_kobj, discard_attrs); 1411fb731430SDavid Sterba kobject_del(fs_info->discard_kobj); 1412fb731430SDavid Sterba kobject_put(fs_info->discard_kobj); 1413e4faab84SDennis Zhou } 1414fb731430SDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 141593945cb4SDennis Zhou if (fs_info->debug_kobj) { 141693945cb4SDennis Zhou sysfs_remove_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 141793945cb4SDennis Zhou kobject_del(fs_info->debug_kobj); 141893945cb4SDennis Zhou kobject_put(fs_info->debug_kobj); 141993945cb4SDennis Zhou } 142071e8978eSDennis Zhou #endif 1421e453d989SJeff Mahoney addrm_unknown_feature_attrs(fs_info, false); 14223092c68fSNikolay Borisov sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 14233092c68fSNikolay Borisov sysfs_remove_files(fsid_kobj, btrfs_attrs); 142453f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_info->fs_devices); 1425e453d989SJeff Mahoney } 1426e453d989SJeff Mahoney 1427f10152bcSDavid Sterba static const char * const btrfs_feature_set_names[FEAT_MAX] = { 142879da4fa4SJeff Mahoney [FEAT_COMPAT] = "compat", 142979da4fa4SJeff Mahoney [FEAT_COMPAT_RO] = "compat_ro", 143079da4fa4SJeff Mahoney [FEAT_INCOMPAT] = "incompat", 143179da4fa4SJeff Mahoney }; 143279da4fa4SJeff Mahoney 14339e6df7ceSDavid Sterba const char *btrfs_feature_set_name(enum btrfs_feature_set set) 1434f10152bcSDavid Sterba { 1435f10152bcSDavid Sterba return btrfs_feature_set_names[set]; 1436f10152bcSDavid Sterba } 1437f10152bcSDavid Sterba 14383b02a68aSJeff Mahoney char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) 14393b02a68aSJeff Mahoney { 14403b02a68aSJeff Mahoney size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */ 14413b02a68aSJeff Mahoney int len = 0; 14423b02a68aSJeff Mahoney int i; 14433b02a68aSJeff Mahoney char *str; 14443b02a68aSJeff Mahoney 14453b02a68aSJeff Mahoney str = kmalloc(bufsize, GFP_KERNEL); 14463b02a68aSJeff Mahoney if (!str) 14473b02a68aSJeff Mahoney return str; 14483b02a68aSJeff Mahoney 14493b02a68aSJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 14503b02a68aSJeff Mahoney const char *name; 14513b02a68aSJeff Mahoney 14523b02a68aSJeff Mahoney if (!(flags & (1ULL << i))) 14533b02a68aSJeff Mahoney continue; 14543b02a68aSJeff Mahoney 14553b02a68aSJeff Mahoney name = btrfs_feature_attrs[set][i].kobj_attr.attr.name; 1456abdd9febSTakashi Iwai len += scnprintf(str + len, bufsize - len, "%s%s", 14573b02a68aSJeff Mahoney len ? "," : "", name); 14583b02a68aSJeff Mahoney } 14593b02a68aSJeff Mahoney 14603b02a68aSJeff Mahoney return str; 14613b02a68aSJeff Mahoney } 14623b02a68aSJeff Mahoney 146379da4fa4SJeff Mahoney static void init_feature_attrs(void) 146479da4fa4SJeff Mahoney { 146579da4fa4SJeff Mahoney struct btrfs_feature_attr *fa; 146679da4fa4SJeff Mahoney int set, i; 146779da4fa4SJeff Mahoney 14683b02a68aSJeff Mahoney memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs)); 14693b02a68aSJeff Mahoney memset(btrfs_unknown_feature_names, 0, 14703b02a68aSJeff Mahoney sizeof(btrfs_unknown_feature_names)); 14713b02a68aSJeff Mahoney 147279da4fa4SJeff Mahoney for (i = 0; btrfs_supported_feature_attrs[i]; i++) { 147379da4fa4SJeff Mahoney struct btrfs_feature_attr *sfa; 147479da4fa4SJeff Mahoney struct attribute *a = btrfs_supported_feature_attrs[i]; 14753b02a68aSJeff Mahoney int bit; 147679da4fa4SJeff Mahoney sfa = attr_to_btrfs_feature_attr(a); 14773b02a68aSJeff Mahoney bit = ilog2(sfa->feature_bit); 14783b02a68aSJeff Mahoney fa = &btrfs_feature_attrs[sfa->feature_set][bit]; 147979da4fa4SJeff Mahoney 148079da4fa4SJeff Mahoney fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name; 148179da4fa4SJeff Mahoney } 148279da4fa4SJeff Mahoney 148379da4fa4SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 148479da4fa4SJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 148579da4fa4SJeff Mahoney char *name = btrfs_unknown_feature_names[set][i]; 148679da4fa4SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 148779da4fa4SJeff Mahoney 148879da4fa4SJeff Mahoney if (fa->kobj_attr.attr.name) 148979da4fa4SJeff Mahoney continue; 149079da4fa4SJeff Mahoney 14916c52157fSTomohiro Misono snprintf(name, BTRFS_FEATURE_NAME_MAX, "%s:%u", 149279da4fa4SJeff Mahoney btrfs_feature_set_names[set], i); 149379da4fa4SJeff Mahoney 149479da4fa4SJeff Mahoney fa->kobj_attr.attr.name = name; 149579da4fa4SJeff Mahoney fa->kobj_attr.attr.mode = S_IRUGO; 149679da4fa4SJeff Mahoney fa->feature_set = set; 149779da4fa4SJeff Mahoney fa->feature_bit = 1ULL << i; 149879da4fa4SJeff Mahoney } 149979da4fa4SJeff Mahoney } 150079da4fa4SJeff Mahoney } 150179da4fa4SJeff Mahoney 150232a9991fSDavid Sterba /* 150332a9991fSDavid Sterba * Create a sysfs entry for a given block group type at path 150432a9991fSDavid Sterba * /sys/fs/btrfs/UUID/allocation/data/TYPE 150532a9991fSDavid Sterba */ 150632da5386SDavid Sterba void btrfs_sysfs_add_block_group_type(struct btrfs_block_group *cache) 150732a9991fSDavid Sterba { 150832a9991fSDavid Sterba struct btrfs_fs_info *fs_info = cache->fs_info; 150932a9991fSDavid Sterba struct btrfs_space_info *space_info = cache->space_info; 151032a9991fSDavid Sterba struct raid_kobject *rkobj; 151132a9991fSDavid Sterba const int index = btrfs_bg_flags_to_raid_index(cache->flags); 151232a9991fSDavid Sterba unsigned int nofs_flag; 151332a9991fSDavid Sterba int ret; 151432a9991fSDavid Sterba 151532a9991fSDavid Sterba /* 151632a9991fSDavid Sterba * Setup a NOFS context because kobject_add(), deep in its call chain, 151732a9991fSDavid Sterba * does GFP_KERNEL allocations, and we are often called in a context 151832a9991fSDavid Sterba * where if reclaim is triggered we can deadlock (we are either holding 151932a9991fSDavid Sterba * a transaction handle or some lock required for a transaction 152032a9991fSDavid Sterba * commit). 152132a9991fSDavid Sterba */ 152232a9991fSDavid Sterba nofs_flag = memalloc_nofs_save(); 152332a9991fSDavid Sterba 152432a9991fSDavid Sterba rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS); 152532a9991fSDavid Sterba if (!rkobj) { 152632a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 152732a9991fSDavid Sterba btrfs_warn(cache->fs_info, 152832a9991fSDavid Sterba "couldn't alloc memory for raid level kobject"); 152932a9991fSDavid Sterba return; 153032a9991fSDavid Sterba } 153132a9991fSDavid Sterba 153232a9991fSDavid Sterba rkobj->flags = cache->flags; 153332a9991fSDavid Sterba kobject_init(&rkobj->kobj, &btrfs_raid_ktype); 153449ea112dSJosef Bacik 153549ea112dSJosef Bacik /* 153649ea112dSJosef Bacik * We call this either on mount, or if we've created a block group for a 153749ea112dSJosef Bacik * new index type while running (i.e. when restriping). The running 153849ea112dSJosef Bacik * case is tricky because we could race with other threads, so we need 153949ea112dSJosef Bacik * to have this check to make sure we didn't already init the kobject. 154049ea112dSJosef Bacik * 154149ea112dSJosef Bacik * We don't have to protect on the free side because it only happens on 154249ea112dSJosef Bacik * unmount. 154349ea112dSJosef Bacik */ 154449ea112dSJosef Bacik spin_lock(&space_info->lock); 154549ea112dSJosef Bacik if (space_info->block_group_kobjs[index]) { 154649ea112dSJosef Bacik spin_unlock(&space_info->lock); 154749ea112dSJosef Bacik kobject_put(&rkobj->kobj); 154849ea112dSJosef Bacik return; 154949ea112dSJosef Bacik } else { 155049ea112dSJosef Bacik space_info->block_group_kobjs[index] = &rkobj->kobj; 155149ea112dSJosef Bacik } 155249ea112dSJosef Bacik spin_unlock(&space_info->lock); 155349ea112dSJosef Bacik 155432a9991fSDavid Sterba ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s", 155532a9991fSDavid Sterba btrfs_bg_type_to_raid_name(rkobj->flags)); 155632a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 155732a9991fSDavid Sterba if (ret) { 155849ea112dSJosef Bacik spin_lock(&space_info->lock); 155949ea112dSJosef Bacik space_info->block_group_kobjs[index] = NULL; 156049ea112dSJosef Bacik spin_unlock(&space_info->lock); 156132a9991fSDavid Sterba kobject_put(&rkobj->kobj); 156232a9991fSDavid Sterba btrfs_warn(fs_info, 156332a9991fSDavid Sterba "failed to add kobject for block cache, ignoring"); 156432a9991fSDavid Sterba return; 156532a9991fSDavid Sterba } 156632a9991fSDavid Sterba } 156732a9991fSDavid Sterba 1568b5865babSDavid Sterba /* 1569b5865babSDavid Sterba * Remove sysfs directories for all block group types of a given space info and 1570b5865babSDavid Sterba * the space info as well 1571b5865babSDavid Sterba */ 1572b5865babSDavid Sterba void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info) 1573b5865babSDavid Sterba { 1574b5865babSDavid Sterba int i; 1575b5865babSDavid Sterba 1576b5865babSDavid Sterba for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { 1577b5865babSDavid Sterba struct kobject *kobj; 1578b5865babSDavid Sterba 1579b5865babSDavid Sterba kobj = space_info->block_group_kobjs[i]; 1580b5865babSDavid Sterba space_info->block_group_kobjs[i] = NULL; 1581b5865babSDavid Sterba if (kobj) { 1582b5865babSDavid Sterba kobject_del(kobj); 1583b5865babSDavid Sterba kobject_put(kobj); 1584b5865babSDavid Sterba } 1585b5865babSDavid Sterba } 1586b5865babSDavid Sterba kobject_del(&space_info->kobj); 1587b5865babSDavid Sterba kobject_put(&space_info->kobj); 1588b5865babSDavid Sterba } 1589b5865babSDavid Sterba 1590b882327aSDavid Sterba static const char *alloc_name(u64 flags) 1591b882327aSDavid Sterba { 1592b882327aSDavid Sterba switch (flags) { 1593b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA: 1594b882327aSDavid Sterba return "mixed"; 1595b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA: 1596b882327aSDavid Sterba return "metadata"; 1597b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_DATA: 1598b882327aSDavid Sterba return "data"; 1599b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_SYSTEM: 1600b882327aSDavid Sterba return "system"; 1601b882327aSDavid Sterba default: 1602b882327aSDavid Sterba WARN_ON(1); 1603b882327aSDavid Sterba return "invalid-combination"; 1604445d8ab5STom Rix } 1605b882327aSDavid Sterba } 1606b882327aSDavid Sterba 1607b882327aSDavid Sterba /* 1608b882327aSDavid Sterba * Create a sysfs entry for a space info type at path 1609b882327aSDavid Sterba * /sys/fs/btrfs/UUID/allocation/TYPE 1610b882327aSDavid Sterba */ 1611b882327aSDavid Sterba int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info, 1612b882327aSDavid Sterba struct btrfs_space_info *space_info) 1613b882327aSDavid Sterba { 1614b882327aSDavid Sterba int ret; 1615b882327aSDavid Sterba 1616b882327aSDavid Sterba ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, 1617b882327aSDavid Sterba fs_info->space_info_kobj, "%s", 1618b882327aSDavid Sterba alloc_name(space_info->flags)); 1619b882327aSDavid Sterba if (ret) { 1620b882327aSDavid Sterba kobject_put(&space_info->kobj); 1621b882327aSDavid Sterba return ret; 1622b882327aSDavid Sterba } 1623b882327aSDavid Sterba 1624b882327aSDavid Sterba return 0; 1625b882327aSDavid Sterba } 1626b882327aSDavid Sterba 162753f8a74cSAnand Jain void btrfs_sysfs_remove_device(struct btrfs_device *device) 162899994cdeSAnand Jain { 1629985e233eSAnand Jain struct kobject *devices_kobj; 163099994cdeSAnand Jain 1631985e233eSAnand Jain /* 1632985e233eSAnand Jain * Seed fs_devices devices_kobj aren't used, fetch kobject from the 1633985e233eSAnand Jain * fs_info::fs_devices. 1634985e233eSAnand Jain */ 1635985e233eSAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1636985e233eSAnand Jain ASSERT(devices_kobj); 163799994cdeSAnand Jain 16388d65269fSChristoph Hellwig if (device->bdev) 16398d65269fSChristoph Hellwig sysfs_remove_link(devices_kobj, bdev_kobj(device->bdev)->name); 164099994cdeSAnand Jain 1641985e233eSAnand Jain if (device->devid_kobj.state_initialized) { 1642985e233eSAnand Jain kobject_del(&device->devid_kobj); 1643985e233eSAnand Jain kobject_put(&device->devid_kobj); 1644985e233eSAnand Jain wait_for_completion(&device->kobj_unregister); 1645985e233eSAnand Jain } 1646b5ddcffaSAnand Jain } 1647668e48afSAnand Jain 1648668e48afSAnand Jain static ssize_t btrfs_devinfo_in_fs_metadata_show(struct kobject *kobj, 1649668e48afSAnand Jain struct kobj_attribute *a, 1650668e48afSAnand Jain char *buf) 1651668e48afSAnand Jain { 1652668e48afSAnand Jain int val; 1653668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1654668e48afSAnand Jain devid_kobj); 1655668e48afSAnand Jain 1656668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state); 1657668e48afSAnand Jain 1658020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1659668e48afSAnand Jain } 1660668e48afSAnand Jain BTRFS_ATTR(devid, in_fs_metadata, btrfs_devinfo_in_fs_metadata_show); 1661668e48afSAnand Jain 166225864778SAnand Jain static ssize_t btrfs_devinfo_missing_show(struct kobject *kobj, 1663668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1664668e48afSAnand Jain { 1665668e48afSAnand Jain int val; 1666668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1667668e48afSAnand Jain devid_kobj); 1668668e48afSAnand Jain 1669668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state); 1670668e48afSAnand Jain 1671020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1672668e48afSAnand Jain } 167325864778SAnand Jain BTRFS_ATTR(devid, missing, btrfs_devinfo_missing_show); 1674668e48afSAnand Jain 1675668e48afSAnand Jain static ssize_t btrfs_devinfo_replace_target_show(struct kobject *kobj, 1676668e48afSAnand Jain struct kobj_attribute *a, 1677668e48afSAnand Jain char *buf) 1678668e48afSAnand Jain { 1679668e48afSAnand Jain int val; 1680668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1681668e48afSAnand Jain devid_kobj); 1682668e48afSAnand Jain 1683668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state); 1684668e48afSAnand Jain 1685020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1686668e48afSAnand Jain } 1687668e48afSAnand Jain BTRFS_ATTR(devid, replace_target, btrfs_devinfo_replace_target_show); 1688668e48afSAnand Jain 1689eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_show(struct kobject *kobj, 1690eb3b5053SDavid Sterba struct kobj_attribute *a, 1691eb3b5053SDavid Sterba char *buf) 1692eb3b5053SDavid Sterba { 1693eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1694eb3b5053SDavid Sterba devid_kobj); 1695eb3b5053SDavid Sterba 1696020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", READ_ONCE(device->scrub_speed_max)); 1697eb3b5053SDavid Sterba } 1698eb3b5053SDavid Sterba 1699eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_store(struct kobject *kobj, 1700eb3b5053SDavid Sterba struct kobj_attribute *a, 1701eb3b5053SDavid Sterba const char *buf, size_t len) 1702eb3b5053SDavid Sterba { 1703eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1704eb3b5053SDavid Sterba devid_kobj); 1705eb3b5053SDavid Sterba char *endptr; 1706eb3b5053SDavid Sterba unsigned long long limit; 1707eb3b5053SDavid Sterba 1708eb3b5053SDavid Sterba limit = memparse(buf, &endptr); 1709eb3b5053SDavid Sterba WRITE_ONCE(device->scrub_speed_max, limit); 1710eb3b5053SDavid Sterba return len; 1711eb3b5053SDavid Sterba } 1712eb3b5053SDavid Sterba BTRFS_ATTR_RW(devid, scrub_speed_max, btrfs_devinfo_scrub_speed_max_show, 1713eb3b5053SDavid Sterba btrfs_devinfo_scrub_speed_max_store); 1714eb3b5053SDavid Sterba 1715668e48afSAnand Jain static ssize_t btrfs_devinfo_writeable_show(struct kobject *kobj, 1716668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1717668e48afSAnand Jain { 1718668e48afSAnand Jain int val; 1719668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1720668e48afSAnand Jain devid_kobj); 1721668e48afSAnand Jain 1722668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state); 1723668e48afSAnand Jain 1724020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1725668e48afSAnand Jain } 1726668e48afSAnand Jain BTRFS_ATTR(devid, writeable, btrfs_devinfo_writeable_show); 1727668e48afSAnand Jain 1728a26d60deSAnand Jain static ssize_t btrfs_devinfo_fsid_show(struct kobject *kobj, 1729a26d60deSAnand Jain struct kobj_attribute *a, char *buf) 1730a26d60deSAnand Jain { 1731a26d60deSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1732a26d60deSAnand Jain devid_kobj); 1733a26d60deSAnand Jain 1734a26d60deSAnand Jain return sysfs_emit(buf, "%pU\n", device->fs_devices->fsid); 1735a26d60deSAnand Jain } 1736a26d60deSAnand Jain BTRFS_ATTR(devid, fsid, btrfs_devinfo_fsid_show); 1737a26d60deSAnand Jain 1738da658b57SDavid Sterba static ssize_t btrfs_devinfo_error_stats_show(struct kobject *kobj, 1739da658b57SDavid Sterba struct kobj_attribute *a, char *buf) 1740da658b57SDavid Sterba { 1741da658b57SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1742da658b57SDavid Sterba devid_kobj); 1743da658b57SDavid Sterba 1744da658b57SDavid Sterba if (!device->dev_stats_valid) 1745020e5277SAnand Jain return sysfs_emit(buf, "invalid\n"); 1746da658b57SDavid Sterba 1747da658b57SDavid Sterba /* 1748da658b57SDavid Sterba * Print all at once so we get a snapshot of all values from the same 1749da658b57SDavid Sterba * time. Keep them in sync and in order of definition of 1750da658b57SDavid Sterba * btrfs_dev_stat_values. 1751da658b57SDavid Sterba */ 1752020e5277SAnand Jain return sysfs_emit(buf, 1753da658b57SDavid Sterba "write_errs %d\n" 1754da658b57SDavid Sterba "read_errs %d\n" 1755da658b57SDavid Sterba "flush_errs %d\n" 1756da658b57SDavid Sterba "corruption_errs %d\n" 1757da658b57SDavid Sterba "generation_errs %d\n", 1758da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_WRITE_ERRS), 1759da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_READ_ERRS), 1760da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_FLUSH_ERRS), 1761da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_CORRUPTION_ERRS), 1762da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_GENERATION_ERRS)); 1763da658b57SDavid Sterba } 1764da658b57SDavid Sterba BTRFS_ATTR(devid, error_stats, btrfs_devinfo_error_stats_show); 1765da658b57SDavid Sterba 1766e7849e33SAnand Jain /* 1767e7849e33SAnand Jain * Information about one device. 1768e7849e33SAnand Jain * 1769e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/devinfo/<devid>/ 1770e7849e33SAnand Jain */ 1771668e48afSAnand Jain static struct attribute *devid_attrs[] = { 1772da658b57SDavid Sterba BTRFS_ATTR_PTR(devid, error_stats), 1773a26d60deSAnand Jain BTRFS_ATTR_PTR(devid, fsid), 1774668e48afSAnand Jain BTRFS_ATTR_PTR(devid, in_fs_metadata), 1775668e48afSAnand Jain BTRFS_ATTR_PTR(devid, missing), 1776668e48afSAnand Jain BTRFS_ATTR_PTR(devid, replace_target), 1777eb3b5053SDavid Sterba BTRFS_ATTR_PTR(devid, scrub_speed_max), 1778668e48afSAnand Jain BTRFS_ATTR_PTR(devid, writeable), 1779668e48afSAnand Jain NULL 1780668e48afSAnand Jain }; 1781668e48afSAnand Jain ATTRIBUTE_GROUPS(devid); 1782668e48afSAnand Jain 1783668e48afSAnand Jain static void btrfs_release_devid_kobj(struct kobject *kobj) 1784668e48afSAnand Jain { 1785668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1786668e48afSAnand Jain devid_kobj); 1787668e48afSAnand Jain 1788668e48afSAnand Jain memset(&device->devid_kobj, 0, sizeof(struct kobject)); 1789668e48afSAnand Jain complete(&device->kobj_unregister); 1790668e48afSAnand Jain } 1791668e48afSAnand Jain 1792668e48afSAnand Jain static struct kobj_type devid_ktype = { 1793668e48afSAnand Jain .sysfs_ops = &kobj_sysfs_ops, 1794668e48afSAnand Jain .default_groups = devid_groups, 1795668e48afSAnand Jain .release = btrfs_release_devid_kobj, 1796668e48afSAnand Jain }; 1797668e48afSAnand Jain 1798cd36da2eSAnand Jain int btrfs_sysfs_add_device(struct btrfs_device *device) 179929e5be24SJeff Mahoney { 1800178a16c9SAnand Jain int ret; 1801a47bd78dSJosef Bacik unsigned int nofs_flag; 1802178a16c9SAnand Jain struct kobject *devices_kobj; 1803178a16c9SAnand Jain struct kobject *devinfo_kobj; 1804178a16c9SAnand Jain 1805178a16c9SAnand Jain /* 1806178a16c9SAnand Jain * Make sure we use the fs_info::fs_devices to fetch the kobjects even 1807178a16c9SAnand Jain * for the seed fs_devices 1808178a16c9SAnand Jain */ 1809178a16c9SAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1810178a16c9SAnand Jain devinfo_kobj = device->fs_info->fs_devices->devinfo_kobj; 1811178a16c9SAnand Jain ASSERT(devices_kobj); 1812178a16c9SAnand Jain ASSERT(devinfo_kobj); 181329e5be24SJeff Mahoney 1814a47bd78dSJosef Bacik nofs_flag = memalloc_nofs_save(); 1815f085381eSAnand Jain 1816178a16c9SAnand Jain if (device->bdev) { 18178d65269fSChristoph Hellwig struct kobject *disk_kobj = bdev_kobj(device->bdev); 181829e5be24SJeff Mahoney 1819178a16c9SAnand Jain ret = sysfs_create_link(devices_kobj, disk_kobj, disk_kobj->name); 1820178a16c9SAnand Jain if (ret) { 1821178a16c9SAnand Jain btrfs_warn(device->fs_info, 1822178a16c9SAnand Jain "creating sysfs device link for devid %llu failed: %d", 1823178a16c9SAnand Jain device->devid, ret); 1824178a16c9SAnand Jain goto out; 1825178a16c9SAnand Jain } 182629e5be24SJeff Mahoney } 182729e5be24SJeff Mahoney 1828178a16c9SAnand Jain init_completion(&device->kobj_unregister); 1829178a16c9SAnand Jain ret = kobject_init_and_add(&device->devid_kobj, &devid_ktype, 1830178a16c9SAnand Jain devinfo_kobj, "%llu", device->devid); 1831178a16c9SAnand Jain if (ret) { 1832178a16c9SAnand Jain kobject_put(&device->devid_kobj); 1833178a16c9SAnand Jain btrfs_warn(device->fs_info, 1834178a16c9SAnand Jain "devinfo init for devid %llu failed: %d", 1835178a16c9SAnand Jain device->devid, ret); 1836668e48afSAnand Jain } 1837178a16c9SAnand Jain 1838178a16c9SAnand Jain out: 1839a47bd78dSJosef Bacik memalloc_nofs_restore(nofs_flag); 1840178a16c9SAnand Jain return ret; 1841178a16c9SAnand Jain } 1842668e48afSAnand Jain 1843cd36da2eSAnand Jain static int btrfs_sysfs_add_fs_devices(struct btrfs_fs_devices *fs_devices) 1844178a16c9SAnand Jain { 1845178a16c9SAnand Jain int ret; 1846cd36da2eSAnand Jain struct btrfs_device *device; 184730b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 1848178a16c9SAnand Jain 1849178a16c9SAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) { 1850178a16c9SAnand Jain ret = btrfs_sysfs_add_device(device); 1851178a16c9SAnand Jain if (ret) 18527ad3912aSAnand Jain goto fail; 1853178a16c9SAnand Jain } 1854178a16c9SAnand Jain 185530b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 185630b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) { 185730b0e4e0SAnand Jain ret = btrfs_sysfs_add_device(device); 185830b0e4e0SAnand Jain if (ret) 18597ad3912aSAnand Jain goto fail; 186030b0e4e0SAnand Jain } 186130b0e4e0SAnand Jain } 186230b0e4e0SAnand Jain 1863178a16c9SAnand Jain return 0; 18647ad3912aSAnand Jain 18657ad3912aSAnand Jain fail: 18667ad3912aSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devices); 18677ad3912aSAnand Jain return ret; 186829e5be24SJeff Mahoney } 186929e5be24SJeff Mahoney 18705b28692eSDavid Sterba void btrfs_kobject_uevent(struct block_device *bdev, enum kobject_action action) 18715b28692eSDavid Sterba { 18725b28692eSDavid Sterba int ret; 18735b28692eSDavid Sterba 18745b28692eSDavid Sterba ret = kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, action); 18755b28692eSDavid Sterba if (ret) 18765b28692eSDavid Sterba pr_warn("BTRFS: Sending event '%d' to kobject: '%s' (%p): failed\n", 18775b28692eSDavid Sterba action, kobject_name(&disk_to_dev(bdev->bd_disk)->kobj), 18785b28692eSDavid Sterba &disk_to_dev(bdev->bd_disk)->kobj); 18795b28692eSDavid Sterba } 18805b28692eSDavid Sterba 18818e560081SNikolay Borisov void btrfs_sysfs_update_sprout_fsid(struct btrfs_fs_devices *fs_devices) 18828e560081SNikolay Borisov 1883f93c3997SDavid Sterba { 1884f93c3997SDavid Sterba char fsid_buf[BTRFS_UUID_UNPARSED_SIZE]; 1885f93c3997SDavid Sterba 1886f93c3997SDavid Sterba /* 1887f93c3997SDavid Sterba * Sprouting changes fsid of the mounted filesystem, rename the fsid 1888f93c3997SDavid Sterba * directory 1889f93c3997SDavid Sterba */ 18908e560081SNikolay Borisov snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", fs_devices->fsid); 1891f93c3997SDavid Sterba if (kobject_rename(&fs_devices->fsid_kobj, fsid_buf)) 1892f93c3997SDavid Sterba btrfs_warn(fs_devices->fs_info, 1893f93c3997SDavid Sterba "sysfs: failed to create fsid for sprout"); 1894f93c3997SDavid Sterba } 1895f93c3997SDavid Sterba 1896668e48afSAnand Jain void btrfs_sysfs_update_devid(struct btrfs_device *device) 1897668e48afSAnand Jain { 1898668e48afSAnand Jain char tmp[24]; 1899668e48afSAnand Jain 1900668e48afSAnand Jain snprintf(tmp, sizeof(tmp), "%llu", device->devid); 1901668e48afSAnand Jain 1902668e48afSAnand Jain if (kobject_rename(&device->devid_kobj, tmp)) 1903668e48afSAnand Jain btrfs_warn(device->fs_devices->fs_info, 1904668e48afSAnand Jain "sysfs: failed to update devid for %llu", 1905668e48afSAnand Jain device->devid); 1906668e48afSAnand Jain } 1907668e48afSAnand Jain 1908510d7360SJeff Mahoney /* /sys/fs/btrfs/ entry */ 1909510d7360SJeff Mahoney static struct kset *btrfs_kset; 1910510d7360SJeff Mahoney 191172059215SAnand Jain /* 1912c6761a9eSAnand Jain * Creates: 1913c6761a9eSAnand Jain * /sys/fs/btrfs/UUID 1914c6761a9eSAnand Jain * 191572059215SAnand Jain * Can be called by the device discovery thread. 191672059215SAnand Jain */ 1917c6761a9eSAnand Jain int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs) 19185ac1d209SJeff Mahoney { 19195ac1d209SJeff Mahoney int error; 19205ac1d209SJeff Mahoney 19212e7910d6SAnand Jain init_completion(&fs_devs->kobj_unregister); 1922c1b7e474SAnand Jain fs_devs->fsid_kobj.kset = btrfs_kset; 1923c6761a9eSAnand Jain error = kobject_init_and_add(&fs_devs->fsid_kobj, &btrfs_ktype, NULL, 1924c6761a9eSAnand Jain "%pU", fs_devs->fsid); 1925e3277335STobin C. Harding if (error) { 1926e3277335STobin C. Harding kobject_put(&fs_devs->fsid_kobj); 192772059215SAnand Jain return error; 192872059215SAnand Jain } 192972059215SAnand Jain 1930bc036bb3SAnand Jain fs_devs->devices_kobj = kobject_create_and_add("devices", 1931bc036bb3SAnand Jain &fs_devs->fsid_kobj); 1932bc036bb3SAnand Jain if (!fs_devs->devices_kobj) { 1933bc036bb3SAnand Jain btrfs_err(fs_devs->fs_info, 1934bc036bb3SAnand Jain "failed to init sysfs device interface"); 19351f6087e6SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1936bc036bb3SAnand Jain return -ENOMEM; 1937bc036bb3SAnand Jain } 1938bc036bb3SAnand Jain 1939a013d141SAnand Jain fs_devs->devinfo_kobj = kobject_create_and_add("devinfo", 1940a013d141SAnand Jain &fs_devs->fsid_kobj); 1941a013d141SAnand Jain if (!fs_devs->devinfo_kobj) { 1942a013d141SAnand Jain btrfs_err(fs_devs->fs_info, 1943a013d141SAnand Jain "failed to init sysfs devinfo kobject"); 1944a013d141SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1945a013d141SAnand Jain return -ENOMEM; 1946a013d141SAnand Jain } 1947a013d141SAnand Jain 1948e3277335STobin C. Harding return 0; 1949e3277335STobin C. Harding } 1950e3277335STobin C. Harding 195196f3136eSAnand Jain int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info) 195272059215SAnand Jain { 195372059215SAnand Jain int error; 19542e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = fs_info->fs_devices; 1955c1b7e474SAnand Jain struct kobject *fsid_kobj = &fs_devs->fsid_kobj; 195672059215SAnand Jain 1957cd36da2eSAnand Jain error = btrfs_sysfs_add_fs_devices(fs_devs); 1958e453d989SJeff Mahoney if (error) 1959e453d989SJeff Mahoney return error; 1960510d7360SJeff Mahoney 1961c1b7e474SAnand Jain error = sysfs_create_files(fsid_kobj, btrfs_attrs); 1962e453d989SJeff Mahoney if (error) { 196353f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devs); 1964e453d989SJeff Mahoney return error; 1965e453d989SJeff Mahoney } 196679da4fa4SJeff Mahoney 1967c1b7e474SAnand Jain error = sysfs_create_group(fsid_kobj, 19680dd2906fSAnand Jain &btrfs_feature_attr_group); 19690dd2906fSAnand Jain if (error) 19700dd2906fSAnand Jain goto failure; 19710dd2906fSAnand Jain 19726e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 197393945cb4SDennis Zhou fs_info->debug_kobj = kobject_create_and_add("debug", fsid_kobj); 197493945cb4SDennis Zhou if (!fs_info->debug_kobj) { 197593945cb4SDennis Zhou error = -ENOMEM; 197693945cb4SDennis Zhou goto failure; 197793945cb4SDennis Zhou } 197893945cb4SDennis Zhou 197993945cb4SDennis Zhou error = sysfs_create_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 19806e369febSDavid Sterba if (error) 19816e369febSDavid Sterba goto failure; 1982fb731430SDavid Sterba #endif 1983e4faab84SDennis Zhou 1984e4faab84SDennis Zhou /* Discard directory */ 1985fb731430SDavid Sterba fs_info->discard_kobj = kobject_create_and_add("discard", fsid_kobj); 1986fb731430SDavid Sterba if (!fs_info->discard_kobj) { 1987e4faab84SDennis Zhou error = -ENOMEM; 1988e4faab84SDennis Zhou goto failure; 1989e4faab84SDennis Zhou } 1990e4faab84SDennis Zhou 1991fb731430SDavid Sterba error = sysfs_create_files(fs_info->discard_kobj, discard_attrs); 1992e4faab84SDennis Zhou if (error) 1993e4faab84SDennis Zhou goto failure; 19946e369febSDavid Sterba 1995e453d989SJeff Mahoney error = addrm_unknown_feature_attrs(fs_info, true); 199679da4fa4SJeff Mahoney if (error) 199779da4fa4SJeff Mahoney goto failure; 199879da4fa4SJeff Mahoney 19993092c68fSNikolay Borisov error = sysfs_create_link(fsid_kobj, &fs_info->sb->s_bdi->dev->kobj, "bdi"); 20003092c68fSNikolay Borisov if (error) 20013092c68fSNikolay Borisov goto failure; 20023092c68fSNikolay Borisov 20036ab0a202SJeff Mahoney fs_info->space_info_kobj = kobject_create_and_add("allocation", 2004c1b7e474SAnand Jain fsid_kobj); 20056ab0a202SJeff Mahoney if (!fs_info->space_info_kobj) { 20066ab0a202SJeff Mahoney error = -ENOMEM; 20076ab0a202SJeff Mahoney goto failure; 20086ab0a202SJeff Mahoney } 20096ab0a202SJeff Mahoney 20106ab0a202SJeff Mahoney error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs); 20116ab0a202SJeff Mahoney if (error) 20126ab0a202SJeff Mahoney goto failure; 20136ab0a202SJeff Mahoney 201479da4fa4SJeff Mahoney return 0; 201579da4fa4SJeff Mahoney failure: 20166618a59bSAnand Jain btrfs_sysfs_remove_mounted(fs_info); 20175ac1d209SJeff Mahoney return error; 20185ac1d209SJeff Mahoney } 20195ac1d209SJeff Mahoney 2020ed2e35d8SQu Wenruo static ssize_t qgroup_enabled_show(struct kobject *qgroups_kobj, 2021ed2e35d8SQu Wenruo struct kobj_attribute *a, 2022ed2e35d8SQu Wenruo char *buf) 2023ed2e35d8SQu Wenruo { 2024ed2e35d8SQu Wenruo struct btrfs_fs_info *fs_info = to_fs_info(qgroups_kobj->parent); 2025ed2e35d8SQu Wenruo bool enabled; 2026ed2e35d8SQu Wenruo 2027ed2e35d8SQu Wenruo spin_lock(&fs_info->qgroup_lock); 2028ed2e35d8SQu Wenruo enabled = fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON; 2029ed2e35d8SQu Wenruo spin_unlock(&fs_info->qgroup_lock); 2030ed2e35d8SQu Wenruo 2031ed2e35d8SQu Wenruo return sysfs_emit(buf, "%d\n", enabled); 2032ed2e35d8SQu Wenruo } 2033ed2e35d8SQu Wenruo BTRFS_ATTR(qgroups, enabled, qgroup_enabled_show); 2034ed2e35d8SQu Wenruo 2035ed2e35d8SQu Wenruo static ssize_t qgroup_inconsistent_show(struct kobject *qgroups_kobj, 2036ed2e35d8SQu Wenruo struct kobj_attribute *a, 2037ed2e35d8SQu Wenruo char *buf) 2038ed2e35d8SQu Wenruo { 2039ed2e35d8SQu Wenruo struct btrfs_fs_info *fs_info = to_fs_info(qgroups_kobj->parent); 2040ed2e35d8SQu Wenruo bool inconsistent; 2041ed2e35d8SQu Wenruo 2042ed2e35d8SQu Wenruo spin_lock(&fs_info->qgroup_lock); 2043ed2e35d8SQu Wenruo inconsistent = (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT); 2044ed2e35d8SQu Wenruo spin_unlock(&fs_info->qgroup_lock); 2045ed2e35d8SQu Wenruo 2046ed2e35d8SQu Wenruo return sysfs_emit(buf, "%d\n", inconsistent); 2047ed2e35d8SQu Wenruo } 2048ed2e35d8SQu Wenruo BTRFS_ATTR(qgroups, inconsistent, qgroup_inconsistent_show); 2049ed2e35d8SQu Wenruo 2050011b46c3SQu Wenruo static ssize_t qgroup_drop_subtree_thres_show(struct kobject *qgroups_kobj, 2051011b46c3SQu Wenruo struct kobj_attribute *a, 2052011b46c3SQu Wenruo char *buf) 2053011b46c3SQu Wenruo { 2054011b46c3SQu Wenruo struct btrfs_fs_info *fs_info = to_fs_info(qgroups_kobj->parent); 2055011b46c3SQu Wenruo u8 result; 2056011b46c3SQu Wenruo 2057011b46c3SQu Wenruo spin_lock(&fs_info->qgroup_lock); 2058011b46c3SQu Wenruo result = fs_info->qgroup_drop_subtree_thres; 2059011b46c3SQu Wenruo spin_unlock(&fs_info->qgroup_lock); 2060011b46c3SQu Wenruo 2061011b46c3SQu Wenruo return sysfs_emit(buf, "%d\n", result); 2062011b46c3SQu Wenruo } 2063011b46c3SQu Wenruo 2064011b46c3SQu Wenruo static ssize_t qgroup_drop_subtree_thres_store(struct kobject *qgroups_kobj, 2065011b46c3SQu Wenruo struct kobj_attribute *a, 2066011b46c3SQu Wenruo const char *buf, size_t len) 2067011b46c3SQu Wenruo { 2068011b46c3SQu Wenruo struct btrfs_fs_info *fs_info = to_fs_info(qgroups_kobj->parent); 2069011b46c3SQu Wenruo u8 new_thres; 2070011b46c3SQu Wenruo int ret; 2071011b46c3SQu Wenruo 2072011b46c3SQu Wenruo ret = kstrtou8(buf, 10, &new_thres); 2073011b46c3SQu Wenruo if (ret) 2074011b46c3SQu Wenruo return -EINVAL; 2075011b46c3SQu Wenruo 2076011b46c3SQu Wenruo if (new_thres > BTRFS_MAX_LEVEL) 2077011b46c3SQu Wenruo return -EINVAL; 2078011b46c3SQu Wenruo 2079011b46c3SQu Wenruo spin_lock(&fs_info->qgroup_lock); 2080011b46c3SQu Wenruo fs_info->qgroup_drop_subtree_thres = new_thres; 2081011b46c3SQu Wenruo spin_unlock(&fs_info->qgroup_lock); 2082011b46c3SQu Wenruo 2083011b46c3SQu Wenruo return len; 2084011b46c3SQu Wenruo } 2085011b46c3SQu Wenruo BTRFS_ATTR_RW(qgroups, drop_subtree_threshold, qgroup_drop_subtree_thres_show, 2086011b46c3SQu Wenruo qgroup_drop_subtree_thres_store); 2087011b46c3SQu Wenruo 2088ed2e35d8SQu Wenruo /* 2089ed2e35d8SQu Wenruo * Qgroups global info 2090ed2e35d8SQu Wenruo * 2091ed2e35d8SQu Wenruo * Path: /sys/fs/btrfs/<uuid>/qgroups/ 2092ed2e35d8SQu Wenruo */ 2093ed2e35d8SQu Wenruo static struct attribute *qgroups_attrs[] = { 2094ed2e35d8SQu Wenruo BTRFS_ATTR_PTR(qgroups, enabled), 2095ed2e35d8SQu Wenruo BTRFS_ATTR_PTR(qgroups, inconsistent), 2096011b46c3SQu Wenruo BTRFS_ATTR_PTR(qgroups, drop_subtree_threshold), 2097ed2e35d8SQu Wenruo NULL 2098ed2e35d8SQu Wenruo }; 2099ed2e35d8SQu Wenruo ATTRIBUTE_GROUPS(qgroups); 2100ed2e35d8SQu Wenruo 2101ed2e35d8SQu Wenruo static void qgroups_release(struct kobject *kobj) 2102ed2e35d8SQu Wenruo { 2103ed2e35d8SQu Wenruo kfree(kobj); 2104ed2e35d8SQu Wenruo } 2105ed2e35d8SQu Wenruo 2106ed2e35d8SQu Wenruo static struct kobj_type qgroups_ktype = { 2107ed2e35d8SQu Wenruo .sysfs_ops = &kobj_sysfs_ops, 2108ed2e35d8SQu Wenruo .default_groups = qgroups_groups, 2109ed2e35d8SQu Wenruo .release = qgroups_release, 2110ed2e35d8SQu Wenruo }; 2111ed2e35d8SQu Wenruo 211249e5fb46SQu Wenruo static inline struct btrfs_fs_info *qgroup_kobj_to_fs_info(struct kobject *kobj) 211349e5fb46SQu Wenruo { 211449e5fb46SQu Wenruo return to_fs_info(kobj->parent->parent); 211549e5fb46SQu Wenruo } 211649e5fb46SQu Wenruo 211749e5fb46SQu Wenruo #define QGROUP_ATTR(_member, _show_name) \ 211849e5fb46SQu Wenruo static ssize_t btrfs_qgroup_show_##_member(struct kobject *qgroup_kobj, \ 211949e5fb46SQu Wenruo struct kobj_attribute *a, \ 212049e5fb46SQu Wenruo char *buf) \ 212149e5fb46SQu Wenruo { \ 212249e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 212349e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 212449e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 212549e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->_member, &fs_info->qgroup_lock, buf); \ 212649e5fb46SQu Wenruo } \ 212749e5fb46SQu Wenruo BTRFS_ATTR(qgroup, _show_name, btrfs_qgroup_show_##_member) 212849e5fb46SQu Wenruo 212949e5fb46SQu Wenruo #define QGROUP_RSV_ATTR(_name, _type) \ 213049e5fb46SQu Wenruo static ssize_t btrfs_qgroup_rsv_show_##_name(struct kobject *qgroup_kobj, \ 213149e5fb46SQu Wenruo struct kobj_attribute *a, \ 213249e5fb46SQu Wenruo char *buf) \ 213349e5fb46SQu Wenruo { \ 213449e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 213549e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 213649e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 213749e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->rsv.values[_type], \ 213849e5fb46SQu Wenruo &fs_info->qgroup_lock, buf); \ 213949e5fb46SQu Wenruo } \ 214049e5fb46SQu Wenruo BTRFS_ATTR(qgroup, rsv_##_name, btrfs_qgroup_rsv_show_##_name) 214149e5fb46SQu Wenruo 214249e5fb46SQu Wenruo QGROUP_ATTR(rfer, referenced); 214349e5fb46SQu Wenruo QGROUP_ATTR(excl, exclusive); 214449e5fb46SQu Wenruo QGROUP_ATTR(max_rfer, max_referenced); 214549e5fb46SQu Wenruo QGROUP_ATTR(max_excl, max_exclusive); 214649e5fb46SQu Wenruo QGROUP_ATTR(lim_flags, limit_flags); 214749e5fb46SQu Wenruo QGROUP_RSV_ATTR(data, BTRFS_QGROUP_RSV_DATA); 214849e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_pertrans, BTRFS_QGROUP_RSV_META_PERTRANS); 214949e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_prealloc, BTRFS_QGROUP_RSV_META_PREALLOC); 215049e5fb46SQu Wenruo 2151e7849e33SAnand Jain /* 2152e7849e33SAnand Jain * Qgroup information. 2153e7849e33SAnand Jain * 2154e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/qgroups/<level>_<qgroupid>/ 2155e7849e33SAnand Jain */ 215649e5fb46SQu Wenruo static struct attribute *qgroup_attrs[] = { 215749e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, referenced), 215849e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, exclusive), 215949e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_referenced), 216049e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_exclusive), 216149e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, limit_flags), 216249e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_data), 216349e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_pertrans), 216449e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_prealloc), 216549e5fb46SQu Wenruo NULL 216649e5fb46SQu Wenruo }; 216749e5fb46SQu Wenruo ATTRIBUTE_GROUPS(qgroup); 216849e5fb46SQu Wenruo 216949e5fb46SQu Wenruo static void qgroup_release(struct kobject *kobj) 217049e5fb46SQu Wenruo { 217149e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(kobj, struct btrfs_qgroup, kobj); 217249e5fb46SQu Wenruo 217349e5fb46SQu Wenruo memset(&qgroup->kobj, 0, sizeof(*kobj)); 217449e5fb46SQu Wenruo } 217549e5fb46SQu Wenruo 217649e5fb46SQu Wenruo static struct kobj_type qgroup_ktype = { 217749e5fb46SQu Wenruo .sysfs_ops = &kobj_sysfs_ops, 217849e5fb46SQu Wenruo .release = qgroup_release, 217949e5fb46SQu Wenruo .default_groups = qgroup_groups, 218049e5fb46SQu Wenruo }; 218149e5fb46SQu Wenruo 218249e5fb46SQu Wenruo int btrfs_sysfs_add_one_qgroup(struct btrfs_fs_info *fs_info, 218349e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 218449e5fb46SQu Wenruo { 218549e5fb46SQu Wenruo struct kobject *qgroups_kobj = fs_info->qgroups_kobj; 218649e5fb46SQu Wenruo int ret; 218749e5fb46SQu Wenruo 218849e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 218949e5fb46SQu Wenruo return 0; 219049e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) 219149e5fb46SQu Wenruo return 0; 219249e5fb46SQu Wenruo if (!qgroups_kobj) 219349e5fb46SQu Wenruo return -EINVAL; 219449e5fb46SQu Wenruo 219549e5fb46SQu Wenruo ret = kobject_init_and_add(&qgroup->kobj, &qgroup_ktype, qgroups_kobj, 219649e5fb46SQu Wenruo "%hu_%llu", btrfs_qgroup_level(qgroup->qgroupid), 219749e5fb46SQu Wenruo btrfs_qgroup_subvolid(qgroup->qgroupid)); 219849e5fb46SQu Wenruo if (ret < 0) 219949e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 220049e5fb46SQu Wenruo 220149e5fb46SQu Wenruo return ret; 220249e5fb46SQu Wenruo } 220349e5fb46SQu Wenruo 220449e5fb46SQu Wenruo void btrfs_sysfs_del_qgroups(struct btrfs_fs_info *fs_info) 220549e5fb46SQu Wenruo { 220649e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 220749e5fb46SQu Wenruo struct btrfs_qgroup *next; 220849e5fb46SQu Wenruo 220949e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 221049e5fb46SQu Wenruo return; 221149e5fb46SQu Wenruo 221249e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 221349e5fb46SQu Wenruo &fs_info->qgroup_tree, node) 221449e5fb46SQu Wenruo btrfs_sysfs_del_one_qgroup(fs_info, qgroup); 221562ab2cc0SQu Wenruo if (fs_info->qgroups_kobj) { 221649e5fb46SQu Wenruo kobject_del(fs_info->qgroups_kobj); 221749e5fb46SQu Wenruo kobject_put(fs_info->qgroups_kobj); 221849e5fb46SQu Wenruo fs_info->qgroups_kobj = NULL; 221949e5fb46SQu Wenruo } 222062ab2cc0SQu Wenruo } 222149e5fb46SQu Wenruo 222249e5fb46SQu Wenruo /* Called when qgroups get initialized, thus there is no need for locking */ 222349e5fb46SQu Wenruo int btrfs_sysfs_add_qgroups(struct btrfs_fs_info *fs_info) 222449e5fb46SQu Wenruo { 222549e5fb46SQu Wenruo struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 222649e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 222749e5fb46SQu Wenruo struct btrfs_qgroup *next; 222849e5fb46SQu Wenruo int ret = 0; 222949e5fb46SQu Wenruo 223049e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 223149e5fb46SQu Wenruo return 0; 223249e5fb46SQu Wenruo 223349e5fb46SQu Wenruo ASSERT(fsid_kobj); 223449e5fb46SQu Wenruo if (fs_info->qgroups_kobj) 223549e5fb46SQu Wenruo return 0; 223649e5fb46SQu Wenruo 2237ed2e35d8SQu Wenruo fs_info->qgroups_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); 2238ed2e35d8SQu Wenruo if (!fs_info->qgroups_kobj) 2239ed2e35d8SQu Wenruo return -ENOMEM; 2240ed2e35d8SQu Wenruo 2241ed2e35d8SQu Wenruo ret = kobject_init_and_add(fs_info->qgroups_kobj, &qgroups_ktype, 2242ed2e35d8SQu Wenruo fsid_kobj, "qgroups"); 2243ed2e35d8SQu Wenruo if (ret < 0) 224449e5fb46SQu Wenruo goto out; 2245ed2e35d8SQu Wenruo 224649e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 224749e5fb46SQu Wenruo &fs_info->qgroup_tree, node) { 224849e5fb46SQu Wenruo ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup); 224949e5fb46SQu Wenruo if (ret < 0) 225049e5fb46SQu Wenruo goto out; 225149e5fb46SQu Wenruo } 225249e5fb46SQu Wenruo 225349e5fb46SQu Wenruo out: 225449e5fb46SQu Wenruo if (ret < 0) 225549e5fb46SQu Wenruo btrfs_sysfs_del_qgroups(fs_info); 225649e5fb46SQu Wenruo return ret; 225749e5fb46SQu Wenruo } 225849e5fb46SQu Wenruo 225949e5fb46SQu Wenruo void btrfs_sysfs_del_one_qgroup(struct btrfs_fs_info *fs_info, 226049e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 226149e5fb46SQu Wenruo { 226249e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 226349e5fb46SQu Wenruo return; 226449e5fb46SQu Wenruo 226549e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) { 226649e5fb46SQu Wenruo kobject_del(&qgroup->kobj); 226749e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 226849e5fb46SQu Wenruo } 226949e5fb46SQu Wenruo } 2270444e7516SDavid Sterba 2271444e7516SDavid Sterba /* 2272444e7516SDavid Sterba * Change per-fs features in /sys/fs/btrfs/UUID/features to match current 2273444e7516SDavid Sterba * values in superblock. Call after any changes to incompat/compat_ro flags 2274444e7516SDavid Sterba */ 2275444e7516SDavid Sterba void btrfs_sysfs_feature_update(struct btrfs_fs_info *fs_info, 2276444e7516SDavid Sterba u64 bit, enum btrfs_feature_set set) 2277444e7516SDavid Sterba { 2278444e7516SDavid Sterba struct btrfs_fs_devices *fs_devs; 2279444e7516SDavid Sterba struct kobject *fsid_kobj; 228024646481SLeon Romanovsky u64 __maybe_unused features; 228124646481SLeon Romanovsky int __maybe_unused ret; 2282444e7516SDavid Sterba 2283444e7516SDavid Sterba if (!fs_info) 2284444e7516SDavid Sterba return; 2285444e7516SDavid Sterba 228624646481SLeon Romanovsky /* 228724646481SLeon Romanovsky * See 14e46e04958df74 and e410e34fad913dd, feature bit updates are not 228824646481SLeon Romanovsky * safe when called from some contexts (eg. balance) 228924646481SLeon Romanovsky */ 2290444e7516SDavid Sterba features = get_features(fs_info, set); 2291444e7516SDavid Sterba ASSERT(bit & supported_feature_masks[set]); 2292444e7516SDavid Sterba 2293444e7516SDavid Sterba fs_devs = fs_info->fs_devices; 2294444e7516SDavid Sterba fsid_kobj = &fs_devs->fsid_kobj; 2295444e7516SDavid Sterba 2296bf609206SDavid Sterba if (!fsid_kobj->state_initialized) 2297bf609206SDavid Sterba return; 2298bf609206SDavid Sterba 2299444e7516SDavid Sterba /* 2300444e7516SDavid Sterba * FIXME: this is too heavy to update just one value, ideally we'd like 2301444e7516SDavid Sterba * to use sysfs_update_group but some refactoring is needed first. 2302444e7516SDavid Sterba */ 2303444e7516SDavid Sterba sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 2304444e7516SDavid Sterba ret = sysfs_create_group(fsid_kobj, &btrfs_feature_attr_group); 2305444e7516SDavid Sterba } 2306444e7516SDavid Sterba 2307f5c29bd9SLiu Bo int __init btrfs_init_sysfs(void) 230858176a96SJosef Bacik { 2309079b72bcSJeff Mahoney int ret; 23101bae3098SDavid Sterba 2311e3fe4e71SGreg KH btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); 2312e3fe4e71SGreg KH if (!btrfs_kset) 2313e3fe4e71SGreg KH return -ENOMEM; 2314079b72bcSJeff Mahoney 23151bae3098SDavid Sterba init_feature_attrs(); 23161bae3098SDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2317001a648dSFilipe Manana if (ret) 2318001a648dSFilipe Manana goto out2; 2319f902bd3aSMisono Tomohiro ret = sysfs_merge_group(&btrfs_kset->kobj, 2320f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2321f902bd3aSMisono Tomohiro if (ret) 2322f902bd3aSMisono Tomohiro goto out_remove_group; 2323001a648dSFilipe Manana 23246e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 23256e369febSDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 2326ffdbb44fSZhen Lei if (ret) { 2327ffdbb44fSZhen Lei sysfs_unmerge_group(&btrfs_kset->kobj, 2328ffdbb44fSZhen Lei &btrfs_static_feature_attr_group); 2329ffdbb44fSZhen Lei goto out_remove_group; 2330ffdbb44fSZhen Lei } 23316e369febSDavid Sterba #endif 23326e369febSDavid Sterba 2333001a648dSFilipe Manana return 0; 2334f902bd3aSMisono Tomohiro 2335f902bd3aSMisono Tomohiro out_remove_group: 2336f902bd3aSMisono Tomohiro sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2337001a648dSFilipe Manana out2: 2338001a648dSFilipe Manana kset_unregister(btrfs_kset); 23391bae3098SDavid Sterba 23401bae3098SDavid Sterba return ret; 234158176a96SJosef Bacik } 234258176a96SJosef Bacik 2343e67c718bSDavid Sterba void __cold btrfs_exit_sysfs(void) 234458176a96SJosef Bacik { 2345f902bd3aSMisono Tomohiro sysfs_unmerge_group(&btrfs_kset->kobj, 2346f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2347079b72bcSJeff Mahoney sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 234871e8978eSDennis Zhou #ifdef CONFIG_BTRFS_DEBUG 234971e8978eSDennis Zhou sysfs_remove_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 235071e8978eSDennis Zhou #endif 2351e3fe4e71SGreg KH kset_unregister(btrfs_kset); 235258176a96SJosef Bacik } 2353