aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristof Schmitt <christof.schmitt@de.ibm.com>2008-01-11 04:09:43 -0500
committerJens Axboe <jens.axboe@oracle.com>2008-01-28 04:04:46 -0500
commit6da127ad0918f93ea93678dad62ce15ffed18797 (patch)
treeb2bf9ad228f18c643342ad376136d2f6b4be4137
parent91525300baf162e83e923b09ca286f9205e21522 (diff)
blktrace: Add blktrace ioctls to SCSI generic devices
Since the SCSI layer uses the request queues from the block layer, blktrace can also be used to trace the requests to all SCSI devices (like SCSI tape drives), not only disks. The only missing part is the ioctl interface to start and stop tracing. This patch adds the SETUP, START, STOP and TEARDOWN ioctls from blktrace to the sg device files. With this change, blktrace can be used for SCSI devices like for disks, e.g.: blktrace -d /dev/sg1 -o - | blkparse -i - Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r--block/blktrace.c24
-rw-r--r--block/compat_ioctl.c5
-rw-r--r--drivers/scsi/sg.c12
-rw-r--r--include/linux/blktrace_api.h12
4 files changed, 40 insertions, 13 deletions
diff --git a/block/blktrace.c b/block/blktrace.c
index 9b4da4ae3c7d..568588cd16b2 100644
--- a/block/blktrace.c
+++ b/block/blktrace.c
@@ -235,7 +235,7 @@ static void blk_trace_cleanup(struct blk_trace *bt)
235 kfree(bt); 235 kfree(bt);
236} 236}
237 237
238static int blk_trace_remove(struct request_queue *q) 238int blk_trace_remove(struct request_queue *q)
239{ 239{
240 struct blk_trace *bt; 240 struct blk_trace *bt;
241 241
@@ -249,6 +249,7 @@ static int blk_trace_remove(struct request_queue *q)
249 249
250 return 0; 250 return 0;
251} 251}
252EXPORT_SYMBOL_GPL(blk_trace_remove);
252 253
253static int blk_dropped_open(struct inode *inode, struct file *filp) 254static int blk_dropped_open(struct inode *inode, struct file *filp)
254{ 255{
@@ -316,18 +317,17 @@ static struct rchan_callbacks blk_relay_callbacks = {
316/* 317/*
317 * Setup everything required to start tracing 318 * Setup everything required to start tracing
318 */ 319 */
319int do_blk_trace_setup(struct request_queue *q, struct block_device *bdev, 320int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
320 struct blk_user_trace_setup *buts) 321 struct blk_user_trace_setup *buts)
321{ 322{
322 struct blk_trace *old_bt, *bt = NULL; 323 struct blk_trace *old_bt, *bt = NULL;
323 struct dentry *dir = NULL; 324 struct dentry *dir = NULL;
324 char b[BDEVNAME_SIZE];
325 int ret, i; 325 int ret, i;
326 326
327 if (!buts->buf_size || !buts->buf_nr) 327 if (!buts->buf_size || !buts->buf_nr)
328 return -EINVAL; 328 return -EINVAL;
329 329
330 strcpy(buts->name, bdevname(bdev, b)); 330 strcpy(buts->name, name);
331 331
332 /* 332 /*
333 * some device names have larger paths - convert the slashes 333 * some device names have larger paths - convert the slashes
@@ -352,7 +352,7 @@ int do_blk_trace_setup(struct request_queue *q, struct block_device *bdev,
352 goto err; 352 goto err;
353 353
354 bt->dir = dir; 354 bt->dir = dir;
355 bt->dev = bdev->bd_dev; 355 bt->dev = dev;
356 atomic_set(&bt->dropped, 0); 356 atomic_set(&bt->dropped, 0);
357 357
358 ret = -EIO; 358 ret = -EIO;
@@ -399,8 +399,8 @@ err:
399 return ret; 399 return ret;
400} 400}
401 401
402static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, 402int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
403 char __user *arg) 403 char __user *arg)
404{ 404{
405 struct blk_user_trace_setup buts; 405 struct blk_user_trace_setup buts;
406 int ret; 406 int ret;
@@ -409,7 +409,7 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev,
409 if (ret) 409 if (ret)
410 return -EFAULT; 410 return -EFAULT;
411 411
412 ret = do_blk_trace_setup(q, bdev, &buts); 412 ret = do_blk_trace_setup(q, name, dev, &buts);
413 if (ret) 413 if (ret)
414 return ret; 414 return ret;
415 415
@@ -418,8 +418,9 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev,
418 418
419 return 0; 419 return 0;
420} 420}
421EXPORT_SYMBOL_GPL(blk_trace_setup);
421 422
422static int blk_trace_startstop(struct request_queue *q, int start) 423int blk_trace_startstop(struct request_queue *q, int start)
423{ 424{
424 struct blk_trace *bt; 425 struct blk_trace *bt;
425 int ret; 426 int ret;
@@ -452,6 +453,7 @@ static int blk_trace_startstop(struct request_queue *q, int start)
452 453
453 return ret; 454 return ret;
454} 455}
456EXPORT_SYMBOL_GPL(blk_trace_startstop);
455 457
456/** 458/**
457 * blk_trace_ioctl: - handle the ioctls associated with tracing 459 * blk_trace_ioctl: - handle the ioctls associated with tracing
@@ -464,6 +466,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
464{ 466{
465 struct request_queue *q; 467 struct request_queue *q;
466 int ret, start = 0; 468 int ret, start = 0;
469 char b[BDEVNAME_SIZE];
467 470
468 q = bdev_get_queue(bdev); 471 q = bdev_get_queue(bdev);
469 if (!q) 472 if (!q)
@@ -473,7 +476,8 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
473 476
474 switch (cmd) { 477 switch (cmd) {
475 case BLKTRACESETUP: 478 case BLKTRACESETUP:
476 ret = blk_trace_setup(q, bdev, arg); 479 strcpy(b, bdevname(bdev, b));
480 ret = blk_trace_setup(q, b, bdev->bd_dev, arg);
477 break; 481 break;
478 case BLKTRACESTART: 482 case BLKTRACESTART:
479 start = 1; 483 start = 1;
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index cae0a852619e..b73373216b0e 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -545,6 +545,7 @@ static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg)
545 struct blk_user_trace_setup buts; 545 struct blk_user_trace_setup buts;
546 struct compat_blk_user_trace_setup cbuts; 546 struct compat_blk_user_trace_setup cbuts;
547 struct request_queue *q; 547 struct request_queue *q;
548 char b[BDEVNAME_SIZE];
548 int ret; 549 int ret;
549 550
550 q = bdev_get_queue(bdev); 551 q = bdev_get_queue(bdev);
@@ -554,6 +555,8 @@ static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg)
554 if (copy_from_user(&cbuts, arg, sizeof(cbuts))) 555 if (copy_from_user(&cbuts, arg, sizeof(cbuts)))
555 return -EFAULT; 556 return -EFAULT;
556 557
558 strcpy(b, bdevname(bdev, b));
559
557 buts = (struct blk_user_trace_setup) { 560 buts = (struct blk_user_trace_setup) {
558 .act_mask = cbuts.act_mask, 561 .act_mask = cbuts.act_mask,
559 .buf_size = cbuts.buf_size, 562 .buf_size = cbuts.buf_size,
@@ -565,7 +568,7 @@ static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg)
565 memcpy(&buts.name, &cbuts.name, 32); 568 memcpy(&buts.name, &cbuts.name, 32);
566 569
567 mutex_lock(&bdev->bd_mutex); 570 mutex_lock(&bdev->bd_mutex);
568 ret = do_blk_trace_setup(q, bdev, &buts); 571 ret = do_blk_trace_setup(q, b, bdev->bd_dev, &buts);
569 mutex_unlock(&bdev->bd_mutex); 572 mutex_unlock(&bdev->bd_mutex);
570 if (ret) 573 if (ret)
571 return ret; 574 return ret;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 17216b76efdc..aba28f335b88 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -48,6 +48,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */
48#include <linux/blkdev.h> 48#include <linux/blkdev.h>
49#include <linux/delay.h> 49#include <linux/delay.h>
50#include <linux/scatterlist.h> 50#include <linux/scatterlist.h>
51#include <linux/blktrace_api.h>
51 52
52#include "scsi.h" 53#include "scsi.h"
53#include <scsi/scsi_dbg.h> 54#include <scsi/scsi_dbg.h>
@@ -1067,6 +1068,17 @@ sg_ioctl(struct inode *inode, struct file *filp,
1067 case BLKSECTGET: 1068 case BLKSECTGET:
1068 return put_user(sdp->device->request_queue->max_sectors * 512, 1069 return put_user(sdp->device->request_queue->max_sectors * 512,
1069 ip); 1070 ip);
1071 case BLKTRACESETUP:
1072 return blk_trace_setup(sdp->device->request_queue,
1073 sdp->disk->disk_name,
1074 sdp->device->sdev_gendev.devt,
1075 (char *)arg);
1076 case BLKTRACESTART:
1077 return blk_trace_startstop(sdp->device->request_queue, 1);
1078 case BLKTRACESTOP:
1079 return blk_trace_startstop(sdp->device->request_queue, 0);
1080 case BLKTRACETEARDOWN:
1081 return blk_trace_remove(sdp->device->request_queue);
1070 default: 1082 default:
1071 if (read_only) 1083 if (read_only)
1072 return -EPERM; /* don't know so take safe approach */ 1084 return -EPERM; /* don't know so take safe approach */
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
index 7e11d23ac36a..06dadba349ac 100644
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -148,7 +148,7 @@ extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *);
148extern void blk_trace_shutdown(struct request_queue *); 148extern void blk_trace_shutdown(struct request_queue *);
149extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *); 149extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *);
150extern int do_blk_trace_setup(struct request_queue *q, 150extern int do_blk_trace_setup(struct request_queue *q,
151 struct block_device *bdev, struct blk_user_trace_setup *buts); 151 char *name, dev_t dev, struct blk_user_trace_setup *buts);
152 152
153 153
154/** 154/**
@@ -282,6 +282,11 @@ static inline void blk_add_trace_remap(struct request_queue *q, struct bio *bio,
282 __blk_add_trace(bt, from, bio->bi_size, bio->bi_rw, BLK_TA_REMAP, !bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r); 282 __blk_add_trace(bt, from, bio->bi_size, bio->bi_rw, BLK_TA_REMAP, !bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r);
283} 283}
284 284
285extern int blk_trace_setup(request_queue_t *q, char *name, dev_t dev,
286 char __user *arg);
287extern int blk_trace_startstop(request_queue_t *q, int start);
288extern int blk_trace_remove(request_queue_t *q);
289
285#else /* !CONFIG_BLK_DEV_IO_TRACE */ 290#else /* !CONFIG_BLK_DEV_IO_TRACE */
286#define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY) 291#define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY)
287#define blk_trace_shutdown(q) do { } while (0) 292#define blk_trace_shutdown(q) do { } while (0)
@@ -290,7 +295,10 @@ static inline void blk_add_trace_remap(struct request_queue *q, struct bio *bio,
290#define blk_add_trace_generic(q, rq, rw, what) do { } while (0) 295#define blk_add_trace_generic(q, rq, rw, what) do { } while (0)
291#define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) 296#define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0)
292#define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) 297#define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0)
293#define do_blk_trace_setup(q, bdev, buts) (-ENOTTY) 298#define do_blk_trace_setup(q, name, dev, buts) (-ENOTTY)
299#define blk_trace_setup(q, name, dev, arg) (-ENOTTY)
300#define blk_trace_startstop(q, start) (-ENOTTY)
301#define blk_trace_remove(q) (-ENOTTY)
294#endif /* CONFIG_BLK_DEV_IO_TRACE */ 302#endif /* CONFIG_BLK_DEV_IO_TRACE */
295#endif /* __KERNEL__ */ 303#endif /* __KERNEL__ */
296#endif 304#endif