[patch 3/8] CKRM: Default Classification Engine

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.12-rc1/include/linux/ckrm_ce.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12-rc1/include/linux/ckrm_ce.h	2005-03-18 15:16:24.330201800 -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.12-rc1/include/linux/ckrm_events.h
===================================================================
--- linux-2.6.12-rc1.orig/include/linux/ckrm_events.h	2005-03-18 15:16:16.981786266 -0800
+++ linux-2.6.12-rc1/include/linux/ckrm_events.h	2005-03-18 15:16:24.335201402 -0800
@@ -108,70 +108,78 @@ int ckrm_unregister_event_cb(enum ckrm_e
 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_userdel(struc
 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.12-rc1/include/linux/ckrm_rc.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12-rc1/include/linux/ckrm_rc.h	2005-03-18 15:16:24.336201323 -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.12-rc1/include/linux/rcfs.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12-rc1/include/linux/rcfs.h	2005-03-18 15:16:24.337201243 -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.12-rc1/include/linux/sched.h
===================================================================
--- linux-2.6.12-rc1.orig/include/linux/sched.h	2005-03-18 15:16:20.891475304 -0800
+++ linux-2.6.12-rc1/include/linux/sched.h	2005-03-18 15:16:24.338201164 -0800
@@ -731,6 +731,11 @@ struct task_struct {
 #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.12-rc1/init/main.c
===================================================================
--- linux-2.6.12-rc1.orig/init/main.c	2005-03-17 17:33:54.000000000 -0800
+++ linux-2.6.12-rc1/init/main.c	2005-03-18 15:16:24.339201084 -0800
@@ -47,6 +47,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>
@@ -465,6 +466,7 @@ asmlinkage void __init start_kernel(void
 	rcu_init();
 	init_IRQ();
 	pidhash_init();
+	ckrm_init();
 	init_timers();
 	softirq_init();
 	time_init();
Index: linux-2.6.12-rc1/kernel/ckrm/ckrm.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12-rc1/kernel/ckrm/ckrm.c	2005-03-18 15:16:24.340201005 -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.12-rc1/kernel/ckrm/ckrmutils.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12-rc1/kernel/ckrm/ckrmutils.c	2005-03-18 15:16:24.341200925 -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.12-rc1/kernel/ckrm/Makefile
===================================================================
--- linux-2.6.12-rc1.orig/kernel/ckrm/Makefile	2005-03-18 15:16:16.983786107 -0800
+++ linux-2.6.12-rc1/kernel/ckrm/Makefile	2005-03-18 15:16:24.341200925 -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/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux