[PATCH 1/6] CKRM core

From: Shailabh Nagar (nagar_at_watson.ibm.com)
Date: 04/29/04

  • Next message: Michael Hunold: "[PATCH][2.6] DVB:Fix adapter module removal bug"
    Date:	Thu, 29 Apr 2004 04:25:16 -0400
    To: linux-kernel <linux-kernel@vger.kernel.org>
    
    
    

    
    

    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;
     }

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/


  • Next message: Michael Hunold: "[PATCH][2.6] DVB:Fix adapter module removal bug"

    Relevant Pages