diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/blktrace.c | 54 | ||||
-rw-r--r-- | block/compat_ioctl.c | 54 |
2 files changed, 88 insertions, 20 deletions
diff --git a/block/blktrace.c b/block/blktrace.c index 20fa034ea4a2..775471ef84a5 100644 --- a/block/blktrace.c +++ b/block/blktrace.c | |||
@@ -312,33 +312,26 @@ static struct rchan_callbacks blk_relay_callbacks = { | |||
312 | /* | 312 | /* |
313 | * Setup everything required to start tracing | 313 | * Setup everything required to start tracing |
314 | */ | 314 | */ |
315 | static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, | 315 | int do_blk_trace_setup(struct request_queue *q, struct block_device *bdev, |
316 | char __user *arg) | 316 | struct blk_user_trace_setup *buts) |
317 | { | 317 | { |
318 | struct blk_user_trace_setup buts; | ||
319 | struct blk_trace *old_bt, *bt = NULL; | 318 | struct blk_trace *old_bt, *bt = NULL; |
320 | struct dentry *dir = NULL; | 319 | struct dentry *dir = NULL; |
321 | char b[BDEVNAME_SIZE]; | 320 | char b[BDEVNAME_SIZE]; |
322 | int ret, i; | 321 | int ret, i; |
323 | 322 | ||
324 | if (copy_from_user(&buts, arg, sizeof(buts))) | 323 | if (!buts->buf_size || !buts->buf_nr) |
325 | return -EFAULT; | ||
326 | |||
327 | if (!buts.buf_size || !buts.buf_nr) | ||
328 | return -EINVAL; | 324 | return -EINVAL; |
329 | 325 | ||
330 | strcpy(buts.name, bdevname(bdev, b)); | 326 | strcpy(buts->name, bdevname(bdev, b)); |
331 | 327 | ||
332 | /* | 328 | /* |
333 | * some device names have larger paths - convert the slashes | 329 | * some device names have larger paths - convert the slashes |
334 | * to underscores for this to work as expected | 330 | * to underscores for this to work as expected |
335 | */ | 331 | */ |
336 | for (i = 0; i < strlen(buts.name); i++) | 332 | for (i = 0; i < strlen(buts->name); i++) |
337 | if (buts.name[i] == '/') | 333 | if (buts->name[i] == '/') |
338 | buts.name[i] = '_'; | 334 | buts->name[i] = '_'; |
339 | |||
340 | if (copy_to_user(arg, &buts, sizeof(buts))) | ||
341 | return -EFAULT; | ||
342 | 335 | ||
343 | ret = -ENOMEM; | 336 | ret = -ENOMEM; |
344 | bt = kzalloc(sizeof(*bt), GFP_KERNEL); | 337 | bt = kzalloc(sizeof(*bt), GFP_KERNEL); |
@@ -350,7 +343,7 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, | |||
350 | goto err; | 343 | goto err; |
351 | 344 | ||
352 | ret = -ENOENT; | 345 | ret = -ENOENT; |
353 | dir = blk_create_tree(buts.name); | 346 | dir = blk_create_tree(buts->name); |
354 | if (!dir) | 347 | if (!dir) |
355 | goto err; | 348 | goto err; |
356 | 349 | ||
@@ -363,20 +356,21 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, | |||
363 | if (!bt->dropped_file) | 356 | if (!bt->dropped_file) |
364 | goto err; | 357 | goto err; |
365 | 358 | ||
366 | bt->rchan = relay_open("trace", dir, buts.buf_size, buts.buf_nr, &blk_relay_callbacks, bt); | 359 | bt->rchan = relay_open("trace", dir, buts->buf_size, |
360 | buts->buf_nr, &blk_relay_callbacks, bt); | ||
367 | if (!bt->rchan) | 361 | if (!bt->rchan) |
368 | goto err; | 362 | goto err; |
369 | 363 | ||
370 | bt->act_mask = buts.act_mask; | 364 | bt->act_mask = buts->act_mask; |
371 | if (!bt->act_mask) | 365 | if (!bt->act_mask) |
372 | bt->act_mask = (u16) -1; | 366 | bt->act_mask = (u16) -1; |
373 | 367 | ||
374 | bt->start_lba = buts.start_lba; | 368 | bt->start_lba = buts->start_lba; |
375 | bt->end_lba = buts.end_lba; | 369 | bt->end_lba = buts->end_lba; |
376 | if (!bt->end_lba) | 370 | if (!bt->end_lba) |
377 | bt->end_lba = -1ULL; | 371 | bt->end_lba = -1ULL; |
378 | 372 | ||
379 | bt->pid = buts.pid; | 373 | bt->pid = buts->pid; |
380 | bt->trace_state = Blktrace_setup; | 374 | bt->trace_state = Blktrace_setup; |
381 | 375 | ||
382 | ret = -EBUSY; | 376 | ret = -EBUSY; |
@@ -401,6 +395,26 @@ err: | |||
401 | return ret; | 395 | return ret; |
402 | } | 396 | } |
403 | 397 | ||
398 | static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, | ||
399 | char __user *arg) | ||
400 | { | ||
401 | struct blk_user_trace_setup buts; | ||
402 | int ret; | ||
403 | |||
404 | ret = copy_from_user(&buts, arg, sizeof(buts)); | ||
405 | if (ret) | ||
406 | return -EFAULT; | ||
407 | |||
408 | ret = do_blk_trace_setup(q, bdev, &buts); | ||
409 | if (ret) | ||
410 | return ret; | ||
411 | |||
412 | if (copy_to_user(arg, &buts, sizeof(buts))) | ||
413 | return -EFAULT; | ||
414 | |||
415 | return 0; | ||
416 | } | ||
417 | |||
404 | static int blk_trace_startstop(struct request_queue *q, int start) | 418 | static int blk_trace_startstop(struct request_queue *q, int start) |
405 | { | 419 | { |
406 | struct blk_trace *bt; | 420 | struct blk_trace *bt; |
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 500cc9e761c1..219b7e76e8ad 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c | |||
@@ -40,6 +40,53 @@ static int compat_put_u64(unsigned long arg, u64 val) | |||
40 | #define BLKBSZSET_32 _IOW(0x12, 113, int) | 40 | #define BLKBSZSET_32 _IOW(0x12, 113, int) |
41 | #define BLKGETSIZE64_32 _IOR(0x12, 114, int) | 41 | #define BLKGETSIZE64_32 _IOR(0x12, 114, int) |
42 | 42 | ||
43 | struct compat_blk_user_trace_setup { | ||
44 | char name[32]; | ||
45 | u16 act_mask; | ||
46 | u32 buf_size; | ||
47 | u32 buf_nr; | ||
48 | compat_u64 start_lba; | ||
49 | compat_u64 end_lba; | ||
50 | u32 pid; | ||
51 | }; | ||
52 | #define BLKTRACESETUP32 _IOWR(0x12, 115, struct compat_blk_user_trace_setup) | ||
53 | |||
54 | static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg) | ||
55 | { | ||
56 | struct blk_user_trace_setup buts; | ||
57 | struct compat_blk_user_trace_setup cbuts; | ||
58 | struct request_queue *q; | ||
59 | int ret; | ||
60 | |||
61 | q = bdev_get_queue(bdev); | ||
62 | if (!q) | ||
63 | return -ENXIO; | ||
64 | |||
65 | if (copy_from_user(&cbuts, arg, sizeof(cbuts))) | ||
66 | return -EFAULT; | ||
67 | |||
68 | buts = (struct blk_user_trace_setup) { | ||
69 | .act_mask = cbuts.act_mask, | ||
70 | .buf_size = cbuts.buf_size, | ||
71 | .buf_nr = cbuts.buf_nr, | ||
72 | .start_lba = cbuts.start_lba, | ||
73 | .end_lba = cbuts.end_lba, | ||
74 | .pid = cbuts.pid, | ||
75 | }; | ||
76 | memcpy(&buts.name, &cbuts.name, 32); | ||
77 | |||
78 | mutex_lock(&bdev->bd_mutex); | ||
79 | ret = do_blk_trace_setup(q, bdev, &buts); | ||
80 | mutex_unlock(&bdev->bd_mutex); | ||
81 | if (ret) | ||
82 | return ret; | ||
83 | |||
84 | if (copy_to_user(arg, &buts.name, 32)) | ||
85 | return -EFAULT; | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
43 | static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, | 90 | static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, |
44 | struct gendisk *disk, unsigned cmd, unsigned long arg) | 91 | struct gendisk *disk, unsigned cmd, unsigned long arg) |
45 | { | 92 | { |
@@ -197,6 +244,13 @@ static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file, | |||
197 | 244 | ||
198 | case BLKGETSIZE64_32: | 245 | case BLKGETSIZE64_32: |
199 | return compat_put_u64(arg, bdev->bd_inode->i_size); | 246 | return compat_put_u64(arg, bdev->bd_inode->i_size); |
247 | |||
248 | case BLKTRACESETUP32: | ||
249 | return compat_blk_trace_setup(bdev, compat_ptr(arg)); | ||
250 | case BLKTRACESTART: /* compatible */ | ||
251 | case BLKTRACESTOP: /* compatible */ | ||
252 | case BLKTRACETEARDOWN: /* compatible */ | ||
253 | return blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); | ||
200 | } | 254 | } |
201 | return -ENOIOCTLCMD; | 255 | return -ENOIOCTLCMD; |
202 | } | 256 | } |