diff options
| -rw-r--r-- | drivers/block/virtio_blk.c | 64 |
1 files changed, 51 insertions, 13 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 258bc2ae2885..23b7c48df843 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
| @@ -225,16 +225,6 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | |||
| 225 | struct gendisk *disk = bdev->bd_disk; | 225 | struct gendisk *disk = bdev->bd_disk; |
| 226 | struct virtio_blk *vblk = disk->private_data; | 226 | struct virtio_blk *vblk = disk->private_data; |
| 227 | 227 | ||
| 228 | if (cmd == 0x56424944) { /* 'VBID' */ | ||
| 229 | void __user *usr_data = (void __user *)data; | ||
| 230 | char id_str[VIRTIO_BLK_ID_BYTES]; | ||
| 231 | int err; | ||
| 232 | |||
| 233 | err = virtblk_get_id(disk, id_str); | ||
| 234 | if (!err && copy_to_user(usr_data, id_str, VIRTIO_BLK_ID_BYTES)) | ||
| 235 | err = -EFAULT; | ||
| 236 | return err; | ||
| 237 | } | ||
| 238 | /* | 228 | /* |
| 239 | * Only allow the generic SCSI ioctls if the host can support it. | 229 | * Only allow the generic SCSI ioctls if the host can support it. |
| 240 | */ | 230 | */ |
| @@ -281,6 +271,27 @@ static int index_to_minor(int index) | |||
| 281 | return index << PART_BITS; | 271 | return index << PART_BITS; |
| 282 | } | 272 | } |
| 283 | 273 | ||
| 274 | static ssize_t virtblk_serial_show(struct device *dev, | ||
| 275 | struct device_attribute *attr, char *buf) | ||
| 276 | { | ||
| 277 | struct gendisk *disk = dev_to_disk(dev); | ||
| 278 | int err; | ||
| 279 | |||
| 280 | /* sysfs gives us a PAGE_SIZE buffer */ | ||
| 281 | BUILD_BUG_ON(PAGE_SIZE < VIRTIO_BLK_ID_BYTES); | ||
| 282 | |||
| 283 | buf[VIRTIO_BLK_ID_BYTES] = '\0'; | ||
| 284 | err = virtblk_get_id(disk, buf); | ||
| 285 | if (!err) | ||
| 286 | return strlen(buf); | ||
| 287 | |||
| 288 | if (err == -EIO) /* Unsupported? Make it empty. */ | ||
| 289 | return 0; | ||
| 290 | |||
| 291 | return err; | ||
| 292 | } | ||
| 293 | DEVICE_ATTR(serial, S_IRUGO, virtblk_serial_show, NULL); | ||
| 294 | |||
| 284 | static int __devinit virtblk_probe(struct virtio_device *vdev) | 295 | static int __devinit virtblk_probe(struct virtio_device *vdev) |
| 285 | { | 296 | { |
| 286 | struct virtio_blk *vblk; | 297 | struct virtio_blk *vblk; |
| @@ -366,12 +377,32 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
| 366 | vblk->disk->driverfs_dev = &vdev->dev; | 377 | vblk->disk->driverfs_dev = &vdev->dev; |
| 367 | index++; | 378 | index++; |
| 368 | 379 | ||
| 369 | /* If barriers are supported, tell block layer that queue is ordered */ | 380 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) { |
| 370 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) | 381 | /* |
| 382 | * If the FLUSH feature is supported we do have support for | ||
| 383 | * flushing a volatile write cache on the host. Use that | ||
| 384 | * to implement write barrier support. | ||
| 385 | */ | ||
| 371 | blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, | 386 | blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, |
| 372 | virtblk_prepare_flush); | 387 | virtblk_prepare_flush); |
| 373 | else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) | 388 | } else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) { |
| 389 | /* | ||
| 390 | * If the BARRIER feature is supported the host expects us | ||
| 391 | * to order request by tags. This implies there is not | ||
| 392 | * volatile write cache on the host, and that the host | ||
| 393 | * never re-orders outstanding I/O. This feature is not | ||
| 394 | * useful for real life scenarious and deprecated. | ||
| 395 | */ | ||
| 374 | blk_queue_ordered(q, QUEUE_ORDERED_TAG, NULL); | 396 | blk_queue_ordered(q, QUEUE_ORDERED_TAG, NULL); |
| 397 | } else { | ||
| 398 | /* | ||
| 399 | * If the FLUSH feature is not supported we must assume that | ||
| 400 | * the host does not perform any kind of volatile write | ||
| 401 | * caching. We still need to drain the queue to provider | ||
| 402 | * proper barrier semantics. | ||
| 403 | */ | ||
| 404 | blk_queue_ordered(q, QUEUE_ORDERED_DRAIN, NULL); | ||
| 405 | } | ||
| 375 | 406 | ||
| 376 | /* If disk is read-only in the host, the guest should obey */ | 407 | /* If disk is read-only in the host, the guest should obey */ |
| 377 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO)) | 408 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO)) |
| @@ -445,8 +476,15 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
| 445 | 476 | ||
| 446 | 477 | ||
| 447 | add_disk(vblk->disk); | 478 | add_disk(vblk->disk); |
| 479 | err = device_create_file(disk_to_dev(vblk->disk), &dev_attr_serial); | ||
| 480 | if (err) | ||
| 481 | goto out_del_disk; | ||
| 482 | |||
| 448 | return 0; | 483 | return 0; |
| 449 | 484 | ||
| 485 | out_del_disk: | ||
| 486 | del_gendisk(vblk->disk); | ||
| 487 | blk_cleanup_queue(vblk->disk->queue); | ||
| 450 | out_put_disk: | 488 | out_put_disk: |
| 451 | put_disk(vblk->disk); | 489 | put_disk(vblk->disk); |
| 452 | out_mempool: | 490 | out_mempool: |
