1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#ifndef _TRANSPORT_RELAYFS_C_ /* -*- linux-c -*- */
#define _TRANSPORT_RELAYFS_C_
/*
* relayfs.c - stp relayfs-related transport functions
*
* Copyright (C) IBM Corporation, 2005
* Copyright (C) Redhat Inc, 2005
*
* This file is released under the GPL.
*/
/** @file relayfs.c
* @brief Systemtap relayfs-related transport functions
*/
/** @addtogroup transport Transport Functions
* @{
*/
#include "relayfs.h"
#ifdef RELAYFS_VERSION_GE_4
/**
* _stp_subbuf_start - subbuf_start() relayfs callback implementation
*/
static int _stp_subbuf_start(struct rchan_buf *buf,
void *subbuf,
void *prev_subbuf,
unsigned int prev_padding)
{
if (relay_buf_full(buf))
return 0;
if (prev_subbuf)
*((unsigned *)prev_subbuf) = prev_padding;
subbuf_start_reserve(buf, sizeof(prev_padding));
return 1;
}
#else
/**
* _stp_subbuf_start - subbuf_start() relayfs callback implementation
*/
static int _stp_subbuf_start(struct rchan_buf *buf,
void *subbuf,
unsigned prev_subbuf_idx,
void *prev_subbuf)
{
unsigned padding = buf->padding[prev_subbuf_idx];
if (prev_subbuf)
*((unsigned *)prev_subbuf) = padding;
return sizeof(padding); /* reserve space for padding */
}
/**
* _stp_buf_full - buf_full() relayfs callback implementation
*/
static void _stp_buf_full(struct rchan_buf *buf,
unsigned subbuf_idx,
void *subbuf)
{
unsigned padding = buf->padding[subbuf_idx];
*((unsigned *)subbuf) = padding;
}
#endif /* RELAYFS_VERSION_GE_4 */
/* relayfs callback functions */
static struct rchan_callbacks stp_rchan_callbacks =
{
.subbuf_start = _stp_subbuf_start,
#ifndef RELAYFS_VERSION_GE_4
.buf_full = _stp_buf_full,
#endif /* RELAYFS_VERSION_GE_4 */
};
/**
* _stp_relayfs_close - destroys relayfs channel
* @chan: the relayfs channel
* @dir: the directory containing the relayfs files
*/
void _stp_relayfs_close(struct rchan *chan, struct dentry *dir)
{
if (!chan)
return;
relay_close(chan);
if (dir)
relayfs_remove_dir(dir);
}
/**
* _stp_relayfs_open - create relayfs channel
* @n_subbufs: number of relayfs sub-buffers
* @subbuf_size: size of relayfs sub-buffers
* @pid: daemon pid
* @outdir: receives directory dentry
*
* Returns relay channel, NULL on failure
*
* Creates relayfs files as /systemtap/pid/cpuX in relayfs root
*/
struct rchan *_stp_relayfs_open(unsigned n_subbufs,
unsigned subbuf_size,
int pid,
struct dentry **outdir)
{
char dirname[16];
struct rchan *chan;
struct dentry* dir = NULL;
sprintf(dirname, "%d", pid);
/* TODO: need to create systemtap dir */
dir = relayfs_create_dir(dirname, NULL);
if (!dir) {
printk("STP: couldn't create relayfs dir %s.\n", dirname);
return NULL;
}
#ifdef RELAYFS_VERSION_GE_4
chan = relay_open("cpu", dir, subbuf_size,
n_subbufs, &stp_rchan_callbacks);
#else
chan = relay_open("cpu", dir, subbuf_size,
n_subbufs, 0, &stp_rchan_callbacks);
#endif /* RELAYFS_VERSION_GE_4 */
if (!chan) {
printk("STP: couldn't create relayfs channel.\n");
if (dir)
relayfs_remove_dir(dir);
}
*outdir = dir;
return chan;
}
#endif /* _TRANSPORT_RELAYFS_C_ */
|