lttng-modules v0.19-stable: setup_trace_write: Fix recursive locking
[lttng-modules.git] / ltt-relay-vfs.c
CommitLineData
1c8284eb
MD
1/*
2 * ltt/ltt-relay-vfs.c
3 *
4 * (C) Copyright 2009 - Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca)
5 *
6 * LTTng VFS interface.
7 *
8 * Author:
9 * Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca)
10 *
11 * Dual LGPL v2.1/GPL v2 license.
12 */
13
14#include <linux/module.h>
15#include <linux/fs.h>
16#include <linux/debugfs.h>
17#include <linux/ltt-channels.h>
18#include <asm/atomic.h>
19
20#include "ltt-tracer.h"
21#include "ltt-relay.h"
22#include "ltt-relay-lockless.h"
23
24/**
25 * ltt_open - open file op for ltt files
26 * @inode: opened inode
27 * @file: opened file
28 *
29 * Open implementation. Makes sure only one open instance of a buffer is
30 * done at a given moment.
31 */
32static int ltt_open(struct inode *inode, struct file *file)
33{
34 struct ltt_chanbuf *buf = inode->i_private;
35 int ret;
36
37 ret = ltt_chanbuf_open_read(buf);
38 if (ret)
39 goto end;
40
41 file->private_data = buf;
42 ret = nonseekable_open(inode, file);
43 /*
44 * Let LTTng splice operation must believe that the file descriptor is
45 * seekable. This is a temporary fix to follow new checks added to
46 * splice.c. We should probably do the proper thing and implement a
47 * llseek function eventually, which involves modifying the lttng splice
48 * actors accordingly. TODO
49 */
50 file->f_mode |= FMODE_PREAD;
51end:
52 return ret;
53}
54
55/**
56 * ltt_release - release file op for ltt files
57 * @inode: opened inode
58 * @file: opened file
59 *
60 * Release implementation.
61 */
62static int ltt_release(struct inode *inode, struct file *file)
63{
64 struct ltt_chanbuf *buf = inode->i_private;
65
66 ltt_chanbuf_release_read(buf);
67
68 return 0;
69}
70
71/**
72 * ltt_poll - file op for ltt files
73 * @filp: the file
74 * @wait: poll table
75 *
76 * Poll implementation.
77 */
78static unsigned int ltt_poll(struct file *filp, poll_table *wait)
79{
80 unsigned int mask = 0;
81 struct inode *inode = filp->f_dentry->d_inode;
82 struct ltt_chanbuf *buf = inode->i_private;
83 struct ltt_chan *chan = container_of(buf->a.chan, struct ltt_chan, a);
84
85 if (filp->f_mode & FMODE_READ) {
86 poll_wait_set_exclusive(wait);
87 poll_wait(filp, &buf->read_wait, wait);
88
89 WARN_ON(atomic_long_read(&buf->active_readers) != 1);
90 if (SUBBUF_TRUNC(ltt_chanbuf_get_offset(buf), chan)
91 - SUBBUF_TRUNC(ltt_chanbuf_get_consumed(buf), chan)
92 == 0) {
93 if (buf->finalized)
94 return POLLHUP;
95 else
96 return 0;
97 } else {
98 if (SUBBUF_TRUNC(ltt_chanbuf_get_offset(buf), chan)
99 - SUBBUF_TRUNC(ltt_chanbuf_get_consumed(buf), chan)
100 >= chan->a.buf_size)
101 return POLLPRI | POLLRDBAND;
102 else
103 return POLLIN | POLLRDNORM;
104 }
105 }
106 return mask;
107}
108
109/**
110 * ltt_ioctl - control on the debugfs file
111 *
1c8284eb
MD
112 * @filp: the file
113 * @cmd: the command
114 * @arg: command arg
115 *
116 * This ioctl implements three commands necessary for a minimal
117 * producer/consumer implementation :
118 * RELAY_GET_SB
119 * Get the next sub-buffer that can be read. It never blocks.
120 * RELAY_PUT_SB
121 * Release the currently read sub-buffer. Parameter is the last
122 * put subbuffer (returned by GET_SUBBUF).
123 * RELAY_GET_N_SB
124 * returns the number of sub-buffers in the per cpu channel.
125 * RELAY_GET_SB_SIZE
126 * returns the size of the current sub-buffer.
127 * RELAY_GET_MAX_SB_SIZE
128 * returns the maximum size for sub-buffers.
129 */
130static
5050cf2d 131long ltt_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1c8284eb 132{
5050cf2d 133 struct inode *inode = filp->f_dentry->d_inode;
1c8284eb
MD
134 struct ltt_chanbuf *buf = inode->i_private;
135 u32 __user *argp = (u32 __user *)arg;
136
137 switch (cmd) {
138 case RELAY_GET_SB:
139 {
140 unsigned long consumed;
141 int ret;
142
143 ret = ltt_chanbuf_get_subbuf(buf, &consumed);
144 if (ret)
145 return ret;
146 else
147 return put_user((u32)consumed, argp);
148 break;
149 }
150 case RELAY_PUT_SB:
151 {
152 u32 uconsumed_old;
153 int ret;
154 long consumed_old;
155
156 ret = get_user(uconsumed_old, argp);
157 if (ret)
158 return ret; /* will return -EFAULT */
159
160 consumed_old = ltt_chanbuf_get_consumed(buf);
161 consumed_old = consumed_old & (~0xFFFFFFFFL);
162 consumed_old = consumed_old | uconsumed_old;
163 ret = ltt_chanbuf_put_subbuf(buf, consumed_old);
164 if (ret)
165 return ret;
166 break;
167 }
168 case RELAY_GET_N_SB:
169 return put_user((u32)buf->a.chan->n_sb, argp);
170 break;
171 case RELAY_GET_SB_SIZE:
172 return put_user(get_read_sb_size(buf), argp);
173 break;
174 case RELAY_GET_MAX_SB_SIZE:
175 return put_user((u32)buf->a.chan->sb_size, argp);
176 break;
177 default:
178 return -ENOIOCTLCMD;
179 }
180 return 0;
181}
182
183#ifdef CONFIG_COMPAT
184static
185long ltt_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
186{
5050cf2d 187 return ltt_ioctl(file, cmd, arg);
1c8284eb
MD
188}
189#endif
190
191static const struct file_operations ltt_file_operations = {
192 .open = ltt_open,
193 .release = ltt_release,
194 .poll = ltt_poll,
195 .splice_read = ltt_relay_file_splice_read,
5050cf2d 196 .unlocked_ioctl = ltt_ioctl,
1c8284eb
MD
197 .llseek = ltt_relay_no_llseek,
198#ifdef CONFIG_COMPAT
199 .compat_ioctl = ltt_compat_ioctl,
200#endif
201};
202
203int ltt_chanbuf_create_file(const char *filename, struct dentry *parent,
204 int mode, struct ltt_chanbuf *buf)
205{
206 struct ltt_chan *chan = container_of(buf->a.chan, struct ltt_chan, a);
207 char *tmpname;
208 int ret = 0;
209
210 tmpname = kzalloc(NAME_MAX + 1, GFP_KERNEL);
211 if (!tmpname) {
212 ret = -ENOMEM;
213 goto end;
214 }
215
216 snprintf(tmpname, NAME_MAX, "%s%s_%d",
217 chan->overwrite ? LTT_FLIGHT_PREFIX : "",
218 chan->a.filename, buf->a.cpu);
219
220 buf->a.dentry = debugfs_create_file(tmpname, mode, parent, buf,
221 &ltt_file_operations);
222 if (!buf->a.dentry) {
223 ret = -ENOMEM;
224 goto free_name;
225 }
226free_name:
227 kfree(tmpname);
228end:
229 return ret;
230}
231
232int ltt_chanbuf_remove_file(struct ltt_chanbuf *buf)
233{
234 debugfs_remove(buf->a.dentry);
235
236 return 0;
237}
This page took 0.03029 seconds and 4 git commands to generate.