lttng-modules v0.19-stable: setup_trace_write: Fix recursive locking
[lttng-modules.git] / ltt-userspace-event.c
CommitLineData
1c8284eb
MD
1/*
2 * Copyright (C) 2008 Mathieu Desnoyers
3 *
4 * Dual LGPL v2.1/GPL v2 license.
5 */
6
7#include <linux/module.h>
8#include <linux/marker.h>
9#include <linux/uaccess.h>
10#include <linux/gfp.h>
11#include <linux/fs.h>
12#include <linux/debugfs.h>
13#include <linux/slab.h>
14
15#include "ltt-type-serializer.h"
16
17#define LTT_WRITE_EVENT_FILE "write_event"
18
19DEFINE_MARKER(userspace, event, "string %s");
20static struct dentry *ltt_event_file;
21
22/**
23 * write_event - write a userspace string into the trace system
24 * @file: file pointer
25 * @user_buf: user string
26 * @count: length to copy, including the final NULL
27 * @ppos: unused
28 *
29 * Copy a string into a trace event, in channel "userspace", event "event".
30 * Copies until either \n or \0 is reached.
31 * On success, returns the number of bytes copied from the source, including the
32 * \n or \0 character (if there was one in the count range). It cannot return
33 * more than count.
34 * Inspired from tracing_mark_write implementation from Steven Rostedt and
35 * Ingo Molnar.
36 */
37static
38ssize_t write_event(struct file *file, const char __user *user_buf,
39 size_t count, loff_t *ppos)
40{
41 struct marker *marker;
42 char *buf, *end;
43 long copycount;
44 ssize_t ret;
45
46 buf = kmalloc(count + 1, GFP_KERNEL);
47 if (!buf) {
48 ret = -ENOMEM;
49 goto string_out;
50 }
51 copycount = strncpy_from_user(buf, user_buf, count);
52 if (copycount < 0) {
53 ret = -EFAULT;
54 goto string_err;
55 }
56 /* Cut from the first nil or newline. */
57 buf[copycount] = '\0';
58 end = strchr(buf, '\n');
59 if (end) {
60 *end = '\0';
61 copycount = end - buf;
62 }
63 /* Add final \0 to copycount */
64 copycount++;
65 marker = &GET_MARKER(userspace, event);
66 ltt_specialized_trace(marker, marker->single.probe_private, buf,
67 copycount, sizeof(char));
68 /* If there is no \0 nor \n in count, do not return a larger value */
69 ret = min_t(size_t, copycount, count);
70string_err:
71 kfree(buf);
72string_out:
73 return ret;
74}
75
76static const struct file_operations ltt_userspace_operations = {
77 .write = write_event,
78};
79
80static int __init ltt_userspace_init(void)
81{
82 struct dentry *ltt_root_dentry;
83 int err = 0;
84
85 ltt_root_dentry = get_ltt_root();
86 if (!ltt_root_dentry) {
87 err = -ENOENT;
88 goto err_no_root;
89 }
90
91 ltt_event_file = debugfs_create_file(LTT_WRITE_EVENT_FILE,
92 S_IWUGO,
93 ltt_root_dentry,
94 NULL,
95 &ltt_userspace_operations);
96 if (IS_ERR(ltt_event_file) || !ltt_event_file) {
97 printk(KERN_ERR
98 "ltt_userspace_init: failed to create file %s\n",
99 LTT_WRITE_EVENT_FILE);
100 err = -EPERM;
101 goto err_no_file;
102 }
103
104 return err;
105err_no_file:
106 put_ltt_root();
107err_no_root:
108 return err;
109}
110
111static void __exit ltt_userspace_exit(void)
112{
113 debugfs_remove(ltt_event_file);
114 put_ltt_root();
115}
116
117module_init(ltt_userspace_init);
118module_exit(ltt_userspace_exit);
119
120MODULE_LICENSE("GPL and additional rights");
121MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>");
122MODULE_DESCRIPTION("Linux Trace Toolkit Userspace Event");
This page took 0.027009 seconds and 4 git commands to generate.