mount.c 4.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
/* -*- mode: c; c-basic-offset: 8; -*-
 * vim: noexpandtab sw=8 ts=8 sts=0:
 *
 * mount.c - operations for initializing and mounting configfs.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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.
 *
 * Based on sysfs:
 * 	sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
 *
 * configfs Copyright (C) 2005 Oracle.  All rights reserved.
 */

#include <linux/fs.h>
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/pagemap.h>
#include <linux/init.h>

#include <linux/configfs.h>
#include "configfs_internal.h"

/* Random magic number */
#define CONFIGFS_MAGIC 0x62656570

struct vfsmount * configfs_mount = NULL;
struct super_block * configfs_sb = NULL;
41
kmem_cache_t *configfs_dir_cachep;
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
static int configfs_mnt_count = 0;

static struct super_operations configfs_ops = {
	.statfs		= simple_statfs,
	.drop_inode	= generic_delete_inode,
};

static struct config_group configfs_root_group = {
	.cg_item = {
		.ci_namebuf	= "root",
		.ci_name	= configfs_root_group.cg_item.ci_namebuf,
	},
};

int configfs_is_root(struct config_item *item)
{
	return item == &configfs_root_group.cg_item;
}

static struct configfs_dirent configfs_root = {
	.s_sibling	= LIST_HEAD_INIT(configfs_root.s_sibling),
	.s_children	= LIST_HEAD_INIT(configfs_root.s_children),
	.s_element	= &configfs_root_group.cg_item,
	.s_type		= CONFIGFS_ROOT,
66
	.s_iattr	= NULL,
67 68 69 70 71 72 73 74 75 76 77
};

static int configfs_fill_super(struct super_block *sb, void *data, int silent)
{
	struct inode *inode;
	struct dentry *root;

	sb->s_blocksize = PAGE_CACHE_SIZE;
	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
	sb->s_magic = CONFIGFS_MAGIC;
	sb->s_op = &configfs_ops;
78
	sb->s_time_gran = 1;
79 80
	configfs_sb = sb;

81 82
	inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
				   &configfs_root);
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
	if (inode) {
		inode->i_op = &configfs_dir_inode_operations;
		inode->i_fop = &configfs_dir_operations;
		/* directory inodes start off with i_nlink == 2 (for "." entry) */
		inode->i_nlink++;
	} else {
		pr_debug("configfs: could not get root inode\n");
		return -ENOMEM;
	}

	root = d_alloc_root(inode);
	if (!root) {
		pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
		iput(inode);
		return -ENOMEM;
	}
	config_group_init(&configfs_root_group);
	configfs_root_group.cg_item.ci_dentry = root;
	root->d_fsdata = &configfs_root;
	sb->s_root = root;
	return 0;
}

static struct super_block *configfs_get_sb(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data)
{
	return get_sb_single(fs_type, flags, data, configfs_fill_super);
}

static struct file_system_type configfs_fs_type = {
	.owner		= THIS_MODULE,
	.name		= "configfs",
	.get_sb		= configfs_get_sb,
	.kill_sb	= kill_litter_super,
};

int configfs_pin_fs(void)
{
	return simple_pin_fs("configfs", &configfs_mount,
			     &configfs_mnt_count);
}

void configfs_release_fs(void)
{
	simple_release_fs(&configfs_mount, &configfs_mnt_count);
}


static decl_subsys(config, NULL, NULL);

static int __init configfs_init(void)
{
135 136 137 138 139 140 141
	int err = -ENOMEM;

	configfs_dir_cachep = kmem_cache_create("configfs_dir_cache",
						sizeof(struct configfs_dirent),
						0, 0, NULL, NULL);
	if (!configfs_dir_cachep)
		goto out;
142 143 144

	kset_set_kset_s(&config_subsys, kernel_subsys);
	err = subsystem_register(&config_subsys);
145 146 147 148 149
	if (err) {
		kmem_cache_destroy(configfs_dir_cachep);
		configfs_dir_cachep = NULL;
		goto out;
	}
150 151 152 153 154

	err = register_filesystem(&configfs_fs_type);
	if (err) {
		printk(KERN_ERR "configfs: Unable to register filesystem!\n");
		subsystem_unregister(&config_subsys);
155 156
		kmem_cache_destroy(configfs_dir_cachep);
		configfs_dir_cachep = NULL;
157 158
	}

159
out:
160 161 162 163 164 165 166
	return err;
}

static void __exit configfs_exit(void)
{
	unregister_filesystem(&configfs_fs_type);
	subsystem_unregister(&config_subsys);
167 168
	kmem_cache_destroy(configfs_dir_cachep);
	configfs_dir_cachep = NULL;
169 170 171 172
}

MODULE_AUTHOR("Oracle");
MODULE_LICENSE("GPL");
173
MODULE_VERSION("0.0.2");
174 175 176 177
MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration.");

module_init(configfs_init);
module_exit(configfs_exit);