diff options
| author | Dave Kleikamp <shaggy@linux.vnet.ibm.com> | 2009-02-02 13:40:55 -0600 | 
|---|---|---|
| committer | Dave Kleikamp <shaggy@linux.vnet.ibm.com> | 2009-02-02 13:40:55 -0600 | 
| commit | 8db0c5d5ef3ab99fe9e5151872b75f45c4282e3c (patch) | |
| tree | da9759151e00221c58cdd9f4de893c0b08753670 /fs/btrfs/sysfs.c | |
| parent | 1ad53a98c927a9b5b1b57288ac0edec562fbcf8d (diff) | |
| parent | 45c82b5a770be66845687a7d027c8b52946d59af (diff) | |
Merge branch 'master' of /home/shaggy/git/linus-clean/
Diffstat (limited to 'fs/btrfs/sysfs.c')
| -rw-r--r-- | fs/btrfs/sysfs.c | 269 | 
1 files changed, 269 insertions, 0 deletions
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c new file mode 100644 index 000000000000..a240b6fa81df --- /dev/null +++ b/fs/btrfs/sysfs.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2007 Oracle.  All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/completion.h> +#include <linux/buffer_head.h> +#include <linux/module.h> +#include <linux/kobject.h> + +#include "ctree.h" +#include "disk-io.h" +#include "transaction.h" + +static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf) +{ +	return snprintf(buf, PAGE_SIZE, "%llu\n", +		(unsigned long long)btrfs_root_used(&root->root_item)); +} + +static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf) +{ +	return snprintf(buf, PAGE_SIZE, "%llu\n", +		(unsigned long long)btrfs_root_limit(&root->root_item)); +} + +static ssize_t super_blocks_used_show(struct btrfs_fs_info *fs, char *buf) +{ + +	return snprintf(buf, PAGE_SIZE, "%llu\n", +		(unsigned long long)btrfs_super_bytes_used(&fs->super_copy)); +} + +static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf) +{ +	return snprintf(buf, PAGE_SIZE, "%llu\n", +		(unsigned long long)btrfs_super_total_bytes(&fs->super_copy)); +} + +static ssize_t super_blocksize_show(struct btrfs_fs_info *fs, char *buf) +{ +	return snprintf(buf, PAGE_SIZE, "%llu\n", +		(unsigned long long)btrfs_super_sectorsize(&fs->super_copy)); +} + +/* this is for root attrs (subvols/snapshots) */ +struct btrfs_root_attr { +	struct attribute attr; +	ssize_t (*show)(struct btrfs_root *, char *); +	ssize_t (*store)(struct btrfs_root *, const char *, size_t); +}; + +#define ROOT_ATTR(name, mode, show, store) \ +static struct btrfs_root_attr btrfs_root_attr_##name = __ATTR(name, mode, \ +							      show, store) + +ROOT_ATTR(blocks_used,	0444,	root_blocks_used_show,	NULL); +ROOT_ATTR(block_limit,	0644,	root_block_limit_show,	NULL); + +static struct attribute *btrfs_root_attrs[] = { +	&btrfs_root_attr_blocks_used.attr, +	&btrfs_root_attr_block_limit.attr, +	NULL, +}; + +/* this is for super attrs (actual full fs) */ +struct btrfs_super_attr { +	struct attribute attr; +	ssize_t (*show)(struct btrfs_fs_info *, char *); +	ssize_t (*store)(struct btrfs_fs_info *, const char *, size_t); +}; + +#define SUPER_ATTR(name, mode, show, store) \ +static struct btrfs_super_attr btrfs_super_attr_##name = __ATTR(name, mode, \ +								show, store) + +SUPER_ATTR(blocks_used,		0444,	super_blocks_used_show,		NULL); +SUPER_ATTR(total_blocks,	0444,	super_total_blocks_show,	NULL); +SUPER_ATTR(blocksize,		0444,	super_blocksize_show,		NULL); + +static struct attribute *btrfs_super_attrs[] = { +	&btrfs_super_attr_blocks_used.attr, +	&btrfs_super_attr_total_blocks.attr, +	&btrfs_super_attr_blocksize.attr, +	NULL, +}; + +static ssize_t btrfs_super_attr_show(struct kobject *kobj, +				    struct attribute *attr, char *buf) +{ +	struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, +						super_kobj); +	struct btrfs_super_attr *a = container_of(attr, +						  struct btrfs_super_attr, +						  attr); + +	return a->show ? a->show(fs, buf) : 0; +} + +static ssize_t btrfs_super_attr_store(struct kobject *kobj, +				     struct attribute *attr, +				     const char *buf, size_t len) +{ +	struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, +						super_kobj); +	struct btrfs_super_attr *a = container_of(attr, +						  struct btrfs_super_attr, +						  attr); + +	return a->store ? a->store(fs, buf, len) : 0; +} + +static ssize_t btrfs_root_attr_show(struct kobject *kobj, +				    struct attribute *attr, char *buf) +{ +	struct btrfs_root *root = container_of(kobj, struct btrfs_root, +						root_kobj); +	struct btrfs_root_attr *a = container_of(attr, +						 struct btrfs_root_attr, +						 attr); + +	return a->show ? a->show(root, buf) : 0; +} + +static ssize_t btrfs_root_attr_store(struct kobject *kobj, +				     struct attribute *attr, +				     const char *buf, size_t len) +{ +	struct btrfs_root *root = container_of(kobj, struct btrfs_root, +						root_kobj); +	struct btrfs_root_attr *a = container_of(attr, +						 struct btrfs_root_attr, +						 attr); +	return a->store ? a->store(root, buf, len) : 0; +} + +static void btrfs_super_release(struct kobject *kobj) +{ +	struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, +						super_kobj); +	complete(&fs->kobj_unregister); +} + +static void btrfs_root_release(struct kobject *kobj) +{ +	struct btrfs_root *root = container_of(kobj, struct btrfs_root, +						root_kobj); +	complete(&root->kobj_unregister); +} + +static struct sysfs_ops btrfs_super_attr_ops = { +	.show	= btrfs_super_attr_show, +	.store	= btrfs_super_attr_store, +}; + +static struct sysfs_ops btrfs_root_attr_ops = { +	.show	= btrfs_root_attr_show, +	.store	= btrfs_root_attr_store, +}; + +static struct kobj_type btrfs_root_ktype = { +	.default_attrs	= btrfs_root_attrs, +	.sysfs_ops	= &btrfs_root_attr_ops, +	.release	= btrfs_root_release, +}; + +static struct kobj_type btrfs_super_ktype = { +	.default_attrs	= btrfs_super_attrs, +	.sysfs_ops	= &btrfs_super_attr_ops, +	.release	= btrfs_super_release, +}; + +/* /sys/fs/btrfs/ entry */ +static struct kset *btrfs_kset; + +int btrfs_sysfs_add_super(struct btrfs_fs_info *fs) +{ +	int error; +	char *name; +	char c; +	int len = strlen(fs->sb->s_id) + 1; +	int i; + +	name = kmalloc(len, GFP_NOFS); +	if (!name) { +		error = -ENOMEM; +		goto fail; +	} + +	for (i = 0; i < len; i++) { +		c = fs->sb->s_id[i]; +		if (c == '/' || c == '\\') +			c = '!'; +		name[i] = c; +	} +	name[len] = '\0'; + +	fs->super_kobj.kset = btrfs_kset; +	error = kobject_init_and_add(&fs->super_kobj, &btrfs_super_ktype, +				     NULL, "%s", name); +	kfree(name); +	if (error) +		goto fail; + +	return 0; + +fail: +	printk(KERN_ERR "btrfs: sysfs creation for super failed\n"); +	return error; +} + +int btrfs_sysfs_add_root(struct btrfs_root *root) +{ +	int error; + +	error = kobject_init_and_add(&root->root_kobj, &btrfs_root_ktype, +				     &root->fs_info->super_kobj, +				     "%s", root->name); +	if (error) +		goto fail; + +	return 0; + +fail: +	printk(KERN_ERR "btrfs: sysfs creation for root failed\n"); +	return error; +} + +void btrfs_sysfs_del_root(struct btrfs_root *root) +{ +	kobject_put(&root->root_kobj); +	wait_for_completion(&root->kobj_unregister); +} + +void btrfs_sysfs_del_super(struct btrfs_fs_info *fs) +{ +	kobject_put(&fs->super_kobj); +	wait_for_completion(&fs->kobj_unregister); +} + +int btrfs_init_sysfs(void) +{ +	btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); +	if (!btrfs_kset) +		return -ENOMEM; +	return 0; +} + +void btrfs_exit_sysfs(void) +{ +	kset_unregister(btrfs_kset); +} +  | 
