public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/6] CKRM task_class classtype
@ 2004-04-29  8:25 Shailabh Nagar
  0 siblings, 0 replies; only message in thread
From: Shailabh Nagar @ 2004-04-29  8:25 UTC (permalink / raw)
  To: linux-kernel, ckrm-tech

[-- Attachment #1: Type: text/plain, Size: 0 bytes --]



[-- Attachment #2: 02-taskclass.ckrm-E12.patch --]
[-- Type: text/plain, Size: 25401 bytes --]

diff -Nru a/include/linux/ckrm_tc.h b/include/linux/ckrm_tc.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/ckrm_tc.h	Wed Apr 28 22:41:05 2004
@@ -0,0 +1,18 @@
+#include <linux/ckrm_rc.h>
+
+
+
+#define TASK_CLASS_TYPE_NAME "taskclass"
+
+typedef struct ckrm_task_class {
+	struct ckrm_core_class core;   
+} ckrm_task_class_t;
+
+
+// Index into genmfdesc array, defined in rcfs/dir_modules.c,
+// which has the mfdesc entry that taskclass wants to use
+#define TC_MF_IDX  0
+
+
+extern int ckrm_forced_reclassify_pid(int pid, struct ckrm_task_class *cls);
+
diff -Nru a/kernel/ckrm/ckrm_tc.c b/kernel/ckrm/ckrm_tc.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/kernel/ckrm/ckrm_tc.c	Wed Apr 28 22:41:05 2004
@@ -0,0 +1,770 @@
+/* ckrm_tc.c - Class-based Kernel Resource Management (CKRM)
+ *
+ * Copyright (C) Hubertus Franke, IBM Corp. 2003,2004
+ *           (C) Shailabh Nagar,  IBM Corp. 2003
+ *           (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.
+ *
+ */
+
+/* Changes
+ *
+ * 28 Aug 2003
+ *        Created.
+ * 06 Nov 2003
+ *        Made modifications to suit the new RBCE module.
+ * 10 Nov 2003
+ *        Fixed a bug in fork and exit callbacks. Added callbacks_active and
+ *        surrounding logic. Added task paramter for all CE callbacks.
+ * 23 Mar 2004
+ *        moved to referenced counted class objects and correct locking
+ * 12 Apr 2004
+ *        introduced adopted to emerging classtype interface
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
+#include <asm/errno.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/ckrm_rc.h>
+
+#include <linux/ckrm_tc.h>
+
+static struct ckrm_task_class  taskclass_dflt_class = {
+};
+
+const char *dflt_taskclass_name = TASK_CLASS_TYPE_NAME;
+
+static struct ckrm_core_class *ckrm_alloc_task_class(struct ckrm_core_class *parent, const char *name);
+static int ckrm_free_task_class(struct ckrm_core_class *core);
+
+static int  tc_forced_reclassify(ckrm_core_class_t *target, const char *resname);
+static int  tc_show_members(struct ckrm_core_class *core, struct seq_file *seq);
+static void tc_add_resctrl(struct ckrm_core_class *core, int resid);
+
+struct ckrm_classtype CT_taskclass = {
+	.mfidx          = TC_MF_IDX,
+	.name           = TASK_CLASS_TYPE_NAME,
+	.typeID         = CKRM_CLASSTYPE_TASK_CLASS, 
+	.maxdepth       = 3,                           // Hubertus .. just to start 
+	.resid_reserved = 4,                           // Hubertus .. reservation
+	.max_res_ctlrs  = CKRM_MAX_RES_CTLRS,        
+	.max_resid      = 0,
+	.bit_res_ctlrs  = 0L,
+	.res_ctlrs_lock = SPIN_LOCK_UNLOCKED,
+	.classes        = LIST_HEAD_INIT(CT_taskclass.classes),
+
+	.default_class  = &taskclass_dflt_class.core,
+	
+	// private version of functions 
+	.alloc          = &ckrm_alloc_task_class,
+	.free           = &ckrm_free_task_class,
+	.show_members   = &tc_show_members,
+	.forced_reclassify = &tc_forced_reclassify,
+
+	// use of default functions 
+	.show_shares    = &ckrm_class_show_shares,
+	.show_stats     = &ckrm_class_show_stats,
+	.show_config    = &ckrm_class_show_config,
+	.set_config     = &ckrm_class_set_config,
+	.set_shares     = &ckrm_class_set_shares,
+	.reset_stats    = &ckrm_class_reset_stats,
+
+	// mandatory private version .. no dflt available
+	.add_resctrl    = &tc_add_resctrl,	
+};
+
+/**************************************************************************
+ *                   Helper Functions                                     *
+ **************************************************************************/
+
+static inline void
+ckrm_init_task_lock(struct task_struct *tsk)
+{
+	tsk->ckrm_tsklock = SPIN_LOCK_UNLOCKED;
+}
+
+// Hubertus .. following functions should move to ckrm_rc.h
+
+static inline void
+ckrm_task_lock(struct task_struct *tsk)
+{
+  	spin_lock(&tsk->ckrm_tsklock);
+}
+
+static inline void
+ckrm_task_unlock(struct task_struct *tsk)
+{
+  	spin_unlock(&tsk->ckrm_tsklock);
+}
+
+/*
+ * Change the task class of the given task.
+ *
+ * Change the task's task class  to "newcls" if the task's current 
+ * class (task->taskclass) is same as given "oldcls", if it is non-NULL.
+ *
+ * Caller is responsible to make sure the task structure stays put through
+ * this function.
+ *
+ * This function should be called with the following locks NOT held
+ * 	- tsk->ckrm_task_lock
+ * 	- core->ckrm_lock, if core is NULL then ckrm_dflt_class.ckrm_lock
+ * 	- tsk->taskclass->ckrm_lock 
+ * 
+ * Function is also called with a ckrm_core_grab on the new core, hence
+ * it needs to be dropped if no assignment takes place.
+ */
+
+static void
+ckrm_set_taskclass(struct task_struct *tsk, ckrm_task_class_t *newcls, 
+		   ckrm_task_class_t *oldcls, enum ckrm_event event)
+{
+	int i;
+	ckrm_classtype_t  *clstype;
+	ckrm_res_ctlr_t   *rcbs;
+	ckrm_task_class_t *curcls;
+	void *old_res_class, *new_res_class;
+	int drop_old_cls;
+
+	ckrm_task_lock(tsk);
+	curcls = tsk->taskclass;
+
+	// check whether compare_and_exchange should
+	if (oldcls && (oldcls != curcls)) {
+		ckrm_task_unlock(tsk);
+		if (newcls) {
+			/* compensate for previous grab */
+			printk("ckrm_set_taskclass(%s:%d): Race-condition caught <%s> %d\n",
+				tsk->comm,tsk->pid,class_core(newcls)->name,event);
+			ckrm_core_drop(class_core(newcls));
+		}
+		return;
+	}
+
+	// make sure we have a real destination core
+	if (!newcls) {
+		newcls = &taskclass_dflt_class;
+		ckrm_core_grab(class_core(newcls));
+	}
+
+	// take out of old class 
+	// remember that we need to drop the oldcore
+	if ((drop_old_cls = (curcls != NULL))) {
+		class_lock(class_core(curcls));
+		if (newcls == curcls) {
+			// we are already in the destination class.
+			// we still need to drop oldcore
+			class_unlock(class_core(curcls));
+			ckrm_task_unlock(tsk);
+			goto out;
+		}
+		list_del(&tsk->taskclass_link);
+		INIT_LIST_HEAD(&tsk->taskclass_link);
+		tsk->taskclass = NULL;
+		class_unlock(class_core(curcls));
+	}	
+
+	// put into new class 
+	class_lock(class_core(newcls));
+	tsk->taskclass = newcls;
+	list_add(&tsk->taskclass_link, &class_core(newcls)->objlist);
+	class_unlock(class_core(newcls));
+
+	if (newcls == curcls) {
+		ckrm_task_unlock(tsk);
+		goto out;
+	}
+
+	CE_NOTIFY(&CT_taskclass,event,newcls,tsk);
+
+	ckrm_task_unlock(tsk);
+
+	clstype = class_isa(newcls);                      // Hubertus .. can hardcode ckrm_CT_taskclass
+	for (i = 0; i < clstype->max_resid; i++) {
+		atomic_inc(&clstype->nr_resusers[i]);
+		old_res_class = curcls ? class_core(curcls)->res_class[i] : NULL;
+		new_res_class = newcls ? class_core(newcls)->res_class[i] : NULL;
+		rcbs = clstype->res_ctlrs[i];
+		if (rcbs && rcbs->change_resclass && (old_res_class != new_res_class)) 
+			(*rcbs->change_resclass)(tsk, old_res_class, new_res_class);
+		atomic_dec(&clstype->nr_resusers[i]);
+	}
+
+ out:
+	if (drop_old_cls) 
+		ckrm_core_drop(class_core(curcls));
+	return;
+}
+
+// HF SUGGEST: we could macro-tize this for other types DEF_FUNC_ADD_RESCTRL(funcname,link)
+//          would DEF_FUNC_ADD_RESCTRL(tc_add_resctrl,taskclass_link)
+
+static void
+tc_add_resctrl(struct ckrm_core_class *core, int resid)
+{
+	struct task_struct *tsk;
+	struct ckrm_res_ctlr *rcbs;
+
+	if ((resid < 0) || (resid >= CKRM_MAX_RES_CTLRS) || ((rcbs = core->classtype->res_ctlrs[resid]) == NULL)) 
+		return;
+
+	spin_lock(&core->ckrm_lock);
+	list_for_each_entry(tsk, &core->objlist, taskclass_link) {
+		if (rcbs->change_resclass)
+			(*rcbs->change_resclass)(tsk, (void *) -1, core->res_class[resid]);
+	}
+	spin_unlock(&core->ckrm_lock);
+}
+
+
+/**************************************************************************
+ *                   Functions called from classification points          *
+ **************************************************************************/
+
+#define ECB_PRINTK(fmt, args...) // do { if (CT_taskclass.ce_regd) printk("%s: " fmt, __FUNCTION__ , ## args); } while (0)
+
+#define CE_CLASSIFY_TASK(event, tsk)						\
+do {										\
+	struct ckrm_task_class *newcls = NULL, *oldcls = tsk->taskclass;	\
+										\
+	CE_CLASSIFY_RET(newcls,&CT_taskclass,event,tsk);			\
+	if (newcls) {								\
+		/* called synchrously. no need to get task struct */		\
+		ckrm_set_taskclass(tsk, newcls, oldcls, event);			\
+	}									\
+} while (0)
+
+#define CE_CLASSIFY_TASK_PROTECT(event, tsk)	\
+do {						\
+	ce_protect(&CT_taskclass);		\
+	CE_CLASSIFY_TASK(event,tsk);		\
+	ce_release(&CT_taskclass);              \
+} while (0)
+
+
+
+
+static void
+cb_taskclass_newtask(struct task_struct *tsk)
+{
+	tsk->taskclass = NULL;
+	INIT_LIST_HEAD(&tsk->taskclass_link);
+}
+
+
+static void
+cb_taskclass_fork(struct task_struct *tsk)
+{
+	struct ckrm_task_class *cls = NULL;
+
+	ECB_PRINTK("%p:%d:%s\n",tsk,tsk->pid,tsk->comm);
+
+	ce_protect(&CT_taskclass);
+	CE_CLASSIFY_RET(cls,&CT_taskclass,CKRM_EVENT_FORK,tsk);	     
+	if (cls == NULL) {
+		ckrm_task_lock(tsk->parent);
+		cls = tsk->parent->taskclass;
+		ckrm_core_grab(class_core(cls));
+		ckrm_task_unlock(tsk->parent);
+	}
+	if (!list_empty(&tsk->taskclass_link))
+		printk("BUG in cb_fork.. tsk (%s:%d> already linked\n",
+			tsk->comm,tsk->pid);
+
+	ckrm_set_taskclass(tsk, cls, NULL, CKRM_EVENT_FORK);
+	ce_release(&CT_taskclass);
+}
+
+static void
+cb_taskclass_exit(struct task_struct *tsk)
+{
+	ckrm_task_class_t *cls;
+
+	// Remove the task from the current core class
+	
+	ECB_PRINTK("%p:%d:%s\n",tsk,tsk->pid,tsk->comm);
+	ckrm_task_lock(tsk);
+
+	CE_CLASSIFY_NORET( &CT_taskclass, CKRM_EVENT_EXIT, tsk);
+
+	if ((cls = tsk->taskclass) != NULL) {
+		class_lock(class_core(cls));
+		tsk->taskclass = NULL;
+		list_del(&tsk->taskclass_link);
+		class_unlock(class_core(cls));
+		ckrm_core_drop(class_core(cls));
+	} else {
+		INIT_LIST_HEAD(&tsk->taskclass_link);
+	}
+	ckrm_task_unlock(tsk);
+}
+
+static void
+cb_taskclass_exec(const char *filename)
+{
+	ECB_PRINTK("%p:%d:%s <%s>\n",current,current->pid,current->comm,filename);
+	CE_CLASSIFY_TASK_PROTECT(CKRM_EVENT_EXEC, current);
+}
+
+static void
+cb_taskclass_uid(void)
+{
+	ECB_PRINTK("%p:%d:%s\n",current,current->pid,current->comm);
+	CE_CLASSIFY_TASK_PROTECT(CKRM_EVENT_UID, current);
+}
+
+static void
+cb_taskclass_gid(void)
+{
+	ECB_PRINTK("%p:%d:%s\n",current,current->pid,current->comm);
+	CE_CLASSIFY_TASK_PROTECT(CKRM_EVENT_GID, current);
+}
+
+static struct ckrm_event_spec taskclass_events_callbacks[] = {
+	CKRM_EVENT_SPEC( NEWTASK, cb_taskclass_newtask ),
+	CKRM_EVENT_SPEC( EXEC   , cb_taskclass_exec ),
+	CKRM_EVENT_SPEC( FORK   , cb_taskclass_fork ),
+	CKRM_EVENT_SPEC( EXIT   , cb_taskclass_exit ),
+	CKRM_EVENT_SPEC( UID    , cb_taskclass_uid  ),
+	CKRM_EVENT_SPEC( GID    , cb_taskclass_gid  ),
+	{ -1 }
+};
+
+/***********************************************************************
+ *
+ * Asynchronous callback functions   (driven by RCFS)
+ * 
+ *    Async functions force a setting of the task structure
+ *    synchronous callbacks are protected against race conditions 
+ *    by using a cmpxchg on the core before setting it.
+ *    Async calls need to be serialized to ensure they can't 
+ *    race against each other 
+ *
+ ***********************************************************************/
+
+DECLARE_MUTEX(async_serializer);    // serialize all async functions
+
+
+/*
+ * Go through the task list and reclassify all tasks according to the current
+ * classification rules.
+ *
+ * We have the problem that we can not hold any lock (including the 
+ * tasklist_lock) while classifying. Two methods possible
+ *
+ * (a) go through entire pidrange (0..pidmax) and if a task exists at 
+ *     that pid then reclassify it
+ * (b) go several time through task list and build a bitmap for a particular 
+ *     subrange of pid otherwise the memory requirements ight be too much.
+ * 
+ * We use a hybrid by comparing ratio nr_threads/pidmax
+ */
+
+static void
+ckrm_reclassify_all_tasks(void)
+{
+	extern int pid_max;
+
+	struct task_struct *proc, *thread;
+	int i;
+	int curpidmax = pid_max;
+	int ratio;
+	int use_bitmap;
+
+
+	ratio = curpidmax / nr_threads;
+	if (curpidmax <= PID_MAX_DEFAULT) {
+	     use_bitmap = 1;
+	} else {
+	     use_bitmap = (ratio >= 2);
+	}
+
+	ce_protect(&CT_taskclass);
+
+ retry:		
+	if (use_bitmap == 0) {
+		// go through it in one walk
+		read_lock(&tasklist_lock);
+		for ( i=0 ; i<curpidmax ; i++ ) {
+			if ((thread = find_task_by_pid(i)) == NULL) 
+				continue;
+			get_task_struct(thread);
+			read_unlock(&tasklist_lock);
+			CE_CLASSIFY_TASK(CKRM_EVENT_RECLASSIFY, thread);
+			put_task_struct(thread);
+			read_lock(&tasklist_lock);
+		}
+		read_unlock(&tasklist_lock);
+	} else {
+		unsigned long *bitmap;
+		int bitmapsize;
+		int order = 0;
+		int num_loops;
+		int pid, do_next;
+
+
+		bitmap = (unsigned long*) __get_free_pages(GFP_KERNEL,order);
+		if (bitmap == NULL) {
+			use_bitmap = 0;
+			goto retry;
+		}
+
+		bitmapsize = 8 * (1 << (order + PAGE_SHIFT));
+		num_loops  = (curpidmax + bitmapsize - 1) / bitmapsize;
+
+		do_next = 1;
+		for ( i=0 ; i < num_loops && do_next; i++) {
+			int pid_start = i*bitmapsize; 
+			int pid_end   = pid_start + bitmapsize;
+			int num_found = 0;
+			int pos;
+
+			memset(bitmap, 0, bitmapsize/8); // start afresh
+			do_next = 0;
+
+			read_lock(&tasklist_lock);
+			do_each_thread(proc, thread) {
+				pid = thread->pid;
+				if ((pid < pid_start) || (pid >= pid_end)) {
+					if (pid >= pid_end) {
+						do_next = 1;
+					}
+					continue;
+				}
+				pid -= pid_start;
+				set_bit(pid, bitmap);
+				num_found++;
+			} while_each_thread(proc, thread);
+			read_unlock(&tasklist_lock);
+		
+			if (num_found == 0) 
+				continue;
+
+			pos = 0;
+			for ( ; num_found-- ; ) {
+				pos = find_next_bit(bitmap, bitmapsize, pos);
+				pid = pos + pid_start;
+
+				read_lock(&tasklist_lock);
+				if ((thread = find_task_by_pid(pid)) != NULL) {
+					get_task_struct(thread);
+					read_unlock(&tasklist_lock);
+					CE_CLASSIFY_TASK(CKRM_EVENT_RECLASSIFY, thread);
+					put_task_struct(thread);
+				} else {
+					read_unlock(&tasklist_lock);
+				}
+			}
+		}
+
+	}
+	ce_release(&CT_taskclass);
+}
+
+int
+ckrm_reclassify(int pid)
+{
+	struct task_struct *tsk;
+	int rc = 0;
+
+	down(&async_serializer);   // protect again race condition
+	if (pid < 0) {
+		// do we want to treat this as process group .. should YES ToDo
+		 rc = -EINVAL;
+	} else if (pid == 0) {
+		// reclassify all tasks in the system
+		ckrm_reclassify_all_tasks();
+	} else {
+		// reclassify particular pid
+		read_lock(&tasklist_lock);
+		if ((tsk = find_task_by_pid(pid)) != NULL) {
+			get_task_struct(tsk);
+			read_unlock(&tasklist_lock);
+			CE_CLASSIFY_TASK_PROTECT(CKRM_EVENT_RECLASSIFY, tsk);
+			put_task_struct(tsk);
+		} else {
+			read_unlock(&tasklist_lock);
+			rc = -EINVAL;
+		}
+	}
+	up(&async_serializer);
+	return rc;
+}
+
+/*
+ * Reclassify all tasks in the given core class.
+ */
+
+static void
+ckrm_reclassify_class_tasks(struct ckrm_task_class *cls)
+{
+	int ce_regd;
+	struct ckrm_hnode *cnode;
+	struct ckrm_task_class *parcls;
+
+	if (!ckrm_validate_and_grab_core(&cls->core))
+		return;
+
+	down(&async_serializer);   // protect again race condition
+
+
+	printk("\t%s: start %p:%s:%d\n",__FUNCTION__,cls,cls->core.name, cls->core.refcnt);
+	// If no CE registered for this classtype, following will be needed repeatedly;
+	ce_regd =  class_core(cls)->classtype->ce_regd;
+	cnode = &(class_core(cls)->hnode);
+	parcls = class_type(ckrm_task_class_t, cnode->parent);
+
+next_task:
+	class_lock(class_core(cls));
+	if (!list_empty(&class_core(cls)->objlist)) {
+		struct ckrm_task_class *newcls = NULL;
+		struct task_struct *tsk = 
+			list_entry(class_core(cls)->objlist.next,
+				   struct task_struct, taskclass_link);
+		
+		get_task_struct(tsk);
+		class_unlock(class_core(cls));
+
+		if (ce_regd) {
+			CE_CLASSIFY_RET(newcls,&CT_taskclass,CKRM_EVENT_RECLASSIFY,tsk); 
+		} else {
+			newcls = parcls;
+			ckrm_core_grab(class_core(newcls));
+		}
+
+		if (cls == newcls) {
+			// don't allow reclassifying to the same class
+			// as we are in the process of cleaning up this class
+			ckrm_core_drop(class_core(newcls)); // to compensate CE's grab
+			newcls = NULL;
+		}
+		ckrm_set_taskclass(tsk, newcls, cls, CKRM_EVENT_RECLASSIFY);
+		put_task_struct(tsk);
+		goto next_task;
+	}
+	printk("\t%s: stop  %p:%s:%d\n",__FUNCTION__,cls,cls->core.name, cls->core.refcnt);
+	ckrm_core_drop(class_core(cls));
+	class_unlock(class_core(cls));
+
+	up(&async_serializer);
+
+	return ;
+}
+
+/*
+ * Change the core class of the given task.
+ */
+
+int 
+ckrm_forced_reclassify_pid(pid_t pid, struct ckrm_task_class *cls)
+{
+	struct task_struct *tsk;
+
+	if (!ckrm_validate_and_grab_core(class_core(cls)))
+		return - EINVAL;
+
+	read_lock(&tasklist_lock);
+	if ((tsk = find_task_by_pid(pid)) == NULL) {
+		read_unlock(&tasklist_lock);
+		return -EINVAL;
+	}
+	get_task_struct(tsk);
+	read_unlock(&tasklist_lock);
+	
+	down(&async_serializer);   // protect again race condition
+	
+	ce_protect(&CT_taskclass);
+	ckrm_set_taskclass(tsk, cls, NULL, CKRM_EVENT_MANUAL);
+	ce_release(&CT_taskclass);
+	put_task_struct(tsk);
+	
+	up(&async_serializer);
+	return 0;
+}
+
+static struct ckrm_core_class *
+ckrm_alloc_task_class(struct ckrm_core_class *parent, const char *name)
+{
+	struct ckrm_task_class *taskcls;
+	taskcls = kmalloc(sizeof(struct ckrm_task_class), GFP_KERNEL);
+	if (taskcls == NULL) 
+		return NULL;
+
+	ckrm_init_core_class(&CT_taskclass,
+			     class_core(taskcls),parent,name);
+
+	ce_protect(&CT_taskclass);
+	if (CT_taskclass.ce_cb_active && CT_taskclass.ce_callbacks.class_add)
+		(*CT_taskclass.ce_callbacks.class_add)(name,taskcls);
+	ce_release(&CT_taskclass);
+
+	return class_core(taskcls);
+}
+
+static int
+ckrm_free_task_class(struct ckrm_core_class *core)
+{
+	struct ckrm_task_class *taskcls;
+
+	if (!ckrm_is_core_valid(core)) {
+		// Invalid core
+		return (-EINVAL);
+	}
+	if (core == core->classtype->default_class) {
+		// reset the name tag
+		core->name = dflt_taskclass_name;
+ 		return 0;
+	}
+
+	printk("%s: stop  %p:%s:%d\n",__FUNCTION__,core,core->name, core->refcnt);
+	taskcls = class_type(struct ckrm_task_class, core);
+
+	ce_protect(&CT_taskclass);
+
+	if (CT_taskclass.ce_cb_active && CT_taskclass.ce_callbacks.class_delete)
+		(*CT_taskclass.ce_callbacks.class_delete)(core->name,taskcls);
+	ckrm_reclassify_class_tasks( taskcls );
+
+	ce_release(&CT_taskclass);
+
+	ckrm_release_core_class(core);  // Hubertus .... could just drop the class .. error message
+	return 0;
+}
+
+
+void __init
+ckrm_meta_init_taskclass(void)
+{
+	printk("...... Initializing ClassType<%s> ........\n",CT_taskclass.name);
+	// intialize the default class
+	ckrm_init_core_class(&CT_taskclass, class_core(&taskclass_dflt_class),
+			     NULL,dflt_taskclass_name);
+
+	// register classtype and initialize default task class
+	ckrm_register_classtype(&CT_taskclass);
+	ckrm_register_event_set(taskclass_events_callbacks);
+
+	// note registeration of all resource controllers will be done later dynamically 
+	// as these are specified as modules
+}
+
+
+
+static int                      
+tc_show_members(struct ckrm_core_class *core, struct seq_file *seq) 
+{
+	struct list_head *lh;
+	struct task_struct *tsk;
+
+	spin_lock(&core->ckrm_lock);
+	list_for_each(lh, &core->objlist) {	
+		tsk = container_of(lh, struct task_struct, taskclass_link);
+		seq_printf(seq,"%ld\n", (long)tsk->pid);
+	}
+	spin_unlock(&core->ckrm_lock);
+
+	return 0;
+}
+
+static int
+tc_forced_reclassify(struct ckrm_core_class *target,const char *obj)
+{	
+	pid_t pid;
+	int rc = -EINVAL;
+
+	pid = (pid_t) simple_strtoul(obj,NULL,10);
+	if (pid > 0) {
+		rc = ckrm_forced_reclassify_pid(pid,
+				class_type(ckrm_task_class_t,target));
+	}
+	return rc;
+} 
+	
+#if 1
+
+/***************************************************************************************
+ * Debugging Task Classes:  Utility functions
+ **************************************************************************************/
+
+void
+check_tasklist_sanity(struct ckrm_task_class *cls)
+{
+	struct ckrm_core_class *core = class_core(cls);
+	struct list_head *lh1, *lh2;
+	int count = 0;
+
+	if (core) {
+		class_lock(core);
+		if (list_empty(&core->objlist)) {
+			class_lock(core);
+			printk("check_tasklist_sanity: class %s empty list\n",
+					core->name);
+			return;
+		}
+		list_for_each_safe(lh1, lh2, &core->objlist) {
+			struct task_struct *tsk = container_of(lh1, struct task_struct, taskclass_link);
+			if (count++ > 20000) {
+				printk("list is CORRUPTED\n");
+				break;
+			}
+			if (tsk->taskclass != cls) {
+				const char *tclsname;
+				tclsname = (tsk->taskclass) ? class_core(tsk->taskclass)->name 
+					                    : "NULL";
+				printk("sanity: task %s:%d has ckrm_core |%s| but in list |%s|\n",
+				       tsk->comm,tsk->pid,tclsname,core->name);
+			}
+		}
+		class_unlock(core);
+	}
+}
+
+void 
+ckrm_debug_free_task_class(struct ckrm_task_class *tskcls)
+{
+	struct task_struct *proc, *thread;
+	int count = 0;
+
+	printk("Analyze Error <%s> %d\n",
+	       class_core(tskcls)->name,atomic_read(&(class_core(tskcls)->refcnt)));
+
+	read_lock(&tasklist_lock);
+	class_lock(class_core(tskcls));
+	do_each_thread(proc, thread) {
+		count += (tskcls == thread->taskclass);
+		if ((thread->taskclass == tskcls) || (tskcls == NULL)) {
+			const char *tclsname;
+			tclsname = (thread->taskclass) ? class_core(thread->taskclass)->name : "NULL";
+			printk("%d thread=<%s:%d>  -> <%s> <%lx>\n",
+			       count,thread->comm,thread->pid,tclsname, thread->flags & PF_EXITING);
+		}
+	} while_each_thread(proc, thread);
+	class_unlock(class_core(tskcls));
+	read_unlock(&tasklist_lock);
+
+	printk("End Analyze Error <%s> %d\n",
+	       class_core(tskcls)->name,atomic_read(&(class_core(tskcls)->refcnt)));
+} 
+
+#endif
diff -Nru a/fs/rcfs/tc_magic.c b/fs/rcfs/tc_magic.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/rcfs/tc_magic.c	Wed Apr 28 22:41:05 2004
@@ -0,0 +1,94 @@
+/* 
+ * fs/rcfs/tc_magic.c 
+ *
+ * Copyright (C) Shailabh Nagar,      IBM Corp. 2004
+ *           (C) Vivek Kashyap,       IBM Corp. 2004
+ *           (C) Chandra Seetharaman, IBM Corp. 2004
+ *           (C) Hubertus Franke,     IBM Corp. 2004
+ *           
+ * 
+ * define magic fileops for taskclass classtype
+ *
+ * Latest version, more details at http://ckrm.sf.net
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+/* Changes
+ *
+ * 23 Apr 2004
+ *        Created.
+ *
+ */
+
+#include <linux/rcfs.h>
+#include <linux/ckrm_tc.h>
+
+
+/*******************************************************************************
+ * Taskclass general
+ *
+ * Define structures for taskclass root directory and its magic files 
+ * In taskclasses, there is one set of magic files, created automatically under
+ * the taskclass root (upon classtype registration) and each directory (class) 
+ * created subsequently. However, classtypes can also choose to have different 
+ * sets of magic files created under their root and other directories under root
+ * using their mkdir function. RCFS only provides helper functions for creating 
+ * the root directory and its magic files
+ * 
+ *******************************************************************************/
+
+#define TC_FILE_MODE (S_IFREG | S_IRUGO | S_IWUSR) 
+	
+#define NR_TCROOTMF  6
+struct rcfs_magf tc_rootdesc[NR_TCROOTMF] = {
+	/* First entry must be root */
+	{ 
+//		.name    = should not be set, copy from classtype name
+		.mode    = RCFS_DEFAULT_DIR_MODE,
+		.i_op    = &rcfs_dir_inode_operations,
+		.i_fop   = &simple_dir_operations,
+	},
+	/* Rest are root's magic files */
+	{ 
+		.name    =  "target", 
+		.mode    = TC_FILE_MODE, 
+		.i_fop   = &target_fileops,
+		.i_op    = &rcfs_file_inode_operations,
+	},
+	{ 
+		.name    =  "config", 
+		.mode    = TC_FILE_MODE, 
+		.i_fop   = &config_fileops, 
+		.i_op    = &rcfs_file_inode_operations,
+	},
+	{ 
+		.name    =  "members", 
+		.mode    = TC_FILE_MODE, 
+		.i_fop   = &members_fileops,
+		.i_op    = &rcfs_file_inode_operations,
+	},
+	{ 
+		.name    =  "stats", 
+		.mode    = TC_FILE_MODE, 
+		.i_fop   = &stats_fileops, 
+		.i_op    = &rcfs_file_inode_operations,
+	},
+	{ 
+		.name    =  "shares", 
+		.mode    = TC_FILE_MODE,
+		.i_fop   = &shares_fileops, 
+		.i_op    = &rcfs_file_inode_operations,
+	},
+};
+
+struct rcfs_mfdesc tc_mfdesc = {
+	.rootmf          = tc_rootdesc,
+	.rootmflen       = NR_TCROOTMF,
+};
+
+

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2004-04-29  8:34 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-29  8:25 [PATCH 3/6] CKRM task_class classtype Shailabh Nagar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox