Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

dtr.c

00001 #define HASH_TABLE_BITS 8
00002 #define HASH_TABLE_SIZE (1<<HASH_TABLE_BITS)
00003 #define BUCKETS 16 /* largest histogram width */
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 /* netlink control channel */
00026 static struct sock *control;
00027 static int seq = 0;
00028 
00029 int pid;
00030 /*
00031  * send_reply - send reply to userspace over netlink control channel
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  * msg_rcv_skb - dispatch userspace requests from netlink control channel
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         //      dlog ("skblen = %d %d\n", skblen, sizeof(*nlh));
00084         if (skblen < sizeof (*nlh))
00085                 return; 
00086 
00087         nlh = (struct nlmsghdr *)skb->data;
00088         nlmsglen = nlh->nlmsg_len;
00089         
00090         //      dlog ("nlmsghlen=%d\n", nlmsglen);
00091         if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen)
00092                 return;
00093 
00094         pid = nlh->nlmsg_pid;
00095         flags = nlh->nlmsg_flags;
00096 
00097         //      dlog ("pid=%d flags=%x %x %x %x\n", pid, flags, NLM_F_REQUEST, MSG_TRUNC, NLM_F_ACK);
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         //      dlog ("NETLINK: Got message \"%s\" of type %d from pid %d\n", data, nlh->nlmsg_type,pid);
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