From: Shailabh Nagar <nagar@watson.ibm.com>
To: linux-kernel <linux-kernel@vger.kernel.org>
Cc: ckrm-tech <ckrm-tech@lists.sourceforge.net>
Subject: [PATCH 1/6] CKRM core
Date: Thu, 29 Apr 2004 04:25:16 -0400 [thread overview]
Message-ID: <4090BBEC.2010205@watson.ibm.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 0 bytes --]
[-- Attachment #2: 00-core.ckrm-E12.patch --]
[-- Type: text/plain, Size: 64581 bytes --]
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c Wed Apr 28 22:41:05 2004
+++ b/fs/exec.c Wed Apr 28 22:41:05 2004
@@ -46,6 +46,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/rmap-locking.h>
+#include <linux/ckrm.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
@@ -1151,6 +1152,8 @@
retval = search_binary_handler(&bprm,regs);
if (retval >= 0) {
free_arg_pages(&bprm);
+
+ ckrm_cb_exec(filename);
/* execve success */
security_bprm_free(&bprm);
diff -Nru a/include/linux/ckrm.h b/include/linux/ckrm.h
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/include/linux/ckrm.h Wed Apr 28 22:41:05 2004
@@ -0,0 +1,156 @@
+/* ckrm.h - 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
+ *
+ *
+ * Provides a base header file including macros and basic data structures.
+ *
+ * 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
+ * Added callbacks_active and surrounding logic. Added task paramter
+ * for all CE callbacks.
+ * 19 Nov 2004
+ * New Event callback structure
+ */
+
+#ifndef _LINUX_CKRM_H
+#define _LINUX_CKRM_H
+
+#ifdef CONFIG_CKRM
+
+// Data structure and function to get the list of registered
+// resource controllers.
+
+// #include <linux/sched.h>
+
+/* CKRM defines a set of events at particular points in the kernel
+ * at which callbacks registered by various class types are called
+ */
+
+enum ckrm_event {
+ /* we distinguish various events types
+ *
+ * (a) CKRM_LATCHABLE_EVENTS
+ * events can be latched for event callbacks by classtypes
+ *
+ * (b) CKRM_NONLATACHBLE_EVENTS
+ * events can not be latched but can be used to call classification
+ *
+ * (c) event that are used for notification purposes
+ * range: [ CKRM_EVENT_CANNOT_CLASSIFY .. )
+ */
+
+ /* events (a) */
+
+ CKRM_LATCHABLE_EVENTS,
+
+ CKRM_EVENT_NEWTASK = CKRM_LATCHABLE_EVENTS,
+ CKRM_EVENT_FORK,
+ CKRM_EVENT_EXIT,
+ CKRM_EVENT_EXEC,
+ CKRM_EVENT_UID,
+ CKRM_EVENT_GID,
+ CKRM_EVENT_LOGIN,
+ CKRM_EVENT_USERADD,
+ CKRM_EVENT_USERDEL,
+ CKRM_EVENT_LISTEN_START,
+ CKRM_EVENT_LISTEN_STOP,
+ CKRM_EVENT_APPTAG,
+
+ /* events (b) */
+
+ CKRM_NONLATCHABLE_EVENTS,
+
+ CKRM_EVENT_RECLASSIFY = CKRM_NONLATCHABLE_EVENTS,
+
+ /* events (c) */
+ CKRM_NOTCLASSIFY_EVENTS,
+
+ CKRM_EVENT_MANUAL = CKRM_NOTCLASSIFY_EVENTS,
+
+ CKRM_NUM_EVENTS
+};
+#endif
+
+#ifdef __KERNEL__
+#ifdef CONFIG_CKRM
+
+extern void ckrm_invoke_event_cb_chain(enum ckrm_event ev, void *arg);
+
+typedef void (*ckrm_event_cb)(void *arg);
+
+struct ckrm_hook_cb {
+ ckrm_event_cb fct;
+ struct ckrm_hook_cb *next;
+};
+
+#define CKRM_DEF_CB(EV,fct) \
+static inline void ckrm_cb_##fct(void) \
+{ \
+ ckrm_invoke_event_cb_chain(CKRM_EVENT_##EV,NULL); \
+}
+
+#define CKRM_DEF_CB_ARG(EV,fct,argtp) \
+static inline void ckrm_cb_##fct(argtp arg) \
+{ \
+ ckrm_invoke_event_cb_chain(CKRM_EVENT_##EV,(void*)arg); \
+}
+
+#else // !CONFIG_CKRM
+
+#define CKRM_DEF_CB(EV,fct) \
+static inline void ckrm_cb_##fct(void) { }
+
+#define CKRM_DEF_CB_ARG(EV,fct,argtp) \
+static inline void ckrm_cb_##fct(argtp arg) { }
+
+#endif // CONFIG_CKRM
+
+/*-----------------------------------------------------------------
+ * define the CKRM event functions
+ * EVENT FCT ARG
+ *-----------------------------------------------------------------*/
+
+// types we refer at
+struct task_struct;
+struct sock;
+struct user_struct;
+
+CKRM_DEF_CB_ARG( FORK , fork, struct task_struct *);
+CKRM_DEF_CB_ARG( EXEC , exec, const char* );
+CKRM_DEF_CB ( UID , uid );
+CKRM_DEF_CB ( GID , gid );
+CKRM_DEF_CB ( APPTAG , apptag );
+CKRM_DEF_CB ( LOGIN , login );
+CKRM_DEF_CB_ARG( USERADD , useradd, struct user_struct *);
+CKRM_DEF_CB_ARG( USERDEL , userdel, struct user_struct *);
+CKRM_DEF_CB_ARG( LISTEN_START , listen_start, struct sock * );
+CKRM_DEF_CB_ARG( LISTEN_STOP , listen_stop, struct sock * );
+
+// and a few special one's
+void ckrm_cb_newtask(struct task_struct *);
+void ckrm_cb_exit(struct task_struct *);
+
+// some other functions required
+extern void ckrm_init(void);
+extern int get_exe_path_name(struct task_struct *, char *, int);
+
+#endif // __KERNEL__
+
+#endif // _LINUX_CKRM_H
diff -Nru a/include/linux/ckrm_ce.h b/include/linux/ckrm_ce.h
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/include/linux/ckrm_ce.h Wed Apr 28 22:41:05 2004
@@ -0,0 +1,91 @@
+/* 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 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
+ *
+ * 12 Nov 2003
+ * Created.
+ * 22 Apr 2004
+ * Adopted to classtypes
+ */
+
+#ifndef _LINUX_CKRM_CE_H
+#define _LINUX_CKRM_CE_H
+
+#ifdef CONFIG_CKRM
+
+#include "ckrm.h" // getting the event names
+
+/* 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
+ */
+
+#ifdef __KERNEL__
+
+typedef void* (*ce_classify_fct_t)(enum ckrm_event event, void *obj, ... );
+typedef void (*ce_notify_fct_t) (enum ckrm_event event, void *classobj, void *obj);
+
+typedef 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 CE is interested in */
+ ce_classify_fct_t classify; /* generic classify */
+
+ void (*class_add) (const char *name, void *core); /* class added */
+ void (*class_delete)(const char *name, void *core); /* class deleted */
+
+ /* callback which are called while holding task_lock(tsk) */
+ unsigned long n_interest; /* set of notification events CE is interested in */
+ ce_notify_fct_t notify; /* notify on class switch */
+
+} ckrm_eng_callback_t;
+
+struct inode;
+struct dentry;
+
+typedef struct rbce_eng_callback {
+ int (*mkdir)(struct inode *, struct dentry *, int); // mkdir
+ int (*rmdir)(struct inode *, struct dentry *); // rmdir
+} rbce_eng_callback_t;
+
+extern int ckrm_register_engine (const char *name, ckrm_eng_callback_t *);
+extern int ckrm_unregister_engine(const char *name);
+
+extern void *ckrm_classobj(char *, int *classtype);
+extern int get_exe_path_name(struct task_struct *t, char *filename, int max_size);
+
+extern int rcfs_register_engine(rbce_eng_callback_t *);
+extern int rcfs_unregister_engine(rbce_eng_callback_t *);
+
+extern int ckrm_reclassify(int pid);
+
+#ifndef _LINUX_CKRM_RC_H
+// ckrm kernel has inlined functions for this which are exported
+extern void ckrm_core_grab(void *);
+extern void ckrm_core_drop(void *);
+#endif
+
+#endif // CONFIG_CKRM
+
+#endif // __KERNEL__
+
+#endif // _LINUX_CKRM_CE_H
diff -Nru a/include/linux/ckrm_rc.h b/include/linux/ckrm_rc.h
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/include/linux/ckrm_rc.h Wed Apr 28 22:41:05 2004
@@ -0,0 +1,366 @@
+/* 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.
+ *
+ * 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
+ *
+ * 12 Nov 2003
+ * Created.
+ */
+
+#ifndef _LINUX_CKRM_RC_H
+#define _LINUX_CKRM_RC_H
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_CKRM
+
+#include <linux/list.h>
+#include <linux/ckrm.h>
+#include <linux/ckrm_ce.h>
+#include <linux/seq_file.h>
+
+
+/* maximum number of class types */
+#define CKRM_MAX_CLASSTYPES 32
+/* maximum classtype name length */
+#define CKRM_MAX_CLASSTYPE_NAME 32
+
+/* maximum resource controllers per classtype */
+#define CKRM_MAX_RES_CTLRS 8
+/* maximum resource controller name length */
+#define CKRM_MAX_RES_NAME 128
+
+
+struct ckrm_core_class;
+struct ckrm_classtype;
+
+/********************************************************************************
+ * Share specifications
+ *******************************************************************************/
+
+typedef 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
+} ckrm_shares_t;
+
+#define CKRM_SHARE_UNCHANGED (-1) // value to indicate no change
+#define CKRM_SHARE_DONTCARE (-2) // value to indicate don't care.
+#define CKRM_SHARE_DFLT_TOTAL_GUARANTEE (100) // Start off with these values
+#define CKRM_SHARE_DFLT_MAX_LIMIT (100) // to simplify set_res_shares logic
+
+
+/********************************************************************************
+ * RESOURCE CONTROLLERS
+ *******************************************************************************/
+
+/* resource controller callback structure */
+
+typedef 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 resource controller
+
+ /* 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_res_ctlr_t;
+
+/***************************************************************************************
+ * CKRM_CLASSTYPE
+ *
+ * A <struct ckrm_classtype> object describes a dimension for CKRM to classify
+ * along. I needs 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
+
+
+typedef struct ckrm_classtype {
+ /* Hubertus: Rearrange slots so that they are more cache friendly during access */
+
+ /* resource controllers */
+ spinlock_t res_ctlrs_lock; /* protect data below (other than atomics) */
+ int max_res_ctlrs; /* maximum number of resource controller allowed */
+ int max_resid; /* maximum resid used */
+ int resid_reserved; /* maximum number of reserved controllers */
+ long bit_res_ctlrs; /* bitmap of resource ID used */
+ atomic_t nr_resusers[CKRM_MAX_RES_CTLRS];
+ ckrm_res_ctlr_t* res_ctlrs[CKRM_MAX_RES_CTLRS];
+
+ /* state about my classes */
+
+ struct ckrm_core_class *default_class; // pointer to default class
+ struct list_head classes; // listhead to link up all classes of this classtype
+ int num_classes; // how many classes do exist
+
+ /* state about my ce interaction */
+ int ce_regd; // Has a CE been registered for this classtype
+ int ce_cb_active; // are callbacks active
+ atomic_t ce_nr_users; // how many transient calls active
+ 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
+ // mfdesc and mfcount
+ 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 typeID; /* 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); /* alloc class instance */
+ int (*free) (struct ckrm_core_class *cls); /* free class instance */
+
+ 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 */
+ void (*add_resctrl)(struct ckrm_core_class *, int resid); // class initialization for new RC
+
+} ckrm_classtype_t;
+
+/******************************************************************************************
+ * 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
+
+typedef struct ckrm_hnode {
+ struct ckrm_core_class *parent;
+ struct list_head siblings; /* linked list of siblings */
+ struct list_head children; /* anchor for children */
+} ckrm_hnode_t;
+
+typedef struct ckrm_core_class {
+ struct ckrm_classtype *classtype; // what type does this core class belong to
+ void* res_class[CKRM_MAX_RES_CTLRS]; // pointer to array of resource classes
+ spinlock_t ckrm_lock; // to protect the list and the array above
+ struct list_head objlist; // generic list for any object list to be maintained by class
+ struct list_head clslist; // to link up all classes in a single list type wrt to type
+ struct dentry *dentry; // dentry of inode in the RCFS
+ int magic;
+ struct ckrm_hnode hnode; // hierarchy
+ rwlock_t hnode_rwlock; // rw_clock protecting the hnode above.
+ atomic_t refcnt;
+ const char *name;
+} ckrm_core_class_t;
+
+/* 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)->ckrm_lock)
+#define class_unlock(coreptr) spin_unlock(&(coreptr)->ckrm_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*)((rescls)->res_class[resid]))
+
+extern int ckrm_register_res_ctlr (struct ckrm_classtype *, ckrm_res_ctlr_t *);
+extern int ckrm_unregister_res_ctlr (ckrm_res_ctlr_t *);
+
+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 *); // Hubertus .. can disappear after cls del debugging
+extern struct ckrm_res_ctlr *ckrm_resctlr_lookup(struct ckrm_classtype *type, const char *resname);
+
+#if 0
+
+// Hubertus ... need to straighten out all these I don't think we will even call thsie ore are we
+
+/* interface to the RCFS filesystem */
+extern struct ckrm_core_class *ckrm_alloc_core_class(struct ckrm_core_class *, const char *, int);
+
+// Reclassify the given pid to the given core class by force
+extern void ckrm_forced_reclassify_pid(int, struct ckrm_core_class *);
+
+// Reclassify the given net_struct to the given core class by force
+extern void ckrm_forced_reclassify_laq(struct ckrm_net_struct *,
+ struct ckrm_core_class *);
+
+#endif
+
+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);
+
+#if 0
+extern void ckrm_ns_hold(struct ckrm_net_struct *);
+extern void ckrm_ns_put(struct ckrm_net_struct *);
+extern void *ckrm_set_rootcore_byname(char *, void *);
+#endif
+
+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(ckrm_core_class_t *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[]; /* should provide a different interface */
+
+
+/*-----------------------------------------------------------------------------
+ * CKRM event callback specification for the classtypes or resource controllers
+ * typically an array is specified using CKRM_EVENT_SPEC terminated with
+ * CKRM_EVENT_SPEC_LAST and then that array is registered using
+ * ckrm_register_event_set.
+ * Individual registration of event_cb is also possible
+ *-----------------------------------------------------------------------------*/
+
+struct ckrm_event_spec {
+ enum ckrm_event ev;
+ struct ckrm_hook_cb cb;
+};
+#define CKRM_EVENT_SPEC(EV,FCT) { CKRM_EVENT_##EV, { (ckrm_event_cb)FCT, NULL } }
+
+int ckrm_register_event_set(struct ckrm_event_spec especs[]);
+int ckrm_unregister_event_set(struct ckrm_event_spec especs[]);
+int ckrm_register_event_cb(enum ckrm_event ev, struct ckrm_hook_cb *cb);
+int ckrm_unregister_event_cb(enum ckrm_event ev, struct ckrm_hook_cb *cb);
+
+/******************************************************************************************
+ * 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)
+
+
+#endif // CONFIG_CKRM
+
+#endif // __KERNEL__
+
+#endif // _LINUX_CKRM_RC_H
+
+
+
+
+
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h Wed Apr 28 22:41:05 2004
+++ b/include/linux/sched.h Wed Apr 28 22:41:05 2004
@@ -493,6 +493,16 @@
unsigned long ptrace_message;
siginfo_t *last_siginfo; /* For ptrace use. */
+
+#ifdef CONFIG_CKRM
+ spinlock_t ckrm_tsklock;
+ void *ce_data;
+#ifdef CONFIG_CKRM_TYPE_TASKCLASS
+ // .. Hubertus should change to CONFIG_CKRM_TYPE_TASKCLASS
+ struct ckrm_task_class *taskclass;
+ struct list_head taskclass_link;
+#endif // CONFIG_CKRM_TYPE_TASKCLASS
+#endif // CONFIG_CKRM
};
static inline pid_t process_group(struct task_struct *tsk)
diff -Nru a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig Wed Apr 28 22:41:05 2004
+++ b/init/Kconfig Wed Apr 28 22:41:05 2004
@@ -104,6 +104,75 @@
up to the user level program to do useful things with this
information. This is generally a good idea, so say Y.
+menu "Class Based Kernel Resource Management"
+
+config CKRM
+ bool "Class Based Kernel Resource Management Core"
+ depends on EXPERIMENTAL
+ help
+ Class-based Kernel Resource Management is a framework for controlling
+ and monitoring resource allocation of user-defined groups of tasks or
+ incoming socket connections. For more information, please visit
+ http://ckrm.sf.net.
+
+ If you say Y here, enable the Resource Class File System and atleast
+ one of the resource controllers below. Say N if you are unsure.
+
+config RCFS_FS
+ tristate "Resource Class File System (User API)"
+ depends on CKRM
+ help
+ RCFS is the filesystem API for CKRM. This separate configuration
+ option is provided only for debugging and will eventually disappear
+ since rcfs will be automounted whenever CKRM is configured.
+
+ Say N if unsure, Y if you've enabled CKRM, M to debug rcfs
+ initialization.
+
+config CKRM_TYPE_TASKCLASS
+ bool "Class Manager for Task Groups"
+ depends on CKRM
+ help
+ TASKCLASS provides the extensions for CKRM to track task classes
+ This is the base to enable task class based resource control for
+ cpu, memory and disk I/O.
+
+ Say N if unsure
+
+config CKRM_RES_NUMTASKS
+ tristate "Number of Tasks Resource Manager"
+ depends on CKRM_TYPE_TASKCLASS
+ default m
+ help
+ Provides a Resource Controller for CKRM that allows limiting no of
+ tasks a task class can have.
+
+ Say N if unsure, Y to use the feature.
+
+config CKRM_TYPE_SOCKETCLASS
+ bool "Class Manager for socket groups"
+ depends on CKRM
+ help
+ SOCKET provides the extensions for CKRM to track per socket
+ classes. This is the base to enable socket based resource
+ control for inbound connection control, bandwidth control etc.
+
+ Say N if unsure.
+
+config CKRM_RES_LISTENAQ
+ tristate "Multiple Accept Queues Resource Manager"
+ depends on CKRM_TYPE_SOCKETCLASS && ACCEPT_QUEUES
+ default m
+ help
+ Provides a resource controller for CKRM to prioritize inbound
+ connection requests. See inbound control description for
+ "IP: TCP Multiple accept queues support". If you choose that
+ option choose this option to control the queue weights.
+
+ If unsure, say N.
+
+endmenu
+
config SYSCTL
bool "Sysctl support"
---help---
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c Wed Apr 28 22:41:05 2004
+++ b/init/main.c Wed Apr 28 22:41:05 2004
@@ -46,6 +46,8 @@
#include <asm/io.h>
#include <asm/bugs.h>
+#include <linux/ckrm.h>
+
/*
* This is one of the first .c files built. Error out early
* if we have compiler trouble..
@@ -431,6 +433,7 @@
rcu_init();
init_IRQ();
pidhash_init();
+ ckrm_init();
sched_init();
softirq_init();
time_init();
@@ -479,6 +482,7 @@
#ifdef CONFIG_PROC_FS
proc_root_init();
#endif
+
check_bugs();
printk("POSIX conformance testing by UNIFIX\n");
diff -Nru a/kernel/Makefile b/kernel/Makefile
--- a/kernel/Makefile Wed Apr 28 22:41:05 2004
+++ b/kernel/Makefile Wed Apr 28 22:41:05 2004
@@ -7,7 +7,7 @@
sysctl.o capability.o ptrace.o timer.o user.o \
signal.o sys.o kmod.o workqueue.o pid.o \
rcupdate.o intermodule.o extable.o params.o posix-timers.o \
- kthread.o
+ kthread.o ckrm/
obj-$(CONFIG_FUTEX) += futex.o
obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
diff -Nru a/kernel/ckrm/Makefile b/kernel/ckrm/Makefile
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/kernel/ckrm/Makefile Wed Apr 28 22:41:05 2004
@@ -0,0 +1,14 @@
+#
+# Makefile for CKRM
+#
+
+ifeq ($(CONFIG_CKRM),y)
+ obj-y = ckrm.o ckrmutils.o
+endif
+
+obj-$(CONFIG_CKRM_TYPE_TASKCLASS) += ckrm_tc.o
+obj-$(CONFIG_CKRM_RES_NUMTASKS) += ckrm_tasks.o
+
+obj-$(CONFIG_CKRM_TYPE_SOCKETCLASS) += ckrm_sockc.o
+obj-$(CONFIG_CKRM_RES_LISTENAQ) += ckrm_listenaq.o
+
diff -Nru a/kernel/ckrm/ckrm.c b/kernel/ckrm/ckrm.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/kernel/ckrm/ckrm.c Wed Apr 28 22:41:05 2004
@@ -0,0 +1,1003 @@
+/* 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.
+ *
+ */
+
+/* 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
+ * 19 Apr 2004
+ * Integrated ckrm hooks, classtypes, ...
+ *
+ */
+
+#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/rcfs.h>
+#include <net/sock.h>
+#include <linux/ip.h>
+
+
+rwlock_t ckrm_class_lock = RW_LOCK_UNLOCKED; // protect classlists
+
+struct rcfs_functions rcfs_fn ;
+EXPORT_SYMBOL(rcfs_fn);
+
+/**************************************************************************
+ * Helper Functions *
+ **************************************************************************/
+
+/*
+ * Return TRUE if the given core class pointer is valid.
+ */
+
+/*
+ * Return TRUE if the given resource is registered.
+ */
+inline unsigned int
+is_res_regd(struct ckrm_classtype *clstype, int resid)
+{
+ return ( (resid>=0) && (resid < clstype->max_resid) &&
+ test_bit(resid, &clstype->bit_res_ctlrs)
+ );
+}
+
+struct ckrm_res_ctlr*
+ckrm_resctlr_lookup(struct ckrm_classtype *clstype, const char *resname)
+{
+ int resid = -1;
+
+ 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(ckrm_resctlr_lookup);
+
+/* given a classname return the class handle and its classtype*/
+void *
+ckrm_classobj(char *classname, int *classTypeID)
+{
+ int i;
+
+ *classTypeID = -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..
+ read_unlock(&ckrm_class_lock);
+ *classTypeID = ctype->typeID;
+ return core;
+ }
+ }
+ }
+ read_unlock(&ckrm_class_lock);
+ return NULL;
+}
+
+EXPORT_SYMBOL(is_res_regd);
+EXPORT_SYMBOL(ckrm_classobj);
+
+/**************************************************************************
+ * Internal Functions/macros *
+ **************************************************************************/
+
+static inline void
+set_callbacks_active(struct ckrm_classtype *ctype)
+{
+ ctype->ce_cb_active = ((atomic_read(&ctype->ce_nr_users) > 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, ckrm_eng_callback_t *ecbs)
+{
+ struct ckrm_classtype *ctype;
+
+ ctype = ckrm_find_classtype_by_name(typename);
+ if (ctype == NULL)
+ return (-ENOENT);
+
+ ce_protect(ctype);
+ if (atomic_read(&ctype->ce_nr_users) != 1) {
+ // Some engine is acive, deregister it first.
+ ce_release(ctype);
+ return (-EBUSY);
+ }
+
+ /* we require that either classify and class_delete are set (due to object reference)
+ * or that notify is set (in case no real classification is supported only notification
+ * also require that the function pointer 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) )
+ {
+ ce_release(ctype);
+ return (-EINVAL);
+ }
+
+
+ /* Is any other engine registered for this classtype ? */
+ if (ctype->ce_regd) {
+ ce_release(ctype);
+ return (-EINVAL);
+ }
+
+ ctype->ce_regd = 1;
+ ctype->ce_callbacks = *ecbs;
+ set_callbacks_active(ctype);
+ if (ctype->ce_callbacks.class_add)
+ (*ctype->ce_callbacks.class_add)(ctype->default_class->name,ctype->default_class);
+ return ctype->typeID;
+}
+
+/*
+ * 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_dec_and_test(&ctype->ce_nr_users) != 1) {
+ // Somebody is currently using the engine, cannot deregister.
+ atomic_inc(&ctype->ce_nr_users);
+ return (-EBUSY);
+ }
+
+ ctype->ce_regd = 0;
+ memset(&ctype->ce_callbacks, 0, sizeof(ckrm_eng_callback_t));
+ 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;
+ }
+
+ spin_lock(&child->ckrm_lock);
+ 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;
+ spin_unlock(&child->ckrm_lock);
+ 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;
+
+ spin_lock(&child->ckrm_lock);
+ /* ensure that the node does not have children */
+ if (!list_empty(&cnode->children)) {
+ spin_unlock(&child->ckrm_lock);
+ return 0;
+ }
+ write_lock(&parent->hnode_rwlock);
+ list_del(&cnode->siblings);
+ write_unlock(&parent->hnode_rwlock);
+ cnode->parent = NULL;
+ spin_unlock(&child->ckrm_lock);
+ 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(ckrm_lock_hier);
+EXPORT_SYMBOL(ckrm_unlock_hier);
+EXPORT_SYMBOL(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)) {
+ ckrm_res_ctlr_t *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)
+{
+ // Hubertus ... should replace name with dentry or add dentry ?
+ int i;
+
+ // Hubertus .. how is this used in initialization
+
+ printk("ckrm_init_core_class: name %s => %p\n", name?name:"default",dcore);
+
+ if ((dcore != clstype->default_class) && ( !ckrm_is_core_valid(parent))) {
+ printk("error not a valid parent %p\n", parent);
+ return -EINVAL;
+ }
+#if 0 // Hubertus .. dynamic allocation still breaks when RCs registers. See def in ckrm_rc.h
+ dcore->res_class = NULL;
+ if (clstype->max_resid > 0) {
+ dcore->res_class = (void**)kmalloc(clstype->max_resid * sizeof(void*) , GFP_KERNEL);
+ if (dcore->res_class == NULL) {
+ printk("error no mem\n");
+ return -ENOMEM;
+ }
+ }
+#endif
+
+ dcore->classtype = clstype;
+ dcore->magic = CKRM_CORE_MAGIC;
+ dcore->name = name;
+ dcore->ckrm_lock = SPIN_LOCK_UNLOCKED;
+ dcore->hnode_rwlock = RW_LOCK_UNLOCKED;
+
+ atomic_set(&dcore->refcnt, 0);
+ write_lock(&ckrm_class_lock);
+
+ INIT_LIST_HEAD(&dcore->objlist);
+ list_add(&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]) {
+ ckrm_res_ctlr_t *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]);
+ atomic_dec(&clstype->nr_resusers[resid]); // for inc in alloc
+ core->res_class[resid] = NULL;
+ }
+ atomic_dec(&clstype->nr_resusers[resid]);
+ }
+}
+
+
+/*
+ * 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;
+
+ printk("%s: core=%p:%s parent=%p:%s\n",__FUNCTION__,core,core->name,parent,parent->name);
+ if (core->magic == 0) {
+ /* 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) {
+ printk("class <%s> deletion delayed refcnt=%d jif=%ld\n",
+ core->name,core->refcnt,jiffies);
+ core->magic = 0; /* 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, ckrm_res_ctlr_t *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, ckrm_res_ctlr_t *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;
+ int resid = rcbs->resid;
+
+ if ((clstype == NULL) || (resid < 0))
+ return -EINVAL;
+
+ if (atomic_read(&clstype->nr_resusers[resid]))
+ return -EBUSY;
+
+ // FIXME: probably need to also call deregistration function
+
+ 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
+ *******************************************************************/
+
+/* Hubertus ... we got to do some locking here */
+
+struct ckrm_classtype* ckrm_classtypes[CKRM_MAX_CLASSTYPES];
+EXPORT_SYMBOL(ckrm_classtypes); // really should build a better interface for this
+
+int
+ckrm_register_classtype(struct ckrm_classtype *clstype)
+{
+ int tid = clstype->typeID;
+
+ 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->typeID = tid;
+ ckrm_classtypes[tid] = clstype;
+
+ /* Hubertus .. we 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->typeID;
+
+ 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->typeID = -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;
+}
+
+
+/*******************************************************************
+ * Event callback invocation
+ *******************************************************************/
+
+struct ckrm_hook_cb* ckrm_event_callbacks[CKRM_NONLATCHABLE_EVENTS];
+
+/* Registration / Deregistration / Invocation functions */
+
+int
+ckrm_register_event_cb(enum ckrm_event ev, struct ckrm_hook_cb *cb)
+{
+ struct ckrm_hook_cb **cbptr;
+
+ if ((ev < CKRM_LATCHABLE_EVENTS) || (ev >= CKRM_NONLATCHABLE_EVENTS))
+ return 1;
+ cbptr = &ckrm_event_callbacks[ev];
+ while (*cbptr != NULL)
+ cbptr = &((*cbptr)->next);
+ *cbptr = cb;
+ return 0;
+}
+
+int
+ckrm_unregister_event_cb(enum ckrm_event ev, struct ckrm_hook_cb *cb)
+{
+ struct ckrm_hook_cb **cbptr;
+
+ if ((ev < CKRM_LATCHABLE_EVENTS) || (ev >= CKRM_NONLATCHABLE_EVENTS))
+ return -1;
+ cbptr = &ckrm_event_callbacks[ev];
+ while ((*cbptr != NULL) && (*cbptr != cb))
+ cbptr = &((*cbptr)->next);
+ if (*cbptr)
+ (*cbptr)->next = cb->next;
+ return (*cbptr == NULL);
+}
+
+int
+ckrm_register_event_set(struct ckrm_event_spec especs[])
+{
+ struct ckrm_event_spec *espec = especs;
+
+ for ( espec = especs ; espec->ev != -1 ; espec++ )
+ ckrm_register_event_cb(espec->ev,&espec->cb);
+ return 0;
+}
+
+int
+ckrm_unregister_event_set(struct ckrm_event_spec especs[])
+{
+ struct ckrm_event_spec *espec = especs;
+
+ for ( espec = especs ; espec->ev != -1 ; espec++ )
+ ckrm_unregister_event_cb(espec->ev,&espec->cb);
+ return 0;
+}
+
+#define ECC_PRINTK(fmt, args...) // printk("%s: " fmt, __FUNCTION__ , ## args)
+
+void
+ckrm_invoke_event_cb_chain(enum ckrm_event ev, void *arg)
+{
+ struct ckrm_hook_cb *cb, *anchor;
+
+ ECC_PRINTK("%d %x\n",current,ev,arg);
+ if ((anchor = ckrm_event_callbacks[ev]) != NULL) {
+ for ( cb = anchor ; cb ; cb = cb->next )
+ (*cb->fct)(arg);
+ }
+}
+
+/*******************************************************************
+ * 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;
+}
+
+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;
+
+ printk("ckrm_class_set_shares(%s,%s)\n",core->name,resname);
+ 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
+ckrm_cb_newtask(struct task_struct *tsk)
+{
+ tsk->ce_data = NULL;
+ spin_lock_init(&tsk->ckrm_tsklock);
+ ckrm_invoke_event_cb_chain(CKRM_EVENT_NEWTASK,tsk);
+}
+
+void
+ckrm_cb_exit(struct task_struct *tsk)
+{
+ ckrm_invoke_event_cb_chain(CKRM_EVENT_EXIT,tsk);
+ tsk->ce_data = NULL;
+}
+
+void __init
+ckrm_init(void)
+{
+ printk("CKRM Initialization\n");
+
+ // 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(ckrm_register_engine);
+EXPORT_SYMBOL(ckrm_unregister_engine);
+
+EXPORT_SYMBOL(ckrm_register_res_ctlr);
+EXPORT_SYMBOL(ckrm_unregister_res_ctlr);
+
+EXPORT_SYMBOL(ckrm_init_core_class);
+EXPORT_SYMBOL(ckrm_free_core_class);
+EXPORT_SYMBOL(ckrm_release_core_class);
+
+EXPORT_SYMBOL(ckrm_register_classtype);
+EXPORT_SYMBOL(ckrm_unregister_classtype);
+EXPORT_SYMBOL(ckrm_find_classtype_by_name);
+
+EXPORT_SYMBOL(ckrm_core_grab);
+EXPORT_SYMBOL(ckrm_core_drop);
+EXPORT_SYMBOL(ckrm_is_core_valid);
+EXPORT_SYMBOL(ckrm_validate_and_grab_core);
+
+EXPORT_SYMBOL(ckrm_register_event_set);
+EXPORT_SYMBOL(ckrm_unregister_event_set);
+EXPORT_SYMBOL(ckrm_register_event_cb);
+EXPORT_SYMBOL(ckrm_unregister_event_cb);
+
+EXPORT_SYMBOL(ckrm_class_show_stats);
+EXPORT_SYMBOL(ckrm_class_show_config);
+EXPORT_SYMBOL(ckrm_class_show_shares);
+
+EXPORT_SYMBOL(ckrm_class_set_config);
+EXPORT_SYMBOL(ckrm_class_set_shares);
+
+EXPORT_SYMBOL(ckrm_class_reset_stats);
diff -Nru a/kernel/ckrm/ckrmutils.c b/kernel/ckrm/ckrmutils.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/kernel/ckrm/ckrmutils.c Wed Apr 28 22:41:05 2004
@@ -0,0 +1,207 @@
+/* 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+/* Changes
+ *
+ * 13 Nov 2003
+ * Created
+ */
+
+#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;
+}
+
+
+/*
+ * 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 've 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(get_exe_path_name);
+EXPORT_SYMBOL(child_guarantee_changed);
+EXPORT_SYMBOL(child_maxlimit_changed);
+EXPORT_SYMBOL(set_shares);
+
+
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c Wed Apr 28 22:41:05 2004
+++ b/kernel/exit.c Wed Apr 28 22:41:05 2004
@@ -22,6 +22,8 @@
#include <linux/profile.h>
#include <linux/mount.h>
#include <linux/proc_fs.h>
+#include <linux/ckrm.h>
+#include <linux/ckrm_tsk.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -625,6 +627,8 @@
int state;
struct task_struct *t;
+ ckrm_cb_exit(tsk);
+
if (signal_pending(tsk) && !tsk->signal->group_exit
&& !thread_group_empty(tsk)) {
/*
@@ -788,6 +792,7 @@
module_put(tsk->binfmt->module);
tsk->exit_code = code;
+ numtasks_put_ref(tsk->taskclass);
exit_notify(tsk);
schedule();
BUG();
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c Wed Apr 28 22:41:05 2004
+++ b/kernel/fork.c Wed Apr 28 22:41:05 2004
@@ -31,6 +31,8 @@
#include <linux/futex.h>
#include <linux/ptrace.h>
#include <linux/mount.h>
+#include <linux/ckrm.h>
+#include <linux/ckrm_tsk.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -256,6 +258,7 @@
tsk->thread_info = ti;
ti->task = tsk;
+ ckrm_cb_newtask(tsk);
/* One for us, one for whoever does the "release_task()" (usually parent) */
atomic_set(&tsk->usage,2);
return tsk;
@@ -1143,6 +1146,10 @@
clone_flags |= CLONE_PTRACE;
}
+ if (numtasks_get_ref(current->taskclass, 0) == 0) {
+ return -ENOMEM;
+ }
+
p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr);
/*
* Do this prior waking up the new thread - the thread pointer
@@ -1153,6 +1160,8 @@
if (!IS_ERR(p)) {
struct completion vfork;
+ ckrm_cb_fork(p);
+
if (clone_flags & CLONE_VFORK) {
p->vfork_done = &vfork;
init_completion(&vfork);
@@ -1187,6 +1196,8 @@
* COW overhead when the child exec()s afterwards.
*/
set_need_resched();
+ } else {
+ numtasks_put_ref(current->taskclass);
}
return pid;
}
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c Wed Apr 28 22:41:05 2004
+++ b/kernel/sys.c Wed Apr 28 22:41:05 2004
@@ -23,6 +23,7 @@
#include <linux/security.h>
#include <linux/dcookies.h>
#include <linux/suspend.h>
+#include <linux/ckrm.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -582,6 +583,9 @@
current->fsgid = new_egid;
current->egid = new_egid;
current->gid = new_rgid;
+
+ ckrm_cb_gid();
+
return 0;
}
@@ -619,6 +623,9 @@
}
else
return -EPERM;
+
+ ckrm_cb_gid();
+
return 0;
}
@@ -707,6 +714,8 @@
current->suid = current->euid;
current->fsuid = current->euid;
+ ckrm_cb_uid();
+
return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
}
@@ -752,6 +761,8 @@
current->fsuid = current->euid = uid;
current->suid = new_suid;
+ ckrm_cb_uid();
+
return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
}
@@ -798,6 +809,8 @@
if (suid != (uid_t) -1)
current->suid = suid;
+ ckrm_cb_uid();
+
return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
}
@@ -847,5 +860,8 @@
current->gid = rgid;
if (sgid != (gid_t) -1)
current->sgid = sgid;
+
+ ckrm_cb_gid();
+
return 0;
}
reply other threads:[~2004-04-29 8:44 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4090BBEC.2010205@watson.ibm.com \
--to=nagar@watson.ibm.com \
--cc=ckrm-tech@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.