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/module.h>
  25#include <linux/kobject.h>
  26
  27#include "ctree.h"
  28#include "disk-io.h"
  29#include "transaction.h"
  30
  31static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf)
  32{
  33        return snprintf(buf, PAGE_SIZE, "%llu\n",
  34                (unsigned long long)btrfs_root_used(&root->root_item));
  35}
  36
  37static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf)
  38{
  39        return snprintf(buf, PAGE_SIZE, "%llu\n",
  40                (unsigned long long)btrfs_root_limit(&root->root_item));
  41}
  42
  43static ssize_t super_blocks_used_show(struct btrfs_fs_info *fs, char *buf)
  44{
  45
  46        return snprintf(buf, PAGE_SIZE, "%llu\n",
  47                (unsigned long long)btrfs_super_bytes_used(&fs->super_copy));
  48}
  49
  50static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf)
  51{
  52        return snprintf(buf, PAGE_SIZE, "%llu\n",
  53                (unsigned long long)btrfs_super_total_bytes(&fs->super_copy));
  54}
  55
  56static ssize_t super_blocksize_show(struct btrfs_fs_info *fs, char *buf)
  57{
  58        return snprintf(buf, PAGE_SIZE, "%llu\n",
  59                (unsigned long long)btrfs_super_sectorsize(&fs->super_copy));
  60}
  61
  62/* this is for root attrs (subvols/snapshots) */
  63struct btrfs_root_attr {
  64        struct attribute attr;
  65        ssize_t (*show)(struct btrfs_root *, char *);
  66        ssize_t (*store)(struct btrfs_root *, const char *, size_t);
  67};
  68
  69#define ROOT_ATTR(name, mode, show, store) \
  70static struct btrfs_root_attr btrfs_root_attr_##name = __ATTR(name, mode, \
  71                                                              show, store)
  72
  73ROOT_ATTR(blocks_used,  0444,   root_blocks_used_show,  NULL);
  74ROOT_ATTR(block_limit,  0644,   root_block_limit_show,  NULL);
  75
  76static struct attribute *btrfs_root_attrs[] = {
  77        &btrfs_root_attr_blocks_used.attr,
  78        &btrfs_root_attr_block_limit.attr,
  79        NULL,
  80};
  81
  82/* this is for super attrs (actual full fs) */
  83struct btrfs_super_attr {
  84        struct attribute attr;
  85        ssize_t (*show)(struct btrfs_fs_info *, char *);
  86        ssize_t (*store)(struct btrfs_fs_info *, const char *, size_t);
  87};
  88
  89#define SUPER_ATTR(name, mode, show, store) \
  90static struct btrfs_super_attr btrfs_super_attr_##name = __ATTR(name, mode, \
  91                                                                show, store)
  92
  93SUPER_ATTR(blocks_used,         0444,   super_blocks_used_show,         NULL);
  94SUPER_ATTR(total_blocks,        0444,   super_total_blocks_show,        NULL);
  95SUPER_ATTR(blocksize,           0444,   super_blocksize_show,           NULL);
  96
  97static struct attribute *btrfs_super_attrs[] = {
  98        &btrfs_super_attr_blocks_used.attr,
  99        &btrfs_super_attr_total_blocks.attr,
 100        &btrfs_super_attr_blocksize.attr,
 101        NULL,
 102};
 103
 104static ssize_t btrfs_super_attr_show(struct kobject *kobj,
 105                                    struct attribute *attr, char *buf)
 106{
 107        struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info,
 108                                                super_kobj);
 109        struct btrfs_super_attr *a = container_of(attr,
 110                                                  struct btrfs_super_attr,
 111                                                  attr);
 112
 113        return a->show ? a->show(fs, buf) : 0;
 114}
 115
 116static ssize_t btrfs_super_attr_store(struct kobject *kobj,
 117                                     struct attribute *attr,
 118                                     const char *buf, size_t len)
 119{
 120        struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info,
 121                                                super_kobj);
 122        struct btrfs_super_attr *a = container_of(attr,
 123                                                  struct btrfs_super_attr,
 124                                                  attr);
 125
 126        return a->store ? a->store(fs, buf, len) : 0;
 127}
 128
 129static ssize_t btrfs_root_attr_show(struct kobject *kobj,
 130                                    struct attribute *attr, char *buf)
 131{
 132        struct btrfs_root *root = container_of(kobj, struct btrfs_root,
 133                                                root_kobj);
 134        struct btrfs_root_attr *a = container_of(attr,
 135                                                 struct btrfs_root_attr,
 136                                                 attr);
 137
 138        return a->show ? a->show(root, buf) : 0;
 139}
 140
 141static ssize_t btrfs_root_attr_store(struct kobject *kobj,
 142                                     struct attribute *attr,
 143                                     const char *buf, size_t len)
 144{
 145        struct btrfs_root *root = container_of(kobj, struct btrfs_root,
 146                                                root_kobj);
 147        struct btrfs_root_attr *a = container_of(attr,
 148                                                 struct btrfs_root_attr,
 149                                                 attr);
 150        return a->store ? a->store(root, buf, len) : 0;
 151}
 152
 153static void btrfs_super_release(struct kobject *kobj)
 154{
 155        struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info,
 156                                                super_kobj);
 157        complete(&fs->kobj_unregister);
 158}
 159
 160static void btrfs_root_release(struct kobject *kobj)
 161{
 162        struct btrfs_root *root = container_of(kobj, struct btrfs_root,
 163                                                root_kobj);
 164        complete(&root->kobj_unregister);
 165}
 166
 167static struct sysfs_ops btrfs_super_attr_ops = {
 168        .show   = btrfs_super_attr_show,
 169        .store  = btrfs_super_attr_store,
 170};
 171
 172static struct sysfs_ops btrfs_root_attr_ops = {
 173        .show   = btrfs_root_attr_show,
 174        .store  = btrfs_root_attr_store,
 175};
 176
 177static struct kobj_type btrfs_root_ktype = {
 178        .default_attrs  = btrfs_root_attrs,
 179        .sysfs_ops      = &btrfs_root_attr_ops,
 180        .release        = btrfs_root_release,
 181};
 182
 183static struct kobj_type btrfs_super_ktype = {
 184        .default_attrs  = btrfs_super_attrs,
 185        .sysfs_ops      = &btrfs_super_attr_ops,
 186        .release        = btrfs_super_release,
 187};
 188
 189/* /sys/fs/btrfs/ entry */
 190static struct kset *btrfs_kset;
 191
 192int btrfs_sysfs_add_super(struct btrfs_fs_info *fs)
 193{
 194        int error;
 195        char *name;
 196        char c;
 197        int len = strlen(fs->sb->s_id) + 1;
 198        int i;
 199
 200        name = kmalloc(len, GFP_NOFS);
 201        if (!name) {
 202                error = -ENOMEM;
 203                goto fail;
 204        }
 205
 206        for (i = 0; i < len; i++) {
 207                c = fs->sb->s_id[i];
 208                if (c == '/' || c == '\\')
 209                        c = '!';
 210                name[i] = c;
 211        }
 212        name[len] = '\0';
 213
 214        fs->super_kobj.kset = btrfs_kset;
 215        error = kobject_init_and_add(&fs->super_kobj, &btrfs_super_ktype,
 216                                     NULL, "%s", name);
 217        kfree(name);
 218        if (error)
 219                goto fail;
 220
 221        return 0;
 222
 223fail:
 224        printk(KERN_ERR "btrfs: sysfs creation for super failed\n");
 225        return error;
 226}
 227
 228int btrfs_sysfs_add_root(struct btrfs_root *root)
 229{
 230        int error;
 231
 232        error = kobject_init_and_add(&root->root_kobj, &btrfs_root_ktype,
 233                                     &root->fs_info->super_kobj,
 234                                     "%s", root->name);
 235        if (error)
 236                goto fail;
 237
 238        return 0;
 239
 240fail:
 241        printk(KERN_ERR "btrfs: sysfs creation for root failed\n");
 242        return error;
 243}
 244
 245void btrfs_sysfs_del_root(struct btrfs_root *root)
 246{
 247        kobject_put(&root->root_kobj);
 248        wait_for_completion(&root->kobj_unregister);
 249}
 250
 251void btrfs_sysfs_del_super(struct btrfs_fs_info *fs)
 252{
 253        kobject_put(&fs->super_kobj);
 254        wait_for_completion(&fs->kobj_unregister);
 255}
 256
 257int btrfs_init_sysfs(void)
 258{
 259        btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj);
 260        if (!btrfs_kset)
 261                return -ENOMEM;
 262        return 0;
 263}
 264
 265void btrfs_exit_sysfs(void)
 266{
 267        kset_unregister(btrfs_kset);
 268}
 269
 270