diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/virtio_blk.c | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index c4845b169464..c0facaa55cf4 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -171,11 +171,43 @@ static void do_virtblk_request(struct request_queue *q) | |||
171 | vblk->vq->vq_ops->kick(vblk->vq); | 171 | vblk->vq->vq_ops->kick(vblk->vq); |
172 | } | 172 | } |
173 | 173 | ||
174 | /* return ATA identify data | ||
175 | */ | ||
176 | static int virtblk_identify(struct gendisk *disk, void *argp) | ||
177 | { | ||
178 | struct virtio_blk *vblk = disk->private_data; | ||
179 | void *opaque; | ||
180 | int err = -ENOMEM; | ||
181 | |||
182 | opaque = kmalloc(VIRTIO_BLK_ID_BYTES, GFP_KERNEL); | ||
183 | if (!opaque) | ||
184 | goto out; | ||
185 | |||
186 | err = virtio_config_buf(vblk->vdev, VIRTIO_BLK_F_IDENTIFY, | ||
187 | offsetof(struct virtio_blk_config, identify), opaque, | ||
188 | VIRTIO_BLK_ID_BYTES); | ||
189 | |||
190 | if (err) | ||
191 | goto out_kfree; | ||
192 | |||
193 | if (copy_to_user(argp, opaque, VIRTIO_BLK_ID_BYTES)) | ||
194 | err = -EFAULT; | ||
195 | |||
196 | out_kfree: | ||
197 | kfree(opaque); | ||
198 | out: | ||
199 | return err; | ||
200 | } | ||
201 | |||
174 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | 202 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, |
175 | unsigned cmd, unsigned long data) | 203 | unsigned cmd, unsigned long data) |
176 | { | 204 | { |
177 | struct gendisk *disk = bdev->bd_disk; | 205 | struct gendisk *disk = bdev->bd_disk; |
178 | struct virtio_blk *vblk = disk->private_data; | 206 | struct virtio_blk *vblk = disk->private_data; |
207 | void __user *argp = (void __user *)data; | ||
208 | |||
209 | if (cmd == HDIO_GET_IDENTITY) | ||
210 | return virtblk_identify(disk, argp); | ||
179 | 211 | ||
180 | /* | 212 | /* |
181 | * Only allow the generic SCSI ioctls if the host can support it. | 213 | * Only allow the generic SCSI ioctls if the host can support it. |
@@ -183,8 +215,7 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | |||
183 | if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) | 215 | if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) |
184 | return -ENOIOCTLCMD; | 216 | return -ENOIOCTLCMD; |
185 | 217 | ||
186 | return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, | 218 | return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); |
187 | (void __user *)data); | ||
188 | } | 219 | } |
189 | 220 | ||
190 | /* We provide getgeo only to please some old bootloader/partitioning tools */ | 221 | /* We provide getgeo only to please some old bootloader/partitioning tools */ |
@@ -390,7 +421,7 @@ static struct virtio_device_id id_table[] = { | |||
390 | static unsigned int features[] = { | 421 | static unsigned int features[] = { |
391 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, | 422 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, |
392 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, | 423 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, |
393 | VIRTIO_BLK_F_SCSI, | 424 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY |
394 | }; | 425 | }; |
395 | 426 | ||
396 | static struct virtio_driver virtio_blk = { | 427 | static struct virtio_driver virtio_blk = { |