00001 #define HASH_TABLE_BITS 8
00002 #define HASH_TABLE_SIZE (1<<HASH_TABLE_BITS)
00003 #define BUCKETS 16
00004 #include <linux/module.h>
00005 #include <linux/interrupt.h>
00006 #include <net/sock.h>
00007 #include <linux/netlink.h>
00008
00009 #include "runtime.h"
00010 #include "io.c"
00011 #include "map.c"
00012 #include "probes.c"
00013 #include "stack.c"
00014
00015 MODULE_DESCRIPTION("SystemTap probe: test4");
00016 MODULE_AUTHOR("Martin Hunt <hunt@redhat.com>");
00017
00018 static char tbuffer[2][50000];
00019 static void stp_helper(void *);
00020 static DECLARE_WORK(stp_work, stp_helper, tbuffer);
00021
00022 MAP opens, reads, writes, traces;
00023 static int bufcount = 0;
00024
00025
00026 static struct sock *control;
00027 static int seq = 0;
00028
00029 int pid;
00030
00031
00032
00033 static int send_reply(int type, void *reply, int len, int pid)
00034 {
00035 struct sk_buff *skb;
00036 struct nlmsghdr *nlh;
00037 void *data;
00038 int size;
00039 int err;
00040
00041 size = NLMSG_SPACE(len);
00042 skb = alloc_skb(size, GFP_KERNEL);
00043 if (!skb)
00044 return -1;
00045 nlh = NLMSG_PUT(skb, pid, seq++, type, size - sizeof(*nlh));
00046 nlh->nlmsg_flags = 0;
00047 data = NLMSG_DATA(nlh);
00048 memcpy(data, reply, len);
00049 err = netlink_unicast(control, skb, pid, MSG_DONTWAIT);
00050
00051 return 0;
00052
00053 nlmsg_failure:
00054 if (skb)
00055 kfree_skb(skb);
00056
00057 return -1;
00058 }
00059
00060 static char pbuff[1024];
00061
00062 void nlog (const char *fmt, ...)
00063 {
00064 int len;
00065 va_list args;
00066 va_start(args, fmt);
00067 len = vscnprintf (pbuff, sizeof(pbuff), fmt, args) + 1;
00068 va_end(args);
00069 send_reply (42, pbuff, len, pid);
00070 }
00071
00072
00073
00074
00075 static void msg_rcv_skb(struct sk_buff *skb)
00076 {
00077 struct nlmsghdr *nlh = NULL;
00078 int flags;
00079 int nlmsglen, skblen;
00080 void *data;
00081
00082 skblen = skb->len;
00083
00084 if (skblen < sizeof (*nlh))
00085 return;
00086
00087 nlh = (struct nlmsghdr *)skb->data;
00088 nlmsglen = nlh->nlmsg_len;
00089
00090
00091 if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen)
00092 return;
00093
00094 pid = nlh->nlmsg_pid;
00095 flags = nlh->nlmsg_flags;
00096
00097
00098 if (pid <= 0 || !(flags & NLM_F_REQUEST)) {
00099 netlink_ack(skb, nlh, -EINVAL);
00100 return;
00101 }
00102
00103 if (flags & MSG_TRUNC) {
00104 netlink_ack(skb, nlh, -ECOMM);
00105 return;
00106 }
00107
00108 data = NLMSG_DATA(nlh);
00109
00110
00111
00112 if (flags & NLM_F_ACK)
00113 netlink_ack(skb, nlh, 0);
00114
00115 send_reply (42, "Howdy Partner", 14, pid);
00116 }
00117
00118 static void msg_rcv(struct sock *sk, int len)
00119 {
00120 struct sk_buff *skb;
00121 dlog ("netlink message received\n");
00122 while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
00123 msg_rcv_skb(skb);
00124 kfree_skb(skb);
00125 }
00126 }
00127
00128 static void stp_helper (void *data)
00129 {
00130 dlog ("HELPER\n");
00131 }
00132
00133 asmlinkage long inst_sys_open (const char __user * filename, int flags, int mode)
00134 {
00135 _stp_map_key_str (opens, current->comm);
00136 _stp_map_add_int64 (opens, 1);
00137 jprobe_return();
00138 return 0;
00139 }
00140
00141 asmlinkage ssize_t inst_sys_read (unsigned int fd, char __user * buf, size_t count)
00142 {
00143 _stp_map_key_str (reads, current->comm);
00144 _stp_map_stat_add (reads, count);
00145 jprobe_return();
00146 return 0;
00147 }
00148
00149 asmlinkage ssize_t inst_sys_write (unsigned int fd, const char __user * buf, size_t count)
00150 {
00151 _stp_map_key_str (writes, current->comm);
00152 _stp_map_stat_add (writes, count);
00153 jprobe_return();
00154 return 0;
00155 }
00156
00157 int inst_show_cpuinfo(struct seq_file *m, void *v)
00158 {
00159 _stp_stack_print (0,0);
00160 _stp_stack_print (1,0);
00161
00162 _stp_scbuf_clear();
00163 _stp_list_add (traces, _stp_stack_sprint(0,0));
00164 if (bufcount++ == 0)
00165 schedule_work (&stp_work);
00166
00167 jprobe_return();
00168 return 0;
00169 }
00170
00171
00172 static struct jprobe dtr_probes[] = {
00173 {
00174 .kp.addr = (kprobe_opcode_t *)"sys_open",
00175 .entry = (kprobe_opcode_t *) inst_sys_open
00176 },
00177 {
00178 .kp.addr = (kprobe_opcode_t *)"sys_read",
00179 .entry = (kprobe_opcode_t *) inst_sys_read
00180 },
00181 {
00182 .kp.addr = (kprobe_opcode_t *)"sys_write",
00183 .entry = (kprobe_opcode_t *) inst_sys_write
00184 },
00185 {
00186 .kp.addr = (kprobe_opcode_t *)"show_cpuinfo",
00187 .entry = (kprobe_opcode_t *) inst_show_cpuinfo,
00188 },
00189 };
00190
00191 #define MAX_DTR_ROUTINE (sizeof(dtr_probes)/sizeof(struct jprobe))
00192
00193 static int init_dtr(void)
00194 {
00195 int ret;
00196
00197 control = netlink_kernel_create(31, msg_rcv);
00198 if (!control) {
00199 dlog ("Couldn't create netlink channel\n");
00200 return -1;
00201 }
00202
00203 opens = _stp_map_new (1000, INT64);
00204 reads = _stp_map_new (1000, STAT);
00205 writes = _stp_map_new (1000, STAT);
00206 traces = _stp_list_new (1000, STRING);
00207
00208 ret = _stp_register_jprobes (dtr_probes, MAX_DTR_ROUTINE);
00209
00210 dlog("instrumentation is enabled...\n");
00211 return ret;
00212
00213 }
00214
00215 static void cleanup_dtr(void)
00216 {
00217 struct map_node_stat *st;
00218 struct map_node_int64 *ptr;
00219 struct map_node_str *sptr;
00220
00221 _stp_unregister_jprobes (dtr_probes, MAX_DTR_ROUTINE);
00222
00223 foreach (traces, sptr)
00224 nlog ("trace: %s\n", sptr->str);
00225
00226 foreach (opens, ptr)
00227 nlog ("opens[%s] = %lld\n", key1str(ptr), ptr->val);
00228 nlog ("\n");
00229
00230 foreach (reads, st)
00231 nlog ("reads[%s] = [count=%lld sum=%lld min=%lld max=%lld]\n", key1str(st),
00232 st->stats.count, st->stats.sum, st->stats.min, st->stats.max);
00233 nlog ("\n");
00234
00235 foreach (writes, st)
00236 nlog ("writes[%s] = [count=%lld sum=%lld min=%lld max=%lld]\n", key1str(st),
00237 st->stats.count, st->stats.sum, st->stats.min, st->stats.max);
00238 nlog ("\n");
00239
00240 _stp_map_del (opens);
00241 _stp_map_del (reads);
00242 _stp_map_del (writes);
00243
00244 if (control)
00245 sock_release(control->sk_socket);
00246
00247 dlog("EXIT\n");
00248 }
00249
00250 module_init(init_dtr);
00251 module_exit(cleanup_dtr);
00252 MODULE_LICENSE("GPL");
00253