Main code for CKRM default classification engine.  Adds Resrouce
Control (rc) filesystem as mechanism for setting policies for
class assignments in CKRM.

Signed-Off-By: Chandra Seetharaman <[EMAIL PROTECTED]>
Signed-Off-By: Hubertus Franke <[EMAIL PROTECTED]>
Signed-Off-By: Shailabh Nagar <[EMAIL PROTECTED]>
Signed-Off-By: Gerrit Huizenga <[EMAIL PROTECTED]>
Signed-Off-By: Vivek Kashyap <[EMAIL PROTECTED]>


 include/linux/ckrm_ce.h     |  108 +++++
 include/linux/ckrm_events.h |    8 
 include/linux/ckrm_rc.h     |  355 ++++++++++++++++
 include/linux/rcfs.h        |   96 ++++
 include/linux/sched.h       |    6 
 init/main.c                 |    2 
 kernel/ckrm/Makefile        |    2 
 kernel/ckrm/ckrm.c          |  927 ++++++++++++++++++++++++++++++++++++++++++++
 kernel/ckrm/ckrmutils.c     |  195 +++++++++
 9 files changed, 1694 insertions(+), 5 deletions(-)

Index: linux-2.6.11-rc5/include/linux/ckrm_ce.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.11-rc5/include/linux/ckrm_ce.h    2005-02-24 00:55:01.390489786 
-0800
@@ -0,0 +1,95 @@
+/*
+ *  ckrm_ce.h - Header file to be used by Classification Engine of CKRM
+ *
+ * Copyright (C) Hubertus Franke, IBM Corp. 2003
+ *           (C) Shailabh Nagar,  IBM Corp. 2003
+ *           (C) Chandra Seetharaman, IBM Corp. 2003
+ * 
+ * Provides data structures, macros and kernel API of CKRM for 
+ * classification engine.
+ *
+ * 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 version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#ifndef _LINUX_CKRM_CE_H
+#define _LINUX_CKRM_CE_H
+
+#ifdef CONFIG_CKRM
+
+#include <linux/ckrm_events.h>
+
+/*
+ * Action parameters identifying the cause of a task<->class notify callback 
+ * these can perculate up to user daemon consuming records send by the 
+ * classification engine
+ */
+
+typedef void *(*ce_classify_fct) (enum ckrm_event event, void *obj, ...);
+typedef void (*ce_notify_fct) (enum ckrm_event event, void *classobj,
+                                void *obj);
+
+struct ckrm_eng_callback {
+       /* general state information */
+       int always_callback;    /* set if CE should always be called back 
+                                  regardless of numclasses */
+
+       /* callbacks which are called without holding locks */
+
+       unsigned long c_interest;       /* set of classification events of 
+                                        * interest to CE 
+                                        */
+
+       /* generic classify */
+       ce_classify_fct classify;
+
+       /* class added */
+       void (*class_add) (const char *name, void *core, int classtype);
+
+       /* class deleted */
+       void (*class_delete) (const char *name, void *core, int classtype);
+
+       /* callbacks which are called while holding task_lock(tsk) */
+       unsigned long n_interest;       /* set of notification events of 
+                                        *  interest to CE 
+                                        */
+       /* notify on class switch */
+       ce_notify_fct notify;   
+};
+
+struct inode;
+struct dentry;
+
+struct rbce_eng_callback {
+       int (*mkdir) (struct inode *, struct dentry *, int);    /* mkdir */
+       int (*rmdir) (struct inode *, struct dentry *);         /* rmdir */
+       int (*mnt) (void);
+       int (*umnt) (void);
+};
+
+extern int ckrm_register_engine(const char *name, struct ckrm_eng_callback *);
+extern int ckrm_unregister_engine(const char *name);
+
+extern void *ckrm_classobj(char *, int *classtype);
+
+extern int rcfs_register_engine(struct rbce_eng_callback *);
+extern int rcfs_unregister_engine(struct rbce_eng_callback *);
+
+extern int ckrm_reclassify(int pid);
+
+#ifndef _LINUX_CKRM_RC_H
+
+extern void ckrm_core_grab(struct ckrm_core_class *core);
+extern void ckrm_core_drop(struct ckrm_core_class *core);
+#endif
+
+#endif /* CONFIG_CKRM */
+#endif /* _LINUX_CKRM_CE_H */
Index: linux-2.6.11-rc5/include/linux/ckrm_events.h
===================================================================
--- linux-2.6.11-rc5.orig/include/linux/ckrm_events.h   2005-02-24 
00:54:50.530799168 -0800
+++ linux-2.6.11-rc5/include/linux/ckrm_events.h        2005-02-24 
00:55:01.391489666 -0800
@@ -108,70 +108,78 @@
 extern void ckrm_invoke_event_cb_chain(enum ckrm_event ev, void *arg);
 
 /* forward declarations for function arguments */
-struct task_struct;
+
+#include <linux/sched.h>               /* for task_struct */
+
 struct sock;
 struct user_struct;
 
 static inline void ckrm_cb_fork(struct task_struct *p)
 {
-         ckrm_invoke_event_cb_chain(CKRM_EVENT_FORK, p);
+       ckrm_invoke_event_cb_chain(CKRM_EVENT_FORK, p);
 }
 
 static inline void ckrm_cb_newtask(struct task_struct *p)
 {
-         ckrm_invoke_event_cb_chain(CKRM_EVENT_NEWTASK, p);
+       
+       p->ce_data = NULL;
+       spin_lock_init(&p->ckrm_tsklock);
+       ckrm_invoke_event_cb_chain(CKRM_EVENT_NEWTASK, p);
 }
 
 static inline void ckrm_cb_exit(struct task_struct *p)
 {
-         ckrm_invoke_event_cb_chain(CKRM_EVENT_EXIT, p);
+       ckrm_invoke_event_cb_chain(CKRM_EVENT_EXIT, p);
+       p->ce_data = NULL;
 }
 
 static inline void ckrm_cb_exec(char *c)
 {
-         ckrm_invoke_event_cb_chain(CKRM_EVENT_EXEC, c);
-}
+       ckrm_invoke_event_cb_chain(CKRM_EVENT_EXEC, c);
+ }
 
 static inline void ckrm_cb_uid(void)
 {
-         ckrm_invoke_event_cb_chain(CKRM_EVENT_UID, NULL);
+       ckrm_invoke_event_cb_chain(CKRM_EVENT_UID, NULL);
 }
 
 static inline void ckrm_cb_gid(void)
 {
-         ckrm_invoke_event_cb_chain(CKRM_EVENT_GID, NULL);
+       ckrm_invoke_event_cb_chain(CKRM_EVENT_GID, NULL);
 }
 
 static inline void ckrm_cb_apptag(void)
 {
-         ckrm_invoke_event_cb_chain(CKRM_EVENT_APPTAG, NULL);
+       ckrm_invoke_event_cb_chain(CKRM_EVENT_APPTAG, NULL);
 }
 
 static inline void ckrm_cb_login(void)
 {
-         ckrm_invoke_event_cb_chain(CKRM_EVENT_LOGIN, NULL);
+       ckrm_invoke_event_cb_chain(CKRM_EVENT_LOGIN, NULL);
 }
 
 static inline void ckrm_cb_useradd(struct user_struct *u)
 {
-         ckrm_invoke_event_cb_chain(CKRM_EVENT_USERADD, u);
+       ckrm_invoke_event_cb_chain(CKRM_EVENT_USERADD, u);
 }
 
 static inline void ckrm_cb_userdel(struct user_struct *u)
 {
-         ckrm_invoke_event_cb_chain(CKRM_EVENT_USERDEL, u);
+       ckrm_invoke_event_cb_chain(CKRM_EVENT_USERDEL, u);
 }
 
 static inline void ckrm_cb_listen_start(struct sock *s)
 {
-         ckrm_invoke_event_cb_chain(CKRM_EVENT_LISTEN_START, s);
+       ckrm_invoke_event_cb_chain(CKRM_EVENT_LISTEN_START, s);
 }
 
 static inline void ckrm_cb_listen_stop(struct sock *s)
 {
-         ckrm_invoke_event_cb_chain(CKRM_EVENT_LISTEN_STOP, s);
+       ckrm_invoke_event_cb_chain(CKRM_EVENT_LISTEN_STOP, s);
 }
 
+extern void ckrm_init(void);
+
 #else /* !CONFIG_CKRM */
 
 static inline void ckrm_cb_fork(struct task_struct *p) { }
@@ -187,6 +195,8 @@
 static inline void ckrm_cb_listen_start(struct sock *s) { }
 static inline void ckrm_cb_listen_stop(struct sock *s) { }
 
+#define ckrm_init()    do { } while (0)
+
 #endif /* CONFIG_CKRM */
 
 #endif /* _LINUX_CKRM_EVENTS_H */
Index: linux-2.6.11-rc5/include/linux/ckrm_rc.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.11-rc5/include/linux/ckrm_rc.h    2005-02-24 00:55:01.434484482 
-0800
@@ -0,0 +1,345 @@
+/*
+ *  ckrm_rc.h - Header file to be used by Resource controllers of CKRM
+ *
+ * Copyright (C) Hubertus Franke, IBM Corp. 2003
+ *           (C) Shailabh Nagar,  IBM Corp. 2003
+ *           (C) Chandra Seetharaman, IBM Corp. 2003
+ *          (C) Vivek Kashyap , IBM Corp. 2004
+ * 
+ * Provides data structures, macros and kernel API of CKRM for 
+ * resource controllers.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_CKRM_RC_H
+#define _LINUX_CKRM_RC_H
+
+#ifdef CONFIG_CKRM
+
+#include <linux/list.h>
+#include <linux/ckrm_events.h>
+#include <linux/ckrm_ce.h>
+#include <linux/seq_file.h>
+
+#define CKRM_MAX_CLASSTYPES         32 /* maximum number of class types */
+#define CKRM_MAX_CLASSTYPE_NAME     32         /* maximum classtype name 
length */
+
+#define CKRM_MAX_RES_CTLRS           8 /* maximum resource controllers per 
classtype */
+#define CKRM_MAX_RES_NAME          128 /* maximum resource controller name 
length */
+
+struct ckrm_core_class;
+struct ckrm_classtype;
+
+/*
+ * Share specifications
+ */
+
+struct ckrm_shares {
+       int my_guarantee;
+       int my_limit;
+       int total_guarantee;
+       int max_limit;
+       int unused_guarantee;   /* not used as parameters */
+       int cur_max_limit;      /* not used as parameters */
+};
+
+#define CKRM_SHARE_UNCHANGED   (-1)
+#define CKRM_SHARE_DONTCARE    (-2)
+#define CKRM_SHARE_DFLT_TOTAL_GUARANTEE        (100)
+#define CKRM_SHARE_DFLT_MAX_LIMIT      (100)
+
+/*
+ * RESOURCE CONTROLLERS
+ */
+
+/* resource controller callback structure */
+
+struct ckrm_res_ctlr {
+       char res_name[CKRM_MAX_RES_NAME];
+       int res_hdepth;         /* maximum hierarchy */
+       int resid;              /* (for now) same as the enum resid */
+       struct ckrm_classtype *classtype;    /* classtype owning this res ctlr 
*/
+
+       /* allocate/free new resource class object for resource controller */
+       void *(*res_alloc) (struct ckrm_core_class * this,
+                           struct ckrm_core_class * parent);
+       void (*res_free) (void *);
+
+       /* set/get limits/guarantees for a resource controller class */
+       int (*set_share_values) (void *, struct ckrm_shares * shares);
+       int (*get_share_values) (void *, struct ckrm_shares * shares);
+
+       /* statistics and configuration access */
+       int (*get_stats) (void *, struct seq_file *);
+       int (*reset_stats) (void *);
+       int (*show_config) (void *, struct seq_file *);
+       int (*set_config) (void *, const char *cfgstr);
+
+       void (*change_resclass) (void *, void *, void *);
+};
+
+/*
+ * CKRM_CLASSTYPE
+ *
+ * A <struct ckrm_classtype> object describes a dimension for CKRM to classify 
+ * along. Need to provide methods to create and manipulate class objects in
+ * this dimension
+ */
+
+/* list of predefined class types, we always recognize */
+#define CKRM_CLASSTYPE_TASK_CLASS    0
+#define CKRM_CLASSTYPE_SOCKET_CLASS  1
+#define CKRM_RESV_CLASSTYPES         2 /* always +1 of last known type */
+
+#define CKRM_MAX_TYPENAME_LEN       32
+
+struct ckrm_classtype {
+       /* TODO: Review for cache alignment */
+
+       /* resource controllers */
+
+       spinlock_t res_ctlrs_lock;  /* protect res ctlr related data */
+       int max_res_ctlrs;          /* max number of res ctlrs allowed */
+       int max_resid;              /* max resid used */
+       int resid_reserved;         /* max number of reserved controllers */
+       long bit_res_ctlrs;         /* bitmap of resource ID used */
+       atomic_t nr_resusers[CKRM_MAX_RES_CTLRS];
+       struct ckrm_res_ctlr *res_ctlrs[CKRM_MAX_RES_CTLRS];
+
+       /* state about my classes */
+
+       struct ckrm_core_class *default_class;  
+       struct list_head classes;  /* link all classes of this classtype */
+       int num_classes;         
+
+       /* state about my ce interaction */
+       atomic_t ce_regd;               /* if CE registered */
+       int ce_cb_active;               /* if Callbacks active */
+       atomic_t ce_nr_users;           /* number of active transient calls */
+       struct ckrm_eng_callback ce_callbacks;  /* callback engine */
+
+       /* Begin classtype-rcfs private data. No rcfs/fs specific types used.  
*/
+
+       int mfidx;              /* Index into genmfdesc array used to 
initialize */
+       void *mfdesc;           /* Array of descriptors of root and magic files 
*/
+       int mfcount;            /* length of above array */
+       void *rootde;           /* root dentry created by rcfs */
+       /* End rcfs private data */
+
+       char name[CKRM_MAX_TYPENAME_LEN]; /* currently same as mfdesc[0]->name  
*/
+                                         /* but could be different */
+       int type_id;                      /* unique TypeID */
+       int maxdepth;                     /* maximum depth supported */
+
+       /* functions to be called on any class type by external API's */
+
+       struct ckrm_core_class *(*alloc) (struct ckrm_core_class * parent, 
+                                         const char *name);    
+       int (*free) (struct ckrm_core_class * cls);     
+       int (*show_members) (struct ckrm_core_class *, struct seq_file *);
+       int (*show_stats) (struct ckrm_core_class *, struct seq_file *);
+       int (*show_config) (struct ckrm_core_class *, struct seq_file *);
+       int (*show_shares) (struct ckrm_core_class *, struct seq_file *);
+
+       int (*reset_stats) (struct ckrm_core_class *, const char *resname,
+                           const char *);
+       int (*set_config) (struct ckrm_core_class *, const char *resname,
+                          const char *cfgstr);
+       int (*set_shares) (struct ckrm_core_class *, const char *resname,
+                          struct ckrm_shares * shares);
+       int (*forced_reclassify) (struct ckrm_core_class *, const char *);
+
+       /* functions to be called on a class type by ckrm internals */
+
+       /* class initialization for new RC */
+       void (*add_resctrl) (struct ckrm_core_class *, int resid);      
+};
+
+/*
+ * CKRM CORE CLASS
+ *      common part to any class structure (i.e. instance of a classtype)
+ */
+
+/*
+ * basic definition of a hierarchy that is to be used by the the CORE classes
+ * and can be used by the resource class objects
+ */
+
+#define CKRM_CORE_MAGIC                0xBADCAFFE
+
+struct ckrm_hnode {
+       struct ckrm_core_class *parent;
+       struct list_head siblings;      
+       struct list_head children;      
+};
+
+struct ckrm_core_class {
+       struct ckrm_classtype *classtype;       
+       void *res_class[CKRM_MAX_RES_CTLRS];    /* resource classes */
+       spinlock_t class_lock;                  /* protects list,array above */
+
+       struct list_head objlist;               /* generic object list */
+       struct list_head clslist;               /* peer classtype classes */
+       struct dentry *dentry;                  /* dentry of inode in the RCFS 
*/
+       int magic;
+
+       struct ckrm_hnode hnode;                /* hierarchy */
+       rwlock_t hnode_rwlock;                  /* protects hnode above. */
+       atomic_t refcnt;
+       const char *name;
+       int delayed;                            /* core deletion delayed  */
+                                               /* because of race conditions */
+};
+
+/* type coerce between derived class types and ckrm core class type */
+#define class_type(type,coreptr)   container_of(coreptr,type,core)
+#define class_core(clsptr)         (&(clsptr)->core)
+/* locking classes */
+#define class_lock(coreptr)        spin_lock(&(coreptr)->class_lock)
+#define class_unlock(coreptr)      spin_unlock(&(coreptr)->class_lock)
+/* what type is a class of ISA */
+#define class_isa(clsptr)          (class_core(clsptr)->classtype)
+
+/*
+ * OTHER
+ */
+
+#define ckrm_get_res_class(rescls, resid, type) \
+       ((type*) (((resid != -1) && ((rescls) != NULL) \
+                          && ((rescls) != (void *)-1)) ? \
+        ((struct ckrm_core_class *)(rescls))->res_class[resid] : NULL))
+
+
+extern int ckrm_register_res_ctlr(struct ckrm_classtype *, struct 
ckrm_res_ctlr *);
+extern int ckrm_unregister_res_ctlr(struct ckrm_res_ctlr *);
+
+extern int ckrm_validate_and_grab_core(struct ckrm_core_class *core);
+extern int ckrm_init_core_class(struct ckrm_classtype *clstype,
+                               struct ckrm_core_class *dcore,
+                               struct ckrm_core_class *parent,
+                               const char *name);
+extern int ckrm_release_core_class(struct ckrm_core_class *);  
+
+/* TODO: can disappear after cls del debugging */
+
+extern struct ckrm_res_ctlr *ckrm_resctlr_lookup(struct ckrm_classtype *type,
+                                                const char *resname);
+
+extern void ckrm_lock_hier(struct ckrm_core_class *);
+extern void ckrm_unlock_hier(struct ckrm_core_class *);
+extern struct ckrm_core_class *ckrm_get_next_child(struct ckrm_core_class *,
+                                                  struct ckrm_core_class *);
+
+extern void child_guarantee_changed(struct ckrm_shares *, int, int);
+extern void child_maxlimit_changed(struct ckrm_shares *, int);
+extern int set_shares(struct ckrm_shares *, struct ckrm_shares *,
+                     struct ckrm_shares *);
+
+/* classtype registration and lookup */
+extern int ckrm_register_classtype(struct ckrm_classtype *clstype);
+extern int ckrm_unregister_classtype(struct ckrm_classtype *clstype);
+extern struct ckrm_classtype *ckrm_find_classtype_by_name(const char *name);
+
+/* default functions that can be used in classtypes's function table */
+extern int ckrm_class_show_shares(struct ckrm_core_class *core,
+                                 struct seq_file *seq);
+extern int ckrm_class_show_stats(struct ckrm_core_class *core,
+                                struct seq_file *seq);
+extern int ckrm_class_show_config(struct ckrm_core_class *core,
+                                 struct seq_file *seq);
+extern int ckrm_class_set_config(struct ckrm_core_class *core,
+                                const char *resname, const char *cfgstr);
+extern int ckrm_class_set_shares(struct ckrm_core_class *core,
+                                const char *resname,
+                                struct ckrm_shares *shares);
+extern int ckrm_class_reset_stats(struct ckrm_core_class *core,
+                                 const char *resname, const char *unused);
+
+static inline void ckrm_core_grab(struct ckrm_core_class *core)
+{
+       if (core)
+               atomic_inc(&core->refcnt);
+}
+
+static inline void ckrm_core_drop(struct ckrm_core_class *core)
+{
+       /* only make definition available in this context */
+       extern void ckrm_free_core_class(struct ckrm_core_class *core);
+       if (core && (atomic_dec_and_test(&core->refcnt)))
+               ckrm_free_core_class(core);
+}
+
+static inline unsigned int ckrm_is_core_valid(struct ckrm_core_class * core)
+{
+       return (core && (core->magic == CKRM_CORE_MAGIC));
+}
+
+/*
+ * iterate through all associate resource controllers:
+ * requires following arguments (ckrm_core_class *cls, 
+ *                               ckrm_res_ctrl   *ctlr,
+ *                               void            *robj,
+ *                               int              bmap)
+ */
+
+#define forall_class_resobjs(cls,rcbs,robj,bmap)                       \
+       for ( bmap=((cls->classtype)->bit_res_ctlrs) ;                  \
+            ({ int rid; ((rid=ffs(bmap)-1) >= 0) &&                    \
+                        (bmap &= ~(1<<rid),                            \
+                               ((rcbs=cls->classtype->res_ctlrs[rid])  \
+                                && (robj=cls->res_class[rid]))); });   \
+           )
+
+extern struct ckrm_classtype *ckrm_classtypes[];       
+
+/*
+ * CE Invocation interface
+ */
+
+#define ce_protect(ctype)      (atomic_inc(&((ctype)->ce_nr_users)))
+#define ce_release(ctype)      (atomic_dec(&((ctype)->ce_nr_users)))
+
+/* CE Classification callbacks with */
+
+#define CE_CLASSIFY_NORET(ctype, event, objs_to_classify...)           \
+do {                                                                   \
+       if ((ctype)->ce_cb_active                                       \
+           && (test_bit(event,&(ctype)->ce_callbacks.c_interest)))     \
+               (*(ctype)->ce_callbacks.classify)(event,                \
+                                                 objs_to_classify);    \
+} while (0)
+
+#define CE_CLASSIFY_RET(ret, ctype, event, objs_to_classify...)                
\
+do {                                                                   \
+       if ((ctype)->ce_cb_active                                       \
+           && (test_bit(event,&(ctype)->ce_callbacks.c_interest)))     \
+               ret = (*(ctype)->ce_callbacks.classify)(event,          \
+                                                       objs_to_classify);\
+} while (0)
+
+#define CE_NOTIFY(ctype, event, cls, objs_to_classify)                 \
+do {                                                                   \
+       if ((ctype)->ce_cb_active                                       \
+           && (test_bit(event,&(ctype)->ce_callbacks.n_interest)))     \
+               (*(ctype)->ce_callbacks.notify)(event,                  \
+                                               cls,objs_to_classify);  \
+} while (0)
+
+/*
+ * RCFS related 
+ */
+
+/* vars needed by other modules/core */
+
+extern int rcfs_mounted;
+extern int rcfs_engine_regd;
+
+#endif /* CONFIG_CKRM */
+#endif /* _LINUX_CKRM_RC_H */
Index: linux-2.6.11-rc5/include/linux/rcfs.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.11-rc5/include/linux/rcfs.h       2005-02-24 00:55:01.435484361 
-0800
@@ -0,0 +1,96 @@
+#ifndef _LINUX_RCFS_H
+#define _LINUX_RCFS_H
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/ckrm_events.h>
+#include <linux/ckrm_rc.h>
+#include <linux/ckrm_ce.h>
+
+/*
+ * The following declarations cannot be included in any of ckrm*.h files 
+ * without jumping hoops. Remove later when rearrangements done
+ */
+
+#define RCFS_MAGIC     0x4feedbac
+#define RCFS_MAGF_NAMELEN 20
+extern int RCFS_IS_MAGIC;
+
+#define rcfs_is_magic(dentry)  ((dentry)->d_fsdata == &RCFS_IS_MAGIC)
+
+struct rcfs_inode_info {
+       struct ckrm_core_class *core;
+       char *name;
+       struct inode vfs_inode;
+};
+
+#define RCFS_DEFAULT_DIR_MODE  (S_IFDIR | S_IRUGO | S_IXUGO)
+#define RCFS_DEFAULT_FILE_MODE (S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP |S_IROTH)
+
+struct rcfs_magf {
+       char name[RCFS_MAGF_NAMELEN];
+       int mode;
+       struct inode_operations *i_op;
+       struct file_operations *i_fop;
+};
+
+struct rcfs_mfdesc {
+       struct rcfs_magf *rootmf;       /* Root directory and its magic files */
+       int rootmflen;                  /* length of above array */
+       /*
+        * Can have a different magf describing magic files 
+        * for non-root entries too.
+        */
+};
+
+extern struct rcfs_mfdesc *genmfdesc[];
+
+struct rcfs_inode_info *RCFS_I(struct inode *inode);
+
+int rcfs_empty(struct dentry *);
+struct inode *rcfs_get_inode(struct super_block *, int, dev_t);
+int rcfs_mknod(struct inode *, struct dentry *, int, dev_t);
+int _rcfs_mknod(struct inode *, struct dentry *, int, dev_t);
+int rcfs_mkdir(struct inode *, struct dentry *, int);
+struct ckrm_core_class *rcfs_make_core(struct dentry *, struct ckrm_core_class 
*);
+struct dentry *rcfs_set_magf_byname(char *, void *);
+
+struct dentry *rcfs_create_internal(struct dentry *, struct rcfs_magf *, int);
+int rcfs_delete_internal(struct dentry *);
+int rcfs_create_magic(struct dentry *, struct rcfs_magf *, int);
+int rcfs_clear_magic(struct dentry *);
+
+extern struct super_operations rcfs_super_ops;
+extern struct address_space_operations rcfs_aops;
+
+extern struct inode_operations rcfs_dir_inode_operations;
+extern struct inode_operations rcfs_rootdir_inode_operations;
+extern struct inode_operations rcfs_file_inode_operations;
+
+extern struct file_operations target_fileops;
+extern struct file_operations shares_fileops;
+extern struct file_operations stats_fileops;
+extern struct file_operations config_fileops;
+extern struct file_operations members_fileops;
+extern struct file_operations reclassify_fileops;
+extern struct file_operations rcfs_file_operations;
+
+/* Callbacks into rcfs from ckrm */
+
+struct rcfs_functions {
+       int (*mkroot) (struct rcfs_magf *, int, struct dentry **);
+       int (*rmroot) (struct dentry *);
+       int (*register_classtype) (struct ckrm_classtype *);
+       int (*deregister_classtype) (struct ckrm_classtype *);
+};
+
+int rcfs_register_classtype(struct ckrm_classtype *);
+int rcfs_deregister_classtype(struct ckrm_classtype *);
+int rcfs_mkroot(struct rcfs_magf *, int, struct dentry **);
+int rcfs_rmroot(struct dentry *);
+
+#define RCFS_ROOT "/rcfs"      /* TODO:  Should use the mount point */
+extern struct dentry *rcfs_rootde;
+extern struct rbce_eng_callback rcfs_eng_callbacks;
+
+#endif /* _LINUX_RCFS_H */
Index: linux-2.6.11-rc5/include/linux/sched.h
===================================================================
--- linux-2.6.11-rc5.orig/include/linux/sched.h 2005-02-24 00:54:56.482081606 
-0800
+++ linux-2.6.11-rc5/include/linux/sched.h      2005-02-24 00:55:01.436484241 
-0800
@@ -689,6 +689,11 @@
 #ifdef CONFIG_DELAY_ACCT
        struct task_delay_info delays;
 #endif
+#ifdef CONFIG_CKRM
+       spinlock_t  ckrm_tsklock;
+       void       *ce_data;
+#endif
+
 };
 
 static inline pid_t process_group(struct task_struct *tsk)
Index: linux-2.6.11-rc5/init/main.c
===================================================================
--- linux-2.6.11-rc5.orig/init/main.c   2005-02-23 20:02:22.000000000 -0800
+++ linux-2.6.11-rc5/init/main.c        2005-02-24 00:55:01.447482914 -0800
@@ -46,6 +46,7 @@
 #include <linux/rmap.h>
 #include <linux/mempolicy.h>
 #include <linux/key.h>
+#include <linux/ckrm_events.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -456,6 +457,7 @@
        rcu_init();
        init_IRQ();
        pidhash_init();
+       ckrm_init();
        init_timers();
        softirq_init();
        time_init();
Index: linux-2.6.11-rc5/kernel/ckrm/ckrm.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.11-rc5/kernel/ckrm/ckrm.c 2005-02-24 00:55:01.448482794 -0800
@@ -0,0 +1,892 @@
+/* ckrm.c - Class-based Kernel Resource Management (CKRM)
+ *
+ * Copyright (C) Hubertus Franke, IBM Corp. 2003, 2004
+ *           (C) Shailabh Nagar,  IBM Corp. 2003, 2004
+ *           (C) Chandra Seetharaman,  IBM Corp. 2003
+ *          (C) Vivek Kashyap, IBM Corp. 2004
+ * 
+ * 
+ * Provides kernel API of CKRM for in-kernel,per-resource controllers 
+ * (one each for cpu, memory, io, network) and callbacks for 
+ * classification modules.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/ckrm_rc.h>
+#include <linux/rcfs.h>
+#include <net/sock.h>
+#include <linux/ip.h>
+
+#include <asm/uaccess.h>
+#include <asm/errno.h>
+
+rwlock_t ckrm_class_lock;      /* protects classlists */
+
+struct rcfs_functions rcfs_fn;
+EXPORT_SYMBOL_GPL(rcfs_fn);
+
+int rcfs_engine_regd;          /* rcfs state needed by another module */
+EXPORT_SYMBOL_GPL(rcfs_engine_regd);
+
+int rcfs_mounted;
+EXPORT_SYMBOL_GPL(rcfs_mounted);
+
+/*
+ * Helper Functions
+ */
+
+/*
+ * Return non-zero if the given resource is registered.
+ */
+inline unsigned int ckrm_is_res_regd(struct ckrm_classtype *clstype, int resid)
+{
+       return ((resid >= 0) && (resid < clstype->max_resid) &&
+               test_bit(resid, &clstype->bit_res_ctlrs)
+           );
+}
+
+/*
+ * Return non-zero if the given core class pointer is valid.
+ */
+struct ckrm_res_ctlr *ckrm_resctlr_lookup(struct ckrm_classtype *clstype,
+                                         const char *resname)
+{
+       int resid = -1;
+
+       if (!clstype || !resname)
+               return NULL;
+       for (resid = 0; resid < clstype->max_resid; resid++) {
+               if (test_bit(resid, &clstype->bit_res_ctlrs)) {
+                       struct ckrm_res_ctlr *rctrl = clstype->res_ctlrs[resid];
+                       if (!strncmp(resname, rctrl->res_name,
+                                    CKRM_MAX_RES_NAME))
+                               return rctrl;
+               }
+       }
+       return NULL;
+}
+
+EXPORT_SYMBOL_GPL(ckrm_resctlr_lookup);
+
+/* given a classname return the class handle and its classtype*/
+void *ckrm_classobj(char *classname, int *classtype_id)
+{
+       int i;
+
+       *classtype_id = -1;
+       if (!classname || !*classname) {
+               return NULL;
+       }
+
+       read_lock(&ckrm_class_lock);
+       for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
+               struct ckrm_classtype *ctype = ckrm_classtypes[i];
+               struct ckrm_core_class *core;
+
+               if (ctype == NULL)
+                       continue;
+               list_for_each_entry(core, &ctype->classes, clslist) {
+                       if (core->name && !strcmp(core->name, classname)) {
+                               /* FIXME:   should grep reference. */
+                               *classtype_id = ctype->type_id;
+                               return core;
+                       }
+               }
+       }
+       read_unlock(&ckrm_class_lock);
+       return NULL;
+}
+
+EXPORT_SYMBOL_GPL(ckrm_is_res_regd);
+EXPORT_SYMBOL_GPL(ckrm_classobj);
+
+/*
+ * Internal Functions/macros
+ */
+
+static inline void set_callbacks_active(struct ckrm_classtype *ctype)
+{
+       ctype->ce_cb_active = ((atomic_read(&ctype->ce_regd) > 0) &&
+                              (ctype->ce_callbacks.always_callback
+                               || (ctype->num_classes > 1)));
+}
+
+int ckrm_validate_and_grab_core(struct ckrm_core_class *core)
+{
+       int rc = 0;
+       read_lock(&ckrm_class_lock);
+       if (likely(ckrm_is_core_valid(core))) {
+               ckrm_core_grab(core);
+               rc = 1;
+       }
+       read_unlock(&ckrm_class_lock);
+       return rc;
+}
+
+/*
+ * Interfaces for classification engine
+ */
+
+/*
+ * Registering a callback structure by the classification engine.
+ *
+ * Returns typeId of class on success -errno for failure.
+ */
+int ckrm_register_engine(const char *typename, struct ckrm_eng_callback * ecbs)
+{
+       struct ckrm_classtype *ctype;
+
+       ctype = ckrm_find_classtype_by_name(typename);
+       if (ctype == NULL)
+               return (-ENOENT);
+
+       atomic_inc(&ctype->ce_regd);
+
+       /* another engine registered or trying to register ? */
+       if (atomic_read(&ctype->ce_regd) != 1) {
+               atomic_dec(&ctype->ce_regd);
+               return (-EBUSY);
+       }
+
+       /*
+        * One of the following must be set: 
+        * classify, class_delete (due to object reference) or 
+        * notify (case where notification supported but not classification)
+        * The function pointer must be set the momement the mask is non-null
+        */
+       if (!(((ecbs->classify) && (ecbs->class_delete)) || (ecbs->notify)) ||
+           (ecbs->c_interest && ecbs->classify == NULL) ||
+           (ecbs->n_interest && ecbs->notify == NULL)) {
+               atomic_dec(&ctype->ce_regd);
+               return -EINVAL;
+       }
+
+       ctype->ce_callbacks = *ecbs;
+       set_callbacks_active(ctype);
+
+       if (ctype->ce_callbacks.class_add) {
+               struct ckrm_core_class *core;
+
+               read_lock(&ckrm_class_lock);
+               list_for_each_entry(core, &ctype->classes, clslist) {
+                       (*ctype->ce_callbacks.class_add) (core->name, core,
+                                                         ctype->type_id);
+               }
+               read_unlock(&ckrm_class_lock);
+       }
+       return ctype->type_id;
+}
+
+/*
+ * Unregistering a callback structure by the classification engine.
+ *
+ * Returns 0 on success -errno for failure.
+ */
+int ckrm_unregister_engine(const char *typename)
+{
+       struct ckrm_classtype *ctype;
+
+       ctype = ckrm_find_classtype_by_name(typename);
+       if (ctype == NULL)
+               return (-ENOENT);
+
+       ctype->ce_cb_active = 0;
+       if (atomic_read(&ctype->ce_nr_users) > 1) {
+               /* Somebody is currently using the engine, cannot deregister. */
+               return (-EAGAIN);
+       }
+       atomic_set(&ctype->ce_regd, 0);
+       memset(&ctype->ce_callbacks, 0, sizeof(struct ckrm_eng_callback));
+       return 0;
+}
+
+/*
+ * Interfaces to manipulate class (core or resource) hierarchies
+ */
+
+static void
+ckrm_add_child(struct ckrm_core_class *parent, struct ckrm_core_class *child)
+{
+       struct ckrm_hnode *cnode = &child->hnode;
+
+       if (!ckrm_is_core_valid(child)) {
+               printk(KERN_ERR "Invalid child %p given in ckrm_add_child\n",
+                      child);
+               return;
+       }
+       class_lock(child);
+       INIT_LIST_HEAD(&cnode->children);
+       INIT_LIST_HEAD(&cnode->siblings);
+
+       if (parent) {
+               struct ckrm_hnode *pnode;
+
+               if (!ckrm_is_core_valid(parent)) {
+                       printk(KERN_ERR
+                              "Invalid parent %p given in ckrm_add_child\n",
+                              parent);
+                       parent = NULL;
+               } else {
+                       pnode = &parent->hnode;
+                       write_lock(&parent->hnode_rwlock);
+                       list_add(&cnode->siblings, &pnode->children);
+                       write_unlock(&parent->hnode_rwlock);
+               }
+       }
+       cnode->parent = parent;
+       class_unlock(child);
+       return;
+}
+
+static int ckrm_remove_child(struct ckrm_core_class *child)
+{
+       struct ckrm_hnode *cnode, *pnode;
+       struct ckrm_core_class *parent;
+
+       if (!ckrm_is_core_valid(child)) {
+               printk(KERN_ERR "Invalid child %p given"
+                               " in ckrm_remove_child\n",
+                       child);
+               return 0;
+       }
+
+       cnode = &child->hnode;
+       parent = cnode->parent;
+       if (!ckrm_is_core_valid(parent)) {
+               printk(KERN_ERR "Invalid parent %p in ckrm_remove_child\n",
+                      parent);
+               return 0;
+       }
+
+       pnode = &parent->hnode;
+
+       class_lock(child);
+       /* ensure that the node does not have children */
+       if (!list_empty(&cnode->children)) {
+               class_unlock(child);
+               return 0;
+       }
+       write_lock(&parent->hnode_rwlock);
+       list_del(&cnode->siblings);
+       write_unlock(&parent->hnode_rwlock);
+       cnode->parent = NULL;
+       class_unlock(child);
+       return 1;
+}
+
+void ckrm_lock_hier(struct ckrm_core_class *parent)
+{
+       if (ckrm_is_core_valid(parent)) {
+               read_lock(&parent->hnode_rwlock);
+       }
+}
+
+void ckrm_unlock_hier(struct ckrm_core_class *parent)
+{
+       if (ckrm_is_core_valid(parent)) {
+               read_unlock(&parent->hnode_rwlock);
+       }
+}
+
+/*
+ * hnode_rwlock of the parent core class must held in read mode.
+ * external callers should 've called ckrm_lock_hier before calling this
+ * function.
+ */
+#define hnode_2_core(ptr) \
+((ptr)? container_of(ptr, struct ckrm_core_class, hnode) : NULL)
+
+struct ckrm_core_class *ckrm_get_next_child(struct ckrm_core_class *parent,
+                                           struct ckrm_core_class *child)
+{
+       struct list_head *cnode;
+       struct ckrm_hnode *next_cnode;
+       struct ckrm_core_class *next_childcore;
+
+       if (!ckrm_is_core_valid(parent)) {
+               printk(KERN_ERR "Invalid parent %p in ckrm_get_next_child\n",
+                      parent);
+               return NULL;
+       }
+       if (list_empty(&parent->hnode.children)) {
+               return NULL;
+       }
+       if (child) {
+               if (!ckrm_is_core_valid(child)) {
+                       printk(KERN_ERR
+                              "Invalid child %p in ckrm_get_next_child\n",
+                              child);
+                       return NULL;
+               }
+               cnode = child->hnode.siblings.next;
+       } else {
+               cnode = parent->hnode.children.next;
+       }
+
+       if (cnode == &parent->hnode.children) { /* back at the anchor */
+               return NULL;
+       }
+
+       next_cnode = container_of(cnode, struct ckrm_hnode, siblings);
+       next_childcore = hnode_2_core(next_cnode);
+
+       if (!ckrm_is_core_valid(next_childcore)) {
+               printk(KERN_ERR
+                      "Invalid next child %p in ckrm_get_next_child\n",
+                      next_childcore);
+               return NULL;
+       }
+       return next_childcore;
+}
+
+EXPORT_SYMBOL_GPL(ckrm_lock_hier);
+EXPORT_SYMBOL_GPL(ckrm_unlock_hier);
+EXPORT_SYMBOL_GPL(ckrm_get_next_child);
+
+static void
+ckrm_alloc_res_class(struct ckrm_core_class *core,
+                    struct ckrm_core_class *parent, int resid)
+{
+
+       struct ckrm_classtype *clstype;
+       /* 
+        * Allocate a resource class only if the resource controller has
+        * registered with core and the engine requests for the class.
+        */
+       if (!ckrm_is_core_valid(core))
+               return;
+       clstype = core->classtype;
+       core->res_class[resid] = NULL;
+
+       if (test_bit(resid, &clstype->bit_res_ctlrs)) {
+               struct ckrm_res_ctlr *rcbs;
+
+               atomic_inc(&clstype->nr_resusers[resid]);
+               rcbs = clstype->res_ctlrs[resid];
+
+               if (rcbs && rcbs->res_alloc) {
+                       core->res_class[resid] =
+                           (*rcbs->res_alloc) (core, parent);
+                       if (core->res_class[resid])
+                               return;
+                       printk(KERN_ERR "Error creating res class\n");
+               }
+               atomic_dec(&clstype->nr_resusers[resid]);
+       }
+}
+
+/*
+ * Initialize a core class
+ *
+ */
+
+int
+ckrm_init_core_class(struct ckrm_classtype *clstype,
+                    struct ckrm_core_class *dcore,
+                    struct ckrm_core_class *parent, const char *name)
+{
+       /* TODO:  Should replace name with dentry or add dentry? */
+       int i;
+
+       /* TODO:  How is this used in initialization? */
+       pr_debug("name %s => %p\n", name ? name : "default", dcore);
+       if ((dcore != clstype->default_class) && (!ckrm_is_core_valid(parent))){
+               printk(KERN_NOTICE "error not a valid parent %p\n", parent);
+               return -EINVAL;
+       }
+       dcore->classtype = clstype;
+       dcore->magic = CKRM_CORE_MAGIC;
+       dcore->name = name;
+       dcore->class_lock = SPIN_LOCK_UNLOCKED;
+       dcore->hnode_rwlock = RW_LOCK_UNLOCKED;
+       dcore->delayed = 0;
+
+       atomic_set(&dcore->refcnt, 0);
+       write_lock(&ckrm_class_lock);
+
+       INIT_LIST_HEAD(&dcore->objlist);
+       list_add_tail(&dcore->clslist, &clstype->classes);
+
+       clstype->num_classes++;
+       set_callbacks_active(clstype);
+
+       write_unlock(&ckrm_class_lock);
+       ckrm_add_child(parent, dcore);
+
+       for (i = 0; i < clstype->max_resid; i++)
+               ckrm_alloc_res_class(dcore, parent, i);
+
+       /* fix for race condition seen in stress with numtasks */
+       if (parent)
+               ckrm_core_grab(parent);
+
+       ckrm_core_grab(dcore);
+       return 0;
+}
+
+static void ckrm_free_res_class(struct ckrm_core_class *core, int resid)
+{
+       /* 
+        * Free a resource class only if the resource controller has
+        * registered with core 
+        */
+       if (core->res_class[resid]) {
+               struct ckrm_res_ctlr *rcbs;
+               struct ckrm_classtype *clstype = core->classtype;
+
+               atomic_inc(&clstype->nr_resusers[resid]);
+               rcbs = clstype->res_ctlrs[resid];
+
+               if (rcbs->res_free) {
+                       (*rcbs->res_free) (core->res_class[resid]);
+                       /* compensate inc in alloc */
+                       atomic_dec(&clstype->nr_resusers[resid]); 
+               }
+               atomic_dec(&clstype->nr_resusers[resid]);
+       }
+       core->res_class[resid] = NULL;
+}
+
+/*
+ * Free a core class 
+ *   requires that all tasks were previously reassigned to another class
+ *
+ * Returns 0 on success -errno on failure.
+ */
+
+void ckrm_free_core_class(struct ckrm_core_class *core)
+{
+       int i;
+       struct ckrm_classtype *clstype = core->classtype;
+       struct ckrm_core_class *parent = core->hnode.parent;
+
+       pr_debug("core=%p:%s parent=%p:%s\n", core, core->name, parent,
+                 parent->name);
+       if (core->delayed) {
+               /* this core was marked as late */
+               printk("class <%s> finally deleted %lu\n", core->name, jiffies);
+       }
+       if (ckrm_remove_child(core) == 0) {
+               printk("Core class removal failed. Chilren present\n");
+       }
+       for (i = 0; i < clstype->max_resid; i++) {
+               ckrm_free_res_class(core, i);
+       }
+
+       write_lock(&ckrm_class_lock);
+       /* Clear the magic, so we would know if this core is reused. */
+       core->magic = 0;
+#if 0                          /* Dynamic not yet enabled */
+       core->res_class = NULL;
+#endif
+       /* Remove this core class from its linked list. */
+       list_del(&core->clslist);
+       clstype->num_classes--;
+       set_callbacks_active(clstype);
+       write_unlock(&ckrm_class_lock);
+
+       /* fix for race condition seen in stress with numtasks */
+       if (parent)
+               ckrm_core_drop(parent);
+
+       kfree(core);
+}
+
+int ckrm_release_core_class(struct ckrm_core_class *core)
+{
+       if (!ckrm_is_core_valid(core)) /* Invalid core */
+               return -EINVAL;
+
+       if (core == core->classtype->default_class)
+               return 0;
+
+       /* need to make sure that the classgot really dropped */
+       if (atomic_read(&core->refcnt) != 1) {
+               pr_debug("class <%s> deletion delayed refcnt=%d jif=%ld\n",
+                         core->name, atomic_read(&core->refcnt), jiffies);
+               core->delayed = 1;      /* just so we have a ref point */
+       }
+       ckrm_core_drop(core);
+       return 0;
+}
+
+/*
+ * Interfaces for the resource controller
+ */
+/*
+ * Registering a callback structure by the resource controller.
+ *
+ * Returns the resource id(0 or +ve) on success, -errno for failure.
+ */
+static int
+ckrm_register_res_ctlr_intern(struct ckrm_classtype *clstype,
+                             struct ckrm_res_ctlr * rcbs)
+{
+       int resid, ret, i;
+
+       if (!rcbs)
+               return -EINVAL;
+
+       resid = rcbs->resid;
+
+       spin_lock(&clstype->res_ctlrs_lock);
+       printk(KERN_WARNING "resid is %d name is %s %s\n",
+              resid, rcbs->res_name, clstype->res_ctlrs[resid]->res_name);
+       if (resid >= 0) {
+               if ((resid < CKRM_MAX_RES_CTLRS)
+                   && (clstype->res_ctlrs[resid] == NULL)) {
+                       clstype->res_ctlrs[resid] = rcbs;
+                       atomic_set(&clstype->nr_resusers[resid], 0);
+                       set_bit(resid, &clstype->bit_res_ctlrs);
+                       ret = resid;
+                       if (resid >= clstype->max_resid) {
+                               clstype->max_resid = resid + 1;
+                       }
+               } else {
+                       ret = -EBUSY;
+               }
+               spin_unlock(&clstype->res_ctlrs_lock);
+               return ret;
+       }
+       for (i = clstype->resid_reserved; i < clstype->max_res_ctlrs; i++) {
+               if (clstype->res_ctlrs[i] == NULL) {
+                       clstype->res_ctlrs[i] = rcbs;
+                       rcbs->resid = i;
+                       atomic_set(&clstype->nr_resusers[i], 0);
+                       set_bit(i, &clstype->bit_res_ctlrs);
+                       if (i >= clstype->max_resid) {
+                               clstype->max_resid = i + 1;
+                       }
+                       spin_unlock(&clstype->res_ctlrs_lock);
+                       return i;
+               }
+       }
+       spin_unlock(&clstype->res_ctlrs_lock);
+       return (-ENOMEM);
+}
+
+int
+ckrm_register_res_ctlr(struct ckrm_classtype *clstype, struct ckrm_res_ctlr 
*rcbs)
+{
+       struct ckrm_core_class *core;
+       int resid;
+
+       resid = ckrm_register_res_ctlr_intern(clstype, rcbs);
+
+       if (resid >= 0) {
+               /* run through all classes and create the resource class 
+                * object and if necessary "initialize" class in context 
+                * of this resource 
+                */
+               read_lock(&ckrm_class_lock);
+               list_for_each_entry(core, &clstype->classes, clslist) {
+                       printk("CKRM .. create res clsobj for resouce <%s>"
+                              "class <%s> par=%p\n", rcbs->res_name, 
+                              core->name, core->hnode.parent);
+                       ckrm_alloc_res_class(core, core->hnode.parent, resid);
+
+                       if (clstype->add_resctrl) { 
+                               /* FIXME: this should be mandatory */
+                               (*clstype->add_resctrl) (core, resid);
+                       }
+               }
+               read_unlock(&ckrm_class_lock);
+       }
+       return resid;
+}
+
+/*
+ * Unregistering a callback structure by the resource controller.
+ *
+ * Returns 0 on success -errno for failure.
+ */
+int ckrm_unregister_res_ctlr(struct ckrm_res_ctlr *rcbs)
+{
+       struct ckrm_classtype *clstype = rcbs->classtype;
+       struct ckrm_core_class *core = NULL;
+       int resid = rcbs->resid;
+
+       if ((clstype == NULL) || (resid < 0)) {
+               return -EINVAL;
+       }
+       /* TODO: probably need to also call deregistration function */
+
+       read_lock(&ckrm_class_lock);
+       /* free up this resource from all the classes */
+       list_for_each_entry(core, &clstype->classes, clslist) {
+               ckrm_free_res_class(core, resid);
+       }
+       read_unlock(&ckrm_class_lock);
+
+       if (atomic_read(&clstype->nr_resusers[resid])) {
+               return -EBUSY;
+       }
+
+       spin_lock(&clstype->res_ctlrs_lock);
+       clstype->res_ctlrs[resid] = NULL;
+       clear_bit(resid, &clstype->bit_res_ctlrs);
+       clstype->max_resid = fls(clstype->bit_res_ctlrs);
+       rcbs->resid = -1;
+       spin_unlock(&clstype->res_ctlrs_lock);
+
+       return 0;
+}
+
+/*
+ * Class Type Registration
+ */
+
+/* TODO: What locking is needed here?*/
+
+struct ckrm_classtype *ckrm_classtypes[CKRM_MAX_CLASSTYPES];
+EXPORT_SYMBOL_GPL(ckrm_classtypes);    
+
+int ckrm_register_classtype(struct ckrm_classtype *clstype)
+{
+       int tid = clstype->type_id;
+
+       if (tid != -1) {
+               if ((tid < 0) || (tid > CKRM_MAX_CLASSTYPES)
+                   || (ckrm_classtypes[tid]))
+                       return -EINVAL;
+       } else {
+               int i;
+               for (i = CKRM_RESV_CLASSTYPES; i < CKRM_MAX_CLASSTYPES; i++) {
+                       if (ckrm_classtypes[i] == NULL) {
+                               tid = i;
+                               break;
+                       }
+               }
+       }
+       if (tid == -1)
+               return -EBUSY;
+       clstype->type_id = tid;
+       ckrm_classtypes[tid] = clstype;
+
+       /* TODO: Need to call the callbacks of the RCFS client */
+       if (rcfs_fn.register_classtype) {
+               (*rcfs_fn.register_classtype) (clstype);
+               /* No error return for now. */
+       }
+       return tid;
+}
+
+int ckrm_unregister_classtype(struct ckrm_classtype *clstype)
+{
+       int tid = clstype->type_id;
+
+       if ((tid < 0) || (tid > CKRM_MAX_CLASSTYPES)
+           || (ckrm_classtypes[tid] != clstype))
+               return -EINVAL;
+
+       if (rcfs_fn.deregister_classtype) {
+               (*rcfs_fn.deregister_classtype) (clstype);
+               /* No error return for now */
+       }
+
+       ckrm_classtypes[tid] = NULL;
+       clstype->type_id = -1;
+       return 0;
+}
+
+struct ckrm_classtype *ckrm_find_classtype_by_name(const char *name)
+{
+       int i;
+       for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
+               struct ckrm_classtype *ctype = ckrm_classtypes[i];
+               if (ctype && !strncmp(ctype->name, name, CKRM_MAX_TYPENAME_LEN))
+                       return ctype;
+       }
+       return NULL;
+}
+
+/*
+ *   Generic Functions that can be used as default functions 
+ *   in almost all classtypes
+ *     (a) function iterator over all resource classes of a class
+ *     (b) function invoker on a named resource
+ */
+
+int ckrm_class_show_shares(struct ckrm_core_class *core, struct seq_file *seq)
+{
+       int i;
+       struct ckrm_res_ctlr *rcbs;
+       struct ckrm_classtype *clstype = core->classtype;
+       struct ckrm_shares shares;
+
+       for (i = 0; i < clstype->max_resid; i++) {
+               atomic_inc(&clstype->nr_resusers[i]);
+               rcbs = clstype->res_ctlrs[i];
+               if (rcbs && rcbs->get_share_values) {
+                       (*rcbs->get_share_values) (core->res_class[i], &shares);
+                       seq_printf(seq,"res=%s,guarantee=%d,limit=%d,"
+                                  "total_guarantee=%d,max_limit=%d\n",
+                                  rcbs->res_name, shares.my_guarantee,
+                                  shares.my_limit, shares.total_guarantee,
+                                  shares.max_limit);
+               }
+               atomic_dec(&clstype->nr_resusers[i]);
+       }
+       return 0;
+}
+
+int ckrm_class_show_stats(struct ckrm_core_class *core, struct seq_file *seq)
+{
+       int i;
+       struct ckrm_res_ctlr *rcbs;
+       struct ckrm_classtype *clstype = core->classtype;
+
+       for (i = 0; i < clstype->max_resid; i++) {
+               atomic_inc(&clstype->nr_resusers[i]);
+               rcbs = clstype->res_ctlrs[i];
+               if (rcbs && rcbs->get_stats)
+                       (*rcbs->get_stats) (core->res_class[i], seq);
+               atomic_dec(&clstype->nr_resusers[i]);
+       }
+       return 0;
+}
+
+int ckrm_class_show_config(struct ckrm_core_class *core, struct seq_file *seq)
+{
+       int i;
+       struct ckrm_res_ctlr *rcbs;
+       struct ckrm_classtype *clstype = core->classtype;
+
+       for (i = 0; i < clstype->max_resid; i++) {
+               atomic_inc(&clstype->nr_resusers[i]);
+               rcbs = clstype->res_ctlrs[i];
+               if (rcbs && rcbs->show_config)
+                       (*rcbs->show_config) (core->res_class[i], seq);
+               atomic_dec(&clstype->nr_resusers[i]);
+       }
+       return 0;
+}
+
+int ckrm_class_set_config(struct ckrm_core_class *core, const char *resname,
+                         const char *cfgstr)
+{
+       struct ckrm_classtype *clstype = core->classtype;
+       struct ckrm_res_ctlr *rcbs = ckrm_resctlr_lookup(clstype, resname);
+       int rc;
+
+       if (rcbs == NULL || rcbs->set_config == NULL)
+               return -EINVAL;
+       rc = (*rcbs->set_config) (core->res_class[rcbs->resid], cfgstr);
+       return rc;
+}
+
+#define legalshare(a)   \
+         ( ((a) >=0) \
+          || ((a) == CKRM_SHARE_UNCHANGED) \
+          || ((a) == CKRM_SHARE_DONTCARE) )
+
+int ckrm_class_set_shares(struct ckrm_core_class *core, const char *resname,
+                         struct ckrm_shares *shares)
+{
+       struct ckrm_classtype *clstype = core->classtype;
+       struct ckrm_res_ctlr *rcbs;
+       int rc;
+
+       /* Check for legal values */
+       if (!legalshare(shares->my_guarantee) || !legalshare(shares->my_limit)
+           || !legalshare(shares->total_guarantee)
+           || !legalshare(shares->max_limit))
+               return -EINVAL;
+
+       rcbs = ckrm_resctlr_lookup(clstype, resname);
+       if (rcbs == NULL || rcbs->set_share_values == NULL)
+               return -EINVAL;
+       rc = (*rcbs->set_share_values) (core->res_class[rcbs->resid], shares);
+       return rc;
+}
+
+int ckrm_class_reset_stats(struct ckrm_core_class *core, const char *resname,
+                          const char *unused)
+{
+       struct ckrm_classtype *clstype = core->classtype;
+       struct ckrm_res_ctlr *rcbs = ckrm_resctlr_lookup(clstype, resname);
+       int rc;
+
+       if (rcbs == NULL || rcbs->reset_stats == NULL)
+               return -EINVAL;
+       rc = (*rcbs->reset_stats) (core->res_class[rcbs->resid]);
+       return rc;
+}
+
+/*
+ * Initialization
+ */
+
+void __init ckrm_init(void)
+{
+       printk("CKRM Initialization\n");
+       rwlock_init(&ckrm_class_lock);
+
+       /* register/initialize the Metatypes */
+
+#ifdef CONFIG_CKRM_TYPE_TASKCLASS
+       {
+               extern void ckrm_meta_init_taskclass(void);
+               ckrm_meta_init_taskclass();
+       }
+#endif
+#ifdef CONFIG_CKRM_TYPE_SOCKETCLASS
+       {
+               extern void ckrm_meta_init_sockclass(void);
+               ckrm_meta_init_sockclass();
+       }
+#endif
+       /* prepare init_task and then rely on inheritance of properties */
+       ckrm_cb_newtask(&init_task);
+       printk("CKRM Initialization done\n");
+}
+
+EXPORT_SYMBOL_GPL(ckrm_register_engine);
+EXPORT_SYMBOL_GPL(ckrm_unregister_engine);
+
+EXPORT_SYMBOL_GPL(ckrm_register_res_ctlr);
+EXPORT_SYMBOL_GPL(ckrm_unregister_res_ctlr);
+
+EXPORT_SYMBOL_GPL(ckrm_init_core_class);
+EXPORT_SYMBOL_GPL(ckrm_free_core_class);
+EXPORT_SYMBOL_GPL(ckrm_release_core_class);
+
+EXPORT_SYMBOL_GPL(ckrm_register_classtype);
+EXPORT_SYMBOL_GPL(ckrm_unregister_classtype);
+EXPORT_SYMBOL_GPL(ckrm_find_classtype_by_name);
+
+EXPORT_SYMBOL_GPL(ckrm_core_grab);
+EXPORT_SYMBOL_GPL(ckrm_core_drop);
+EXPORT_SYMBOL_GPL(ckrm_is_core_valid);
+EXPORT_SYMBOL_GPL(ckrm_validate_and_grab_core);
+
+EXPORT_SYMBOL_GPL(ckrm_register_event_set);
+EXPORT_SYMBOL_GPL(ckrm_unregister_event_set);
+EXPORT_SYMBOL_GPL(ckrm_register_event_cb);
+EXPORT_SYMBOL_GPL(ckrm_unregister_event_cb);
+
+EXPORT_SYMBOL_GPL(ckrm_class_show_stats);
+EXPORT_SYMBOL_GPL(ckrm_class_show_config);
+EXPORT_SYMBOL_GPL(ckrm_class_show_shares);
+
+EXPORT_SYMBOL_GPL(ckrm_class_set_config);
+EXPORT_SYMBOL_GPL(ckrm_class_set_shares);
+
+EXPORT_SYMBOL_GPL(ckrm_class_reset_stats);
Index: linux-2.6.11-rc5/kernel/ckrm/ckrmutils.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.11-rc5/kernel/ckrm/ckrmutils.c    2005-02-24 00:55:01.449482673 
-0800
@@ -0,0 +1,188 @@
+/*
+ * ckrmutils.c - Utility functions for CKRM
+ *
+ * Copyright (C) Chandra Seetharaman,  IBM Corp. 2003
+ *           (C) Hubertus Franke    ,  IBM Corp. 2004
+ * 
+ * Provides simple utility functions for the core module, CE and resource
+ * controllers.
+ *
+ * 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 version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/mm.h>
+#include <linux/err.h>
+#include <linux/mount.h>
+#include <linux/module.h>
+#include <linux/ckrm_rc.h>
+
+int get_exe_path_name(struct task_struct *tsk, char *buf, int buflen)
+{
+       struct vm_area_struct *vma;
+       struct vfsmount *mnt;
+       struct mm_struct *mm = get_task_mm(tsk);
+       struct dentry *dentry;
+       char *lname;
+       int rc = 0;
+
+       *buf = '\0';
+       if (!mm) {
+               return -EINVAL;
+       }
+       down_read(&mm->mmap_sem);
+       vma = mm->mmap;
+       while (vma) {
+               if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
+                       dentry = dget(vma->vm_file->f_dentry);
+                       mnt = mntget(vma->vm_file->f_vfsmnt);
+                       lname = d_path(dentry, mnt, buf, buflen);
+                       if (!IS_ERR(lname)) {
+                               strncpy(buf, lname, strlen(lname) + 1);
+                       } else {
+                               rc = (int)PTR_ERR(lname);
+                       }
+                       mntput(mnt);
+                       dput(dentry);
+                       break;
+               }
+               vma = vma->vm_next;
+       }
+       up_read(&mm->mmap_sem);
+       mmput(mm);
+       return rc;
+}
+
+/*
+ * TODO:  Use sparce to enforce cnt_lock.
+ *
+ * must be called with cnt_lock of parres held
+ * Caller is responsible for making sure that the new guarantee doesn't
+ * overflow parent's total guarantee.
+ */
+void child_guarantee_changed(struct ckrm_shares *parent, int cur, int new)
+{
+       if (new == cur || !parent) {
+               return;
+       }
+       if (new != CKRM_SHARE_DONTCARE) {
+               parent->unused_guarantee -= new;
+       }
+       if (cur != CKRM_SHARE_DONTCARE) {
+               parent->unused_guarantee += cur;
+       }
+       return;
+}
+
+/*
+ * must be called with cnt_lock of parres held
+ * Caller is responsible for making sure that the new limit is not more 
+ * than parent's max_limit
+ */
+void child_maxlimit_changed(struct ckrm_shares *parent, int new_limit)
+{
+       if (parent && parent->cur_max_limit < new_limit) {
+               parent->cur_max_limit = new_limit;
+       }
+       return;
+}
+
+/*
+ * Caller is responsible for holding any lock to protect the data
+ * structures passed to this function
+ */
+int
+set_shares(struct ckrm_shares *new, struct ckrm_shares *cur,
+          struct ckrm_shares *par)
+{
+       int rc = -EINVAL;
+       int cur_usage_guar = cur->total_guarantee - cur->unused_guarantee;
+       int increase_by = new->my_guarantee - cur->my_guarantee;
+
+       /* Check total_guarantee for correctness */
+       if (new->total_guarantee <= CKRM_SHARE_DONTCARE) {
+               goto set_share_err;
+       } else if (new->total_guarantee == CKRM_SHARE_UNCHANGED) {
+               /* do nothing */;
+       } else if (cur_usage_guar > new->total_guarantee) {
+               goto set_share_err;
+       }
+       /* Check max_limit for correctness */
+       if (new->max_limit <= CKRM_SHARE_DONTCARE) {
+               goto set_share_err;
+       } else if (new->max_limit == CKRM_SHARE_UNCHANGED) {
+               /* do nothing */;
+       } else if (cur->cur_max_limit > new->max_limit) {
+               goto set_share_err;
+       }
+       /* Check my_guarantee for correctness */
+       if (new->my_guarantee == CKRM_SHARE_UNCHANGED) {
+               /* do nothing */;
+       } else if (new->my_guarantee == CKRM_SHARE_DONTCARE) {
+               /* do nothing */;
+       } else if (par && increase_by > par->unused_guarantee) {
+               goto set_share_err;
+       }
+       /* Check my_limit for correctness */
+       if (new->my_limit == CKRM_SHARE_UNCHANGED) {
+               /* do nothing */;
+       } else if (new->my_limit == CKRM_SHARE_DONTCARE) {
+               /* do nothing */;
+       } else if (par && new->my_limit > par->max_limit) {
+               /* I can't get more limit than my parent's limit */
+               goto set_share_err;
+
+       }
+       /* make sure guarantee is lesser than limit */
+       if (new->my_limit == CKRM_SHARE_DONTCARE) {
+               /* do nothing */;
+       } else if (new->my_limit == CKRM_SHARE_UNCHANGED) {
+               if (new->my_guarantee == CKRM_SHARE_DONTCARE) {
+                       /* do nothing */;
+               } else if (new->my_guarantee == CKRM_SHARE_UNCHANGED) {
+                       /*
+                        * do nothing; earlier setting would have
+                        * taken care of it
+                        */;
+               } else if (new->my_guarantee > cur->my_limit) {
+                       goto set_share_err;
+               }
+       } else {                /* new->my_limit has a valid value */
+               if (new->my_guarantee == CKRM_SHARE_DONTCARE) {
+                       /* do nothing */;
+               } else if (new->my_guarantee == CKRM_SHARE_UNCHANGED) {
+                       if (cur->my_guarantee > new->my_limit) {
+                               goto set_share_err;
+                       }
+               } else if (new->my_guarantee > new->my_limit) {
+                       goto set_share_err;
+               }
+       }
+       if (new->my_guarantee != CKRM_SHARE_UNCHANGED) {
+               child_guarantee_changed(par, cur->my_guarantee,
+                                       new->my_guarantee);
+               cur->my_guarantee = new->my_guarantee;
+       }
+       if (new->my_limit != CKRM_SHARE_UNCHANGED) {
+               child_maxlimit_changed(par, new->my_limit);
+               cur->my_limit = new->my_limit;
+       }
+       if (new->total_guarantee != CKRM_SHARE_UNCHANGED) {
+               cur->unused_guarantee = new->total_guarantee - cur_usage_guar;
+               cur->total_guarantee = new->total_guarantee;
+       }
+       if (new->max_limit != CKRM_SHARE_UNCHANGED) {
+               cur->max_limit = new->max_limit;
+       }
+       rc = 0;
+set_share_err:
+       return rc;
+}
+
+EXPORT_SYMBOL_GPL(get_exe_path_name);
+EXPORT_SYMBOL_GPL(child_guarantee_changed);
+EXPORT_SYMBOL_GPL(child_maxlimit_changed);
+EXPORT_SYMBOL_GPL(set_shares);
Index: linux-2.6.11-rc5/kernel/ckrm/Makefile
===================================================================
--- linux-2.6.11-rc5.orig/kernel/ckrm/Makefile  2005-02-24 00:54:50.540797962 
-0800
+++ linux-2.6.11-rc5/kernel/ckrm/Makefile       2005-02-24 00:55:01.465480744 
-0800
@@ -2,4 +2,4 @@
 # Makefile for CKRM
 #
 
-obj-y := ckrm_events.o
+obj-y += ckrm_events.o ckrm.o ckrmutils.o
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to