blob: e574fbf5e6dfeb024d69a5305f07cde22408763e [file] [log] [blame]
Thomas Gleixner09c434b2019-05-19 13:08:20 +01001// SPDX-License-Identifier: GPL-2.0-only
Rusty Russelle467cde2007-10-22 11:03:38 +10002//#define DEBUG
3#include <linux/spinlock.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +09004#include <linux/slab.h>
Rusty Russelle467cde2007-10-22 11:03:38 +10005#include <linux/blkdev.h>
6#include <linux/hdreg.h>
Paul Gortmaker0c8d44f2011-07-01 15:56:05 -04007#include <linux/module.h>
Michael S. Tsirkin4678d6f92012-01-12 15:44:44 +10308#include <linux/mutex.h>
Christoph Hellwigad714732017-02-05 18:15:25 +01009#include <linux/interrupt.h>
Rusty Russelle467cde2007-10-22 11:03:38 +100010#include <linux/virtio.h>
11#include <linux/virtio_blk.h>
Jens Axboe3d1266c2007-10-24 13:21:21 +020012#include <linux/scatterlist.h>
Christoph Hellwig7a7c9242011-02-01 21:43:48 +010013#include <linux/string_helpers.h>
Michael S. Tsirkin5087a502011-10-30 21:29:59 +020014#include <linux/idr.h>
Jens Axboe1cf7e9c2013-11-01 10:52:52 -060015#include <linux/blk-mq.h>
Christoph Hellwigad714732017-02-05 18:15:25 +010016#include <linux/blk-mq-virtio.h>
Jens Axboe1cf7e9c2013-11-01 10:52:52 -060017#include <linux/numa.h>
Michael S. Tsirkin55a24152020-04-17 03:14:34 -040018#include <uapi/linux/virtio_ring.h>
Jens Axboe3d1266c2007-10-24 13:21:21 +020019
Christian Borntraeger4f3bf192008-01-31 15:53:53 +010020#define PART_BITS 4
Ming Lei6a27b652014-06-26 17:41:48 +080021#define VQ_NAME_LEN 16
Changpeng Liu1f238162018-11-01 15:40:35 -070022#define MAX_DISCARD_SEGMENTS 256u
Rusty Russelle467cde2007-10-22 11:03:38 +100023
Stefan Hajnoczi63947b32021-05-24 16:40:20 +010024/* The maximum number of sg elements that fit into a virtqueue */
25#define VIRTIO_BLK_MAX_SG_ELEMS 32768
26
Michael S. Tsirkin5087a502011-10-30 21:29:59 +020027static int major;
28static DEFINE_IDA(vd_index_ida);
29
Jonghwan Choi2a647bf2013-05-20 10:25:39 +093030static struct workqueue_struct *virtblk_wq;
Christian Borntraeger4f3bf192008-01-31 15:53:53 +010031
Ming Lei6a27b652014-06-26 17:41:48 +080032struct virtio_blk_vq {
33 struct virtqueue *vq;
34 spinlock_t lock;
35 char name[VQ_NAME_LEN];
36} ____cacheline_aligned_in_smp;
37
Michael S. Tsirkinbb6ec572015-01-15 13:33:31 +020038struct virtio_blk {
Stefan Hajnoczi90b5feb2020-04-30 15:04:42 +010039 /*
40 * This mutex must be held by anything that may run after
41 * virtblk_remove() sets vblk->vdev to NULL.
42 *
43 * blk-mq, virtqueue processing, and sysfs attribute code paths are
44 * shut down before vblk->vdev is set to NULL and therefore do not need
45 * to hold this mutex.
46 */
47 struct mutex vdev_mutex;
Rusty Russelle467cde2007-10-22 11:03:38 +100048 struct virtio_device *vdev;
Rusty Russelle467cde2007-10-22 11:03:38 +100049
50 /* The disk structure for the kernel. */
51 struct gendisk *disk;
52
Christoph Hellwig24d2f902014-04-15 14:14:00 -060053 /* Block layer tags. */
54 struct blk_mq_tag_set tag_set;
55
Christoph Hellwig7a7c9242011-02-01 21:43:48 +010056 /* Process context for config space updates */
57 struct work_struct config_work;
58
Stefan Hajnoczi90b5feb2020-04-30 15:04:42 +010059 /*
60 * Tracks references from block_device_operations open/release and
61 * virtio_driver probe/remove so this object can be freed once no
62 * longer in use.
63 */
64 refcount_t refs;
65
Rusty Russell0864b792008-12-30 09:26:05 -060066 /* What host tells us, plus 2 for header & tailer. */
67 unsigned int sg_elems;
68
Michael S. Tsirkin5087a502011-10-30 21:29:59 +020069 /* Ida index - used to track minor number allocations. */
70 int index;
Ming Lei6a27b652014-06-26 17:41:48 +080071
72 /* num of vqs */
73 int num_vqs;
74 struct virtio_blk_vq *vqs;
Rusty Russelle467cde2007-10-22 11:03:38 +100075};
76
Michael S. Tsirkinbb6ec572015-01-15 13:33:31 +020077struct virtblk_req {
Christoph Hellwig97b50a62017-01-28 09:32:53 +010078 struct virtio_blk_outhdr out_hdr;
79 u8 status;
Asias Hea98755c2012-08-08 16:07:04 +080080 struct scatterlist sg[];
Rusty Russelle467cde2007-10-22 11:03:38 +100081};
82
Christoph Hellwig2a842ac2017-06-03 09:38:04 +020083static inline blk_status_t virtblk_result(struct virtblk_req *vbr)
Asias Hea98755c2012-08-08 16:07:04 +080084{
85 switch (vbr->status) {
86 case VIRTIO_BLK_S_OK:
Christoph Hellwig2a842ac2017-06-03 09:38:04 +020087 return BLK_STS_OK;
Asias Hea98755c2012-08-08 16:07:04 +080088 case VIRTIO_BLK_S_UNSUPP:
Christoph Hellwig2a842ac2017-06-03 09:38:04 +020089 return BLK_STS_NOTSUPP;
Asias Hea98755c2012-08-08 16:07:04 +080090 default:
Christoph Hellwig2a842ac2017-06-03 09:38:04 +020091 return BLK_STS_IOERR;
Asias Hea98755c2012-08-08 16:07:04 +080092 }
93}
94
Christoph Hellwig97b50a62017-01-28 09:32:53 +010095static int virtblk_add_req(struct virtqueue *vq, struct virtblk_req *vbr,
96 struct scatterlist *data_sg, bool have_data)
97{
98 struct scatterlist hdr, status, *sgs[3];
99 unsigned int num_out = 0, num_in = 0;
100
101 sg_init_one(&hdr, &vbr->out_hdr, sizeof(vbr->out_hdr));
102 sgs[num_out++] = &hdr;
103
104 if (have_data) {
105 if (vbr->out_hdr.type & cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_OUT))
106 sgs[num_out++] = data_sg;
107 else
108 sgs[num_out + num_in++] = data_sg;
Paolo Bonzini8f39db92013-03-20 15:44:27 +1030109 }
110
111 sg_init_one(&status, &vbr->status, sizeof(vbr->status));
112 sgs[num_out + num_in++] = &status;
113
114 return virtqueue_add_sgs(vq, sgs, num_out, num_in, vbr, GFP_ATOMIC);
Paolo Bonzini5ee21a52013-03-20 15:44:27 +1030115}
Asias Hec85a1f92012-08-08 16:07:05 +0800116
Changpeng Liu1f238162018-11-01 15:40:35 -0700117static int virtblk_setup_discard_write_zeroes(struct request *req, bool unmap)
118{
119 unsigned short segments = blk_rq_nr_discard_segments(req);
120 unsigned short n = 0;
121 struct virtio_blk_discard_write_zeroes *range;
122 struct bio *bio;
123 u32 flags = 0;
124
125 if (unmap)
126 flags |= VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP;
127
128 range = kmalloc_array(segments, sizeof(*range), GFP_ATOMIC);
129 if (!range)
130 return -ENOMEM;
131
Ming Leiaf822aa2020-08-17 17:52:40 +0800132 /*
133 * Single max discard segment means multi-range discard isn't
134 * supported, and block layer only runs contiguity merge like
135 * normal RW request. So we can't reply on bio for retrieving
136 * each range info.
137 */
138 if (queue_max_discard_segments(req->q) == 1) {
139 range[0].flags = cpu_to_le32(flags);
140 range[0].num_sectors = cpu_to_le32(blk_rq_sectors(req));
141 range[0].sector = cpu_to_le64(blk_rq_pos(req));
142 n = 1;
143 } else {
144 __rq_for_each_bio(bio, req) {
145 u64 sector = bio->bi_iter.bi_sector;
146 u32 num_sectors = bio->bi_iter.bi_size >> SECTOR_SHIFT;
Changpeng Liu1f238162018-11-01 15:40:35 -0700147
Ming Leiaf822aa2020-08-17 17:52:40 +0800148 range[n].flags = cpu_to_le32(flags);
149 range[n].num_sectors = cpu_to_le32(num_sectors);
150 range[n].sector = cpu_to_le64(sector);
151 n++;
152 }
Changpeng Liu1f238162018-11-01 15:40:35 -0700153 }
154
Ming Leiaf822aa2020-08-17 17:52:40 +0800155 WARN_ON_ONCE(n != segments);
156
Changpeng Liu1f238162018-11-01 15:40:35 -0700157 req->special_vec.bv_page = virt_to_page(range);
158 req->special_vec.bv_offset = offset_in_page(range);
159 req->special_vec.bv_len = sizeof(*range) * segments;
160 req->rq_flags |= RQF_SPECIAL_PAYLOAD;
161
162 return 0;
163}
164
Christoph Hellwig5124c282014-02-10 03:24:39 -0800165static inline void virtblk_request_done(struct request *req)
Asias Hec85a1f92012-08-08 16:07:05 +0800166{
Christoph Hellwig9d74e252014-04-14 10:30:07 +0200167 struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
Asias Hea98755c2012-08-08 16:07:04 +0800168
Changpeng Liu1f238162018-11-01 15:40:35 -0700169 if (req->rq_flags & RQF_SPECIAL_PAYLOAD) {
170 kfree(page_address(req->special_vec.bv_page) +
171 req->special_vec.bv_offset);
172 }
173
Christoph Hellwigd19633d2017-04-20 16:03:00 +0200174 blk_mq_end_request(req, virtblk_result(vbr));
Asias Hea98755c2012-08-08 16:07:04 +0800175}
176
177static void virtblk_done(struct virtqueue *vq)
Rusty Russelle467cde2007-10-22 11:03:38 +1000178{
179 struct virtio_blk *vblk = vq->vdev->priv;
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600180 bool req_done = false;
Ming Lei6a27b652014-06-26 17:41:48 +0800181 int qid = vq->index;
Rusty Russelle467cde2007-10-22 11:03:38 +1000182 struct virtblk_req *vbr;
Rusty Russelle467cde2007-10-22 11:03:38 +1000183 unsigned long flags;
Asias Hea98755c2012-08-08 16:07:04 +0800184 unsigned int len;
Rusty Russelle467cde2007-10-22 11:03:38 +1000185
Ming Lei6a27b652014-06-26 17:41:48 +0800186 spin_lock_irqsave(&vblk->vqs[qid].lock, flags);
Asias Hebb811102012-09-25 10:36:17 +0800187 do {
188 virtqueue_disable_cb(vq);
Ming Lei6a27b652014-06-26 17:41:48 +0800189 while ((vbr = virtqueue_get_buf(vblk->vqs[qid].vq, &len)) != NULL) {
Christoph Hellwig85dada02017-01-28 09:32:52 +0100190 struct request *req = blk_mq_rq_from_pdu(vbr);
191
Christoph Hellwig15f73f52020-06-11 08:44:47 +0200192 if (likely(!blk_should_fake_timeout(req->q)))
193 blk_mq_complete_request(req);
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600194 req_done = true;
Rusty Russelle467cde2007-10-22 11:03:38 +1000195 }
Heinz Graalfs7f03b172013-10-29 09:40:30 +1030196 if (unlikely(virtqueue_is_broken(vq)))
197 break;
Asias Hebb811102012-09-25 10:36:17 +0800198 } while (!virtqueue_enable_cb(vq));
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600199
Rusty Russelle467cde2007-10-22 11:03:38 +1000200 /* In case queue is stopped waiting for more buffers. */
Asias Hea98755c2012-08-08 16:07:04 +0800201 if (req_done)
Christoph Hellwig1b4a3252014-04-16 09:44:54 +0200202 blk_mq_start_stopped_hw_queues(vblk->disk->queue, true);
Ming Lei6a27b652014-06-26 17:41:48 +0800203 spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
Asias Hea98755c2012-08-08 16:07:04 +0800204}
205
Jens Axboe944e7c82018-11-26 11:00:12 -0700206static void virtio_commit_rqs(struct blk_mq_hw_ctx *hctx)
207{
208 struct virtio_blk *vblk = hctx->queue->queuedata;
209 struct virtio_blk_vq *vq = &vblk->vqs[hctx->queue_num];
210 bool kick;
211
212 spin_lock_irq(&vq->lock);
213 kick = virtqueue_kick_prepare(vq->vq);
214 spin_unlock_irq(&vq->lock);
215
216 if (kick)
217 virtqueue_notify(vq->vq);
218}
219
Christoph Hellwigfc17b652017-06-03 09:38:05 +0200220static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
Jens Axboe74c45052014-10-29 11:14:52 -0600221 const struct blk_mq_queue_data *bd)
Rusty Russelle467cde2007-10-22 11:03:38 +1000222{
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600223 struct virtio_blk *vblk = hctx->queue->queuedata;
Jens Axboe74c45052014-10-29 11:14:52 -0600224 struct request *req = bd->rq;
Christoph Hellwig9d74e252014-04-14 10:30:07 +0200225 struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600226 unsigned long flags;
Paolo Bonzini20af3cf2013-03-20 15:44:27 +1030227 unsigned int num;
Ming Lei6a27b652014-06-26 17:41:48 +0800228 int qid = hctx->queue_num;
Rusty Russell5261b852014-03-13 11:23:39 +1030229 int err;
Ming Leie8edca62014-05-30 10:49:29 +0800230 bool notify = false;
Changpeng Liu1f238162018-11-01 15:40:35 -0700231 bool unmap = false;
Christoph Hellwigaebf5262017-01-31 16:57:31 +0100232 u32 type;
Rusty Russelle467cde2007-10-22 11:03:38 +1000233
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600234 BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems);
Rusty Russelle467cde2007-10-22 11:03:38 +1000235
Christoph Hellwigaebf5262017-01-31 16:57:31 +0100236 switch (req_op(req)) {
237 case REQ_OP_READ:
238 case REQ_OP_WRITE:
239 type = 0;
240 break;
241 case REQ_OP_FLUSH:
242 type = VIRTIO_BLK_T_FLUSH;
243 break;
Changpeng Liu1f238162018-11-01 15:40:35 -0700244 case REQ_OP_DISCARD:
245 type = VIRTIO_BLK_T_DISCARD;
246 break;
247 case REQ_OP_WRITE_ZEROES:
248 type = VIRTIO_BLK_T_WRITE_ZEROES;
249 unmap = !(req->cmd_flags & REQ_NOUNMAP);
250 break;
Christoph Hellwigaebf5262017-01-31 16:57:31 +0100251 case REQ_OP_DRV_IN:
252 type = VIRTIO_BLK_T_GET_ID;
253 break;
254 default:
255 WARN_ON_ONCE(1);
Christoph Hellwigfc17b652017-06-03 09:38:05 +0200256 return BLK_STS_IOERR;
Rusty Russelle467cde2007-10-22 11:03:38 +1000257 }
258
Christoph Hellwigaebf5262017-01-31 16:57:31 +0100259 vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, type);
260 vbr->out_hdr.sector = type ?
261 0 : cpu_to_virtio64(vblk->vdev, blk_rq_pos(req));
262 vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(req));
263
Christoph Hellwige2490072014-09-13 16:40:09 -0700264 blk_mq_start_request(req);
265
Changpeng Liu1f238162018-11-01 15:40:35 -0700266 if (type == VIRTIO_BLK_T_DISCARD || type == VIRTIO_BLK_T_WRITE_ZEROES) {
267 err = virtblk_setup_discard_write_zeroes(req, unmap);
268 if (err)
269 return BLK_STS_RESOURCE;
270 }
271
Christoph Hellwig85dada02017-01-28 09:32:52 +0100272 num = blk_rq_map_sg(hctx->queue, req, vbr->sg);
Hannes Reinecke1cde26f2009-05-18 14:41:30 +0200273 if (num) {
Christoph Hellwig85dada02017-01-28 09:32:52 +0100274 if (rq_data_dir(req) == WRITE)
Michael S. Tsirkin19c1c5a2014-10-07 16:39:49 +0200275 vbr->out_hdr.type |= cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_OUT);
Paolo Bonzini20af3cf2013-03-20 15:44:27 +1030276 else
Michael S. Tsirkin19c1c5a2014-10-07 16:39:49 +0200277 vbr->out_hdr.type |= cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_IN);
Rusty Russelle467cde2007-10-22 11:03:38 +1000278 }
279
Ming Lei6a27b652014-06-26 17:41:48 +0800280 spin_lock_irqsave(&vblk->vqs[qid].lock, flags);
Christoph Hellwig782e0672019-12-12 17:37:19 +0100281 err = virtblk_add_req(vblk->vqs[qid].vq, vbr, vbr->sg, num);
Rusty Russell5261b852014-03-13 11:23:39 +1030282 if (err) {
Ming Lei6a27b652014-06-26 17:41:48 +0800283 virtqueue_kick(vblk->vqs[qid].vq);
Halil Pasicf5f6b952020-02-13 13:37:27 +0100284 /* Don't stop the queue if -ENOMEM: we may have failed to
285 * bounce the buffer due to global resource outage.
286 */
287 if (err == -ENOSPC)
288 blk_mq_stop_hw_queue(hctx);
Ming Lei6a27b652014-06-26 17:41:48 +0800289 spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
Halil Pasic3d973b22020-02-13 13:37:28 +0100290 switch (err) {
291 case -ENOSPC:
Ming Lei86ff7c22018-01-30 22:04:57 -0500292 return BLK_STS_DEV_RESOURCE;
Halil Pasic3d973b22020-02-13 13:37:28 +0100293 case -ENOMEM:
294 return BLK_STS_RESOURCE;
295 default:
296 return BLK_STS_IOERR;
297 }
Asias Hea98755c2012-08-08 16:07:04 +0800298 }
299
Jens Axboe74c45052014-10-29 11:14:52 -0600300 if (bd->last && virtqueue_kick_prepare(vblk->vqs[qid].vq))
Ming Leie8edca62014-05-30 10:49:29 +0800301 notify = true;
Ming Lei6a27b652014-06-26 17:41:48 +0800302 spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
Ming Leie8edca62014-05-30 10:49:29 +0800303
304 if (notify)
Ming Lei6a27b652014-06-26 17:41:48 +0800305 virtqueue_notify(vblk->vqs[qid].vq);
Christoph Hellwigfc17b652017-06-03 09:38:05 +0200306 return BLK_STS_OK;
Asias Hea98755c2012-08-08 16:07:04 +0800307}
308
john cooper4cb2ea22010-03-25 01:33:33 -0400309/* return id (s/n) string for *disk to *id_str
310 */
311static int virtblk_get_id(struct gendisk *disk, char *id_str)
312{
313 struct virtio_blk *vblk = disk->private_data;
Christoph Hellwigf9596692016-07-19 11:31:49 +0200314 struct request_queue *q = vblk->disk->queue;
john cooper4cb2ea22010-03-25 01:33:33 -0400315 struct request *req;
Mike Snitzere4c47762010-10-09 12:12:13 +1030316 int err;
john cooper4cb2ea22010-03-25 01:33:33 -0400317
Christoph Hellwigff005a02018-05-09 09:54:05 +0200318 req = blk_get_request(q, REQ_OP_DRV_IN, 0);
Christoph Hellwigf9596692016-07-19 11:31:49 +0200319 if (IS_ERR(req))
john cooper4cb2ea22010-03-25 01:33:33 -0400320 return PTR_ERR(req);
Mike Snitzere4c47762010-10-09 12:12:13 +1030321
Christoph Hellwigf9596692016-07-19 11:31:49 +0200322 err = blk_rq_map_kern(q, req, id_str, VIRTIO_BLK_ID_BYTES, GFP_KERNEL);
323 if (err)
324 goto out;
325
Guoqing Jiang684da762021-01-25 05:49:58 +0100326 blk_execute_rq(vblk->disk, req, false);
Christoph Hellwig2a842ac2017-06-03 09:38:04 +0200327 err = blk_status_to_errno(virtblk_result(blk_mq_rq_to_pdu(req)));
Christoph Hellwigf9596692016-07-19 11:31:49 +0200328out:
329 blk_put_request(req);
Mike Snitzere4c47762010-10-09 12:12:13 +1030330 return err;
john cooper4cb2ea22010-03-25 01:33:33 -0400331}
332
Stefan Hajnoczi90b5feb2020-04-30 15:04:42 +0100333static void virtblk_get(struct virtio_blk *vblk)
334{
335 refcount_inc(&vblk->refs);
336}
337
338static void virtblk_put(struct virtio_blk *vblk)
339{
340 if (refcount_dec_and_test(&vblk->refs)) {
341 ida_simple_remove(&vd_index_ida, vblk->index);
342 mutex_destroy(&vblk->vdev_mutex);
343 kfree(vblk);
344 }
345}
346
347static int virtblk_open(struct block_device *bd, fmode_t mode)
348{
349 struct virtio_blk *vblk = bd->bd_disk->private_data;
350 int ret = 0;
351
352 mutex_lock(&vblk->vdev_mutex);
353
354 if (vblk->vdev)
355 virtblk_get(vblk);
356 else
357 ret = -ENXIO;
358
359 mutex_unlock(&vblk->vdev_mutex);
360 return ret;
361}
362
363static void virtblk_release(struct gendisk *disk, fmode_t mode)
364{
365 struct virtio_blk *vblk = disk->private_data;
366
367 virtblk_put(vblk);
368}
369
Christian Borntraeger135da0b2008-01-23 17:56:50 +0100370/* We provide getgeo only to please some old bootloader/partitioning tools */
371static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
372{
Ryan Harper48e40432008-04-16 13:56:37 -0500373 struct virtio_blk *vblk = bd->bd_disk->private_data;
Stefan Hajnoczi90b5feb2020-04-30 15:04:42 +0100374 int ret = 0;
375
376 mutex_lock(&vblk->vdev_mutex);
377
378 if (!vblk->vdev) {
379 ret = -ENXIO;
380 goto out;
381 }
Ryan Harper48e40432008-04-16 13:56:37 -0500382
383 /* see if the host passed in geometry config */
Rusty Russell855e0c52013-10-14 18:11:51 +1030384 if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_GEOMETRY)) {
385 virtio_cread(vblk->vdev, struct virtio_blk_config,
386 geometry.cylinders, &geo->cylinders);
387 virtio_cread(vblk->vdev, struct virtio_blk_config,
388 geometry.heads, &geo->heads);
389 virtio_cread(vblk->vdev, struct virtio_blk_config,
390 geometry.sectors, &geo->sectors);
Ryan Harper48e40432008-04-16 13:56:37 -0500391 } else {
392 /* some standard values, similar to sd */
393 geo->heads = 1 << 6;
394 geo->sectors = 1 << 5;
395 geo->cylinders = get_capacity(bd->bd_disk) >> 11;
396 }
Stefan Hajnoczi90b5feb2020-04-30 15:04:42 +0100397out:
398 mutex_unlock(&vblk->vdev_mutex);
399 return ret;
Christian Borntraeger135da0b2008-01-23 17:56:50 +0100400}
401
Alexey Dobriyan83d5cde2009-09-21 17:01:13 -0700402static const struct block_device_operations virtblk_fops = {
Christian Borntraeger135da0b2008-01-23 17:56:50 +0100403 .owner = THIS_MODULE,
Stefan Hajnoczi90b5feb2020-04-30 15:04:42 +0100404 .open = virtblk_open,
405 .release = virtblk_release,
Christian Borntraeger135da0b2008-01-23 17:56:50 +0100406 .getgeo = virtblk_getgeo,
Rusty Russelle467cde2007-10-22 11:03:38 +1000407};
408
Christian Borntraegerd50ed902008-02-01 09:05:00 +0100409static int index_to_minor(int index)
410{
411 return index << PART_BITS;
412}
413
Michael S. Tsirkin5087a502011-10-30 21:29:59 +0200414static int minor_to_index(int minor)
415{
416 return minor >> PART_BITS;
417}
418
Hannes Reineckee982c4d2018-09-28 08:17:23 +0200419static ssize_t serial_show(struct device *dev,
420 struct device_attribute *attr, char *buf)
Ryan Harpera5eb9e42010-06-23 22:19:57 -0500421{
422 struct gendisk *disk = dev_to_disk(dev);
423 int err;
424
425 /* sysfs gives us a PAGE_SIZE buffer */
426 BUILD_BUG_ON(PAGE_SIZE < VIRTIO_BLK_ID_BYTES);
427
428 buf[VIRTIO_BLK_ID_BYTES] = '\0';
429 err = virtblk_get_id(disk, buf);
430 if (!err)
431 return strlen(buf);
432
433 if (err == -EIO) /* Unsupported? Make it empty. */
434 return 0;
435
436 return err;
437}
Michael S. Tsirkin393c5252014-10-23 16:08:44 +0300438
Hannes Reineckee982c4d2018-09-28 08:17:23 +0200439static DEVICE_ATTR_RO(serial);
Ryan Harpera5eb9e42010-06-23 22:19:57 -0500440
Stefan Hajnoczidaf2a502018-01-03 16:03:39 +0000441/* The queue's logical block size must be set before calling this */
442static void virtblk_update_capacity(struct virtio_blk *vblk, bool resize)
Christoph Hellwig7a7c9242011-02-01 21:43:48 +0100443{
Christoph Hellwig7a7c9242011-02-01 21:43:48 +0100444 struct virtio_device *vdev = vblk->vdev;
445 struct request_queue *q = vblk->disk->queue;
446 char cap_str_2[10], cap_str_10[10];
Stefan Hajnoczi1046d302017-07-26 15:32:23 +0100447 unsigned long long nblocks;
James Bottomleyb9f28d82015-03-05 18:47:01 -0800448 u64 capacity;
Christoph Hellwig7a7c9242011-02-01 21:43:48 +0100449
450 /* Host must always specify the capacity. */
Rusty Russell855e0c52013-10-14 18:11:51 +1030451 virtio_cread(vdev, struct virtio_blk_config, capacity, &capacity);
Christoph Hellwig7a7c9242011-02-01 21:43:48 +0100452
Stefan Hajnoczi1046d302017-07-26 15:32:23 +0100453 nblocks = DIV_ROUND_UP_ULL(capacity, queue_logical_block_size(q) >> 9);
454
455 string_get_size(nblocks, queue_logical_block_size(q),
James Bottomleyb9f28d82015-03-05 18:47:01 -0800456 STRING_UNITS_2, cap_str_2, sizeof(cap_str_2));
Stefan Hajnoczi1046d302017-07-26 15:32:23 +0100457 string_get_size(nblocks, queue_logical_block_size(q),
James Bottomleyb9f28d82015-03-05 18:47:01 -0800458 STRING_UNITS_10, cap_str_10, sizeof(cap_str_10));
Christoph Hellwig7a7c9242011-02-01 21:43:48 +0100459
460 dev_notice(&vdev->dev,
Stefan Hajnoczidaf2a502018-01-03 16:03:39 +0000461 "[%s] %s%llu %d-byte logical blocks (%s/%s)\n",
462 vblk->disk->disk_name,
463 resize ? "new size: " : "",
Stefan Hajnoczi1046d302017-07-26 15:32:23 +0100464 nblocks,
465 queue_logical_block_size(q),
466 cap_str_10,
467 cap_str_2);
Christoph Hellwig7a7c9242011-02-01 21:43:48 +0100468
Christoph Hellwig449f4ec2020-11-16 15:56:56 +0100469 set_capacity_and_notify(vblk->disk, capacity);
Stefan Hajnoczidaf2a502018-01-03 16:03:39 +0000470}
471
472static void virtblk_config_changed_work(struct work_struct *work)
473{
474 struct virtio_blk *vblk =
475 container_of(work, struct virtio_blk, config_work);
Stefan Hajnoczidaf2a502018-01-03 16:03:39 +0000476
477 virtblk_update_capacity(vblk, true);
Christoph Hellwig7a7c9242011-02-01 21:43:48 +0100478}
479
480static void virtblk_config_changed(struct virtio_device *vdev)
481{
482 struct virtio_blk *vblk = vdev->priv;
483
484 queue_work(virtblk_wq, &vblk->config_work);
485}
486
Amit Shah6abd6e52011-12-22 16:58:29 +0530487static int init_vq(struct virtio_blk *vblk)
488{
Markus Elfring2ff98442016-09-13 13:43:50 +0200489 int err;
Ming Lei6a27b652014-06-26 17:41:48 +0800490 int i;
491 vq_callback_t **callbacks;
492 const char **names;
493 struct virtqueue **vqs;
494 unsigned short num_vqs;
495 struct virtio_device *vdev = vblk->vdev;
Christoph Hellwigad714732017-02-05 18:15:25 +0100496 struct irq_affinity desc = { 0, };
Amit Shah6abd6e52011-12-22 16:58:29 +0530497
Ming Lei6a27b652014-06-26 17:41:48 +0800498 err = virtio_cread_feature(vdev, VIRTIO_BLK_F_MQ,
499 struct virtio_blk_config, num_queues,
500 &num_vqs);
501 if (err)
502 num_vqs = 1;
Amit Shah6abd6e52011-12-22 16:58:29 +0530503
Dongli Zhangbf348f92019-03-27 18:36:34 +0800504 num_vqs = min_t(unsigned int, nr_cpu_ids, num_vqs);
505
Markus Elfring668866b2016-09-13 11:32:22 +0200506 vblk->vqs = kmalloc_array(num_vqs, sizeof(*vblk->vqs), GFP_KERNEL);
Minfei Huang347a5292016-08-09 16:39:20 +0800507 if (!vblk->vqs)
508 return -ENOMEM;
509
Markus Elfring668866b2016-09-13 11:32:22 +0200510 names = kmalloc_array(num_vqs, sizeof(*names), GFP_KERNEL);
511 callbacks = kmalloc_array(num_vqs, sizeof(*callbacks), GFP_KERNEL);
512 vqs = kmalloc_array(num_vqs, sizeof(*vqs), GFP_KERNEL);
Minfei Huang347a5292016-08-09 16:39:20 +0800513 if (!names || !callbacks || !vqs) {
Ming Lei6a27b652014-06-26 17:41:48 +0800514 err = -ENOMEM;
515 goto out;
516 }
517
Ming Lei6a27b652014-06-26 17:41:48 +0800518 for (i = 0; i < num_vqs; i++) {
519 callbacks[i] = virtblk_done;
520 snprintf(vblk->vqs[i].name, VQ_NAME_LEN, "req.%d", i);
521 names[i] = vblk->vqs[i].name;
522 }
523
524 /* Discover virtqueues and write information to configuration. */
Michael S. Tsirkin9b2bbdb2017-03-06 18:19:39 +0200525 err = virtio_find_vqs(vdev, num_vqs, vqs, callbacks, names, &desc);
Ming Lei6a27b652014-06-26 17:41:48 +0800526 if (err)
Minfei Huang347a5292016-08-09 16:39:20 +0800527 goto out;
Ming Lei6a27b652014-06-26 17:41:48 +0800528
529 for (i = 0; i < num_vqs; i++) {
530 spin_lock_init(&vblk->vqs[i].lock);
531 vblk->vqs[i].vq = vqs[i];
532 }
533 vblk->num_vqs = num_vqs;
534
Minfei Huang347a5292016-08-09 16:39:20 +0800535out:
Ming Lei6a27b652014-06-26 17:41:48 +0800536 kfree(vqs);
Ming Lei6a27b652014-06-26 17:41:48 +0800537 kfree(callbacks);
Ming Lei6a27b652014-06-26 17:41:48 +0800538 kfree(names);
Ming Lei6a27b652014-06-26 17:41:48 +0800539 if (err)
540 kfree(vblk->vqs);
Amit Shah6abd6e52011-12-22 16:58:29 +0530541 return err;
542}
543
Ren Mingxinc0aa3e02012-04-10 15:28:05 +0800544/*
545 * Legacy naming scheme used for virtio devices. We are stuck with it for
546 * virtio blk but don't ever use it for any new driver.
547 */
548static int virtblk_name_format(char *prefix, int index, char *buf, int buflen)
549{
550 const int base = 'z' - 'a' + 1;
551 char *begin = buf + strlen(prefix);
552 char *end = buf + buflen;
553 char *p;
554 int unit;
555
556 p = end - 1;
557 *p = '\0';
558 unit = base;
559 do {
560 if (p == begin)
561 return -EINVAL;
562 *--p = 'a' + (index % unit);
563 index = (index / unit) - 1;
564 } while (index >= 0);
565
566 memmove(begin, p, end - p);
567 memcpy(buf, prefix, strlen(prefix));
568
569 return 0;
570}
571
Paolo Bonzinicd5d5032012-07-03 15:19:37 +0200572static int virtblk_get_cache_mode(struct virtio_device *vdev)
573{
574 u8 writeback;
575 int err;
576
Rusty Russell855e0c52013-10-14 18:11:51 +1030577 err = virtio_cread_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE,
578 struct virtio_blk_config, wce,
579 &writeback);
Michael S. Tsirkin592002f2016-02-24 17:07:27 +0200580
581 /*
582 * If WCE is not configurable and flush is not available,
583 * assume no writeback cache is in use.
584 */
Paolo Bonzinicd5d5032012-07-03 15:19:37 +0200585 if (err)
Michael S. Tsirkin592002f2016-02-24 17:07:27 +0200586 writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH);
Paolo Bonzinicd5d5032012-07-03 15:19:37 +0200587
588 return writeback;
589}
590
591static void virtblk_update_cache_mode(struct virtio_device *vdev)
592{
593 u8 writeback = virtblk_get_cache_mode(vdev);
594 struct virtio_blk *vblk = vdev->priv;
595
Jens Axboead9126a2016-03-30 10:12:58 -0600596 blk_queue_write_cache(vblk->disk->queue, writeback, false);
Paolo Bonzinicd5d5032012-07-03 15:19:37 +0200597}
598
599static const char *const virtblk_cache_types[] = {
600 "write through", "write back"
601};
602
603static ssize_t
Hannes Reineckee982c4d2018-09-28 08:17:23 +0200604cache_type_store(struct device *dev, struct device_attribute *attr,
605 const char *buf, size_t count)
Paolo Bonzinicd5d5032012-07-03 15:19:37 +0200606{
607 struct gendisk *disk = dev_to_disk(dev);
608 struct virtio_blk *vblk = disk->private_data;
609 struct virtio_device *vdev = vblk->vdev;
610 int i;
Paolo Bonzinicd5d5032012-07-03 15:19:37 +0200611
612 BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE));
Andy Shevchenkof53d5aa2017-06-09 15:07:42 +0300613 i = sysfs_match_string(virtblk_cache_types, buf);
Paolo Bonzinicd5d5032012-07-03 15:19:37 +0200614 if (i < 0)
Andy Shevchenkof53d5aa2017-06-09 15:07:42 +0300615 return i;
Paolo Bonzinicd5d5032012-07-03 15:19:37 +0200616
Rusty Russell855e0c52013-10-14 18:11:51 +1030617 virtio_cwrite8(vdev, offsetof(struct virtio_blk_config, wce), i);
Paolo Bonzinicd5d5032012-07-03 15:19:37 +0200618 virtblk_update_cache_mode(vdev);
619 return count;
620}
621
622static ssize_t
Hannes Reineckee982c4d2018-09-28 08:17:23 +0200623cache_type_show(struct device *dev, struct device_attribute *attr, char *buf)
Paolo Bonzinicd5d5032012-07-03 15:19:37 +0200624{
625 struct gendisk *disk = dev_to_disk(dev);
626 struct virtio_blk *vblk = disk->private_data;
627 u8 writeback = virtblk_get_cache_mode(vblk->vdev);
628
629 BUG_ON(writeback >= ARRAY_SIZE(virtblk_cache_types));
630 return snprintf(buf, 40, "%s\n", virtblk_cache_types[writeback]);
631}
632
Hannes Reineckee982c4d2018-09-28 08:17:23 +0200633static DEVICE_ATTR_RW(cache_type);
634
635static struct attribute *virtblk_attrs[] = {
636 &dev_attr_serial.attr,
637 &dev_attr_cache_type.attr,
638 NULL,
639};
640
641static umode_t virtblk_attrs_are_visible(struct kobject *kobj,
642 struct attribute *a, int n)
643{
Tian Tao4ce79062020-08-21 09:19:15 +0800644 struct device *dev = kobj_to_dev(kobj);
Hannes Reineckee982c4d2018-09-28 08:17:23 +0200645 struct gendisk *disk = dev_to_disk(dev);
646 struct virtio_blk *vblk = disk->private_data;
647 struct virtio_device *vdev = vblk->vdev;
648
649 if (a == &dev_attr_cache_type.attr &&
650 !virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE))
651 return S_IRUGO;
652
653 return a->mode;
654}
655
656static const struct attribute_group virtblk_attr_group = {
657 .attrs = virtblk_attrs,
658 .is_visible = virtblk_attrs_are_visible,
659};
660
661static const struct attribute_group *virtblk_attr_groups[] = {
662 &virtblk_attr_group,
663 NULL,
664};
Paolo Bonzinicd5d5032012-07-03 15:19:37 +0200665
Christoph Hellwigd6296d392017-05-01 10:19:08 -0600666static int virtblk_init_request(struct blk_mq_tag_set *set, struct request *rq,
667 unsigned int hctx_idx, unsigned int numa_node)
Christoph Hellwige9b267d2014-04-15 13:59:10 -0600668{
Christoph Hellwigd6296d392017-05-01 10:19:08 -0600669 struct virtio_blk *vblk = set->driver_data;
Christoph Hellwige9b267d2014-04-15 13:59:10 -0600670 struct virtblk_req *vbr = blk_mq_rq_to_pdu(rq);
671
672 sg_init_table(vbr->sg, vblk->sg_elems);
673 return 0;
674}
675
Christoph Hellwigad714732017-02-05 18:15:25 +0100676static int virtblk_map_queues(struct blk_mq_tag_set *set)
677{
678 struct virtio_blk *vblk = set->driver_data;
679
Dongli Zhang9bc00752019-03-12 09:31:56 +0800680 return blk_mq_virtio_map_queues(&set->map[HCTX_TYPE_DEFAULT],
681 vblk->vdev, 0);
Christoph Hellwigad714732017-02-05 18:15:25 +0100682}
683
Eric Biggersf363b082017-03-30 13:39:16 -0700684static const struct blk_mq_ops virtio_mq_ops = {
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600685 .queue_rq = virtio_queue_rq,
Jens Axboe944e7c82018-11-26 11:00:12 -0700686 .commit_rqs = virtio_commit_rqs,
Christoph Hellwig5124c282014-02-10 03:24:39 -0800687 .complete = virtblk_request_done,
Christoph Hellwig24d2f902014-04-15 14:14:00 -0600688 .init_request = virtblk_init_request,
Christoph Hellwigad714732017-02-05 18:15:25 +0100689 .map_queues = virtblk_map_queues,
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600690};
691
Christoph Hellwig24d2f902014-04-15 14:14:00 -0600692static unsigned int virtblk_queue_depth;
693module_param_named(queue_depth, virtblk_queue_depth, uint, 0444);
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600694
Xie Yongji82e89ea2021-08-09 18:16:09 +0800695static int virtblk_validate(struct virtio_device *vdev)
696{
697 u32 blk_size;
698
699 if (!vdev->config->get) {
700 dev_err(&vdev->dev, "%s failure: config access disabled\n",
701 __func__);
702 return -EINVAL;
703 }
704
705 if (!virtio_has_feature(vdev, VIRTIO_BLK_F_BLK_SIZE))
706 return 0;
707
708 blk_size = virtio_cread32(vdev,
709 offsetof(struct virtio_blk_config, blk_size));
710
711 if (blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE)
712 __virtio_clear_bit(vdev, VIRTIO_BLK_F_BLK_SIZE);
713
714 return 0;
715}
716
Greg Kroah-Hartman8d85fce2012-12-21 15:13:49 -0800717static int virtblk_probe(struct virtio_device *vdev)
Rusty Russelle467cde2007-10-22 11:03:38 +1000718{
719 struct virtio_blk *vblk;
Christoph Hellwig69740c82010-02-24 14:22:25 -0600720 struct request_queue *q;
Michael S. Tsirkin5087a502011-10-30 21:29:59 +0200721 int err, index;
Asias Hea98755c2012-08-08 16:07:04 +0800722
Joerg Roedelfd1068e2019-02-07 12:59:17 +0100723 u32 v, blk_size, max_size, sg_elems, opt_io_size;
Christoph Hellwig69740c82010-02-24 14:22:25 -0600724 u16 min_io_size;
725 u8 physical_block_exp, alignment_offset;
Joseph Qid1e9aa92021-01-22 17:21:46 +0800726 unsigned int queue_depth;
Rusty Russelle467cde2007-10-22 11:03:38 +1000727
Michael S. Tsirkin5087a502011-10-30 21:29:59 +0200728 err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS),
729 GFP_KERNEL);
730 if (err < 0)
731 goto out;
732 index = err;
Christian Borntraeger4f3bf192008-01-31 15:53:53 +0100733
Rusty Russell0864b792008-12-30 09:26:05 -0600734 /* We need to know how many segments before we allocate. */
Rusty Russell855e0c52013-10-14 18:11:51 +1030735 err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SEG_MAX,
736 struct virtio_blk_config, seg_max,
737 &sg_elems);
Christoph Hellwiga5b365a2010-05-25 14:17:54 +0200738
739 /* We need at least one SG element, whatever they say. */
740 if (err || !sg_elems)
Rusty Russell0864b792008-12-30 09:26:05 -0600741 sg_elems = 1;
742
Stefan Hajnoczi63947b32021-05-24 16:40:20 +0100743 /* Prevent integer overflows and honor max vq size */
744 sg_elems = min_t(u32, sg_elems, VIRTIO_BLK_MAX_SG_ELEMS - 2);
745
746 /* We need extra sg elements at head and tail. */
Rusty Russell0864b792008-12-30 09:26:05 -0600747 sg_elems += 2;
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600748 vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL);
Rusty Russelle467cde2007-10-22 11:03:38 +1000749 if (!vblk) {
750 err = -ENOMEM;
Michael S. Tsirkin5087a502011-10-30 21:29:59 +0200751 goto out_free_index;
Rusty Russelle467cde2007-10-22 11:03:38 +1000752 }
753
Stefan Hajnoczi90b5feb2020-04-30 15:04:42 +0100754 /* This reference is dropped in virtblk_remove(). */
755 refcount_set(&vblk->refs, 1);
756 mutex_init(&vblk->vdev_mutex);
757
Rusty Russelle467cde2007-10-22 11:03:38 +1000758 vblk->vdev = vdev;
Rusty Russell0864b792008-12-30 09:26:05 -0600759 vblk->sg_elems = sg_elems;
Asias Hea98755c2012-08-08 16:07:04 +0800760
Christoph Hellwig7a7c9242011-02-01 21:43:48 +0100761 INIT_WORK(&vblk->config_work, virtblk_config_changed_work);
Rusty Russelle467cde2007-10-22 11:03:38 +1000762
Amit Shah6abd6e52011-12-22 16:58:29 +0530763 err = init_vq(vblk);
764 if (err)
Rusty Russelle467cde2007-10-22 11:03:38 +1000765 goto out_free_vblk;
Rusty Russelle467cde2007-10-22 11:03:38 +1000766
Rusty Russellfc4324b2014-03-19 17:08:24 +1030767 /* Default queue sizing is to fill the ring. */
Max Gurtovoy6105d1f2021-09-05 11:57:17 +0300768 if (!virtblk_queue_depth) {
Joseph Qid1e9aa92021-01-22 17:21:46 +0800769 queue_depth = vblk->vqs[0].vq->num_free;
Rusty Russellfc4324b2014-03-19 17:08:24 +1030770 /* ... but without indirect descs, we use 2 descs per req */
771 if (!virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC))
Joseph Qid1e9aa92021-01-22 17:21:46 +0800772 queue_depth /= 2;
773 } else {
774 queue_depth = virtblk_queue_depth;
Rusty Russellfc4324b2014-03-19 17:08:24 +1030775 }
Christoph Hellwig24d2f902014-04-15 14:14:00 -0600776
777 memset(&vblk->tag_set, 0, sizeof(vblk->tag_set));
778 vblk->tag_set.ops = &virtio_mq_ops;
Joseph Qid1e9aa92021-01-22 17:21:46 +0800779 vblk->tag_set.queue_depth = queue_depth;
Christoph Hellwig24d2f902014-04-15 14:14:00 -0600780 vblk->tag_set.numa_node = NUMA_NO_NODE;
781 vblk->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
782 vblk->tag_set.cmd_size =
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600783 sizeof(struct virtblk_req) +
784 sizeof(struct scatterlist) * sg_elems;
Christoph Hellwig24d2f902014-04-15 14:14:00 -0600785 vblk->tag_set.driver_data = vblk;
Ming Lei6a27b652014-06-26 17:41:48 +0800786 vblk->tag_set.nr_hw_queues = vblk->num_vqs;
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600787
Christoph Hellwig24d2f902014-04-15 14:14:00 -0600788 err = blk_mq_alloc_tag_set(&vblk->tag_set);
789 if (err)
Christoph Hellwig89a5f062021-06-02 09:53:19 +0300790 goto out_free_vq;
Christoph Hellwig24d2f902014-04-15 14:14:00 -0600791
Christoph Hellwig89a5f062021-06-02 09:53:19 +0300792 vblk->disk = blk_mq_alloc_disk(&vblk->tag_set, vblk);
793 if (IS_ERR(vblk->disk)) {
794 err = PTR_ERR(vblk->disk);
Christoph Hellwig24d2f902014-04-15 14:14:00 -0600795 goto out_free_tags;
Rusty Russelle467cde2007-10-22 11:03:38 +1000796 }
Christoph Hellwig89a5f062021-06-02 09:53:19 +0300797 q = vblk->disk->queue;
Fernando Luis Vázquez Cao7d116b62008-10-27 18:45:15 +0900798
Ren Mingxinc0aa3e02012-04-10 15:28:05 +0800799 virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN);
Christian Borntraegerd50ed902008-02-01 09:05:00 +0100800
Rusty Russelle467cde2007-10-22 11:03:38 +1000801 vblk->disk->major = major;
Christian Borntraegerd50ed902008-02-01 09:05:00 +0100802 vblk->disk->first_minor = index_to_minor(index);
Christoph Hellwig89a5f062021-06-02 09:53:19 +0300803 vblk->disk->minors = 1 << PART_BITS;
Rusty Russelle467cde2007-10-22 11:03:38 +1000804 vblk->disk->private_data = vblk;
805 vblk->disk->fops = &virtblk_fops;
Fam Zheng5fa31422015-09-06 17:05:42 +0800806 vblk->disk->flags |= GENHD_FL_EXT_DEVT;
Michael S. Tsirkin5087a502011-10-30 21:29:59 +0200807 vblk->index = index;
Christian Borntraeger4f3bf192008-01-31 15:53:53 +0100808
Tejun Heo02c42b72010-09-03 11:56:18 +0200809 /* configure queue flush support */
Paolo Bonzinicd5d5032012-07-03 15:19:37 +0200810 virtblk_update_cache_mode(vdev);
Rusty Russelle467cde2007-10-22 11:03:38 +1000811
Christian Borntraeger3ef53602008-05-16 11:17:03 +0200812 /* If disk is read-only in the host, the guest should obey */
813 if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
814 set_disk_ro(vblk->disk, 1);
815
Rusty Russell0864b792008-12-30 09:26:05 -0600816 /* We can handle whatever the host told us to handle. */
Martin K. Petersenee714f22010-03-10 00:48:32 -0500817 blk_queue_max_segments(q, vblk->sg_elems-2);
Rusty Russell0864b792008-12-30 09:26:05 -0600818
Rusty Russell4b7f7e22008-12-30 09:26:04 -0600819 /* No real sector limit. */
Martin K. Petersenee714f22010-03-10 00:48:32 -0500820 blk_queue_max_hw_sectors(q, -1U);
Rusty Russell4b7f7e22008-12-30 09:26:04 -0600821
Joerg Roedelfd1068e2019-02-07 12:59:17 +0100822 max_size = virtio_max_dma_size(vdev);
823
Rusty Russella586d4f2008-02-04 23:49:56 -0500824 /* Host can optionally specify maximum segment size and number of
825 * segments. */
Rusty Russell855e0c52013-10-14 18:11:51 +1030826 err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SIZE_MAX,
827 struct virtio_blk_config, size_max, &v);
Rusty Russelle467cde2007-10-22 11:03:38 +1000828 if (!err)
Joerg Roedelfd1068e2019-02-07 12:59:17 +0100829 max_size = min(max_size, v);
830
831 blk_queue_max_segment_size(q, max_size);
Rusty Russelle467cde2007-10-22 11:03:38 +1000832
Christian Borntraeger066f4d82008-05-29 11:08:26 +0200833 /* Host can optionally specify the block size of the device */
Rusty Russell855e0c52013-10-14 18:11:51 +1030834 err = virtio_cread_feature(vdev, VIRTIO_BLK_F_BLK_SIZE,
835 struct virtio_blk_config, blk_size,
836 &blk_size);
Christian Borntraeger066f4d82008-05-29 11:08:26 +0200837 if (!err)
Christoph Hellwig69740c82010-02-24 14:22:25 -0600838 blk_queue_logical_block_size(q, blk_size);
839 else
840 blk_size = queue_logical_block_size(q);
841
Max Gurtovoy6105d1f2021-09-05 11:57:17 +0300842 if (blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE) {
Xie Yongji82e89ea2021-08-09 18:16:09 +0800843 dev_err(&vdev->dev,
844 "block size is changed unexpectedly, now is %u\n",
845 blk_size);
846 err = -EINVAL;
847 goto err_cleanup_disk;
848 }
849
Christoph Hellwig69740c82010-02-24 14:22:25 -0600850 /* Use topology information if available */
Rusty Russell855e0c52013-10-14 18:11:51 +1030851 err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
852 struct virtio_blk_config, physical_block_exp,
853 &physical_block_exp);
Christoph Hellwig69740c82010-02-24 14:22:25 -0600854 if (!err && physical_block_exp)
855 blk_queue_physical_block_size(q,
856 blk_size * (1 << physical_block_exp));
857
Rusty Russell855e0c52013-10-14 18:11:51 +1030858 err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
859 struct virtio_blk_config, alignment_offset,
860 &alignment_offset);
Christoph Hellwig69740c82010-02-24 14:22:25 -0600861 if (!err && alignment_offset)
862 blk_queue_alignment_offset(q, blk_size * alignment_offset);
863
Rusty Russell855e0c52013-10-14 18:11:51 +1030864 err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
865 struct virtio_blk_config, min_io_size,
866 &min_io_size);
Christoph Hellwig69740c82010-02-24 14:22:25 -0600867 if (!err && min_io_size)
868 blk_queue_io_min(q, blk_size * min_io_size);
869
Rusty Russell855e0c52013-10-14 18:11:51 +1030870 err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
871 struct virtio_blk_config, opt_io_size,
872 &opt_io_size);
Christoph Hellwig69740c82010-02-24 14:22:25 -0600873 if (!err && opt_io_size)
874 blk_queue_io_opt(q, blk_size * opt_io_size);
875
Changpeng Liu1f238162018-11-01 15:40:35 -0700876 if (virtio_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) {
877 q->limits.discard_granularity = blk_size;
878
879 virtio_cread(vdev, struct virtio_blk_config,
880 discard_sector_alignment, &v);
881 q->limits.discard_alignment = v ? v << SECTOR_SHIFT : 0;
882
883 virtio_cread(vdev, struct virtio_blk_config,
884 max_discard_sectors, &v);
885 blk_queue_max_discard_sectors(q, v ? v : UINT_MAX);
886
887 virtio_cread(vdev, struct virtio_blk_config, max_discard_seg,
888 &v);
889 blk_queue_max_discard_segments(q,
890 min_not_zero(v,
891 MAX_DISCARD_SEGMENTS));
892
893 blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
894 }
895
896 if (virtio_has_feature(vdev, VIRTIO_BLK_F_WRITE_ZEROES)) {
897 virtio_cread(vdev, struct virtio_blk_config,
898 max_write_zeroes_sectors, &v);
899 blk_queue_max_write_zeroes_sectors(q, v ? v : UINT_MAX);
900 }
901
Stefan Hajnoczidaf2a502018-01-03 16:03:39 +0000902 virtblk_update_capacity(vblk, false);
Michael S. Tsirkin7a113702014-10-15 10:22:30 +1030903 virtio_device_ready(vdev);
904
Hannes Reineckee982c4d2018-09-28 08:17:23 +0200905 device_add_disk(&vdev->dev, vblk->disk, virtblk_attr_groups);
Rusty Russelle467cde2007-10-22 11:03:38 +1000906 return 0;
907
Xie Yongji82e89ea2021-08-09 18:16:09 +0800908err_cleanup_disk:
909 blk_cleanup_disk(vblk->disk);
Christoph Hellwig24d2f902014-04-15 14:14:00 -0600910out_free_tags:
911 blk_mq_free_tag_set(&vblk->tag_set);
Rusty Russelle467cde2007-10-22 11:03:38 +1000912out_free_vq:
Michael S. Tsirkind2a7ddd2009-06-12 22:16:36 -0600913 vdev->config->del_vqs(vdev);
Hou Taoe7eea442020-06-15 12:14:59 +0800914 kfree(vblk->vqs);
Rusty Russelle467cde2007-10-22 11:03:38 +1000915out_free_vblk:
916 kfree(vblk);
Michael S. Tsirkin5087a502011-10-30 21:29:59 +0200917out_free_index:
918 ida_simple_remove(&vd_index_ida, index);
Rusty Russelle467cde2007-10-22 11:03:38 +1000919out:
920 return err;
921}
922
Greg Kroah-Hartman8d85fce2012-12-21 15:13:49 -0800923static void virtblk_remove(struct virtio_device *vdev)
Rusty Russelle467cde2007-10-22 11:03:38 +1000924{
925 struct virtio_blk *vblk = vdev->priv;
Rusty Russelle467cde2007-10-22 11:03:38 +1000926
Michael S. Tsirkincc74f712014-10-15 10:22:26 +1030927 /* Make sure no work handler is accessing the device. */
928 flush_work(&vblk->config_work);
Christoph Hellwig7a7c9242011-02-01 21:43:48 +0100929
Asias He02e2b122012-05-25 10:34:47 +0800930 del_gendisk(vblk->disk);
Christoph Hellwig89a5f062021-06-02 09:53:19 +0300931 blk_cleanup_disk(vblk->disk);
Christoph Hellwig24d2f902014-04-15 14:14:00 -0600932 blk_mq_free_tag_set(&vblk->tag_set);
933
Stefan Hajnoczi90b5feb2020-04-30 15:04:42 +0100934 mutex_lock(&vblk->vdev_mutex);
935
Rusty Russell6e5aa7e2008-02-04 23:50:03 -0500936 /* Stop all the virtqueues. */
937 vdev->config->reset(vdev);
938
Stefan Hajnoczi90b5feb2020-04-30 15:04:42 +0100939 /* Virtqueues are stopped, nothing can use vblk->vdev anymore. */
940 vblk->vdev = NULL;
941
Michael S. Tsirkind2a7ddd2009-06-12 22:16:36 -0600942 vdev->config->del_vqs(vdev);
Ming Lei6a27b652014-06-26 17:41:48 +0800943 kfree(vblk->vqs);
Alexander Graff4953fe2013-01-02 15:37:17 +1030944
Stefan Hajnoczi90b5feb2020-04-30 15:04:42 +0100945 mutex_unlock(&vblk->vdev_mutex);
946
947 virtblk_put(vblk);
Rusty Russelle467cde2007-10-22 11:03:38 +1000948}
949
Aaron Lu89107002013-09-17 09:25:23 +0930950#ifdef CONFIG_PM_SLEEP
Amit Shahf8fb5bc2011-12-22 16:58:30 +0530951static int virtblk_freeze(struct virtio_device *vdev)
952{
953 struct virtio_blk *vblk = vdev->priv;
954
955 /* Ensure we don't receive any more interrupts */
956 vdev->config->reset(vdev);
957
Michael S. Tsirkincc74f712014-10-15 10:22:26 +1030958 /* Make sure no work handler is accessing the device. */
Amit Shahf8fb5bc2011-12-22 16:58:30 +0530959 flush_work(&vblk->config_work);
960
Sagi Grimberg9b3e9902017-07-04 10:03:03 +0300961 blk_mq_quiesce_queue(vblk->disk->queue);
Amit Shahf8fb5bc2011-12-22 16:58:30 +0530962
963 vdev->config->del_vqs(vdev);
Xie Yongjib71ba222021-05-17 16:43:32 +0800964 kfree(vblk->vqs);
965
Amit Shahf8fb5bc2011-12-22 16:58:30 +0530966 return 0;
967}
968
969static int virtblk_restore(struct virtio_device *vdev)
970{
971 struct virtio_blk *vblk = vdev->priv;
972 int ret;
973
Amit Shahf8fb5bc2011-12-22 16:58:30 +0530974 ret = init_vq(vdev->priv);
Michael S. Tsirkin6d62c372014-10-15 10:22:32 +1030975 if (ret)
976 return ret;
Jens Axboe1cf7e9c2013-11-01 10:52:52 -0600977
Michael S. Tsirkin6d62c372014-10-15 10:22:32 +1030978 virtio_device_ready(vdev);
979
Sagi Grimberg9b3e9902017-07-04 10:03:03 +0300980 blk_mq_unquiesce_queue(vblk->disk->queue);
Michael S. Tsirkin6d62c372014-10-15 10:22:32 +1030981 return 0;
Amit Shahf8fb5bc2011-12-22 16:58:30 +0530982}
983#endif
984
Márton Németh47483e22010-01-10 13:40:02 +0100985static const struct virtio_device_id id_table[] = {
Rusty Russelle467cde2007-10-22 11:03:38 +1000986 { VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID },
987 { 0 },
988};
989
Michael S. Tsirkin19c1c5a2014-10-07 16:39:49 +0200990static unsigned int features_legacy[] = {
Tejun Heo02c42b72010-09-03 11:56:18 +0200991 VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
Christoph Hellwig97b50a62017-01-28 09:32:53 +0100992 VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
Michael S. Tsirkin592002f2016-02-24 17:07:27 +0200993 VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE,
Changpeng Liu1f238162018-11-01 15:40:35 -0700994 VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_WRITE_ZEROES,
Michael S. Tsirkin19c1c5a2014-10-07 16:39:49 +0200995}
996;
997static unsigned int features[] = {
998 VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
999 VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
Michael S. Tsirkin592002f2016-02-24 17:07:27 +02001000 VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE,
Changpeng Liu1f238162018-11-01 15:40:35 -07001001 VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_WRITE_ZEROES,
Rusty Russellc45a6812008-05-02 21:50:50 -05001002};
1003
Greg Kroah-Hartman8d85fce2012-12-21 15:13:49 -08001004static struct virtio_driver virtio_blk = {
Michael S. Tsirkin19c1c5a2014-10-07 16:39:49 +02001005 .feature_table = features,
1006 .feature_table_size = ARRAY_SIZE(features),
1007 .feature_table_legacy = features_legacy,
1008 .feature_table_size_legacy = ARRAY_SIZE(features_legacy),
1009 .driver.name = KBUILD_MODNAME,
1010 .driver.owner = THIS_MODULE,
1011 .id_table = id_table,
Xie Yongji82e89ea2021-08-09 18:16:09 +08001012 .validate = virtblk_validate,
Michael S. Tsirkin19c1c5a2014-10-07 16:39:49 +02001013 .probe = virtblk_probe,
1014 .remove = virtblk_remove,
1015 .config_changed = virtblk_config_changed,
Aaron Lu89107002013-09-17 09:25:23 +09301016#ifdef CONFIG_PM_SLEEP
Michael S. Tsirkin19c1c5a2014-10-07 16:39:49 +02001017 .freeze = virtblk_freeze,
1018 .restore = virtblk_restore,
Amit Shahf8fb5bc2011-12-22 16:58:30 +05301019#endif
Rusty Russelle467cde2007-10-22 11:03:38 +10001020};
1021
1022static int __init init(void)
1023{
Christoph Hellwig7a7c9242011-02-01 21:43:48 +01001024 int error;
1025
1026 virtblk_wq = alloc_workqueue("virtio-blk", 0, 0);
1027 if (!virtblk_wq)
1028 return -ENOMEM;
1029
Christian Borntraeger4f3bf192008-01-31 15:53:53 +01001030 major = register_blkdev(0, "virtblk");
Christoph Hellwig7a7c9242011-02-01 21:43:48 +01001031 if (major < 0) {
1032 error = major;
1033 goto out_destroy_workqueue;
1034 }
1035
1036 error = register_virtio_driver(&virtio_blk);
1037 if (error)
1038 goto out_unregister_blkdev;
1039 return 0;
1040
1041out_unregister_blkdev:
1042 unregister_blkdev(major, "virtblk");
1043out_destroy_workqueue:
1044 destroy_workqueue(virtblk_wq);
1045 return error;
Rusty Russelle467cde2007-10-22 11:03:38 +10001046}
1047
1048static void __exit fini(void)
1049{
Rusty Russelle467cde2007-10-22 11:03:38 +10001050 unregister_virtio_driver(&virtio_blk);
Michael S. Tsirkin38f37b52014-10-23 18:57:19 +03001051 unregister_blkdev(major, "virtblk");
Christoph Hellwig7a7c9242011-02-01 21:43:48 +01001052 destroy_workqueue(virtblk_wq);
Rusty Russelle467cde2007-10-22 11:03:38 +10001053}
1054module_init(init);
1055module_exit(fini);
1056
1057MODULE_DEVICE_TABLE(virtio, id_table);
1058MODULE_DESCRIPTION("Virtio block driver");
1059MODULE_LICENSE("GPL");