Skip to content

Commit 43e1b12

Browse files
committed
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
Pull virtio updates from Michael Tsirkin: "vhost and virtio fixes and features: - Hardening work by Jason - vdpa driver for Alibaba ENI - Performance tweaks for virtio blk - virtio rng rework using an internal buffer - mac/mtu programming for mlx5 vdpa - Misc fixes, cleanups" * tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: (45 commits) vdpa/mlx5: Forward only packets with allowed MAC address vdpa/mlx5: Support configuration of MAC vdpa/mlx5: Fix clearing of VIRTIO_NET_F_MAC feature bit vdpa_sim_net: Enable user to set mac address and mtu vdpa: Enable user to set mac and mtu of vdpa device vdpa: Use kernel coding style for structure comments vdpa: Introduce query of device config layout vdpa: Introduce and use vdpa device get, set config helpers virtio-scsi: don't let virtio core to validate used buffer length virtio-blk: don't let virtio core to validate used length virtio-net: don't let virtio core to validate used length virtio_ring: validate used buffer length virtio_blk: correct types for status handling virtio_blk: allow 0 as num_request_queues i2c: virtio: Add support for zero-length requests virtio-blk: fixup coccinelle warnings virtio_ring: fix typos in vring_desc_extra virtio-pci: harden INTX interrupts virtio_pci: harden MSI-X interrupts virtio_config: introduce a new .enable_cbs method ...
2 parents d4ec3d5 + 540061a commit 43e1b12

36 files changed

+1780
-296
lines changed

MAINTAINERS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20083,6 +20083,13 @@ S: Maintained
2008320083
F: drivers/i2c/busses/i2c-virtio.c
2008420084
F: include/uapi/linux/virtio_i2c.h
2008520085

20086+
VIRTIO PMEM DRIVER
20087+
M: Pankaj Gupta <[email protected]>
20088+
20089+
S: Maintained
20090+
F: drivers/nvdimm/virtio_pmem.c
20091+
F: drivers/nvdimm/nd_virtio.c
20092+
2008620093
VIRTUAL BOX GUEST DEVICE DRIVER
2008720094
M: Hans de Goede <[email protected]>
2008820095
M: Arnd Bergmann <[email protected]>

drivers/block/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ config XEN_BLKDEV_BACKEND
371371
config VIRTIO_BLK
372372
tristate "Virtio block driver"
373373
depends on VIRTIO
374+
select SG_POOL
374375
help
375376
This is the virtual block driver for virtio. It can be used with
376377
QEMU based VMMs (like KVM or Xen). Say Y or M.

drivers/block/virtio_blk.c

Lines changed: 119 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@
2424
/* The maximum number of sg elements that fit into a virtqueue */
2525
#define VIRTIO_BLK_MAX_SG_ELEMS 32768
2626

27+
#ifdef CONFIG_ARCH_NO_SG_CHAIN
28+
#define VIRTIO_BLK_INLINE_SG_CNT 0
29+
#else
30+
#define VIRTIO_BLK_INLINE_SG_CNT 2
31+
#endif
32+
33+
static unsigned int num_request_queues;
34+
module_param(num_request_queues, uint, 0644);
35+
MODULE_PARM_DESC(num_request_queues,
36+
"Limit the number of request queues to use for blk device. "
37+
"0 for no limit. "
38+
"Values > nr_cpu_ids truncated to nr_cpu_ids.");
39+
2740
static int major;
2841
static DEFINE_IDA(vd_index_ida);
2942

@@ -77,6 +90,7 @@ struct virtio_blk {
7790
struct virtblk_req {
7891
struct virtio_blk_outhdr out_hdr;
7992
u8 status;
93+
struct sg_table sg_table;
8094
struct scatterlist sg[];
8195
};
8296

@@ -162,12 +176,93 @@ static int virtblk_setup_discard_write_zeroes(struct request *req, bool unmap)
162176
return 0;
163177
}
164178

165-
static inline void virtblk_request_done(struct request *req)
179+
static void virtblk_unmap_data(struct request *req, struct virtblk_req *vbr)
166180
{
167-
struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
181+
if (blk_rq_nr_phys_segments(req))
182+
sg_free_table_chained(&vbr->sg_table,
183+
VIRTIO_BLK_INLINE_SG_CNT);
184+
}
185+
186+
static int virtblk_map_data(struct blk_mq_hw_ctx *hctx, struct request *req,
187+
struct virtblk_req *vbr)
188+
{
189+
int err;
190+
191+
if (!blk_rq_nr_phys_segments(req))
192+
return 0;
193+
194+
vbr->sg_table.sgl = vbr->sg;
195+
err = sg_alloc_table_chained(&vbr->sg_table,
196+
blk_rq_nr_phys_segments(req),
197+
vbr->sg_table.sgl,
198+
VIRTIO_BLK_INLINE_SG_CNT);
199+
if (unlikely(err))
200+
return -ENOMEM;
168201

202+
return blk_rq_map_sg(hctx->queue, req, vbr->sg_table.sgl);
203+
}
204+
205+
static void virtblk_cleanup_cmd(struct request *req)
206+
{
169207
if (req->rq_flags & RQF_SPECIAL_PAYLOAD)
170208
kfree(bvec_virt(&req->special_vec));
209+
}
210+
211+
static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev,
212+
struct request *req,
213+
struct virtblk_req *vbr)
214+
{
215+
bool unmap = false;
216+
u32 type;
217+
218+
vbr->out_hdr.sector = 0;
219+
220+
switch (req_op(req)) {
221+
case REQ_OP_READ:
222+
type = VIRTIO_BLK_T_IN;
223+
vbr->out_hdr.sector = cpu_to_virtio64(vdev,
224+
blk_rq_pos(req));
225+
break;
226+
case REQ_OP_WRITE:
227+
type = VIRTIO_BLK_T_OUT;
228+
vbr->out_hdr.sector = cpu_to_virtio64(vdev,
229+
blk_rq_pos(req));
230+
break;
231+
case REQ_OP_FLUSH:
232+
type = VIRTIO_BLK_T_FLUSH;
233+
break;
234+
case REQ_OP_DISCARD:
235+
type = VIRTIO_BLK_T_DISCARD;
236+
break;
237+
case REQ_OP_WRITE_ZEROES:
238+
type = VIRTIO_BLK_T_WRITE_ZEROES;
239+
unmap = !(req->cmd_flags & REQ_NOUNMAP);
240+
break;
241+
case REQ_OP_DRV_IN:
242+
type = VIRTIO_BLK_T_GET_ID;
243+
break;
244+
default:
245+
WARN_ON_ONCE(1);
246+
return BLK_STS_IOERR;
247+
}
248+
249+
vbr->out_hdr.type = cpu_to_virtio32(vdev, type);
250+
vbr->out_hdr.ioprio = cpu_to_virtio32(vdev, req_get_ioprio(req));
251+
252+
if (type == VIRTIO_BLK_T_DISCARD || type == VIRTIO_BLK_T_WRITE_ZEROES) {
253+
if (virtblk_setup_discard_write_zeroes(req, unmap))
254+
return BLK_STS_RESOURCE;
255+
}
256+
257+
return 0;
258+
}
259+
260+
static inline void virtblk_request_done(struct request *req)
261+
{
262+
struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
263+
264+
virtblk_unmap_data(req, vbr);
265+
virtblk_cleanup_cmd(req);
171266
blk_mq_end_request(req, virtblk_result(vbr));
172267
}
173268

@@ -223,59 +318,26 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
223318
unsigned long flags;
224319
unsigned int num;
225320
int qid = hctx->queue_num;
226-
int err;
227321
bool notify = false;
228-
bool unmap = false;
229-
u32 type;
322+
blk_status_t status;
323+
int err;
230324

231325
BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems);
232326

233-
switch (req_op(req)) {
234-
case REQ_OP_READ:
235-
case REQ_OP_WRITE:
236-
type = 0;
237-
break;
238-
case REQ_OP_FLUSH:
239-
type = VIRTIO_BLK_T_FLUSH;
240-
break;
241-
case REQ_OP_DISCARD:
242-
type = VIRTIO_BLK_T_DISCARD;
243-
break;
244-
case REQ_OP_WRITE_ZEROES:
245-
type = VIRTIO_BLK_T_WRITE_ZEROES;
246-
unmap = !(req->cmd_flags & REQ_NOUNMAP);
247-
break;
248-
case REQ_OP_DRV_IN:
249-
type = VIRTIO_BLK_T_GET_ID;
250-
break;
251-
default:
252-
WARN_ON_ONCE(1);
253-
return BLK_STS_IOERR;
254-
}
255-
256-
vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, type);
257-
vbr->out_hdr.sector = type ?
258-
0 : cpu_to_virtio64(vblk->vdev, blk_rq_pos(req));
259-
vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(req));
327+
status = virtblk_setup_cmd(vblk->vdev, req, vbr);
328+
if (unlikely(status))
329+
return status;
260330

261331
blk_mq_start_request(req);
262332

263-
if (type == VIRTIO_BLK_T_DISCARD || type == VIRTIO_BLK_T_WRITE_ZEROES) {
264-
err = virtblk_setup_discard_write_zeroes(req, unmap);
265-
if (err)
266-
return BLK_STS_RESOURCE;
267-
}
268-
269-
num = blk_rq_map_sg(hctx->queue, req, vbr->sg);
270-
if (num) {
271-
if (rq_data_dir(req) == WRITE)
272-
vbr->out_hdr.type |= cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_OUT);
273-
else
274-
vbr->out_hdr.type |= cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_IN);
333+
num = virtblk_map_data(hctx, req, vbr);
334+
if (unlikely(num < 0)) {
335+
virtblk_cleanup_cmd(req);
336+
return BLK_STS_RESOURCE;
275337
}
276338

277339
spin_lock_irqsave(&vblk->vqs[qid].lock, flags);
278-
err = virtblk_add_req(vblk->vqs[qid].vq, vbr, vbr->sg, num);
340+
err = virtblk_add_req(vblk->vqs[qid].vq, vbr, vbr->sg_table.sgl, num);
279341
if (err) {
280342
virtqueue_kick(vblk->vqs[qid].vq);
281343
/* Don't stop the queue if -ENOMEM: we may have failed to
@@ -284,6 +346,8 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
284346
if (err == -ENOSPC)
285347
blk_mq_stop_hw_queue(hctx);
286348
spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
349+
virtblk_unmap_data(req, vbr);
350+
virtblk_cleanup_cmd(req);
287351
switch (err) {
288352
case -ENOSPC:
289353
return BLK_STS_DEV_RESOURCE;
@@ -497,8 +561,14 @@ static int init_vq(struct virtio_blk *vblk)
497561
&num_vqs);
498562
if (err)
499563
num_vqs = 1;
564+
if (!err && !num_vqs) {
565+
dev_err(&vdev->dev, "MQ advertised but zero queues reported\n");
566+
return -EINVAL;
567+
}
500568

501-
num_vqs = min_t(unsigned int, nr_cpu_ids, num_vqs);
569+
num_vqs = min_t(unsigned int,
570+
min_not_zero(num_request_queues, nr_cpu_ids),
571+
num_vqs);
502572

503573
vblk->vqs = kmalloc_array(num_vqs, sizeof(*vblk->vqs), GFP_KERNEL);
504574
if (!vblk->vqs)
@@ -624,7 +694,7 @@ cache_type_show(struct device *dev, struct device_attribute *attr, char *buf)
624694
u8 writeback = virtblk_get_cache_mode(vblk->vdev);
625695

626696
BUG_ON(writeback >= ARRAY_SIZE(virtblk_cache_types));
627-
return snprintf(buf, 40, "%s\n", virtblk_cache_types[writeback]);
697+
return sysfs_emit(buf, "%s\n", virtblk_cache_types[writeback]);
628698
}
629699

630700
static DEVICE_ATTR_RW(cache_type);
@@ -660,16 +730,6 @@ static const struct attribute_group *virtblk_attr_groups[] = {
660730
NULL,
661731
};
662732

663-
static int virtblk_init_request(struct blk_mq_tag_set *set, struct request *rq,
664-
unsigned int hctx_idx, unsigned int numa_node)
665-
{
666-
struct virtio_blk *vblk = set->driver_data;
667-
struct virtblk_req *vbr = blk_mq_rq_to_pdu(rq);
668-
669-
sg_init_table(vbr->sg, vblk->sg_elems);
670-
return 0;
671-
}
672-
673733
static int virtblk_map_queues(struct blk_mq_tag_set *set)
674734
{
675735
struct virtio_blk *vblk = set->driver_data;
@@ -682,7 +742,6 @@ static const struct blk_mq_ops virtio_mq_ops = {
682742
.queue_rq = virtio_queue_rq,
683743
.commit_rqs = virtio_commit_rqs,
684744
.complete = virtblk_request_done,
685-
.init_request = virtblk_init_request,
686745
.map_queues = virtblk_map_queues,
687746
};
688747

@@ -762,7 +821,7 @@ static int virtblk_probe(struct virtio_device *vdev)
762821
vblk->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
763822
vblk->tag_set.cmd_size =
764823
sizeof(struct virtblk_req) +
765-
sizeof(struct scatterlist) * sg_elems;
824+
sizeof(struct scatterlist) * VIRTIO_BLK_INLINE_SG_CNT;
766825
vblk->tag_set.driver_data = vblk;
767826
vblk->tag_set.nr_hw_queues = vblk->num_vqs;
768827

@@ -990,6 +1049,7 @@ static struct virtio_driver virtio_blk = {
9901049
.feature_table_size = ARRAY_SIZE(features),
9911050
.feature_table_legacy = features_legacy,
9921051
.feature_table_size_legacy = ARRAY_SIZE(features_legacy),
1052+
.suppress_used_validation = true,
9931053
.driver.name = KBUILD_MODNAME,
9941054
.driver.owner = THIS_MODULE,
9951055
.id_table = id_table,

0 commit comments

Comments
 (0)