virtio: sector discard support

Experimental untested patch.
---
 drivers/block/virtio_blk.c |   14 ++++++++++++++
 include/linux/virtio_blk.h |    4 ++++
 2 files changed, 18 insertions(+)

diff -r f727e9a3e55c drivers/block/virtio_blk.c
--- a/drivers/block/virtio_blk.c	Sat Aug 16 15:55:11 2008 +1000
+++ b/drivers/block/virtio_blk.c	Mon Aug 18 12:00:49 2008 +1000
@@ -88,6 +88,10 @@ static bool do_req(struct request_queue 
 	} else if (blk_pc_request(vbr->req)) {
 		vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD;
 		vbr->out_hdr.sector = 0;
+		vbr->out_hdr.ioprio = vbr->req->ioprio;
+	} else if (blk_discard_rq(vbr->req)) {
+		vbr->out_hdr.type = VIRTIO_BLK_T_DISCARD;
+		vbr->out_hdr.sector = vbr->req->sector;
 		vbr->out_hdr.ioprio = vbr->req->ioprio;
 	} else {
 		/* We don't put anything else in the queue. */
@@ -190,6 +194,12 @@ static int index_to_minor(int index)
 	return index << PART_BITS;
 }
 
+/* We need to set a function to indicate we can handle discards. */
+static int nothing_for_discard(struct request_queue *q, struct request *req)
+{
+	return 0;
+}
+
 static int virtblk_probe(struct virtio_device *vdev)
 {
 	struct virtio_blk *vblk;
@@ -265,6 +275,9 @@ static int virtblk_probe(struct virtio_d
 	if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
 		set_disk_ro(vblk->disk, 1);
 
+	if (virtio_has_feature(vdev, VIRTIO_BLK_F_DISCARD))
+		blk_queue_set_discard(vblk->disk->queue, nothing_for_discard);
+
 	/* Host must always specify the capacity. */
 	vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity),
 			  &cap, sizeof(cap));
@@ -339,6 +352,7 @@ static unsigned int features[] = {
 static unsigned int features[] = {
 	VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
 	VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
+	VIRTIO_BLK_F_DISCARD,
 };
 
 static struct virtio_driver virtio_blk = {
diff -r f727e9a3e55c include/linux/virtio_blk.h
--- a/include/linux/virtio_blk.h	Sat Aug 16 15:55:11 2008 +1000
+++ b/include/linux/virtio_blk.h	Mon Aug 18 12:00:49 2008 +1000
@@ -14,6 +14,7 @@
 #define VIRTIO_BLK_F_GEOMETRY	4	/* Legacy geometry available  */
 #define VIRTIO_BLK_F_RO		5	/* Disk is read-only */
 #define VIRTIO_BLK_F_BLK_SIZE	6	/* Block size of disk is available*/
+#define VIRTIO_BLK_F_DISCARD	7	/* Understands VIRTIO_BLK_T_DISCARD */
 
 struct virtio_blk_config
 {
@@ -40,6 +41,9 @@ struct virtio_blk_config
 /* This bit says it's a scsi command, not an actual read or write. */
 #define VIRTIO_BLK_T_SCSI_CMD	2
 
+/* This says it's actually a discard. */
+#define VIRTIO_BLK_T_DISCARD	4
+
 /* Barrier before this op. */
 #define VIRTIO_BLK_T_BARRIER	0x80000000
 
