Commit d0deef5b authored by Shawn Du's avatar Shawn Du Committed by Ingo Molnar

blktrace: support per-partition tracing

Though one can specify '-d /dev/sda1' when using blktrace, it still
traces the whole sda.

To support per-partition tracing, when we start tracing, we initialize
bt->start_lba and bt->end_lba to the start and end sector of that
partition.

Note some actions are per device, thus we don't filter 0-sector events.

The original patch and discussion can be found here:
	http://marc.info/?l=linux-btrace&m=122949374214540&w=2Signed-off-by: default avatarShawn Du <duyuyang@gmail.com>
Signed-off-by: default avatarLi Zefan <lizf@cn.fujitsu.com>
Acked-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
LKML-Reference: <49E42620.4050701@cn.fujitsu.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 9cfe06f8
...@@ -568,7 +568,7 @@ static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg) ...@@ -568,7 +568,7 @@ static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg)
memcpy(&buts.name, &cbuts.name, 32); memcpy(&buts.name, &cbuts.name, 32);
mutex_lock(&bdev->bd_mutex); mutex_lock(&bdev->bd_mutex);
ret = do_blk_trace_setup(q, b, bdev->bd_dev, &buts); ret = do_blk_trace_setup(q, b, bdev->bd_dev, bdev, &buts);
mutex_unlock(&bdev->bd_mutex); mutex_unlock(&bdev->bd_mutex);
if (ret) if (ret)
return ret; return ret;
......
...@@ -1065,6 +1065,7 @@ sg_ioctl(struct inode *inode, struct file *filp, ...@@ -1065,6 +1065,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
return blk_trace_setup(sdp->device->request_queue, return blk_trace_setup(sdp->device->request_queue,
sdp->disk->disk_name, sdp->disk->disk_name,
MKDEV(SCSI_GENERIC_MAJOR, sdp->index), MKDEV(SCSI_GENERIC_MAJOR, sdp->index),
NULL,
(char *)arg); (char *)arg);
case BLKTRACESTART: case BLKTRACESTART:
return blk_trace_startstop(sdp->device->request_queue, 1); return blk_trace_startstop(sdp->device->request_queue, 1);
......
...@@ -165,8 +165,9 @@ struct blk_trace { ...@@ -165,8 +165,9 @@ struct blk_trace {
extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *); extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *);
extern void blk_trace_shutdown(struct request_queue *); extern void blk_trace_shutdown(struct request_queue *);
extern int do_blk_trace_setup(struct request_queue *q, extern int do_blk_trace_setup(struct request_queue *q, char *name,
char *name, dev_t dev, struct blk_user_trace_setup *buts); dev_t dev, struct block_device *bdev,
struct blk_user_trace_setup *buts);
extern void __trace_note_message(struct blk_trace *, const char *fmt, ...); extern void __trace_note_message(struct blk_trace *, const char *fmt, ...);
/** /**
...@@ -193,6 +194,7 @@ extern void __trace_note_message(struct blk_trace *, const char *fmt, ...); ...@@ -193,6 +194,7 @@ extern void __trace_note_message(struct blk_trace *, const char *fmt, ...);
extern void blk_add_driver_data(struct request_queue *q, struct request *rq, extern void blk_add_driver_data(struct request_queue *q, struct request *rq,
void *data, size_t len); void *data, size_t len);
extern int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, extern int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
struct block_device *bdev,
char __user *arg); char __user *arg);
extern int blk_trace_startstop(struct request_queue *q, int start); extern int blk_trace_startstop(struct request_queue *q, int start);
extern int blk_trace_remove(struct request_queue *q); extern int blk_trace_remove(struct request_queue *q);
...@@ -200,15 +202,15 @@ extern int blk_trace_remove(struct request_queue *q); ...@@ -200,15 +202,15 @@ extern int blk_trace_remove(struct request_queue *q);
extern struct attribute_group blk_trace_attr_group; extern struct attribute_group blk_trace_attr_group;
#else /* !CONFIG_BLK_DEV_IO_TRACE */ #else /* !CONFIG_BLK_DEV_IO_TRACE */
#define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY) # define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY)
#define blk_trace_shutdown(q) do { } while (0) # define blk_trace_shutdown(q) do { } while (0)
#define do_blk_trace_setup(q, name, dev, buts) (-ENOTTY) # define do_blk_trace_setup(q, name, dev, bdev, buts) (-ENOTTY)
#define blk_add_driver_data(q, rq, data, len) do {} while (0) # define blk_add_driver_data(q, rq, data, len) do {} while (0)
#define blk_trace_setup(q, name, dev, arg) (-ENOTTY) # define blk_trace_setup(q, name, dev, bdev, arg) (-ENOTTY)
#define blk_trace_startstop(q, start) (-ENOTTY) # define blk_trace_startstop(q, start) (-ENOTTY)
#define blk_trace_remove(q) (-ENOTTY) # define blk_trace_remove(q) (-ENOTTY)
#define blk_add_trace_msg(q, fmt, ...) do { } while (0) # define blk_add_trace_msg(q, fmt, ...) do { } while (0)
#endif /* CONFIG_BLK_DEV_IO_TRACE */ #endif /* CONFIG_BLK_DEV_IO_TRACE */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif #endif
...@@ -147,7 +147,7 @@ static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector, ...@@ -147,7 +147,7 @@ static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector,
{ {
if (((bt->act_mask << BLK_TC_SHIFT) & what) == 0) if (((bt->act_mask << BLK_TC_SHIFT) & what) == 0)
return 1; return 1;
if (sector < bt->start_lba || sector > bt->end_lba) if (sector && (sector < bt->start_lba || sector > bt->end_lba))
return 1; return 1;
if (bt->pid && pid != bt->pid) if (bt->pid && pid != bt->pid)
return 1; return 1;
...@@ -192,7 +192,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, ...@@ -192,7 +192,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
what |= MASK_TC_BIT(rw, DISCARD); what |= MASK_TC_BIT(rw, DISCARD);
pid = tsk->pid; pid = tsk->pid;
if (unlikely(act_log_check(bt, what, sector, pid))) if (act_log_check(bt, what, sector, pid))
return; return;
cpu = raw_smp_processor_id(); cpu = raw_smp_processor_id();
...@@ -407,11 +407,13 @@ static struct rchan_callbacks blk_relay_callbacks = { ...@@ -407,11 +407,13 @@ static struct rchan_callbacks blk_relay_callbacks = {
* Setup everything required to start tracing * Setup everything required to start tracing
*/ */
int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
struct block_device *bdev,
struct blk_user_trace_setup *buts) struct blk_user_trace_setup *buts)
{ {
struct blk_trace *old_bt, *bt = NULL; struct blk_trace *old_bt, *bt = NULL;
struct dentry *dir = NULL; struct dentry *dir = NULL;
int ret, i; int ret, i;
struct hd_struct *part = NULL;
if (!buts->buf_size || !buts->buf_nr) if (!buts->buf_size || !buts->buf_nr)
return -EINVAL; return -EINVAL;
...@@ -480,10 +482,20 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, ...@@ -480,10 +482,20 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
if (!bt->act_mask) if (!bt->act_mask)
bt->act_mask = (u16) -1; bt->act_mask = (u16) -1;
if (bdev)
part = bdev->bd_part;
if (part) {
bt->start_lba = part->start_sect;
bt->end_lba = part->start_sect + part->nr_sects;
} else
bt->end_lba = -1ULL;
/* overwrite with user settings */
if (buts->start_lba)
bt->start_lba = buts->start_lba; bt->start_lba = buts->start_lba;
if (buts->end_lba)
bt->end_lba = buts->end_lba; bt->end_lba = buts->end_lba;
if (!bt->end_lba)
bt->end_lba = -1ULL;
bt->pid = buts->pid; bt->pid = buts->pid;
bt->trace_state = Blktrace_setup; bt->trace_state = Blktrace_setup;
...@@ -505,6 +517,7 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, ...@@ -505,6 +517,7 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
} }
int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
struct block_device *bdev,
char __user *arg) char __user *arg)
{ {
struct blk_user_trace_setup buts; struct blk_user_trace_setup buts;
...@@ -514,7 +527,7 @@ int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, ...@@ -514,7 +527,7 @@ int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
if (ret) if (ret)
return -EFAULT; return -EFAULT;
ret = do_blk_trace_setup(q, name, dev, &buts); ret = do_blk_trace_setup(q, name, dev, bdev, &buts);
if (ret) if (ret)
return ret; return ret;
...@@ -582,7 +595,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) ...@@ -582,7 +595,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
switch (cmd) { switch (cmd) {
case BLKTRACESETUP: case BLKTRACESETUP:
bdevname(bdev, b); bdevname(bdev, b);
ret = blk_trace_setup(q, b, bdev->bd_dev, arg); ret = blk_trace_setup(q, b, bdev->bd_dev, bdev, arg);
break; break;
case BLKTRACESTART: case BLKTRACESTART:
start = 1; start = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment