This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug runtime/3857] Flight Recorder on Memory


------- Additional Comments From masami dot hiramatsu dot pt at hitachi dot com  2007-01-23 06:00 -------
Subject: Re:  Flight Recorder on Memory

Hi,

fche at redhat dot com wrote:
> ------- Additional Comments From fche at redhat dot com  2007-01-22 20:12 -------
> Yes, we've been looking for an approach to this problem for some time.
> 
> (In reply to comment #1)
>> Created an attachment (id=1486)
 --> (http://sourceware.org/bugzilla/attachment.cgi?id=1486&action=view)
>  --> (http://sourceware.org/bugzilla/attachment.cgi?id=1486&action=view)
>> flight-recorder in kernel memory
> 
> I'm sorry, the attachment appears to be unreadable.
> Could you reattach it in plain ASCII, or just post it
> to the mailing list?

OK, I attach it to this mail.

Thanks,

transport-prevent_double_init_relay.patch 
transport-support_flightrecorder.patch
staprun-add_launch_only.patch 
staprun-add_attach_module.patch
staprun-add_detach_module.patch
---
 runtime/stpd/librelay.c |   58 +++++++++++++++++++++++++-----------------------
 runtime/stpd/stpd.c     |   14 +++++++++--
 2 files changed, 43 insertions(+), 29 deletions(-)

 This patch adds -A option to the staprun for supporting "attach
 to the module" feature. If you run the staprun with -A option,
 it opens the control interface of the specified module, and sends
 STP_TRANSPORT_INFO and STP_START for getting transport information
 and starting data transporting.

Index: systemtap/runtime/stpd/librelay.c
===================================================================
--- systemtap.orig/runtime/stpd/librelay.c
+++ systemtap/runtime/stpd/librelay.c
@@ -50,6 +50,7 @@ static struct params
 	unsigned subbuf_size;
 	unsigned n_subbufs;
 	int merge;
+	int pid;
 	char relay_filebase[256];
 } params;
 
@@ -81,7 +82,7 @@ static pthread_t reader[NR_CPUS];
 int control_channel;
 
 /* flags */
-extern int print_only, quiet, verbose, launch_only;
+extern int print_only, quiet, verbose, launch_only, attach_mod;
 extern unsigned int buffer_size;
 extern char *modname;
 extern char *modpath;
@@ -394,11 +395,11 @@ int init_relayfs(void)
 	}
 
 	if (statfs("/mnt/relay", &st) == 0 && (int) st.f_type == (int) RELAYFS_MAGIC)
- 		sprintf(params.relay_filebase, "/mnt/relay/systemtap/%d/cpu", getpid());
+ 		sprintf(params.relay_filebase, "/mnt/relay/systemtap/%d/cpu", params.pid);
  	else if (statfs("/sys/kernel/debug", &st) == 0 && (int) st.f_type == (int) DEBUGFS_MAGIC)
- 		sprintf(params.relay_filebase, "/sys/kernel/debug/systemtap/%d/cpu", getpid());
+ 		sprintf(params.relay_filebase, "/sys/kernel/debug/systemtap/%d/cpu", params.pid);
  	else
- 		sprintf(params.relay_filebase, "/debug/systemtap/%d/cpu", getpid());
+ 		sprintf(params.relay_filebase, "/debug/systemtap/%d/cpu", params.pid);
 	
 	for (i = 0; i < ncpus; i++) {
 		if (open_relayfs_files(i, params.relay_filebase) < 0) {
@@ -494,29 +495,31 @@ int init_stp(int print_summary)
 	ncpus = sysconf(_SC_NPROCESSORS_ONLN);
 	print_totals = print_summary;
 
-	/* insert module */
-	sprintf(buf, "_stp_pid=%d", (int)getpid());
-        modoptions[0] = "insmod";
-        modoptions[1] = modpath;
-        modoptions[2] = buf;
-        /* modoptions[3...N] set by command line parser. */
-
-	if ((pid = fork()) < 0) {
-		perror ("fork");
-		exit(-1);
-	} else if (pid == 0) {
-		if (execvp("/sbin/insmod",  modoptions) < 0)
+	if (!attach_mod) {
+		/* insert module */
+		sprintf(buf, "_stp_pid=%d", (int)getpid());
+		modoptions[0] = "insmod";
+		modoptions[1] = modpath;
+		modoptions[2] = buf;
+		/* modoptions[3...N] set by command line parser. */
+
+		if ((pid = fork()) < 0) {
+			perror ("fork");
+			exit(-1);
+		} else if (pid == 0) {
+			if (execvp("/sbin/insmod",  modoptions) < 0)
 			_exit(-1);
+		}
+		if (waitpid(pid, &rstatus, 0) < 0) {
+			perror("waitpid");
+			exit(-1);
+		}
+		if (WIFEXITED(rstatus) && WEXITSTATUS(rstatus)) {
+			fprintf(stderr, "ERROR, couldn't insmod probe module %s\n", modpath);
+			return -1;
+		}
 	}
-	if (waitpid(pid, &rstatus, 0) < 0) {
-		perror("waitpid");
-		exit(-1);
-	}
-	if (WIFEXITED(rstatus) && WEXITSTATUS(rstatus)) {
-		fprintf(stderr, "ERROR, couldn't insmod probe module %s\n", modpath);
-		return -1;
-	}
-	
+
 	sprintf (proc_filebase, "/proc/systemtap/%s", modname);
 	char *ptr = index(proc_filebase,'.');
 	if (ptr)
@@ -550,7 +553,7 @@ int init_stp(int print_summary)
 
  do_rmmod:
 	snprintf(buf, sizeof(buf), "/sbin/rmmod -w %s", modname);
-	if (system(buf))
+	if (!attach_mod && system(buf))
 		fprintf(stderr, "ERROR: couldn't rmmod probe module %s.\n", modname);
 	return -1;
 }
@@ -749,7 +752,7 @@ int stp_main_loop(void)
 		type = *(int *)recvbuf;
 		data = (void *)(recvbuf + sizeof(int));
 
-		if (!transport_mode && type != STP_TRANSPORT_INFO && type != STP_EXIT) {
+		if (!transport_mode && type != STP_TRANSPORT_INFO && type != STP_EXIT && !attach_mod) {
 			fprintf(stderr, "WARNING: invalid stp command: no transport\n");
 			continue;
 		}
@@ -796,6 +799,7 @@ int stp_main_loop(void)
 			params.subbuf_size = info->subbuf_size;
 			params.n_subbufs = info->n_subbufs;
 			params.merge = info->merge;
+			params.pid = info->pid;
 			if (launch_only) goto out;
 #ifdef DEBUG
 			if (transport_mode == STP_TRANSPORT_RELAYFS) {
Index: systemtap/runtime/stpd/stpd.c
===================================================================
--- systemtap.orig/runtime/stpd/stpd.c
+++ systemtap/runtime/stpd/stpd.c
@@ -33,6 +33,7 @@ int verbose = 0;
 int target_pid = 0;
 int driver_pid = 0;
 int launch_only = 0;
+int attach_mod = 0;
 unsigned int buffer_size = 0;
 char *modname = NULL;
 char *modpath = NULL;
@@ -46,11 +47,12 @@ gid_t cmd_gid;
 
 static void usage(char *prog)
 {
-	fprintf(stderr, "\n%s [-m] [-p] [-q] [-r] [-L] [-c cmd ] [-t pid]\n"
+	fprintf(stderr, "\n%s [-m] [-p] [-q] [-r] [-L] [-A] [-c cmd ] [-t pid]\n"
                 "\t[-b bufsize] [-o FILE] kmod-name [kmod-options]\n", prog);
 	fprintf(stderr, "-p  Print only.  Don't log to files.\n");
 	fprintf(stderr, "-q  Quiet. Don't display trace to stdout.\n");
 	fprintf(stderr, "-L  Launch only. Just after launching the module, detach from it.\n");
+	fprintf(stderr, "-A  Attach to the launched module. \n");
 	fprintf(stderr, "-c cmd.  Command \'cmd\' will be run and staprun will exit when it does.\n");
 	fprintf(stderr, "   _stp_target will contain the pid for the command.\n");
 	fprintf(stderr, "-t pid.  Sets _stp_target to pid.\n");
@@ -68,7 +70,7 @@ int main(int argc, char **argv)
 {
 	int c;
 	
-	while ((c = getopt(argc, argv, "mpqrLb:n:t:d:c:vo:u:")) != EOF)
+	while ((c = getopt(argc, argv, "mpqrLAb:n:t:d:c:vo:u:")) != EOF)
 	{
 		switch (c) {
 		case 'm':
@@ -116,6 +118,9 @@ int main(int argc, char **argv)
 		case 'L':
 			launch_only = 1;
 			break;
+		case 'A':
+			attach_mod = 1;
+			break;
 		default:
 			usage(argv[0]);
 		}
@@ -152,6 +157,11 @@ int main(int argc, char **argv)
 		usage(argv[0]);
 	}
 
+	if (attach_mod && launch_only) {
+		fprintf (stderr, "Cannot do \"-A\" and \"-L\" both.\n");
+		usage(argv[0]);
+	}
+
 	if (print_only && quiet) {
 		fprintf (stderr, "Cannot do \"-p\" and \"-q\" both.\n");
 		usage(argv[0]);
---
 runtime/stpd/librelay.c       |   20 +++++++++++++++-----
 runtime/stpd/stpd.c           |   14 ++++++++++++--
 runtime/transport/transport.c |    2 ++
 3 files changed, 29 insertions(+), 7 deletions(-)

 This patch adds -D option to the staprun for supporting "Detach 
 from module" feature. This option can be used with -A (attach)
 option. If you run the staprun with both -D and -A options, it
 exits after reading all data in the data message queue.

Index: systemtap/runtime/stpd/librelay.c
===================================================================
--- systemtap.orig/runtime/stpd/librelay.c
+++ systemtap/runtime/stpd/librelay.c
@@ -32,7 +32,7 @@
 #include <linux/limits.h>
 #include <sys/wait.h>
 #include <sys/statfs.h>
-
+#include <limits.h>
 
 /* stp_check script */
 #ifdef PKGLIBDIR
@@ -71,6 +71,7 @@ static int transport_mode;
 static int ncpus;
 static int print_totals;
 static int exiting;
+static int nr_buffers = INT_MAX;
 
 /* per-cpu data */
 static int relay_file[NR_CPUS];
@@ -82,7 +83,7 @@ static pthread_t reader[NR_CPUS];
 int control_channel;
 
 /* flags */
-extern int print_only, quiet, verbose, launch_only, attach_mod;
+extern int print_only, quiet, verbose, launch_only, attach_mod, detach_soon;
 extern unsigned int buffer_size;
 extern char *modname;
 extern char *modpath;
@@ -332,7 +333,7 @@ static void *reader_thread(void *data)
 	pollfd.events = POLLIN;
 
 	do {
-		rc = poll(&pollfd, 1, -1);
+		rc = poll(&pollfd, 1, detach_soon ? 0 : -1);
 		if (rc < 0) {
 			if (errno != EINTR) {
 				fprintf(stderr, "ERROR: poll error: %s\n",
@@ -356,7 +357,7 @@ static void *reader_thread(void *data)
 			if (write (proc_file[cpu], &consumed_info, sizeof(struct _stp_consumed_info)) < 0)
 				fprintf(stderr,"WARNING: writing consumed info failed.\n");
 		}
-		if (status[cpu].info.flushing)
+		if (status[cpu].info.flushing || detach_soon)
 			pthread_exit(NULL);
 	} while (1);
 }
@@ -543,7 +544,7 @@ int init_stp(int print_summary)
 	ti.n_subbufs = 0;
 	ti.target = target_pid;
 	if (send_request(STP_TRANSPORT_INFO, &ti, sizeof(ti)) < 0) {
-		fprintf(stderr, "staprun failed because TRANSPORT_INFO returned an error.\n");
+		fprintf(stderr, "staprun failed because TRANSPORT_INFO returned an error. (%s)\n", strerror(errno));
 		if (target_cmd)
 			kill (target_pid, SIGKILL);
 		close(control_channel);
@@ -728,6 +729,7 @@ int stp_main_loop(void)
 	void *data;
 	int type;
 	FILE *ofp = stdout;
+	int count = 0;
 
 	setvbuf(ofp, (char *)NULL, _IOLBF, 0);
 
@@ -739,15 +741,22 @@ int stp_main_loop(void)
         if (driver_pid)
           driver_poll(0); // And by the way, I'm also the signal handler.
 
+	if (detach_soon)
+		fcntl(control_channel, F_SETFL, O_NONBLOCK|O_RDWR);
+
 	dbug("in main loop\n");
 
 	while (1) { /* handle messages from control channel */
 		nb = read(control_channel, recvbuf, sizeof(recvbuf));
 		if (nb <= 0) {
+			if (errno == EAGAIN && detach_soon)
+				cleanup_and_exit(1);
 			perror("recv");
 			fprintf(stderr, "WARNING: unexpected EOF. nb=%d\n", nb);
 			continue;
 		}
+		if (++count >= nr_buffers && detach_soon)
+			cleanup_and_exit(1);
 
 		type = *(int *)recvbuf;
 		data = (void *)(recvbuf + sizeof(int));
@@ -795,6 +804,7 @@ int stp_main_loop(void)
 		{
 			struct _stp_transport_info *info = (struct _stp_transport_info *)data;
 			struct _stp_transport_start ts;
+			nr_buffers = info->buf_size;
 			transport_mode = info->transport_mode;
 			params.subbuf_size = info->subbuf_size;
 			params.n_subbufs = info->n_subbufs;
Index: systemtap/runtime/stpd/stpd.c
===================================================================
--- systemtap.orig/runtime/stpd/stpd.c
+++ systemtap/runtime/stpd/stpd.c
@@ -34,6 +34,7 @@ int target_pid = 0;
 int driver_pid = 0;
 int launch_only = 0;
 int attach_mod = 0;
+int detach_soon = 0;
 unsigned int buffer_size = 0;
 char *modname = NULL;
 char *modpath = NULL;
@@ -47,12 +48,13 @@ gid_t cmd_gid;
 
 static void usage(char *prog)
 {
-	fprintf(stderr, "\n%s [-m] [-p] [-q] [-r] [-L] [-A] [-c cmd ] [-t pid]\n"
+	fprintf(stderr, "\n%s [-m] [-p] [-q] [-r] [-L] [-A] [-D] [-c cmd ] [-t pid]\n"
                 "\t[-b bufsize] [-o FILE] kmod-name [kmod-options]\n", prog);
 	fprintf(stderr, "-p  Print only.  Don't log to files.\n");
 	fprintf(stderr, "-q  Quiet. Don't display trace to stdout.\n");
 	fprintf(stderr, "-L  Launch only. Just after launching the module, detach from it.\n");
 	fprintf(stderr, "-A  Attach to the launched module. \n");
+	fprintf(stderr, "-D  Detach from the module immediately. Use with -A.\n");
 	fprintf(stderr, "-c cmd.  Command \'cmd\' will be run and staprun will exit when it does.\n");
 	fprintf(stderr, "   _stp_target will contain the pid for the command.\n");
 	fprintf(stderr, "-t pid.  Sets _stp_target to pid.\n");
@@ -70,7 +72,7 @@ int main(int argc, char **argv)
 {
 	int c;
 	
-	while ((c = getopt(argc, argv, "mpqrLAb:n:t:d:c:vo:u:")) != EOF)
+	while ((c = getopt(argc, argv, "mpqrLADb:n:t:d:c:vo:u:")) != EOF)
 	{
 		switch (c) {
 		case 'm':
@@ -121,6 +123,9 @@ int main(int argc, char **argv)
 		case 'A':
 			attach_mod = 1;
 			break;
+		case 'D':
+			detach_soon = 1;
+			break;
 		default:
 			usage(argv[0]);
 		}
@@ -167,6 +172,11 @@ int main(int argc, char **argv)
 		usage(argv[0]);
 	}
 
+	if (detach_soon && !attach_mod) {
+		fprintf (stderr, "Cannot do \"-D\" without \"-A\".\n");
+		usage(argv[0]);
+	}
+
 	if (username) {
 		struct passwd *pw = getpwnam(username);
 		if (!pw) {
Index: systemtap/runtime/transport/transport.c
===================================================================
--- systemtap.orig/runtime/transport/transport.c
+++ systemtap/runtime/transport/transport.c
@@ -314,6 +314,8 @@ int _stp_transport_open(struct _stp_tran
 			_stp_set_buffers(info->buf_size * 1024 * 1024 / STP_BUFFER_SIZE);
 	}
 
+	info->buf_size = _stp_current_buffers;
+
 	/* send reply */
 	return _stp_transport_send (STP_TRANSPORT_INFO, info, sizeof(*info));
 }
---
 runtime/stpd/librelay.c |    6 +++++-
 runtime/stpd/stpd.c     |    9 +++++++--
 2 files changed, 12 insertions(+), 3 deletions(-)

 This patch adds -L option to the staprun for supporting "launch
 module" feature. If you run the staprun with -L option, it loads
 a compiled module, initializes the transport, sends symbols and
 module information, and exit. 

Index: systemtap/runtime/stpd/librelay.c
===================================================================
--- systemtap.orig/runtime/stpd/librelay.c
+++ systemtap/runtime/stpd/librelay.c
@@ -81,7 +81,7 @@ static pthread_t reader[NR_CPUS];
 int control_channel;
 
 /* flags */
-extern int print_only, quiet, verbose;
+extern int print_only, quiet, verbose, launch_only;
 extern unsigned int buffer_size;
 extern char *modname;
 extern char *modpath;
@@ -778,6 +778,8 @@ int stp_main_loop(void)
 				cleanup_and_exit(0);
 			} else if (target_cmd)
 				kill (target_pid, SIGUSR1);
+			if (launch_only)
+				cleanup_and_exit(1);
 			break;
 		}
 		case STP_SYSTEM:
@@ -794,6 +796,7 @@ int stp_main_loop(void)
 			params.subbuf_size = info->subbuf_size;
 			params.n_subbufs = info->n_subbufs;
 			params.merge = info->merge;
+			if (launch_only) goto out;
 #ifdef DEBUG
 			if (transport_mode == STP_TRANSPORT_RELAYFS) {
 				fprintf(stderr,"TRANSPORT_INFO recvd: RELAYFS %d bufs of %d bytes.\n", 
@@ -819,6 +822,7 @@ int stp_main_loop(void)
 					cleanup_and_exit(0);
 				}
 			}
+ out:
 			ts.pid = getpid();
 			send_request(STP_START, &ts, sizeof(ts));
 			break;
Index: systemtap/runtime/stpd/stpd.c
===================================================================
--- systemtap.orig/runtime/stpd/stpd.c
+++ systemtap/runtime/stpd/stpd.c
@@ -32,6 +32,7 @@ int quiet = 0;
 int verbose = 0;
 int target_pid = 0;
 int driver_pid = 0;
+int launch_only = 0;
 unsigned int buffer_size = 0;
 char *modname = NULL;
 char *modpath = NULL;
@@ -45,10 +46,11 @@ gid_t cmd_gid;
 
 static void usage(char *prog)
 {
-	fprintf(stderr, "\n%s [-m] [-p] [-q] [-r] [-c cmd ] [-t pid]\n"
+	fprintf(stderr, "\n%s [-m] [-p] [-q] [-r] [-L] [-c cmd ] [-t pid]\n"
                 "\t[-b bufsize] [-o FILE] kmod-name [kmod-options]\n", prog);
 	fprintf(stderr, "-p  Print only.  Don't log to files.\n");
 	fprintf(stderr, "-q  Quiet. Don't display trace to stdout.\n");
+	fprintf(stderr, "-L  Launch only. Just after launching the module, detach from it.\n");
 	fprintf(stderr, "-c cmd.  Command \'cmd\' will be run and staprun will exit when it does.\n");
 	fprintf(stderr, "   _stp_target will contain the pid for the command.\n");
 	fprintf(stderr, "-t pid.  Sets _stp_target to pid.\n");
@@ -66,7 +68,7 @@ int main(int argc, char **argv)
 {
 	int c;
 	
-	while ((c = getopt(argc, argv, "mpqrb:n:t:d:c:vo:u:")) != EOF)
+	while ((c = getopt(argc, argv, "mpqrLb:n:t:d:c:vo:u:")) != EOF)
 	{
 		switch (c) {
 		case 'm':
@@ -111,6 +113,9 @@ int main(int argc, char **argv)
 		case 'u':
 			username = optarg;
 			break;
+		case 'L':
+			launch_only = 1;
+			break;
 		default:
 			usage(argv[0]);
 		}
---
 runtime/transport/transport.c      |   37 ++++++++++++++++++++++---------------
 runtime/transport/transport_msgs.h |    1 +
 2 files changed, 23 insertions(+), 15 deletions(-)

 When the staprun attaches to launched module, it will issue 
 STP_TRANSPORT_INFO and STP_START for getting transport information
 and starting data transporting.
 This patch avoids multiple initialization of the kernel module if
 the staprun sends STP_TRANSPORT_INFO and STP_START again.
 Also, this patch returns pid to tell the interface name of relayfs
 provided by this module.

Index: systemtap/runtime/transport/transport.c
===================================================================
--- systemtap.orig/runtime/transport/transport.c
+++ systemtap/runtime/transport/transport.c
@@ -127,18 +127,23 @@ void _stp_handle_start (struct _stp_tran
 		_stp_transport_send(STP_MODULE, &mod, sizeof(struct _stp_module));
 		return;
 	}
+#endif
 
-	if (register_module_notifier(&_stp_module_load_nb))
-		printk("Systemtap error: failed to load module notifier\n");
+	if (!atomic_read(&_stp_start_finished)) {
+#ifdef CONFIG_MODULES
+		if (register_module_notifier(&_stp_module_load_nb))
+			printk("Systemtap error: failed to load module notifier\n");
 #endif
 
-	/* note: st->pid is actually the return code for the reply packet */
-	st->pid = probe_start();
-	atomic_set(&_stp_start_finished,1);
+		/* note: st->pid is actually the return code for the reply packet */
+		st->pid = probe_start();
+		atomic_set(&_stp_start_finished,1);
 
-	/* if probe_start() failed, suppress calling probe_exit() */
-	if (st->pid < 0)
-		_stp_exit_called = 1;
+		/* if probe_start() failed, suppress calling probe_exit() */
+		if (st->pid < 0)
+			_stp_exit_called = 1;
+	} else
+		st->pid = 0;
 
 	_stp_transport_send(STP_START, st, sizeof(*st));
 }
@@ -279,7 +284,7 @@ int _stp_transport_open(struct _stp_tran
 
 #ifdef STP_RELAYFS
 	if (_stp_transport_mode == STP_TRANSPORT_RELAYFS) {
-		if (info->buf_size) {
+		if (info->buf_size && !_stp_chan) {
 			unsigned size = info->buf_size * 1024 * 1024;
 			subbuf_size = ((size >> 2) + 1) * 65536;
 			n_subbufs = size / subbuf_size;
@@ -290,13 +295,15 @@ int _stp_transport_open(struct _stp_tran
 #ifdef STP_RELAYFS_MERGE
 		info->merge = 1;
 #endif
+		if (!_stp_chan) {
+			_stp_chan = _stp_relayfs_open(n_subbufs, subbuf_size, _stp_pid, &_stp_dir);
 
-		_stp_chan = _stp_relayfs_open(n_subbufs, subbuf_size, _stp_pid, &_stp_dir);
-
-		if (!_stp_chan)
-			return -ENOMEM;
-		kbug ("stp_transport_open: %u Mb buffers, subbuf_size=%u, n_subbufs=%u\n",
-		      info->buf_size, subbuf_size, n_subbufs);
+			if (!_stp_chan)
+				return -ENOMEM;
+			kbug ("stp_transport_open: %u Mb buffers, subbuf_size=%u, n_subbufs=%u\n",
+			      info->buf_size, subbuf_size, n_subbufs);
+		}
+		info->pid = _stp_pid;
 	} else 
 #endif
 	{
Index: systemtap/runtime/transport/transport_msgs.h
===================================================================
--- systemtap.orig/runtime/transport/transport_msgs.h
+++ systemtap/runtime/transport/transport_msgs.h
@@ -43,6 +43,7 @@ struct _stp_transport_info
 	int32_t transport_mode;
 	int32_t merge;		// merge relayfs output?
 	int32_t target;		// target pid
+	int32_t pid;		// launcher pid
 #if 0
 	char cmd[256];		// cmd to process data
 #endif
---
 runtime/transport/procfs.c    |  101 +++++++++++++++++++++++++++++++++++-------
 runtime/transport/relayfs.c   |    2 
 runtime/transport/transport.c |    5 +-
 3 files changed, 90 insertions(+), 18 deletions(-)

 This patch introduces the following features.
 - use subbufs of relayfs cyclically.
 - record the owner process who attaches to this module.
   (If a process has already attached, other processes can't attach.)
 - separate the session message queue from the data message queue.
   (only STP_REALTIME_DATA and STP_SYSTEM are sent to the data message 
   queue)
 - the session queue is cleared when the owner process disconnects.

Index: systemtap/runtime/transport/relayfs.c
===================================================================
--- systemtap.orig/runtime/transport/relayfs.c
+++ systemtap/runtime/transport/relayfs.c
@@ -31,7 +31,7 @@ static int _stp_subbuf_start(struct rcha
 			     size_t prev_padding)
 {
 	if (relay_buf_full(buf))
-		return 0;
+		relay_subbufs_consumed(buf->chan, buf->cpu, 1);
 
 	if (prev_subbuf)
 		*((unsigned *)prev_subbuf) = prev_padding;
Index: systemtap/runtime/transport/procfs.c
===================================================================
--- systemtap.orig/runtime/transport/procfs.c
+++ systemtap/runtime/transport/procfs.c
@@ -13,10 +13,13 @@
 static int _stp_current_buffers = STP_DEFAULT_BUFFERS;
 
 static struct list_head _stp_ready_q;
+static struct list_head _stp_session_q;
 static struct list_head _stp_pool_q;
 spinlock_t _stp_pool_lock = SPIN_LOCK_UNLOCKED;
 spinlock_t _stp_ready_lock = SPIN_LOCK_UNLOCKED;
 
+static pid_t _stp_control_owner = 0;
+
 #ifdef STP_RELAYFS
 extern int _stp_relay_flushing;
 /* handle the per-cpu subbuf info read for relayfs */
@@ -139,7 +142,7 @@ struct _stp_buffer {
 
 static DECLARE_WAIT_QUEUE_HEAD(_stp_proc_wq);
 
-static int _stp_write (int type, void *data, int len)
+static int _stp_write_queue (int type, void *data, int len, struct list_head *queue)
 {
 	struct _stp_buffer *bptr;
 	unsigned long flags;
@@ -154,8 +157,8 @@ static int _stp_write (int type, void *d
 	if (unlikely (numtrylock >= MAXTRYLOCK))
 		return 0;
 
-	if (!list_empty(&_stp_ready_q)) {
-		bptr = (struct _stp_buffer *)_stp_ready_q.prev;
+	if (!list_empty(queue)) {
+		bptr = (struct _stp_buffer *)queue->prev;
 		if (bptr->len + len <= STP_BUFFER_SIZE 
 		    && type == STP_REALTIME_DATA 
 		    && bptr->type == STP_REALTIME_DATA) {
@@ -174,32 +177,55 @@ static int _stp_write (int type, void *d
 	if (unlikely (numtrylock >= MAXTRYLOCK))
 		return 0;
 
-	if (list_empty(&_stp_pool_q)) {
+	if (!list_empty(&_stp_pool_q)) {
+		/* get the next buffer from the pool */
+		bptr = (struct _stp_buffer *)_stp_pool_q.next;
+		list_del_init(&bptr->list);
 		spin_unlock_irqrestore(&_stp_pool_lock, flags);
-		return -1;
+	} else {
+		spin_unlock_irqrestore(&_stp_pool_lock, flags);
+		/* reclaim a message from the ready queue */
+		numtrylock = 0;
+		while (!spin_trylock_irqsave (&_stp_ready_lock, flags) && (++numtrylock < MAXTRYLOCK))
+			ndelay (TRYLOCKDELAY);
+		if (unlikely (numtrylock >= MAXTRYLOCK))
+			return 0;
+		if (!list_empty(&_stp_ready_q)) {
+			bptr = (struct _stp_buffer *)_stp_ready_q.next;
+			list_del_init(&bptr->list);
+			spin_unlock_irqrestore(&_stp_ready_lock, flags);
+		} else {
+			spin_unlock_irqrestore(&_stp_ready_lock, flags);
+			return -1;
+		}
 	}
 
-	/* get the next buffer from the pool */
-	bptr = (struct _stp_buffer *)_stp_pool_q.next;
-	list_del_init(&bptr->list);
-	spin_unlock_irqrestore(&_stp_pool_lock, flags);
-
 	bptr->type = type;
 	memcpy (bptr->buf, data, len);
 	bptr->len = len;
 	
-	/* put it on the pool of ready buffers */
+	/* put it on the specified pool of ready buffers */
 	numtrylock = 0;
 	while (!spin_trylock_irqsave (&_stp_ready_lock, flags) && (++numtrylock < MAXTRYLOCK)) 
 		ndelay (TRYLOCKDELAY);
 	if (unlikely (numtrylock >= MAXTRYLOCK))
 		return 0;
-	list_add_tail(&bptr->list, &_stp_ready_q);
+	list_add_tail(&bptr->list, queue);
 	spin_unlock_irqrestore(&_stp_ready_lock, flags);
 
 	return len;
 }
 
+static int _stp_write (int type, void *data, int len)
+{
+	return _stp_write_queue(type, data, len, &_stp_ready_q);
+}
+
+static int _stp_write_session (int type, void *data, int len)
+{
+	return _stp_write_queue(type, data, len, &_stp_session_q);
+}
+
 static ssize_t
 _stp_proc_read_cmd (struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
@@ -211,17 +237,21 @@ _stp_proc_read_cmd (struct file *file, c
 
 	/* wait for nonempty ready queue */
 	spin_lock_irqsave(&_stp_ready_lock, flags);
-	while (list_empty(&_stp_ready_q)) {
+	while (list_empty(&_stp_ready_q) && list_empty(&_stp_session_q)) {
 		spin_unlock_irqrestore(&_stp_ready_lock, flags);
 		if (file->f_flags & O_NONBLOCK)
 			return -EAGAIN;
-		if (wait_event_interruptible(_stp_proc_wq, !list_empty(&_stp_ready_q)))
+		if (wait_event_interruptible(_stp_proc_wq, (!list_empty(&_stp_ready_q) || !list_empty(&_stp_session_q))))
 			return -ERESTARTSYS;
 		spin_lock_irqsave(&_stp_ready_lock, flags);
 	}
   
-	/* get the next buffer off the ready list */
-	bptr = (struct _stp_buffer *)_stp_ready_q.next;
+	/* get the next buffer off the ready or the session list */
+	if (!list_empty(&_stp_session_q)) {
+		bptr = (struct _stp_buffer *)_stp_session_q.next;
+	} else {
+		bptr = (struct _stp_buffer *)_stp_ready_q.next;
+	}
 	list_del_init(&bptr->list);
 	spin_unlock_irqrestore(&_stp_ready_lock, flags);
 
@@ -243,11 +273,49 @@ _stp_proc_read_cmd (struct file *file, c
 	return len;
 }
 
+static int _stp_proc_open_cmd (struct inode * inode, struct file * file)
+{
+	if (_stp_control_owner != 0)
+		return -EBUSY;
+	_stp_control_owner = current->pid;
+	return 0;
+}
+
+int _stp_proc_close_cmd (struct inode * inode, struct file * file)
+{
+	unsigned long flags;
+	struct _stp_buffer *bptr;
+
+	/* clear messages in the session queue */
+	do {
+		spin_lock_irqsave(&_stp_ready_lock, flags);
+		if (list_empty(&_stp_session_q)) {
+			spin_unlock_irqrestore(&_stp_ready_lock, flags);
+			break;
+		}
+
+		/* get the next buffer off the ready list */
+		bptr = (struct _stp_buffer *)_stp_session_q.next;
+		list_del_init(&bptr->list);
+		spin_unlock_irqrestore(&_stp_ready_lock, flags);
+
+		/* put it on the pool of free buffers */
+		spin_lock_irqsave(&_stp_pool_lock, flags);
+		list_add_tail(&bptr->list, &_stp_pool_q);
+		spin_unlock_irqrestore(&_stp_pool_lock, flags);
+	} while (1);
+
+	_stp_control_owner = 0;
+
+	return 0;
+}
 
 static struct file_operations _stp_proc_fops_cmd = {
 	.owner = THIS_MODULE,
 	.read = _stp_proc_read_cmd,
 	.write = _stp_proc_write_cmd,
+	.open = _stp_proc_open_cmd,
+	.release = _stp_proc_close_cmd,
 //	.poll = _stp_proc_poll_cmd
 };
 
@@ -310,6 +378,7 @@ static int _stp_register_procfs (void)
 	struct list_head *p, *tmp;
 
 	INIT_LIST_HEAD(&_stp_ready_q);
+	INIT_LIST_HEAD(&_stp_session_q);
 	INIT_LIST_HEAD(&_stp_pool_q);
 
 	/* allocate buffers */
Index: systemtap/runtime/transport/transport.c
===================================================================
--- systemtap.orig/runtime/transport/transport.c
+++ systemtap/runtime/transport/transport.c
@@ -61,7 +61,10 @@ int _stp_transport_open(struct _stp_tran
 static int _stp_transport_send (int type, void *data, int len)
 {
 	int err, trylimit = 50;
-	while ((err = _stp_write(type, data, len)) < 0 && trylimit--)
+	struct list_head *q = &_stp_session_q;
+	if (type == STP_REALTIME_DATA || type == STP_SYSTEM)
+		q = &_stp_ready_q;
+	while ((err = _stp_write_queue(type, data, len, q)) < 0 && trylimit--)
 		msleep (5);
 	return err;
 }


-- 


http://sourceware.org/bugzilla/show_bug.cgi?id=3857

------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]