From: Badari Pulavarty Here is the patch to add exit-notifier to the current connector infrastructure in -mm tree. Its directly derived from Guillaume's fork notifier. Signed-off-by: Andrew Morton --- drivers/connector/Kconfig | 10 ++ drivers/connector/Makefile | 1 drivers/connector/cn_exit.c | 166 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/cn_exit.h | 65 +++++++++++++++++ include/linux/connector.h | 3 kernel/exit.c | 1 6 files changed, 246 insertions(+) diff -puN /dev/null drivers/connector/cn_exit.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/drivers/connector/cn_exit.c 2005-06-30 22:24:18.000000000 -0700 @@ -0,0 +1,166 @@ +/* + * cn_exit.c - Exit connector + * + * Copyright (C) 2005 IBM Corporation + * Author: Badari Pulavarty + * + * derived from connector/cn_fork.c - Copyright (C) 2005 BULL SA. + * + * This module implements the exit connector. It allows to send a + * netlink datagram, when enabled, from the do_exit() routine. The + * message can be read by a user space application. By this way, + * the user space application is alerted when a exit occurs. + * + * It uses the userspace <-> kernelspace connector that works on top of + * the netlink protocol. The exit connector is enabled or disabled by + * sending a message to the connector. The unique sequence number of + * messages can be used to check if a message is lost. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include + +#define CN_EXIT_INFO_SIZE sizeof(struct cn_exit_msg) +#define CN_EXIT_MSG_SIZE (sizeof(struct cn_msg) + CN_EXIT_INFO_SIZE) + +static int cn_exit_enable = 0; +struct cb_id cb_exit_id = { CN_IDX_EXIT, CN_VAL_EXIT }; + +/* exit_counts is used as the sequence number of the netlink message */ +static DEFINE_PER_CPU(unsigned long, exit_counts); + +/** + * exit_connector - send information about exit through a connector + * @pid: Process ID + * @ptid: Process thread ID + * @code: Process exit code + * + * It sends information to a user space application through the + * connector when a new process is created. + */ +void exit_connector(pid_t pid, pid_t ptid, long code) +{ + if (cn_exit_enable) { + struct cn_msg *msg; + struct cn_exit_msg *exitmsg; + __u8 buffer[CN_EXIT_MSG_SIZE]; + + msg = (struct cn_msg *)buffer; + + memcpy(&msg->id, &cb_exit_id, sizeof(msg->id)); + + msg->ack = 0; /* not used */ + msg->seq = get_cpu_var(exit_counts)++; + + msg->len = CN_EXIT_INFO_SIZE; + exitmsg = (struct cn_exit_msg *)msg->data; + exitmsg->type = EXIT_CN_MSG_P; + exitmsg->cpu = smp_processor_id(); + exitmsg->u.s.pid = pid; + exitmsg->u.s.ptid = ptid; + exitmsg->u.s.code = code; + + put_cpu_var(exit_counts); + + /* If cn_netlink_send() failed, the data is not send */ + cn_netlink_send(msg, CN_IDX_EXIT, GFP_KERNEL); + } +} + +/** + * cn_exit_send_status - send a message with the status + * + * It sends information about the status of the exit connector + * to a user space application through the connector. The status + * is stored in the global variable "cn_exit_enable". + */ +static inline void cn_exit_send_status(void) +{ + struct cn_msg *msg; + struct cn_exit_msg *exitmsg; + __u8 buffer[CN_EXIT_MSG_SIZE]; + + msg = (struct cn_msg *)buffer; + + memcpy(&msg->id, &cb_exit_id, sizeof(msg->id)); + + msg->ack = 0; /* not used */ + msg->seq = 0; /* not used */ + + msg->len = CN_EXIT_INFO_SIZE; + exitmsg = (struct cn_exit_msg *)msg->data; + exitmsg->type = EXIT_CN_MSG_S; + exitmsg->u.status = cn_exit_enable; + + cn_netlink_send(msg, CN_IDX_EXIT, GFP_KERNEL); +} + +/** + * cn_exit_callback - enable or disable the exit connector + * @data: message send by the connector + * + * The callback allows to enable or disable the sending of information + * about exit in the do_exit() routine. To enable the exit, the user + * space application must send the integer 1 in the data part of the + * message. To disable the exit connector, it must send the integer 0. + */ +static void cn_exit_callback(void *data) +{ + struct cn_msg *msg = data; + int action; + + if (cn_already_initialized && (msg->len == sizeof(cn_exit_enable))) { + memcpy(&action, msg->data, sizeof(cn_exit_enable)); + switch (action) { + case EXIT_CN_START: + cn_exit_enable = 1; + break; + case EXIT_CN_STOP: + cn_exit_enable = 0; + break; + case EXIT_CN_STATUS: + cn_exit_send_status(); + break; + } + } +} + +/** + * cn_exit_init - initialization entry point + * + * This routine will be run at kernel boot time because this driver is + * built in the kernel. It adds the connector callback to the connector + * driver. + */ +int __init cn_exit_init(void) +{ + int err; + + err = cn_add_callback(&cb_exit_id, "cn_exit", &cn_exit_callback); + if (err) { + printk(KERN_WARNING "Failed to register cn_exit\n"); + return -EINVAL; + } + + printk(KERN_NOTICE "cn_exit is registered\n"); + return 0; +} + +__initcall(cn_exit_init); diff -puN drivers/connector/Kconfig~connector-exit-notifier drivers/connector/Kconfig --- devel/drivers/connector/Kconfig~connector-exit-notifier 2005-06-30 22:24:18.000000000 -0700 +++ devel-akpm/drivers/connector/Kconfig 2005-06-30 22:24:18.000000000 -0700 @@ -10,4 +10,14 @@ config CONNECTOR Connector support can also be built as a module. If so, the module will be called cn.ko. +config EXIT_CONNECTOR + bool "Enable exit connector" + select CONNECTOR + default y + ---help--- + It adds a connector in kernel/exit.c:do_exit() function. When a exit + occurs, netlink is used to transfer information about the process and + its parent. This information can be used by a user space application. + The exit connector can be enable/disable by sending a message to the + connector with the corresponding group id. endmenu diff -puN drivers/connector/Makefile~connector-exit-notifier drivers/connector/Makefile --- devel/drivers/connector/Makefile~connector-exit-notifier 2005-06-30 22:24:18.000000000 -0700 +++ devel-akpm/drivers/connector/Makefile 2005-06-30 22:24:18.000000000 -0700 @@ -1,2 +1,3 @@ obj-$(CONFIG_CONNECTOR) += cn.o cn-objs := cn_queue.o connector.o +obj-$(CONFIG_EXIT_CONNECTOR) += cn_exit.o diff -puN /dev/null include/linux/cn_exit.h --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/include/linux/cn_exit.h 2005-06-30 22:24:18.000000000 -0700 @@ -0,0 +1,65 @@ +/* + * cn_exit.h - Exit connector + * + * Copyright (C) 2005 IBM Corporation + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef CN_EXIT_H +#define CN_EXIT_H + +#include +#include + +#define EXIT_CN_STOP 0 +#define EXIT_CN_START 1 +#define EXIT_CN_STATUS 2 + +#define EXIT_CN_MSG_P 0 /* Message about processes */ +#define EXIT_CN_MSG_S 1 /* Message about exit connector's state */ + +/* + * The exit connector sends information to a user-space + * application. From the user's point of view, the process + * ID is the thread group ID and thread ID is the internal + * kernel "pid". So, fields are assigned as follow: + */ +struct cn_exit_msg { + int type; /* 0: information about processes + 1: exit connector's state */ + int cpu; /* ID of the cpu where the exit occurred */ + union { + struct { + pid_t pid; /* process ID */ + pid_t ptid; /* process thread ID */ + pid_t code; /* process exit code */ + } s; + int status; + } u; +}; + +/* Code above is only inside the kernel */ +#ifdef __KERNEL__ +#ifdef CONFIG_EXIT_CONNECTOR +extern void exit_connector(pid_t pid, pid_t ptid, long code); +#else +static inline void exit_connector(pid_t ppid, pid_t ptid, long code) +{ + return; +} +#endif /* CONFIG_EXIT_CONNECTOR */ +#endif /* __KERNEL__ */ +#endif /* CN_EXIT_H */ diff -puN include/linux/connector.h~connector-exit-notifier include/linux/connector.h --- devel/include/linux/connector.h~connector-exit-notifier 2005-06-30 22:24:18.000000000 -0700 +++ devel-akpm/include/linux/connector.h 2005-06-30 22:24:18.000000000 -0700 @@ -27,6 +27,9 @@ #define CN_IDX_CONNECTOR 0xffffffff #define CN_VAL_CONNECTOR 0xffffffff +#define CN_IDX_EXIT 0xfeec /* exit events */ +#define CN_VAL_EXIT 0xceef + /* * Maximum connector's message size. */ diff -puN kernel/exit.c~connector-exit-notifier kernel/exit.c --- devel/kernel/exit.c~connector-exit-notifier 2005-06-30 22:24:18.000000000 -0700 +++ devel-akpm/kernel/exit.c 2005-06-30 22:24:18.000000000 -0700 @@ -795,6 +795,7 @@ fastcall NORET_TYPE void do_exit(long co if (tsk->io_context) exit_io_context(); + exit_connector(tsk->tgid, tsk->pid, code); if (unlikely(current->ptrace & PT_TRACE_EXIT)) { current->ptrace_message = code; ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP); _