[PATCH] Add argument parsing for blktrace
authorAlan D. Brunelle <Alan.Brunelle@hp.com>
Wed, 31 Aug 2005 06:49:05 +0000 (08:49 +0200)
committerJens Axboe <axboe@suse.de>
Wed, 31 Aug 2005 06:49:05 +0000 (08:49 +0200)
This patch adds the option of specifying the trace mask for blktrace, so you
can register an interest in only certain events.

CHANGELOG
README
blktrace.c

index ef2bfb4ee4c39e21db5a4695250a6464e57b94fa..377369c5b7fdc6ba2bcf280de0804402f4590cb1 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+20050830:
+       - Added argument parsing
+       - Added action mask set up
 20050829:
        - Improved error handling
        - Remove _dat files, include the payload in _out
diff --git a/README b/README
index 673683fadb2ae38a68f46bac4889d53825088918..6167b842e5efa7e2463602d138c2c9393f37d1b7 100644 (file)
--- a/README
+++ b/README
@@ -26,7 +26,18 @@ Usage
 -----
 
 To run:
-       % blktrace <dev>
+       % blktrace -d <dev> [-a <trace> [-a <trace>]]
+               -a <trace> is one of: (use multiple -a options to get more)
+                       READ
+                       WRITE
+                       BARRIER
+                       SYNC
+                       QUEUE
+                       REQUEUE
+                       ISSUE
+                       COMPLETE
+                       FS
+                       PC
        --- run task to generate load to be traced ---
        <SIGINT to kill>
        --- Generates:
index 1af278375c8a202e2b5750cef9e696294b5381d5..db1c8402c243bfe6d41631332ae95fa6eaa94a0a 100644 (file)
@@ -2,7 +2,6 @@
  * block queue tracing application
  *
  * TODO (in no particular order):
- *     - Add ability to specify capture mask instead of logging all events
  *     - Add option for relayfs mount point
  *
  */
 #include <stdio.h>
 #include <stdlib.h>
 #include <sched.h>
+#include <ctype.h>
+#include <getopt.h>
 
 #include "blktrace.h"
 
 #define BUF_SIZE       (128 *1024)
 #define BUF_NR         (4)
 
+#define DECLARE_MASK_MAP(mask)          { BLK_TC_##mask, #mask, "BLK_TC_"#mask }
+#define COMPARE_MASK_MAP(mmp, str)                                      \
+        (!strcmp(mmp->short_form, toupper(str)) ||                      \
+         !strcmp(mmp->long_form, toupper(str)))
+
+#define VALID_SET(x)   ((1 <= (x)) && ((x) < (1 << BLK_TC_SHIFT)))
+
+struct mask_map {
+       int mask;
+       char *short_form;
+       char *long_form;
+};
+
+struct mask_map mask_maps[] = {
+        DECLARE_MASK_MAP( READ     ),
+        DECLARE_MASK_MAP( WRITE    ),
+        DECLARE_MASK_MAP( BARRIER  ),
+        DECLARE_MASK_MAP( SYNC     ),
+        DECLARE_MASK_MAP( QUEUE    ),
+        DECLARE_MASK_MAP( REQUEUE  ),
+        DECLARE_MASK_MAP( ISSUE    ),
+        DECLARE_MASK_MAP( COMPLETE ),
+        DECLARE_MASK_MAP( FS       ),
+        DECLARE_MASK_MAP( PC       ),
+};
+
+#define S_OPTS "d:a:A:"
+struct option l_opts[] = {
+       { 
+               .name = "dev",
+               .has_arg = 1,
+               .flag = NULL,
+               .val = 'd'
+       },
+       { 
+               .name = "act-mask",
+               .has_arg = 1,
+               .flag = NULL,
+               .val = 'a'
+       },
+       { 
+               .name = "set-mask",
+               .has_arg = 1,
+               .flag = NULL,
+               .val = 'A'
+       },
+       {
+               .name = NULL,
+               .has_arg = 0,
+               .flag = NULL,
+               .val = 0
+       }
+};
+
 struct thread_information {
        int cpu;
        pthread_t thread;
@@ -38,6 +93,30 @@ static volatile int done;
 static int devfd, ncpus;
 static struct thread_information *thread_information;
 static char *buts_name_p;
+static char *dev;
+static int act_mask = ~0;
+
+inline int compare_mask_map(struct mask_map *mmp, char *string)
+{
+        int i;
+        char *s, *ustring = strdup(string);
+
+        for (i = 0, s = ustring; i < strlen(ustring); i++, s++)
+                *s = toupper(*s);
+
+        return !strcmp(mmp->short_form, ustring) ||
+               !strcmp(mmp->long_form, ustring);
+}
+
+int find_mask_map(char *string)
+{
+        int i;
+
+        for (i = 0; i < sizeof(mask_maps)/sizeof(mask_maps[0]); i++)
+                if (compare_mask_map(&mask_maps[i], string))
+                        return mask_maps[i].mask;
+       return -1;
+}
 
 static int start_trace(char *dev)
 {
@@ -52,6 +131,7 @@ static int start_trace(char *dev)
        memset(&buts, sizeof(buts), 0);
        buts.buf_size = BUF_SIZE;
        buts.buf_nr = BUF_NR;
+       buts.act_mask = act_mask;
 
        printf("Starting trace on %s\n", dev);
        if (ioctl(devfd, BLKSTARTTRACE, &buts) < 0) {
@@ -245,21 +325,65 @@ void handle_sigint(int sig)
 int main(int argc, char *argv[])
 {
        struct stat st;
-       int i;
+       int i, c;
+       int act_mask_tmp = 0;
+
+       while ((c = getopt_long(argc, argv, S_OPTS, l_opts, NULL)) >= 0) {
+               switch (c) {
+               case 'a':
+                       i = find_mask_map(optarg);
+                       if (i < 0) {
+                               fprintf(stderr,"Invalid action mask %s\n", 
+                                       optarg);
+                               return 4;
+                       }
+                       act_mask_tmp |= i;
+                       break;
+
+               case 'A':
+                       if ((sscanf(optarg, "%x", &i) != 1) || !VALID_SET(i)) {
+                               fprintf(stderr,
+                                       "Invalid set action mask %s/0x%x\n", 
+                                       optarg, i);
+                               return 4;
+                       }
+                       act_mask_tmp = i;
+                       break;
 
-       if (argc < 2) {
-               fprintf(stderr, "Usage: %s <dev>\n", argv[0]);
-               return 1;
+               case 'd':
+                       dev = strdup(optarg);
+                       break;
+
+               default:
+                       fprintf(stderr,"Usage: %s -d <dev> "
+                                      "[-a <trace> [-a <trace>]]\n", argv[0]);
+                       return 4;
+               }
+       }
+
+       if ((dev == NULL) || (optind < argc)) {
+               fprintf(stderr,"Usage: %s -d <dev> "
+                              "[-a <trace> [-a <trace>]]\n", argv[0]);
+               return 4;
+       }
+
+       if (act_mask_tmp != 0) {
+               act_mask = act_mask_tmp;
+               printf("Tracing 0x%04x: ", act_mask);
+               for (i = 0; i < BLK_TC_SHIFT; i++)
+                       if (act_mask & (1 << i))
+                               printf("%s ", mask_maps[i].short_form);
+               printf("\n");
        }
 
        if (stat(relay_path, &st) < 0) {
-               fprintf(stderr,"%s does not appear to be mounted\n", 
+               fprintf(stderr,"%s does not appear to be mounted\n",
                        relay_path);
                return 2;
        }
 
-       if (start_trace(argv[1])) {
-               fprintf(stderr, "Failed to start trace\n");
+       if (start_trace(dev)) {
+               fprintf(stderr, "Failed to start trace on %s\n", dev);
                stop_trace();
                return 3;
        }