Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 171044d4 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Jens Axboe
Browse files

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: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 7199d4cd
Loading
Loading
Loading
Loading
+34 −20
Original line number Original line Diff line number Diff line
@@ -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,
int do_blk_trace_setup(struct request_queue *q, struct block_device *bdev,
			   char __user *arg)
			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)))
	if (!buts->buf_size || !buts->buf_nr)
		return -EFAULT;

	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++)
	for (i = 0; i < strlen(buts->name); i++)
		if (buts.name[i] == '/')
		if (buts->name[i] == '/')
			buts.name[i] = '_';
			buts->name[i] = '_';

	if (copy_to_user(arg, &buts, sizeof(buts)))
		return -EFAULT;


	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->start_lba = buts->start_lba;
	bt->end_lba = buts.end_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 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev,
	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;
+54 −0
Original line number Original line Diff line number Diff line
@@ -40,6 +40,53 @@ static int compat_put_u64(unsigned long arg, u64 val)
#define BLKBSZSET_32		_IOW(0x12, 113, int)
#define BLKBSZSET_32		_IOW(0x12, 113, int)
#define BLKGETSIZE64_32		_IOR(0x12, 114, 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,
static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
			struct gendisk *disk, unsigned cmd, unsigned long arg)
			struct gendisk *disk, unsigned cmd, unsigned long arg)
{
{
@@ -197,6 +244,13 @@ static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file,


	case BLKGETSIZE64_32:
	case BLKGETSIZE64_32:
		return compat_put_u64(arg, bdev->bd_inode->i_size);
		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;
	return -ENOIOCTLCMD;
}
}
+0 −8
Original line number Original line Diff line number Diff line
@@ -62,7 +62,6 @@
#include <linux/i2c-dev.h>
#include <linux/i2c-dev.h>
#include <linux/wireless.h>
#include <linux/wireless.h>
#include <linux/atalk.h>
#include <linux/atalk.h>
#include <linux/blktrace_api.h>
#include <linux/loop.h>
#include <linux/loop.h>


#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/bluetooth.h>
@@ -2477,13 +2476,6 @@ COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */
/* 0x00 */
/* 0x00 */
COMPATIBLE_IOCTL(FIBMAP)
COMPATIBLE_IOCTL(FIBMAP)
COMPATIBLE_IOCTL(FIGETBSZ)
COMPATIBLE_IOCTL(FIGETBSZ)
/* 0x12 */
#ifdef CONFIG_BLOCK
COMPATIBLE_IOCTL(BLKTRACESTART)
COMPATIBLE_IOCTL(BLKTRACESTOP)
COMPATIBLE_IOCTL(BLKTRACESETUP)
COMPATIBLE_IOCTL(BLKTRACETEARDOWN)
#endif
/* RAID */
/* RAID */
COMPATIBLE_IOCTL(RAID_VERSION)
COMPATIBLE_IOCTL(RAID_VERSION)
COMPATIBLE_IOCTL(GET_ARRAY_INFO)
COMPATIBLE_IOCTL(GET_ARRAY_INFO)
+6 −1
Original line number Original line Diff line number Diff line
@@ -142,10 +142,14 @@ struct blk_user_trace_setup {
	u32 pid;
	u32 pid;
};
};


#ifdef __KERNEL__
#if defined(CONFIG_BLK_DEV_IO_TRACE)
#if defined(CONFIG_BLK_DEV_IO_TRACE)
extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *);
extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *);
extern void blk_trace_shutdown(struct request_queue *);
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 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
 * 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,
#define blk_add_trace_generic(q, rq, rw, what)	do { } while (0)
#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_pdu_int(q, what, bio, pdu)	do { } while (0)
#define blk_add_trace_remap(q, bio, dev, f, t)	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 /* CONFIG_BLK_DEV_IO_TRACE */

#endif /* __KERNEL__ */
#endif
#endif