Remove ltt-channels.c. Part of LTTng kernel tree.
[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 *
112 * @inode: the inode
113 * @filp: the file
114 * @cmd: the command
115 * @arg: command arg
116 *
117 * This ioctl implements three commands necessary for a minimal
118 * producer/consumer implementation :
119 * RELAY_GET_SB
120 * Get the next sub-buffer that can be read. It never blocks.
121 * RELAY_PUT_SB
122 * Release the currently read sub-buffer. Parameter is the last
123 * put subbuffer (returned by GET_SUBBUF).
124 * RELAY_GET_N_SB
125 * returns the number of sub-buffers in the per cpu channel.
126 * RELAY_GET_SB_SIZE
127 * returns the size of the current sub-buffer.
128 * RELAY_GET_MAX_SB_SIZE
129 * returns the maximum size for sub-buffers.
130 */
131static
132int ltt_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
133 unsigned long arg)
134{
135 struct ltt_chanbuf *buf = inode->i_private;
136 u32 __user *argp = (u32 __user *)arg;
137
138 switch (cmd) {
139 case RELAY_GET_SB:
140 {
141 unsigned long consumed;
142 int ret;
143
144 ret = ltt_chanbuf_get_subbuf(buf, &consumed);
145 if (ret)
146 return ret;
147 else
148 return put_user((u32)consumed, argp);
149 break;
150 }
151 case RELAY_PUT_SB:
152 {
153 u32 uconsumed_old;
154 int ret;
155 long consumed_old;
156
157 ret = get_user(uconsumed_old, argp);
158 if (ret)
159 return ret; /* will return -EFAULT */
160
161 consumed_old = ltt_chanbuf_get_consumed(buf);
162 consumed_old = consumed_old & (~0xFFFFFFFFL);
163 consumed_old = consumed_old | uconsumed_old;
164 ret = ltt_chanbuf_put_subbuf(buf, consumed_old);
165 if (ret)
166 return ret;
167 break;
168 }
169 case RELAY_GET_N_SB:
170 return put_user((u32)buf->a.chan->n_sb, argp);
171 break;
172 case RELAY_GET_SB_SIZE:
173 return put_user(get_read_sb_size(buf), argp);
174 break;
175 case RELAY_GET_MAX_SB_SIZE:
176 return put_user((u32)buf->a.chan->sb_size, argp);
177 break;
178 default:
179 return -ENOIOCTLCMD;
180 }
181 return 0;
182}
183
184#ifdef CONFIG_COMPAT
185static
186long ltt_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
187{
188 long ret = -ENOIOCTLCMD;
189
190 lock_kernel();
191 ret = ltt_ioctl(file->f_dentry->d_inode, file, cmd, arg);
192 unlock_kernel();
193
194 return ret;
195}
196#endif
197
198static const struct file_operations ltt_file_operations = {
199 .open = ltt_open,
200 .release = ltt_release,
201 .poll = ltt_poll,
202 .splice_read = ltt_relay_file_splice_read,
203 .ioctl = ltt_ioctl,
204 .llseek = ltt_relay_no_llseek,
205#ifdef CONFIG_COMPAT
206 .compat_ioctl = ltt_compat_ioctl,
207#endif
208};
209
210int ltt_chanbuf_create_file(const char *filename, struct dentry *parent,
211 int mode, struct ltt_chanbuf *buf)
212{
213 struct ltt_chan *chan = container_of(buf->a.chan, struct ltt_chan, a);
214 char *tmpname;
215 int ret = 0;
216
217 tmpname = kzalloc(NAME_MAX + 1, GFP_KERNEL);
218 if (!tmpname) {
219 ret = -ENOMEM;
220 goto end;
221 }
222
223 snprintf(tmpname, NAME_MAX, "%s%s_%d",
224 chan->overwrite ? LTT_FLIGHT_PREFIX : "",
225 chan->a.filename, buf->a.cpu);
226
227 buf->a.dentry = debugfs_create_file(tmpname, mode, parent, buf,
228 &ltt_file_operations);
229 if (!buf->a.dentry) {
230 ret = -ENOMEM;
231 goto free_name;
232 }
233free_name:
234 kfree(tmpname);
235end:
236 return ret;
237}
238
239int ltt_chanbuf_remove_file(struct ltt_chanbuf *buf)
240{
241 debugfs_remove(buf->a.dentry);
242
243 return 0;
244}
This page took 0.030952 seconds and 4 git commands to generate.