aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/virtio_blk.c37
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 */
176static 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
196out_kfree:
197 kfree(opaque);
198out:
199 return err;
200}
201
174static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, 202static 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[] = {
390static unsigned int features[] = { 421static 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
396static struct virtio_driver virtio_blk = { 427static struct virtio_driver virtio_blk = {