aboutsummaryrefslogtreecommitdiff
path: root/sys/compat/linux/linux_util.c
diff options
context:
space:
mode:
authorAlexander Leidinger <netchild@FreeBSD.org>2012-05-05 19:42:38 +0000
committerAlexander Leidinger <netchild@FreeBSD.org>2012-05-05 19:42:38 +0000
commit19e252baebe7a7466b33c27560420b7d95fe294d (patch)
tree2c944ca220ef9f94f80b967133cbd2ab53caa81c /sys/compat/linux/linux_util.c
parent15efbb17a8f66ae91118c2ea564ae71a3689a594 (diff)
- >500 static DTrace probes for the linuxulator
- DTrace scripts to check for errors, performance, ... they serve mostly as examples of what you can do with the static probe;s with moderate load the scripts may be overwhelmed, excessive lock-tracing may influence program behavior (see the last design decission) Design decissions: - use "linuxulator" as the provider for the native bitsize; add the bitsize for the non-native emulation (e.g. "linuxuator32" on amd64) - Add probes only for locks which are acquired in one function and released in another function. Locks which are aquired and released in the same function should be easy to pair in the code, inter-function locking is more easy to verify in DTrace. - Probes for locks should be fired after locking and before releasing to prevent races (to provide data/function stability in DTrace, see the man-page of "dtrace -v ..." and the corresponding DTrace docs).
Notes
Notes: svn path=/head/; revision=235063
Diffstat (limited to 'sys/compat/linux/linux_util.c')
-rw-r--r--sys/compat/linux/linux_util.c122
1 files changed, 106 insertions, 16 deletions
diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c
index 3c26f88d6983..76c210c591fe 100644
--- a/sys/compat/linux/linux_util.c
+++ b/sys/compat/linux/linux_util.c
@@ -33,16 +33,19 @@
__FBSDID("$FreeBSD$");
#include "opt_compat.h"
+#include "opt_kdtrace.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/fcntl.h>
#include <sys/lock.h>
#include <sys/malloc.h>
+#include <sys/kernel.h>
#include <sys/linker_set.h>
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/proc.h>
+#include <sys/sdt.h>
#include <sys/syscallsubr.h>
#include <sys/systm.h>
#include <sys/vnode.h>
@@ -56,8 +59,42 @@ __FBSDID("$FreeBSD$");
#include <machine/../linux/linux.h>
#endif
+#include <compat/linux/linux_dtrace.h>
+
const char linux_emul_path[] = "/compat/linux";
+/* DTrace init */
+LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
+
+/**
+ * DTrace probes in this module.
+ */
+LIN_SDT_PROBE_DEFINE5(util, linux_emul_convpath, entry, "const char *",
+ "enum uio_seg", "char **", "int", "int");
+LIN_SDT_PROBE_DEFINE1(util, linux_emul_convpath, return, "int");
+LIN_SDT_PROBE_DEFINE1(util, linux_msg, entry, "const char *");
+LIN_SDT_PROBE_DEFINE0(util, linux_msg, return);
+LIN_SDT_PROBE_DEFINE2(util, linux_driver_get_name_dev, entry, "device_t",
+ "const char *");
+LIN_SDT_PROBE_DEFINE0(util, linux_driver_get_name_dev, nullcall);
+LIN_SDT_PROBE_DEFINE1(util, linux_driver_get_name_dev, return, "char *");
+LIN_SDT_PROBE_DEFINE3(util, linux_driver_get_major_minor, entry, "char *",
+ "int *", "int *");
+LIN_SDT_PROBE_DEFINE0(util, linux_driver_get_major_minor, nullcall);
+LIN_SDT_PROBE_DEFINE1(util, linux_driver_get_major_minor, notfound, "char *");
+LIN_SDT_PROBE_DEFINE3(util, linux_driver_get_major_minor, return, "int",
+ "int", "int");
+LIN_SDT_PROBE_DEFINE0(util, linux_get_char_devices, entry);
+LIN_SDT_PROBE_DEFINE1(util, linux_get_char_devices, return, "char *");
+LIN_SDT_PROBE_DEFINE1(util, linux_free_get_char_devices, entry, "char *");
+LIN_SDT_PROBE_DEFINE0(util, linux_free_get_char_devices, return);
+LIN_SDT_PROBE_DEFINE1(util, linux_device_register_handler, entry,
+ "struct linux_device_handler *");
+LIN_SDT_PROBE_DEFINE1(util, linux_device_register_handler, return, "int");
+LIN_SDT_PROBE_DEFINE1(util, linux_device_unregister_handler, entry,
+ "struct linux_device_handler *");
+LIN_SDT_PROBE_DEFINE1(util, linux_device_unregister_handler, return, "int");
+
/*
* Search an alternate path before passing pathname arguments on to
* system calls. Useful for keeping a separate 'emulation tree'.
@@ -66,17 +103,19 @@ const char linux_emul_path[] = "/compat/linux";
* named file, i.e. we check if the directory it should be in exists.
*/
int
-linux_emul_convpath(td, path, pathseg, pbuf, cflag, dfd)
- struct thread *td;
- const char *path;
- enum uio_seg pathseg;
- char **pbuf;
- int cflag;
- int dfd;
+linux_emul_convpath(struct thread *td, const char *path, enum uio_seg pathseg,
+ char **pbuf, int cflag, int dfd)
{
+ int retval;
+
+ LIN_SDT_PROBE5(util, linux_emul_convpath, entry, path, pathseg, pbuf,
+ cflag, dfd);
+
+ retval = kern_alternate_path(td, linux_emul_path, path, pathseg, pbuf,
+ cflag, dfd);
- return (kern_alternate_path(td, linux_emul_path, path, pathseg, pbuf,
- cflag, dfd));
+ LIN_SDT_PROBE1(util, linux_emul_convpath, return, retval);
+ return (retval);
}
void
@@ -85,12 +124,16 @@ linux_msg(const struct thread *td, const char *fmt, ...)
va_list ap;
struct proc *p;
+ LIN_SDT_PROBE1(util, linux_msg, entry, fmt);
+
p = td->td_proc;
printf("linux: pid %d (%s): ", (int)p->p_pid, p->p_comm);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
printf("\n");
+
+ LIN_SDT_PROBE0(util, linux_msg, return);
}
struct device_element
@@ -113,13 +156,23 @@ linux_driver_get_name_dev(device_t dev)
struct device_element *de;
const char *device_name = device_get_name(dev);
- if (device_name == NULL)
+ LIN_SDT_PROBE2(util, linux_driver_get_name_dev, entry, dev,
+ device_name);
+
+ if (device_name == NULL) {
+ LIN_SDT_PROBE0(util, linux_driver_get_name_dev, nullcall);
+ LIN_SDT_PROBE1(util, linux_driver_get_name_dev, return, NULL);
return NULL;
+ }
TAILQ_FOREACH(de, &devices, list) {
- if (strcmp(device_name, de->entry.bsd_driver_name) == 0)
+ if (strcmp(device_name, de->entry.bsd_driver_name) == 0) {
+ LIN_SDT_PROBE1(util, linux_driver_get_name_dev, return,
+ de->entry.linux_driver_name);
return (de->entry.linux_driver_name);
+ }
}
+ LIN_SDT_PROBE1(util, linux_driver_get_name_dev, return, NULL);
return NULL;
}
@@ -128,8 +181,15 @@ linux_driver_get_major_minor(const char *node, int *major, int *minor)
{
struct device_element *de;
- if (node == NULL || major == NULL || minor == NULL)
+ LIN_SDT_PROBE3(util, linux_driver_get_major_minor, entry, node, major,
+ minor);
+
+ if (node == NULL || major == NULL || minor == NULL) {
+ LIN_SDT_PROBE0(util, linux_driver_get_major_minor, nullcall);
+ LIN_SDT_PROBE3(util, linux_driver_get_major_minor, return, 1,
+ 0, 0);
return 1;
+ }
if (strlen(node) > strlen("pts/") &&
strncmp(node, "pts/", strlen("pts/")) == 0) {
@@ -143,6 +203,9 @@ linux_driver_get_major_minor(const char *node, int *major, int *minor)
devno = strtoul(node + strlen("pts/"), NULL, 10);
*major = 136 + (devno / 256);
*minor = devno % 256;
+
+ LIN_SDT_PROBE3(util, linux_driver_get_major_minor, return, 0,
+ *major, *minor);
return 0;
}
@@ -150,10 +213,15 @@ linux_driver_get_major_minor(const char *node, int *major, int *minor)
if (strcmp(node, de->entry.bsd_device_name) == 0) {
*major = de->entry.linux_major;
*minor = de->entry.linux_minor;
+
+ LIN_SDT_PROBE3(util, linux_driver_get_major_minor,
+ return, 0, *major, *minor);
return 0;
}
}
+ LIN_SDT_PROBE1(util, linux_driver_get_major_minor, notfound, node);
+ LIN_SDT_PROBE3(util, linux_driver_get_major_minor, return, 1, 0, 0);
return 1;
}
@@ -165,6 +233,8 @@ linux_get_char_devices()
char formated[256];
int current_size = 0, string_size = 1024;
+ LIN_SDT_PROBE0(util, linux_get_char_devices, entry);
+
string = malloc(string_size, M_LINUX, M_WAITOK);
string[0] = '\000';
last = "";
@@ -191,13 +261,19 @@ linux_get_char_devices()
}
}
+ LIN_SDT_PROBE1(util, linux_get_char_devices, return, string);
return string;
}
void
linux_free_get_char_devices(char *string)
{
+
+ LIN_SDT_PROBE1(util, linux_get_char_devices, entry, string);
+
free(string, M_LINUX);
+
+ LIN_SDT_PROBE0(util, linux_get_char_devices, return);
}
static int linux_major_starting = 200;
@@ -207,11 +283,15 @@ linux_device_register_handler(struct linux_device_handler *d)
{
struct device_element *de;
- if (d == NULL)
+ LIN_SDT_PROBE1(util, linux_device_register_handler, entry, d);
+
+ if (d == NULL) {
+ LIN_SDT_PROBE1(util, linux_device_register_handler, return,
+ EINVAL);
return (EINVAL);
+ }
- de = malloc(sizeof(*de),
- M_LINUX, M_WAITOK);
+ de = malloc(sizeof(*de), M_LINUX, M_WAITOK);
if (d->linux_major < 0) {
d->linux_major = linux_major_starting++;
}
@@ -220,6 +300,7 @@ linux_device_register_handler(struct linux_device_handler *d)
/* Add the element to the list, sorted on span. */
TAILQ_INSERT_TAIL(&devices, de, list);
+ LIN_SDT_PROBE1(util, linux_device_register_handler, return, 0);
return (0);
}
@@ -228,16 +309,25 @@ linux_device_unregister_handler(struct linux_device_handler *d)
{
struct device_element *de;
- if (d == NULL)
+ LIN_SDT_PROBE1(util, linux_device_unregister_handler, entry, d);
+
+ if (d == NULL) {
+ LIN_SDT_PROBE1(util, linux_device_unregister_handler, return,
+ EINVAL);
return (EINVAL);
+ }
TAILQ_FOREACH(de, &devices, list) {
if (bcmp(d, &de->entry, sizeof(*d)) == 0) {
TAILQ_REMOVE(&devices, de, list);
free(de, M_LINUX);
+
+ LIN_SDT_PROBE1(util, linux_device_unregister_handler,
+ return, 0);
return (0);
}
}
+ LIN_SDT_PROBE1(util, linux_device_unregister_handler, return, EINVAL);
return (EINVAL);
}