aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/virtio_blk.c30
-rw-r--r--include/linux/virtio_blk.h5
2 files changed, 35 insertions, 0 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 2138a7ae050c..759dee8330ac 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -70,6 +70,8 @@ static void blk_done(struct virtqueue *vq)
70 vbr->req->sense_len = vbr->in_hdr.sense_len; 70 vbr->req->sense_len = vbr->in_hdr.sense_len;
71 vbr->req->errors = vbr->in_hdr.errors; 71 vbr->req->errors = vbr->in_hdr.errors;
72 } 72 }
73 if (blk_special_request(vbr->req))
74 vbr->req->errors = (error != 0);
73 75
74 __blk_end_request_all(vbr->req, error); 76 __blk_end_request_all(vbr->req, error);
75 list_del(&vbr->list); 77 list_del(&vbr->list);
@@ -103,6 +105,11 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
103 vbr->out_hdr.sector = 0; 105 vbr->out_hdr.sector = 0;
104 vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); 106 vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
105 break; 107 break;
108 case REQ_TYPE_SPECIAL:
109 vbr->out_hdr.type = VIRTIO_BLK_T_GET_ID;
110 vbr->out_hdr.sector = 0;
111 vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
112 break;
106 case REQ_TYPE_LINUX_BLOCK: 113 case REQ_TYPE_LINUX_BLOCK:
107 if (req->cmd[0] == REQ_LB_OP_FLUSH) { 114 if (req->cmd[0] == REQ_LB_OP_FLUSH) {
108 vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH; 115 vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH;
@@ -189,6 +196,29 @@ static void virtblk_prepare_flush(struct request_queue *q, struct request *req)
189 req->cmd[0] = REQ_LB_OP_FLUSH; 196 req->cmd[0] = REQ_LB_OP_FLUSH;
190} 197}
191 198
199/* return id (s/n) string for *disk to *id_str
200 */
201static int virtblk_get_id(struct gendisk *disk, char *id_str)
202{
203 struct virtio_blk *vblk = disk->private_data;
204 struct request *req;
205 struct bio *bio;
206
207 bio = bio_map_kern(vblk->disk->queue, id_str, VIRTIO_BLK_ID_BYTES,
208 GFP_KERNEL);
209 if (IS_ERR(bio))
210 return PTR_ERR(bio);
211
212 req = blk_make_request(vblk->disk->queue, bio, GFP_KERNEL);
213 if (IS_ERR(req)) {
214 bio_put(bio);
215 return PTR_ERR(req);
216 }
217
218 req->cmd_type = REQ_TYPE_SPECIAL;
219 return blk_execute_rq(vblk->disk->queue, vblk->disk, req, false);
220}
221
192static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, 222static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
193 unsigned cmd, unsigned long data) 223 unsigned cmd, unsigned long data)
194{ 224{
diff --git a/include/linux/virtio_blk.h b/include/linux/virtio_blk.h
index e52029e98919..167720d695ed 100644
--- a/include/linux/virtio_blk.h
+++ b/include/linux/virtio_blk.h
@@ -17,6 +17,8 @@
17#define VIRTIO_BLK_F_FLUSH 9 /* Cache flush command support */ 17#define VIRTIO_BLK_F_FLUSH 9 /* Cache flush command support */
18#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ 18#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */
19 19
20#define VIRTIO_BLK_ID_BYTES 20 /* ID string length */
21
20struct virtio_blk_config { 22struct virtio_blk_config {
21 /* The capacity (in 512-byte sectors). */ 23 /* The capacity (in 512-byte sectors). */
22 __u64 capacity; 24 __u64 capacity;
@@ -67,6 +69,9 @@ struct virtio_blk_config {
67/* Cache flush command */ 69/* Cache flush command */
68#define VIRTIO_BLK_T_FLUSH 4 70#define VIRTIO_BLK_T_FLUSH 4
69 71
72/* Get device ID command */
73#define VIRTIO_BLK_T_GET_ID 8
74
70/* Barrier before this op. */ 75/* Barrier before this op. */
71#define VIRTIO_BLK_T_BARRIER 0x80000000 76#define VIRTIO_BLK_T_BARRIER 0x80000000
72 77