1c1d7c514SDavid Sterba // SPDX-License-Identifier: GPL-2.0 26cbd5570SChris Mason /* 36cbd5570SChris Mason * Copyright (C) 2007 Oracle. All rights reserved. 46cbd5570SChris Mason */ 56cbd5570SChris Mason 658176a96SJosef Bacik #include <linux/sched.h> 732a9991fSDavid Sterba #include <linux/sched/mm.h> 858176a96SJosef Bacik #include <linux/slab.h> 958176a96SJosef Bacik #include <linux/spinlock.h> 1058176a96SJosef Bacik #include <linux/completion.h> 1179da4fa4SJeff Mahoney #include <linux/bug.h> 1241e6d2a8SJohannes Thumshirn #include <crypto/hash.h> 1358176a96SJosef Bacik 14bae45de0SChris Mason #include "ctree.h" 15dfb79ddbSDennis Zhou #include "discard.h" 16bae45de0SChris Mason #include "disk-io.h" 177573df55SOmar Sandoval #include "send.h" 18bae45de0SChris Mason #include "transaction.h" 19079b72bcSJeff Mahoney #include "sysfs.h" 2029e5be24SJeff Mahoney #include "volumes.h" 218719aaaeSJosef Bacik #include "space-info.h" 22aac0023cSJosef Bacik #include "block-group.h" 2349e5fb46SQu Wenruo #include "qgroup.h" 24079b72bcSJeff Mahoney 25e7849e33SAnand Jain /* 26e7849e33SAnand Jain * Structure name Path 27e7849e33SAnand Jain * -------------------------------------------------------------------------- 28e7849e33SAnand Jain * btrfs_supported_static_feature_attrs /sys/fs/btrfs/features 29e7849e33SAnand Jain * btrfs_supported_feature_attrs /sys/fs/btrfs/features and 30e7849e33SAnand Jain * /sys/fs/btrfs/<uuid>/features 31e7849e33SAnand Jain * btrfs_attrs /sys/fs/btrfs/<uuid> 32e7849e33SAnand Jain * devid_attrs /sys/fs/btrfs/<uuid>/devinfo/<devid> 33e7849e33SAnand Jain * allocation_attrs /sys/fs/btrfs/<uuid>/allocation 34e7849e33SAnand Jain * qgroup_attrs /sys/fs/btrfs/<uuid>/qgroups/<level>_<qgroupid> 35e7849e33SAnand Jain * space_info_attrs /sys/fs/btrfs/<uuid>/allocation/<bg-type> 36e7849e33SAnand Jain * raid_attrs /sys/fs/btrfs/<uuid>/allocation/<bg-type>/<bg-profile> 37e7849e33SAnand Jain * 38e7849e33SAnand Jain * When built with BTRFS_CONFIG_DEBUG: 39e7849e33SAnand Jain * 40e7849e33SAnand Jain * btrfs_debug_feature_attrs /sys/fs/btrfs/debug 41e7849e33SAnand Jain * btrfs_debug_mount_attrs /sys/fs/btrfs/<uuid>/debug 42e7849e33SAnand Jain * discard_debug_attrs /sys/fs/btrfs/<uuid>/debug/discard 43e7849e33SAnand Jain */ 44e7849e33SAnand Jain 459188db61SDavid Sterba struct btrfs_feature_attr { 469188db61SDavid Sterba struct kobj_attribute kobj_attr; 479188db61SDavid Sterba enum btrfs_feature_set feature_set; 489188db61SDavid Sterba u64 feature_bit; 499188db61SDavid Sterba }; 509188db61SDavid Sterba 519188db61SDavid Sterba /* For raid type sysfs entries */ 529188db61SDavid Sterba struct raid_kobject { 539188db61SDavid Sterba u64 flags; 549188db61SDavid Sterba struct kobject kobj; 559188db61SDavid Sterba }; 569188db61SDavid Sterba 579188db61SDavid Sterba #define __INIT_KOBJ_ATTR(_name, _mode, _show, _store) \ 589188db61SDavid Sterba { \ 599188db61SDavid Sterba .attr = { .name = __stringify(_name), .mode = _mode }, \ 609188db61SDavid Sterba .show = _show, \ 619188db61SDavid Sterba .store = _store, \ 629188db61SDavid Sterba } 639188db61SDavid Sterba 649188db61SDavid Sterba #define BTRFS_ATTR_RW(_prefix, _name, _show, _store) \ 659188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 669188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0644, _show, _store) 679188db61SDavid Sterba 689188db61SDavid Sterba #define BTRFS_ATTR(_prefix, _name, _show) \ 699188db61SDavid Sterba static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ 709188db61SDavid Sterba __INIT_KOBJ_ATTR(_name, 0444, _show, NULL) 719188db61SDavid Sterba 729188db61SDavid Sterba #define BTRFS_ATTR_PTR(_prefix, _name) \ 739188db61SDavid Sterba (&btrfs_attr_##_prefix##_##_name.attr) 749188db61SDavid Sterba 759188db61SDavid Sterba #define BTRFS_FEAT_ATTR(_name, _feature_set, _feature_prefix, _feature_bit) \ 769188db61SDavid Sterba static struct btrfs_feature_attr btrfs_attr_features_##_name = { \ 779188db61SDavid Sterba .kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO, \ 789188db61SDavid Sterba btrfs_feature_attr_show, \ 799188db61SDavid Sterba btrfs_feature_attr_store), \ 809188db61SDavid Sterba .feature_set = _feature_set, \ 819188db61SDavid Sterba .feature_bit = _feature_prefix ##_## _feature_bit, \ 829188db61SDavid Sterba } 839188db61SDavid Sterba #define BTRFS_FEAT_ATTR_PTR(_name) \ 849188db61SDavid Sterba (&btrfs_attr_features_##_name.kobj_attr.attr) 859188db61SDavid Sterba 869188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT(name, feature) \ 879188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT, BTRFS_FEATURE_COMPAT, feature) 889188db61SDavid Sterba #define BTRFS_FEAT_ATTR_COMPAT_RO(name, feature) \ 899188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_COMPAT_RO, BTRFS_FEATURE_COMPAT_RO, feature) 909188db61SDavid Sterba #define BTRFS_FEAT_ATTR_INCOMPAT(name, feature) \ 919188db61SDavid Sterba BTRFS_FEAT_ATTR(name, FEAT_INCOMPAT, BTRFS_FEATURE_INCOMPAT, feature) 929188db61SDavid Sterba 93510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); 942e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj); 955ac1d209SJeff Mahoney 968f52316cSDavid Sterba static struct btrfs_feature_attr *to_btrfs_feature_attr(struct kobj_attribute *a) 978f52316cSDavid Sterba { 988f52316cSDavid Sterba return container_of(a, struct btrfs_feature_attr, kobj_attr); 998f52316cSDavid Sterba } 1008f52316cSDavid Sterba 1018f52316cSDavid Sterba static struct kobj_attribute *attr_to_btrfs_attr(struct attribute *attr) 1028f52316cSDavid Sterba { 1038f52316cSDavid Sterba return container_of(attr, struct kobj_attribute, attr); 1048f52316cSDavid Sterba } 1058f52316cSDavid Sterba 1068f52316cSDavid Sterba static struct btrfs_feature_attr *attr_to_btrfs_feature_attr( 1078f52316cSDavid Sterba struct attribute *attr) 1088f52316cSDavid Sterba { 1098f52316cSDavid Sterba return to_btrfs_feature_attr(attr_to_btrfs_attr(attr)); 1108f52316cSDavid Sterba } 1118f52316cSDavid Sterba 112510d7360SJeff Mahoney static u64 get_features(struct btrfs_fs_info *fs_info, 113510d7360SJeff Mahoney enum btrfs_feature_set set) 1145ac1d209SJeff Mahoney { 115510d7360SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 116510d7360SJeff Mahoney if (set == FEAT_COMPAT) 117510d7360SJeff Mahoney return btrfs_super_compat_flags(disk_super); 118510d7360SJeff Mahoney else if (set == FEAT_COMPAT_RO) 119510d7360SJeff Mahoney return btrfs_super_compat_ro_flags(disk_super); 120510d7360SJeff Mahoney else 121510d7360SJeff Mahoney return btrfs_super_incompat_flags(disk_super); 1225ac1d209SJeff Mahoney } 1235ac1d209SJeff Mahoney 124ba631941SJeff Mahoney static void set_features(struct btrfs_fs_info *fs_info, 125ba631941SJeff Mahoney enum btrfs_feature_set set, u64 features) 126ba631941SJeff Mahoney { 127ba631941SJeff Mahoney struct btrfs_super_block *disk_super = fs_info->super_copy; 128ba631941SJeff Mahoney if (set == FEAT_COMPAT) 129ba631941SJeff Mahoney btrfs_set_super_compat_flags(disk_super, features); 130ba631941SJeff Mahoney else if (set == FEAT_COMPAT_RO) 131ba631941SJeff Mahoney btrfs_set_super_compat_ro_flags(disk_super, features); 132ba631941SJeff Mahoney else 133ba631941SJeff Mahoney btrfs_set_super_incompat_flags(disk_super, features); 134ba631941SJeff Mahoney } 135ba631941SJeff Mahoney 136ba631941SJeff Mahoney static int can_modify_feature(struct btrfs_feature_attr *fa) 137ba631941SJeff Mahoney { 138ba631941SJeff Mahoney int val = 0; 139ba631941SJeff Mahoney u64 set, clear; 140ba631941SJeff Mahoney switch (fa->feature_set) { 141ba631941SJeff Mahoney case FEAT_COMPAT: 142ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 143ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 144ba631941SJeff Mahoney break; 145ba631941SJeff Mahoney case FEAT_COMPAT_RO: 146ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 147ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 148ba631941SJeff Mahoney break; 149ba631941SJeff Mahoney case FEAT_INCOMPAT: 150ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 151ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 152ba631941SJeff Mahoney break; 153ba631941SJeff Mahoney default: 15462e85577SJeff Mahoney pr_warn("btrfs: sysfs: unknown feature set %d\n", 155cc37bb04SDavid Sterba fa->feature_set); 156cc37bb04SDavid Sterba return 0; 157ba631941SJeff Mahoney } 158ba631941SJeff Mahoney 159ba631941SJeff Mahoney if (set & fa->feature_bit) 160ba631941SJeff Mahoney val |= 1; 161ba631941SJeff Mahoney if (clear & fa->feature_bit) 162ba631941SJeff Mahoney val |= 2; 163ba631941SJeff Mahoney 164ba631941SJeff Mahoney return val; 165ba631941SJeff Mahoney } 166ba631941SJeff Mahoney 167079b72bcSJeff Mahoney static ssize_t btrfs_feature_attr_show(struct kobject *kobj, 168079b72bcSJeff Mahoney struct kobj_attribute *a, char *buf) 169079b72bcSJeff Mahoney { 170510d7360SJeff Mahoney int val = 0; 171510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 172510d7360SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 173ba631941SJeff Mahoney if (fs_info) { 174510d7360SJeff Mahoney u64 features = get_features(fs_info, fa->feature_set); 175510d7360SJeff Mahoney if (features & fa->feature_bit) 176510d7360SJeff Mahoney val = 1; 177ba631941SJeff Mahoney } else 178ba631941SJeff Mahoney val = can_modify_feature(fa); 179510d7360SJeff Mahoney 180020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 181510d7360SJeff Mahoney } 182510d7360SJeff Mahoney 183ba631941SJeff Mahoney static ssize_t btrfs_feature_attr_store(struct kobject *kobj, 184ba631941SJeff Mahoney struct kobj_attribute *a, 185ba631941SJeff Mahoney const char *buf, size_t count) 186ba631941SJeff Mahoney { 187ba631941SJeff Mahoney struct btrfs_fs_info *fs_info; 188ba631941SJeff Mahoney struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); 189ba631941SJeff Mahoney u64 features, set, clear; 190ba631941SJeff Mahoney unsigned long val; 191ba631941SJeff Mahoney int ret; 192ba631941SJeff Mahoney 193ba631941SJeff Mahoney fs_info = to_fs_info(kobj); 194ba631941SJeff Mahoney if (!fs_info) 195ba631941SJeff Mahoney return -EPERM; 196ba631941SJeff Mahoney 197bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 198ee611138SDavid Sterba return -EROFS; 199ee611138SDavid Sterba 200ba631941SJeff Mahoney ret = kstrtoul(skip_spaces(buf), 0, &val); 201ba631941SJeff Mahoney if (ret) 202ba631941SJeff Mahoney return ret; 203ba631941SJeff Mahoney 204ba631941SJeff Mahoney if (fa->feature_set == FEAT_COMPAT) { 205ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_SAFE_SET; 206ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; 207ba631941SJeff Mahoney } else if (fa->feature_set == FEAT_COMPAT_RO) { 208ba631941SJeff Mahoney set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; 209ba631941SJeff Mahoney clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; 210ba631941SJeff Mahoney } else { 211ba631941SJeff Mahoney set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; 212ba631941SJeff Mahoney clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; 213ba631941SJeff Mahoney } 214ba631941SJeff Mahoney 215ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 216ba631941SJeff Mahoney 217ba631941SJeff Mahoney /* Nothing to do */ 218ba631941SJeff Mahoney if ((val && (features & fa->feature_bit)) || 219ba631941SJeff Mahoney (!val && !(features & fa->feature_bit))) 220ba631941SJeff Mahoney return count; 221ba631941SJeff Mahoney 222ba631941SJeff Mahoney if ((val && !(set & fa->feature_bit)) || 223ba631941SJeff Mahoney (!val && !(clear & fa->feature_bit))) { 224ba631941SJeff Mahoney btrfs_info(fs_info, 225ba631941SJeff Mahoney "%sabling feature %s on mounted fs is not supported.", 226ba631941SJeff Mahoney val ? "En" : "Dis", fa->kobj_attr.attr.name); 227ba631941SJeff Mahoney return -EPERM; 228ba631941SJeff Mahoney } 229ba631941SJeff Mahoney 230ba631941SJeff Mahoney btrfs_info(fs_info, "%s %s feature flag", 231ba631941SJeff Mahoney val ? "Setting" : "Clearing", fa->kobj_attr.attr.name); 232ba631941SJeff Mahoney 233ba631941SJeff Mahoney spin_lock(&fs_info->super_lock); 234ba631941SJeff Mahoney features = get_features(fs_info, fa->feature_set); 235ba631941SJeff Mahoney if (val) 236ba631941SJeff Mahoney features |= fa->feature_bit; 237ba631941SJeff Mahoney else 238ba631941SJeff Mahoney features &= ~fa->feature_bit; 239ba631941SJeff Mahoney set_features(fs_info, fa->feature_set, features); 240ba631941SJeff Mahoney spin_unlock(&fs_info->super_lock); 241ba631941SJeff Mahoney 2420eae2747SDavid Sterba /* 2430eae2747SDavid Sterba * We don't want to do full transaction commit from inside sysfs 2440eae2747SDavid Sterba */ 2450eae2747SDavid Sterba btrfs_set_pending(fs_info, COMMIT); 2460eae2747SDavid Sterba wake_up_process(fs_info->transaction_kthread); 247ba631941SJeff Mahoney 248ba631941SJeff Mahoney return count; 249ba631941SJeff Mahoney } 250ba631941SJeff Mahoney 251510d7360SJeff Mahoney static umode_t btrfs_feature_visible(struct kobject *kobj, 252510d7360SJeff Mahoney struct attribute *attr, int unused) 253510d7360SJeff Mahoney { 254510d7360SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 255510d7360SJeff Mahoney umode_t mode = attr->mode; 256510d7360SJeff Mahoney 257510d7360SJeff Mahoney if (fs_info) { 258510d7360SJeff Mahoney struct btrfs_feature_attr *fa; 259510d7360SJeff Mahoney u64 features; 260510d7360SJeff Mahoney 261510d7360SJeff Mahoney fa = attr_to_btrfs_feature_attr(attr); 262510d7360SJeff Mahoney features = get_features(fs_info, fa->feature_set); 263510d7360SJeff Mahoney 264ba631941SJeff Mahoney if (can_modify_feature(fa)) 265ba631941SJeff Mahoney mode |= S_IWUSR; 266ba631941SJeff Mahoney else if (!(features & fa->feature_bit)) 267510d7360SJeff Mahoney mode = 0; 268510d7360SJeff Mahoney } 269510d7360SJeff Mahoney 270510d7360SJeff Mahoney return mode; 271079b72bcSJeff Mahoney } 272079b72bcSJeff Mahoney 273079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_backref, MIXED_BACKREF); 274079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL); 275079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS); 276079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO); 2775c1aab1dSNick Terrell BTRFS_FEAT_ATTR_INCOMPAT(compress_zstd, COMPRESS_ZSTD); 278079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(big_metadata, BIG_METADATA); 279079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF); 280079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56); 281079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA); 282c736c095SDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES); 28356f20f40SNikolay Borisov BTRFS_FEAT_ATTR_INCOMPAT(metadata_uuid, METADATA_UUID); 2843b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE); 285cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_INCOMPAT(raid1c34, RAID1C34); 2867b3d5a90SNaohiro Aota /* Remove once support for zoned allocation is feature complete */ 2877b3d5a90SNaohiro Aota #ifdef CONFIG_BTRFS_DEBUG 2887b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_INCOMPAT(zoned, ZONED); 2897b3d5a90SNaohiro Aota #endif 29014605409SBoris Burkov #ifdef CONFIG_FS_VERITY 29114605409SBoris Burkov BTRFS_FEAT_ATTR_COMPAT_RO(verity, VERITY); 29214605409SBoris Burkov #endif 293079b72bcSJeff Mahoney 294e7849e33SAnand Jain /* 295e7849e33SAnand Jain * Features which depend on feature bits and may differ between each fs. 296e7849e33SAnand Jain * 297e7849e33SAnand Jain * /sys/fs/btrfs/features - all available features implemeted by this version 298e7849e33SAnand Jain * /sys/fs/btrfs/UUID/features - features of the fs which are enabled or 299e7849e33SAnand Jain * can be changed on a mounted filesystem. 300e7849e33SAnand Jain */ 301079b72bcSJeff Mahoney static struct attribute *btrfs_supported_feature_attrs[] = { 302079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_backref), 303079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(default_subvol), 304079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(mixed_groups), 305079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(compress_lzo), 3065c1aab1dSNick Terrell BTRFS_FEAT_ATTR_PTR(compress_zstd), 307079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(big_metadata), 308079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(extended_iref), 309079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(raid56), 310079b72bcSJeff Mahoney BTRFS_FEAT_ATTR_PTR(skinny_metadata), 311c736c095SDavid Sterba BTRFS_FEAT_ATTR_PTR(no_holes), 31256f20f40SNikolay Borisov BTRFS_FEAT_ATTR_PTR(metadata_uuid), 3133b5bb73bSDavid Sterba BTRFS_FEAT_ATTR_PTR(free_space_tree), 314cfbb825cSDavid Sterba BTRFS_FEAT_ATTR_PTR(raid1c34), 3157b3d5a90SNaohiro Aota #ifdef CONFIG_BTRFS_DEBUG 3167b3d5a90SNaohiro Aota BTRFS_FEAT_ATTR_PTR(zoned), 3177b3d5a90SNaohiro Aota #endif 31814605409SBoris Burkov #ifdef CONFIG_FS_VERITY 31914605409SBoris Burkov BTRFS_FEAT_ATTR_PTR(verity), 32014605409SBoris Burkov #endif 321079b72bcSJeff Mahoney NULL 322079b72bcSJeff Mahoney }; 323079b72bcSJeff Mahoney 324079b72bcSJeff Mahoney static const struct attribute_group btrfs_feature_attr_group = { 325079b72bcSJeff Mahoney .name = "features", 326510d7360SJeff Mahoney .is_visible = btrfs_feature_visible, 327079b72bcSJeff Mahoney .attrs = btrfs_supported_feature_attrs, 328079b72bcSJeff Mahoney }; 32958176a96SJosef Bacik 330f902bd3aSMisono Tomohiro static ssize_t rmdir_subvol_show(struct kobject *kobj, 331f902bd3aSMisono Tomohiro struct kobj_attribute *ka, char *buf) 332f902bd3aSMisono Tomohiro { 333020e5277SAnand Jain return sysfs_emit(buf, "0\n"); 334f902bd3aSMisono Tomohiro } 335f902bd3aSMisono Tomohiro BTRFS_ATTR(static_feature, rmdir_subvol, rmdir_subvol_show); 336f902bd3aSMisono Tomohiro 337f7cea56cSDavid Sterba static ssize_t supported_checksums_show(struct kobject *kobj, 338f7cea56cSDavid Sterba struct kobj_attribute *a, char *buf) 339f7cea56cSDavid Sterba { 340f7cea56cSDavid Sterba ssize_t ret = 0; 341f7cea56cSDavid Sterba int i; 342f7cea56cSDavid Sterba 343f7cea56cSDavid Sterba for (i = 0; i < btrfs_get_num_csums(); i++) { 344f7cea56cSDavid Sterba /* 345f7cea56cSDavid Sterba * This "trick" only works as long as 'enum btrfs_csum_type' has 346f7cea56cSDavid Sterba * no holes in it 347f7cea56cSDavid Sterba */ 348020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i == 0 ? "" : " "), 349020e5277SAnand Jain btrfs_super_csum_name(i)); 350f7cea56cSDavid Sterba 351f7cea56cSDavid Sterba } 352f7cea56cSDavid Sterba 353020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 354f7cea56cSDavid Sterba return ret; 355f7cea56cSDavid Sterba } 356f7cea56cSDavid Sterba BTRFS_ATTR(static_feature, supported_checksums, supported_checksums_show); 357f7cea56cSDavid Sterba 3587573df55SOmar Sandoval static ssize_t send_stream_version_show(struct kobject *kobj, 3597573df55SOmar Sandoval struct kobj_attribute *ka, char *buf) 3607573df55SOmar Sandoval { 361020e5277SAnand Jain return sysfs_emit(buf, "%d\n", BTRFS_SEND_STREAM_VERSION); 3627573df55SOmar Sandoval } 3637573df55SOmar Sandoval BTRFS_ATTR(static_feature, send_stream_version, send_stream_version_show); 3647573df55SOmar Sandoval 365ceafe3ccSJosef Bacik static const char *rescue_opts[] = { 366ceafe3ccSJosef Bacik "usebackuproot", 367ceafe3ccSJosef Bacik "nologreplay", 36842437a63SJosef Bacik "ignorebadroots", 369882dbe0cSJosef Bacik "ignoredatacsums", 3709037d3cbSJosef Bacik "all", 371ceafe3ccSJosef Bacik }; 372ceafe3ccSJosef Bacik 373ceafe3ccSJosef Bacik static ssize_t supported_rescue_options_show(struct kobject *kobj, 374ceafe3ccSJosef Bacik struct kobj_attribute *a, 375ceafe3ccSJosef Bacik char *buf) 376ceafe3ccSJosef Bacik { 377ceafe3ccSJosef Bacik ssize_t ret = 0; 378ceafe3ccSJosef Bacik int i; 379ceafe3ccSJosef Bacik 380ceafe3ccSJosef Bacik for (i = 0; i < ARRAY_SIZE(rescue_opts); i++) 381020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%s%s", (i ? " " : ""), rescue_opts[i]); 382020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "\n"); 383ceafe3ccSJosef Bacik return ret; 384ceafe3ccSJosef Bacik } 385ceafe3ccSJosef Bacik BTRFS_ATTR(static_feature, supported_rescue_options, 386ceafe3ccSJosef Bacik supported_rescue_options_show); 387ceafe3ccSJosef Bacik 388fc57ad8dSQu Wenruo static ssize_t supported_sectorsizes_show(struct kobject *kobj, 389fc57ad8dSQu Wenruo struct kobj_attribute *a, 390fc57ad8dSQu Wenruo char *buf) 391fc57ad8dSQu Wenruo { 392fc57ad8dSQu Wenruo ssize_t ret = 0; 393fc57ad8dSQu Wenruo 39495ea0486SQu Wenruo /* 4K sector size is also supported with 64K page size */ 39595ea0486SQu Wenruo if (PAGE_SIZE == SZ_64K) 396020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%u ", SZ_4K); 39795ea0486SQu Wenruo 398fc57ad8dSQu Wenruo /* Only sectorsize == PAGE_SIZE is now supported */ 399020e5277SAnand Jain ret += sysfs_emit_at(buf, ret, "%lu\n", PAGE_SIZE); 400fc57ad8dSQu Wenruo 401fc57ad8dSQu Wenruo return ret; 402fc57ad8dSQu Wenruo } 403fc57ad8dSQu Wenruo BTRFS_ATTR(static_feature, supported_sectorsizes, 404fc57ad8dSQu Wenruo supported_sectorsizes_show); 405fc57ad8dSQu Wenruo 406e7849e33SAnand Jain /* 407e7849e33SAnand Jain * Features which only depend on kernel version. 408e7849e33SAnand Jain * 409e7849e33SAnand Jain * These are listed in /sys/fs/btrfs/features along with 410e7849e33SAnand Jain * btrfs_supported_feature_attrs. 411e7849e33SAnand Jain */ 412f902bd3aSMisono Tomohiro static struct attribute *btrfs_supported_static_feature_attrs[] = { 413f902bd3aSMisono Tomohiro BTRFS_ATTR_PTR(static_feature, rmdir_subvol), 414f7cea56cSDavid Sterba BTRFS_ATTR_PTR(static_feature, supported_checksums), 4157573df55SOmar Sandoval BTRFS_ATTR_PTR(static_feature, send_stream_version), 416ceafe3ccSJosef Bacik BTRFS_ATTR_PTR(static_feature, supported_rescue_options), 417fc57ad8dSQu Wenruo BTRFS_ATTR_PTR(static_feature, supported_sectorsizes), 418f902bd3aSMisono Tomohiro NULL 419f902bd3aSMisono Tomohiro }; 420f902bd3aSMisono Tomohiro 421f902bd3aSMisono Tomohiro static const struct attribute_group btrfs_static_feature_attr_group = { 422f902bd3aSMisono Tomohiro .name = "features", 423f902bd3aSMisono Tomohiro .attrs = btrfs_supported_static_feature_attrs, 424f902bd3aSMisono Tomohiro }; 425f902bd3aSMisono Tomohiro 4266e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 4276e369febSDavid Sterba 4286e369febSDavid Sterba /* 429e4faab84SDennis Zhou * Discard statistics and tunables 430e4faab84SDennis Zhou */ 431dfb79ddbSDennis Zhou #define discard_to_fs_info(_kobj) to_fs_info((_kobj)->parent->parent) 432dfb79ddbSDennis Zhou 4335dc7c10bSDennis Zhou static ssize_t btrfs_discardable_bytes_show(struct kobject *kobj, 4345dc7c10bSDennis Zhou struct kobj_attribute *a, 4355dc7c10bSDennis Zhou char *buf) 4365dc7c10bSDennis Zhou { 4375dc7c10bSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4385dc7c10bSDennis Zhou 439020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4405dc7c10bSDennis Zhou atomic64_read(&fs_info->discard_ctl.discardable_bytes)); 4415dc7c10bSDennis Zhou } 4425dc7c10bSDennis Zhou BTRFS_ATTR(discard, discardable_bytes, btrfs_discardable_bytes_show); 4435dc7c10bSDennis Zhou 444dfb79ddbSDennis Zhou static ssize_t btrfs_discardable_extents_show(struct kobject *kobj, 445dfb79ddbSDennis Zhou struct kobj_attribute *a, 446dfb79ddbSDennis Zhou char *buf) 447dfb79ddbSDennis Zhou { 448dfb79ddbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 449dfb79ddbSDennis Zhou 450020e5277SAnand Jain return sysfs_emit(buf, "%d\n", 451dfb79ddbSDennis Zhou atomic_read(&fs_info->discard_ctl.discardable_extents)); 452dfb79ddbSDennis Zhou } 453dfb79ddbSDennis Zhou BTRFS_ATTR(discard, discardable_extents, btrfs_discardable_extents_show); 454dfb79ddbSDennis Zhou 4559ddf648fSDennis Zhou static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj, 4569ddf648fSDennis Zhou struct kobj_attribute *a, 4579ddf648fSDennis Zhou char *buf) 4589ddf648fSDennis Zhou { 4599ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4609ddf648fSDennis Zhou 461020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4629ddf648fSDennis Zhou fs_info->discard_ctl.discard_bitmap_bytes); 4639ddf648fSDennis Zhou } 4649ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bitmap_bytes, btrfs_discard_bitmap_bytes_show); 4659ddf648fSDennis Zhou 4669ddf648fSDennis Zhou static ssize_t btrfs_discard_bytes_saved_show(struct kobject *kobj, 4679ddf648fSDennis Zhou struct kobj_attribute *a, 4689ddf648fSDennis Zhou char *buf) 4699ddf648fSDennis Zhou { 4709ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4719ddf648fSDennis Zhou 472020e5277SAnand Jain return sysfs_emit(buf, "%lld\n", 4739ddf648fSDennis Zhou atomic64_read(&fs_info->discard_ctl.discard_bytes_saved)); 4749ddf648fSDennis Zhou } 4759ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_bytes_saved, btrfs_discard_bytes_saved_show); 4769ddf648fSDennis Zhou 4779ddf648fSDennis Zhou static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj, 4789ddf648fSDennis Zhou struct kobj_attribute *a, 4799ddf648fSDennis Zhou char *buf) 4809ddf648fSDennis Zhou { 4819ddf648fSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 4829ddf648fSDennis Zhou 483020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 4849ddf648fSDennis Zhou fs_info->discard_ctl.discard_extent_bytes); 4859ddf648fSDennis Zhou } 4869ddf648fSDennis Zhou BTRFS_ATTR(discard, discard_extent_bytes, btrfs_discard_extent_bytes_show); 4879ddf648fSDennis Zhou 488a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_show(struct kobject *kobj, 489a2309300SDennis Zhou struct kobj_attribute *a, 490a2309300SDennis Zhou char *buf) 491a2309300SDennis Zhou { 492a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 493a2309300SDennis Zhou 494020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 495a2309300SDennis Zhou READ_ONCE(fs_info->discard_ctl.iops_limit)); 496a2309300SDennis Zhou } 497a2309300SDennis Zhou 498a2309300SDennis Zhou static ssize_t btrfs_discard_iops_limit_store(struct kobject *kobj, 499a2309300SDennis Zhou struct kobj_attribute *a, 500a2309300SDennis Zhou const char *buf, size_t len) 501a2309300SDennis Zhou { 502a2309300SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 503a2309300SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 504a2309300SDennis Zhou u32 iops_limit; 505a2309300SDennis Zhou int ret; 506a2309300SDennis Zhou 507a2309300SDennis Zhou ret = kstrtou32(buf, 10, &iops_limit); 508a2309300SDennis Zhou if (ret) 509a2309300SDennis Zhou return -EINVAL; 510a2309300SDennis Zhou 511a2309300SDennis Zhou WRITE_ONCE(discard_ctl->iops_limit, iops_limit); 5123e48d8d2SPavel Begunkov btrfs_discard_calc_delay(discard_ctl); 5133e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 514a2309300SDennis Zhou return len; 515a2309300SDennis Zhou } 516a2309300SDennis Zhou BTRFS_ATTR_RW(discard, iops_limit, btrfs_discard_iops_limit_show, 517a2309300SDennis Zhou btrfs_discard_iops_limit_store); 518a2309300SDennis Zhou 519e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_show(struct kobject *kobj, 520e93591bbSDennis Zhou struct kobj_attribute *a, 521e93591bbSDennis Zhou char *buf) 522e93591bbSDennis Zhou { 523e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 524e93591bbSDennis Zhou 525020e5277SAnand Jain return sysfs_emit(buf, "%u\n", 526e93591bbSDennis Zhou READ_ONCE(fs_info->discard_ctl.kbps_limit)); 527e93591bbSDennis Zhou } 528e93591bbSDennis Zhou 529e93591bbSDennis Zhou static ssize_t btrfs_discard_kbps_limit_store(struct kobject *kobj, 530e93591bbSDennis Zhou struct kobj_attribute *a, 531e93591bbSDennis Zhou const char *buf, size_t len) 532e93591bbSDennis Zhou { 533e93591bbSDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 534e93591bbSDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 535e93591bbSDennis Zhou u32 kbps_limit; 536e93591bbSDennis Zhou int ret; 537e93591bbSDennis Zhou 538e93591bbSDennis Zhou ret = kstrtou32(buf, 10, &kbps_limit); 539e93591bbSDennis Zhou if (ret) 540e93591bbSDennis Zhou return -EINVAL; 541e93591bbSDennis Zhou 542e93591bbSDennis Zhou WRITE_ONCE(discard_ctl->kbps_limit, kbps_limit); 5433e48d8d2SPavel Begunkov btrfs_discard_schedule_work(discard_ctl, true); 544e93591bbSDennis Zhou return len; 545e93591bbSDennis Zhou } 546e93591bbSDennis Zhou BTRFS_ATTR_RW(discard, kbps_limit, btrfs_discard_kbps_limit_show, 547e93591bbSDennis Zhou btrfs_discard_kbps_limit_store); 548e93591bbSDennis Zhou 54919b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_show(struct kobject *kobj, 55019b2a2c7SDennis Zhou struct kobj_attribute *a, 55119b2a2c7SDennis Zhou char *buf) 55219b2a2c7SDennis Zhou { 55319b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 55419b2a2c7SDennis Zhou 555020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", 55619b2a2c7SDennis Zhou READ_ONCE(fs_info->discard_ctl.max_discard_size)); 55719b2a2c7SDennis Zhou } 55819b2a2c7SDennis Zhou 55919b2a2c7SDennis Zhou static ssize_t btrfs_discard_max_discard_size_store(struct kobject *kobj, 56019b2a2c7SDennis Zhou struct kobj_attribute *a, 56119b2a2c7SDennis Zhou const char *buf, size_t len) 56219b2a2c7SDennis Zhou { 56319b2a2c7SDennis Zhou struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); 56419b2a2c7SDennis Zhou struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; 56519b2a2c7SDennis Zhou u64 max_discard_size; 56619b2a2c7SDennis Zhou int ret; 56719b2a2c7SDennis Zhou 56819b2a2c7SDennis Zhou ret = kstrtou64(buf, 10, &max_discard_size); 56919b2a2c7SDennis Zhou if (ret) 57019b2a2c7SDennis Zhou return -EINVAL; 57119b2a2c7SDennis Zhou 57219b2a2c7SDennis Zhou WRITE_ONCE(discard_ctl->max_discard_size, max_discard_size); 57319b2a2c7SDennis Zhou 57419b2a2c7SDennis Zhou return len; 57519b2a2c7SDennis Zhou } 57619b2a2c7SDennis Zhou BTRFS_ATTR_RW(discard, max_discard_size, btrfs_discard_max_discard_size_show, 57719b2a2c7SDennis Zhou btrfs_discard_max_discard_size_store); 57819b2a2c7SDennis Zhou 579e7849e33SAnand Jain /* 580e7849e33SAnand Jain * Per-filesystem debugging of discard (when mounted with discard=async). 581e7849e33SAnand Jain * 582e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/debug/discard/ 583e7849e33SAnand Jain */ 584e4faab84SDennis Zhou static const struct attribute *discard_debug_attrs[] = { 5855dc7c10bSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_bytes), 586dfb79ddbSDennis Zhou BTRFS_ATTR_PTR(discard, discardable_extents), 5879ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bitmap_bytes), 5889ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_bytes_saved), 5899ddf648fSDennis Zhou BTRFS_ATTR_PTR(discard, discard_extent_bytes), 590a2309300SDennis Zhou BTRFS_ATTR_PTR(discard, iops_limit), 591e93591bbSDennis Zhou BTRFS_ATTR_PTR(discard, kbps_limit), 59219b2a2c7SDennis Zhou BTRFS_ATTR_PTR(discard, max_discard_size), 593e4faab84SDennis Zhou NULL, 594e4faab84SDennis Zhou }; 595e4faab84SDennis Zhou 596e4faab84SDennis Zhou /* 597e7849e33SAnand Jain * Per-filesystem runtime debugging exported via sysfs. 5986e369febSDavid Sterba * 599e7849e33SAnand Jain * Path: /sys/fs/btrfs/UUID/debug/ 6006e369febSDavid Sterba */ 60193945cb4SDennis Zhou static const struct attribute *btrfs_debug_mount_attrs[] = { 60293945cb4SDennis Zhou NULL, 60393945cb4SDennis Zhou }; 60493945cb4SDennis Zhou 605e7849e33SAnand Jain /* 606e7849e33SAnand Jain * Runtime debugging exported via sysfs, applies to all mounted filesystems. 607e7849e33SAnand Jain * 608e7849e33SAnand Jain * Path: /sys/fs/btrfs/debug 609e7849e33SAnand Jain */ 6106e369febSDavid Sterba static struct attribute *btrfs_debug_feature_attrs[] = { 6116e369febSDavid Sterba NULL 6126e369febSDavid Sterba }; 6136e369febSDavid Sterba 6146e369febSDavid Sterba static const struct attribute_group btrfs_debug_feature_attr_group = { 6156e369febSDavid Sterba .name = "debug", 6166e369febSDavid Sterba .attrs = btrfs_debug_feature_attrs, 6176e369febSDavid Sterba }; 6186e369febSDavid Sterba 6196e369febSDavid Sterba #endif 6206e369febSDavid Sterba 6216ab0a202SJeff Mahoney static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf) 6226ab0a202SJeff Mahoney { 6236ab0a202SJeff Mahoney u64 val; 6246ab0a202SJeff Mahoney if (lock) 6256ab0a202SJeff Mahoney spin_lock(lock); 6266ab0a202SJeff Mahoney val = *value_ptr; 6276ab0a202SJeff Mahoney if (lock) 6286ab0a202SJeff Mahoney spin_unlock(lock); 629020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6306ab0a202SJeff Mahoney } 6316ab0a202SJeff Mahoney 6326ab0a202SJeff Mahoney static ssize_t global_rsv_size_show(struct kobject *kobj, 6336ab0a202SJeff Mahoney struct kobj_attribute *ka, char *buf) 6346ab0a202SJeff Mahoney { 6356ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6366ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6376ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf); 6386ab0a202SJeff Mahoney } 639a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_size, global_rsv_size_show); 6406ab0a202SJeff Mahoney 6416ab0a202SJeff Mahoney static ssize_t global_rsv_reserved_show(struct kobject *kobj, 6426ab0a202SJeff Mahoney struct kobj_attribute *a, char *buf) 6436ab0a202SJeff Mahoney { 6446ab0a202SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); 6456ab0a202SJeff Mahoney struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; 6466ab0a202SJeff Mahoney return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf); 6476ab0a202SJeff Mahoney } 648a969f4ccSHans van Kranenburg BTRFS_ATTR(allocation, global_rsv_reserved, global_rsv_reserved_show); 6496ab0a202SJeff Mahoney 6506ab0a202SJeff Mahoney #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj) 651c1895442SJeff Mahoney #define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj) 6526ab0a202SJeff Mahoney 6536ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6546ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf); 655a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, total_bytes, raid_bytes_show); 656a969f4ccSHans van Kranenburg BTRFS_ATTR(raid, used_bytes, raid_bytes_show); 6576ab0a202SJeff Mahoney 6586ab0a202SJeff Mahoney static ssize_t raid_bytes_show(struct kobject *kobj, 6596ab0a202SJeff Mahoney struct kobj_attribute *attr, char *buf) 6606ab0a202SJeff Mahoney 6616ab0a202SJeff Mahoney { 6626ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj->parent); 66332da5386SDavid Sterba struct btrfs_block_group *block_group; 66475cb379dSJeff Mahoney int index = btrfs_bg_flags_to_raid_index(to_raid_kobj(kobj)->flags); 6656ab0a202SJeff Mahoney u64 val = 0; 6666ab0a202SJeff Mahoney 6676ab0a202SJeff Mahoney down_read(&sinfo->groups_sem); 6686ab0a202SJeff Mahoney list_for_each_entry(block_group, &sinfo->block_groups[index], list) { 669a969f4ccSHans van Kranenburg if (&attr->attr == BTRFS_ATTR_PTR(raid, total_bytes)) 670b3470b5dSDavid Sterba val += block_group->length; 6716ab0a202SJeff Mahoney else 672bf38be65SDavid Sterba val += block_group->used; 6736ab0a202SJeff Mahoney } 6746ab0a202SJeff Mahoney up_read(&sinfo->groups_sem); 675020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", val); 6766ab0a202SJeff Mahoney } 6776ab0a202SJeff Mahoney 678e7849e33SAnand Jain /* 679e7849e33SAnand Jain * Allocation information about block group profiles. 680e7849e33SAnand Jain * 681e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/<bg-profile>/ 682e7849e33SAnand Jain */ 6837c7e3014SKimberly Brown static struct attribute *raid_attrs[] = { 684a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, total_bytes), 685a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(raid, used_bytes), 6866ab0a202SJeff Mahoney NULL 6876ab0a202SJeff Mahoney }; 6887c7e3014SKimberly Brown ATTRIBUTE_GROUPS(raid); 6896ab0a202SJeff Mahoney 6906ab0a202SJeff Mahoney static void release_raid_kobj(struct kobject *kobj) 6916ab0a202SJeff Mahoney { 692c1895442SJeff Mahoney kfree(to_raid_kobj(kobj)); 6936ab0a202SJeff Mahoney } 6946ab0a202SJeff Mahoney 695536ea45cSDavid Sterba static struct kobj_type btrfs_raid_ktype = { 6966ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 6976ab0a202SJeff Mahoney .release = release_raid_kobj, 6987c7e3014SKimberly Brown .default_groups = raid_groups, 6996ab0a202SJeff Mahoney }; 7006ab0a202SJeff Mahoney 7016ab0a202SJeff Mahoney #define SPACE_INFO_ATTR(field) \ 7026ab0a202SJeff Mahoney static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \ 7036ab0a202SJeff Mahoney struct kobj_attribute *a, \ 7046ab0a202SJeff Mahoney char *buf) \ 7056ab0a202SJeff Mahoney { \ 7066ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); \ 7076ab0a202SJeff Mahoney return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \ 7086ab0a202SJeff Mahoney } \ 709a969f4ccSHans van Kranenburg BTRFS_ATTR(space_info, field, btrfs_space_info_show_##field) 7106ab0a202SJeff Mahoney 7116ab0a202SJeff Mahoney SPACE_INFO_ATTR(flags); 7126ab0a202SJeff Mahoney SPACE_INFO_ATTR(total_bytes); 7136ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_used); 7146ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_pinned); 7156ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_reserved); 7166ab0a202SJeff Mahoney SPACE_INFO_ATTR(bytes_may_use); 717c1fd5c30SWang Xiaoguang SPACE_INFO_ATTR(bytes_readonly); 718169e0da9SNaohiro Aota SPACE_INFO_ATTR(bytes_zone_unusable); 7196ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_used); 7206ab0a202SJeff Mahoney SPACE_INFO_ATTR(disk_total); 7216ab0a202SJeff Mahoney 722e7849e33SAnand Jain /* 723e7849e33SAnand Jain * Allocation information about block group types. 724e7849e33SAnand Jain * 725e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/<bg-type>/ 726e7849e33SAnand Jain */ 7276ab0a202SJeff Mahoney static struct attribute *space_info_attrs[] = { 728a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, flags), 729a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, total_bytes), 730a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_used), 731a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_pinned), 732a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_reserved), 733a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_may_use), 734a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, bytes_readonly), 735169e0da9SNaohiro Aota BTRFS_ATTR_PTR(space_info, bytes_zone_unusable), 736a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_used), 737a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(space_info, disk_total), 7386ab0a202SJeff Mahoney NULL, 7396ab0a202SJeff Mahoney }; 7407c7e3014SKimberly Brown ATTRIBUTE_GROUPS(space_info); 7416ab0a202SJeff Mahoney 7426ab0a202SJeff Mahoney static void space_info_release(struct kobject *kobj) 7436ab0a202SJeff Mahoney { 7446ab0a202SJeff Mahoney struct btrfs_space_info *sinfo = to_space_info(kobj); 7456ab0a202SJeff Mahoney kfree(sinfo); 7466ab0a202SJeff Mahoney } 7476ab0a202SJeff Mahoney 74827992d01SDavid Sterba static struct kobj_type space_info_ktype = { 7496ab0a202SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 7506ab0a202SJeff Mahoney .release = space_info_release, 7517c7e3014SKimberly Brown .default_groups = space_info_groups, 7526ab0a202SJeff Mahoney }; 7536ab0a202SJeff Mahoney 754e7849e33SAnand Jain /* 755e7849e33SAnand Jain * Allocation information about block groups. 756e7849e33SAnand Jain * 757e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/allocation/ 758e7849e33SAnand Jain */ 7596ab0a202SJeff Mahoney static const struct attribute *allocation_attrs[] = { 760a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_reserved), 761a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(allocation, global_rsv_size), 7626ab0a202SJeff Mahoney NULL, 7636ab0a202SJeff Mahoney }; 7646ab0a202SJeff Mahoney 765f8ba9c11SJeff Mahoney static ssize_t btrfs_label_show(struct kobject *kobj, 766f8ba9c11SJeff Mahoney struct kobj_attribute *a, char *buf) 767f8ba9c11SJeff Mahoney { 768f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 76948fcc3ffSSatoru Takeuchi char *label = fs_info->super_copy->label; 770ee17fc80SDavid Sterba ssize_t ret; 771ee17fc80SDavid Sterba 772ee17fc80SDavid Sterba spin_lock(&fs_info->super_lock); 773020e5277SAnand Jain ret = sysfs_emit(buf, label[0] ? "%s\n" : "%s", label); 774ee17fc80SDavid Sterba spin_unlock(&fs_info->super_lock); 775ee17fc80SDavid Sterba 776ee17fc80SDavid Sterba return ret; 777f8ba9c11SJeff Mahoney } 778f8ba9c11SJeff Mahoney 779f8ba9c11SJeff Mahoney static ssize_t btrfs_label_store(struct kobject *kobj, 780f8ba9c11SJeff Mahoney struct kobj_attribute *a, 781f8ba9c11SJeff Mahoney const char *buf, size_t len) 782f8ba9c11SJeff Mahoney { 783f8ba9c11SJeff Mahoney struct btrfs_fs_info *fs_info = to_fs_info(kobj); 78448fcc3ffSSatoru Takeuchi size_t p_len; 785f8ba9c11SJeff Mahoney 78666ac9fe7SDavid Sterba if (!fs_info) 78766ac9fe7SDavid Sterba return -EPERM; 78866ac9fe7SDavid Sterba 789bc98a42cSDavid Howells if (sb_rdonly(fs_info->sb)) 79079aec2b8SAnand Jain return -EROFS; 79179aec2b8SAnand Jain 79248fcc3ffSSatoru Takeuchi /* 79348fcc3ffSSatoru Takeuchi * p_len is the len until the first occurrence of either 79448fcc3ffSSatoru Takeuchi * '\n' or '\0' 79548fcc3ffSSatoru Takeuchi */ 79648fcc3ffSSatoru Takeuchi p_len = strcspn(buf, "\n"); 79748fcc3ffSSatoru Takeuchi 79848fcc3ffSSatoru Takeuchi if (p_len >= BTRFS_LABEL_SIZE) 799f8ba9c11SJeff Mahoney return -EINVAL; 800f8ba9c11SJeff Mahoney 801a6f69dc8SDavid Sterba spin_lock(&fs_info->super_lock); 80248fcc3ffSSatoru Takeuchi memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE); 80348fcc3ffSSatoru Takeuchi memcpy(fs_info->super_copy->label, buf, p_len); 804a6f69dc8SDavid Sterba spin_unlock(&fs_info->super_lock); 805f8ba9c11SJeff Mahoney 806a6f69dc8SDavid Sterba /* 807a6f69dc8SDavid Sterba * We don't want to do full transaction commit from inside sysfs 808a6f69dc8SDavid Sterba */ 809a6f69dc8SDavid Sterba btrfs_set_pending(fs_info, COMMIT); 810a6f69dc8SDavid Sterba wake_up_process(fs_info->transaction_kthread); 811a6f69dc8SDavid Sterba 812f8ba9c11SJeff Mahoney return len; 813f8ba9c11SJeff Mahoney } 814a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, label, btrfs_label_show, btrfs_label_store); 815f8ba9c11SJeff Mahoney 816df93589aSDavid Sterba static ssize_t btrfs_nodesize_show(struct kobject *kobj, 817df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 818df93589aSDavid Sterba { 819df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 820df93589aSDavid Sterba 821020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->nodesize); 822df93589aSDavid Sterba } 823df93589aSDavid Sterba 824a969f4ccSHans van Kranenburg BTRFS_ATTR(, nodesize, btrfs_nodesize_show); 825df93589aSDavid Sterba 826df93589aSDavid Sterba static ssize_t btrfs_sectorsize_show(struct kobject *kobj, 827df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 828df93589aSDavid Sterba { 829df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 830df93589aSDavid Sterba 831020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 832df93589aSDavid Sterba } 833df93589aSDavid Sterba 834a969f4ccSHans van Kranenburg BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show); 835df93589aSDavid Sterba 836df93589aSDavid Sterba static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, 837df93589aSDavid Sterba struct kobj_attribute *a, char *buf) 838df93589aSDavid Sterba { 839df93589aSDavid Sterba struct btrfs_fs_info *fs_info = to_fs_info(kobj); 840df93589aSDavid Sterba 841020e5277SAnand Jain return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); 842df93589aSDavid Sterba } 843df93589aSDavid Sterba 844a969f4ccSHans van Kranenburg BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show); 845df93589aSDavid Sterba 8462723480aSSargun Dhillon static ssize_t quota_override_show(struct kobject *kobj, 8472723480aSSargun Dhillon struct kobj_attribute *a, char *buf) 8482723480aSSargun Dhillon { 8492723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 8502723480aSSargun Dhillon int quota_override; 8512723480aSSargun Dhillon 8522723480aSSargun Dhillon quota_override = test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 853020e5277SAnand Jain return sysfs_emit(buf, "%d\n", quota_override); 8542723480aSSargun Dhillon } 8552723480aSSargun Dhillon 8562723480aSSargun Dhillon static ssize_t quota_override_store(struct kobject *kobj, 8572723480aSSargun Dhillon struct kobj_attribute *a, 8582723480aSSargun Dhillon const char *buf, size_t len) 8592723480aSSargun Dhillon { 8602723480aSSargun Dhillon struct btrfs_fs_info *fs_info = to_fs_info(kobj); 8612723480aSSargun Dhillon unsigned long knob; 8622723480aSSargun Dhillon int err; 8632723480aSSargun Dhillon 8642723480aSSargun Dhillon if (!fs_info) 8652723480aSSargun Dhillon return -EPERM; 8662723480aSSargun Dhillon 8672723480aSSargun Dhillon if (!capable(CAP_SYS_RESOURCE)) 8682723480aSSargun Dhillon return -EPERM; 8692723480aSSargun Dhillon 8702723480aSSargun Dhillon err = kstrtoul(buf, 10, &knob); 8712723480aSSargun Dhillon if (err) 8722723480aSSargun Dhillon return err; 8732723480aSSargun Dhillon if (knob > 1) 8742723480aSSargun Dhillon return -EINVAL; 8752723480aSSargun Dhillon 8762723480aSSargun Dhillon if (knob) 8772723480aSSargun Dhillon set_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 8782723480aSSargun Dhillon else 8792723480aSSargun Dhillon clear_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); 8802723480aSSargun Dhillon 8812723480aSSargun Dhillon return len; 8822723480aSSargun Dhillon } 8832723480aSSargun Dhillon 884a969f4ccSHans van Kranenburg BTRFS_ATTR_RW(, quota_override, quota_override_show, quota_override_store); 8852723480aSSargun Dhillon 88656f20f40SNikolay Borisov static ssize_t btrfs_metadata_uuid_show(struct kobject *kobj, 88756f20f40SNikolay Borisov struct kobj_attribute *a, char *buf) 88856f20f40SNikolay Borisov { 88956f20f40SNikolay Borisov struct btrfs_fs_info *fs_info = to_fs_info(kobj); 89056f20f40SNikolay Borisov 891020e5277SAnand Jain return sysfs_emit(buf, "%pU\n", fs_info->fs_devices->metadata_uuid); 89256f20f40SNikolay Borisov } 89356f20f40SNikolay Borisov 89456f20f40SNikolay Borisov BTRFS_ATTR(, metadata_uuid, btrfs_metadata_uuid_show); 89556f20f40SNikolay Borisov 89641e6d2a8SJohannes Thumshirn static ssize_t btrfs_checksum_show(struct kobject *kobj, 89741e6d2a8SJohannes Thumshirn struct kobj_attribute *a, char *buf) 89841e6d2a8SJohannes Thumshirn { 89941e6d2a8SJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 90041e6d2a8SJohannes Thumshirn u16 csum_type = btrfs_super_csum_type(fs_info->super_copy); 90141e6d2a8SJohannes Thumshirn 902020e5277SAnand Jain return sysfs_emit(buf, "%s (%s)\n", 90341e6d2a8SJohannes Thumshirn btrfs_super_csum_name(csum_type), 90441e6d2a8SJohannes Thumshirn crypto_shash_driver_name(fs_info->csum_shash)); 90541e6d2a8SJohannes Thumshirn } 90641e6d2a8SJohannes Thumshirn 90741e6d2a8SJohannes Thumshirn BTRFS_ATTR(, checksum, btrfs_checksum_show); 90841e6d2a8SJohannes Thumshirn 90966a2823cSGoldwyn Rodrigues static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj, 91066a2823cSGoldwyn Rodrigues struct kobj_attribute *a, char *buf) 91166a2823cSGoldwyn Rodrigues { 91266a2823cSGoldwyn Rodrigues struct btrfs_fs_info *fs_info = to_fs_info(kobj); 91366a2823cSGoldwyn Rodrigues const char *str; 91466a2823cSGoldwyn Rodrigues 91566a2823cSGoldwyn Rodrigues switch (READ_ONCE(fs_info->exclusive_operation)) { 91666a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_NONE: 91766a2823cSGoldwyn Rodrigues str = "none\n"; 91866a2823cSGoldwyn Rodrigues break; 91966a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_BALANCE: 92066a2823cSGoldwyn Rodrigues str = "balance\n"; 92166a2823cSGoldwyn Rodrigues break; 92266a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_ADD: 92366a2823cSGoldwyn Rodrigues str = "device add\n"; 92466a2823cSGoldwyn Rodrigues break; 92566a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REMOVE: 92666a2823cSGoldwyn Rodrigues str = "device remove\n"; 92766a2823cSGoldwyn Rodrigues break; 92866a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_DEV_REPLACE: 92966a2823cSGoldwyn Rodrigues str = "device replace\n"; 93066a2823cSGoldwyn Rodrigues break; 93166a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_RESIZE: 93266a2823cSGoldwyn Rodrigues str = "resize\n"; 93366a2823cSGoldwyn Rodrigues break; 93466a2823cSGoldwyn Rodrigues case BTRFS_EXCLOP_SWAP_ACTIVATE: 93566a2823cSGoldwyn Rodrigues str = "swap activate\n"; 93666a2823cSGoldwyn Rodrigues break; 93766a2823cSGoldwyn Rodrigues default: 93866a2823cSGoldwyn Rodrigues str = "UNKNOWN\n"; 93966a2823cSGoldwyn Rodrigues break; 94066a2823cSGoldwyn Rodrigues } 941020e5277SAnand Jain return sysfs_emit(buf, "%s", str); 94266a2823cSGoldwyn Rodrigues } 94366a2823cSGoldwyn Rodrigues BTRFS_ATTR(, exclusive_operation, btrfs_exclusive_operation_show); 94466a2823cSGoldwyn Rodrigues 945089c8b05SAnand Jain static ssize_t btrfs_generation_show(struct kobject *kobj, 946089c8b05SAnand Jain struct kobj_attribute *a, char *buf) 947089c8b05SAnand Jain { 948089c8b05SAnand Jain struct btrfs_fs_info *fs_info = to_fs_info(kobj); 949089c8b05SAnand Jain 950020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", fs_info->generation); 951089c8b05SAnand Jain } 952089c8b05SAnand Jain BTRFS_ATTR(, generation, btrfs_generation_show); 953089c8b05SAnand Jain 954aaefed20SAnand Jain /* 955aaefed20SAnand Jain * Look for an exact string @string in @buffer with possible leading or 956aaefed20SAnand Jain * trailing whitespace 957aaefed20SAnand Jain */ 958aaefed20SAnand Jain static bool strmatch(const char *buffer, const char *string) 959aaefed20SAnand Jain { 960aaefed20SAnand Jain const size_t len = strlen(string); 961aaefed20SAnand Jain 962aaefed20SAnand Jain /* Skip leading whitespace */ 963aaefed20SAnand Jain buffer = skip_spaces(buffer); 964aaefed20SAnand Jain 965aaefed20SAnand Jain /* Match entire string, check if the rest is whitespace or empty */ 966aaefed20SAnand Jain if (strncmp(string, buffer, len) == 0 && 967aaefed20SAnand Jain strlen(skip_spaces(buffer + len)) == 0) 968aaefed20SAnand Jain return true; 969aaefed20SAnand Jain 970aaefed20SAnand Jain return false; 971aaefed20SAnand Jain } 972aaefed20SAnand Jain 9733d8cc17aSAnand Jain static const char * const btrfs_read_policy_name[] = { "pid" }; 9743d8cc17aSAnand Jain 9753d8cc17aSAnand Jain static ssize_t btrfs_read_policy_show(struct kobject *kobj, 9763d8cc17aSAnand Jain struct kobj_attribute *a, char *buf) 9773d8cc17aSAnand Jain { 9783d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 9793d8cc17aSAnand Jain ssize_t ret = 0; 9803d8cc17aSAnand Jain int i; 9813d8cc17aSAnand Jain 9823d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 9833d8cc17aSAnand Jain if (fs_devices->read_policy == i) 9843d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s[%s]", 9853d8cc17aSAnand Jain (ret == 0 ? "" : " "), 9863d8cc17aSAnand Jain btrfs_read_policy_name[i]); 9873d8cc17aSAnand Jain else 9883d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s", 9893d8cc17aSAnand Jain (ret == 0 ? "" : " "), 9903d8cc17aSAnand Jain btrfs_read_policy_name[i]); 9913d8cc17aSAnand Jain } 9923d8cc17aSAnand Jain 9933d8cc17aSAnand Jain ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); 9943d8cc17aSAnand Jain 9953d8cc17aSAnand Jain return ret; 9963d8cc17aSAnand Jain } 9973d8cc17aSAnand Jain 9983d8cc17aSAnand Jain static ssize_t btrfs_read_policy_store(struct kobject *kobj, 9993d8cc17aSAnand Jain struct kobj_attribute *a, 10003d8cc17aSAnand Jain const char *buf, size_t len) 10013d8cc17aSAnand Jain { 10023d8cc17aSAnand Jain struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); 10033d8cc17aSAnand Jain int i; 10043d8cc17aSAnand Jain 10053d8cc17aSAnand Jain for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { 10063d8cc17aSAnand Jain if (strmatch(buf, btrfs_read_policy_name[i])) { 10073d8cc17aSAnand Jain if (i != fs_devices->read_policy) { 10083d8cc17aSAnand Jain fs_devices->read_policy = i; 10093d8cc17aSAnand Jain btrfs_info(fs_devices->fs_info, 10103d8cc17aSAnand Jain "read policy set to '%s'", 10113d8cc17aSAnand Jain btrfs_read_policy_name[i]); 10123d8cc17aSAnand Jain } 10133d8cc17aSAnand Jain return len; 10143d8cc17aSAnand Jain } 10153d8cc17aSAnand Jain } 10163d8cc17aSAnand Jain 10173d8cc17aSAnand Jain return -EINVAL; 10183d8cc17aSAnand Jain } 10193d8cc17aSAnand Jain BTRFS_ATTR_RW(, read_policy, btrfs_read_policy_show, btrfs_read_policy_store); 10203d8cc17aSAnand Jain 102118bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_show(struct kobject *kobj, 102218bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 102318bb8bbfSJohannes Thumshirn char *buf) 102418bb8bbfSJohannes Thumshirn { 102518bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 102618bb8bbfSJohannes Thumshirn ssize_t ret; 102718bb8bbfSJohannes Thumshirn 1028020e5277SAnand Jain ret = sysfs_emit(buf, "%d\n", READ_ONCE(fs_info->bg_reclaim_threshold)); 102918bb8bbfSJohannes Thumshirn 103018bb8bbfSJohannes Thumshirn return ret; 103118bb8bbfSJohannes Thumshirn } 103218bb8bbfSJohannes Thumshirn 103318bb8bbfSJohannes Thumshirn static ssize_t btrfs_bg_reclaim_threshold_store(struct kobject *kobj, 103418bb8bbfSJohannes Thumshirn struct kobj_attribute *a, 103518bb8bbfSJohannes Thumshirn const char *buf, size_t len) 103618bb8bbfSJohannes Thumshirn { 103718bb8bbfSJohannes Thumshirn struct btrfs_fs_info *fs_info = to_fs_info(kobj); 103818bb8bbfSJohannes Thumshirn int thresh; 103918bb8bbfSJohannes Thumshirn int ret; 104018bb8bbfSJohannes Thumshirn 104118bb8bbfSJohannes Thumshirn ret = kstrtoint(buf, 10, &thresh); 104218bb8bbfSJohannes Thumshirn if (ret) 104318bb8bbfSJohannes Thumshirn return ret; 104418bb8bbfSJohannes Thumshirn 104577233c2dSJohannes Thumshirn if (thresh != 0 && (thresh <= 50 || thresh > 100)) 104618bb8bbfSJohannes Thumshirn return -EINVAL; 104718bb8bbfSJohannes Thumshirn 104877233c2dSJohannes Thumshirn WRITE_ONCE(fs_info->bg_reclaim_threshold, thresh); 104918bb8bbfSJohannes Thumshirn 105018bb8bbfSJohannes Thumshirn return len; 105118bb8bbfSJohannes Thumshirn } 105218bb8bbfSJohannes Thumshirn BTRFS_ATTR_RW(, bg_reclaim_threshold, btrfs_bg_reclaim_threshold_show, 105318bb8bbfSJohannes Thumshirn btrfs_bg_reclaim_threshold_store); 105418bb8bbfSJohannes Thumshirn 1055e7849e33SAnand Jain /* 1056e7849e33SAnand Jain * Per-filesystem information and stats. 1057e7849e33SAnand Jain * 1058e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/ 1059e7849e33SAnand Jain */ 10600dd2906fSAnand Jain static const struct attribute *btrfs_attrs[] = { 1061a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, label), 1062a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, nodesize), 1063a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, sectorsize), 1064a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, clone_alignment), 1065a969f4ccSHans van Kranenburg BTRFS_ATTR_PTR(, quota_override), 106656f20f40SNikolay Borisov BTRFS_ATTR_PTR(, metadata_uuid), 106741e6d2a8SJohannes Thumshirn BTRFS_ATTR_PTR(, checksum), 106866a2823cSGoldwyn Rodrigues BTRFS_ATTR_PTR(, exclusive_operation), 1069089c8b05SAnand Jain BTRFS_ATTR_PTR(, generation), 10703d8cc17aSAnand Jain BTRFS_ATTR_PTR(, read_policy), 107118bb8bbfSJohannes Thumshirn BTRFS_ATTR_PTR(, bg_reclaim_threshold), 1072f8ba9c11SJeff Mahoney NULL, 1073f8ba9c11SJeff Mahoney }; 1074f8ba9c11SJeff Mahoney 1075c1b7e474SAnand Jain static void btrfs_release_fsid_kobj(struct kobject *kobj) 1076510d7360SJeff Mahoney { 10772e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj); 1078248d200dSAnand Jain 1079c1b7e474SAnand Jain memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject)); 10802e7910d6SAnand Jain complete(&fs_devs->kobj_unregister); 1081510d7360SJeff Mahoney } 1082510d7360SJeff Mahoney 1083510d7360SJeff Mahoney static struct kobj_type btrfs_ktype = { 1084510d7360SJeff Mahoney .sysfs_ops = &kobj_sysfs_ops, 1085c1b7e474SAnand Jain .release = btrfs_release_fsid_kobj, 1086510d7360SJeff Mahoney }; 1087510d7360SJeff Mahoney 10882e7910d6SAnand Jain static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj) 10892e7910d6SAnand Jain { 10902e7910d6SAnand Jain if (kobj->ktype != &btrfs_ktype) 10912e7910d6SAnand Jain return NULL; 1092c1b7e474SAnand Jain return container_of(kobj, struct btrfs_fs_devices, fsid_kobj); 10932e7910d6SAnand Jain } 10942e7910d6SAnand Jain 1095510d7360SJeff Mahoney static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj) 1096510d7360SJeff Mahoney { 1097510d7360SJeff Mahoney if (kobj->ktype != &btrfs_ktype) 1098510d7360SJeff Mahoney return NULL; 10992e7910d6SAnand Jain return to_fs_devs(kobj)->fs_info; 1100510d7360SJeff Mahoney } 110158176a96SJosef Bacik 1102e453d989SJeff Mahoney #define NUM_FEATURE_BITS 64 11036c52157fSTomohiro Misono #define BTRFS_FEATURE_NAME_MAX 13 11046c52157fSTomohiro Misono static char btrfs_unknown_feature_names[FEAT_MAX][NUM_FEATURE_BITS][BTRFS_FEATURE_NAME_MAX]; 11056c52157fSTomohiro Misono static struct btrfs_feature_attr btrfs_feature_attrs[FEAT_MAX][NUM_FEATURE_BITS]; 1106e453d989SJeff Mahoney 11076c52157fSTomohiro Misono static const u64 supported_feature_masks[FEAT_MAX] = { 1108e453d989SJeff Mahoney [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP, 1109e453d989SJeff Mahoney [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP, 1110e453d989SJeff Mahoney [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP, 1111e453d989SJeff Mahoney }; 1112e453d989SJeff Mahoney 1113e453d989SJeff Mahoney static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add) 11145ac1d209SJeff Mahoney { 1115e453d989SJeff Mahoney int set; 1116e453d989SJeff Mahoney 1117e453d989SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 1118e453d989SJeff Mahoney int i; 1119e453d989SJeff Mahoney struct attribute *attrs[2]; 1120e453d989SJeff Mahoney struct attribute_group agroup = { 1121e453d989SJeff Mahoney .name = "features", 1122e453d989SJeff Mahoney .attrs = attrs, 1123e453d989SJeff Mahoney }; 1124e453d989SJeff Mahoney u64 features = get_features(fs_info, set); 1125e453d989SJeff Mahoney features &= ~supported_feature_masks[set]; 1126e453d989SJeff Mahoney 1127e453d989SJeff Mahoney if (!features) 1128e453d989SJeff Mahoney continue; 1129e453d989SJeff Mahoney 1130e453d989SJeff Mahoney attrs[1] = NULL; 1131e453d989SJeff Mahoney for (i = 0; i < NUM_FEATURE_BITS; i++) { 1132e453d989SJeff Mahoney struct btrfs_feature_attr *fa; 1133e453d989SJeff Mahoney 1134e453d989SJeff Mahoney if (!(features & (1ULL << i))) 1135e453d989SJeff Mahoney continue; 1136e453d989SJeff Mahoney 1137e453d989SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 1138e453d989SJeff Mahoney attrs[0] = &fa->kobj_attr.attr; 1139e453d989SJeff Mahoney if (add) { 1140e453d989SJeff Mahoney int ret; 1141c1b7e474SAnand Jain ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj, 1142e453d989SJeff Mahoney &agroup); 1143e453d989SJeff Mahoney if (ret) 1144e453d989SJeff Mahoney return ret; 1145e453d989SJeff Mahoney } else 1146c1b7e474SAnand Jain sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj, 1147e453d989SJeff Mahoney &agroup); 1148e453d989SJeff Mahoney } 1149e453d989SJeff Mahoney 1150e453d989SJeff Mahoney } 1151e453d989SJeff Mahoney return 0; 1152e453d989SJeff Mahoney } 1153e453d989SJeff Mahoney 11542e3e1281SAnand Jain static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 1155e453d989SJeff Mahoney { 1156a013d141SAnand Jain if (fs_devs->devinfo_kobj) { 1157a013d141SAnand Jain kobject_del(fs_devs->devinfo_kobj); 1158a013d141SAnand Jain kobject_put(fs_devs->devinfo_kobj); 1159a013d141SAnand Jain fs_devs->devinfo_kobj = NULL; 1160a013d141SAnand Jain } 1161a013d141SAnand Jain 1162b5501504SAnand Jain if (fs_devs->devices_kobj) { 1163b5501504SAnand Jain kobject_del(fs_devs->devices_kobj); 1164b5501504SAnand Jain kobject_put(fs_devs->devices_kobj); 1165b5501504SAnand Jain fs_devs->devices_kobj = NULL; 1166aaf13305SAnand Jain } 1167aaf13305SAnand Jain 1168c1b7e474SAnand Jain if (fs_devs->fsid_kobj.state_initialized) { 1169c1b7e474SAnand Jain kobject_del(&fs_devs->fsid_kobj); 1170c1b7e474SAnand Jain kobject_put(&fs_devs->fsid_kobj); 11712e7910d6SAnand Jain wait_for_completion(&fs_devs->kobj_unregister); 11725ac1d209SJeff Mahoney } 1173f90fc547SAnand Jain } 11745ac1d209SJeff Mahoney 11752e3e1281SAnand Jain /* when fs_devs is NULL it will remove all fsid kobject */ 11761d1c1be3SAnand Jain void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) 11772e3e1281SAnand Jain { 11782e3e1281SAnand Jain struct list_head *fs_uuids = btrfs_get_fs_uuids(); 11792e3e1281SAnand Jain 11802e3e1281SAnand Jain if (fs_devs) { 11812e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 11822e3e1281SAnand Jain return; 11832e3e1281SAnand Jain } 11842e3e1281SAnand Jain 1185c4babc5eSAnand Jain list_for_each_entry(fs_devs, fs_uuids, fs_list) { 11862e3e1281SAnand Jain __btrfs_sysfs_remove_fsid(fs_devs); 11872e3e1281SAnand Jain } 11882e3e1281SAnand Jain } 11892e3e1281SAnand Jain 119053f8a74cSAnand Jain static void btrfs_sysfs_remove_fs_devices(struct btrfs_fs_devices *fs_devices) 119153f8a74cSAnand Jain { 119253f8a74cSAnand Jain struct btrfs_device *device; 119330b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 119453f8a74cSAnand Jain 119553f8a74cSAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) 119653f8a74cSAnand Jain btrfs_sysfs_remove_device(device); 119730b0e4e0SAnand Jain 119830b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 119930b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) 120030b0e4e0SAnand Jain btrfs_sysfs_remove_device(device); 120130b0e4e0SAnand Jain } 120253f8a74cSAnand Jain } 120353f8a74cSAnand Jain 12046618a59bSAnand Jain void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info) 1205e453d989SJeff Mahoney { 12063092c68fSNikolay Borisov struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 12073092c68fSNikolay Borisov 12083092c68fSNikolay Borisov sysfs_remove_link(fsid_kobj, "bdi"); 12093092c68fSNikolay Borisov 1210e453d989SJeff Mahoney if (fs_info->space_info_kobj) { 1211e453d989SJeff Mahoney sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); 1212e453d989SJeff Mahoney kobject_del(fs_info->space_info_kobj); 1213e453d989SJeff Mahoney kobject_put(fs_info->space_info_kobj); 1214e453d989SJeff Mahoney } 121571e8978eSDennis Zhou #ifdef CONFIG_BTRFS_DEBUG 1216e4faab84SDennis Zhou if (fs_info->discard_debug_kobj) { 1217e4faab84SDennis Zhou sysfs_remove_files(fs_info->discard_debug_kobj, 1218e4faab84SDennis Zhou discard_debug_attrs); 1219e4faab84SDennis Zhou kobject_del(fs_info->discard_debug_kobj); 1220e4faab84SDennis Zhou kobject_put(fs_info->discard_debug_kobj); 1221e4faab84SDennis Zhou } 122293945cb4SDennis Zhou if (fs_info->debug_kobj) { 122393945cb4SDennis Zhou sysfs_remove_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 122493945cb4SDennis Zhou kobject_del(fs_info->debug_kobj); 122593945cb4SDennis Zhou kobject_put(fs_info->debug_kobj); 122693945cb4SDennis Zhou } 122771e8978eSDennis Zhou #endif 1228e453d989SJeff Mahoney addrm_unknown_feature_attrs(fs_info, false); 12293092c68fSNikolay Borisov sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 12303092c68fSNikolay Borisov sysfs_remove_files(fsid_kobj, btrfs_attrs); 123153f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_info->fs_devices); 1232e453d989SJeff Mahoney } 1233e453d989SJeff Mahoney 1234f10152bcSDavid Sterba static const char * const btrfs_feature_set_names[FEAT_MAX] = { 123579da4fa4SJeff Mahoney [FEAT_COMPAT] = "compat", 123679da4fa4SJeff Mahoney [FEAT_COMPAT_RO] = "compat_ro", 123779da4fa4SJeff Mahoney [FEAT_INCOMPAT] = "incompat", 123879da4fa4SJeff Mahoney }; 123979da4fa4SJeff Mahoney 12409e6df7ceSDavid Sterba const char *btrfs_feature_set_name(enum btrfs_feature_set set) 1241f10152bcSDavid Sterba { 1242f10152bcSDavid Sterba return btrfs_feature_set_names[set]; 1243f10152bcSDavid Sterba } 1244f10152bcSDavid Sterba 12453b02a68aSJeff Mahoney char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) 12463b02a68aSJeff Mahoney { 12473b02a68aSJeff Mahoney size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */ 12483b02a68aSJeff Mahoney int len = 0; 12493b02a68aSJeff Mahoney int i; 12503b02a68aSJeff Mahoney char *str; 12513b02a68aSJeff Mahoney 12523b02a68aSJeff Mahoney str = kmalloc(bufsize, GFP_KERNEL); 12533b02a68aSJeff Mahoney if (!str) 12543b02a68aSJeff Mahoney return str; 12553b02a68aSJeff Mahoney 12563b02a68aSJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 12573b02a68aSJeff Mahoney const char *name; 12583b02a68aSJeff Mahoney 12593b02a68aSJeff Mahoney if (!(flags & (1ULL << i))) 12603b02a68aSJeff Mahoney continue; 12613b02a68aSJeff Mahoney 12623b02a68aSJeff Mahoney name = btrfs_feature_attrs[set][i].kobj_attr.attr.name; 1263abdd9febSTakashi Iwai len += scnprintf(str + len, bufsize - len, "%s%s", 12643b02a68aSJeff Mahoney len ? "," : "", name); 12653b02a68aSJeff Mahoney } 12663b02a68aSJeff Mahoney 12673b02a68aSJeff Mahoney return str; 12683b02a68aSJeff Mahoney } 12693b02a68aSJeff Mahoney 127079da4fa4SJeff Mahoney static void init_feature_attrs(void) 127179da4fa4SJeff Mahoney { 127279da4fa4SJeff Mahoney struct btrfs_feature_attr *fa; 127379da4fa4SJeff Mahoney int set, i; 127479da4fa4SJeff Mahoney 127579da4fa4SJeff Mahoney BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names) != 127679da4fa4SJeff Mahoney ARRAY_SIZE(btrfs_feature_attrs)); 127779da4fa4SJeff Mahoney BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names[0]) != 127879da4fa4SJeff Mahoney ARRAY_SIZE(btrfs_feature_attrs[0])); 127979da4fa4SJeff Mahoney 12803b02a68aSJeff Mahoney memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs)); 12813b02a68aSJeff Mahoney memset(btrfs_unknown_feature_names, 0, 12823b02a68aSJeff Mahoney sizeof(btrfs_unknown_feature_names)); 12833b02a68aSJeff Mahoney 128479da4fa4SJeff Mahoney for (i = 0; btrfs_supported_feature_attrs[i]; i++) { 128579da4fa4SJeff Mahoney struct btrfs_feature_attr *sfa; 128679da4fa4SJeff Mahoney struct attribute *a = btrfs_supported_feature_attrs[i]; 12873b02a68aSJeff Mahoney int bit; 128879da4fa4SJeff Mahoney sfa = attr_to_btrfs_feature_attr(a); 12893b02a68aSJeff Mahoney bit = ilog2(sfa->feature_bit); 12903b02a68aSJeff Mahoney fa = &btrfs_feature_attrs[sfa->feature_set][bit]; 129179da4fa4SJeff Mahoney 129279da4fa4SJeff Mahoney fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name; 129379da4fa4SJeff Mahoney } 129479da4fa4SJeff Mahoney 129579da4fa4SJeff Mahoney for (set = 0; set < FEAT_MAX; set++) { 129679da4fa4SJeff Mahoney for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { 129779da4fa4SJeff Mahoney char *name = btrfs_unknown_feature_names[set][i]; 129879da4fa4SJeff Mahoney fa = &btrfs_feature_attrs[set][i]; 129979da4fa4SJeff Mahoney 130079da4fa4SJeff Mahoney if (fa->kobj_attr.attr.name) 130179da4fa4SJeff Mahoney continue; 130279da4fa4SJeff Mahoney 13036c52157fSTomohiro Misono snprintf(name, BTRFS_FEATURE_NAME_MAX, "%s:%u", 130479da4fa4SJeff Mahoney btrfs_feature_set_names[set], i); 130579da4fa4SJeff Mahoney 130679da4fa4SJeff Mahoney fa->kobj_attr.attr.name = name; 130779da4fa4SJeff Mahoney fa->kobj_attr.attr.mode = S_IRUGO; 130879da4fa4SJeff Mahoney fa->feature_set = set; 130979da4fa4SJeff Mahoney fa->feature_bit = 1ULL << i; 131079da4fa4SJeff Mahoney } 131179da4fa4SJeff Mahoney } 131279da4fa4SJeff Mahoney } 131379da4fa4SJeff Mahoney 131432a9991fSDavid Sterba /* 131532a9991fSDavid Sterba * Create a sysfs entry for a given block group type at path 131632a9991fSDavid Sterba * /sys/fs/btrfs/UUID/allocation/data/TYPE 131732a9991fSDavid Sterba */ 131832da5386SDavid Sterba void btrfs_sysfs_add_block_group_type(struct btrfs_block_group *cache) 131932a9991fSDavid Sterba { 132032a9991fSDavid Sterba struct btrfs_fs_info *fs_info = cache->fs_info; 132132a9991fSDavid Sterba struct btrfs_space_info *space_info = cache->space_info; 132232a9991fSDavid Sterba struct raid_kobject *rkobj; 132332a9991fSDavid Sterba const int index = btrfs_bg_flags_to_raid_index(cache->flags); 132432a9991fSDavid Sterba unsigned int nofs_flag; 132532a9991fSDavid Sterba int ret; 132632a9991fSDavid Sterba 132732a9991fSDavid Sterba /* 132832a9991fSDavid Sterba * Setup a NOFS context because kobject_add(), deep in its call chain, 132932a9991fSDavid Sterba * does GFP_KERNEL allocations, and we are often called in a context 133032a9991fSDavid Sterba * where if reclaim is triggered we can deadlock (we are either holding 133132a9991fSDavid Sterba * a transaction handle or some lock required for a transaction 133232a9991fSDavid Sterba * commit). 133332a9991fSDavid Sterba */ 133432a9991fSDavid Sterba nofs_flag = memalloc_nofs_save(); 133532a9991fSDavid Sterba 133632a9991fSDavid Sterba rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS); 133732a9991fSDavid Sterba if (!rkobj) { 133832a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 133932a9991fSDavid Sterba btrfs_warn(cache->fs_info, 134032a9991fSDavid Sterba "couldn't alloc memory for raid level kobject"); 134132a9991fSDavid Sterba return; 134232a9991fSDavid Sterba } 134332a9991fSDavid Sterba 134432a9991fSDavid Sterba rkobj->flags = cache->flags; 134532a9991fSDavid Sterba kobject_init(&rkobj->kobj, &btrfs_raid_ktype); 134649ea112dSJosef Bacik 134749ea112dSJosef Bacik /* 134849ea112dSJosef Bacik * We call this either on mount, or if we've created a block group for a 134949ea112dSJosef Bacik * new index type while running (i.e. when restriping). The running 135049ea112dSJosef Bacik * case is tricky because we could race with other threads, so we need 135149ea112dSJosef Bacik * to have this check to make sure we didn't already init the kobject. 135249ea112dSJosef Bacik * 135349ea112dSJosef Bacik * We don't have to protect on the free side because it only happens on 135449ea112dSJosef Bacik * unmount. 135549ea112dSJosef Bacik */ 135649ea112dSJosef Bacik spin_lock(&space_info->lock); 135749ea112dSJosef Bacik if (space_info->block_group_kobjs[index]) { 135849ea112dSJosef Bacik spin_unlock(&space_info->lock); 135949ea112dSJosef Bacik kobject_put(&rkobj->kobj); 136049ea112dSJosef Bacik return; 136149ea112dSJosef Bacik } else { 136249ea112dSJosef Bacik space_info->block_group_kobjs[index] = &rkobj->kobj; 136349ea112dSJosef Bacik } 136449ea112dSJosef Bacik spin_unlock(&space_info->lock); 136549ea112dSJosef Bacik 136632a9991fSDavid Sterba ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s", 136732a9991fSDavid Sterba btrfs_bg_type_to_raid_name(rkobj->flags)); 136832a9991fSDavid Sterba memalloc_nofs_restore(nofs_flag); 136932a9991fSDavid Sterba if (ret) { 137049ea112dSJosef Bacik spin_lock(&space_info->lock); 137149ea112dSJosef Bacik space_info->block_group_kobjs[index] = NULL; 137249ea112dSJosef Bacik spin_unlock(&space_info->lock); 137332a9991fSDavid Sterba kobject_put(&rkobj->kobj); 137432a9991fSDavid Sterba btrfs_warn(fs_info, 137532a9991fSDavid Sterba "failed to add kobject for block cache, ignoring"); 137632a9991fSDavid Sterba return; 137732a9991fSDavid Sterba } 137832a9991fSDavid Sterba } 137932a9991fSDavid Sterba 1380b5865babSDavid Sterba /* 1381b5865babSDavid Sterba * Remove sysfs directories for all block group types of a given space info and 1382b5865babSDavid Sterba * the space info as well 1383b5865babSDavid Sterba */ 1384b5865babSDavid Sterba void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info) 1385b5865babSDavid Sterba { 1386b5865babSDavid Sterba int i; 1387b5865babSDavid Sterba 1388b5865babSDavid Sterba for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { 1389b5865babSDavid Sterba struct kobject *kobj; 1390b5865babSDavid Sterba 1391b5865babSDavid Sterba kobj = space_info->block_group_kobjs[i]; 1392b5865babSDavid Sterba space_info->block_group_kobjs[i] = NULL; 1393b5865babSDavid Sterba if (kobj) { 1394b5865babSDavid Sterba kobject_del(kobj); 1395b5865babSDavid Sterba kobject_put(kobj); 1396b5865babSDavid Sterba } 1397b5865babSDavid Sterba } 1398b5865babSDavid Sterba kobject_del(&space_info->kobj); 1399b5865babSDavid Sterba kobject_put(&space_info->kobj); 1400b5865babSDavid Sterba } 1401b5865babSDavid Sterba 1402b882327aSDavid Sterba static const char *alloc_name(u64 flags) 1403b882327aSDavid Sterba { 1404b882327aSDavid Sterba switch (flags) { 1405b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA: 1406b882327aSDavid Sterba return "mixed"; 1407b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_METADATA: 1408b882327aSDavid Sterba return "metadata"; 1409b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_DATA: 1410b882327aSDavid Sterba return "data"; 1411b882327aSDavid Sterba case BTRFS_BLOCK_GROUP_SYSTEM: 1412b882327aSDavid Sterba return "system"; 1413b882327aSDavid Sterba default: 1414b882327aSDavid Sterba WARN_ON(1); 1415b882327aSDavid Sterba return "invalid-combination"; 1416445d8ab5STom Rix } 1417b882327aSDavid Sterba } 1418b882327aSDavid Sterba 1419b882327aSDavid Sterba /* 1420b882327aSDavid Sterba * Create a sysfs entry for a space info type at path 1421b882327aSDavid Sterba * /sys/fs/btrfs/UUID/allocation/TYPE 1422b882327aSDavid Sterba */ 1423b882327aSDavid Sterba int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info, 1424b882327aSDavid Sterba struct btrfs_space_info *space_info) 1425b882327aSDavid Sterba { 1426b882327aSDavid Sterba int ret; 1427b882327aSDavid Sterba 1428b882327aSDavid Sterba ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, 1429b882327aSDavid Sterba fs_info->space_info_kobj, "%s", 1430b882327aSDavid Sterba alloc_name(space_info->flags)); 1431b882327aSDavid Sterba if (ret) { 1432b882327aSDavid Sterba kobject_put(&space_info->kobj); 1433b882327aSDavid Sterba return ret; 1434b882327aSDavid Sterba } 1435b882327aSDavid Sterba 1436b882327aSDavid Sterba return 0; 1437b882327aSDavid Sterba } 1438b882327aSDavid Sterba 143953f8a74cSAnand Jain void btrfs_sysfs_remove_device(struct btrfs_device *device) 144099994cdeSAnand Jain { 1441985e233eSAnand Jain struct kobject *devices_kobj; 144299994cdeSAnand Jain 1443985e233eSAnand Jain /* 1444985e233eSAnand Jain * Seed fs_devices devices_kobj aren't used, fetch kobject from the 1445985e233eSAnand Jain * fs_info::fs_devices. 1446985e233eSAnand Jain */ 1447985e233eSAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1448985e233eSAnand Jain ASSERT(devices_kobj); 144999994cdeSAnand Jain 14508d65269fSChristoph Hellwig if (device->bdev) 14518d65269fSChristoph Hellwig sysfs_remove_link(devices_kobj, bdev_kobj(device->bdev)->name); 145299994cdeSAnand Jain 1453985e233eSAnand Jain if (device->devid_kobj.state_initialized) { 1454985e233eSAnand Jain kobject_del(&device->devid_kobj); 1455985e233eSAnand Jain kobject_put(&device->devid_kobj); 1456985e233eSAnand Jain wait_for_completion(&device->kobj_unregister); 1457985e233eSAnand Jain } 1458b5ddcffaSAnand Jain } 1459668e48afSAnand Jain 1460668e48afSAnand Jain static ssize_t btrfs_devinfo_in_fs_metadata_show(struct kobject *kobj, 1461668e48afSAnand Jain struct kobj_attribute *a, 1462668e48afSAnand Jain char *buf) 1463668e48afSAnand Jain { 1464668e48afSAnand Jain int val; 1465668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1466668e48afSAnand Jain devid_kobj); 1467668e48afSAnand Jain 1468668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state); 1469668e48afSAnand Jain 1470020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1471668e48afSAnand Jain } 1472668e48afSAnand Jain BTRFS_ATTR(devid, in_fs_metadata, btrfs_devinfo_in_fs_metadata_show); 1473668e48afSAnand Jain 147425864778SAnand Jain static ssize_t btrfs_devinfo_missing_show(struct kobject *kobj, 1475668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1476668e48afSAnand Jain { 1477668e48afSAnand Jain int val; 1478668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1479668e48afSAnand Jain devid_kobj); 1480668e48afSAnand Jain 1481668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state); 1482668e48afSAnand Jain 1483020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1484668e48afSAnand Jain } 148525864778SAnand Jain BTRFS_ATTR(devid, missing, btrfs_devinfo_missing_show); 1486668e48afSAnand Jain 1487668e48afSAnand Jain static ssize_t btrfs_devinfo_replace_target_show(struct kobject *kobj, 1488668e48afSAnand Jain struct kobj_attribute *a, 1489668e48afSAnand Jain char *buf) 1490668e48afSAnand Jain { 1491668e48afSAnand Jain int val; 1492668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1493668e48afSAnand Jain devid_kobj); 1494668e48afSAnand Jain 1495668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state); 1496668e48afSAnand Jain 1497020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1498668e48afSAnand Jain } 1499668e48afSAnand Jain BTRFS_ATTR(devid, replace_target, btrfs_devinfo_replace_target_show); 1500668e48afSAnand Jain 1501eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_show(struct kobject *kobj, 1502eb3b5053SDavid Sterba struct kobj_attribute *a, 1503eb3b5053SDavid Sterba char *buf) 1504eb3b5053SDavid Sterba { 1505eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1506eb3b5053SDavid Sterba devid_kobj); 1507eb3b5053SDavid Sterba 1508020e5277SAnand Jain return sysfs_emit(buf, "%llu\n", READ_ONCE(device->scrub_speed_max)); 1509eb3b5053SDavid Sterba } 1510eb3b5053SDavid Sterba 1511eb3b5053SDavid Sterba static ssize_t btrfs_devinfo_scrub_speed_max_store(struct kobject *kobj, 1512eb3b5053SDavid Sterba struct kobj_attribute *a, 1513eb3b5053SDavid Sterba const char *buf, size_t len) 1514eb3b5053SDavid Sterba { 1515eb3b5053SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1516eb3b5053SDavid Sterba devid_kobj); 1517eb3b5053SDavid Sterba char *endptr; 1518eb3b5053SDavid Sterba unsigned long long limit; 1519eb3b5053SDavid Sterba 1520eb3b5053SDavid Sterba limit = memparse(buf, &endptr); 1521eb3b5053SDavid Sterba WRITE_ONCE(device->scrub_speed_max, limit); 1522eb3b5053SDavid Sterba return len; 1523eb3b5053SDavid Sterba } 1524eb3b5053SDavid Sterba BTRFS_ATTR_RW(devid, scrub_speed_max, btrfs_devinfo_scrub_speed_max_show, 1525eb3b5053SDavid Sterba btrfs_devinfo_scrub_speed_max_store); 1526eb3b5053SDavid Sterba 1527668e48afSAnand Jain static ssize_t btrfs_devinfo_writeable_show(struct kobject *kobj, 1528668e48afSAnand Jain struct kobj_attribute *a, char *buf) 1529668e48afSAnand Jain { 1530668e48afSAnand Jain int val; 1531668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1532668e48afSAnand Jain devid_kobj); 1533668e48afSAnand Jain 1534668e48afSAnand Jain val = !!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state); 1535668e48afSAnand Jain 1536020e5277SAnand Jain return sysfs_emit(buf, "%d\n", val); 1537668e48afSAnand Jain } 1538668e48afSAnand Jain BTRFS_ATTR(devid, writeable, btrfs_devinfo_writeable_show); 1539668e48afSAnand Jain 1540*a26d60deSAnand Jain static ssize_t btrfs_devinfo_fsid_show(struct kobject *kobj, 1541*a26d60deSAnand Jain struct kobj_attribute *a, char *buf) 1542*a26d60deSAnand Jain { 1543*a26d60deSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1544*a26d60deSAnand Jain devid_kobj); 1545*a26d60deSAnand Jain 1546*a26d60deSAnand Jain return sysfs_emit(buf, "%pU\n", device->fs_devices->fsid); 1547*a26d60deSAnand Jain } 1548*a26d60deSAnand Jain BTRFS_ATTR(devid, fsid, btrfs_devinfo_fsid_show); 1549*a26d60deSAnand Jain 1550da658b57SDavid Sterba static ssize_t btrfs_devinfo_error_stats_show(struct kobject *kobj, 1551da658b57SDavid Sterba struct kobj_attribute *a, char *buf) 1552da658b57SDavid Sterba { 1553da658b57SDavid Sterba struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1554da658b57SDavid Sterba devid_kobj); 1555da658b57SDavid Sterba 1556da658b57SDavid Sterba if (!device->dev_stats_valid) 1557020e5277SAnand Jain return sysfs_emit(buf, "invalid\n"); 1558da658b57SDavid Sterba 1559da658b57SDavid Sterba /* 1560da658b57SDavid Sterba * Print all at once so we get a snapshot of all values from the same 1561da658b57SDavid Sterba * time. Keep them in sync and in order of definition of 1562da658b57SDavid Sterba * btrfs_dev_stat_values. 1563da658b57SDavid Sterba */ 1564020e5277SAnand Jain return sysfs_emit(buf, 1565da658b57SDavid Sterba "write_errs %d\n" 1566da658b57SDavid Sterba "read_errs %d\n" 1567da658b57SDavid Sterba "flush_errs %d\n" 1568da658b57SDavid Sterba "corruption_errs %d\n" 1569da658b57SDavid Sterba "generation_errs %d\n", 1570da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_WRITE_ERRS), 1571da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_READ_ERRS), 1572da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_FLUSH_ERRS), 1573da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_CORRUPTION_ERRS), 1574da658b57SDavid Sterba btrfs_dev_stat_read(device, BTRFS_DEV_STAT_GENERATION_ERRS)); 1575da658b57SDavid Sterba } 1576da658b57SDavid Sterba BTRFS_ATTR(devid, error_stats, btrfs_devinfo_error_stats_show); 1577da658b57SDavid Sterba 1578e7849e33SAnand Jain /* 1579e7849e33SAnand Jain * Information about one device. 1580e7849e33SAnand Jain * 1581e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/devinfo/<devid>/ 1582e7849e33SAnand Jain */ 1583668e48afSAnand Jain static struct attribute *devid_attrs[] = { 1584da658b57SDavid Sterba BTRFS_ATTR_PTR(devid, error_stats), 1585*a26d60deSAnand Jain BTRFS_ATTR_PTR(devid, fsid), 1586668e48afSAnand Jain BTRFS_ATTR_PTR(devid, in_fs_metadata), 1587668e48afSAnand Jain BTRFS_ATTR_PTR(devid, missing), 1588668e48afSAnand Jain BTRFS_ATTR_PTR(devid, replace_target), 1589eb3b5053SDavid Sterba BTRFS_ATTR_PTR(devid, scrub_speed_max), 1590668e48afSAnand Jain BTRFS_ATTR_PTR(devid, writeable), 1591668e48afSAnand Jain NULL 1592668e48afSAnand Jain }; 1593668e48afSAnand Jain ATTRIBUTE_GROUPS(devid); 1594668e48afSAnand Jain 1595668e48afSAnand Jain static void btrfs_release_devid_kobj(struct kobject *kobj) 1596668e48afSAnand Jain { 1597668e48afSAnand Jain struct btrfs_device *device = container_of(kobj, struct btrfs_device, 1598668e48afSAnand Jain devid_kobj); 1599668e48afSAnand Jain 1600668e48afSAnand Jain memset(&device->devid_kobj, 0, sizeof(struct kobject)); 1601668e48afSAnand Jain complete(&device->kobj_unregister); 1602668e48afSAnand Jain } 1603668e48afSAnand Jain 1604668e48afSAnand Jain static struct kobj_type devid_ktype = { 1605668e48afSAnand Jain .sysfs_ops = &kobj_sysfs_ops, 1606668e48afSAnand Jain .default_groups = devid_groups, 1607668e48afSAnand Jain .release = btrfs_release_devid_kobj, 1608668e48afSAnand Jain }; 1609668e48afSAnand Jain 1610cd36da2eSAnand Jain int btrfs_sysfs_add_device(struct btrfs_device *device) 161129e5be24SJeff Mahoney { 1612178a16c9SAnand Jain int ret; 1613a47bd78dSJosef Bacik unsigned int nofs_flag; 1614178a16c9SAnand Jain struct kobject *devices_kobj; 1615178a16c9SAnand Jain struct kobject *devinfo_kobj; 1616178a16c9SAnand Jain 1617178a16c9SAnand Jain /* 1618178a16c9SAnand Jain * Make sure we use the fs_info::fs_devices to fetch the kobjects even 1619178a16c9SAnand Jain * for the seed fs_devices 1620178a16c9SAnand Jain */ 1621178a16c9SAnand Jain devices_kobj = device->fs_info->fs_devices->devices_kobj; 1622178a16c9SAnand Jain devinfo_kobj = device->fs_info->fs_devices->devinfo_kobj; 1623178a16c9SAnand Jain ASSERT(devices_kobj); 1624178a16c9SAnand Jain ASSERT(devinfo_kobj); 162529e5be24SJeff Mahoney 1626a47bd78dSJosef Bacik nofs_flag = memalloc_nofs_save(); 1627f085381eSAnand Jain 1628178a16c9SAnand Jain if (device->bdev) { 16298d65269fSChristoph Hellwig struct kobject *disk_kobj = bdev_kobj(device->bdev); 163029e5be24SJeff Mahoney 1631178a16c9SAnand Jain ret = sysfs_create_link(devices_kobj, disk_kobj, disk_kobj->name); 1632178a16c9SAnand Jain if (ret) { 1633178a16c9SAnand Jain btrfs_warn(device->fs_info, 1634178a16c9SAnand Jain "creating sysfs device link for devid %llu failed: %d", 1635178a16c9SAnand Jain device->devid, ret); 1636178a16c9SAnand Jain goto out; 1637178a16c9SAnand Jain } 163829e5be24SJeff Mahoney } 163929e5be24SJeff Mahoney 1640178a16c9SAnand Jain init_completion(&device->kobj_unregister); 1641178a16c9SAnand Jain ret = kobject_init_and_add(&device->devid_kobj, &devid_ktype, 1642178a16c9SAnand Jain devinfo_kobj, "%llu", device->devid); 1643178a16c9SAnand Jain if (ret) { 1644178a16c9SAnand Jain kobject_put(&device->devid_kobj); 1645178a16c9SAnand Jain btrfs_warn(device->fs_info, 1646178a16c9SAnand Jain "devinfo init for devid %llu failed: %d", 1647178a16c9SAnand Jain device->devid, ret); 1648668e48afSAnand Jain } 1649178a16c9SAnand Jain 1650178a16c9SAnand Jain out: 1651a47bd78dSJosef Bacik memalloc_nofs_restore(nofs_flag); 1652178a16c9SAnand Jain return ret; 1653178a16c9SAnand Jain } 1654668e48afSAnand Jain 1655cd36da2eSAnand Jain static int btrfs_sysfs_add_fs_devices(struct btrfs_fs_devices *fs_devices) 1656178a16c9SAnand Jain { 1657178a16c9SAnand Jain int ret; 1658cd36da2eSAnand Jain struct btrfs_device *device; 165930b0e4e0SAnand Jain struct btrfs_fs_devices *seed; 1660178a16c9SAnand Jain 1661178a16c9SAnand Jain list_for_each_entry(device, &fs_devices->devices, dev_list) { 1662178a16c9SAnand Jain ret = btrfs_sysfs_add_device(device); 1663178a16c9SAnand Jain if (ret) 16647ad3912aSAnand Jain goto fail; 1665178a16c9SAnand Jain } 1666178a16c9SAnand Jain 166730b0e4e0SAnand Jain list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { 166830b0e4e0SAnand Jain list_for_each_entry(device, &seed->devices, dev_list) { 166930b0e4e0SAnand Jain ret = btrfs_sysfs_add_device(device); 167030b0e4e0SAnand Jain if (ret) 16717ad3912aSAnand Jain goto fail; 167230b0e4e0SAnand Jain } 167330b0e4e0SAnand Jain } 167430b0e4e0SAnand Jain 1675178a16c9SAnand Jain return 0; 16767ad3912aSAnand Jain 16777ad3912aSAnand Jain fail: 16787ad3912aSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devices); 16797ad3912aSAnand Jain return ret; 168029e5be24SJeff Mahoney } 168129e5be24SJeff Mahoney 16825b28692eSDavid Sterba void btrfs_kobject_uevent(struct block_device *bdev, enum kobject_action action) 16835b28692eSDavid Sterba { 16845b28692eSDavid Sterba int ret; 16855b28692eSDavid Sterba 16865b28692eSDavid Sterba ret = kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, action); 16875b28692eSDavid Sterba if (ret) 16885b28692eSDavid Sterba pr_warn("BTRFS: Sending event '%d' to kobject: '%s' (%p): failed\n", 16895b28692eSDavid Sterba action, kobject_name(&disk_to_dev(bdev->bd_disk)->kobj), 16905b28692eSDavid Sterba &disk_to_dev(bdev->bd_disk)->kobj); 16915b28692eSDavid Sterba } 16925b28692eSDavid Sterba 16938e560081SNikolay Borisov void btrfs_sysfs_update_sprout_fsid(struct btrfs_fs_devices *fs_devices) 16948e560081SNikolay Borisov 1695f93c3997SDavid Sterba { 1696f93c3997SDavid Sterba char fsid_buf[BTRFS_UUID_UNPARSED_SIZE]; 1697f93c3997SDavid Sterba 1698f93c3997SDavid Sterba /* 1699f93c3997SDavid Sterba * Sprouting changes fsid of the mounted filesystem, rename the fsid 1700f93c3997SDavid Sterba * directory 1701f93c3997SDavid Sterba */ 17028e560081SNikolay Borisov snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", fs_devices->fsid); 1703f93c3997SDavid Sterba if (kobject_rename(&fs_devices->fsid_kobj, fsid_buf)) 1704f93c3997SDavid Sterba btrfs_warn(fs_devices->fs_info, 1705f93c3997SDavid Sterba "sysfs: failed to create fsid for sprout"); 1706f93c3997SDavid Sterba } 1707f93c3997SDavid Sterba 1708668e48afSAnand Jain void btrfs_sysfs_update_devid(struct btrfs_device *device) 1709668e48afSAnand Jain { 1710668e48afSAnand Jain char tmp[24]; 1711668e48afSAnand Jain 1712668e48afSAnand Jain snprintf(tmp, sizeof(tmp), "%llu", device->devid); 1713668e48afSAnand Jain 1714668e48afSAnand Jain if (kobject_rename(&device->devid_kobj, tmp)) 1715668e48afSAnand Jain btrfs_warn(device->fs_devices->fs_info, 1716668e48afSAnand Jain "sysfs: failed to update devid for %llu", 1717668e48afSAnand Jain device->devid); 1718668e48afSAnand Jain } 1719668e48afSAnand Jain 1720510d7360SJeff Mahoney /* /sys/fs/btrfs/ entry */ 1721510d7360SJeff Mahoney static struct kset *btrfs_kset; 1722510d7360SJeff Mahoney 172372059215SAnand Jain /* 1724c6761a9eSAnand Jain * Creates: 1725c6761a9eSAnand Jain * /sys/fs/btrfs/UUID 1726c6761a9eSAnand Jain * 172772059215SAnand Jain * Can be called by the device discovery thread. 172872059215SAnand Jain */ 1729c6761a9eSAnand Jain int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs) 17305ac1d209SJeff Mahoney { 17315ac1d209SJeff Mahoney int error; 17325ac1d209SJeff Mahoney 17332e7910d6SAnand Jain init_completion(&fs_devs->kobj_unregister); 1734c1b7e474SAnand Jain fs_devs->fsid_kobj.kset = btrfs_kset; 1735c6761a9eSAnand Jain error = kobject_init_and_add(&fs_devs->fsid_kobj, &btrfs_ktype, NULL, 1736c6761a9eSAnand Jain "%pU", fs_devs->fsid); 1737e3277335STobin C. Harding if (error) { 1738e3277335STobin C. Harding kobject_put(&fs_devs->fsid_kobj); 173972059215SAnand Jain return error; 174072059215SAnand Jain } 174172059215SAnand Jain 1742bc036bb3SAnand Jain fs_devs->devices_kobj = kobject_create_and_add("devices", 1743bc036bb3SAnand Jain &fs_devs->fsid_kobj); 1744bc036bb3SAnand Jain if (!fs_devs->devices_kobj) { 1745bc036bb3SAnand Jain btrfs_err(fs_devs->fs_info, 1746bc036bb3SAnand Jain "failed to init sysfs device interface"); 17471f6087e6SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1748bc036bb3SAnand Jain return -ENOMEM; 1749bc036bb3SAnand Jain } 1750bc036bb3SAnand Jain 1751a013d141SAnand Jain fs_devs->devinfo_kobj = kobject_create_and_add("devinfo", 1752a013d141SAnand Jain &fs_devs->fsid_kobj); 1753a013d141SAnand Jain if (!fs_devs->devinfo_kobj) { 1754a013d141SAnand Jain btrfs_err(fs_devs->fs_info, 1755a013d141SAnand Jain "failed to init sysfs devinfo kobject"); 1756a013d141SAnand Jain btrfs_sysfs_remove_fsid(fs_devs); 1757a013d141SAnand Jain return -ENOMEM; 1758a013d141SAnand Jain } 1759a013d141SAnand Jain 1760e3277335STobin C. Harding return 0; 1761e3277335STobin C. Harding } 1762e3277335STobin C. Harding 176396f3136eSAnand Jain int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info) 176472059215SAnand Jain { 176572059215SAnand Jain int error; 17662e7910d6SAnand Jain struct btrfs_fs_devices *fs_devs = fs_info->fs_devices; 1767c1b7e474SAnand Jain struct kobject *fsid_kobj = &fs_devs->fsid_kobj; 176872059215SAnand Jain 1769cd36da2eSAnand Jain error = btrfs_sysfs_add_fs_devices(fs_devs); 1770e453d989SJeff Mahoney if (error) 1771e453d989SJeff Mahoney return error; 1772510d7360SJeff Mahoney 1773c1b7e474SAnand Jain error = sysfs_create_files(fsid_kobj, btrfs_attrs); 1774e453d989SJeff Mahoney if (error) { 177553f8a74cSAnand Jain btrfs_sysfs_remove_fs_devices(fs_devs); 1776e453d989SJeff Mahoney return error; 1777e453d989SJeff Mahoney } 177879da4fa4SJeff Mahoney 1779c1b7e474SAnand Jain error = sysfs_create_group(fsid_kobj, 17800dd2906fSAnand Jain &btrfs_feature_attr_group); 17810dd2906fSAnand Jain if (error) 17820dd2906fSAnand Jain goto failure; 17830dd2906fSAnand Jain 17846e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 178593945cb4SDennis Zhou fs_info->debug_kobj = kobject_create_and_add("debug", fsid_kobj); 178693945cb4SDennis Zhou if (!fs_info->debug_kobj) { 178793945cb4SDennis Zhou error = -ENOMEM; 178893945cb4SDennis Zhou goto failure; 178993945cb4SDennis Zhou } 179093945cb4SDennis Zhou 179193945cb4SDennis Zhou error = sysfs_create_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); 17926e369febSDavid Sterba if (error) 17936e369febSDavid Sterba goto failure; 1794e4faab84SDennis Zhou 1795e4faab84SDennis Zhou /* Discard directory */ 1796e4faab84SDennis Zhou fs_info->discard_debug_kobj = kobject_create_and_add("discard", 1797e4faab84SDennis Zhou fs_info->debug_kobj); 1798e4faab84SDennis Zhou if (!fs_info->discard_debug_kobj) { 1799e4faab84SDennis Zhou error = -ENOMEM; 1800e4faab84SDennis Zhou goto failure; 1801e4faab84SDennis Zhou } 1802e4faab84SDennis Zhou 1803e4faab84SDennis Zhou error = sysfs_create_files(fs_info->discard_debug_kobj, 1804e4faab84SDennis Zhou discard_debug_attrs); 1805e4faab84SDennis Zhou if (error) 1806e4faab84SDennis Zhou goto failure; 18076e369febSDavid Sterba #endif 18086e369febSDavid Sterba 1809e453d989SJeff Mahoney error = addrm_unknown_feature_attrs(fs_info, true); 181079da4fa4SJeff Mahoney if (error) 181179da4fa4SJeff Mahoney goto failure; 181279da4fa4SJeff Mahoney 18133092c68fSNikolay Borisov error = sysfs_create_link(fsid_kobj, &fs_info->sb->s_bdi->dev->kobj, "bdi"); 18143092c68fSNikolay Borisov if (error) 18153092c68fSNikolay Borisov goto failure; 18163092c68fSNikolay Borisov 18176ab0a202SJeff Mahoney fs_info->space_info_kobj = kobject_create_and_add("allocation", 1818c1b7e474SAnand Jain fsid_kobj); 18196ab0a202SJeff Mahoney if (!fs_info->space_info_kobj) { 18206ab0a202SJeff Mahoney error = -ENOMEM; 18216ab0a202SJeff Mahoney goto failure; 18226ab0a202SJeff Mahoney } 18236ab0a202SJeff Mahoney 18246ab0a202SJeff Mahoney error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs); 18256ab0a202SJeff Mahoney if (error) 18266ab0a202SJeff Mahoney goto failure; 18276ab0a202SJeff Mahoney 182879da4fa4SJeff Mahoney return 0; 182979da4fa4SJeff Mahoney failure: 18306618a59bSAnand Jain btrfs_sysfs_remove_mounted(fs_info); 18315ac1d209SJeff Mahoney return error; 18325ac1d209SJeff Mahoney } 18335ac1d209SJeff Mahoney 183449e5fb46SQu Wenruo static inline struct btrfs_fs_info *qgroup_kobj_to_fs_info(struct kobject *kobj) 183549e5fb46SQu Wenruo { 183649e5fb46SQu Wenruo return to_fs_info(kobj->parent->parent); 183749e5fb46SQu Wenruo } 183849e5fb46SQu Wenruo 183949e5fb46SQu Wenruo #define QGROUP_ATTR(_member, _show_name) \ 184049e5fb46SQu Wenruo static ssize_t btrfs_qgroup_show_##_member(struct kobject *qgroup_kobj, \ 184149e5fb46SQu Wenruo struct kobj_attribute *a, \ 184249e5fb46SQu Wenruo char *buf) \ 184349e5fb46SQu Wenruo { \ 184449e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 184549e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 184649e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 184749e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->_member, &fs_info->qgroup_lock, buf); \ 184849e5fb46SQu Wenruo } \ 184949e5fb46SQu Wenruo BTRFS_ATTR(qgroup, _show_name, btrfs_qgroup_show_##_member) 185049e5fb46SQu Wenruo 185149e5fb46SQu Wenruo #define QGROUP_RSV_ATTR(_name, _type) \ 185249e5fb46SQu Wenruo static ssize_t btrfs_qgroup_rsv_show_##_name(struct kobject *qgroup_kobj, \ 185349e5fb46SQu Wenruo struct kobj_attribute *a, \ 185449e5fb46SQu Wenruo char *buf) \ 185549e5fb46SQu Wenruo { \ 185649e5fb46SQu Wenruo struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ 185749e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ 185849e5fb46SQu Wenruo struct btrfs_qgroup, kobj); \ 185949e5fb46SQu Wenruo return btrfs_show_u64(&qgroup->rsv.values[_type], \ 186049e5fb46SQu Wenruo &fs_info->qgroup_lock, buf); \ 186149e5fb46SQu Wenruo } \ 186249e5fb46SQu Wenruo BTRFS_ATTR(qgroup, rsv_##_name, btrfs_qgroup_rsv_show_##_name) 186349e5fb46SQu Wenruo 186449e5fb46SQu Wenruo QGROUP_ATTR(rfer, referenced); 186549e5fb46SQu Wenruo QGROUP_ATTR(excl, exclusive); 186649e5fb46SQu Wenruo QGROUP_ATTR(max_rfer, max_referenced); 186749e5fb46SQu Wenruo QGROUP_ATTR(max_excl, max_exclusive); 186849e5fb46SQu Wenruo QGROUP_ATTR(lim_flags, limit_flags); 186949e5fb46SQu Wenruo QGROUP_RSV_ATTR(data, BTRFS_QGROUP_RSV_DATA); 187049e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_pertrans, BTRFS_QGROUP_RSV_META_PERTRANS); 187149e5fb46SQu Wenruo QGROUP_RSV_ATTR(meta_prealloc, BTRFS_QGROUP_RSV_META_PREALLOC); 187249e5fb46SQu Wenruo 1873e7849e33SAnand Jain /* 1874e7849e33SAnand Jain * Qgroup information. 1875e7849e33SAnand Jain * 1876e7849e33SAnand Jain * Path: /sys/fs/btrfs/<uuid>/qgroups/<level>_<qgroupid>/ 1877e7849e33SAnand Jain */ 187849e5fb46SQu Wenruo static struct attribute *qgroup_attrs[] = { 187949e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, referenced), 188049e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, exclusive), 188149e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_referenced), 188249e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, max_exclusive), 188349e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, limit_flags), 188449e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_data), 188549e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_pertrans), 188649e5fb46SQu Wenruo BTRFS_ATTR_PTR(qgroup, rsv_meta_prealloc), 188749e5fb46SQu Wenruo NULL 188849e5fb46SQu Wenruo }; 188949e5fb46SQu Wenruo ATTRIBUTE_GROUPS(qgroup); 189049e5fb46SQu Wenruo 189149e5fb46SQu Wenruo static void qgroup_release(struct kobject *kobj) 189249e5fb46SQu Wenruo { 189349e5fb46SQu Wenruo struct btrfs_qgroup *qgroup = container_of(kobj, struct btrfs_qgroup, kobj); 189449e5fb46SQu Wenruo 189549e5fb46SQu Wenruo memset(&qgroup->kobj, 0, sizeof(*kobj)); 189649e5fb46SQu Wenruo } 189749e5fb46SQu Wenruo 189849e5fb46SQu Wenruo static struct kobj_type qgroup_ktype = { 189949e5fb46SQu Wenruo .sysfs_ops = &kobj_sysfs_ops, 190049e5fb46SQu Wenruo .release = qgroup_release, 190149e5fb46SQu Wenruo .default_groups = qgroup_groups, 190249e5fb46SQu Wenruo }; 190349e5fb46SQu Wenruo 190449e5fb46SQu Wenruo int btrfs_sysfs_add_one_qgroup(struct btrfs_fs_info *fs_info, 190549e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 190649e5fb46SQu Wenruo { 190749e5fb46SQu Wenruo struct kobject *qgroups_kobj = fs_info->qgroups_kobj; 190849e5fb46SQu Wenruo int ret; 190949e5fb46SQu Wenruo 191049e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 191149e5fb46SQu Wenruo return 0; 191249e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) 191349e5fb46SQu Wenruo return 0; 191449e5fb46SQu Wenruo if (!qgroups_kobj) 191549e5fb46SQu Wenruo return -EINVAL; 191649e5fb46SQu Wenruo 191749e5fb46SQu Wenruo ret = kobject_init_and_add(&qgroup->kobj, &qgroup_ktype, qgroups_kobj, 191849e5fb46SQu Wenruo "%hu_%llu", btrfs_qgroup_level(qgroup->qgroupid), 191949e5fb46SQu Wenruo btrfs_qgroup_subvolid(qgroup->qgroupid)); 192049e5fb46SQu Wenruo if (ret < 0) 192149e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 192249e5fb46SQu Wenruo 192349e5fb46SQu Wenruo return ret; 192449e5fb46SQu Wenruo } 192549e5fb46SQu Wenruo 192649e5fb46SQu Wenruo void btrfs_sysfs_del_qgroups(struct btrfs_fs_info *fs_info) 192749e5fb46SQu Wenruo { 192849e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 192949e5fb46SQu Wenruo struct btrfs_qgroup *next; 193049e5fb46SQu Wenruo 193149e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 193249e5fb46SQu Wenruo return; 193349e5fb46SQu Wenruo 193449e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 193549e5fb46SQu Wenruo &fs_info->qgroup_tree, node) 193649e5fb46SQu Wenruo btrfs_sysfs_del_one_qgroup(fs_info, qgroup); 193762ab2cc0SQu Wenruo if (fs_info->qgroups_kobj) { 193849e5fb46SQu Wenruo kobject_del(fs_info->qgroups_kobj); 193949e5fb46SQu Wenruo kobject_put(fs_info->qgroups_kobj); 194049e5fb46SQu Wenruo fs_info->qgroups_kobj = NULL; 194149e5fb46SQu Wenruo } 194262ab2cc0SQu Wenruo } 194349e5fb46SQu Wenruo 194449e5fb46SQu Wenruo /* Called when qgroups get initialized, thus there is no need for locking */ 194549e5fb46SQu Wenruo int btrfs_sysfs_add_qgroups(struct btrfs_fs_info *fs_info) 194649e5fb46SQu Wenruo { 194749e5fb46SQu Wenruo struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; 194849e5fb46SQu Wenruo struct btrfs_qgroup *qgroup; 194949e5fb46SQu Wenruo struct btrfs_qgroup *next; 195049e5fb46SQu Wenruo int ret = 0; 195149e5fb46SQu Wenruo 195249e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 195349e5fb46SQu Wenruo return 0; 195449e5fb46SQu Wenruo 195549e5fb46SQu Wenruo ASSERT(fsid_kobj); 195649e5fb46SQu Wenruo if (fs_info->qgroups_kobj) 195749e5fb46SQu Wenruo return 0; 195849e5fb46SQu Wenruo 195949e5fb46SQu Wenruo fs_info->qgroups_kobj = kobject_create_and_add("qgroups", fsid_kobj); 196049e5fb46SQu Wenruo if (!fs_info->qgroups_kobj) { 196149e5fb46SQu Wenruo ret = -ENOMEM; 196249e5fb46SQu Wenruo goto out; 196349e5fb46SQu Wenruo } 196449e5fb46SQu Wenruo rbtree_postorder_for_each_entry_safe(qgroup, next, 196549e5fb46SQu Wenruo &fs_info->qgroup_tree, node) { 196649e5fb46SQu Wenruo ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup); 196749e5fb46SQu Wenruo if (ret < 0) 196849e5fb46SQu Wenruo goto out; 196949e5fb46SQu Wenruo } 197049e5fb46SQu Wenruo 197149e5fb46SQu Wenruo out: 197249e5fb46SQu Wenruo if (ret < 0) 197349e5fb46SQu Wenruo btrfs_sysfs_del_qgroups(fs_info); 197449e5fb46SQu Wenruo return ret; 197549e5fb46SQu Wenruo } 197649e5fb46SQu Wenruo 197749e5fb46SQu Wenruo void btrfs_sysfs_del_one_qgroup(struct btrfs_fs_info *fs_info, 197849e5fb46SQu Wenruo struct btrfs_qgroup *qgroup) 197949e5fb46SQu Wenruo { 198049e5fb46SQu Wenruo if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) 198149e5fb46SQu Wenruo return; 198249e5fb46SQu Wenruo 198349e5fb46SQu Wenruo if (qgroup->kobj.state_initialized) { 198449e5fb46SQu Wenruo kobject_del(&qgroup->kobj); 198549e5fb46SQu Wenruo kobject_put(&qgroup->kobj); 198649e5fb46SQu Wenruo } 198749e5fb46SQu Wenruo } 1988444e7516SDavid Sterba 1989444e7516SDavid Sterba /* 1990444e7516SDavid Sterba * Change per-fs features in /sys/fs/btrfs/UUID/features to match current 1991444e7516SDavid Sterba * values in superblock. Call after any changes to incompat/compat_ro flags 1992444e7516SDavid Sterba */ 1993444e7516SDavid Sterba void btrfs_sysfs_feature_update(struct btrfs_fs_info *fs_info, 1994444e7516SDavid Sterba u64 bit, enum btrfs_feature_set set) 1995444e7516SDavid Sterba { 1996444e7516SDavid Sterba struct btrfs_fs_devices *fs_devs; 1997444e7516SDavid Sterba struct kobject *fsid_kobj; 199824646481SLeon Romanovsky u64 __maybe_unused features; 199924646481SLeon Romanovsky int __maybe_unused ret; 2000444e7516SDavid Sterba 2001444e7516SDavid Sterba if (!fs_info) 2002444e7516SDavid Sterba return; 2003444e7516SDavid Sterba 200424646481SLeon Romanovsky /* 200524646481SLeon Romanovsky * See 14e46e04958df74 and e410e34fad913dd, feature bit updates are not 200624646481SLeon Romanovsky * safe when called from some contexts (eg. balance) 200724646481SLeon Romanovsky */ 2008444e7516SDavid Sterba features = get_features(fs_info, set); 2009444e7516SDavid Sterba ASSERT(bit & supported_feature_masks[set]); 2010444e7516SDavid Sterba 2011444e7516SDavid Sterba fs_devs = fs_info->fs_devices; 2012444e7516SDavid Sterba fsid_kobj = &fs_devs->fsid_kobj; 2013444e7516SDavid Sterba 2014bf609206SDavid Sterba if (!fsid_kobj->state_initialized) 2015bf609206SDavid Sterba return; 2016bf609206SDavid Sterba 2017444e7516SDavid Sterba /* 2018444e7516SDavid Sterba * FIXME: this is too heavy to update just one value, ideally we'd like 2019444e7516SDavid Sterba * to use sysfs_update_group but some refactoring is needed first. 2020444e7516SDavid Sterba */ 2021444e7516SDavid Sterba sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); 2022444e7516SDavid Sterba ret = sysfs_create_group(fsid_kobj, &btrfs_feature_attr_group); 2023444e7516SDavid Sterba } 2024444e7516SDavid Sterba 2025f5c29bd9SLiu Bo int __init btrfs_init_sysfs(void) 202658176a96SJosef Bacik { 2027079b72bcSJeff Mahoney int ret; 20281bae3098SDavid Sterba 2029e3fe4e71SGreg KH btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); 2030e3fe4e71SGreg KH if (!btrfs_kset) 2031e3fe4e71SGreg KH return -ENOMEM; 2032079b72bcSJeff Mahoney 20331bae3098SDavid Sterba init_feature_attrs(); 20341bae3098SDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2035001a648dSFilipe Manana if (ret) 2036001a648dSFilipe Manana goto out2; 2037f902bd3aSMisono Tomohiro ret = sysfs_merge_group(&btrfs_kset->kobj, 2038f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2039f902bd3aSMisono Tomohiro if (ret) 2040f902bd3aSMisono Tomohiro goto out_remove_group; 2041001a648dSFilipe Manana 20426e369febSDavid Sterba #ifdef CONFIG_BTRFS_DEBUG 20436e369febSDavid Sterba ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 20446e369febSDavid Sterba if (ret) 20456e369febSDavid Sterba goto out2; 20466e369febSDavid Sterba #endif 20476e369febSDavid Sterba 2048001a648dSFilipe Manana return 0; 2049f902bd3aSMisono Tomohiro 2050f902bd3aSMisono Tomohiro out_remove_group: 2051f902bd3aSMisono Tomohiro sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 2052001a648dSFilipe Manana out2: 2053001a648dSFilipe Manana kset_unregister(btrfs_kset); 20541bae3098SDavid Sterba 20551bae3098SDavid Sterba return ret; 205658176a96SJosef Bacik } 205758176a96SJosef Bacik 2058e67c718bSDavid Sterba void __cold btrfs_exit_sysfs(void) 205958176a96SJosef Bacik { 2060f902bd3aSMisono Tomohiro sysfs_unmerge_group(&btrfs_kset->kobj, 2061f902bd3aSMisono Tomohiro &btrfs_static_feature_attr_group); 2062079b72bcSJeff Mahoney sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); 206371e8978eSDennis Zhou #ifdef CONFIG_BTRFS_DEBUG 206471e8978eSDennis Zhou sysfs_remove_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); 206571e8978eSDennis Zhou #endif 2066e3fe4e71SGreg KH kset_unregister(btrfs_kset); 206758176a96SJosef Bacik } 206855d47414SChris Mason 2069