Skip to contentSkip to conversation

Process Notification / pnotify

PATCH In review Erik Jacobson 4 participants 8 messages Oct 3, 2005 – Oct 4, 2005

Subsystems (7)
Documentation VFS MM core Scheduler +3 more subsystems
lore
Share & tools
lore
#0 lore raw

PATCH 1/3 Process Notification / pnotify

Here is a new patch for Process Notification (pnotify). This patch is derived from PAGG. We've changed the name to better reflect its purpose and changed the functions and structure names to make it easier to understand.

The pnotify patch allows kernel module authors to associate data with tasks and receive notification about certain stages in the life of a task through callbacks.

After applying the patch, please see Documentation/pnotify.txt for more details and examples.

I implemented feedback received from lse-tech and the pagg mailing list and this patch is the result.

We have received positive feedback from multiple sources about this patch. This patch, in its PAGG form, also has received exposure on ia64 by being part of SLES9.

We're hoping this patch will be considered for mm inclusion and eventually make it in to the kernel.

There will be two more postings showing two pnotify users:
Linux Job and keyrings. keyrings is a proof of concept patch showing how one might change an existing kernel component to use pnotify. Job is the inescapable job container implementation.

I'm hoping we can move beyond this being seen as only a tool for accounting and consider its broader applications.

This was discussed in lse-tech recently. Unfortunately, the threads got a bit broken up in the archives but the major pieces are:

main thread:
http://marc.theaimsgroup.com/?l=lse-tech&m=112733871706425&w=2

Performance data, 2p system:
http://marc.theaimsgroup.com/?l=lse-tech&m=112801353626865&w=2

Performance data, 32p system:
http://marc.theaimsgroup.com/?l=lse-tech&m=112810597609896&w=2

In addition, there has been activity on the PAGG mailing list about pnotify. Find the list archives here:
http://oss.sgi.com/archives/pagg/

Note: In lse-tech, I was asked to implement pnotify using RCU protections instead of semaphore read locks. I did this in a proof of concecpt patch but I feel RCU is too restrictive for the kernel module users in terms of sleep and, as I showed in the performance data, it doesn't buy us anything in terms of performance.

Signed-off-by Erik Jacobson <erikj.sgi.com>

---

 Documentation/pnotify.txt |  368 +++++++++++++++++++++++++++++
 fs/exec.c                 |    2
 include/linux/init_task.h |    2
 include/linux/pnotify.h   |  227 ++++++++++++++++++
 include/linux/sched.h     |    5
 init/Kconfig              |    8
 kernel/Makefile           |    1
 kernel/exit.c             |    4
 kernel/fork.c             |   17 +
 kernel/pnotify.c          |  568 ++++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 1201 insertions(+), 1 deletion(-)
fs/exec.c +2 -0
Index: linux/fs/exec.c
===================================================================
@@ -48,6 +48,7 @@
 #include <linux/syscalls.h>
 #include <linux/rmap.h>
 #include <linux/acct.h>
+#include <linux/pnotify.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -1203,6 +1204,7 @@
 	retval = search_binary_handler(bprm,regs);
 	if (retval >= 0) {
 		free_arg_pages(bprm);
+		pnotify_exec(current);
 
 		/* execve success */
 		security_bprm_free(bprm);
include/linux/init_task.h +2 -0
Index: linux/include/linux/init_task.h
===================================================================
@@ -2,6 +2,7 @@
 #define _LINUX__INIT_TASK_H
 
 #include <linux/file.h>
+#include <linux/pnotify.h>
 #include <linux/rcupdate.h>
 
 #define INIT_FDTABLE \
@@ -121,6 +122,7 @@
 	.proc_lock	= SPIN_LOCK_UNLOCKED,				\
 	.journal_info	= NULL,						\
 	.cpu_timers	= INIT_CPU_TIMERS(tsk.cpu_timers),		\
+	INIT_TASK_PNOTIFY(tsk)						\
 	.fs_excl	= ATOMIC_INIT(0),				\
 }
 
include/linux/sched.h +5 -0
Index: linux/include/linux/sched.h
===================================================================
@@ -795,6 +795,11 @@
   	struct mempolicy *mempolicy;
 	short il_next;
 #endif
+#ifdef CONFIG_PNOTIFY
+/* List of pnotify kernel module subscribers */
+	struct list_head pnotify_subscriber_list;
+	struct rw_semaphore pnotify_subscriber_list_sem;
+#endif
 #ifdef CONFIG_CPUSETS
 	struct cpuset *cpuset;
 	nodemask_t mems_allowed;
init/Kconfig +8 -0
Index: linux/init/Kconfig
===================================================================
@@ -162,6 +162,14 @@
 	  for processing it. A preliminary version of these tools is available
 	  at <http://www.physik3.uni-rostock.de/tim/kernel/utils/acct/>.
 
+config PNOTIFY
+	bool "Support for Process Notification"
+	help
+     Say Y here if you will be loading modules which provide support
+     for process notification.  Examples of such modules include the
+     Linux Jobs module and the Linux Array Sessions module.  If you will not
+     be using such modules, say N.
+
 config SYSCTL
 	bool "Sysctl support"
 	---help---
kernel/Makefile +1 -0
Index: linux/kernel/Makefile
===================================================================
@@ -20,6 +20,7 @@
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_PNOTIFY) += pnotify.o
 obj-$(CONFIG_CPUSETS) += cpuset.o
 obj-$(CONFIG_IKCONFIG) += configs.o
 obj-$(CONFIG_IKCONFIG_PROC) += configs.o
kernel/fork.c +16 -1
Index: linux/kernel/fork.c
===================================================================
@@ -42,6 +42,7 @@
 #include <linux/profile.h>
 #include <linux/rmap.h>
 #include <linux/acct.h>
+#include <linux/pnotify.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -151,6 +152,9 @@
 	init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
 	init_task.signal->rlim[RLIMIT_SIGPENDING] =
 		init_task.signal->rlim[RLIMIT_NPROC];
+
+	/* Initialize the pnotify list in pid 0 before it can clone itself. */
+	INIT_PNOTIFY_LIST(current);
 }
 
 static struct task_struct *dup_task_struct(struct task_struct *orig)
@@ -1039,6 +1043,15 @@
 	p->exit_state = 0;
 
 	/*
+	 * Call pnotify kernel module subscribers and add the same subscribers the
+	 * parent has to the new process.
+	 * Fail the fork on error.
+	 */
+	retval = pnotify_fork(p, current);
+	if (retval)
+ 		goto bad_fork_cleanup_namespace;
+
+	/*
 	 * Ok, make it visible to the rest of the system.
 	 * We dont wake it up yet.
 	 */
@@ -1073,7 +1086,7 @@
 	if (sigismember(&current->pending.signal, SIGKILL)) {
 		write_unlock_irq(&tasklist_lock);
 		retval = -EINTR;
-		goto bad_fork_cleanup_namespace;
+		goto bad_fork_cleanup_pnotify;
 	}
 
 	/* CLONE_PARENT re-uses the old parent */
@@ -1159,6 +1172,8 @@
 		return ERR_PTR(retval);
 	return p;
 
+bad_fork_cleanup_pnotify:
+	pnotify_exit(p);
 bad_fork_cleanup_namespace:
 	exit_namespace(p);
 bad_fork_cleanup_keys:
kernel/exit.c +4 -0
Index: linux/kernel/exit.c
===================================================================
@@ -29,6 +29,7 @@
 #include <linux/proc_fs.h>
 #include <linux/mempolicy.h>
 #include <linux/cpuset.h>
+#include <linux/pnotify.h>
 #include <linux/syscalls.h>
 #include <linux/signal.h>
 
@@ -866,6 +867,9 @@
 		module_put(tsk->binfmt->module);
 
 	tsk->exit_code = code;
+
+	pnotify_exit(tsk);
+
 	exit_notify(tsk);
 #ifdef CONFIG_NUMA
 	mpol_free(tsk->mempolicy);
kernel/pnotify.c new file +568 -0

568 lines not on this page · raw message

include/linux/pnotify.h new file +227 -0

227 lines not on this page · raw message

Documentation/pnotify.txt new file +368 -0

368 lines not on this page · raw message

#1 lore raw

PATCH 2/3 Process Notification / pnotify user: keyrings

Here is an example implementation showing keyrings using pnotify as a proof of concecpt. Not all the callouts that keyrings needs are currently implemented in pnotify (but most could be if desired).

---

 include/linux/key.h          |   21 +++++
 include/linux/sched.h        |    4 -
 kernel/exit.c                |    1
 kernel/fork.c                |    6 -
 security/keys/key.c          |   22 ++++++
 security/keys/keyctl.c       |   28 ++++++-
 security/keys/process_keys.c |  152 ++++++++++++++++++++++++++++++++++++-------
 security/keys/request_key.c  |   31 +++++++-
 8 files changed, 222 insertions(+), 43 deletions(-)
include/linux/key.h +19 -2
Index: linux/include/linux/key.h
===================================================================
@@ -19,6 +19,7 @@
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include <linux/rcupdate.h>
+#include <linux/pnotify.h>
 #include <asm/atomic.h>
 
 #ifdef __KERNEL__
@@ -262,9 +263,9 @@
 extern struct key root_user_keyring, root_session_keyring;
 extern int alloc_uid_keyring(struct user_struct *user);
 extern void switch_uid_keyring(struct user_struct *new_user);
-extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk);
+extern int copy_keys(struct task_struct *tsk, struct pnotify_subscriber *sub, void *olddata);
 extern int copy_thread_group_keys(struct task_struct *tsk);
-extern void exit_keys(struct task_struct *tsk);
+extern void exit_keys(struct task_struct *task, struct pnotify_subscriber *sub);
 extern void exit_thread_group_keys(struct signal_struct *tg);
 extern int suid_keys(struct task_struct *tsk);
 extern int exec_keys(struct task_struct *tsk);
@@ -279,6 +280,22 @@
 	old_session;						\
 })
 
+/* pnotify subscriber service request */
+static struct pnotify_events key_events = {
+	.module = NULL,
+	.name = "key",
+	.data = NULL,
+	.entry = LIST_HEAD_INIT(key_events.entry),
+	.fork = copy_keys,
+	.exit = exit_keys,
+};
+
+/* key info associated with the task struct and managed by pnotify */
+struct key_task {
+	struct key *thread_keyring; /* keyring private to this thread */
+	unsigned char jit_keyring; /* default keyring to attach requested keys to */
+};
+
 #else /* CONFIG_KEYS */
 
 #define key_validate(k)			0
kernel/exit.c +0 -1
Index: linux/kernel/exit.c
===================================================================
@@ -857,7 +857,6 @@
 	exit_namespace(tsk);
 	exit_thread();
 	cpuset_exit(tsk);
-	exit_keys(tsk);
 
 	if (group_dead && tsk->signal->leader)
 		disassociate_ctty(1);
kernel/fork.c +1 -5
Index: linux/kernel/fork.c
===================================================================
@@ -1009,10 +1009,8 @@
 		goto bad_fork_cleanup_sighand;
 	if ((retval = copy_mm(clone_flags, p)))
 		goto bad_fork_cleanup_signal;
-	if ((retval = copy_keys(clone_flags, p)))
-		goto bad_fork_cleanup_mm;
 	if ((retval = copy_namespace(clone_flags, p)))
-		goto bad_fork_cleanup_keys;
+		goto bad_fork_cleanup_mm;
 	retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
 	if (retval)
 		goto bad_fork_cleanup_namespace;
@@ -1175,8 +1173,6 @@
 bad_fork_cleanup_namespace:
 	pnotify_exit(p);
 	exit_namespace(p);
-bad_fork_cleanup_keys:
-	exit_keys(p);
 bad_fork_cleanup_mm:
 	if (p->mm)
 		mmput(p->mm);
security/keys/key.c +22 -0
Index: linux/security/keys/key.c
===================================================================
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/err.h>
+#include <linux/pnotify.h>
 #include "internal.h"
 
 static kmem_cache_t	*key_jar;
@@ -1009,6 +1010,9 @@
  */
 void __init key_init(void)
 {
+	struct key_task *kt;
+	struct pnotify_subscriber *sub;
+
 	/* allocate a slab in which we can store keys */
 	key_jar = kmem_cache_create("key_jar", sizeof(struct key),
 			0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
@@ -1039,4 +1043,22 @@
 	/* link the two root keyrings together */
 	key_link(&root_session_keyring, &root_user_keyring);
 
+	/* Allocate memory for task assocated key_task structure */
+	kt = (struct key_task *)kmalloc(sizeof(struct key_task),GFP_KERNEL);
+	if (!kt) {
+		printk(KERN_ERR "Insufficient memory to allocate key_task structure"
+		  " in key_init function.\n");
+		return;
+   }
+	kt->thread_keyring = NULL;
+
+	/* subscribe this kernel entity to the subscriber list for current task */
+	sub = pnotify_subscribe(current, &key_events);
+	if (!sub) {
+		printk(KERN_ERR "Insufficient memory to add to subscriber list structure"
+		  " in key_init function.\n");
+	}
+	/* Associate the kt structure with this task via pnotify subscriber */
+	sub->data = (void *)kt;
+
 } /* end key_init() */
security/keys/process_keys.c +128 -24

259 lines not on this page · raw message

include/linux/sched.h +0 -4
Index: linux/include/linux/sched.h
===================================================================
@@ -718,10 +718,6 @@
 	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
 	unsigned keep_capabilities:1;
 	struct user_struct *user;
-#ifdef CONFIG_KEYS
-	struct key *thread_keyring;	/* keyring private to this thread */
-	unsigned char jit_keyring;	/* default keyring to attach requested keys to */
-#endif
 	int oomkilladj; /* OOM kill score adjustment (bit shift). */
 	char comm[TASK_COMM_LEN]; /* executable name excluding path
 				     - access with [gs]et_task_comm (which lock
security/keys/keyctl.c +24 -4
Index: linux/security/keys/keyctl.c
===================================================================
@@ -931,31 +931,51 @@
 long keyctl_set_reqkey_keyring(int reqkey_defl)
 {
 	int ret;
+	unsigned char jit_return;
+	struct pnotify_subscriber *sub;
+	struct key_task *kt;
+
+	down_write(&current->pnotify_subscriber_list_sem);
+	sub = pnotify_get_subscriber(current, key_events.name);
+	if (sub == NULL || sub->data == NULL) { /* shouldn't happen */
+		printk(KERN_ERR "keyctl_set_reqkey_keyring pnotify subscriber or data ptr null, task: %d\n", current->pid);
+		up_write(&current->pnotify_subscriber_list_sem);
+		return -EFAULT;
+	}
+	kt = (struct key_task *)sub->data;
 
 	switch (reqkey_defl) {
 	case KEY_REQKEY_DEFL_THREAD_KEYRING:
 		ret = install_thread_keyring(current);
-		if (ret < 0)
+		if (ret < 0) {
+			up_write(&current->pnotify_subscriber_list_sem);
 			return ret;
+		}
 		goto set;
 
 	case KEY_REQKEY_DEFL_PROCESS_KEYRING:
 		ret = install_process_keyring(current);
-		if (ret < 0)
+		if (ret < 0) {
+			up_write(&current->pnotify_subscriber_list_sem);
 			return ret;
+		}
 
 	case KEY_REQKEY_DEFL_DEFAULT:
 	case KEY_REQKEY_DEFL_SESSION_KEYRING:
 	case KEY_REQKEY_DEFL_USER_KEYRING:
 	case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
 	set:
-		current->jit_keyring = reqkey_defl;
+
+		kt->jit_keyring = reqkey_defl;
 
 	case KEY_REQKEY_DEFL_NO_CHANGE:
-		return current->jit_keyring;
+		jit_return = kt->jit_keyring;
+		up_write(&current->pnotify_subscriber_list_sem);
+		return jit_return;
 
 	case KEY_REQKEY_DEFL_GROUP_KEYRING:
 	default:
+		up_write(&current->pnotify_subscriber_list_sem);
 		return -EINVAL;
 	}
 
security/keys/request_key.c +28 -3
Index: linux/security/keys/request_key.c
===================================================================
@@ -14,6 +14,7 @@
 #include <linux/kmod.h>
 #include <linux/err.h>
 #include <linux/keyctl.h>
+#include <linux/pnotify.h>
 #include "internal.h"
 
 struct key_construction {
@@ -39,6 +40,17 @@
 	char *argv[10], *envp[3], uid_str[12], gid_str[12];
 	char key_str[12], keyring_str[3][12];
 	int ret, i;
+	struct pnotify_subscriber *sub;
+	struct key_task *kt;
+
+	down_write(&tsk->pnotify_subscriber_list_sem);
+	sub = pnotify_get_subscriber(current, key_events.name);
+	if (sub == NULL || sub->data == NULL) { /* shouldn't happen */
+		printk(KERN_ERR "call_request_key pnotify subscriber or data ptr null, task: %d\n", tsk->pid);
+		up_write(&tsk->pnotify_subscriber_list_sem);
+		return -EFAULT;
+	}
+	kt = (struct key_task *)sub->data;
 
 	kenter("{%d},%s,%s", key->serial, op, callout_info);
 
@@ -58,7 +70,7 @@
 
 	/* we specify the process's default keyrings */
 	sprintf(keyring_str[0], "%d",
-		tsk->thread_keyring ? tsk->thread_keyring->serial : 0);
+		kt->thread_keyring ? kt->thread_keyring->serial : 0);
 
 	prkey = 0;
 	if (tsk->signal->process_keyring)
@@ -105,6 +117,7 @@
 	key_put(session_keyring);
 
  error:
+	up_write(&tsk->pnotify_subscriber_list_sem);
 	kleave(" = %d", ret);
 	return ret;
 
@@ -300,15 +313,26 @@
 {
 	struct task_struct *tsk = current;
 	struct key *drop = NULL;
+	struct pnotify_subscriber *sub;
+	struct key_task *kt;
+
+	down_write(&tsk->pnotify_subscriber_list_sem);
+	sub = pnotify_get_subscriber(current, key_events.name);
+	if (sub == NULL || sub->data == NULL) { /* shouldn't happen */
+		printk(KERN_ERR "request_key_link pnotify subscriber or data ptr null, task: %d\n", tsk->pid);
+		up_write(&tsk->pnotify_subscriber_list_sem);
+		return;
+	}
+	kt = (struct key_task *)sub->data;
 
 	kenter("{%d},%p", key->serial, dest_keyring);
 
 	/* find the appropriate keyring */
 	if (!dest_keyring) {
-		switch (tsk->jit_keyring) {
+		switch (kt->jit_keyring) {
 		case KEY_REQKEY_DEFL_DEFAULT:
 		case KEY_REQKEY_DEFL_THREAD_KEYRING:
-			dest_keyring = tsk->thread_keyring;
+			dest_keyring = kt->thread_keyring;
 			if (dest_keyring)
 				break;
 
@@ -347,6 +371,7 @@
 	key_put(drop);
 
 	kleave("");
+	down_write(&tsk->pnotify_subscriber_list_sem);
 
 } /* end request_key_link() */
 
#2 lore raw

PATCH 3/3 Process Notification / pnotify user: Job

Here is the Linux job implementation. It provides inescapable job containers built on top of pnotify.

More information can be found in Documentation/job.txt and
http://oss.sgi.com/projects/pagg/

Note: In the past, the community suggested using a virtual filesystem interface to userland and moving much of the logic to user space. We implemented and posted this, but we have found it to suffer greatly in performance in certain situations. For that reason, I'm posting the stable non-jobfs version here because it works better. We're open to more discussion in the jobfs version if people have ideas on how to make it faster. In particular, we ran in to performance problems when there was rapid process firing and the site administrator did something that required a job operation for most tasks. We'd end up spending lots of time doing inode operations in the virtual filesystem. This patch doesn't suffer from that problem.

---
 Documentation/job.txt    |  104 ++
 include/linux/job_acct.h |  124 +++
 include/linux/jobctl.h   |  185 ++++
 init/Kconfig             |   29
 kernel/Makefile          |    1
 kernel/fork.c            |    1
 kernel/job.c             | 1871 +++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 2315 insertions(+)
Documentation/job.txt new file +104 -0
Index: linux/Documentation/job.txt
===================================================================
@@ -0,0 +1,104 @@
+Linux Jobs - A Process Notification (pnotify) Module
+----------------------------------------------------
+
+1. Overview
+
+This document provides two additional sections.  Section 2 provides a
+listing of the manual page that describes the particulars of the Linux
+job implementation.  Section 3 provides some information about using
+the user job library to interface to jobs.
+
+2. Job Man Page
+
+
+JOB(7)		       Linux User's Manual		   JOB(7)
+
+
+NAME
+       job - Linux Jobs kernel module overview
+
+DESCRIPTION
+       A job is a group of related processes all descended from a
+       point of entry process and  identified  by  a  unique  job
+       identifier  (jid).   A  job  can	 contain multiple process
+       groups or sessions, and all processes in one of these sub-
+       groups can only be contained within a single job.
+
+       The  primary  purpose  for  having  jobs is to provide job
+       based resource limits.  The  current  implementation  only
+       provides	 the  job  container  and resource limits will be
+       provided in a later implementation.  When  an  implementa-
+       tion  that provides job limits is available, this descrip-
+       tion will be expanded to provide	 further  explanation  of
+       job based limits.
+
+       Not  every  process  on the system is part of a job.  That
+       is, only processes which are started by a login	initiator
+       like  login, rlogin, rsh and so on, get assigned a job ID.
+       In the Linux environment, jobs are created via a PAM  mod-
+       ule.
+
+       Jobs on Linux are provided using a loadable kernel module.
+       Linux jobs have the following characteristics:
+
+       o   A job is an inescapable container.  A  process  cannot
+	   leave the job nor can a new process be created outside
+	   the job without explicit action,  that  is,	a  system
+	   call with root privilege.
+
+       o   Each	 new  process  inherits	 the jid and limits [when
+	   implemented] from its parent process.
+
+       o   All point of entry processes (job initiators) create a
+	   new	job  and  set  the  job limits [when implemented]
+	   appropriately.
+
+       o   Job initiation on Linux is performed via a PAM session
+	   module.
+
+       o   The job initiator performs authentication and security
+	   checks.
+
+       o   Users can raise and lower their own job limits  within
+	   maximum  values  specified by the system administrator
+	   [when implemented].
+
+       o   Not all processes on a system need be members of a job.
+
+       o   The	process control initialization process (init(1M))
+	   and startup scripts called by init are not part  of	a
+	   job.
+
+
+       Job initiators can be categorized as either interactive or
+       batch processes.	 Limit domain names are	 defined  by  the
+       system  administrator when the user limits database (ULDB)
+       is created.  [The ULDB will be implemented in  conjunction
+       with future job limits work.]
+
+       Note: The existing command jobs(1) applies to shell "jobs"
+       and it is not related to the  Linux  Kernel  Module  jobs.
+       The  at(1),  atd(8),  atq(1), batch(1), atrun(8), atrm(1))
+       man pages refer to  shell  scripts  as  a  job.	 a  shell
+       script.
+
+SEE ALSO
+       job(1), jwait(1), jstat(1), jkill(1)
+
+
+
+
+
+
+
+
+
+3. User Job Library
+
+For developers who wish to make software using Linux Jobs, there exists
+a user job library.  This library contains functions for obtaining information
+about running jobs, creating jobs, detaching, etc.
+
+The library is part of the job package and can be obtained from oss.sgi.com
+using anonymous ftp.  Look in the /projects/pagg/download directory.  See the
+README in the job source package for more information.
init/Kconfig +29 -0
Index: linux/init/Kconfig
===================================================================
@@ -170,6 +170,35 @@
      Linux Jobs module and the Linux Array Sessions module.  If you will not
      be using such modules, say N.
 
+config JOB
+	tristate "  Process Notification (pnotify) based jobs"
+	depends on PNOTIFY
+	help
+	  The Job feature implements a type of process aggregate,
+	  or grouping.  A job is the collection of all processes that
+	  are descended from a point-of-entry process.  Examples of such
+	  points-of-entry include telnet, rlogin, and console logins.
+
+	  Batch schedulers such as LSF also make use of Job for containing,
+	  maintaining, and signaling a job as one entity.
+
+	  A job differs from a session and process group since the job
+	  container (or group) is inescapable.  Only root level processes,
+	  or those with the CAP_SYS_RESOURCE capability, can create new jobs
+	  or escape from a job.
+
+	  A job is identified by a unique job identifier (jid).  Currently,
+	  that jid can be used to obtain status information about the job
+	  and the processes it contians.  The jid can also be used to send
+	  signals to all processes contained in the job.  In addition,
+	  other processes can wait for the completion of a job - the event
+	  where the last process contained in the job has exited.
+
+	  If you want to compile support for jobs into the kernel, select
+	  this entry using Y.  If you want the support for jobs provided as
+	  a module, select this entry using M.  If you do not want support
+	  for jobs, select N.
+
 config SYSCTL
 	bool "Sysctl support"
 	---help---
kernel/job.c new file +1871 -0

1,871 lines not on this page · raw message

kernel/Makefile +1 -0
Index: linux/kernel/Makefile
===================================================================
@@ -21,6 +21,7 @@
 obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_COMPAT) += compat.o
 obj-$(CONFIG_PNOTIFY) += pnotify.o
+obj-$(CONFIG_JOB) += job.o
 obj-$(CONFIG_CPUSETS) += cpuset.o
 obj-$(CONFIG_IKCONFIG) += configs.o
 obj-$(CONFIG_IKCONFIG_PROC) += configs.o
include/linux/jobctl.h new file +185 -0

185 lines not on this page · raw message

include/linux/job_acct.h new file +124 -0

124 lines not on this page · raw message

kernel/fork.c +1 -0
Index: linux/kernel/fork.c
===================================================================
@@ -122,6 +122,7 @@
 	if (!profile_handoff_task(tsk))
 		free_task(tsk);
 }
+EXPORT_SYMBOL_GPL(__put_task_struct);
 
 void __init fork_init(unsigned long mempages)
 {
#3 lore raw

Re: [PATCH 3/3] Process Notification / pnotify user: Job

init/Kconfig line 174

Quoted 10 lines · Erik Jacobson

Index: linux/init/Kconfig
===================================================================

init/Kconfig +2 -0
@@ -170,6 +170,35 @@
      Linux Jobs module and the Linux Array Sessions module.  If you will not
      be using such modules, say N.
 
+config JOB
+	tristate "  Process Notification (pnotify) based jobs"

Should it be possible to compile job as a module, or should this not be "tristate"?

It makes use of send_group_sig_info, which is not EXPORTed.

thanks,
-serge

#4 lore raw

Re: [PATCH 3/3] Process Notification / pnotify user: Job

Quoted 4 lines

Should it be possible to compile job as a module, or should this not be "tristate"?

It makes use of send_group_sig_info, which is not EXPORTed.

You are right, the patch is supposed to export that variable as well. I must have forgot to add it to the file list using quilt before sending it out, and I tested it as built-in so I didn't catch it.

I'll fix this. Thank you.

We're only using send_group_sig_info because it does a check for signal 'zero' which means status check. send_sig_info doesn't do that check any more. We could probably just handle this inside job some how and use send_sig_info instead.

--
Erik Jacobson - Linux System Software - Silicon Graphics - Eagan, Minnesota

#5 lore raw

Re: [PATCH 3/3] Process Notification / pnotify user: Job

In reply to [email protected]
Quoted 2 lines

Should it be possible to compile job as a module, or should this not be "tristate"?

So I added this to the patch. I tested it as a kernel module. Sorry this was missed in the patch I sent out.

kernel/signal.c +1 -0
Index: linux/kernel/signal.c
===================================================================
@@ -1978,6 +1978,7 @@
 EXPORT_SYMBOL(ptrace_notify);
 EXPORT_SYMBOL(send_sig);
 EXPORT_SYMBOL(send_sig_info);
+EXPORT_SYMBOL(send_group_sig_info);
 EXPORT_SYMBOL(sigprocmask);
 EXPORT_SYMBOL(block_all_signals);
 EXPORT_SYMBOL(unblock_all_signals);
#6 lore raw
In reply to Erik Jacobson

Hmmm ... I notice with interest two notification patches posted in the last few days to lkml:

Matthew Helsley's Process Events Connector (posted 28 Sep 2005) Erik Jacobson's pnotify (posted 3 Oct 2005)

I suspect Matthew and Erik will both instantly hate me for asking, but does it make sense to integrate these two?

If I understand these two proposals correctly:

Helsley adds hooks in fork, exec, id change, and exit, to pass events to userspace.

Jacobson adds hooks in fork, exec and exit, to pass events to kernel routines and loadable modules.

Perhaps, just brainstorming here, it would make sense for Halsley to register with pnotify instead of adding his own hooks in parallel. This presumes that pnotify is accepted into the kernel, and that pnotify adds the id change hook that Helsley requires.

Signature · 3 lines
                  I won't rest till it's the best ...
                  Programmer, Linux Scalability
                  Paul Jackson <[email protected]> 1.925.600.0401
#7 lore raw
Quoted 14 lines · Paul Jackson

Hmmm ... I notice with interest two notification patches posted in the last few days to lkml:

Matthew Helsley's Process Events Connector (posted 28 Sep 2005) Erik Jacobson's pnotify (posted 3 Oct 2005)

I suspect Matthew and Erik will both instantly hate me for asking, but does it make sense to integrate these two?

If I understand these two proposals correctly:

Helsley adds hooks in fork, exec, id change, and exit, to pass events to userspace.

Quoted 7 lines

Jacobson adds hooks in fork, exec and exit, to pass events to kernel routines and loadable modules.

Perhaps, just brainstorming here, it would make sense for Halsley to register with pnotify instead of adding his own hooks in parallel. This presumes that pnotify is accepted into the kernel, and that pnotify adds the id change hook that Helsley requires.

Paul,

pnotify is extreme overkill for the process events connector. The
per-task subscriber lists, data, inheritance of those lists, tasklist locking, and iteration over the lists are all overhead compared to the process events connector patch.

For the process events connector it makes more sense to have a global
list of subscribers interested all tasks. If there are M kernel modules interested in getting events for all N tasks this would save space proportional to M*N compared to pnotify. Of course this means the elements of this list could not have per-task data.

I think per-task data should be split out from pnotify and submitted as
a separate system used by pnotify. Maybe with a *_PER_TASK API similar to *_PER_CPU.

Cheers,
-Matt Helsley