/*
* Setup everything required to start tracing
*/
-static int blk_trace_setup(struct request_queue *q, struct block_device *bdev,
- char __user *arg)
+int do_blk_trace_setup(struct request_queue *q, struct block_device *bdev,
+ struct blk_user_trace_setup *buts)
{
- 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 (copy_from_user(&buts, arg, sizeof(buts)))
- return -EFAULT;
-
- if (!buts.buf_size || !buts.buf_nr)
+ if (!buts->buf_size || !buts->buf_nr)
return -EINVAL;
- strcpy(buts.name, bdevname(bdev, b));
+ strcpy(buts->name, bdevname(bdev, b));
/*
* some device names have larger paths - convert the slashes
* to underscores for this to work as expected
*/
- for (i = 0; i < strlen(buts.name); i++)
- if (buts.name[i] == '/')
- buts.name[i] = '_';
-
- if (copy_to_user(arg, &buts, sizeof(buts)))
- return -EFAULT;
+ for (i = 0; i < strlen(buts->name); i++)
+ if (buts->name[i] == '/')
+ buts->name[i] = '_';
ret = -ENOMEM;
bt = kzalloc(sizeof(*bt), GFP_KERNEL);
goto err;
ret = -ENOENT;
- dir = blk_create_tree(buts.name);
+ dir = blk_create_tree(buts->name);
if (!dir)
goto err;
if (!bt->dropped_file)
goto err;
- bt->rchan = relay_open("trace", dir, buts.buf_size, buts.buf_nr, &blk_relay_callbacks, bt);
+ bt->rchan = relay_open("trace", dir, buts->buf_size,
+ buts->buf_nr, &blk_relay_callbacks, bt);
if (!bt->rchan)
goto err;
- bt->act_mask = buts.act_mask;
+ bt->act_mask = buts->act_mask;
if (!bt->act_mask)
bt->act_mask = (u16) -1;
- bt->start_lba = buts.start_lba;
- bt->end_lba = buts.end_lba;
+ bt->start_lba = buts->start_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;
ret = -EBUSY;
return ret;
}
+static int blk_trace_setup(struct request_queue *q, struct block_device *bdev,
+ char __user *arg)
+{
+ struct blk_user_trace_setup buts;
+ int ret;
+
+ ret = copy_from_user(&buts, arg, sizeof(buts));
+ if (ret)
+ return -EFAULT;
+
+ ret = do_blk_trace_setup(q, bdev, &buts);
+ if (ret)
+ return ret;
+
+ if (copy_to_user(arg, &buts, sizeof(buts)))
+ return -EFAULT;
+
+ return 0;
+}
+
static int blk_trace_startstop(struct request_queue *q, int start)
{
struct blk_trace *bt;
#define BLKBSZSET_32 _IOW(0x12, 113, int)
#define BLKGETSIZE64_32 _IOR(0x12, 114, int)
+struct compat_blk_user_trace_setup {
+ char name[32];
+ u16 act_mask;
+ u32 buf_size;
+ u32 buf_nr;
+ compat_u64 start_lba;
+ compat_u64 end_lba;
+ u32 pid;
+};
+#define BLKTRACESETUP32 _IOWR(0x12, 115, struct compat_blk_user_trace_setup)
+
+static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg)
+{
+ struct blk_user_trace_setup buts;
+ struct compat_blk_user_trace_setup cbuts;
+ struct request_queue *q;
+ int ret;
+
+ q = bdev_get_queue(bdev);
+ if (!q)
+ return -ENXIO;
+
+ if (copy_from_user(&cbuts, arg, sizeof(cbuts)))
+ return -EFAULT;
+
+ buts = (struct blk_user_trace_setup) {
+ .act_mask = cbuts.act_mask,
+ .buf_size = cbuts.buf_size,
+ .buf_nr = cbuts.buf_nr,
+ .start_lba = cbuts.start_lba,
+ .end_lba = cbuts.end_lba,
+ .pid = cbuts.pid,
+ };
+ memcpy(&buts.name, &cbuts.name, 32);
+
+ mutex_lock(&bdev->bd_mutex);
+ ret = do_blk_trace_setup(q, bdev, &buts);
+ mutex_unlock(&bdev->bd_mutex);
+ if (ret)
+ return ret;
+
+ if (copy_to_user(arg, &buts.name, 32))
+ return -EFAULT;
+
+ return 0;
+}
+
static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
struct gendisk *disk, unsigned cmd, unsigned long arg)
{
case BLKGETSIZE64_32:
return compat_put_u64(arg, bdev->bd_inode->i_size);
+
+ case BLKTRACESETUP32:
+ return compat_blk_trace_setup(bdev, compat_ptr(arg));
+ case BLKTRACESTART: /* compatible */
+ case BLKTRACESTOP: /* compatible */
+ case BLKTRACETEARDOWN: /* compatible */
+ return blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
}
return -ENOIOCTLCMD;
}
#include <linux/i2c-dev.h>
#include <linux/wireless.h>
#include <linux/atalk.h>
-#include <linux/blktrace_api.h>
#include <linux/loop.h>
#include <net/bluetooth/bluetooth.h>
/* 0x00 */
COMPATIBLE_IOCTL(FIBMAP)
COMPATIBLE_IOCTL(FIGETBSZ)
-/* 0x12 */
-#ifdef CONFIG_BLOCK
-COMPATIBLE_IOCTL(BLKTRACESTART)
-COMPATIBLE_IOCTL(BLKTRACESTOP)
-COMPATIBLE_IOCTL(BLKTRACESETUP)
-COMPATIBLE_IOCTL(BLKTRACETEARDOWN)
-#endif
/* RAID */
COMPATIBLE_IOCTL(RAID_VERSION)
COMPATIBLE_IOCTL(GET_ARRAY_INFO)
u32 pid;
};
+#ifdef __KERNEL__
#if defined(CONFIG_BLK_DEV_IO_TRACE)
extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *);
extern void blk_trace_shutdown(struct request_queue *);
extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *);
+extern int do_blk_trace_setup(struct request_queue *q,
+ struct block_device *bdev, struct blk_user_trace_setup *buts);
+
/**
* blk_add_trace_rq - Add a trace for a request oriented action
#define blk_add_trace_generic(q, rq, rw, what) do { } while (0)
#define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0)
#define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0)
+#define do_blk_trace_setup(q, bdev, buts) do {} while (0)
#endif /* CONFIG_BLK_DEV_IO_TRACE */
-
+#endif /* __KERNEL__ */
#endif