All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guillaume Thouvenin <guillaume.thouvenin@bull.net>
To: Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [PATCH] Enhanced Linux System Accounting
Date: Wed, 12 May 2004 14:20:48 +0200	[thread overview]
Message-ID: <40A216A0.9010202@bull.net> (raw)

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

Hello,

 This is a new patch "patch-2.6.6-elsa" for 2.6.6 kernel. It can be 
downloaded from:
http://sourceforge.net/project/showfiles.php?group_id=105806

  I also attach it at the end of this file. In this patch we rewrite 
functions and we made a clean separation between different parts of ELSA 
(thank you very much to Chris Wright for its usefull comments). This 
patch allows you to test BSD-like accounting for a group of process. 
Informations are dumped in /var/log/bank (need to change that). "BANK" 
can be manipulated via ioctl() and /dev/elsacct. A C program, called 
"elsa_cmd.c", that allows to add/remove process to/from a bank can be 
downloaded from the CVS:
http://cvs.sourceforge.net/viewcvs.py/elsa/tests/

  We need to improve lock between the main structure called "elsa_broot" 
and add new accounting informations. Our goal is to provide an 
environment that can support System V accounting and a unify interface 
from existing accounting tools (like sar) to be used by existing Linux 
administrative tools (like WebMin).

Any feedbacks, any comments are welcome
Best,
Guillaume



[-- Attachment #2: patch-2.6.6-elsa --]
[-- Type: text/plain, Size: 42174 bytes --]

diff -uprN -X elsa_import/dontdiff linux-2.6.6/drivers/elsacct/bank.c linux-2.6.6-elsa/drivers/elsacct/bank.c
--- linux-2.6.6/drivers/elsacct/bank.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.6-elsa/drivers/elsacct/bank.c	2004-05-12 07:24:41.380161848 +0200
@@ -0,0 +1,607 @@
+/*
+ *  driver/elsacct/bank.c
+ * 
+ *  ELSA - Enhanced Linux System Accounting
+ *  Guillaume Thouvenin - 26/04/2004
+ *
+ *  This file implements Enhanced Linux System Accounting. It 
+ *  provides structure and functions to manipulate "BANK". 
+ *
+ * 
+ *  This code is licenced under GPL.
+ */
+
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+
+#include <linux/bank.h>
+
+#include <asm/semaphore.h>
+#include <asm/bug.h>
+
+ /*********************************************
+ * structures and macros used to manage banks *
+ *********************************************/
+
+#ifdef CONFIG_BANK_DEBUG
+#define dprintk(format...) printk(format)
+#else
+#define dprintk(format)
+#endif
+
+/* It's the head on the list of banks */
+static struct bank_root elsa_broot = BANK_ROOT_INIT(elsa_broot);
+
+/* semaphore that protect access to bank id */
+static DECLARE_MUTEX(elsa_bid_sem);
+//SPIN_LOCK_UNLOCKED(elsalist_lock);
+
+ /********************************************************************
+ * Following functions can be use by a module (=> they are exported) *
+ ********************************************************************/
+
+/**
+ * elsa_bank_alloc - Allocates a new bank
+ * @fn : callback used when a data or a bank are destroyed
+ * @info : generic information attached to a bank (used for accounting) 
+ *
+ * Allocates a new bank and returns the new created bank.
+ * If an error is encountered NULL is returned.
+ *
+ * Here are different steps of the operation
+ *
+ *   1) Allocate space for the new bank
+ *   2) Give it an identifier
+ *   3) Initialize the head of the list of items (items will point to process)
+ *   4) Add it to the list of available bank
+ */
+struct elsa_bank
+*elsa_bank_alloc(int (*fn) (int, struct elsa_bank *, struct elsa_data *),
+		 void *info)
+{
+	struct elsa_bank *b;
+	int bid;
+
+	/* allocate space for the new bank */
+	b = (struct elsa_bank *)kmalloc(sizeof(struct elsa_bank), GFP_KERNEL);
+	if (!b) {
+		printk("elsa_bank_alloc: cannot allocate space\n");
+		return NULL;
+	}
+
+	/* 
+	 * give it an id 
+	 * Currently we only used next_bid field but this mechnism 
+	 * can give problems if we use many banks and the bid go through
+	 * its maximum  
+	 */
+	down(&elsa_bid_sem);
+	bid = elsa_broot.next_bid++;
+	up(&elsa_bid_sem);
+
+	if (bid <= 0) {
+		/* There is no available id == ERROR */
+		kfree(b);
+		printk("elsa_bank_alloc: can not find bank identifier\n");
+		return NULL;
+	} else {
+		b->bid = bid;
+	}
+
+	/* Initialize fields */
+	b->info = info;
+	b->callback = fn;
+	INIT_LIST_HEAD(&(b->data_head));
+
+	/* add the new bank to the list of banks --- NEED LOCK */
+	list_add(&(b->bank_list), &(elsa_broot.bank_head));
+
+	dprintk("elsa_bank_alloc: bank #%d created\n", b->bid);
+
+	return b;
+}
+
+/**
+ * elsa_data_alloc - Allocates a new data
+ * 
+ * Allocates a new data and returns the new created item.
+ * If an error is encountered NULL is returned.
+ *
+ * Here are different steps of the operation
+ *
+ *   1) Allocate space for the new data
+ *   2) Initialize different fields
+ */
+struct elsa_data *elsa_data_alloc(void)
+{
+	struct elsa_data *d;
+
+	/* allocate space for the new data */
+	d = (struct elsa_data *)kmalloc(sizeof(struct elsa_data), GFP_KERNEL);
+	if (!d) {
+		printk("elsa_data_alloc: cannot allocate space\n");
+		return NULL;
+	}
+
+	/* Initialize fields */
+	d->bid = 0;
+	d->process = NULL;
+	INIT_LIST_HEAD(&(d->data_list));
+	INIT_LIST_HEAD(&(d->bank_list));
+
+	return d;
+}
+
+/**
+ * elsa_bank_free - Frees space occupied by a bank.
+ * @bank: a pointer to the bank to delete
+ * 
+ * Removes a bank and returns the identifiers of the removed bank.
+ * When this function is called bank *MUST* be empty.
+ *
+ * Here are different steps of the operation
+ *
+ *   1) Write accounting information
+ *   2) Remove it from the list of banks
+ *   3) Free space used by bank
+ */
+void elsa_bank_free(struct elsa_bank *bank)
+{
+	BUG_ON(bank == NULL);
+	BUG_ON(!list_empty(&bank->data_head));
+
+	/* Before deleting the bank, we can do some action */
+	/* callback */
+	if (bank->callback) {
+		(bank->callback) (ELSA_BANK_CALLBACK, bank, NULL);
+	}
+
+	/* remove bank from the bank's list */
+	list_del(&(bank->bank_list));
+	dprintk("elsa_bank_free: bank #%d removed from the list\n", bank->bid);
+	kfree(bank);
+}
+
+/**
+ * elsa_data_free - Free data
+ * @data: data to be removed
+ * 
+ * Frees memory space used by data. 
+ */
+void elsa_data_free(struct elsa_data *data)
+{
+	struct elsa_bank *b = NULL;
+
+	BUG_ON(data == NULL);
+
+	/*
+	 * if data->bid is equal to 0, it means that an error occured between
+	 * data's allocation and data's addition in a bank. So, it isn't inserted
+	 * in any list and there is no need to call the "callback"
+	 */
+	if (data->bid != 0) {
+		/* callback, we are in the child so callback code */
+		b = elsa_get_bank(data->bid);
+		if (b && b->callback) {
+			(b->callback) (ELSA_DATA_CALLBACK, b, data);
+		}
+
+		list_del(&data->data_list);
+
+		/* Need access to head_list in task_struct */
+		write_lock_irq(&tasklist_lock);
+		list_del(&data->bank_list);
+		write_unlock_irq(&tasklist_lock);
+
+		dprintk
+		    ("elsa_data_free: process #%d removed from the bank#%d\n",
+		     data->process->pid, b->bid);
+	}
+
+	kfree(data);
+}
+
+/**
+ * elsa_bank_add - Add a process to a given bank
+ * @b  : pointer to a bank 
+ * @p  : pointer to a process
+ *
+ * add a data to a bank by setting lists. Other fields are unchanged
+ *
+ * If an error is encountered, a negative value is returned. 
+ * It can not return 0.
+ *
+ * Here are steps to perform
+ *  
+ *   1) Check arguments
+ *   2) Check if process is already in the bank
+ *   3) Initialize its fields
+ *   4) Return BID
+ */
+int elsa_bank_add(struct elsa_bank *b, struct elsa_data *d)
+{
+	if (!b || !d || !(d->process)) {
+		dprintk("elsa_bank_add: Wrong parameters\n");
+		return -EINVAL;
+	}
+
+	/* Bank ID cannot be equal to 0 */
+	BUG_ON(b->bid == 0);
+
+	/* check if process is already present */
+	if (elsa_process_present(d->process, b))
+		/* Process already in the bank, so we can not add it */
+		return -EPERM;
+
+	/* Set BID */
+	d->bid = b->bid;
+
+	/* Add data in the list of bank's data */
+	list_add(&(d->data_list), &(b->data_head));
+
+	/* Add data in the list of process's bank */
+	write_lock_irq(&tasklist_lock);
+	list_add(&(d->bank_list), &(d->process->bank_head));
+	write_unlock_irq(&tasklist_lock);
+
+	dprintk("elsa_bank_add: Add process #%d to bank #%d\n", d->process->pid,
+		b->bid);
+
+	return b->bid;
+}
+
+/**
+ * elsa_bank_remove - Remove a process to a given bank
+ * @b: pointer to the bank
+ * @d: pointer to the process
+ *
+ * Removes a given process from a given bank. 
+ * Return 0 if succedeed, negative value otherwise
+ */
+int elsa_bank_remove(struct elsa_data *d)
+{
+	int b_empty = 0;
+	struct elsa_bank *b = NULL;	/*  Used if d is the last 
+					   item of the bank */
+
+	if (!d)
+		return -EINVAL;
+
+	/* bank will be empty if d is the last item in the bank */
+	if (d->data_list.next == d->data_list.prev) {
+		b_empty = 1;
+		b = elsa_get_bank(d->bid);
+	}
+
+	/* kfree memory */
+	elsa_data_free(d);
+
+	/* 
+	 * We must free bank after data otherwise we will miss 
+	 * accounting informations 
+	 */
+	if (b_empty)
+		elsa_bank_free(b);
+
+	return 0;
+}
+
+/**
+ * elsa_bank_clean - Removes all datas in a given bank
+ * @b: pointer to the bank to be removed
+ *
+ * Removes data found in a bank given as paramater. It go through the
+ * list, removes link and free space occupied by the data.
+ * Return 0 if succedeed, negative value otherwise
+ */
+int elsa_bank_clean(struct elsa_bank *b)
+{
+	if (!b) {
+		/* bank doesn't exist */
+		dprintk("elsa_bank_clean: bank doesn't exist\n");
+		return -EAGAIN;
+	}
+
+	/* release all datas and remove the bank */
+	while (!list_empty(&(b->data_head))) {
+		/* get pointer to the first element in the list */
+		struct elsa_data *d = list_entry(b->data_head.next,
+						 struct elsa_data, data_list);
+		elsa_data_free(d);
+	}
+
+	elsa_bank_free(b);
+
+	return 0;
+}
+
+/**
+ * elsa_process_remove - Remove a process from all banks that it belongs
+ * @p: pointer to the process to be removed
+ *
+ * Removes process from all banks
+ * Return 0 if succedeed, negative value otherwise
+ */
+int elsa_process_remove(struct task_struct *p)
+{
+
+	if (!p) {
+		/* bank doesn't exist */
+		dprintk("elsa_process_remove: process doesn't exist\n");
+		return -EAGAIN;
+	}
+
+	/* release all datas and remove the bank */
+	while (!list_empty(&(p->bank_head))) {
+		/* get pointer to the first element in the list */
+		struct elsa_data *d = list_entry(p->bank_head.next,
+						 struct elsa_data, bank_list);
+		elsa_bank_remove(d);
+	}
+
+	return 0;
+}
+
+/**
+ * elsa_get_bank - Returns a pointer to a bank
+ * @bid: The identifier of a bank
+ * 
+ * Finds the bank with given ID in the list of banks
+ */
+struct elsa_bank *elsa_get_bank(unsigned int bid)
+{
+	struct list_head *entry;
+
+	list_for_each(entry, &(elsa_broot.bank_head)) {
+		struct elsa_bank *b =
+		    list_entry(entry, struct elsa_bank, bank_list);
+		if (b->bid == bid)
+			return b;
+	}
+
+	return NULL;
+}
+
+/**
+ * elsa_get_data - Returns a pointer to the container of a 
+ *                 given pid in a given bank.
+ * @pid: The identifier of the process
+ * 
+ * Find the data that holds process #PID in a given bank. If
+ * not found, NULL is returned.
+ */
+struct elsa_data *elsa_get_data(unsigned int pid, unsigned int bid)
+{
+	struct list_head *entry;
+	struct task_struct *p;
+
+	read_lock(&tasklist_lock);
+	p = find_task_by_pid(pid);
+	read_unlock(&tasklist_lock);
+
+	list_for_each(entry, &(p->bank_head)) {
+		struct elsa_data *d =
+		    list_entry(entry, struct elsa_data, bank_list);
+		if (d->bid == bid)
+			/* Got it */
+			return d;
+	}
+
+	return NULL;
+}
+
+/**
+ * elsa_process_present - Returns 1 if process is in the bank
+ * @p: the process identifier to look for
+ * @b: the bank in which we must look.
+ * 
+ * Return 1 if process is present in a bank, 0 otherwise
+ */
+int elsa_process_present(struct task_struct *p, struct elsa_bank *b)
+{
+	struct list_head *entry;
+
+	list_for_each(entry, &(b->data_head)) {
+		struct elsa_data *d =
+		    list_entry(entry, struct elsa_data, data_list);
+		if (d->process == p) {
+			/* Found it */
+			return 1;
+		}
+	}
+
+	/* Process not found in b */
+	return 0;
+}
+
+/* memory management */
+EXPORT_SYMBOL(elsa_bank_alloc);
+EXPORT_SYMBOL(elsa_data_alloc);
+EXPORT_SYMBOL(elsa_bank_free);
+EXPORT_SYMBOL(elsa_data_free);
+
+/* data manipulation */
+EXPORT_SYMBOL(elsa_bank_add);
+EXPORT_SYMBOL(elsa_bank_remove);
+EXPORT_SYMBOL(elsa_bank_clean);
+EXPORT_SYMBOL(elsa_process_remove);
+
+/* get informations */
+EXPORT_SYMBOL(elsa_get_bank);
+EXPORT_SYMBOL(elsa_get_data);
+EXPORT_SYMBOL(elsa_process_present);
+
+ /*****************************************************************************
+ * Following functions are called from kernel function.                       *
+ *   elsa_copy_parent_bank() is used when child is created (kernel/fork.c)  *
+ *****************************************************************************/
+
+/**
+ * elsa_copy_parent_bank - Add a given process to the same banks 
+ *                          as another one
+ * @from: Process from where we will copy information
+ * @to: Process to where we will copy information 
+ * 
+ * Goes through the banks to which "from" process belong and add 
+ * the process in those banks. 
+ *
+ * It is used when doing a fork (kernel/fork.c - copy_process()). 
+ * This function is used by the kernel to update child's banks.
+ */
+void elsa_copy_parent_bank(struct task_struct *from, struct task_struct *to)
+{
+	struct list_head *entry;
+
+	/* 
+	 * First, initialize to->bank_head otherwise, if 
+	 * from->bank_head is NULL it won't be initialize
+	 */
+	write_lock_irq(&tasklist_lock);
+	INIT_LIST_HEAD(&(to->bank_head));
+	write_unlock_irq(&tasklist_lock);
+
+	list_for_each(entry, &(from->bank_head)) {
+		struct elsa_bank *b;
+		struct elsa_data *d_from;
+		struct elsa_data *d_to;
+
+		dprintk("elsa_copy_parent_bank: from pid#%d to pid#%d\n",
+			from->pid, to->pid);
+
+		d_from = list_entry(entry, struct elsa_data, bank_list);
+		if (!d_from)
+			return;
+
+		/* allocat space to new data */
+		d_to = elsa_data_alloc();
+		if (!d_to) {
+			printk("elsa_copy_parent_bank: Cannot create data\n");
+			return;
+		}
+
+		d_to->bid = d_from->bid;
+		d_to->process = to;
+
+		/* d_to->process is set so we can call elsa_bank_add */
+		b = elsa_get_bank(d_from->bid);
+		if (!b) {
+			elsa_data_free(d_to);
+			printk
+			    ("elsa_copy_parent_bank: Destination not found\n");
+			return;
+		}
+
+		if (b->bid != elsa_bank_add(b, d_to)) {
+			elsa_data_free(d_to);
+			printk("elsa_copy_parent_bank: Copy error\n");
+			return;
+		}
+	}
+}
+
+ /*********************************
+ * functions used to manage /proc *
+ *                                *
+ * The entry is /proc/bankinfo    *
+ *********************************/
+
+/***
+ * Add an entry in /proc to get informations concerning
+ * banks. This entry is called /proc/bankinfo
+ ****/
+#ifdef CONFIG_PROC_FS
+static void *b_start(struct seq_file *m, loff_t * pos)
+{
+	loff_t n = *pos;
+	struct list_head *p;
+
+	/* Header is displaying just during the first called */
+	if (!n) {
+		seq_puts(m, "# - bankinfo -\n");
+		seq_puts(m, "# bankid:\t<process> <process> ...\n");
+	}
+
+	if (list_empty(&elsa_broot.bank_head))
+		return NULL;
+
+	p = elsa_broot.bank_head.next;
+	while (n--) {
+		p = p->next;
+		if (p == &elsa_broot.bank_head)
+			return NULL;
+	}
+
+	/* we return a pointer to the data in the bank */
+	return list_entry(p, struct elsa_bank, bank_list);
+}
+
+static void b_stop(struct seq_file *m, void *v)
+{
+}
+
+static void *b_next(struct seq_file *m, void *v, loff_t * pos)
+{
+	struct elsa_bank *bank = v;
+
+	++*pos;
+	return bank->bank_list.next == &elsa_broot.bank_head ? NULL :
+	    list_entry(bank->bank_list.next, struct elsa_bank, bank_list);
+}
+
+static int show_bankinfo(struct seq_file *m, void *v)
+{
+	struct elsa_bank *bank = v;
+	struct elsa_data *data;
+
+	if (!bank) {
+		seq_printf(m, "There is no banks\n");
+	} else {
+		/* display bank identifier */
+		seq_printf(m, "%d:", bank->bid);
+		/* add a tabulation */
+		seq_printf(m, "\t");
+		/* display list of processus */
+		if (list_empty(&(bank->data_head))) {
+			seq_printf(m, "Empty");
+		} else {
+			list_for_each_entry(data, &(bank->data_head), data_list)
+			    seq_printf(m, "%d ", data->process->pid);
+		}
+		/* add EOL */
+		seq_printf(m, "\n");
+	}
+
+	return 0;
+}
+
+/* bankinfo_op - iterator that generates /proc/bankinfo
+ *
+ * Output layout:
+ * bankID	pid ...
+ */
+struct seq_operations bankinfo_op = {
+	.start = b_start,
+	.stop = b_stop,
+	.next = b_next,
+	.show = show_bankinfo,
+};
+
+int bankinfo_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &bankinfo_op);
+}
+
+struct file_operations proc_bankinfo_ops = {
+	.open = bankinfo_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+EXPORT_SYMBOL(proc_bankinfo_ops);
+
+#endif
diff -uprN -X elsa_import/dontdiff linux-2.6.6/drivers/elsacct/elsacct.c linux-2.6.6-elsa/drivers/elsacct/elsacct.c
--- linux-2.6.6/drivers/elsacct/elsacct.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.6-elsa/drivers/elsacct/elsacct.c	2004-05-12 07:24:41.389160480 +0200
@@ -0,0 +1,438 @@
+/*
+ *  driver/elsacct/elsacct.c
+ * 
+ *  ELSA - Enhanced Linux System Accounting
+ *  Guillaume Thouvenin - 26/04/2004
+ *
+ *  This module implements Enhanced Linux System Accounting. 
+ *  We implement a character driver to transfer data between 
+ *  BANK that are in the kernel adress space and the user 
+ *  adress space. 
+ *
+ *  This code is licenced under GPL.
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/blkdev.h>
+#include <linux/times.h>
+
+#include <linux/elsacct.h>
+#include <linux/bank.h>
+
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_ELSACCT_DEBUG
+#define dprintk(format...) printk(format)
+#else
+#define dprintk(format...)
+#endif
+
+static int elsa_major;
+static struct elsa_acct acct_info = ELSA_ACCT_INIT;
+
+/**
+ *  encode_comp_t - encode an unsigned long into a comp_t
+ *  @value: value to encode
+ *
+ *  This routine has been adopted from the encode_comp_t() function in
+ *  the kern_acct.c file of the FreeBSD operating system. The encoding
+ *  is a 13-bit fraction with a 3-bit (base 8) exponent. 
+ *
+ *  This routine is taken from kernel/acct.c
+ */
+#define	MANTSIZE	13	/* 13 bit mantissa. */
+#define	EXPSIZE		3	/* Base 8 (3 bit) exponent. */
+#define	MAXFRACT	((1 << MANTSIZE) - 1)	/* Maximum fractional value. */
+
+typedef __u16 comp_t;
+
+static comp_t encode_comp_t(unsigned long value)
+{
+	int exp, rnd;
+
+	exp = rnd = 0;
+	while (value > MAXFRACT) {
+		rnd = value & (1 << (EXPSIZE - 1));	/* Round up? */
+		value >>= EXPSIZE;	/* Base 8 exponent == 3 bit shift. */
+		exp++;
+	}
+
+	/*
+	 * If we need to round up, do it (and handle overflow correctly).
+	 */
+	if (rnd && (++value > MAXFRACT)) {
+		value >>= EXPSIZE;
+		exp++;
+	}
+
+	/*
+	 * Clean it up and polish it off.
+	 */
+	exp <<= MANTSIZE;	/* Shift the exponent into place */
+	exp += value;		/* and add on the mantissa. */
+	return exp;
+}
+
+ /**************************
+ * Accounting is done here *
+ **************************/
+/*
+ * It's just for testing (Can not choose file)
+ */
+/**
+ * do_elsacct_data - Update accounting information when bank is removed
+ * @b: pointer to bank's data
+ *
+ * We copy code from BSD accounting. It's just to test accounting
+ * Result is written in a file (you can not choose it for now).
+ * It returns 0 if succeded, negative value otherwise
+ */
+static int do_elsacct_bank(struct elsa_bank *b)
+{
+	struct elsa_acct *info = (struct elsa_acct *)b->info;
+	struct file *file = NULL;
+	mm_segment_t old_fs;
+
+	if (!info)
+		return -EINVAL;
+
+	/* Set bank ID */
+	info->eac_bid = b->bid;
+
+	/* Open file where accounting information will be written */
+	file = filp_open(ELSACCT_FILE, O_CREAT | O_WRONLY | O_APPEND, 0666);
+
+	if (IS_ERR(file)) {
+		return (PTR_ERR(file));
+	}
+
+	if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
+		filp_close(file, NULL);
+		return (-EACCES);
+	}
+
+	if (!file->f_op->write) {
+		filp_close(file, NULL);
+		return (-EIO);
+	}
+
+	/*
+	 * Kernel segment override to datasegment and write it
+	 * to the accounting file. 
+	 */
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	file->f_op->write(file, (char *)info, sizeof(struct elsa_acct),
+			  &file->f_pos);
+
+	set_fs(old_fs);
+
+	filp_close(file, NULL);
+	return 0;
+}
+
+/**
+ * do_elsacct_data - Update accounting information when data is removed
+ * @b: pointer to bank's data
+ * @d: pointer to the data
+ *
+ * We copy code from BSD accounting. It's just to test accounting
+ * It returns 0 if succeded, negative value otherwise
+ */
+static int do_elsacct_data(struct elsa_bank *b, struct elsa_data *d)
+{
+	u64 elapsed;
+	struct elsa_acct *info = (struct elsa_acct *)b->info;
+	struct task_struct *p = d->process;
+
+	if (!info)
+		return -EINVAL;
+
+	/* One more process in the bank */
+	info->eac_ptot++;
+
+	/* elapsed time */
+	elapsed = jiffies_64_to_clock_t(get_jiffies_64() - p->start_time);
+	info->eac_etime += encode_comp_t(elapsed < (unsigned long)-1l ?
+					 (unsigned long)elapsed : (unsigned
+								   long)-1l);
+
+	/* user time and system time */
+	info->eac_utime += encode_comp_t(jiffies_to_clock_t(p->utime));
+	info->eac_stime += encode_comp_t(jiffies_to_clock_t(p->stime));
+
+	/* minor and major page faults */
+	info->eac_minflt += encode_comp_t(p->min_flt);
+	info->eac_majflt += encode_comp_t(p->maj_flt);
+
+	return 0;
+}
+
+int do_elsacct(int opcode, struct elsa_bank *b, struct elsa_data *d)
+{
+	int retval = 0;
+
+	switch (opcode) {
+	case ELSA_BANK_CALLBACK:
+		BUG_ON(b == NULL);
+		retval = do_elsacct_bank(b);
+		break;
+	case ELSA_DATA_CALLBACK:
+		BUG_ON(b == NULL);
+		BUG_ON(d == NULL);
+		retval = do_elsacct_data(b, d);
+		break;
+	default:
+		printk("do_elsacct: unknown opcode\n");
+		retval = -ENOIOCTLCMD;
+		break;
+	}
+
+	return retval;
+}
+
+ /**************************************************************
+ * functions used to manipulate the device                     *
+ *                                                             *
+ * The enhanced linux system accounting device is /dev/elsacct *
+ * and the major number is dynamically given by OS             *
+ **************************************************************/
+
+/* 
+ * The process context, represented as a typical driver method - ioctl(), must 
+ * use spin_lock_irq() because it knows that interrupts are always enabled while 
+ * executing the device ioctl() method.
+ */
+spinlock_t elsa_lock = SPIN_LOCK_UNLOCKED;
+
+/**
+ * elsacct_ioctl - issue a device specific command
+ * @inode: pointer to inode structure
+ * @file : file pointer
+ * @cmd  : specific command to perform.
+ * @arg  : arguments that depend of cmd.
+ *
+ * Perform some actions on banks that depend of command passed to the
+ * system call
+ */
+int elsacct_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		  unsigned long arg)
+{
+	int retval = 0;
+	struct elsa_ioctl_args args;
+	struct task_struct *p;
+	struct elsa_bank *b;
+	struct elsa_data *d;
+
+	/* Recover ioctl parameters */
+	if (copy_from_user(&args, (struct elsa_ioctl_args *)arg,
+			   sizeof(struct elsa_ioctl_args)))
+		return -EFAULT;
+
+	switch (cmd) {
+	case ELSACCT_BANK_REMOVE:
+		/*
+		 * To remove a data from a bank, we need to:
+		 *     1) if #BID == 0
+		 *            get pointer to process
+		 *            remove from all banks that it belongs
+		 *        else
+		 *            get pointer to data
+		 *            remove from bank #BID
+		 *        endif
+		 */
+		if (args.bid == 0) {
+			read_lock(&tasklist_lock);
+			p = find_task_by_pid(args.pid);
+			read_unlock(&tasklist_lock);
+			if (!p) {
+				dprintk("elsacct_ioct: process #%d not found\n",
+					args.pid);
+				return -EAGAIN;
+			}
+
+			spin_lock_irq(&elsa_lock);
+			retval = elsa_process_remove(p);
+			spin_unlock_irq(&elsa_lock);
+		} else {
+
+			d = elsa_get_data(args.pid, args.bid);
+			if (!d) {
+				dprintk("elsacct_ioct: data not found\n");
+				return -EAGAIN;
+			}
+
+			spin_lock_irq(&elsa_lock);
+			retval = elsa_bank_remove(d);
+			spin_unlock_irq(&elsa_lock);
+		}
+		break;
+
+	case ELSACCT_BANK_CLEAN:
+		/*
+		 * To clean a bank (remove all data), we need to:
+		 *     1) Get pointer to the bank
+		 *     2) Remove it
+		 */
+		b = elsa_get_bank(args.bid);
+		if (!b) {
+			dprintk("elsacct_ioct: BANK not found\n");
+			return -EAGAIN;
+		}
+
+		spin_lock_irq(&elsa_lock);
+		retval = elsa_bank_clean(b);
+		spin_unlock_irq(&elsa_lock);
+		break;
+
+	case ELSACCT_BANK_ADD:
+		/*
+		 * To add a process to a bank we need to perform 
+		 * following actions:
+		 *     1) Allocate memory space to data (container)
+		 *     2) Update process in data field
+		 *     3) If #BID == 0
+		 *          create a new bank;
+		 *        else
+		 *          get pointer to bank #BID
+		 *     4) Add the container to the bank
+		 */
+		d = elsa_data_alloc();
+		if (!d)
+			return -ENOMEM;
+
+		/* We need the pointer to task_struct */
+		read_lock(&tasklist_lock);
+		p = find_task_by_pid(args.pid);
+		read_unlock(&tasklist_lock);
+		if (!p) {
+			dprintk("elsacct_ioct: PID#%d not found\n", args.pid);
+			/* Don't forget to release memory */
+			elsa_data_free(d);
+			return -EAGAIN;
+		}
+		d->process = p;
+
+		if (args.bid == 0)
+			b = elsa_bank_alloc(&do_elsacct, &acct_info);
+		else
+			b = elsa_get_bank(args.bid);
+
+		if (!b) {
+			dprintk("elsacct_ioct: BID#%d not found\n", args.bid);
+			/* Don't forget to release memory */
+			elsa_data_free(d);
+			return -EAGAIN;
+		}
+
+		spin_lock_irq(&elsa_lock);
+		retval = elsa_bank_add(b, d);
+		spin_unlock_irq(&elsa_lock);
+		break;
+
+	default:
+		dprintk(KERN_WARNING
+			"elsacct_ioctl: 0x%x unsupported ioctl command\n", cmd);
+		retval = -ENOIOCTLCMD;
+	};
+
+	return retval;
+}
+
+struct file_operations elsa_fops = {
+	.owner = THIS_MODULE,
+	.ioctl = elsacct_ioctl,
+};
+
+/**
+ * elsacct_init - Initialize enhanced linux system accounting
+ * 
+ * Initializes "callbacks" to bank and data. Those 
+ * functions are called a bank or a data are destroyed.
+ * It allows to perform some actions in the module.
+ */
+static int __init elsacct_init(void)
+{
+	int retval = 0;
+	struct proc_dir_entry *entry;
+
+	/* register character device with a dynamic major number */
+	elsa_major = register_chrdev(0, "elsacct", &elsa_fops);
+	if (!elsa_major) {
+		dprintk(KERN_WARNING
+			"elsacct_init: can't get major %d\n", elsa_major);
+		return -EIO;
+	}
+
+	/* 
+	 * To get the major number we use a script that parse /proc/devices
+	 * and get the correct major number. We don't use elsa_major except
+	 * to test if the device is registered.
+	 */
+	dprintk(KERN_INFO "ELSACCT: device driver is recorded\n");
+	/*
+	 * From here, dev is registered. Thus, if there is a problem
+	 * we must unregister the device.
+	 */
+
+#ifdef CONFIG_PROC_FS
+	/* create /proc entry */
+	entry = create_proc_entry("bankinfo", 0, NULL);
+	if (entry) {
+		entry->proc_fops = &proc_bankinfo_ops;
+	} else {
+		unregister_chrdev(elsa_major, "elsacct");
+		return -EIO;
+	}
+#endif
+
+	/* succeed */
+	return retval;
+}
+
+ /************************
+ * Module initialization *
+ ************************/
+
+/**
+ * elsacct_init_module - called when module is loaded
+ *
+ * Display a message in dmesg and call the real 
+ * initialization function.
+ */
+static int __init elsacct_init_module(void)
+{
+	dprintk(KERN_INFO "ELSA accounting started\n");
+	return elsacct_init();
+}
+
+/**
+ * elsacct_cleanup - called when module is unloaded
+ *
+ * Display a message in dmesg 
+ */
+static void __exit elsacct_cleanup_module(void)
+{
+	/* release the major number when module is unloaded */
+	if (unregister_chrdev(elsa_major, "elsacct"))
+		dprintk(KERN_WARNING
+			"elsacct_cleanup: cannot unregister blkdev\n");
+	else
+		dprintk(KERN_INFO "elsacct_cleanup: accounting terminated\n");
+}
+
+module_init(elsacct_init_module);
+module_exit(elsacct_cleanup_module);
+
+MODULE_DESCRIPTION("Enhanced Linux System Accounting.");
+MODULE_AUTHOR("Guillaume Thouvenin <guillaume.thouvenin@bull.net>");
+
+MODULE_LICENSE("GPL");
diff -uprN -X elsa_import/dontdiff linux-2.6.6/drivers/elsacct/Kconfig linux-2.6.6-elsa/drivers/elsacct/Kconfig
--- linux-2.6.6/drivers/elsacct/Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.6-elsa/drivers/elsacct/Kconfig	2004-05-11 14:19:56.000000000 +0200
@@ -0,0 +1,61 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+menu "ELSAcct Driver"
+
+config BANK
+	bool "ELSA bank support"
+	depends on EXPERIMENTAL
+	default n
+	---help---
+	  BANK structures are needed if you want to do enhanced 
+	  linux system accounting
+
+	  say Y if you want to use Enhanced Linux Sytem Accounting
+
+config BANK_DEBUG
+	bool "ELSA bank debugging support"
+	depends on BANK
+	default n
+	---help---
+          This option allows you to enable debugging output when using 
+	  banks structure. Currently, such structure is used by Enhanced
+	  Linux System Accounting (ELSA). Informations are sent to the 
+	  console.
+
+config ELSACCT
+	tristate "Enhanced Linux System Accounting"
+	depends on EXPERIMENTAL
+	requires BANK
+	default n
+	---help---
+  	  The goal of accounting is to collect and report the use of various 
+  	  system resources by applications. Informations, like process time, 
+  	  CPU usage, connect time or disk space usage, provides data that helps 
+  	  the system to adjust the use of resources between processes.
+  	
+  	  The current BSD-like process accounting that already exists in Linux 
+  	  collects informations on individual users or groups of users. The ELSA 
+  	  project aims to improve and extend the monitoring of resources with 
+  	  different criteria like groups of processes. Another target for this 
+  	  project is to give Linux an homogeneous set of commands for all kinds 
+  	  of accounting (memory, CPU and I/O).
+  	
+     	  To compile this driver as a module, choose M here: the module will be 
+  	  called elsa-acct.
+  
+  	  Documentation about ELSA is available from
+  	  <http://elsa.sourceforge.net>
+
+config ELSACCT_DEBUG
+	bool "ELSA accounting debugging support"
+	depends on ELSACCT
+	default n
+	---help---
+          This option allows you to enable debugging output when using 
+	  enhanced linux system accounting. Informations are sent to the 
+	  console.
+
+endmenu
diff -uprN -X elsa_import/dontdiff linux-2.6.6/drivers/elsacct/Makefile linux-2.6.6-elsa/drivers/elsacct/Makefile
--- linux-2.6.6/drivers/elsacct/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.6-elsa/drivers/elsacct/Makefile	2004-05-06 12:39:50.000000000 +0200
@@ -0,0 +1,5 @@
+#
+# Makefile for the Enhanced Linux System Accounting
+#
+obj-$(CONFIG_BANK)	+= bank.o
+obj-$(CONFIG_ELSACCT)	+= elsacct.o
diff -uprN -X elsa_import/dontdiff linux-2.6.6/drivers/Kconfig linux-2.6.6-elsa/drivers/Kconfig
--- linux-2.6.6/drivers/Kconfig	2004-05-10 04:33:20.000000000 +0200
+++ linux-2.6.6-elsa/drivers/Kconfig	2004-05-10 09:45:43.000000000 +0200
@@ -4,6 +4,8 @@ menu "Device Drivers"
 
 source "drivers/base/Kconfig"
 
+source "drivers/elsacct/Kconfig"
+
 source "drivers/mtd/Kconfig"
 
 source "drivers/parport/Kconfig"
diff -uprN -X elsa_import/dontdiff linux-2.6.6/drivers/Makefile linux-2.6.6-elsa/drivers/Makefile
--- linux-2.6.6/drivers/Makefile	2004-05-10 04:33:13.000000000 +0200
+++ linux-2.6.6-elsa/drivers/Makefile	2004-05-10 09:46:10.000000000 +0200
@@ -50,3 +50,4 @@ obj-$(CONFIG_MCA)		+= mca/
 obj-$(CONFIG_EISA)		+= eisa/
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
 obj-y				+= firmware/
+obj-y				+= elsacct/
diff -uprN -X elsa_import/dontdiff linux-2.6.6/include/linux/bank.h linux-2.6.6-elsa/include/linux/bank.h
--- linux-2.6.6/include/linux/bank.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.6-elsa/include/linux/bank.h	2004-05-12 07:24:35.766015328 +0200
@@ -0,0 +1,164 @@
+/*
+ *  include/linux/elsa_bank.h
+ * 
+ *  ELSA - Enhanced Linux System Accounting
+ *  Guillaume Thouvenin - 26/04/2004
+ *  
+ *  Provides structures and functions to manipulate "BANK". 
+ *  They are containers that store a set of processes. 
+ *  When a "BANK" is empty it is destroy and accounting infor-
+ *  mations are stored in a file. Informations are about 
+ *  all process contained in a "BANK"
+ * 
+ *  The idea is to provide a mechanism that allows to group 
+ *  chosen process together. "BANK" must have some properties like:
+ *    o If a process belongs to a bank, its children belong to the same bank
+ *    o A process can be placed in several different banks
+ *    o When the user adds a process to an non-existent bank, the container
+ *      must automatically be created
+ *    o When the last process of a bank exits, informations about all processes
+ *      that belonged to the bank must be stored (maybe in a file) and the
+ *      container must be destroyed
+ * 
+ *  To do that, we use a double linked list provides by the kernel
+ *  (include/linux/list.h) and we do the following thing:
+ * 
+ *                              BANK #1           BANK #2  
+ *                             elsa_bank       elsa_bank  
+ *         elsa_broot         -----------       ----------- 
+ *          bank_root        |  bid = 1  |     |  bid = 2  |
+ *       --------------      |-----------|     |-----------|
+ *      | next_bid = 3 |     |   info    |     |   info    |
+ *      |--------------|     |-----------|     |-----------|
+ *      | freebid_head |     | callback  |     | callback  |
+ *      |--------------|     |-----------|     |-----------|
+ *      | bank_head    |<===>| bank_list |<===>| bank_list |<===>...
+ *       --------------      |-----------|     |-----------|
+ *                           | data_head |     | data_head |<===>...
+ *                            ----------        -----------
+ *                                   ^ ^
+ *                                   | |
+ *                                   |  ================= 
+ *    PROCESS            DATA #1     |     DATA #2       |  
+ *  task_struct         elsa_data    |    elsa_data      |
+ *   ---------         -----------   |   -----------     |
+ *  |         |       |  bid = 1  |  |  |  bid = 1  |    |
+ *  |         |       |-----------|  |  |-----------|    |
+ *  |         |<------|  process  |  |  |  process  |    |
+ *  |         |       |-----------|  |  |-----------|    |
+ *  |         |       | data_list |<=   | data_list |<===
+ * ...       ...      |           |<===>|           |
+ *  |---------|       |-----------|     |-----------|
+ *  |bank_head|<=====>| bank_list |     | bank_list |
+ *   ---------         -----------       -----------
+ *
+ *
+ * Field "bank_list" in the elsa_data is used to know which are banks with
+ * a given process. Structure "task_struc" is modified to use this field.
+ */
+
+#ifndef __LINUX_BANK_H
+#define __LINUX_BANK_H
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+#define ELSA_BANK_CALLBACK 0
+#define ELSA_DATA_CALLBACK 1
+
+extern rwlock_t elsalist_lock;
+
+/***
+ * Internal structures
+ ***/
+
+struct bank_root {
+	/* 
+	 * We need to protect ID by a semaphore since it must be
+	 * a unique number. We can't have to bank with same ID
+	 */
+	unsigned int next_bid;	/* next available bank identifier */
+	struct list_head freebid_head;	/* a list of free bank identifier - Not used yet */
+	struct list_head bank_head;	/* head of the list of bank */
+};
+
+#define BANK_ROOT_INIT(root) \
+{							     \
+	.next_bid 	= 1,                                 \
+	.freebid_head 	= LIST_HEAD_INIT(root.freebid_head), \
+	.bank_head	= LIST_HEAD_INIT(root.bank_head),    \
+}
+
+struct elsa_freebid {
+	int bid;
+	struct list_head bid_list;
+};
+
+struct elsa_data;		/* Needed in struct elsa_bank */
+
+struct elsa_bank {
+	int bid;		/* the bank identifier */
+	void *info;		/* allow to hang information to banks */
+	int (*callback) (int, struct elsa_bank *, struct elsa_data *);	/* callback */
+	struct list_head bank_list;	/* list of available banks */
+	struct list_head data_head;	/* head of the list of datas in the 
+					   bank */
+};
+
+struct elsa_data {
+	int bid;		/* the bank to which data belong */
+	struct task_struct *process;	/* the process information */
+	struct list_head data_list;	/* link between datas in a bank */
+	struct list_head bank_list;	/* used by a process to link banks 
+					   that contains it */
+};
+
+#ifdef CONFIG_PROC_FS
+extern struct file_operations proc_bankinfo_ops;
+#endif
+
+ /*********************************************
+ * Following functions can be use by a module *
+ * (=> they are exported)                     *
+ *********************************************/
+
+/* allocate memory space: (call to kmalloc) */
+struct elsa_bank
+*elsa_bank_alloc(int (*fn) (int, struct elsa_bank *, struct elsa_data *),
+		 void *);
+struct elsa_data *elsa_data_alloc(void);
+void elsa_bank_free(struct elsa_bank *bank);
+void elsa_data_free(struct elsa_data *data);
+
+/* 
+ * manipulate datas:
+ * Memory space can be released (call to kfree) in the last three
+ * functions.
+ */
+int elsa_bank_add(struct elsa_bank *b, struct elsa_data *d);
+int elsa_bank_remove(struct elsa_data *d);
+int elsa_bank_clean(struct elsa_bank *b);
+/* elsa_process_remove() is used by the kernel so it is declared below */
+
+/* get information */
+struct elsa_bank *elsa_get_bank(unsigned int bid);
+struct elsa_data *elsa_get_data(unsigned int pid, unsigned int bid);
+int elsa_process_present(struct task_struct *p, struct elsa_bank *b);
+
+ /*****************************************************************************
+ * Following functions are called from kernel function.                       *
+ *   elsa_copy_parent() is used when child is created (kernel/fork.c)         *
+ *   elsa_process_remove() is used when a process terminates (kernel/exit.c) *
+ *****************************************************************************/
+#ifdef CONFIG_BANK
+extern void elsa_copy_parent_bank(struct task_struct *from,
+				  struct task_struct *to);
+extern int elsa_process_remove(struct task_struct *p);
+#else
+#define elsa_copy_parent_bank(a,b) do {} while(0)
+#define elsa_bank_remove_all(a)    do {} while(0)
+#endif				/* !(CONFIG_BANK) */
+
+#endif				/* !(__LINUX_BANK_H) */
diff -uprN -X elsa_import/dontdiff linux-2.6.6/include/linux/elsacct.h linux-2.6.6-elsa/include/linux/elsacct.h
--- linux-2.6.6/include/linux/elsacct.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.6-elsa/include/linux/elsacct.h	2004-05-12 07:24:32.067577576 +0200
@@ -0,0 +1,55 @@
+/*
+ *  include/linux/elsa_acct.h
+ * 
+ *  ELSA - Enhanced Linux System Accounting
+ *  Guillaume Thouvenin - 26/04/2004
+ *      
+ */
+
+#ifndef __LINUX_ELSACCT_H
+#define __LINUX_ELSACCT_H
+
+/* IOCTL numbers */
+#define ELSACCT_MAGIC		0x3538
+
+#define ELSACCT_BANK_REMOVE	0x353801	/* Remove one data from a bank, 
+						 * if #BID == 0 remove from all banks */
+#define ELSACCT_BANK_CLEAN	0x353802	/* Remove all data from a bank */
+#define ELSACCT_BANK_ADD	0x353803	/* Add a process to a bank,
+						 * if #BID == 0 create the bank */
+
+/* Currently, informations are stored in the same file and we cannot chose it */
+#define ELSACCT_FILE	"/var/log/bank"
+
+struct elsa_ioctl_args {
+	unsigned int bid;	/* bank identifier */
+	unsigned int pid;	/* process identifier */
+};
+
+/* 
+ * Currently, we take as a starting point the BSD-style 
+ * process accounting and we write values into dmesg
+ * buffer. (of course we need to change this) 
+ */
+struct elsa_acct {
+	int eac_bid;		/* Bank id */
+	int eac_ptot;		/* Total number of process that are added to a bank */
+	int eac_utime;		/* Accounting User Time */
+	int eac_stime;		/* Accounting System Time */
+	int eac_etime;		/* Accounting Elapsed Time */
+	int eac_minflt;		/* Accounting Minor Pagefaults */
+	int eac_majflt;		/* Accounting Major Pagefaults */
+};
+
+#define ELSA_ACCT_INIT 		\
+{ 				\
+	.eac_bid 	= 0,	\
+	.eac_ptot	= 0,	\
+	.eac_utime	= 0,	\
+	.eac_stime	= 0,	\
+	.eac_etime	= 0,	\
+	.eac_minflt 	= 0,	\
+	.eac_majflt 	= 0,	\
+}
+
+#endif				/* !(__LINUX_ELSACCT_H) */
diff -uprN -X elsa_import/dontdiff linux-2.6.6/include/linux/init_task.h linux-2.6.6-elsa/include/linux/init_task.h
--- linux-2.6.6/include/linux/init_task.h	2004-05-10 04:32:00.000000000 +0200
+++ linux-2.6.6-elsa/include/linux/init_task.h	2004-05-10 09:48:18.000000000 +0200
@@ -112,6 +112,7 @@ extern struct group_info init_groups;
 	.proc_lock	= SPIN_LOCK_UNLOCKED,				\
 	.switch_lock	= SPIN_LOCK_UNLOCKED,				\
 	.journal_info	= NULL,						\
+	.bank_head	= LIST_HEAD_INIT(tsk.bank_head),		\
 }
 
 
diff -uprN -X elsa_import/dontdiff linux-2.6.6/include/linux/sched.h linux-2.6.6-elsa/include/linux/sched.h
--- linux-2.6.6/include/linux/sched.h	2004-05-10 04:32:00.000000000 +0200
+++ linux-2.6.6-elsa/include/linux/sched.h	2004-05-10 09:50:04.000000000 +0200
@@ -504,6 +504,9 @@ struct task_struct {
 
 	unsigned long ptrace_message;
 	siginfo_t *last_siginfo; /* For ptrace use.  */
+
+/* List of BANK to which the process belong -- Used by ELSA */
+	struct list_head bank_head;
 };
 
 static inline pid_t process_group(struct task_struct *tsk)
diff -uprN -X elsa_import/dontdiff linux-2.6.6/kernel/exit.c linux-2.6.6-elsa/kernel/exit.c
--- linux-2.6.6/kernel/exit.c	2004-05-10 04:33:19.000000000 +0200
+++ linux-2.6.6-elsa/kernel/exit.c	2004-05-10 09:55:57.000000000 +0200
@@ -59,6 +59,7 @@ repeat: 
 	atomic_dec(&p->user->processes);
 	spin_lock(&p->proc_lock);
 	proc_dentry = proc_pid_unhash(p);
+	elsa_process_remove(p);
 	write_lock_irq(&tasklist_lock);
 	if (unlikely(p->ptrace))
 		__ptrace_unlink(p);
diff -uprN -X elsa_import/dontdiff linux-2.6.6/kernel/fork.c linux-2.6.6-elsa/kernel/fork.c
--- linux-2.6.6/kernel/fork.c	2004-05-10 04:32:00.000000000 +0200
+++ linux-2.6.6-elsa/kernel/fork.c	2004-05-10 09:57:36.000000000 +0200
@@ -1011,6 +1011,19 @@ struct task_struct *copy_process(unsigne
 	INIT_LIST_HEAD(&p->ptrace_children);
 	INIT_LIST_HEAD(&p->ptrace_list);
 
+        /*
+         * Child is in the same BANK as parent. So we copy the list of banks
+         * from current to p. We can not just counting reference on the structure
+         * because the may evoluate in differents way. I think it's easier to
+         * do like this but maybe I'm wrong... -- guillaume
+         *
+         * We put that call outside lock_irq because elsa_copy_parent_bank
+         * uses kmalloc(GFP_KERNEL). Therefore, as we modify task_struct,
+         * we manage lock_irq ourselves. -- guillaume
+         *
+         */
+        elsa_copy_parent_bank(current, p);
+	
 	/* Need tasklist lock for parent etc handling! */
 	write_lock_irq(&tasklist_lock);
 	/*
diff -uprN -X elsa_import/dontdiff linux-2.6.6/Makefile linux-2.6.6-elsa/Makefile
--- linux-2.6.6/Makefile	2004-05-10 04:32:53.000000000 +0200
+++ linux-2.6.6-elsa/Makefile	2004-05-10 09:58:01.000000000 +0200
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 6
-EXTRAVERSION =
+EXTRAVERSION = -elsa
 NAME=Zonked Quokka
 
 # *DOCUMENTATION*


             reply	other threads:[~2004-05-12 12:22 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-05-12 12:20 Guillaume Thouvenin [this message]
  -- strict thread matches above, loose matches on Subject: below --
2004-05-05 13:26 [PATCH] Enhanced Linux System Accounting Guillaume Thouvenin
2004-05-05 18:12 ` Karim Yaghmour
2004-05-05 20:18 ` Chris Wright

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=40A216A0.9010202@bull.net \
    --to=guillaume.thouvenin@bull.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.