aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2007-10-09 07:23:53 -0400
committerJens Axboe <axboe@carl.home.kernel.dk>2007-10-10 03:26:00 -0400
commit171044d449611c6e5040b37210ff6aba47f33ee4 (patch)
tree74a380863b395f9db13f2da333e91cd817dc4970
parent7199d4cdd8485f802df3e1bc131245c69009b9a4 (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.c54
-rw-r--r--block/compat_ioctl.c54
-rw-r--r--fs/compat_ioctl.c8
-rw-r--r--include/linux/blktrace_api.h7
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 */
315static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, 315int 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
398static 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
404static int blk_trace_startstop(struct request_queue *q, int start) 418static 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
43struct 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
54static 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
43static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, 90static 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 */
2478COMPATIBLE_IOCTL(FIBMAP) 2477COMPATIBLE_IOCTL(FIBMAP)
2479COMPATIBLE_IOCTL(FIGETBSZ) 2478COMPATIBLE_IOCTL(FIGETBSZ)
2480/* 0x12 */
2481#ifdef CONFIG_BLOCK
2482COMPATIBLE_IOCTL(BLKTRACESTART)
2483COMPATIBLE_IOCTL(BLKTRACESTOP)
2484COMPATIBLE_IOCTL(BLKTRACESETUP)
2485COMPATIBLE_IOCTL(BLKTRACETEARDOWN)
2486#endif
2487/* RAID */ 2479/* RAID */
2488COMPATIBLE_IOCTL(RAID_VERSION) 2480COMPATIBLE_IOCTL(RAID_VERSION)
2489COMPATIBLE_IOCTL(GET_ARRAY_INFO) 2481COMPATIBLE_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)
146extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *); 147extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *);
147extern void blk_trace_shutdown(struct request_queue *); 148extern void blk_trace_shutdown(struct request_queue *);
148extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *); 149extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *);
150extern 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