summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Axboe <jaxboe@fusionio.com>2010-10-28 21:37:51 -0600
committerJens Axboe <jaxboe@fusionio.com>2010-10-28 21:37:51 -0600
commit806d89c7cb34e34a2ab7ae673f77f41745d99606 (patch)
tree758dff54acce11bc2bf435d2217bdfc40a57b179
parentf3101bab4a24c8206ccd5377511ca6dca70a17bd (diff)
binject: ioctl fixup and fix for unaligned commandsbinject
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
-rw-r--r--block/binject.c24
-rw-r--r--block/binject.h4
2 files changed, 21 insertions, 7 deletions
diff --git a/block/binject.c b/block/binject.c
index f0d9deaff7c2..438fb1c2685b 100644
--- a/block/binject.c
+++ b/block/binject.c
@@ -39,6 +39,7 @@ struct b_dev {
atomic_t in_flight;
wait_queue_head_t wq_done;
struct block_device *bdev;
+ unsigned int bs;
atomic_t ref;
struct file *file;
struct device *dev;
@@ -283,7 +284,7 @@ static void b_dev_complete_commands(struct b_dev *bd)
complete_and_free_bio(bc);
}
-static int b_dev_validate_command(struct b_user_cmd *buc)
+static int b_dev_validate_command(struct b_dev *bd, struct b_user_cmd *buc)
{
int i;
@@ -295,8 +296,16 @@ static int b_dev_validate_command(struct b_user_cmd *buc)
if (ucm->type != buc->type)
continue;
- if (ucm->data_transfer && !buc->len)
- break;
+ if (ucm->data_transfer) {
+ unsigned int mask = bd->bs - 1;
+
+ if (!buc->len)
+ break;
+ if (!ucm->map_zero &&
+ ((buc->len & mask) || (buc->buf & mask) ||
+ (buc->offset & mask)))
+ break;
+ }
return 0;
}
@@ -412,7 +421,7 @@ static struct bio *map_uc_to_bio(struct b_dev *bd, struct b_user_cmd *uc)
bio = ERR_PTR(-ENOMEM);
else if (!IS_ERR(bio)) {
map_uc_to_bio_flags(bio, uc);
- bio->bi_sector = uc->offset / queue_physical_block_size(q);
+ bio->bi_sector = uc->offset / bd->bs;
bio->bi_rw |= ucm->rw_flags;
}
@@ -523,7 +532,7 @@ static ssize_t b_dev_write(struct file *file, const char __user *buf,
break;
}
- err = b_dev_validate_command(&bc->cmd);
+ err = b_dev_validate_command(bd, &bc->cmd);
if (err)
break;
@@ -672,6 +681,7 @@ static int b_add_dev(struct b_ioctl_cmd *bic)
init_waitqueue_head(&bd->wq_done);
bd->file = file;
bd->bdev = inode->i_bdev;;
+ bd->bs = queue_physical_block_size(bdev_get_queue(bd->bdev));
spin_lock(&b_dev_lock);
@@ -719,14 +729,14 @@ static long b_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return -EFAULT;
switch (cmd) {
- case 0:
+ case B_IOCTL_ADD:
ret = b_add_dev(&bic);
if (!ret && copy_to_user(uarg, &bic, sizeof(bic))) {
b_del_dev(&bic);
ret = -EFAULT;
}
break;
- case 1:
+ case B_IOCTL_DEL:
ret = b_del_dev(&bic);
break;
default:
diff --git a/block/binject.h b/block/binject.h
index acf8a2736c9e..5396dc051e44 100644
--- a/block/binject.h
+++ b/block/binject.h
@@ -23,6 +23,10 @@ struct b_ioctl_cmd {
int minor;
};
+#define BINJECT_IOCTL_CHR 'J'
+#define B_IOCTL_ADD _IOWR(BINJECT_IOCTL_CHR, 1, struct b_ioctl_cmd)
+#define B_IOCTL_DEL _IOWR(BINJECT_IOCTL_CHR, 2, struct b_ioctl_cmd)
+
enum {
B_TYPE_READ = 0,
B_TYPE_WRITE,