|
@@ -312,33 +312,26 @@ static struct rchan_callbacks blk_relay_callbacks = {
|
|
/*
|
|
/*
|
|
* Setup everything required to start tracing
|
|
* 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 blk_trace *old_bt, *bt = NULL;
|
|
struct dentry *dir = NULL;
|
|
struct dentry *dir = NULL;
|
|
char b[BDEVNAME_SIZE];
|
|
char b[BDEVNAME_SIZE];
|
|
int ret, i;
|
|
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;
|
|
return -EINVAL;
|
|
|
|
|
|
- strcpy(buts.name, bdevname(bdev, b));
|
|
|
|
|
|
+ strcpy(buts->name, bdevname(bdev, b));
|
|
|
|
|
|
/*
|
|
/*
|
|
* some device names have larger paths - convert the slashes
|
|
* some device names have larger paths - convert the slashes
|
|
* to underscores for this to work as expected
|
|
* 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;
|
|
ret = -ENOMEM;
|
|
bt = kzalloc(sizeof(*bt), GFP_KERNEL);
|
|
bt = kzalloc(sizeof(*bt), GFP_KERNEL);
|
|
@@ -350,7 +343,7 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev,
|
|
goto err;
|
|
goto err;
|
|
|
|
|
|
ret = -ENOENT;
|
|
ret = -ENOENT;
|
|
- dir = blk_create_tree(buts.name);
|
|
|
|
|
|
+ dir = blk_create_tree(buts->name);
|
|
if (!dir)
|
|
if (!dir)
|
|
goto err;
|
|
goto err;
|
|
|
|
|
|
@@ -363,20 +356,21 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev,
|
|
if (!bt->dropped_file)
|
|
if (!bt->dropped_file)
|
|
goto err;
|
|
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)
|
|
if (!bt->rchan)
|
|
goto err;
|
|
goto err;
|
|
|
|
|
|
- bt->act_mask = buts.act_mask;
|
|
|
|
|
|
+ bt->act_mask = buts->act_mask;
|
|
if (!bt->act_mask)
|
|
if (!bt->act_mask)
|
|
bt->act_mask = (u16) -1;
|
|
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)
|
|
if (!bt->end_lba)
|
|
bt->end_lba = -1ULL;
|
|
bt->end_lba = -1ULL;
|
|
|
|
|
|
- bt->pid = buts.pid;
|
|
|
|
|
|
+ bt->pid = buts->pid;
|
|
bt->trace_state = Blktrace_setup;
|
|
bt->trace_state = Blktrace_setup;
|
|
|
|
|
|
ret = -EBUSY;
|
|
ret = -EBUSY;
|
|
@@ -401,6 +395,26 @@ err:
|
|
return ret;
|
|
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)
|
|
static int blk_trace_startstop(struct request_queue *q, int start)
|
|
{
|
|
{
|
|
struct blk_trace *bt;
|
|
struct blk_trace *bt;
|