]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - block/blktrace.c
block: make blktrace use per-cpu buffers for message notes
[linux-2.6-omap-h63xx.git] / block / blktrace.c
index 498a0a54a6aa664f27edce4a32d2fb2d37f4c110..7ae87cc4a163fc0dfcae0f65e6d25e9b185c4b91 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/time.h>
 #include <asm/uaccess.h>
 
-static DEFINE_PER_CPU(unsigned long long, blk_trace_cpu_offset) = { 0, };
 static unsigned int blktrace_seq __read_mostly = 1;
 
 /*
@@ -41,7 +40,7 @@ static void trace_note(struct blk_trace *bt, pid_t pid, int action,
                const int cpu = smp_processor_id();
 
                t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION;
-               t->time = cpu_clock(cpu) - per_cpu(blk_trace_cpu_offset, cpu);
+               t->time = ktime_to_ns(ktime_get());
                t->device = bt->dev;
                t->action = action;
                t->pid = pid;
@@ -76,6 +75,23 @@ static void trace_note_time(struct blk_trace *bt)
        local_irq_restore(flags);
 }
 
+void __trace_note_message(struct blk_trace *bt, const char *fmt, ...)
+{
+       int n;
+       va_list args;
+       char *buf;
+
+       preempt_disable();
+       buf = per_cpu_ptr(bt->msg_data, smp_processor_id());
+       va_start(args, fmt);
+       n = vscnprintf(buf, BLK_TN_MAX_MSG, fmt, args);
+       va_end(args);
+
+       trace_note(bt, 0, BLK_TN_MESSAGE, buf, n);
+       preempt_enable();
+}
+EXPORT_SYMBOL_GPL(__trace_note_message);
+
 static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector,
                         pid_t pid)
 {
@@ -159,7 +175,7 @@ void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
 
                t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION;
                t->sequence = ++(*sequence);
-               t->time = cpu_clock(cpu) - per_cpu(blk_trace_cpu_offset, cpu);
+               t->time = ktime_to_ns(ktime_get());
                t->sector = sector;
                t->bytes = bytes;
                t->action = what;
@@ -179,7 +195,7 @@ void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
 EXPORT_SYMBOL_GPL(__blk_add_trace);
 
 static struct dentry *blk_tree_root;
-static struct mutex blk_tree_mutex;
+static DEFINE_MUTEX(blk_tree_mutex);
 static unsigned int root_users;
 
 static inline void blk_remove_root(void)
@@ -233,10 +249,11 @@ static void blk_trace_cleanup(struct blk_trace *bt)
        debugfs_remove(bt->dropped_file);
        blk_remove_tree(bt->dir);
        free_percpu(bt->sequence);
+       free_percpu(bt->msg_data);
        kfree(bt);
 }
 
-static int blk_trace_remove(struct request_queue *q)
+int blk_trace_remove(struct request_queue *q)
 {
        struct blk_trace *bt;
 
@@ -250,6 +267,7 @@ static int blk_trace_remove(struct request_queue *q)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(blk_trace_remove);
 
 static int blk_dropped_open(struct inode *inode, struct file *filp)
 {
@@ -317,18 +335,17 @@ static struct rchan_callbacks blk_relay_callbacks = {
 /*
  * Setup everything required to start tracing
  */
-int do_blk_trace_setup(struct request_queue *q, struct block_device *bdev,
+int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
                        struct blk_user_trace_setup *buts)
 {
        struct blk_trace *old_bt, *bt = NULL;
        struct dentry *dir = NULL;
-       char b[BDEVNAME_SIZE];
        int ret, i;
 
        if (!buts->buf_size || !buts->buf_nr)
                return -EINVAL;
 
-       strcpy(buts->name, bdevname(bdev, b));
+       strcpy(buts->name, name);
 
        /*
         * some device names have larger paths - convert the slashes
@@ -347,13 +364,17 @@ int do_blk_trace_setup(struct request_queue *q, struct block_device *bdev,
        if (!bt->sequence)
                goto err;
 
+       bt->msg_data = __alloc_percpu(BLK_TN_MAX_MSG);
+       if (!bt->msg_data)
+               goto err;
+
        ret = -ENOENT;
        dir = blk_create_tree(buts->name);
        if (!dir)
                goto err;
 
        bt->dir = dir;
-       bt->dev = bdev->bd_dev;
+       bt->dev = dev;
        atomic_set(&bt->dropped, 0);
 
        ret = -EIO;
@@ -393,6 +414,7 @@ err:
                if (bt->dropped_file)
                        debugfs_remove(bt->dropped_file);
                free_percpu(bt->sequence);
+               free_percpu(bt->msg_data);
                if (bt->rchan)
                        relay_close(bt->rchan);
                kfree(bt);
@@ -400,8 +422,8 @@ err:
        return ret;
 }
 
-static int blk_trace_setup(struct request_queue *q, struct block_device *bdev,
-                          char __user *arg)
+int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
+                   char __user *arg)
 {
        struct blk_user_trace_setup buts;
        int ret;
@@ -410,7 +432,7 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev,
        if (ret)
                return -EFAULT;
 
-       ret = do_blk_trace_setup(q, bdev, &buts);
+       ret = do_blk_trace_setup(q, name, dev, &buts);
        if (ret)
                return ret;
 
@@ -419,8 +441,9 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(blk_trace_setup);
 
-static int blk_trace_startstop(struct request_queue *q, int start)
+int blk_trace_startstop(struct request_queue *q, int start)
 {
        struct blk_trace *bt;
        int ret;
@@ -453,6 +476,7 @@ static int blk_trace_startstop(struct request_queue *q, int start)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(blk_trace_startstop);
 
 /**
  * blk_trace_ioctl: - handle the ioctls associated with tracing
@@ -465,6 +489,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
 {
        struct request_queue *q;
        int ret, start = 0;
+       char b[BDEVNAME_SIZE];
 
        q = bdev_get_queue(bdev);
        if (!q)
@@ -474,7 +499,8 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
 
        switch (cmd) {
        case BLKTRACESETUP:
-               ret = blk_trace_setup(q, bdev, arg);
+               bdevname(bdev, b);
+               ret = blk_trace_setup(q, b, bdev->bd_dev, arg);
                break;
        case BLKTRACESTART:
                start = 1;
@@ -505,77 +531,3 @@ void blk_trace_shutdown(struct request_queue *q)
                blk_trace_remove(q);
        }
 }
-
-/*
- * Average offset over two calls to cpu_clock() with a gettimeofday()
- * in the middle
- */
-static void blk_check_time(unsigned long long *t, int this_cpu)
-{
-       unsigned long long a, b;
-       struct timeval tv;
-
-       a = cpu_clock(this_cpu);
-       do_gettimeofday(&tv);
-       b = cpu_clock(this_cpu);
-
-       *t = tv.tv_sec * 1000000000 + tv.tv_usec * 1000;
-       *t -= (a + b) / 2;
-}
-
-/*
- * calibrate our inter-CPU timings
- */
-static void blk_trace_check_cpu_time(void *data)
-{
-       unsigned long long *t;
-       int this_cpu = get_cpu();
-
-       t = &per_cpu(blk_trace_cpu_offset, this_cpu);
-
-       /*
-        * Just call it twice, hopefully the second call will be cache hot
-        * and a little more precise
-        */
-       blk_check_time(t, this_cpu);
-       blk_check_time(t, this_cpu);
-
-       put_cpu();
-}
-
-static void blk_trace_set_ht_offsets(void)
-{
-#if defined(CONFIG_SCHED_SMT)
-       int cpu, i;
-
-       /*
-        * now make sure HT siblings have the same time offset
-        */
-       preempt_disable();
-       for_each_online_cpu(cpu) {
-               unsigned long long *cpu_off, *sibling_off;
-
-               for_each_cpu_mask(i, per_cpu(cpu_sibling_map, cpu)) {
-                       if (i == cpu)
-                               continue;
-
-                       cpu_off = &per_cpu(blk_trace_cpu_offset, cpu);
-                       sibling_off = &per_cpu(blk_trace_cpu_offset, i);
-                       *sibling_off = *cpu_off;
-               }
-       }
-       preempt_enable();
-#endif
-}
-
-static __init int blk_trace_init(void)
-{
-       mutex_init(&blk_tree_mutex);
-       on_each_cpu(blk_trace_check_cpu_time, NULL, 1, 1);
-       blk_trace_set_ht_offsets();
-
-       return 0;
-}
-
-module_init(blk_trace_init);
-