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;
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;
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;
}
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;
}
break;
}
- err = b_dev_validate_command(&bc->cmd);
+ err = b_dev_validate_command(bd, &bc->cmd);
if (err)
break;
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);
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:
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,