diff options
author | Arnd Bergmann <arnd@arndb.de> | 2007-10-09 07:23:53 -0400 |
---|---|---|
committer | Jens Axboe <axboe@carl.home.kernel.dk> | 2007-10-10 03:26:00 -0400 |
commit | 171044d449611c6e5040b37210ff6aba47f33ee4 (patch) | |
tree | 74a380863b395f9db13f2da333e91cd817dc4970 | |
parent | 7199d4cdd8485f802df3e1bc131245c69009b9a4 (diff) |
compat_ioctl: handle blk_trace ioctls
blk_trace_setup is broken on x86_64 compat systems,
this makes the code work correctly on all 64 bit architectures
in compat mode.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | block/blktrace.c | 54 | ||||
-rw-r--r-- | block/compat_ioctl.c | 54 | ||||
-rw-r--r-- | fs/compat_ioctl.c | 8 | ||||
-rw-r--r-- | include/linux/blktrace_api.h | 7 |
4 files changed, 94 insertions, 29 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 | } |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 16d681c331f9..71065603a581 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -62,7 +62,6 @@ | |||
62 | #include <linux/i2c-dev.h> | 62 | #include <linux/i2c-dev.h> |
63 | #include <linux/wireless.h> | 63 | #include <linux/wireless.h> |
64 | #include <linux/atalk.h> | 64 | #include <linux/atalk.h> |
65 | #include <linux/blktrace_api.h> | ||
66 | #include <linux/loop.h> | 65 | #include <linux/loop.h> |
67 | 66 | ||
68 | #include <net/bluetooth/bluetooth.h> | 67 | #include <net/bluetooth/bluetooth.h> |
@@ -2477,13 +2476,6 @@ COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ | |||
2477 | /* 0x00 */ | 2476 | /* 0x00 */ |
2478 | COMPATIBLE_IOCTL(FIBMAP) | 2477 | COMPATIBLE_IOCTL(FIBMAP) |
2479 | COMPATIBLE_IOCTL(FIGETBSZ) | 2478 | COMPATIBLE_IOCTL(FIGETBSZ) |
2480 | /* 0x12 */ | ||
2481 | #ifdef CONFIG_BLOCK | ||
2482 | COMPATIBLE_IOCTL(BLKTRACESTART) | ||
2483 | COMPATIBLE_IOCTL(BLKTRACESTOP) | ||
2484 | COMPATIBLE_IOCTL(BLKTRACESETUP) | ||
2485 | COMPATIBLE_IOCTL(BLKTRACETEARDOWN) | ||
2486 | #endif | ||
2487 | /* RAID */ | 2479 | /* RAID */ |
2488 | COMPATIBLE_IOCTL(RAID_VERSION) | 2480 | COMPATIBLE_IOCTL(RAID_VERSION) |
2489 | COMPATIBLE_IOCTL(GET_ARRAY_INFO) | 2481 | COMPATIBLE_IOCTL(GET_ARRAY_INFO) |
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index 7b5d56b82b59..972093bf1853 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h | |||
@@ -142,10 +142,14 @@ struct blk_user_trace_setup { | |||
142 | u32 pid; | 142 | u32 pid; |
143 | }; | 143 | }; |
144 | 144 | ||
145 | #ifdef __KERNEL__ | ||
145 | #if defined(CONFIG_BLK_DEV_IO_TRACE) | 146 | #if defined(CONFIG_BLK_DEV_IO_TRACE) |
146 | extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *); | 147 | extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *); |
147 | extern void blk_trace_shutdown(struct request_queue *); | 148 | extern void blk_trace_shutdown(struct request_queue *); |
148 | extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *); | 149 | extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *); |
150 | extern int do_blk_trace_setup(struct request_queue *q, | ||
151 | struct block_device *bdev, struct blk_user_trace_setup *buts); | ||
152 | |||
149 | 153 | ||
150 | /** | 154 | /** |
151 | * blk_add_trace_rq - Add a trace for a request oriented action | 155 | * blk_add_trace_rq - Add a trace for a request oriented action |
@@ -286,6 +290,7 @@ static inline void blk_add_trace_remap(struct request_queue *q, struct bio *bio, | |||
286 | #define blk_add_trace_generic(q, rq, rw, what) do { } while (0) | 290 | #define blk_add_trace_generic(q, rq, rw, what) do { } while (0) |
287 | #define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) | 291 | #define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) |
288 | #define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) | 292 | #define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) |
293 | #define do_blk_trace_setup(q, bdev, buts) do {} while (0) | ||
289 | #endif /* CONFIG_BLK_DEV_IO_TRACE */ | 294 | #endif /* CONFIG_BLK_DEV_IO_TRACE */ |
290 | 295 | #endif /* __KERNEL__ */ | |
291 | #endif | 296 | #endif |