binject: ioctl fixup and fix for unaligned commands binject
authorJens Axboe <jaxboe@fusionio.com>
Fri, 29 Oct 2010 03:37:51 +0000 (21:37 -0600)
committerJens Axboe <jaxboe@fusionio.com>
Fri, 29 Oct 2010 03:37:51 +0000 (21:37 -0600)
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
block/binject.c
block/binject.h

index f0d9deaff7c270290098419ab3ea12c57dcec18b..438fb1c2685b0e9e4b8470c6cd7f2cc5c409c9f2 100644 (file)
@@ -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:
index acf8a2736c9e9d7a633d84f931c7ead2f362aaa6..5396dc051e44e6b83779cbb71ed9bd2b85e5eded 100644 (file)
@@ -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,