File: [Development] / linux-2.6-xfs / drivers / block / Attic / blktrace.c (download)
Revision 1.1, Mon Aug 29 15:19:41 2005 UTC (12 years, 1 month ago) by nathans.longdrop.melbourne.sgi.com
Branch: MAIN
Merge relayfs and the initial block device tracing patch from Jens.
Merge of 2.6.x-xfs-melb:linux:23656a by kenmcd.
|
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/blkdev.h>
#include <linux/blktrace.h>
#include <asm/uaccess.h>
void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
int rw, u32 what, int error, int pdu_len, char *pdu_data)
{
struct blk_io_trace t;
unsigned long flags;
if (rw & (1 << BIO_RW_BARRIER))
what |= BLK_TC_ACT(BLK_TC_BARRIER);
if (rw & (1 << BIO_RW_SYNC))
what |= BLK_TC_ACT(BLK_TC_SYNC);
if (rw & WRITE)
what |= BLK_TC_ACT(BLK_TC_WRITE);
else
what |= BLK_TC_ACT(BLK_TC_READ);
if (((bt->act_mask << BLK_TC_SHIFT) & what) == 0)
return;
t.magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION;
t.sequence = atomic_add_return(1, &bt->sequence);
t.time = sched_clock();
t.sector = sector;
t.bytes = bytes;
t.action = what;
t.pid = current->pid;
t.error = error;
t.pdu_len = pdu_len;
local_irq_save(flags);
__relay_write(bt->rchan, &t, sizeof(t));
if (pdu_len)
__relay_write(bt->rchan, pdu_data, pdu_len);
local_irq_restore(flags);
}
int blk_stop_trace(struct block_device *bdev)
{
request_queue_t *q = bdev_get_queue(bdev);
struct blk_trace *bt = NULL;
int ret = -EINVAL;
if (!q)
return -ENXIO;
down(&bdev->bd_sem);
spin_lock_irq(q->queue_lock);
if (q->blk_trace) {
bt = q->blk_trace;
q->blk_trace = NULL;
ret = 0;
}
spin_unlock_irq(q->queue_lock);
up(&bdev->bd_sem);
if (bt) {
relay_close(bt->rchan);
kfree(bt);
}
return ret;
}
int blk_start_trace(struct block_device *bdev, char __user *arg)
{
request_queue_t *q = bdev_get_queue(bdev);
struct blk_user_trace_setup buts;
struct blk_trace *bt;
char b[BDEVNAME_SIZE];
int ret = 0;
if (!q)
return -ENXIO;
if (copy_from_user(&buts, arg, sizeof(buts)))
return -EFAULT;
if (!buts.buf_size || !buts.buf_nr)
return -EINVAL;
strcpy(buts.name, bdevname(bdev, b));
if (copy_to_user(arg, &buts, sizeof(buts)))
return -EFAULT;
down(&bdev->bd_sem);
ret = -EBUSY;
if (q->blk_trace)
goto err;
ret = -ENOMEM;
bt = kmalloc(sizeof(*bt), GFP_KERNEL);
if (!bt)
goto err;
atomic_set(&bt->sequence, 0);
bt->rchan = relay_open(bdevname(bdev, b), NULL, buts.buf_size,
buts.buf_nr, NULL);
ret = -EIO;
if (!bt->rchan)
goto err;
bt->act_mask = buts.act_mask;
if (!bt->act_mask)
bt->act_mask = (u16) -1;
spin_lock_irq(q->queue_lock);
q->blk_trace = bt;
spin_unlock_irq(q->queue_lock);
ret = 0;
err:
up(&bdev->bd_sem);
return ret;
}