linux/fs/btrfs/sysfs.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2007 Oracle.  All rights reserved.
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public
   6 * License v2 as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11 * General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public
  14 * License along with this program; if not, write to the
  15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  16 * Boston, MA 021110-1307, USA.
  17 */
  18
  19#include <linux/sched.h>
  20#include <linux/slab.h>
  21#include <linux/spinlock.h>
  22#include <linux/completion.h>
  23#include <linux/buffer_head.h>
  24#include <linux/kobject.h>
  25#include <linux/bug.h>
  26#include <linux/genhd.h>
  27#include <linux/debugfs.h>
  28
  29#include "ctree.h"
  30#include "disk-io.h"
  31#include "transaction.h"
  32#include "sysfs.h"
  33#include "volumes.h"
  34
  35static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj);
  36static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj);
  37
  38static u64 get_features(struct btrfs_fs_info *fs_info,
  39                        enum btrfs_feature_set set)
  40{
  41        struct btrfs_super_block *disk_super = fs_info->super_copy;
  42        if (set == FEAT_COMPAT)
  43                return btrfs_super_compat_flags(disk_super);
  44        else if (set == FEAT_COMPAT_RO)
  45                return btrfs_super_compat_ro_flags(disk_super);
  46        else
  47                return btrfs_super_incompat_flags(disk_super);
  48}
  49
  50static void set_features(struct btrfs_fs_info *fs_info,
  51                         enum btrfs_feature_set set, u64 features)
  52{
  53        struct btrfs_super_block *disk_super = fs_info->super_copy;
  54        if (set == FEAT_COMPAT)
  55                btrfs_set_super_compat_flags(disk_super, features);
  56        else if (set == FEAT_COMPAT_RO)
  57                btrfs_set_super_compat_ro_flags(disk_super, features);
  58        else
  59                btrfs_set_super_incompat_flags(disk_super, features);
  60}
  61
  62static int can_modify_feature(struct btrfs_feature_attr *fa)
  63{
  64        int val = 0;
  65        u64 set, clear;
  66        switch (fa->feature_set) {
  67        case FEAT_COMPAT:
  68                set = BTRFS_FEATURE_COMPAT_SAFE_SET;
  69                clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR;
  70                break;
  71        case FEAT_COMPAT_RO:
  72                set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET;
  73                clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR;
  74                break;
  75        case FEAT_INCOMPAT:
  76                set = BTRFS_FEATURE_INCOMPAT_SAFE_SET;
  77                clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR;
  78                break;
  79        default:
  80                pr_warn("btrfs: sysfs: unknown feature set %d\n",
  81                                fa->feature_set);
  82                return 0;
  83        }
  84
  85        if (set & fa->feature_bit)
  86                val |= 1;
  87        if (clear & fa->feature_bit)
  88                val |= 2;
  89
  90        return val;
  91}
  92
  93static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
  94                                       struct kobj_attribute *a, char *buf)
  95{
  96        int val = 0;
  97        struct btrfs_fs_info *fs_info = to_fs_info(kobj);
  98        struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
  99        if (fs_info) {
 100                u64 features = get_features(fs_info, fa->feature_set);
 101                if (features & fa->feature_bit)
 102                        val = 1;
 103        } else
 104                val = can_modify_feature(fa);
 105
 106        return snprintf(buf, PAGE_SIZE, "%d\n", val);
 107}
 108
 109static ssize_t btrfs_feature_attr_store(struct kobject *kobj,
 110                                        struct kobj_attribute *a,
 111                                        const char *buf, size_t count)
 112{
 113        struct btrfs_fs_info *fs_info;
 114        struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
 115        u64 features, set, clear;
 116        unsigned long val;
 117        int ret;
 118
 119        fs_info = to_fs_info(kobj);
 120        if (!fs_info)
 121                return -EPERM;
 122
 123        if (fs_info->sb->s_flags & MS_RDONLY)
 124                return -EROFS;
 125
 126        ret = kstrtoul(skip_spaces(buf), 0, &val);
 127        if (ret)
 128                return ret;
 129
 130        if (fa->feature_set == FEAT_COMPAT) {
 131                set = BTRFS_FEATURE_COMPAT_SAFE_SET;
 132                clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR;
 133        } else if (fa->feature_set == FEAT_COMPAT_RO) {
 134                set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET;
 135                clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR;
 136        } else {
 137                set = BTRFS_FEATURE_INCOMPAT_SAFE_SET;
 138                clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR;
 139        }
 140
 141        features = get_features(fs_info, fa->feature_set);
 142
 143        /* Nothing to do */
 144        if ((val && (features & fa->feature_bit)) ||
 145            (!val && !(features & fa->feature_bit)))
 146                return count;
 147
 148        if ((val && !(set & fa->feature_bit)) ||
 149            (!val && !(clear & fa->feature_bit))) {
 150                btrfs_info(fs_info,
 151                        "%sabling feature %s on mounted fs is not supported.",
 152                        val ? "En" : "Dis", fa->kobj_attr.attr.name);
 153                return -EPERM;
 154        }
 155
 156        btrfs_info(fs_info, "%s %s feature flag",
 157                   val ? "Setting" : "Clearing", fa->kobj_attr.attr.name);
 158
 159        spin_lock(&fs_info->super_lock);
 160        features = get_features(fs_info, fa->feature_set);
 161        if (val)
 162                features |= fa->feature_bit;
 163        else
 164                features &= ~fa->feature_bit;
 165        set_features(fs_info, fa->feature_set, features);
 166        spin_unlock(&fs_info->super_lock);
 167
 168        /*
 169         * We don't want to do full transaction commit from inside sysfs
 170         */
 171        btrfs_set_pending(fs_info, COMMIT);
 172        wake_up_process(fs_info->transaction_kthread);
 173
 174        return count;
 175}
 176
 177static umode_t btrfs_feature_visible(struct kobject *kobj,
 178                                     struct attribute *attr, int unused)
 179{
 180        struct btrfs_fs_info *fs_info = to_fs_info(kobj);
 181        umode_t mode = attr->mode;
 182
 183        if (fs_info) {
 184                struct btrfs_feature_attr *fa;
 185                u64 features;
 186
 187                fa = attr_to_btrfs_feature_attr(attr);
 188                features = get_features(fs_info, fa->feature_set);
 189
 190                if (can_modify_feature(fa))
 191                        mode |= S_IWUSR;
 192                else if (!(features & fa->feature_bit))
 193                        mode = 0;
 194        }
 195
 196        return mode;
 197}
 198
 199BTRFS_FEAT_ATTR_INCOMPAT(mixed_backref, MIXED_BACKREF);
 200BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL);
 201BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS);
 202BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO);
 203BTRFS_FEAT_ATTR_INCOMPAT(big_metadata, BIG_METADATA);
 204BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF);
 205BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56);
 206BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA);
 207BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES);
 208BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE);
 209
 210static struct attribute *btrfs_supported_feature_attrs[] = {
 211        BTRFS_FEAT_ATTR_PTR(mixed_backref),
 212        BTRFS_FEAT_ATTR_PTR(default_subvol),
 213        BTRFS_FEAT_ATTR_PTR(mixed_groups),
 214        BTRFS_FEAT_ATTR_PTR(compress_lzo),
 215        BTRFS_FEAT_ATTR_PTR(big_metadata),
 216        BTRFS_FEAT_ATTR_PTR(extended_iref),
 217        BTRFS_FEAT_ATTR_PTR(raid56),
 218        BTRFS_FEAT_ATTR_PTR(skinny_metadata),
 219        BTRFS_FEAT_ATTR_PTR(no_holes),
 220        BTRFS_FEAT_ATTR_PTR(free_space_tree),
 221        NULL
 222};
 223
 224static const struct attribute_group btrfs_feature_attr_group = {
 225        .name = "features",
 226        .is_visible = btrfs_feature_visible,
 227        .attrs = btrfs_supported_feature_attrs,
 228};
 229
 230static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf)
 231{
 232        u64 val;
 233        if (lock)
 234                spin_lock(lock);
 235        val = *value_ptr;
 236        if (lock)
 237                spin_unlock(lock);
 238        return snprintf(buf, PAGE_SIZE, "%llu\n", val);
 239}
 240
 241static ssize_t global_rsv_size_show(struct kobject *kobj,
 242                                    struct kobj_attribute *ka, char *buf)
 243{
 244        struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
 245        struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
 246        return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf);
 247}
 248BTRFS_ATTR(global_rsv_size, global_rsv_size_show);
 249
 250static ssize_t global_rsv_reserved_show(struct kobject *kobj,
 251                                        struct kobj_attribute *a, char *buf)
 252{
 253        struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
 254        struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
 255        return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf);
 256}
 257BTRFS_ATTR(global_rsv_reserved, global_rsv_reserved_show);
 258
 259#define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj)
 260#define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj)
 261
 262static ssize_t raid_bytes_show(struct kobject *kobj,
 263                               struct kobj_attribute *attr, char *buf);
 264BTRFS_RAID_ATTR(total_bytes, raid_bytes_show);
 265BTRFS_RAID_ATTR(used_bytes, raid_bytes_show);
 266
 267static ssize_t raid_bytes_show(struct kobject *kobj,
 268                               struct kobj_attribute *attr, char *buf)
 269
 270{
 271        struct btrfs_space_info *sinfo = to_space_info(kobj->parent);
 272        struct btrfs_block_group_cache *block_group;
 273        int index = to_raid_kobj(kobj)->raid_type;
 274        u64 val = 0;
 275
 276        down_read(&sinfo->groups_sem);
 277        list_for_each_entry(block_group, &sinfo->block_groups[index], list) {
 278                if (&attr->attr == BTRFS_RAID_ATTR_PTR(total_bytes))
 279                        val += block_group->key.offset;
 280                else
 281                        val += btrfs_block_group_used(&block_group->item);
 282        }
 283        up_read(&sinfo->groups_sem);
 284        return snprintf(buf, PAGE_SIZE, "%llu\n", val);
 285}
 286
 287static struct attribute *raid_attributes[] = {
 288        BTRFS_RAID_ATTR_PTR(total_bytes),
 289        BTRFS_RAID_ATTR_PTR(used_bytes),
 290        NULL
 291};
 292
 293static void release_raid_kobj(struct kobject *kobj)
 294{
 295        kfree(to_raid_kobj(kobj));
 296}
 297
 298struct kobj_type btrfs_raid_ktype = {
 299        .sysfs_ops = &kobj_sysfs_ops,
 300        .release = release_raid_kobj,
 301        .default_attrs = raid_attributes,
 302};
 303
 304#define SPACE_INFO_ATTR(field)                                          \
 305static ssize_t btrfs_space_info_show_##field(struct kobject *kobj,      \
 306                                             struct kobj_attribute *a,  \
 307                                             char *buf)                 \
 308{                                                                       \
 309        struct btrfs_space_info *sinfo = to_space_info(kobj);           \
 310        return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf);        \
 311}                                                                       \
 312BTRFS_ATTR(field, btrfs_space_info_show_##field)
 313
 314static ssize_t btrfs_space_info_show_total_bytes_pinned(struct kobject *kobj,
 315                                                       struct kobj_attribute *a,
 316                                                       char *buf)
 317{
 318        struct btrfs_space_info *sinfo = to_space_info(kobj);
 319        s64 val = percpu_counter_sum(&sinfo->total_bytes_pinned);
 320        return snprintf(buf, PAGE_SIZE, "%lld\n", val);
 321}
 322
 323SPACE_INFO_ATTR(flags);
 324SPACE_INFO_ATTR(total_bytes);
 325SPACE_INFO_ATTR(bytes_used);
 326SPACE_INFO_ATTR(bytes_pinned);
 327SPACE_INFO_ATTR(bytes_reserved);
 328SPACE_INFO_ATTR(bytes_may_use);
 329SPACE_INFO_ATTR(bytes_readonly);
 330SPACE_INFO_ATTR(disk_used);
 331SPACE_INFO_ATTR(disk_total);
 332BTRFS_ATTR(total_bytes_pinned, btrfs_space_info_show_total_bytes_pinned);
 333
 334static struct attribute *space_info_attrs[] = {
 335        BTRFS_ATTR_PTR(flags),
 336        BTRFS_ATTR_PTR(total_bytes),
 337        BTRFS_ATTR_PTR(bytes_used),
 338        BTRFS_ATTR_PTR(bytes_pinned),
 339        BTRFS_ATTR_PTR(bytes_reserved),
 340        BTRFS_ATTR_PTR(bytes_may_use),
 341        BTRFS_ATTR_PTR(bytes_readonly),
 342        BTRFS_ATTR_PTR(disk_used),
 343        BTRFS_ATTR_PTR(disk_total),
 344        BTRFS_ATTR_PTR(total_bytes_pinned),
 345        NULL,
 346};
 347
 348static void space_info_release(struct kobject *kobj)
 349{
 350        struct btrfs_space_info *sinfo = to_space_info(kobj);
 351        percpu_counter_destroy(&sinfo->total_bytes_pinned);
 352        kfree(sinfo);
 353}
 354
 355struct kobj_type space_info_ktype = {
 356        .sysfs_ops = &kobj_sysfs_ops,
 357        .release = space_info_release,
 358        .default_attrs = space_info_attrs,
 359};
 360
 361static const struct attribute *allocation_attrs[] = {
 362        BTRFS_ATTR_PTR(global_rsv_reserved),
 363        BTRFS_ATTR_PTR(global_rsv_size),
 364        NULL,
 365};
 366
 367static ssize_t btrfs_label_show(struct kobject *kobj,
 368                                struct kobj_attribute *a, char *buf)
 369{
 370        struct btrfs_fs_info *fs_info = to_fs_info(kobj);
 371        char *label = fs_info->super_copy->label;
 372        ssize_t ret;
 373
 374        spin_lock(&fs_info->super_lock);
 375        ret = snprintf(buf, PAGE_SIZE, label[0] ? "%s\n" : "%s", label);
 376        spin_unlock(&fs_info->super_lock);
 377
 378        return ret;
 379}
 380
 381static ssize_t btrfs_label_store(struct kobject *kobj,
 382                                 struct kobj_attribute *a,
 383                                 const char *buf, size_t len)
 384{
 385        struct btrfs_fs_info *fs_info = to_fs_info(kobj);
 386        size_t p_len;
 387
 388        if (!fs_info)
 389                return -EPERM;
 390
 391        if (fs_info->sb->s_flags & MS_RDONLY)
 392                return -EROFS;
 393
 394        /*
 395         * p_len is the len until the first occurrence of either
 396         * '\n' or '\0'
 397         */
 398        p_len = strcspn(buf, "\n");
 399
 400        if (p_len >= BTRFS_LABEL_SIZE)
 401                return -EINVAL;
 402
 403        spin_lock(&fs_info->super_lock);
 404        memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE);
 405        memcpy(fs_info->super_copy->label, buf, p_len);
 406        spin_unlock(&fs_info->super_lock);
 407
 408        /*
 409         * We don't want to do full transaction commit from inside sysfs
 410         */
 411        btrfs_set_pending(fs_info, COMMIT);
 412        wake_up_process(fs_info->transaction_kthread);
 413
 414        return len;
 415}
 416BTRFS_ATTR_RW(label, btrfs_label_show, btrfs_label_store);
 417
 418static ssize_t btrfs_nodesize_show(struct kobject *kobj,
 419                                struct kobj_attribute *a, char *buf)
 420{
 421        struct btrfs_fs_info *fs_info = to_fs_info(kobj);
 422
 423        return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->nodesize);
 424}
 425
 426BTRFS_ATTR(nodesize, btrfs_nodesize_show);
 427
 428static ssize_t btrfs_sectorsize_show(struct kobject *kobj,
 429                                struct kobj_attribute *a, char *buf)
 430{
 431        struct btrfs_fs_info *fs_info = to_fs_info(kobj);
 432
 433        return snprintf(buf, PAGE_SIZE, "%u\n",
 434                        fs_info->super_copy->sectorsize);
 435}
 436
 437BTRFS_ATTR(sectorsize, btrfs_sectorsize_show);
 438
 439static ssize_t btrfs_clone_alignment_show(struct kobject *kobj,
 440                                struct kobj_attribute *a, char *buf)
 441{
 442        struct btrfs_fs_info *fs_info = to_fs_info(kobj);
 443
 444        return snprintf(buf, PAGE_SIZE, "%u\n",
 445                        fs_info->super_copy->sectorsize);
 446}
 447
 448BTRFS_ATTR(clone_alignment, btrfs_clone_alignment_show);
 449
 450static const struct attribute *btrfs_attrs[] = {
 451        BTRFS_ATTR_PTR(label),
 452        BTRFS_ATTR_PTR(nodesize),
 453        BTRFS_ATTR_PTR(sectorsize),
 454        BTRFS_ATTR_PTR(clone_alignment),
 455        NULL,
 456};
 457
 458static void btrfs_release_fsid_kobj(struct kobject *kobj)
 459{
 460        struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj);
 461
 462        memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject));
 463        complete(&fs_devs->kobj_unregister);
 464}
 465
 466static struct kobj_type btrfs_ktype = {
 467        .sysfs_ops      = &kobj_sysfs_ops,
 468        .release        = btrfs_release_fsid_kobj,
 469};
 470
 471static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj)
 472{
 473        if (kobj->ktype != &btrfs_ktype)
 474                return NULL;
 475        return container_of(kobj, struct btrfs_fs_devices, fsid_kobj);
 476}
 477
 478static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
 479{
 480        if (kobj->ktype != &btrfs_ktype)
 481                return NULL;
 482        return to_fs_devs(kobj)->fs_info;
 483}
 484
 485#define NUM_FEATURE_BITS 64
 486static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13];
 487static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS];
 488
 489static const u64 supported_feature_masks[3] = {
 490        [FEAT_COMPAT]    = BTRFS_FEATURE_COMPAT_SUPP,
 491        [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP,
 492        [FEAT_INCOMPAT]  = BTRFS_FEATURE_INCOMPAT_SUPP,
 493};
 494
 495static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add)
 496{
 497        int set;
 498
 499        for (set = 0; set < FEAT_MAX; set++) {
 500                int i;
 501                struct attribute *attrs[2];
 502                struct attribute_group agroup = {
 503                        .name = "features",
 504                        .attrs = attrs,
 505                };
 506                u64 features = get_features(fs_info, set);
 507                features &= ~supported_feature_masks[set];
 508
 509                if (!features)
 510                        continue;
 511
 512                attrs[1] = NULL;
 513                for (i = 0; i < NUM_FEATURE_BITS; i++) {
 514                        struct btrfs_feature_attr *fa;
 515
 516                        if (!(features & (1ULL << i)))
 517                                continue;
 518
 519                        fa = &btrfs_feature_attrs[set][i];
 520                        attrs[0] = &fa->kobj_attr.attr;
 521                        if (add) {
 522                                int ret;
 523                                ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj,
 524                                                        &agroup);
 525                                if (ret)
 526                                        return ret;
 527                        } else
 528                                sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj,
 529                                                    &agroup);
 530                }
 531
 532        }
 533        return 0;
 534}
 535
 536static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs)
 537{
 538        if (fs_devs->device_dir_kobj) {
 539                kobject_del(fs_devs->device_dir_kobj);
 540                kobject_put(fs_devs->device_dir_kobj);
 541                fs_devs->device_dir_kobj = NULL;
 542        }
 543
 544        if (fs_devs->fsid_kobj.state_initialized) {
 545                kobject_del(&fs_devs->fsid_kobj);
 546                kobject_put(&fs_devs->fsid_kobj);
 547                wait_for_completion(&fs_devs->kobj_unregister);
 548        }
 549}
 550
 551/* when fs_devs is NULL it will remove all fsid kobject */
 552void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs)
 553{
 554        struct list_head *fs_uuids = btrfs_get_fs_uuids();
 555
 556        if (fs_devs) {
 557                __btrfs_sysfs_remove_fsid(fs_devs);
 558                return;
 559        }
 560
 561        list_for_each_entry(fs_devs, fs_uuids, list) {
 562                __btrfs_sysfs_remove_fsid(fs_devs);
 563        }
 564}
 565
 566void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info)
 567{
 568        btrfs_reset_fs_info_ptr(fs_info);
 569
 570        if (fs_info->space_info_kobj) {
 571                sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs);
 572                kobject_del(fs_info->space_info_kobj);
 573                kobject_put(fs_info->space_info_kobj);
 574        }
 575        addrm_unknown_feature_attrs(fs_info, false);
 576        sysfs_remove_group(&fs_info->fs_devices->fsid_kobj, &btrfs_feature_attr_group);
 577        sysfs_remove_files(&fs_info->fs_devices->fsid_kobj, btrfs_attrs);
 578        btrfs_sysfs_rm_device_link(fs_info->fs_devices, NULL);
 579}
 580
 581const char * const btrfs_feature_set_names[3] = {
 582        [FEAT_COMPAT]    = "compat",
 583        [FEAT_COMPAT_RO] = "compat_ro",
 584        [FEAT_INCOMPAT]  = "incompat",
 585};
 586
 587char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags)
 588{
 589        size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */
 590        int len = 0;
 591        int i;
 592        char *str;
 593
 594        str = kmalloc(bufsize, GFP_KERNEL);
 595        if (!str)
 596                return str;
 597
 598        for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) {
 599                const char *name;
 600
 601                if (!(flags & (1ULL << i)))
 602                        continue;
 603
 604                name = btrfs_feature_attrs[set][i].kobj_attr.attr.name;
 605                len += snprintf(str + len, bufsize - len, "%s%s",
 606                                len ? "," : "", name);
 607        }
 608
 609        return str;
 610}
 611
 612static void init_feature_attrs(void)
 613{
 614        struct btrfs_feature_attr *fa;
 615        int set, i;
 616
 617        BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names) !=
 618                     ARRAY_SIZE(btrfs_feature_attrs));
 619        BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names[0]) !=
 620                     ARRAY_SIZE(btrfs_feature_attrs[0]));
 621
 622        memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs));
 623        memset(btrfs_unknown_feature_names, 0,
 624               sizeof(btrfs_unknown_feature_names));
 625
 626        for (i = 0; btrfs_supported_feature_attrs[i]; i++) {
 627                struct btrfs_feature_attr *sfa;
 628                struct attribute *a = btrfs_supported_feature_attrs[i];
 629                int bit;
 630                sfa = attr_to_btrfs_feature_attr(a);
 631                bit = ilog2(sfa->feature_bit);
 632                fa = &btrfs_feature_attrs[sfa->feature_set][bit];
 633
 634                fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name;
 635        }
 636
 637        for (set = 0; set < FEAT_MAX; set++) {
 638                for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) {
 639                        char *name = btrfs_unknown_feature_names[set][i];
 640                        fa = &btrfs_feature_attrs[set][i];
 641
 642                        if (fa->kobj_attr.attr.name)
 643                                continue;
 644
 645                        snprintf(name, 13, "%s:%u",
 646                                 btrfs_feature_set_names[set], i);
 647
 648                        fa->kobj_attr.attr.name = name;
 649                        fa->kobj_attr.attr.mode = S_IRUGO;
 650                        fa->feature_set = set;
 651                        fa->feature_bit = 1ULL << i;
 652                }
 653        }
 654}
 655
 656/* when one_device is NULL, it removes all device links */
 657
 658int btrfs_sysfs_rm_device_link(struct btrfs_fs_devices *fs_devices,
 659                struct btrfs_device *one_device)
 660{
 661        struct hd_struct *disk;
 662        struct kobject *disk_kobj;
 663
 664        if (!fs_devices->device_dir_kobj)
 665                return -EINVAL;
 666
 667        if (one_device && one_device->bdev) {
 668                disk = one_device->bdev->bd_part;
 669                disk_kobj = &part_to_dev(disk)->kobj;
 670
 671                sysfs_remove_link(fs_devices->device_dir_kobj,
 672                                                disk_kobj->name);
 673        }
 674
 675        if (one_device)
 676                return 0;
 677
 678        list_for_each_entry(one_device,
 679                        &fs_devices->devices, dev_list) {
 680                if (!one_device->bdev)
 681                        continue;
 682                disk = one_device->bdev->bd_part;
 683                disk_kobj = &part_to_dev(disk)->kobj;
 684
 685                sysfs_remove_link(fs_devices->device_dir_kobj,
 686                                                disk_kobj->name);
 687        }
 688
 689        return 0;
 690}
 691
 692int btrfs_sysfs_add_device(struct btrfs_fs_devices *fs_devs)
 693{
 694        if (!fs_devs->device_dir_kobj)
 695                fs_devs->device_dir_kobj = kobject_create_and_add("devices",
 696                                                &fs_devs->fsid_kobj);
 697
 698        if (!fs_devs->device_dir_kobj)
 699                return -ENOMEM;
 700
 701        return 0;
 702}
 703
 704int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices,
 705                                struct btrfs_device *one_device)
 706{
 707        int error = 0;
 708        struct btrfs_device *dev;
 709
 710        list_for_each_entry(dev, &fs_devices->devices, dev_list) {
 711                struct hd_struct *disk;
 712                struct kobject *disk_kobj;
 713
 714                if (!dev->bdev)
 715                        continue;
 716
 717                if (one_device && one_device != dev)
 718                        continue;
 719
 720                disk = dev->bdev->bd_part;
 721                disk_kobj = &part_to_dev(disk)->kobj;
 722
 723                error = sysfs_create_link(fs_devices->device_dir_kobj,
 724                                          disk_kobj, disk_kobj->name);
 725                if (error)
 726                        break;
 727        }
 728
 729        return error;
 730}
 731
 732/* /sys/fs/btrfs/ entry */
 733static struct kset *btrfs_kset;
 734
 735/* /sys/kernel/debug/btrfs */
 736static struct dentry *btrfs_debugfs_root_dentry;
 737
 738/* Debugging tunables and exported data */
 739u64 btrfs_debugfs_test;
 740
 741/*
 742 * Can be called by the device discovery thread.
 743 * And parent can be specified for seed device
 744 */
 745int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs,
 746                                struct kobject *parent)
 747{
 748        int error;
 749
 750        init_completion(&fs_devs->kobj_unregister);
 751        fs_devs->fsid_kobj.kset = btrfs_kset;
 752        error = kobject_init_and_add(&fs_devs->fsid_kobj,
 753                                &btrfs_ktype, parent, "%pU", fs_devs->fsid);
 754        return error;
 755}
 756
 757int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info)
 758{
 759        int error;
 760        struct btrfs_fs_devices *fs_devs = fs_info->fs_devices;
 761        struct kobject *fsid_kobj = &fs_devs->fsid_kobj;
 762
 763        btrfs_set_fs_info_ptr(fs_info);
 764
 765        error = btrfs_sysfs_add_device_link(fs_devs, NULL);
 766        if (error)
 767                return error;
 768
 769        error = sysfs_create_files(fsid_kobj, btrfs_attrs);
 770        if (error) {
 771                btrfs_sysfs_rm_device_link(fs_devs, NULL);
 772                return error;
 773        }
 774
 775        error = sysfs_create_group(fsid_kobj,
 776                                   &btrfs_feature_attr_group);
 777        if (error)
 778                goto failure;
 779
 780        error = addrm_unknown_feature_attrs(fs_info, true);
 781        if (error)
 782                goto failure;
 783
 784        fs_info->space_info_kobj = kobject_create_and_add("allocation",
 785                                                  fsid_kobj);
 786        if (!fs_info->space_info_kobj) {
 787                error = -ENOMEM;
 788                goto failure;
 789        }
 790
 791        error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs);
 792        if (error)
 793                goto failure;
 794
 795        return 0;
 796failure:
 797        btrfs_sysfs_remove_mounted(fs_info);
 798        return error;
 799}
 800
 801
 802/*
 803 * Change per-fs features in /sys/fs/btrfs/UUID/features to match current
 804 * values in superblock. Call after any changes to incompat/compat_ro flags
 805 */
 806void btrfs_sysfs_feature_update(struct btrfs_fs_info *fs_info,
 807                u64 bit, enum btrfs_feature_set set)
 808{
 809        struct btrfs_fs_devices *fs_devs;
 810        struct kobject *fsid_kobj;
 811        u64 features;
 812        int ret;
 813
 814        if (!fs_info)
 815                return;
 816
 817        features = get_features(fs_info, set);
 818        ASSERT(bit & supported_feature_masks[set]);
 819
 820        fs_devs = fs_info->fs_devices;
 821        fsid_kobj = &fs_devs->fsid_kobj;
 822
 823        if (!fsid_kobj->state_initialized)
 824                return;
 825
 826        /*
 827         * FIXME: this is too heavy to update just one value, ideally we'd like
 828         * to use sysfs_update_group but some refactoring is needed first.
 829         */
 830        sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group);
 831        ret = sysfs_create_group(fsid_kobj, &btrfs_feature_attr_group);
 832}
 833
 834static int btrfs_init_debugfs(void)
 835{
 836#ifdef CONFIG_DEBUG_FS
 837        btrfs_debugfs_root_dentry = debugfs_create_dir("btrfs", NULL);
 838        if (!btrfs_debugfs_root_dentry)
 839                return -ENOMEM;
 840
 841        /*
 842         * Example code, how to export data through debugfs.
 843         *
 844         * file:        /sys/kernel/debug/btrfs/test
 845         * contents of: btrfs_debugfs_test
 846         */
 847#ifdef CONFIG_BTRFS_DEBUG
 848        debugfs_create_u64("test", S_IRUGO | S_IWUSR, btrfs_debugfs_root_dentry,
 849                        &btrfs_debugfs_test);
 850#endif
 851
 852#endif
 853        return 0;
 854}
 855
 856int btrfs_init_sysfs(void)
 857{
 858        int ret;
 859
 860        btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj);
 861        if (!btrfs_kset)
 862                return -ENOMEM;
 863
 864        ret = btrfs_init_debugfs();
 865        if (ret)
 866                goto out1;
 867
 868        init_feature_attrs();
 869        ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
 870        if (ret)
 871                goto out2;
 872
 873        return 0;
 874out2:
 875        debugfs_remove_recursive(btrfs_debugfs_root_dentry);
 876out1:
 877        kset_unregister(btrfs_kset);
 878
 879        return ret;
 880}
 881
 882void btrfs_exit_sysfs(void)
 883{
 884        sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
 885        kset_unregister(btrfs_kset);
 886        debugfs_remove_recursive(btrfs_debugfs_root_dentry);
 887}
 888
 889