aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/virtio_blk.c
diff options
context:
space:
mode:
authorjohn cooper <john.cooper@redhat.com>2009-06-09 08:41:40 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-06-09 08:41:40 -0400
commit1d589bb16b825b3a7b4edd34d997f1f1f953033d (patch)
tree2abc78cb296b6f341c3b08b3f261392e77d6668c /drivers/block/virtio_blk.c
parent77634f33d4078542cf1087995cced0ffdae25aa2 (diff)
Add serial number support for virtio_blk, V4a
This patch extracts the opaque data from pci i/o region 0 via the added VIRTIO_BLK_F_IDENTIFY field. By convention this data takes the form of that returned by an ATA IDENTIFY DEVICE command, however the driver (except for structure size) makes no interpretation of the data. The structure data is copied wholesale to userspace via a HDIO_GET_IDENTITY ioctl command (eg: hdparm -i <dev>). Signed-off-by: john cooper <john.cooper@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/block/virtio_blk.c')
-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 = {