mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Christian Engwer <christi@fsmath.zbt.uni-heidelberg.de>
To: linux-kernel@vger.kernel.org
Subject: kernel patch to keep control over batch processes
Date: Mon, 27 Aug 2001 13:47:15 +0200	[thread overview]
Message-ID: <20010827134715.A21058@mathphys.fsk.uni-heidelberg.de> (raw)

Hello,

I am not shure, wether any one else could use a patch like this.
We have a cluster at the ,,Kirchhoff Institut fuer Physik'' at
Heidelberg and would like to keep track of the tasks a batch-job forks.

In order to achieve this I have written a kernel-patch (safefork)
(for kernel 2.4.4 right now).

I have added 3 flags and one datum to the task_struct, where I store
my data. Further changes are made to the proc file system, where I
have added a new file /proc/safefork and added some fields to
/proc/$PID/status.
You can mark a process to be watched by piping a command into
/proc/$PID/status.

At least I have made some changes to do_fork and do_exit, in order to
keep track of the forked processes.

Anyone interested in this can have more information at
http://tipsrv.kip.uni-heidelberg.de/christi/safefork

I will also add the most important parts of the patch.

CU Christian

PS: If this is not the right place to post this mail... please don't
    flame me - it's my first patch

PSS: the important parts of the patch LocalWords:  not shure wether
#
# SafeFork kernel patch
#
# additionel ifo in /proc/$PID/status
diff -u -r -N linux/fs/proc/array.c linux-safefork/fs/proc/array.c
--- linux/fs/proc/array.c	Fri Apr  6 19:51:19 2001
+++ linux-safefork/fs/proc/array.c	Sun Aug 26 17:22:26 2001
@@ -76,6 +80,35 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 
+#ifdef CONFIG_SAFEFORK
+static inline char * task_safefork(struct task_struct *p, char *buffer)
+{
+	struct task_struct *list_p;        
+        read_lock(&tasklist_lock);
+	buffer += sprintf(buffer, "sf_flags:\t");
+	if (p->sf_watchme)
+		buffer += sprintf(buffer, "watchme ");
+	if (p->sf_zombie)
+		buffer += sprintf(buffer, "zombie ");
+	if (p->sf_killchildren)
+		buffer += sprintf(buffer, "killchildren");
+	buffer += sprintf(buffer,"\nsf_parent:\t%d", p->sf_parent);
+	if (p->sf_parent==p->pid)
+		buffer += sprintf(buffer, " (me)\n");
+	else
+		buffer += sprintf(buffer, "\n");	    
+	buffer += sprintf(buffer,"\sf_children:");
+	for_each_task(list_p) {
+		if (list_p->sf_parent==p->pid && list_p->pid!=p->pid) {
+			buffer += sprintf(buffer," %d",list_p->pid);	    
+		}
+	}
+	buffer += sprintf(buffer,"\n");
+	read_unlock(&tasklist_lock);	  
+	return buffer;
+}
+#endif
+
 /* Gcc optimizes away "strlen(x)" for constant x */
 #define ADDBUF(buffer, string) \
 do { memcpy(buffer, string, strlen(string)); \
# write support for /proc/$PID/status
diff -u -r -N linux/fs/proc/base.c linux-safefork/fs/proc/base.c
--- linux/fs/proc/base.c	Mon Mar 19 21:34:55 2001
+++ linux-safefork/fs/proc/base.c	Sun Aug 26 17:23:52 2001
@@ -271,6 +276,73 @@
 
 #define PROC_BLOCK_SIZE	(3*1024)		/* 4K page size but our output routines use some slack for overruns */
 
+#ifdef CONFIG_SAFEFORK
+static ssize_t status_safefork_write(struct file * file, const char * buf,
+				     size_t count, loff_t *ppos)
+{
+  	char * buffer;
+	int err;
+	uid_t w_uid, o_uid;
+	struct inode * inode = file->f_dentry->d_inode;
+	struct task_struct *p = inode->u.proc_i.task;
+
+	/* Who is writing? */
+	w_uid = file->f_uid;
+	printk(KERN_DEBUG "%i wants to write to /proc/%i/status\n",
+	       w_uid, p->pid);
+	/* Who own's the process? */
+	o_uid = p->uid;
+	printk(KERN_DEBUG "%i owns /proc/%i/status\n",
+	       o_uid, p->pid);
+
+	/* only root and the process owner can change the flags */
+	if ( o_uid!=w_uid && w_uid!=0)
+		return -EACCES;
+
+	/* check the buffer */
+	if (!buf || count>PAGE_SIZE)
+		return -EINVAL;
+
+	if (!(buffer = (char *) __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	copy_from_user(buffer, buf, count);
+
+	err = -EINVAL;
+	/* Here comes a REALLY stupid parser */
+#define SF_KILL "safefork killchildren"
+#define SF_WATCH "safefork watchme"
+	if (0==strncmp(SF_KILL, buffer, strlen(SF_KILL))) {	    
+		if (!p->sf_watchme) {
+			write_lock_irq(&tasklist_lock);
+			/* set the flags
+			// take care of me
+			p->sf_watchme=1;
+			// kill my children :-)
+			p->sf_killchildren=1;
+			// I am the master parent
+			p->sf_parent=p->pid;
+			write_unlock_irq(&tasklist_lock);
+		}
+	}
+	else
+		if (0==strncmp(SF_WATCH, buffer, strlen(SF_WATCH))) {
+			if (!p->sf_watchme) {
+				write_lock_irq(&tasklist_lock);
+				/* set the flags */
+				// take care of me
+				p->sf_watchme=1; 
+				// don't kill my children
+				p->sf_killchildren=0;
+				// I am the master parent
+				p->sf_parent=p->pid;
+				write_unlock_irq(&tasklist_lock);
+			}
+		}
+	free_page((unsigned long) buffer);
+	return err;
+}
+#endif
+
 static ssize_t proc_info_read(struct file * file, char * buf,
 			  size_t count, loff_t *ppos)
 {
# the new file /proc/safefork
diff -u -r -N linux/fs/proc/proc_misc.c linux-safefork/fs/proc/proc_misc.c
--- linux/fs/proc/proc_misc.c	Sat Apr 14 05:26:07 2001
+++ linux-safefork/fs/proc/proc_misc.c	Sun Aug 26 17:24:12 2001
@@ -375,6 +378,54 @@
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
+#ifdef CONFIG_SAFEFORK
+static int safefork_read_proc(char *page, char **start, off_t off,
+			      int count, int *eof, void *data)
+{
+	int len,zombie=0,watchme=0,killchildren=0;
+	char* buffer=page;
+	
+	struct task_struct *list_p;        
+        read_lock(&tasklist_lock);
+	
+	buffer += sprintf(buffer, "SafeFork:\n");
+	for_each_task(list_p) {
+		if (list_p->sf_watchme) watchme++;
+		if (list_p->sf_killchildren) killchildren++;
+		if (list_p->sf_zombie) zombie++;
+	}
+	
+	buffer += sprintf(buffer, "watchme [%i]:",watchme);
+	for_each_task(list_p) {
+		if (list_p->sf_watchme) {
+			buffer += sprintf(buffer," %d",list_p->pid);	    
+		}
+	}
+	buffer += sprintf(buffer,"\n");
+	
+	buffer += sprintf(buffer, "killchildren [%i]:",killchildren);
+	for_each_task(list_p) {
+		if (list_p->sf_killchildren) {
+			buffer += sprintf(buffer," %d",list_p->pid);	    
+		}
+	}
+	buffer += sprintf(buffer,"\n");
+	
+	buffer += sprintf(buffer, "zombie [%i]:",zombie);
+	for_each_task(list_p) {
+		if (list_p->sf_zombie) {
+			buffer += sprintf(buffer," %d",list_p->pid);	    
+		}
+	}
+	buffer += sprintf(buffer,"\n");
+	
+	read_unlock(&tasklist_lock);	  
+	
+	len = strlen(page);
+	return proc_calc_metrics(page, start, off, count, eof, len);
+}
+#endif
+
 static int ioports_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
 {
# the new flags in task_struct
diff -u -r -N linux/include/linux/sched.h linux-safefork/include/linux/sched.h
--- linux/include/linux/sched.h	Sat Apr 28 00:48:34 2001
+++ linux-safefork/include/linux/sched.h	Sun Aug 26 17:40:48 2001
@@ -322,7 +322,17 @@
 	int pdeath_signal;  /*  The signal sent when the parent dies  */
 	/* ??? */
 	unsigned long personality;
-	int dumpable:1;
+
+#ifdef CONFIG_SAFEFORK
+        /* -- flags needed by safefork -- */
+        int sf_killchildren:1;
+        int sf_watchme:1;
+        int sf_zombie:1;
+        pid_t sf_parent; /* the master parent */
+        /* -- end safefork -- */
+#endif
+  
+        int dumpable:1;
 	int did_exec:1;
 	pid_t pid;
 	pid_t pgrp;
# do_exit calls now 2 extra funtions sf_kill_children
# and sf_mark_children
diff -u -r -N linux/kernel/exit.c linux-safefork/kernel/exit.c
--- linux/kernel/exit.c	Fri Feb  9 20:29:44 2001
+++ linux-safefork/kernel/exit.c	Sun Aug 26 17:28:07 2001
@@ -419,6 +429,66 @@
 	write_unlock_irq(&tasklist_lock);
 }
 
+#ifdef CONFIG_SAFEFORK
+/*
+ * if killchildren is set, I will send SIGTERM & SIGKILL to all children
+ */
+void sf_exit_children(struct task_struct *tsk)
+{
+	struct task_struct *list_p;        
+	int priv=1; // kernel privileges
+
+	/* check the flags */
+	if (!tsk->sf_killchildren)
+		return;
+
+	/* loop through the tasks and TERM & KILL */
+	read_lock(&tasklist_lock);
+	for_each_task(list_p) {
+		if (list_p->sf_parent==tsk->pid && list_p->pid!=tsk->pid) {
+			// hope that's the right way to send signals
+			// taken from signal.c
+			send_sig_info(SIGTERM,
+				      (void*)(long)(priv != 0), list_p);
+			send_sig_info(SIGKILL,
+				      (void*)(long)(priv != 0), list_p);
+			printk(KERN_INFO
+			       "safefork: Sending process %i"
+			       "SIGTERM and SIGKILL\n",
+			       list_p->pid );
+		}
+	}
+	read_unlock(&tasklist_lock);
+}
+	
+/*
+ * If I am master parent, then all my children become zombies
+ */
+void sf_mark_children(struct task_struct *tsk)
+{
+	struct task_struct *list_p;        
+
+	/* Am I master? */
+	if (tsk->sf_parent!=tsk->pid)
+		return;
+
+	/* loop through the tasks */
+	write_lock_irq(&tasklist_lock);
+	for_each_task(list_p) {
+		if (list_p->sf_parent==tsk->pid && list_p->pid!=tsk->pid)
+		{
+			/* turn children to zombies */
+			list_p->sf_zombie=1;
+			/* make children master */
+			list_p->sf_killchildren=tsk->sf_killchildren;
+			list_p->sf_parent=list_p->pid;
+		}
+	}
+	write_unlock_irq(&tasklist_lock);
+}
+
+/* end safefork */
+#endif
+
 NORET_TYPE void do_exit(long code)
 {
 	struct task_struct *tsk = current;
@@ -445,6 +515,11 @@
 	exit_sighand(tsk);
 	exit_thread();
 
+#ifdef CONFIG_SAFEFORK
+	sf_exit_children(tsk);
+	sf_mark_children(tsk);
+#endif
+	
 	if (current->leader)
 		disassociate_ctty(1);

# do_fork is nearly not changed, I just set one flag 
diff -u -r -N linux/kernel/fork.c linux-safefork/kernel/fork.c
--- linux/kernel/fork.c	Thu Apr 26 15:11:17 2001
+++ linux-safefork/kernel/fork.c	Sun Aug 26 17:29:31 2001
@@ -11,6 +11,13 @@
  * management can be a bitch. See 'mm/memory.c': 'copy_page_tables()'
  */
 
+/*
+ * Changes:
+ * Christian Engwer  :  added SafeFork support
+ *                      little changes to do_fork()
+ *                      <christi@uni-hd.de>
+ */
+
 #include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -601,6 +608,12 @@
 	copy_flags(clone_flags, p);
 	p->pid = get_pid(clone_flags);
 
+#ifdef CONFIG_SAFEFORK
+	/* set safefork flags */
+	p->sf_killchildren=0; // this flag must be set by the user
+	/* end safefork */
+#endif
+	
 	p->run_list.next = NULL;
 	p->run_list.prev = NULL;
 

             reply	other threads:[~2001-08-27 11:47 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-08-27 11:47 Christian Engwer [this message]
2001-08-27 13:42 ` Daniel Phillips

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=20010827134715.A21058@mathphys.fsk.uni-heidelberg.de \
    --to=christi@fsmath.zbt.uni-heidelberg.de \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®