ChangeLog:

  - Remove the global cn_fork_lock and replace it by a per CPU 
    counter. 
  - The processor ID has been added in the data part of the message.
    Thus datas sent in a message are: "CPU_ID PARENT_PID CHILD_PID"

  Those modifications were done to be more scalable because, as
mentioned by Jesse Barnes, the global cn_fork_lock won't work well on a
large CPU system.

  This patch applies to 2.6.11-mm4.

Regards,
Guillaume

---

 drivers/connector/Kconfig   |   11 +++++
 drivers/connector/Makefile  |    1
 drivers/connector/cn_fork.c |   85 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/connector.h   |    4 ++
 kernel/fork.c               |   44 ++++++++++++++++++++++
 5 files changed, 145 insertions(+)


Index: linux-2.6.11-mm4-cnfork/drivers/connector/Kconfig
===================================================================
--- linux-2.6.11-mm4-cnfork.orig/drivers/connector/Kconfig      2005-03-16 
14:21:46.000000000 +0100
+++ linux-2.6.11-mm4-cnfork/drivers/connector/Kconfig   2005-03-16 
14:34:41.000000000 +0100
@@ -10,4 +10,15 @@
          Connector support can also be built as a module.  If so, the module
          will be called cn.ko.
 
+config FORK_CONNECTOR
+       bool "Enable fork connector"
+       depends on CONNECTOR=y
+       default y
+       ---help---
+         It adds a connector in kernel/fork.c:do_fork() function. When a fork
+         occurs, netlink is used to transfer information about the parent and 
+         its child. This information can be used by a user space application.
+         The fork connector can be enable/disable by sending a message to the
+         connector with the corresponding group id.
+         
 endmenu
Index: linux-2.6.11-mm4-cnfork/drivers/connector/Makefile
===================================================================
--- linux-2.6.11-mm4-cnfork.orig/drivers/connector/Makefile     2005-03-16 
14:21:46.000000000 +0100
+++ linux-2.6.11-mm4-cnfork/drivers/connector/Makefile  2005-03-16 
14:34:41.000000000 +0100
@@ -1,2 +1,3 @@
 obj-$(CONFIG_CONNECTOR)                += cn.o
+obj-$(CONFIG_FORK_CONNECTOR)   += cn_fork.o 
 cn-objs                := cn_queue.o connector.o
Index: linux-2.6.11-mm4-cnfork/drivers/connector/cn_fork.c
===================================================================
--- linux-2.6.11-mm4-cnfork.orig/drivers/connector/cn_fork.c    2003-01-30 
11:24:37.000000000 +0100
+++ linux-2.6.11-mm4-cnfork/drivers/connector/cn_fork.c 2005-03-16 
14:34:41.000000000 +0100
@@ -0,0 +1,85 @@
+/*
+ *     cn_fork.c
+ * 
+ * 2005 Copyright (c) Guillaume Thouvenin <[EMAIL PROTECTED]>
+ * All rights reserved.
+ * 
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <linux/connector.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Guillaume Thouvenin <[EMAIL PROTECTED]>");
+MODULE_DESCRIPTION("Enable or disable the usage of the fork connector");
+
+int cn_fork_enable = 0;
+struct cb_id cb_fork_id = { CN_IDX_FORK, CN_VAL_FORK };
+
+/**
+ * cn_fork_callback - enable or disable the fork connector
+ * @data: message send by the connector 
+ *
+ * The callback allows to enable or disable the sending of information
+ * about fork in the do_fork() routine. To enable the fork, the user 
+ * space application must send the integer 1 in the data part of the 
+ * message. To disable the fork connector, it must send the integer 0.
+ */
+static void cn_fork_callback(void *data) 
+{
+       struct cn_msg *msg = (struct cn_msg *)data;
+
+       if (cn_already_initialized && (msg->len == sizeof(cn_fork_enable)))
+               memcpy(&cn_fork_enable, msg->data, sizeof(cn_fork_enable));
+}
+
+/**
+ * cn_fork_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.
+ */
+static int cn_fork_init(void)
+{
+       int err;
+       
+       err = cn_add_callback(&cb_fork_id, "cn_fork", &cn_fork_callback);
+       if (err) {
+               printk(KERN_WARNING "Failed to register cn_fork\n");
+               return -EINVAL;
+       }       
+               
+       printk(KERN_NOTICE "cn_fork is registered\n");
+       return 0;
+}
+
+/**
+ * cn_fork_exit - exit entry point
+ *
+ * As this driver is always statically compiled into the kernel the
+ * cn_fork_exit has no effect.
+ */
+static void cn_fork_exit(void)
+{
+       cn_del_callback(&cb_fork_id);
+}
+
+module_init(cn_fork_init);
+module_exit(cn_fork_exit);
Index: linux-2.6.11-mm4-cnfork/include/linux/connector.h
===================================================================
--- linux-2.6.11-mm4-cnfork.orig/include/linux/connector.h      2005-03-16 
14:21:49.000000000 +0100
+++ linux-2.6.11-mm4-cnfork/include/linux/connector.h   2005-03-16 
14:34:41.000000000 +0100
@@ -28,6 +28,8 @@
 #define CN_VAL_KOBJECT_UEVENT          0x0000
 #define CN_IDX_SUPERIO                 0xaabb  /* SuperIO subsystem */
 #define CN_VAL_SUPERIO                 0xccdd
+#define CN_IDX_FORK                    0xfeed  /* fork events */
+#define CN_VAL_FORK                    0xbeef
 
 
 #define CONNECTOR_MAX_MSG_SIZE         1024
@@ -133,6 +135,8 @@
 };
 
 extern int cn_already_initialized;
+extern int cn_fork_enable;
+extern struct cb_id cb_fork_id;
 
 int cn_add_callback(struct cb_id *, char *, void (* callback)(void *));
 void cn_del_callback(struct cb_id *);
Index: linux-2.6.11-mm4-cnfork/kernel/fork.c
===================================================================
--- linux-2.6.11-mm4-cnfork.orig/kernel/fork.c  2005-03-16 14:21:49.000000000 
+0100
+++ linux-2.6.11-mm4-cnfork/kernel/fork.c       2005-03-21 13:13:25.000000000 
+0100
@@ -41,6 +41,7 @@
 #include <linux/profile.h>
 #include <linux/rmap.h>
 #include <linux/acct.h>
+#include <linux/connector.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -63,6 +64,47 @@
 
 EXPORT_SYMBOL(tasklist_lock);
 
+#ifdef CONFIG_FORK_CONNECTOR
+
+#define CN_FORK_INFO_SIZE      64
+#define CN_FORK_MSG_SIZE       (sizeof(struct cn_msg) + CN_FORK_INFO_SIZE)
+
+static DEFINE_PER_CPU(unsigned long, fork_counts);
+
+static inline void fork_connector(pid_t parent, pid_t child)
+{
+       if (cn_fork_enable) {
+               struct cn_msg *msg;
+               __u8 buffer[CN_FORK_MSG_SIZE];  
+
+               msg = (struct cn_msg *)buffer;
+                       
+               memcpy(&msg->id, &cb_fork_id, sizeof(msg->id));
+               
+               msg->ack = 0; /* not used */
+               msg->seq = get_cpu_var(fork_counts)++;
+               
+               /* 
+                * size of data is the number of characters 
+                * printed plus one for the trailing '\0'
+                */
+               memset(msg->data, '\0', CN_FORK_INFO_SIZE);
+               msg->len = scnprintf(msg->data, CN_FORK_INFO_SIZE-1, 
+                                   "%i %i %i", 
+                                   smp_processor_id(), parent, child) + 1;
+               
+               put_cpu_var(fork_counts);
+
+               cn_netlink_send(msg, CN_IDX_FORK);
+       }
+}
+#else
+static inline void fork_connector(pid_t parent, pid_t child) 
+{
+       return; 
+}
+#endif /* CONFIG_FORK_CONNECTOR */
+
 int nr_processes(void)
 {
        int cpu;
@@ -1253,6 +1295,8 @@
                        if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE))
                                ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | 
SIGTRAP);
                }
+               
+               fork_connector(current->pid, p->pid);
        } else {
                free_pidmap(pid);
                pid = PTR_ERR(p);


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

Reply via email to