lkml.org 
[lkml]   [2004]   [Nov]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] CKRM: 4/10 CKRM: Full rcfs support
    Date
    Updates CKRM Resource Control Filesystem (rcfs) to include full
    directory structure support.

    Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
    Signed-Off-By: Hubertus Franke <frankeh@us.ibm.com>
    Signed-Off-By: Shailabh Nagar <nagar@us.ibm.com>
    Signed-Off-By: Vivek Kashyap <vivk@us.ibm.com>
    Signed-Off-By: Gerrit Huizenga <gh@us.ibm.com>


    Index: linux-2.6.10-rc2/fs/Makefile
    ===================================================================
    --- linux-2.6.10-rc2.orig/fs/Makefile 2004-11-14 17:27:52.000000000 -0800
    +++ linux-2.6.10-rc2/fs/Makefile 2004-11-19 20:44:18.255709415 -0800
    @@ -92,5 +92,6 @@
    obj-$(CONFIG_XFS_FS) += xfs/
    obj-$(CONFIG_AFS_FS) += afs/
    obj-$(CONFIG_BEFS_FS) += befs/
    +obj-$(CONFIG_RCFS_FS) += rcfs/
    obj-$(CONFIG_HOSTFS) += hostfs/
    obj-$(CONFIG_HPPFS) += hppfs/
    Index: linux-2.6.10-rc2/fs/rcfs/dir.c
    ===================================================================
    --- /dev/null 1970-01-01 00:00:00.000000000 +0000
    +++ linux-2.6.10-rc2/fs/rcfs/dir.c 2004-11-19 20:44:18.261708464 -0800
    @@ -0,0 +1,300 @@
    +/*
    + * fs/rcfs/dir.c
    + *
    + * Copyright (C) Shailabh Nagar, IBM Corp. 2004
    + * Vivek Kashyap, IBM Corp. 2004
    + *
    + *
    + * Directory operations for rcfs
    + *
    + * Latest version, more details at http://ckrm.sf.net
    + *
    + * 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.
    + *
    + */
    +
    +/*
    + * Changes
    + *
    + * 08 Mar 2004
    + * Created.
    + */
    +
    +#include <linux/module.h>
    +#include <linux/fs.h>
    +#include <linux/namei.h>
    +#include <linux/namespace.h>
    +#include <linux/dcache.h>
    +#include <linux/seq_file.h>
    +#include <linux/pagemap.h>
    +#include <linux/highmem.h>
    +#include <linux/init.h>
    +#include <linux/string.h>
    +#include <linux/smp_lock.h>
    +#include <linux/backing-dev.h>
    +#include <linux/parser.h>
    +
    +#include <asm/uaccess.h>
    +
    +#include <linux/rcfs.h>
    +
    +#define rcfs_positive(dentry) ((dentry)->d_inode && !d_unhashed((dentry)))
    +
    +int rcfs_empty(struct dentry *dentry)
    +{
    + struct dentry *child;
    + int ret = 0;
    +
    + spin_lock(&dcache_lock);
    + list_for_each_entry(child, &dentry->d_subdirs, d_child)
    + if (!rcfs_is_magic(child) && rcfs_positive(child))
    + goto out;
    + ret = 1;
    +out:
    + spin_unlock(&dcache_lock);
    + return ret;
    +}
    +
    +/* Directory inode operations */
    +
    +int
    +rcfs_create(struct inode *dir, struct dentry *dentry, int mode,
    + struct nameidata *nd)
    +{
    + return rcfs_mknod(dir, dentry, mode | S_IFREG, 0);
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_create);
    +
    +/* Symlinks permitted ?? */
    +int rcfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
    +{
    + struct inode *inode;
    + int error = -ENOSPC;
    +
    + inode = rcfs_get_inode(dir->i_sb, S_IFLNK | S_IRWXUGO, 0);
    + if (inode) {
    + int l = strlen(symname) + 1;
    + error = page_symlink(inode, symname, l);
    + if (!error) {
    + if (dir->i_mode & S_ISGID)
    + inode->i_gid = dir->i_gid;
    + d_instantiate(dentry, inode);
    + dget(dentry);
    + } else
    + iput(inode);
    + }
    + return error;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_symlink);
    +
    +int rcfs_create_coredir(struct inode *dir, struct dentry *dentry)
    +{
    +
    + struct rcfs_inode_info *ripar, *ridir;
    + int sz;
    +
    + ripar = RCFS_I(dir);
    + ridir = RCFS_I(dentry->d_inode);
    + /* Inform resource controllers - do Core operations */
    + if (ckrm_is_core_valid(ripar->core)) {
    + sz = strlen(ripar->name) + strlen(dentry->d_name.name) + 2;
    + ridir->name = kmalloc(sz, GFP_KERNEL);
    + if (!ridir->name) {
    + return -ENOMEM;
    + }
    + snprintf(ridir->name, sz, "%s/%s", ripar->name,
    + dentry->d_name.name);
    + ridir->core = (*(ripar->core->classtype->alloc))
    + (ripar->core, ridir->name);
    + } else {
    + printk(KERN_ERR "rcfs_mkdir: Invalid parent core %p\n",
    + ripar->core);
    + return -EINVAL;
    + }
    +
    + return 0;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_create_coredir);
    +
    +int rcfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
    +{
    +
    + int retval = 0;
    + ckrm_classtype_t *clstype;
    +
    +#if 0
    + struct dentry *pd = list_entry(dir->i_dentry.next, struct dentry,
    + d_alias);
    + if ((!strcmp(pd->d_name.name, "/") &&
    + !strcmp(dentry->d_name.name, "ce"))) {
    + /* Call CE's mkdir if it has registered, else fail. */
    + if (rcfs_eng_callbacks.mkdir) {
    + return (*rcfs_eng_callbacks.mkdir) (dir, dentry, mode);
    + } else {
    + return -EINVAL;
    + }
    + }
    +#endif
    + if (_rcfs_mknod(dir, dentry, mode | S_IFDIR, 0)) {
    + printk(KERN_ERR "rcfs_mkdir: error in _rcfs_mknod\n");
    + return retval;
    + }
    + dir->i_nlink++;
    + /* Inherit parent's ops since _rcfs_mknod assigns noperm ops. */
    + dentry->d_inode->i_op = dir->i_op;
    + dentry->d_inode->i_fop = dir->i_fop;
    + retval = rcfs_create_coredir(dir, dentry);
    + if (retval) {
    + simple_rmdir(dir, dentry);
    + return retval;
    + }
    + /* create the default set of magic files */
    + clstype = (RCFS_I(dentry->d_inode))->core->classtype;
    + rcfs_create_magic(dentry, &(((struct rcfs_magf *)clstype->mfdesc)[1]),
    + clstype->mfcount - 3);
    + return retval;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_mkdir);
    +
    +int rcfs_rmdir(struct inode *dir, struct dentry *dentry)
    +{
    + struct rcfs_inode_info *ri = RCFS_I(dentry->d_inode);
    +
    +#if 0
    + struct dentry *pd = list_entry(dir->i_dentry.next,
    + struct dentry, d_alias);
    + if ((!strcmp(pd->d_name.name, "/") &&
    + !strcmp(dentry->d_name.name, "ce"))) {
    + // Call CE's mkdir if it has registered, else fail.
    + if (rcfs_eng_callbacks.rmdir) {
    + return (*rcfs_eng_callbacks.rmdir) (dir, dentry);
    + } else {
    + return simple_rmdir(dir, dentry);
    + }
    + } else if ((!strcmp(pd->d_name.name, "/") &&
    + !strcmp(dentry->d_name.name, "network"))) {
    + return -EPERM;
    + }
    +#endif
    + if (!rcfs_empty(dentry)) {
    + printk(KERN_ERR "rcfs_rmdir: directory not empty\n");
    + return -ENOTEMPTY;
    + }
    + /* Core class removal */
    +
    + if (ri->core == NULL) {
    + printk(KERN_ERR "rcfs_rmdir: core==NULL\n");
    + // likely a race condition
    + return 0;
    + }
    +
    + if ((*(ri->core->classtype->free)) (ri->core)) {
    + printk(KERN_ERR "rcfs_rmdir: ckrm_free_core_class failed\n");
    + goto out;
    + }
    + ri->core = NULL; // just to be safe
    +
    + /* Clear magic files only after core successfully removed */
    + rcfs_clear_magic(dentry);
    +
    + return simple_rmdir(dir, dentry);
    +
    +out:
    + return -EBUSY;
    +}
    +
    +EXPORT_SYMBOL(rcfs_rmdir);
    +
    +int rcfs_unlink(struct inode *dir, struct dentry *dentry)
    +{
    + // -ENOENT and not -ENOPERM to allow rm -rf to work despite
    + // magic files being present
    + return -ENOENT;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_unlink);
    +
    +/* rename is allowed on directories only */
    +int
    +rcfs_rename(struct inode *old_dir, struct dentry *old_dentry,
    + struct inode *new_dir, struct dentry *new_dentry)
    +{
    + if (S_ISDIR(old_dentry->d_inode->i_mode))
    + return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
    + else
    + return -EINVAL;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_rename);
    +
    +struct inode_operations rcfs_dir_inode_operations = {
    + .create = rcfs_create,
    + .lookup = simple_lookup,
    + .link = simple_link,
    + .unlink = rcfs_unlink,
    + .symlink = rcfs_symlink,
    + .mkdir = rcfs_mkdir,
    + .rmdir = rcfs_rmdir,
    + .mknod = rcfs_mknod,
    + .rename = rcfs_rename,
    +};
    +
    +int
    +rcfs_root_create(struct inode *dir, struct dentry *dentry, int mode,
    + struct nameidata *nd)
    +{
    + return -EPERM;
    +}
    +
    +int
    +rcfs_root_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
    +{
    + return -EPERM;
    +}
    +
    +int rcfs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)
    +{
    + return -EPERM;
    +}
    +
    +int rcfs_root_rmdir(struct inode *dir, struct dentry *dentry)
    +{
    + return -EPERM;
    +}
    +
    +int rcfs_root_unlink(struct inode *dir, struct dentry *dentry)
    +{
    + return -EPERM;
    +}
    +
    +int
    +rcfs_root_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
    +{
    + return -EPERM;
    +}
    +
    +int
    +rcfs_root_rename(struct inode *old_dir, struct dentry *old_dentry,
    + struct inode *new_dir, struct dentry *new_dentry)
    +{
    + return -EPERM;
    +}
    +
    +struct inode_operations rcfs_rootdir_inode_operations = {
    + .create = rcfs_root_create,
    + .lookup = simple_lookup,
    + .link = simple_link,
    + .unlink = rcfs_root_unlink,
    + .symlink = rcfs_root_symlink,
    + .mkdir = rcfs_root_mkdir,
    + .rmdir = rcfs_root_rmdir,
    + .mknod = rcfs_root_mknod,
    + .rename = rcfs_root_rename,
    +};
    Index: linux-2.6.10-rc2/fs/rcfs/inode.c
    ===================================================================
    --- /dev/null 1970-01-01 00:00:00.000000000 +0000
    +++ linux-2.6.10-rc2/fs/rcfs/inode.c 2004-11-19 20:44:18.265707831 -0800
    @@ -0,0 +1,189 @@
    +/*
    + * fs/rcfs/inode.c
    + *
    + * Copyright (C) Shailabh Nagar, IBM Corp. 2004
    + * Vivek Kashyap, IBM Corp. 2004
    + *
    + * Resource class filesystem (rcfs) forming the
    + * user interface to Class-based Kernel Resource Management (CKRM).
    + *
    + * Latest version, more details at http://ckrm.sf.net
    + *
    + * 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.
    + *
    + */
    +
    +/* Changes
    + *
    + * 05 Mar 2004
    + * Created.
    + * 06 Mar 2004
    + * Parsing for shares added
    + */
    +
    +#include <linux/module.h>
    +#include <linux/list.h>
    +#include <linux/fs.h>
    +#include <linux/namei.h>
    +#include <linux/namespace.h>
    +#include <linux/dcache.h>
    +#include <linux/seq_file.h>
    +#include <linux/pagemap.h>
    +#include <linux/highmem.h>
    +#include <linux/init.h>
    +#include <linux/string.h>
    +#include <linux/smp_lock.h>
    +#include <linux/backing-dev.h>
    +#include <linux/parser.h>
    +#include <asm/uaccess.h>
    +
    +#include <linux/rcfs.h>
    +
    +/*
    + * Address of variable used as flag to indicate a magic file,
    + * value unimportant
    + */
    +int RCFS_IS_MAGIC;
    +
    +struct inode *rcfs_get_inode(struct super_block *sb, int mode, dev_t dev)
    +{
    + struct inode *inode = new_inode(sb);
    +
    + if (inode) {
    + inode->i_mode = mode;
    + inode->i_uid = current->fsuid;
    + inode->i_gid = current->fsgid;
    + inode->i_blksize = PAGE_CACHE_SIZE;
    + inode->i_blocks = 0;
    + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
    + switch (mode & S_IFMT) {
    + default:
    + init_special_inode(inode, mode, dev);
    + break;
    + case S_IFREG:
    + /* Treat as default assignment */
    + inode->i_op = &rcfs_file_inode_operations;
    + /* inode->i_fop = &rcfs_file_operations; */
    + break;
    + case S_IFDIR:
    + /* inode->i_op = &rcfs_dir_inode_operations; */
    + inode->i_op = &rcfs_rootdir_inode_operations;
    + inode->i_fop = &simple_dir_operations;
    +
    + /*
    + * directory inodes start off with i_nlink == 2
    + * (for "." entry)
    + */
    + inode->i_nlink++;
    + break;
    + case S_IFLNK:
    + inode->i_op = &page_symlink_inode_operations;
    + break;
    + }
    + }
    + return inode;
    +}
    +
    +int _rcfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
    +{
    + struct inode *inode;
    + int error = -EPERM;
    +
    + if (dentry->d_inode)
    + return -EEXIST;
    + inode = rcfs_get_inode(dir->i_sb, mode, dev);
    + if (inode) {
    + if (dir->i_mode & S_ISGID) {
    + inode->i_gid = dir->i_gid;
    + if (S_ISDIR(mode))
    + inode->i_mode |= S_ISGID;
    + }
    + d_instantiate(dentry, inode);
    + dget(dentry);
    + error = 0;
    + }
    + return error;
    +}
    +
    +EXPORT_SYMBOL_GPL(_rcfs_mknod);
    +
    +int rcfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
    +{
    + /* User can only create directories, not files */
    + if ((mode & S_IFMT) != S_IFDIR)
    + return -EINVAL;
    +
    + return dir->i_op->mkdir(dir, dentry, mode);
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_mknod);
    +
    +struct dentry *rcfs_create_internal(struct dentry *parent,
    + struct rcfs_magf *magf, int magic)
    +{
    + struct qstr qstr;
    + struct dentry *mfdentry;
    +
    + /* Get new dentry for name */
    + qstr.name = magf->name;
    + qstr.len = strlen(magf->name);
    + qstr.hash = full_name_hash(magf->name, qstr.len);
    + mfdentry = lookup_hash(&qstr, parent);
    +
    + if (!IS_ERR(mfdentry)) {
    + int err;
    +
    + down(&parent->d_inode->i_sem);
    + if (magic && (magf->mode & S_IFDIR))
    + err = parent->d_inode->i_op->mkdir(parent->d_inode,
    + mfdentry,
    + magf->mode);
    + else {
    + err = _rcfs_mknod(parent->d_inode, mfdentry,
    + magf->mode, 0);
    + /*
    + * _rcfs_mknod doesn't increment parent's link count,
    + * i_op->mkdir does.
    + */
    + parent->d_inode->i_nlink++;
    + }
    + up(&parent->d_inode->i_sem);
    + if (err) {
    + dput(mfdentry);
    + return mfdentry;
    + }
    + }
    + return mfdentry;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_create_internal);
    +
    +int rcfs_delete_internal(struct dentry *mfdentry)
    +{
    + struct dentry *parent;
    +
    + if (!mfdentry || !mfdentry->d_parent)
    + return -EINVAL;
    + parent = mfdentry->d_parent;
    + if (!mfdentry->d_inode) {
    + return 0;
    + }
    + down(&mfdentry->d_inode->i_sem);
    + if (S_ISDIR(mfdentry->d_inode->i_mode))
    + simple_rmdir(parent->d_inode, mfdentry);
    + else
    + simple_unlink(parent->d_inode, mfdentry);
    + up(&mfdentry->d_inode->i_sem);
    + d_delete(mfdentry);
    +
    + return 0;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_delete_internal);
    +
    +struct inode_operations rcfs_file_inode_operations = {
    + .getattr = simple_getattr,
    +};
    Index: linux-2.6.10-rc2/fs/rcfs/magic.c
    ===================================================================
    --- /dev/null 1970-01-01 00:00:00.000000000 +0000
    +++ linux-2.6.10-rc2/fs/rcfs/magic.c 2004-11-19 20:44:18.272706722 -0800
    @@ -0,0 +1,542 @@
    +/*
    + * fs/rcfs/magic.c
    + *
    + * Copyright (C) Shailabh Nagar, IBM Corp. 2004
    + * (C) Vivek Kashyap, IBM Corp. 2004
    + * (C) Chandra Seetharaman, IBM Corp. 2004
    + * (C) Hubertus Franke, IBM Corp. 2004
    + *
    + * File operations for common magic files in rcfs,
    + * the user interface for CKRM.
    + *
    + * Latest version, more details at http://ckrm.sf.net
    + *
    + * 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.
    + */
    +
    +/*
    + * Changes
    + *
    + * 23 Apr 2004
    + * Created from code kept earlier in fs/rcfs/magic_*.c
    + */
    +
    +#include <linux/module.h>
    +#include <linux/fs.h>
    +#include <linux/namei.h>
    +#include <linux/namespace.h>
    +#include <linux/dcache.h>
    +#include <linux/seq_file.h>
    +#include <linux/init.h>
    +#include <linux/string.h>
    +#include <linux/smp_lock.h>
    +#include <linux/parser.h>
    +#include <asm/uaccess.h>
    +
    +#include <linux/rcfs.h>
    +
    +/*
    + * Macros
    + *
    + * generic macros to assist in writing magic fileops
    + *
    + */
    +
    +#define MAGIC_SHOW(FUNC) \
    +static int \
    +FUNC ## _show(struct seq_file *s, void *v) \
    +{ \
    + int rc=0; \
    + ssize_t precnt; \
    + ckrm_core_class_t *core ; \
    + \
    + core = (ckrm_core_class_t *) \
    + (((struct rcfs_inode_info *)s->private)->core); \
    + \
    + if (!ckrm_is_core_valid(core)) { \
    + return -EINVAL; \
    + } \
    + precnt = s->count ; \
    + if (core->classtype->show_ ## FUNC) \
    + rc = (* core->classtype->show_ ## FUNC)(core, s); \
    + \
    + if (s->count == precnt) \
    + seq_printf(s, "No data to display\n"); \
    + return rc; \
    +};
    +
    +#define MAGIC_OPEN(FUNC) \
    +static int \
    +FUNC ## _open(struct inode *inode, struct file *file) \
    +{ \
    + struct rcfs_inode_info *ri; \
    + int ret=-EINVAL; \
    + \
    + if (file->f_dentry && file->f_dentry->d_parent) { \
    + \
    + ri = RCFS_I(file->f_dentry->d_parent->d_inode); \
    + ret = single_open(file,FUNC ## _show, (void *)ri); \
    + } \
    + return ret; \
    +}
    +
    +#define MAGIC_CLOSE(FUNC) \
    +static int \
    +FUNC ## _close(struct inode *inode, struct file *file) \
    +{ \
    + return single_release(inode,file); \
    +}
    +
    +#define MAGIC_PARSE(FUNC) \
    +static int \
    +FUNC ## _parse(char *options, char **resstr, char **otherstr) \
    +{ \
    + char *p; \
    + *resstr = NULL; \
    + \
    + if (!options) \
    + return 0; \
    + \
    + while ((p = strsep(&options, ",")) != NULL) { \
    + substring_t args[MAX_OPT_ARGS]; \
    + int token; \
    + \
    + if (!*p) \
    + continue; \
    + \
    + token = match_token(p, FUNC##_tokens, args); \
    + switch (token) { \
    + case FUNC ## _res_type: \
    + *resstr = match_strdup(args); \
    + if (!strcmp(#FUNC, "config")) { \
    + char *str = p + strlen(p) + 1; \
    + *otherstr = kmalloc(strlen(str) + 1, \
    + GFP_KERNEL); \
    + if (*otherstr == NULL) { \
    + kfree(*resstr); \
    + *resstr = NULL; \
    + return 0; \
    + } else { \
    + strcpy(*otherstr, str); \
    + return 1; \
    + } \
    + } \
    + break; \
    + case FUNC ## _str: \
    + *otherstr = match_strdup(args); \
    + break; \
    + default: \
    + return 0; \
    + } \
    + } \
    + return (*resstr != NULL); \
    +}
    +
    +#define MAGIC_WRITE(FUNC,CLSTYPEFUN) \
    +static ssize_t \
    +FUNC ## _write(struct file *file, const char __user *buf, \
    + size_t count, loff_t *ppos) \
    +{ \
    + struct rcfs_inode_info *ri = \
    + RCFS_I(file->f_dentry->d_parent->d_inode); \
    + char *optbuf, *otherstr=NULL, *resname=NULL; \
    + int done, rc = 0; \
    + ckrm_core_class_t *core ; \
    + \
    + core = ri->core; \
    + if (!ckrm_is_core_valid(core)) \
    + return -EINVAL; \
    + \
    + if ((ssize_t) count < 0 \
    + || (ssize_t) count > FUNC ## _max_input_size) \
    + return -EINVAL; \
    + \
    + if (!access_ok(VERIFY_READ, buf, count)) \
    + return -EFAULT; \
    + \
    + down(&(ri->vfs_inode.i_sem)); \
    + \
    + optbuf = kmalloc(FUNC ## _max_input_size, GFP_KERNEL); \
    + __copy_from_user(optbuf, buf, count); \
    + if (optbuf[count-1] == '\n') \
    + optbuf[count-1]='\0'; \
    + \
    + done = FUNC ## _parse(optbuf, &resname, &otherstr); \
    + \
    + if (!done) { \
    + printk(KERN_ERR "Error parsing FUNC \n"); \
    + goto FUNC ## _write_out; \
    + } \
    + \
    + if (core->classtype-> CLSTYPEFUN) { \
    + rc = (*core->classtype->CLSTYPEFUN) \
    + (core, resname, otherstr); \
    + if (rc) { \
    + printk(KERN_ERR "FUNC_write: CLSTYPEFUN error\n"); \
    + goto FUNC ## _write_out; \
    + } \
    + } \
    + \
    +FUNC ## _write_out: \
    + up(&(ri->vfs_inode.i_sem)); \
    + kfree(optbuf); \
    + kfree(otherstr); \
    + kfree(resname); \
    + return rc ? rc : count; \
    +}
    +
    +#define MAGIC_RD_FILEOPS(FUNC) \
    +struct file_operations FUNC ## _fileops = { \
    + .open = FUNC ## _open, \
    + .read = seq_read, \
    + .llseek = seq_lseek, \
    + .release = FUNC ## _close, \
    +}; \
    +EXPORT_SYMBOL(FUNC ## _fileops);
    +
    +#define MAGIC_RDWR_FILEOPS(FUNC) \
    +struct file_operations FUNC ## _fileops = { \
    + .open = FUNC ## _open, \
    + .read = seq_read, \
    + .llseek = seq_lseek, \
    + .release = FUNC ## _close, \
    + .write = FUNC ## _write, \
    +}; \
    +EXPORT_SYMBOL(FUNC ## _fileops);
    +
    +/*
    + * Shared function used by Target / Reclassify
    + */
    +
    +#define TARGET_MAX_INPUT_SIZE 100
    +
    +static ssize_t
    +target_reclassify_write(struct file *file, const char __user * buf,
    + size_t count, loff_t * ppos, int manual)
    +{
    + struct rcfs_inode_info *ri = RCFS_I(file->f_dentry->d_inode);
    + char *optbuf;
    + int rc = -EINVAL;
    + ckrm_classtype_t *clstype;
    +
    + if ((ssize_t) count < 0 || (ssize_t) count > TARGET_MAX_INPUT_SIZE)
    + return -EINVAL;
    + if (!access_ok(VERIFY_READ, buf, count))
    + return -EFAULT;
    + down(&(ri->vfs_inode.i_sem));
    + optbuf = kmalloc(TARGET_MAX_INPUT_SIZE, GFP_KERNEL);
    + __copy_from_user(optbuf, buf, count);
    + if (optbuf[count - 1] == '\n')
    + optbuf[count - 1] = '\0';
    + clstype = ri->core->classtype;
    + if (clstype->forced_reclassify)
    + rc = (*clstype->forced_reclassify) (manual ? ri->core: NULL, optbuf);
    + up(&(ri->vfs_inode.i_sem));
    + kfree(optbuf);
    + return (!rc ? count : rc);
    +
    +}
    +
    +/*
    + * Target
    + *
    + * pseudo file for manually reclassifying members to a class
    + */
    +
    +static ssize_t
    +target_write(struct file *file, const char __user * buf,
    + size_t count, loff_t * ppos)
    +{
    + return target_reclassify_write(file,buf,count,ppos,1);
    +}
    +
    +struct file_operations target_fileops = {
    + .write = target_write,
    +};
    +
    +EXPORT_SYMBOL_GPL(target_fileops);
    +
    +/*
    + * Reclassify
    + *
    + * pseudo file for reclassification of an object through CE
    + */
    +
    +static ssize_t
    +reclassify_write(struct file *file, const char __user * buf,
    + size_t count, loff_t * ppos)
    +{
    + return target_reclassify_write(file,buf,count,ppos,0);
    +}
    +
    +struct file_operations reclassify_fileops = {
    + .write = reclassify_write,
    +};
    +
    +EXPORT_SYMBOL_GPL(reclassify_fileops);
    +
    +/*
    + * Config
    + *
    + * Set/get configuration parameters of a class.
    + */
    +
    +/*
    + * Currently there are no per-class config parameters defined.
    + * Use existing code as a template
    + */
    +
    +#define config_max_input_size 300
    +
    +enum config_token_t {
    + config_str, config_res_type, config_err
    +};
    +
    +static match_table_t config_tokens = {
    + {config_res_type, "res=%s"},
    + {config_err, NULL},
    +};
    +
    +MAGIC_PARSE(config);
    +MAGIC_WRITE(config, set_config);
    +MAGIC_SHOW(config);
    +MAGIC_OPEN(config);
    +MAGIC_CLOSE(config);
    +
    +MAGIC_RDWR_FILEOPS(config);
    +
    +/*
    + * Members
    + *
    + * List members of a class
    + */
    +
    +MAGIC_SHOW(members);
    +MAGIC_OPEN(members);
    +MAGIC_CLOSE(members);
    +
    +MAGIC_RD_FILEOPS(members);
    +
    +/*
    + * Stats
    + *
    + * Get/reset class statistics
    + * No standard set of stats defined. Each resource controller chooses
    + * its own set of statistics to maintain and export.
    + */
    +
    +#define stats_max_input_size 50
    +
    +enum stats_token_t {
    + stats_res_type, stats_str, stats_err
    +};
    +
    +static match_table_t stats_tokens = {
    + {stats_res_type, "res=%s"},
    + {stats_str, NULL},
    + {stats_err, NULL},
    +};
    +
    +MAGIC_PARSE(stats);
    +MAGIC_WRITE(stats, reset_stats);
    +MAGIC_SHOW(stats);
    +MAGIC_OPEN(stats);
    +MAGIC_CLOSE(stats);
    +
    +MAGIC_RDWR_FILEOPS(stats);
    +
    +/*
    + * Shares
    + *
    + * Set/get shares of a taskclass.
    + * Share types and semantics are defined by rcfs and ckrm core
    + */
    +
    +#define SHARES_MAX_INPUT_SIZE 300
    +
    +/*
    + * The enums for the share types should match the indices expected by
    + * array parameter to ckrm_set_resshare
    + *
    + * Note only the first NUM_SHAREVAL enums correspond to share types,
    + * the remaining ones are for token matching purposes
    + */
    +
    +enum share_token_t {
    + MY_GUAR, MY_LIM, TOT_GUAR, MAX_LIM, SHARE_RES_TYPE, SHARE_ERR
    +};
    +
    +/* Token matching for parsing input to this magic file */
    +static match_table_t shares_tokens = {
    + {SHARE_RES_TYPE, "res=%s"},
    + {MY_GUAR, "guarantee=%d"},
    + {MY_LIM, "limit=%d"},
    + {TOT_GUAR, "total_guarantee=%d"},
    + {MAX_LIM, "max_limit=%d"},
    + {SHARE_ERR, NULL}
    +};
    +
    +static int
    +shares_parse(char *options, char **resstr, struct ckrm_shares *shares)
    +{
    + char *p;
    + int option;
    +
    + if (!options)
    + return 1;
    + while ((p = strsep(&options, ",")) != NULL) {
    + substring_t args[MAX_OPT_ARGS];
    + int token;
    +
    + if (!*p)
    + continue;
    + token = match_token(p, shares_tokens, args);
    + switch (token) {
    + case SHARE_RES_TYPE:
    + *resstr = match_strdup(args);
    + break;
    + case MY_GUAR:
    + if (match_int(args, &option))
    + return 0;
    + shares->my_guarantee = option;
    + break;
    + case MY_LIM:
    + if (match_int(args, &option))
    + return 0;
    + shares->my_limit = option;
    + break;
    + case TOT_GUAR:
    + if (match_int(args, &option))
    + return 0;
    + shares->total_guarantee = option;
    + break;
    + case MAX_LIM:
    + if (match_int(args, &option))
    + return 0;
    + shares->max_limit = option;
    + break;
    + default:
    + return 0;
    + }
    + }
    + return 1;
    +}
    +
    +static ssize_t
    +shares_write(struct file *file, const char __user * buf,
    + size_t count, loff_t * ppos)
    +{
    + struct inode *inode = file->f_dentry->d_inode;
    + struct rcfs_inode_info *ri;
    + char *optbuf;
    + int rc = 0;
    + struct ckrm_core_class *core;
    + int done;
    + char *resname = NULL;
    +
    + struct ckrm_shares newshares = {
    + CKRM_SHARE_UNCHANGED,
    + CKRM_SHARE_UNCHANGED,
    + CKRM_SHARE_UNCHANGED,
    + CKRM_SHARE_UNCHANGED,
    + CKRM_SHARE_UNCHANGED,
    + CKRM_SHARE_UNCHANGED
    + };
    + if ((ssize_t) count < 0 || (ssize_t) count > SHARES_MAX_INPUT_SIZE)
    + return -EINVAL;
    + if (!access_ok(VERIFY_READ, buf, count))
    + return -EFAULT;
    + ri = RCFS_I(file->f_dentry->d_parent->d_inode);
    + if (!ri || !ckrm_is_core_valid((ckrm_core_class_t *) (ri->core))) {
    + printk(KERN_ERR "shares_write: Error accessing core class\n");
    + return -EFAULT;
    + }
    + down(&inode->i_sem);
    + core = ri->core;
    + optbuf = kmalloc(SHARES_MAX_INPUT_SIZE, GFP_KERNEL);
    + if (!optbuf) {
    + up(&inode->i_sem);
    + return -ENOMEM;
    + }
    + __copy_from_user(optbuf, buf, count);
    + if (optbuf[count - 1] == '\n')
    + optbuf[count - 1] = '\0';
    + done = shares_parse(optbuf, &resname, &newshares);
    + if (!done) {
    + printk(KERN_ERR "Error parsing shares\n");
    + rc = -EINVAL;
    + goto write_out;
    + }
    + if (core->classtype->set_shares) {
    + rc = (*core->classtype->set_shares) (core, resname, &newshares);
    + if (rc) {
    + printk(KERN_ERR
    + "shares_write: resctlr share set error\n");
    + goto write_out;
    + }
    + }
    + printk(KERN_ERR "Set %s shares to %d %d %d %d\n",
    + resname,
    + newshares.my_guarantee,
    + newshares.my_limit,
    + newshares.total_guarantee, newshares.max_limit);
    + rc = count;
    +
    +write_out:
    + up(&inode->i_sem);
    + kfree(optbuf);
    + kfree(resname);
    + return rc;
    +}
    +
    +MAGIC_SHOW(shares);
    +MAGIC_OPEN(shares);
    +MAGIC_CLOSE(shares);
    +
    +MAGIC_RDWR_FILEOPS(shares);
    +
    +/*
    + * magic file creation/deletion
    + */
    +
    +int rcfs_clear_magic(struct dentry *parent)
    +{
    + struct dentry *mftmp, *mfdentry;
    +
    + list_for_each_entry_safe(mfdentry, mftmp, &parent->d_subdirs, d_child) {
    + if (!rcfs_is_magic(mfdentry))
    + continue;
    + if (rcfs_delete_internal(mfdentry))
    + printk(KERN_ERR
    + "rcfs_clear_magic: error deleting one\n");
    + }
    + return 0;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_clear_magic);
    +
    +int rcfs_create_magic(struct dentry *parent, struct rcfs_magf magf[], int count)
    +{
    + int i;
    + struct dentry *mfdentry;
    +
    + for (i = 0; i < count; i++) {
    + mfdentry = rcfs_create_internal(parent, &magf[i], 0);
    + if (IS_ERR(mfdentry)) {
    + rcfs_clear_magic(parent);
    + return -ENOMEM;
    + }
    + RCFS_I(mfdentry->d_inode)->core = RCFS_I(parent->d_inode)->core;
    + mfdentry->d_fsdata = &RCFS_IS_MAGIC;
    + if (magf[i].i_fop)
    + mfdentry->d_inode->i_fop = magf[i].i_fop;
    + if (magf[i].i_op)
    + mfdentry->d_inode->i_op = magf[i].i_op;
    + }
    + return 0;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_create_magic);
    Index: linux-2.6.10-rc2/fs/rcfs/Makefile
    ===================================================================
    --- /dev/null 1970-01-01 00:00:00.000000000 +0000
    +++ linux-2.6.10-rc2/fs/rcfs/Makefile 2004-11-19 20:44:18.274706405 -0800
    @@ -0,0 +1,6 @@
    +#
    +# Makefile for rcfs routines.
    +#
    +
    +obj-$(CONFIG_RCFS_FS) += rcfs.o
    +rcfs-objs := super.o inode.o dir.o rootdir.o magic.o
    Index: linux-2.6.10-rc2/fs/rcfs/rootdir.c
    ===================================================================
    --- /dev/null 1970-01-01 00:00:00.000000000 +0000
    +++ linux-2.6.10-rc2/fs/rcfs/rootdir.c 2004-11-19 20:44:18.279705613 -0800
    @@ -0,0 +1,209 @@
    +/*
    + * fs/rcfs/rootdir.c
    + *
    + * Copyright (C) Vivek Kashyap, IBM Corp. 2004
    + *
    + *
    + * Functions for creating root directories and magic files
    + * for classtypes and classification engines under rcfs
    + *
    + * Latest version, more details at http://ckrm.sf.net
    + *
    + * 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.
    + *
    + */
    +
    +/*
    + * Changes
    + *
    + * 08 April 2004
    + * Created.
    + */
    +
    +#include <linux/module.h>
    +#include <linux/fs.h>
    +#include <linux/namei.h>
    +#include <linux/namespace.h>
    +#include <linux/dcache.h>
    +#include <linux/seq_file.h>
    +#include <linux/pagemap.h>
    +#include <linux/highmem.h>
    +#include <linux/init.h>
    +#include <linux/string.h>
    +#include <linux/smp_lock.h>
    +#include <linux/backing-dev.h>
    +#include <linux/parser.h>
    +
    +#include <asm/uaccess.h>
    +
    +#include <linux/rcfs.h>
    +
    +rbce_eng_callback_t rcfs_eng_callbacks = {
    + NULL, NULL
    +};
    +
    +int rcfs_register_engine(rbce_eng_callback_t * rcbs)
    +{
    + if (!rcbs->mkdir || rcfs_eng_callbacks.mkdir) {
    + return -EINVAL;
    + }
    + rcfs_eng_callbacks = *rcbs;
    + rcfs_engine_regd++;
    + return 0;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_register_engine);
    +
    +int rcfs_unregister_engine(rbce_eng_callback_t * rcbs)
    +{
    + if (!rcbs->mkdir || !rcfs_eng_callbacks.mkdir ||
    + (rcbs->mkdir != rcfs_eng_callbacks.mkdir)) {
    + return -EINVAL;
    + }
    + rcfs_eng_callbacks.mkdir = NULL;
    + rcfs_eng_callbacks.rmdir = NULL;
    + rcfs_engine_regd--;
    + return 0;
    +}
    +
    +EXPORT_SYMBOL(rcfs_unregister_engine);
    +
    +/*
    + * rcfs_mkroot
    + * Create and return a "root" dentry under /rcfs.
    + * Also create associated magic files
    + *
    + * @mfdesc: array of rcfs_magf describing root dir and its magic files
    + * @count: number of entries in mfdesc
    + * @core: core class to be associated with root
    + * @rootde: output parameter to return the newly created root dentry
    + */
    +
    +int rcfs_mkroot(struct rcfs_magf *mfdesc, int mfcount, struct dentry **rootde)
    +{
    + int sz;
    + struct rcfs_magf *rootdesc = &mfdesc[0];
    + struct dentry *dentry;
    + struct rcfs_inode_info *rootri;
    +
    + if ((mfcount < 0) || (!mfdesc))
    + return -EINVAL;
    +
    + rootdesc = &mfdesc[0];
    + printk("allocating classtype root <%s>\n", rootdesc->name);
    + dentry = rcfs_create_internal(rcfs_rootde, rootdesc, 0);
    +
    + if (!dentry) {
    + printk(KERN_ERR "Could not create %s\n", rootdesc->name);
    + return -ENOMEM;
    + }
    + rootri = RCFS_I(dentry->d_inode);
    + sz = strlen(rootdesc->name) + strlen(RCFS_ROOT) + 2;
    + rootri->name = kmalloc(sz, GFP_KERNEL);
    + if (!rootri->name) {
    + printk(KERN_ERR "Error allocating name for %s\n",
    + rootdesc->name);
    + rcfs_delete_internal(dentry);
    + return -ENOMEM;
    + }
    + snprintf(rootri->name, sz, "%s/%s", RCFS_ROOT, rootdesc->name);
    + if (rootdesc->i_fop)
    + dentry->d_inode->i_fop = rootdesc->i_fop;
    + if (rootdesc->i_op)
    + dentry->d_inode->i_op = rootdesc->i_op;
    +
    + /* set output parameters */
    + *rootde = dentry;
    +
    + return 0;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_mkroot);
    +
    +int rcfs_rmroot(struct dentry *rootde)
    +{
    + struct rcfs_inode_info *ri;
    +
    + if (!rootde)
    + return -EINVAL;
    +
    + rcfs_clear_magic(rootde);
    + ri = RCFS_I(rootde->d_inode);
    + kfree(ri->name);
    + ri->name = NULL;
    + rcfs_delete_internal(rootde);
    + return 0;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_rmroot);
    +
    +int rcfs_register_classtype(ckrm_classtype_t * clstype)
    +{
    + int rc;
    + struct rcfs_inode_info *rootri;
    + struct rcfs_magf *mfdesc;
    +
    + if (genmfdesc[clstype->mfidx] == NULL) {
    + return -ENOMEM;
    + }
    +
    + clstype->mfdesc = (void *)genmfdesc[clstype->mfidx]->rootmf;
    + clstype->mfcount = genmfdesc[clstype->mfidx]->rootmflen;
    +
    + mfdesc = (struct rcfs_magf *)clstype->mfdesc;
    +
    + /* rcfs root entry has the same name as the classtype */
    + strncpy(mfdesc[0].name, clstype->name, RCFS_MAGF_NAMELEN);
    +
    + rc = rcfs_mkroot(mfdesc, clstype->mfcount,
    + (struct dentry **)&(clstype->rootde));
    + if (rc)
    + return rc;
    + rootri = RCFS_I(((struct dentry *)(clstype->rootde))->d_inode);
    + rootri->core = clstype->default_class;
    + clstype->default_class->name = rootri->name;
    + ckrm_core_grab(clstype->default_class);
    +
    + /* Create magic files under root */
    + if ((rc = rcfs_create_magic(clstype->rootde, &mfdesc[1],
    + clstype->mfcount - 1))) {
    + kfree(rootri->name);
    + rootri->name = NULL;
    + rcfs_delete_internal(clstype->rootde);
    + return rc;
    + }
    + return rc;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_register_classtype);
    +
    +int rcfs_deregister_classtype(ckrm_classtype_t * clstype)
    +{
    + int rc;
    +
    + rc = rcfs_rmroot((struct dentry *)clstype->rootde);
    + if (!rc) {
    + clstype->default_class->name = NULL;
    + ckrm_core_drop(clstype->default_class);
    + }
    + return rc;
    +}
    +
    +EXPORT_SYMBOL_GPL(rcfs_deregister_classtype);
    +
    +/* Common root and magic file entries.
    + * root name, root permissions, magic file names and magic file permissions
    + * are needed by all entities (classtypes and classification engines) existing
    + * under the rcfs mount point
    + *
    + * The common sets of these attributes are listed here as a table. Individual
    + * classtypes and classification engines can simple specify the index into the
    + * table to initialize their magf entries.
    + */
    +
    +struct rcfs_mfdesc *genmfdesc[] = {
    + NULL,
    +};
    Index: linux-2.6.10-rc2/fs/rcfs/super.c
    ===================================================================
    --- /dev/null 1970-01-01 00:00:00.000000000 +0000
    +++ linux-2.6.10-rc2/fs/rcfs/super.c 2004-11-19 20:44:18.283704980 -0800
    @@ -0,0 +1,304 @@
    +/*
    + * fs/rcfs/super.c
    + *
    + * Copyright (C) Shailabh Nagar, IBM Corp. 2004
    + * Vivek Kashyap, IBM Corp. 2004
    + *
    + * Super block operations for rcfs
    + *
    + *
    + * Latest version, more details at http://ckrm.sf.net
    + *
    + * 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.
    + *
    + */
    +
    +/*
    + * Changes
    + *
    + * 08 Mar 2004
    + * Created.
    + */
    +
    +#include <linux/module.h>
    +#include <linux/fs.h>
    +#include <linux/namei.h>
    +#include <linux/namespace.h>
    +#include <linux/dcache.h>
    +#include <linux/seq_file.h>
    +#include <linux/pagemap.h>
    +#include <linux/highmem.h>
    +#include <linux/init.h>
    +#include <linux/string.h>
    +#include <linux/smp_lock.h>
    +#include <linux/backing-dev.h>
    +#include <linux/parser.h>
    +
    +#include <asm/uaccess.h>
    +
    +#include <linux/rcfs.h>
    +#include <linux/ckrm_rc.h>
    +#include <linux/ckrm_ce.h>
    +
    +static kmem_cache_t *rcfs_inode_cachep;
    +
    +inline struct rcfs_inode_info *RCFS_I(struct inode *inode)
    +{
    + return container_of(inode, struct rcfs_inode_info, vfs_inode);
    +}
    +
    +EXPORT_SYMBOL_GPL(RCFS_I);
    +
    +static struct inode *rcfs_alloc_inode(struct super_block *sb)
    +{
    + struct rcfs_inode_info *ri;
    + ri = (struct rcfs_inode_info *)kmem_cache_alloc(rcfs_inode_cachep,
    + SLAB_KERNEL);
    + if (!ri)
    + return NULL;
    + ri->name = NULL;
    + return &ri->vfs_inode;
    +}
    +
    +static void rcfs_destroy_inode(struct inode *inode)
    +{
    + struct rcfs_inode_info *ri = RCFS_I(inode);
    +
    + kfree(ri->name);
    + kmem_cache_free(rcfs_inode_cachep, ri);
    +}
    +
    +static void
    +rcfs_init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
    +{
    + struct rcfs_inode_info *ri = (struct rcfs_inode_info *)foo;
    +
    + if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
    + SLAB_CTOR_CONSTRUCTOR)
    + inode_init_once(&ri->vfs_inode);
    +}
    +
    +int rcfs_init_inodecache(void)
    +{
    + rcfs_inode_cachep = kmem_cache_create("rcfs_inode_cache",
    + sizeof(struct rcfs_inode_info),
    + 0,
    + SLAB_HWCACHE_ALIGN |
    + SLAB_RECLAIM_ACCOUNT,
    + rcfs_init_once, NULL);
    + if (rcfs_inode_cachep == NULL)
    + return -ENOMEM;
    + return 0;
    +}
    +
    +void rcfs_destroy_inodecache(void)
    +{
    + printk(KERN_WARNING "destroy inodecache was called\n");
    + if (kmem_cache_destroy(rcfs_inode_cachep))
    + printk(KERN_INFO
    + "rcfs_inode_cache: not all structures were freed\n");
    +}
    +
    +struct super_operations rcfs_super_ops = {
    + .alloc_inode = rcfs_alloc_inode,
    + .destroy_inode = rcfs_destroy_inode,
    + .statfs = simple_statfs,
    + .drop_inode = generic_delete_inode,
    +};
    +
    +struct dentry *rcfs_rootde; /* redundant; can also get it from sb */
    +static struct inode *rcfs_root;
    +static struct rcfs_inode_info *rcfs_rootri;
    +
    +static int rcfs_fill_super(struct super_block *sb, void *data, int silent)
    +{
    + struct inode *inode;
    + struct dentry *root;
    + struct rcfs_inode_info *rootri;
    + struct ckrm_classtype *clstype;
    + int i, rc;
    +
    + sb->s_fs_info = NULL;
    + if (rcfs_mounted) {
    + return -EPERM;
    + }
    + rcfs_mounted++;
    +
    + sb->s_blocksize = PAGE_CACHE_SIZE;
    + sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
    + sb->s_magic = RCFS_MAGIC;
    + sb->s_op = &rcfs_super_ops;
    + inode = rcfs_get_inode(sb, S_IFDIR | 0755, 0);
    + if (!inode)
    + return -ENOMEM;
    + inode->i_op = &rcfs_rootdir_inode_operations;
    +
    + root = d_alloc_root(inode);
    + if (!root) {
    + iput(inode);
    + return -ENOMEM;
    + }
    + sb->s_root = root;
    +
    + /* Link inode and core class */
    + rootri = RCFS_I(inode);
    + rootri->name = kmalloc(strlen(RCFS_ROOT) + 1, GFP_KERNEL);
    + if (!rootri->name) {
    + d_delete(root);
    + iput(inode);
    + return -ENOMEM;
    + }
    + strcpy(rootri->name, RCFS_ROOT);
    + rootri->core = NULL;
    +
    + rcfs_root = inode;
    + sb->s_fs_info = rcfs_root = inode;
    + rcfs_rootde = root;
    + rcfs_rootri = rootri;
    +
    + /* register metatypes */
    + for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
    + clstype = ckrm_classtypes[i];
    + if (clstype == NULL)
    + continue;
    + printk("A non null classtype\n");
    +
    + if ((rc = rcfs_register_classtype(clstype)))
    + continue; /* could return with an error too */
    + }
    +
    + /*
    + * do post-mount initializations needed by CE
    + * this is distinct from CE registration done on rcfs module load
    + */
    + if (rcfs_engine_regd) {
    + if (rcfs_eng_callbacks.mnt)
    + if ((rc = (*rcfs_eng_callbacks.mnt) ())) {
    + printk(KERN_ERR "Error in CE mnt %d\n", rc);
    + }
    + }
    + /*
    + * Following comment handled by code above; keep nonetheless if it
    + * can be done better
    + *
    + * register CE's with rcfs
    + * check if CE loaded
    + * call rcfs_register_engine for each classtype
    + * AND rcfs_mkroot (preferably subsume latter in former)
    + */
    + return 0;
    +}
    +
    +static struct super_block *rcfs_get_sb(struct file_system_type *fs_type,
    + int flags, const char *dev_name,
    + void *data)
    +{
    + return get_sb_nodev(fs_type, flags, data, rcfs_fill_super);
    +}
    +
    +void rcfs_kill_sb(struct super_block *sb)
    +{
    + int i, rc;
    + struct ckrm_classtype *clstype;
    +
    + if (sb->s_fs_info != rcfs_root) {
    + generic_shutdown_super(sb);
    + return;
    + }
    + rcfs_mounted--;
    +
    + for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
    + clstype = ckrm_classtypes[i];
    + if (clstype == NULL || clstype->rootde == NULL)
    + continue;
    +
    + if ((rc = rcfs_deregister_classtype(clstype))) {
    + printk(KERN_ERR "Error removing classtype %s\n",
    + clstype->name);
    + }
    + }
    +
    + /*
    + * do pre-umount shutdown needed by CE
    + * this is distinct from CE deregistration done on rcfs module unload
    + */
    + if (rcfs_engine_regd) {
    + if (rcfs_eng_callbacks.umnt)
    + if ((rc = (*rcfs_eng_callbacks.umnt) ())) {
    + printk(KERN_ERR "Error in CE umnt %d\n", rc);
    + /* TODO: return ; until error handling improves */
    + }
    + }
    + /*
    + * Following comment handled by code above; keep nonetheless if it
    + * can be done better
    + *
    + * deregister CE with rcfs
    + * Check if loaded
    + * if ce is in one directory /rcfs/ce,
    + * rcfs_deregister_engine for all classtypes within above
    + * codebase
    + * followed by
    + * rcfs_rmroot here
    + * if ce in multiple (per-classtype) directories
    + * call rbce_deregister_engine within ckrm_deregister_classtype
    + *
    + * following will automatically clear rcfs root entry including its
    + * rcfs_inode_info
    + */
    +
    + generic_shutdown_super(sb);
    +}
    +
    +static struct file_system_type rcfs_fs_type = {
    + .name = "rcfs",
    + .get_sb = rcfs_get_sb,
    + .kill_sb = rcfs_kill_sb,
    +};
    +
    +struct rcfs_functions my_rcfs_fn = {
    + .mkroot = rcfs_mkroot,
    + .rmroot = rcfs_rmroot,
    + .register_classtype = rcfs_register_classtype,
    + .deregister_classtype = rcfs_deregister_classtype,
    +};
    +
    +extern struct rcfs_functions rcfs_fn;
    +
    +static int __init init_rcfs_fs(void)
    +{
    + int ret;
    +
    + ret = register_filesystem(&rcfs_fs_type);
    + if (ret)
    + goto init_register_err;
    + ret = rcfs_init_inodecache();
    + if (ret)
    + goto init_cache_err;
    + rcfs_fn = my_rcfs_fn;
    + /*
    + * Due to tight coupling of this module with ckrm
    + * do not allow this module to be removed.
    + */
    + try_module_get(THIS_MODULE);
    + return ret;
    +
    +init_cache_err:
    + unregister_filesystem(&rcfs_fs_type);
    +init_register_err:
    + return ret;
    +}
    +
    +static void __exit exit_rcfs_fs(void)
    +{
    + rcfs_destroy_inodecache();
    + unregister_filesystem(&rcfs_fs_type);
    +}
    +
    +module_init(init_rcfs_fs)
    +module_exit(exit_rcfs_fs)
    +
    +MODULE_LICENSE("GPL");
    Index: linux-2.6.10-rc2/init/Kconfig
    ===================================================================
    --- linux-2.6.10-rc2.orig/init/Kconfig 2004-11-19 20:41:45.572898412 -0800
    +++ linux-2.6.10-rc2/init/Kconfig 2004-11-19 20:44:18.288704188 -0800
    @@ -152,6 +152,17 @@
    If you say Y here, enable the Resource Class File System and atleast
    one of the resource controllers below. Say N if you are unsure.

    +config RCFS_FS
    + tristate "Resource Class File System (User API)"
    + depends on CKRM
    + help
    + RCFS is the filesystem API for CKRM. This separate configuration
    + option is provided only for debugging and will eventually disappear
    + since rcfs will be automounted whenever CKRM is configured.
    +
    + Say N if unsure, Y if you've enabled CKRM, M to debug rcfs
    + initialization.
    +
    endmenu

    config SYSCTL
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2005-03-22 14:08    [W:0.119 / U:91.684 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site