diff options
Diffstat (limited to 'sys/compat/linux/linux_util.c')
-rw-r--r-- | sys/compat/linux/linux_util.c | 122 |
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); } |