All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHSET 0/17] Convert drivers to blk-mq
@ 2018-10-11 16:58 Jens Axboe
  2018-10-11 16:58 ` [PATCH 01/17] sunvdc: convert " Jens Axboe
                   ` (16 more replies)
  0 siblings, 17 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:58 UTC (permalink / raw)
  To: linux-block

The long term plan has always been to deprecate and remove the
legacy request_fn based IO path. This also means killing all that
code, and going back to maintaining a single IO stack again. To
accomplish this, we need to convert the remaining drivers to blk-mq.

This converts everything but the floppy drivers, which should be
coming shortly as well.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH 01/17] sunvdc: convert to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
@ 2018-10-11 16:58 ` Jens Axboe
  2018-10-15 10:38   ` Ming Lei
  2018-10-11 16:58 ` [PATCH 02/17] sx8: " Jens Axboe
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:58 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe, David Miller

Convert from the old request_fn style driver to blk-mq.

Cc: David Miller <davem@davemloft.net>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/block/sunvdc.c | 161 ++++++++++++++++++++++++++++-------------
 1 file changed, 110 insertions(+), 51 deletions(-)

diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index f68e9baffad7..bf51a2307ce1 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -6,7 +6,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/hdreg.h>
 #include <linux/genhd.h>
 #include <linux/cdrom.h>
@@ -66,9 +66,10 @@ struct vdc_port {
 
 	u64			max_xfer_size;
 	u32			vdisk_block_size;
+	u32			drain;
 
 	u64			ldc_timeout;
-	struct timer_list	ldc_reset_timer;
+	struct delayed_work	ldc_reset_timer_work;
 	struct work_struct	ldc_reset_work;
 
 	/* The server fills these in for us in the disk attribute
@@ -80,12 +81,14 @@ struct vdc_port {
 	u8			vdisk_mtype;
 	u32			vdisk_phys_blksz;
 
+	struct blk_mq_tag_set	tag_set;
+
 	char			disk_name[32];
 };
 
 static void vdc_ldc_reset(struct vdc_port *port);
 static void vdc_ldc_reset_work(struct work_struct *work);
-static void vdc_ldc_reset_timer(struct timer_list *t);
+static void vdc_ldc_reset_timer_work(struct work_struct *work);
 
 static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio)
 {
@@ -175,11 +178,8 @@ static void vdc_blk_queue_start(struct vdc_port *port)
 	 * handshake completes, so check for initial handshake before we've
 	 * allocated a disk.
 	 */
-	if (port->disk && blk_queue_stopped(port->disk->queue) &&
-	    vdc_tx_dring_avail(dr) * 100 / VDC_TX_RING_SIZE >= 50) {
-		blk_start_queue(port->disk->queue);
-	}
-
+	if (port->disk && vdc_tx_dring_avail(dr) * 100 / VDC_TX_RING_SIZE >= 50)
+		blk_mq_start_hw_queues(port->disk->queue);
 }
 
 static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for)
@@ -197,7 +197,7 @@ static void vdc_handshake_complete(struct vio_driver_state *vio)
 {
 	struct vdc_port *port = to_vdc_port(vio);
 
-	del_timer(&port->ldc_reset_timer);
+	cancel_delayed_work(&port->ldc_reset_timer_work);
 	vdc_finish(vio, 0, WAITING_FOR_LINK_UP);
 	vdc_blk_queue_start(port);
 }
@@ -320,7 +320,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
 
 	rqe->req = NULL;
 
-	__blk_end_request(req, (desc->status ? BLK_STS_IOERR : 0), desc->size);
+	blk_mq_end_request(req, desc->status ? BLK_STS_IOERR : 0);
 
 	vdc_blk_queue_start(port);
 }
@@ -525,29 +525,40 @@ static int __send_request(struct request *req)
 	return err;
 }
 
-static void do_vdc_request(struct request_queue *rq)
+static blk_status_t vdc_queue_rq(struct blk_mq_hw_ctx *hctx,
+				 const struct blk_mq_queue_data *bd)
 {
-	struct request *req;
+	struct vdc_port *port = hctx->queue->queuedata;
+	struct vio_dring_state *dr;
+	unsigned long flags;
 
-	while ((req = blk_peek_request(rq)) != NULL) {
-		struct vdc_port *port;
-		struct vio_dring_state *dr;
+	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
 
-		port = req->rq_disk->private_data;
-		dr = &port->vio.drings[VIO_DRIVER_TX_RING];
-		if (unlikely(vdc_tx_dring_avail(dr) < 1))
-			goto wait;
+	blk_mq_start_request(bd->rq);
 
-		blk_start_request(req);
+	spin_lock_irqsave(&port->vio.lock, flags);
 
-		if (__send_request(req) < 0) {
-			blk_requeue_request(rq, req);
-wait:
-			/* Avoid pointless unplugs. */
-			blk_stop_queue(rq);
-			break;
-		}
+	/*
+	 * Doing drain, just end the request in error
+	 */
+	if (unlikely(port->drain)) {
+		spin_unlock_irqrestore(&port->vio.lock, flags);
+		return BLK_STS_IOERR;
 	}
+
+	if (unlikely(vdc_tx_dring_avail(dr) < 1)) {
+		spin_unlock_irqrestore(&port->vio.lock, flags);
+		blk_mq_stop_hw_queue(hctx);
+		return BLK_STS_DEV_RESOURCE;
+	}
+
+	if (__send_request(bd->rq) < 0) {
+		spin_unlock_irqrestore(&port->vio.lock, flags);
+		return BLK_STS_IOERR;
+	}
+
+	spin_unlock_irqrestore(&port->vio.lock, flags);
+	return BLK_STS_OK;
 }
 
 static int generic_request(struct vdc_port *port, u8 op, void *buf, int len)
@@ -759,6 +770,44 @@ static void vdc_port_down(struct vdc_port *port)
 	vio_ldc_free(&port->vio);
 }
 
+static const struct blk_mq_ops vdc_mq_ops = {
+	.queue_rq	= vdc_queue_rq,
+};
+
+static void cleanup_queue(struct request_queue *q)
+{
+	struct vdc_port *port = q->queuedata;
+
+	blk_mq_free_tag_set(&port->tag_set);
+	blk_cleanup_queue(q);
+}
+
+static struct request_queue *init_queue(struct vdc_port *port)
+{
+	struct blk_mq_tag_set *set = &port->tag_set;
+	struct request_queue *q;
+	int ret;
+
+	set->ops = &vdc_mq_ops;
+	set->nr_hw_queues = 1;
+	set->queue_depth = VDC_TX_RING_SIZE;
+	set->numa_node = NUMA_NO_NODE;
+	set->flags = BLK_MQ_F_SHOULD_MERGE;
+
+	ret = blk_mq_alloc_tag_set(set);
+	if (ret)
+		return ERR_PTR(ret);
+
+	q = blk_mq_init_queue(set);
+	if (IS_ERR(q)) {
+		blk_mq_free_tag_set(set);
+		return q;
+	}
+
+	q->queuedata = port;
+	return q;
+}
+
 static int probe_disk(struct vdc_port *port)
 {
 	struct request_queue *q;
@@ -796,17 +845,17 @@ static int probe_disk(struct vdc_port *port)
 				    (u64)geom.num_sec);
 	}
 
-	q = blk_init_queue(do_vdc_request, &port->vio.lock);
-	if (!q) {
+	q = init_queue(port);
+	if (IS_ERR(q)) {
 		printk(KERN_ERR PFX "%s: Could not allocate queue.\n",
 		       port->vio.name);
-		return -ENOMEM;
+		return PTR_ERR(q);
 	}
 	g = alloc_disk(1 << PARTITION_SHIFT);
 	if (!g) {
 		printk(KERN_ERR PFX "%s: Could not allocate gendisk.\n",
 		       port->vio.name);
-		blk_cleanup_queue(q);
+		cleanup_queue(q);
 		return -ENOMEM;
 	}
 
@@ -981,7 +1030,7 @@ static int vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 	 */
 	ldc_timeout = mdesc_get_property(hp, vdev->mp, "vdc-timeout", NULL);
 	port->ldc_timeout = ldc_timeout ? *ldc_timeout : 0;
-	timer_setup(&port->ldc_reset_timer, vdc_ldc_reset_timer, 0);
+	INIT_DELAYED_WORK(&port->ldc_reset_timer_work, vdc_ldc_reset_timer_work);
 	INIT_WORK(&port->ldc_reset_work, vdc_ldc_reset_work);
 
 	err = vio_driver_init(&port->vio, vdev, VDEV_DISK,
@@ -1034,18 +1083,14 @@ static int vdc_port_remove(struct vio_dev *vdev)
 	struct vdc_port *port = dev_get_drvdata(&vdev->dev);
 
 	if (port) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&port->vio.lock, flags);
-		blk_stop_queue(port->disk->queue);
-		spin_unlock_irqrestore(&port->vio.lock, flags);
+		blk_mq_stop_hw_queues(port->disk->queue);
 
 		flush_work(&port->ldc_reset_work);
-		del_timer_sync(&port->ldc_reset_timer);
+		cancel_delayed_work_sync(&port->ldc_reset_timer_work);
 		del_timer_sync(&port->vio.timer);
 
 		del_gendisk(port->disk);
-		blk_cleanup_queue(port->disk->queue);
+		cleanup_queue(port->disk->queue);
 		put_disk(port->disk);
 		port->disk = NULL;
 
@@ -1080,32 +1125,46 @@ static void vdc_requeue_inflight(struct vdc_port *port)
 		}
 
 		rqe->req = NULL;
-		blk_requeue_request(port->disk->queue, req);
+		blk_mq_requeue_request(req, false);
 	}
 }
 
 static void vdc_queue_drain(struct vdc_port *port)
 {
-	struct request *req;
+	struct request_queue *q = port->disk->queue;
 
-	while ((req = blk_fetch_request(port->disk->queue)) != NULL)
-		__blk_end_request_all(req, BLK_STS_IOERR);
+	/*
+	 * Mark the queue as draining, then freeze/quiesce to ensure
+	 * that all existing requests are seen in ->queue_rq() and killed
+	 */
+	port->drain = 1;
+	spin_unlock_irq(&port->vio.lock);
+
+	blk_mq_freeze_queue(q);
+	blk_mq_quiesce_queue(q);
+
+	spin_lock_irq(&port->vio.lock);
+	port->drain = 0;
+	blk_mq_unquiesce_queue(q);
+	blk_mq_unfreeze_queue(q);
 }
 
-static void vdc_ldc_reset_timer(struct timer_list *t)
+static void vdc_ldc_reset_timer_work(struct work_struct *work)
 {
-	struct vdc_port *port = from_timer(port, t, ldc_reset_timer);
-	struct vio_driver_state *vio = &port->vio;
-	unsigned long flags;
+	struct vdc_port *port;
+	struct vio_driver_state *vio;
 
-	spin_lock_irqsave(&vio->lock, flags);
+	port = container_of(work, struct vdc_port, ldc_reset_timer_work.work);
+	vio = &port->vio;
+
+	spin_lock_irq(&vio->lock);
 	if (!(port->vio.hs_state & VIO_HS_COMPLETE)) {
 		pr_warn(PFX "%s ldc down %llu seconds, draining queue\n",
 			port->disk_name, port->ldc_timeout);
 		vdc_queue_drain(port);
 		vdc_blk_queue_start(port);
 	}
-	spin_unlock_irqrestore(&vio->lock, flags);
+	spin_unlock_irq(&vio->lock);
 }
 
 static void vdc_ldc_reset_work(struct work_struct *work)
@@ -1129,7 +1188,7 @@ static void vdc_ldc_reset(struct vdc_port *port)
 	assert_spin_locked(&port->vio.lock);
 
 	pr_warn(PFX "%s ldc link reset\n", port->disk_name);
-	blk_stop_queue(port->disk->queue);
+	blk_mq_stop_hw_queues(port->disk->queue);
 	vdc_requeue_inflight(port);
 	vdc_port_down(port);
 
@@ -1146,7 +1205,7 @@ static void vdc_ldc_reset(struct vdc_port *port)
 	}
 
 	if (port->ldc_timeout)
-		mod_timer(&port->ldc_reset_timer,
+		mod_delayed_work(system_wq, &port->ldc_reset_timer_work,
 			  round_jiffies(jiffies + HZ * port->ldc_timeout));
 	mod_timer(&port->vio.timer, round_jiffies(jiffies + HZ));
 	return;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 02/17] sx8: convert to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
  2018-10-11 16:58 ` [PATCH 01/17] sunvdc: convert " Jens Axboe
@ 2018-10-11 16:58 ` Jens Axboe
  2018-10-11 16:58 ` [PATCH 03/17] ps3disk: " Jens Axboe
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:58 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe

Convert from the old request_fn style driver to blk-mq.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/block/sx8.c | 133 +++++++++++++++++++++++++++++---------------
 1 file changed, 88 insertions(+), 45 deletions(-)

diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 4d90e5eba2f5..5402dfdf331b 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -16,7 +16,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/compiler.h>
@@ -244,6 +244,7 @@ struct carm_port {
 	unsigned int			port_no;
 	struct gendisk			*disk;
 	struct carm_host		*host;
+	struct blk_mq_tag_set		tag_set;
 
 	/* attached device characteristics */
 	u64				capacity;
@@ -279,6 +280,7 @@ struct carm_host {
 	unsigned int			state;
 	u32				fw_ver;
 
+	struct blk_mq_tag_set		tag_set;
 	struct request_queue		*oob_q;
 	unsigned int			n_oob;
 
@@ -750,7 +752,7 @@ static inline void carm_end_request_queued(struct carm_host *host,
 	struct request *req = crq->rq;
 	int rc;
 
-	__blk_end_request_all(req, error);
+	blk_mq_end_request(req, error);
 
 	rc = carm_put_request(host, crq);
 	assert(rc == 0);
@@ -760,7 +762,7 @@ static inline void carm_push_q (struct carm_host *host, struct request_queue *q)
 {
 	unsigned int idx = host->wait_q_prod % CARM_MAX_WAIT_Q;
 
-	blk_stop_queue(q);
+	blk_mq_stop_hw_queues(q);
 	VPRINTK("STOPPED QUEUE %p\n", q);
 
 	host->wait_q[idx] = q;
@@ -785,7 +787,7 @@ static inline void carm_round_robin(struct carm_host *host)
 {
 	struct request_queue *q = carm_pop_q(host);
 	if (q) {
-		blk_start_queue(q);
+		blk_mq_start_hw_queues(q);
 		VPRINTK("STARTED QUEUE %p\n", q);
 	}
 }
@@ -802,62 +804,62 @@ static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
 	}
 }
 
-static void carm_oob_rq_fn(struct request_queue *q)
+static blk_status_t carm_oob_queue_rq(struct blk_mq_hw_ctx *hctx,
+				      const struct blk_mq_queue_data *bd)
 {
+	struct request_queue *q = hctx->queue;
 	struct carm_host *host = q->queuedata;
 	struct carm_request *crq;
-	struct request *rq;
 	int rc;
 
-	while (1) {
-		DPRINTK("get req\n");
-		rq = blk_fetch_request(q);
-		if (!rq)
-			break;
+	blk_mq_start_request(bd->rq);
+
+	spin_lock_irq(&host->lock);
 
-		crq = rq->special;
-		assert(crq != NULL);
-		assert(crq->rq == rq);
+	crq = bd->rq->special;
+	assert(crq != NULL);
+	assert(crq->rq == bd->rq);
 
-		crq->n_elem = 0;
+	crq->n_elem = 0;
 
-		DPRINTK("send req\n");
-		rc = carm_send_msg(host, crq);
-		if (rc) {
-			blk_requeue_request(q, rq);
-			carm_push_q(host, q);
-			return;		/* call us again later, eventually */
-		}
+	DPRINTK("send req\n");
+	rc = carm_send_msg(host, crq);
+	if (rc) {
+		carm_push_q(host, q);
+		spin_unlock_irq(&host->lock);
+		return BLK_STS_DEV_RESOURCE;
 	}
+
+	spin_unlock_irq(&host->lock);
+	return BLK_STS_OK;
 }
 
-static void carm_rq_fn(struct request_queue *q)
+static blk_status_t carm_queue_rq(struct blk_mq_hw_ctx *hctx,
+				  const struct blk_mq_queue_data *bd)
 {
+	struct request_queue *q = hctx->queue;
 	struct carm_port *port = q->queuedata;
 	struct carm_host *host = port->host;
 	struct carm_msg_rw *msg;
 	struct carm_request *crq;
-	struct request *rq;
+	struct request *rq = bd->rq;
 	struct scatterlist *sg;
 	int writing = 0, pci_dir, i, n_elem, rc;
 	u32 tmp;
 	unsigned int msg_size;
 
-queue_one_request:
-	VPRINTK("get req\n");
-	rq = blk_peek_request(q);
-	if (!rq)
-		return;
+	blk_mq_start_request(rq);
+
+	spin_lock_irq(&host->lock);
 
 	crq = carm_get_request(host);
 	if (!crq) {
 		carm_push_q(host, q);
-		return;		/* call us again later, eventually */
+		spin_unlock_irq(&host->lock);
+		return BLK_STS_DEV_RESOURCE;
 	}
 	crq->rq = rq;
 
-	blk_start_request(rq);
-
 	if (rq_data_dir(rq) == WRITE) {
 		writing = 1;
 		pci_dir = PCI_DMA_TODEVICE;
@@ -869,15 +871,19 @@ static void carm_rq_fn(struct request_queue *q)
 	sg = &crq->sg[0];
 	n_elem = blk_rq_map_sg(q, rq, sg);
 	if (n_elem <= 0) {
+		/* request with no s/g entries? */
 		carm_end_rq(host, crq, BLK_STS_IOERR);
-		return;		/* request with no s/g entries? */
+		spin_unlock_irq(&host->lock);
+		return BLK_STS_IOERR;
 	}
 
 	/* map scatterlist to PCI bus addresses */
 	n_elem = pci_map_sg(host->pdev, sg, n_elem, pci_dir);
 	if (n_elem <= 0) {
+		/* request with no s/g entries? */
 		carm_end_rq(host, crq, BLK_STS_IOERR);
-		return;		/* request with no s/g entries? */
+		spin_unlock_irq(&host->lock);
+		return BLK_STS_IOERR;
 	}
 	crq->n_elem = n_elem;
 	crq->port = port;
@@ -927,12 +933,13 @@ static void carm_rq_fn(struct request_queue *q)
 	rc = carm_send_msg(host, crq);
 	if (rc) {
 		carm_put_request(host, crq);
-		blk_requeue_request(q, rq);
 		carm_push_q(host, q);
-		return;		/* call us again later, eventually */
+		spin_unlock_irq(&host->lock);
+		return BLK_STS_DEV_RESOURCE;
 	}
 
-	goto queue_one_request;
+	spin_unlock_irq(&host->lock);
+	return BLK_STS_OK;
 }
 
 static void carm_handle_array_info(struct carm_host *host,
@@ -1485,6 +1492,14 @@ static int carm_init_host(struct carm_host *host)
 	return 0;
 }
 
+static const struct blk_mq_ops carm_oob_mq_ops = {
+	.queue_rq	= carm_oob_queue_rq,
+};
+
+static const struct blk_mq_ops carm_mq_ops = {
+	.queue_rq	= carm_queue_rq,
+};
+
 static int carm_init_disks(struct carm_host *host)
 {
 	unsigned int i;
@@ -1494,6 +1509,7 @@ static int carm_init_disks(struct carm_host *host)
 		struct gendisk *disk;
 		struct request_queue *q;
 		struct carm_port *port;
+		struct blk_mq_tag_set *set;
 
 		port = &host->port[i];
 		port->host = host;
@@ -1513,9 +1529,19 @@ static int carm_init_disks(struct carm_host *host)
 		disk->fops = &carm_bd_ops;
 		disk->private_data = port;
 
-		q = blk_init_queue(carm_rq_fn, &host->lock);
-		if (!q) {
-			rc = -ENOMEM;
+		set = &port->tag_set;
+		set->ops = &carm_mq_ops;
+		set->nr_hw_queues = 1;
+		set->queue_depth = max_queue;
+		set->numa_node = NUMA_NO_NODE;
+		set->flags = BLK_MQ_F_SHOULD_MERGE;
+		rc = blk_mq_alloc_tag_set(set);
+		if (rc)
+			break;
+
+		q = blk_mq_init_queue(set);
+		if (IS_ERR(q)) {
+			rc = PTR_ERR(q);
 			break;
 		}
 		disk->queue = q;
@@ -1533,14 +1559,18 @@ static void carm_free_disks(struct carm_host *host)
 	unsigned int i;
 
 	for (i = 0; i < CARM_MAX_PORTS; i++) {
-		struct gendisk *disk = host->port[i].disk;
+		struct carm_port *port = &host->port[i];
+		struct gendisk *disk = port->disk;
+
 		if (disk) {
 			struct request_queue *q = disk->queue;
 
 			if (disk->flags & GENHD_FL_UP)
 				del_gendisk(disk);
-			if (q)
+			if (q) {
+				blk_mq_free_tag_set(&port->tag_set);
 				blk_cleanup_queue(q);
+			}
 			put_disk(disk);
 		}
 	}
@@ -1568,6 +1598,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	unsigned int pci_dac;
 	int rc;
 	struct request_queue *q;
+	struct blk_mq_tag_set *set;
 	unsigned int i;
 
 	printk_once(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
@@ -1636,11 +1667,21 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_out_iounmap;
 	}
 
-	q = blk_init_queue(carm_oob_rq_fn, &host->lock);
-	if (!q) {
+	set = &host->tag_set;
+	set->ops = &carm_oob_mq_ops;
+	set->nr_hw_queues = 1;
+	set->queue_depth = 1;
+	set->numa_node = NUMA_NO_NODE;
+	set->flags = BLK_MQ_F_NO_SCHED;
+	rc = blk_mq_alloc_tag_set(set);
+	if (rc)
+		goto err_out_pci_free;
+
+	q = blk_mq_init_queue(set);
+	if (IS_ERR(q)) {
 		printk(KERN_ERR DRV_NAME "(%s): OOB queue alloc failure\n",
 		       pci_name(pdev));
-		rc = -ENOMEM;
+		rc = PTR_ERR(q);
 		goto err_out_pci_free;
 	}
 	host->oob_q = q;
@@ -1704,6 +1745,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 		clear_bit(0, &carm_major_alloc);
 	else if (host->major == 161)
 		clear_bit(1, &carm_major_alloc);
+	blk_mq_free_tag_set(&host->tag_set);
 	blk_cleanup_queue(host->oob_q);
 err_out_pci_free:
 	pci_free_consistent(pdev, CARM_SHM_SIZE, host->shm, host->shm_dma);
@@ -1735,6 +1777,7 @@ static void carm_remove_one (struct pci_dev *pdev)
 		clear_bit(0, &carm_major_alloc);
 	else if (host->major == 161)
 		clear_bit(1, &carm_major_alloc);
+	blk_mq_free_tag_set(&host->tag_set);
 	blk_cleanup_queue(host->oob_q);
 	pci_free_consistent(pdev, CARM_SHM_SIZE, host->shm, host->shm_dma);
 	iounmap(host->mmio);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 03/17] ps3disk: convert to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
  2018-10-11 16:58 ` [PATCH 01/17] sunvdc: convert " Jens Axboe
  2018-10-11 16:58 ` [PATCH 02/17] sx8: " Jens Axboe
@ 2018-10-11 16:58 ` Jens Axboe
  2018-10-12 22:47   ` Geoff Levand
  2018-10-11 16:58 ` [PATCH 04/17] paride: convert pcd " Jens Axboe
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:58 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe, Geoff Levand, Benjamin Herrenschmidt

Convert from the old request_fn style driver to blk-mq.

Cc: Geoff Levand <geoff@infradead.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/block/ps3disk.c | 95 +++++++++++++++++++++++------------------
 1 file changed, 54 insertions(+), 41 deletions(-)

diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index afe1508d82c6..e8b41e95a679 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -19,7 +19,7 @@
  */
 
 #include <linux/ata.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 
@@ -42,6 +42,7 @@
 struct ps3disk_private {
 	spinlock_t lock;		/* Request queue spinlock */
 	struct request_queue *queue;
+	struct blk_mq_tag_set tag_set;
 	struct gendisk *gendisk;
 	unsigned int blocking_factor;
 	struct request *req;
@@ -118,8 +119,8 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
 	}
 }
 
-static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
-				     struct request *req)
+static void ps3disk_submit_request_sg(struct ps3_storage_device *dev,
+				      struct request *req)
 {
 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 	int write = rq_data_dir(req), res;
@@ -158,16 +159,15 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
 	if (res) {
 		dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
 			__LINE__, op, res);
-		__blk_end_request_all(req, BLK_STS_IOERR);
-		return 0;
+		blk_mq_end_request(req, BLK_STS_IOERR);
+		return;
 	}
 
 	priv->req = req;
-	return 1;
 }
 
-static int ps3disk_submit_flush_request(struct ps3_storage_device *dev,
-					struct request *req)
+static void ps3disk_submit_flush_request(struct ps3_storage_device *dev,
+					 struct request *req)
 {
 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 	u64 res;
@@ -180,50 +180,46 @@ static int ps3disk_submit_flush_request(struct ps3_storage_device *dev,
 	if (res) {
 		dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
 			__func__, __LINE__, res);
-		__blk_end_request_all(req, BLK_STS_IOERR);
-		return 0;
+		blk_mq_end_request(req, BLK_STS_IOERR);
+		return;
 	}
 
 	priv->req = req;
-	return 1;
 }
 
 static void ps3disk_do_request(struct ps3_storage_device *dev,
-			       struct request_queue *q)
+			       struct request *req)
 {
-	struct request *req;
-
 	dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
 
-	while ((req = blk_fetch_request(q))) {
-		switch (req_op(req)) {
-		case REQ_OP_FLUSH:
-			if (ps3disk_submit_flush_request(dev, req))
-				return;
-			break;
-		case REQ_OP_READ:
-		case REQ_OP_WRITE:
-			if (ps3disk_submit_request_sg(dev, req))
-				return;
-			break;
-		default:
-			blk_dump_rq_flags(req, DEVICE_NAME " bad request");
-			__blk_end_request_all(req, BLK_STS_IOERR);
-		}
+	switch (req_op(req)) {
+	case REQ_OP_FLUSH:
+		ps3disk_submit_flush_request(dev, req);
+		break;
+	case REQ_OP_READ:
+	case REQ_OP_WRITE:
+		ps3disk_submit_request_sg(dev, req);
+		break;
+	default:
+		blk_dump_rq_flags(req, DEVICE_NAME " bad request");
+		blk_mq_end_request(req, BLK_STS_IOERR);
 	}
 }
 
-static void ps3disk_request(struct request_queue *q)
+static blk_status_t ps3disk_queue_rq(struct blk_mq_hw_ctx *hctx,
+				     const struct blk_mq_queue_data *bd)
 {
+	struct request_queue *q = hctx->queue;
 	struct ps3_storage_device *dev = q->queuedata;
 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 
-	if (priv->req) {
-		dev_dbg(&dev->sbd.core, "%s:%u busy\n", __func__, __LINE__);
-		return;
-	}
+	blk_mq_start_request(bd->rq);
+
+	spin_lock_irq(&priv->lock);
+	ps3disk_do_request(dev, bd->rq);
+	spin_unlock_irq(&priv->lock);
 
-	ps3disk_do_request(dev, q);
+	return BLK_STS_OK;
 }
 
 static irqreturn_t ps3disk_interrupt(int irq, void *data)
@@ -279,12 +275,13 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
 			ps3disk_scatter_gather(dev, req, 0);
 	}
 
+	blk_mq_end_request(req, error);
+
 	spin_lock(&priv->lock);
-	__blk_end_request_all(req, error);
 	priv->req = NULL;
-	ps3disk_do_request(dev, priv->queue);
 	spin_unlock(&priv->lock);
 
+	blk_mq_start_hw_queues(priv->queue);
 	return IRQ_HANDLED;
 }
 
@@ -404,6 +401,10 @@ static unsigned long ps3disk_mask;
 
 static DEFINE_MUTEX(ps3disk_mask_mutex);
 
+static const struct blk_mq_ops ps3disk_mq_ops = {
+	.queue_rq	= ps3disk_queue_rq,
+};
+
 static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 {
 	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
@@ -411,6 +412,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 	int error;
 	unsigned int devidx;
 	struct request_queue *queue;
+	struct blk_mq_tag_set *set;
 	struct gendisk *gendisk;
 
 	if (dev->blk_size < 512) {
@@ -454,11 +456,21 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 
 	ps3disk_identify(dev);
 
-	queue = blk_init_queue(ps3disk_request, &priv->lock);
-	if (!queue) {
-		dev_err(&dev->sbd.core, "%s:%u: blk_init_queue failed\n",
+	set = &priv->tag_set;
+	set->ops = &ps3disk_mq_ops;
+	set->nr_hw_queues = 1;
+	set->queue_depth = 2;
+	set->numa_node = NUMA_NO_NODE;
+	set->flags = BLK_MQ_F_SHOULD_MERGE;
+	error = blk_mq_alloc_tag_set(set);
+	if (error)
+		goto fail_teardown;
+
+	queue = blk_mq_init_queue(set);
+	if (IS_ERR(queue)) {
+		dev_err(&dev->sbd.core, "%s:%u: blk_mq_init_queue failed\n",
 			__func__, __LINE__);
-		error = -ENOMEM;
+		error = PTR_ERR(queue);
 		goto fail_teardown;
 	}
 
@@ -504,6 +516,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 	return 0;
 
 fail_cleanup_queue:
+	blk_mq_free_tag_set(&priv->tag_set);
 	blk_cleanup_queue(queue);
 fail_teardown:
 	ps3stor_teardown(dev);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 04/17] paride: convert pcd to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (2 preceding siblings ...)
  2018-10-11 16:58 ` [PATCH 03/17] ps3disk: " Jens Axboe
@ 2018-10-11 16:58 ` Jens Axboe
  2018-10-11 16:58 ` [PATCH 05/17] paride: convert pd " Jens Axboe
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:58 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe

Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/block/paride/pcd.c | 98 +++++++++++++++++++++++++-------------
 1 file changed, 66 insertions(+), 32 deletions(-)

diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index a026211afb51..f2b82e3510d8 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -137,7 +137,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
 #include <linux/delay.h>
 #include <linux/cdrom.h>
 #include <linux/spinlock.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
 
@@ -186,7 +186,8 @@ static int pcd_packet(struct cdrom_device_info *cdi,
 static int pcd_detect(void);
 static void pcd_probe_capabilities(void);
 static void do_pcd_read_drq(void);
-static void do_pcd_request(struct request_queue * q);
+static blk_status_t pcd_queue_rq(struct blk_mq_hw_ctx *hctx,
+				 const struct blk_mq_queue_data *bd);
 static void do_pcd_read(void);
 
 struct pcd_unit {
@@ -199,6 +200,8 @@ struct pcd_unit {
 	char *name;		/* pcd0, pcd1, etc */
 	struct cdrom_device_info info;	/* uniform cdrom interface */
 	struct gendisk *disk;
+	struct blk_mq_tag_set tag_set;
+	struct list_head rq_list;
 };
 
 static struct pcd_unit pcd[PCD_UNITS];
@@ -292,6 +295,10 @@ static const struct cdrom_device_ops pcd_dops = {
 			  CDC_CD_RW,
 };
 
+static const struct blk_mq_ops pcd_mq_ops = {
+	.queue_rq	= pcd_queue_rq,
+};
+
 static void pcd_init_units(void)
 {
 	struct pcd_unit *cd;
@@ -300,13 +307,29 @@ static void pcd_init_units(void)
 	pcd_drive_count = 0;
 	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 		struct gendisk *disk = alloc_disk(1);
+		struct blk_mq_tag_set *set;
+
 		if (!disk)
 			continue;
-		disk->queue = blk_init_queue(do_pcd_request, &pcd_lock);
-		if (!disk->queue) {
-			put_disk(disk);
+
+		set = &cd->tag_set;
+		set->ops = &pcd_mq_ops;
+		set->nr_hw_queues = 1;
+		set->queue_depth = 1;
+		set->numa_node = NUMA_NO_NODE;
+		set->flags = BLK_MQ_F_SHOULD_MERGE;
+		if (blk_mq_alloc_tag_set(set))
+			continue;
+
+		disk->queue = blk_mq_init_queue(set);
+		if (IS_ERR(disk->queue)) {
+			blk_mq_free_tag_set(set);
+			disk->queue = NULL;
 			continue;
 		}
+
+		INIT_LIST_HEAD(&cd->rq_list);
+		disk->queue->queuedata = cd;
 		blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
 		cd->disk = disk;
 		cd->pi = &cd->pia;
@@ -748,18 +771,18 @@ static int pcd_queue;
 static int set_next_request(void)
 {
 	struct pcd_unit *cd;
-	struct request_queue *q;
 	int old_pos = pcd_queue;
 
 	do {
 		cd = &pcd[pcd_queue];
-		q = cd->present ? cd->disk->queue : NULL;
 		if (++pcd_queue == PCD_UNITS)
 			pcd_queue = 0;
-		if (q) {
-			pcd_req = blk_fetch_request(q);
-			if (pcd_req)
-				break;
+		if (cd->present && !list_empty(&cd->rq_list)) {
+			pcd_req = list_first_entry(&cd->rq_list, struct request,
+							queuelist);
+			list_del_init(&pcd_req->queuelist);
+			blk_mq_start_request(pcd_req);
+			break;
 		}
 	} while (pcd_queue != old_pos);
 
@@ -768,33 +791,41 @@ static int set_next_request(void)
 
 static void pcd_request(void)
 {
+	struct pcd_unit *cd;
+
 	if (pcd_busy)
 		return;
-	while (1) {
-		if (!pcd_req && !set_next_request())
-			return;
 
-		if (rq_data_dir(pcd_req) == READ) {
-			struct pcd_unit *cd = pcd_req->rq_disk->private_data;
-			if (cd != pcd_current)
-				pcd_bufblk = -1;
-			pcd_current = cd;
-			pcd_sector = blk_rq_pos(pcd_req);
-			pcd_count = blk_rq_cur_sectors(pcd_req);
-			pcd_buf = bio_data(pcd_req->bio);
-			pcd_busy = 1;
-			ps_set_intr(do_pcd_read, NULL, 0, nice);
-			return;
-		} else {
-			__blk_end_request_all(pcd_req, BLK_STS_IOERR);
-			pcd_req = NULL;
-		}
-	}
+	if (!pcd_req && !set_next_request())
+		return;
+
+	cd = pcd_req->rq_disk->private_data;
+	if (cd != pcd_current)
+		pcd_bufblk = -1;
+	pcd_current = cd;
+	pcd_sector = blk_rq_pos(pcd_req);
+	pcd_count = blk_rq_cur_sectors(pcd_req);
+	pcd_buf = bio_data(pcd_req->bio);
+	pcd_busy = 1;
+	ps_set_intr(do_pcd_read, NULL, 0, nice);
 }
 
-static void do_pcd_request(struct request_queue *q)
+static blk_status_t pcd_queue_rq(struct blk_mq_hw_ctx *hctx,
+				 const struct blk_mq_queue_data *bd)
 {
+	struct pcd_unit *cd = hctx->queue->queuedata;
+
+	if (rq_data_dir(bd->rq) != READ) {
+		blk_mq_start_request(bd->rq);
+		return BLK_STS_IOERR;
+	}
+
+	spin_lock_irq(&pcd_lock);
+	list_add_tail(&bd->rq->queuelist, &cd->rq_list);
 	pcd_request();
+	spin_unlock_irq(&pcd_lock);
+
+	return BLK_STS_OK;
 }
 
 static inline void next_request(blk_status_t err)
@@ -802,8 +833,10 @@ static inline void next_request(blk_status_t err)
 	unsigned long saved_flags;
 
 	spin_lock_irqsave(&pcd_lock, saved_flags);
-	if (!__blk_end_request_cur(pcd_req, err))
+	if (!blk_update_request(pcd_req, err, blk_rq_cur_bytes(pcd_req))) {
+		__blk_mq_end_request(pcd_req, err);
 		pcd_req = NULL;
+	}
 	pcd_busy = 0;
 	pcd_request();
 	spin_unlock_irqrestore(&pcd_lock, saved_flags);
@@ -1010,6 +1043,7 @@ static void __exit pcd_exit(void)
 			pi_release(cd->pi);
 			unregister_cdrom(&cd->info);
 		}
+		blk_mq_free_tag_set(&cd->tag_set);
 		blk_cleanup_queue(cd->disk->queue);
 		put_disk(cd->disk);
 	}
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 05/17] paride: convert pd to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (3 preceding siblings ...)
  2018-10-11 16:58 ` [PATCH 04/17] paride: convert pcd " Jens Axboe
@ 2018-10-11 16:58 ` Jens Axboe
  2018-10-11 16:58 ` [PATCH 06/17] paride: convert pf " Jens Axboe
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:58 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe

Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/block/paride/pd.c | 109 ++++++++++++++++++++++----------------
 1 file changed, 62 insertions(+), 47 deletions(-)

diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 7cf947586fe4..87636d6ce191 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -151,7 +151,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV};
 #include <linux/delay.h>
 #include <linux/hdreg.h>
 #include <linux/cdrom.h>	/* for the eject ioctl */
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/blkpg.h>
 #include <linux/kernel.h>
 #include <linux/mutex.h>
@@ -236,6 +236,7 @@ struct pd_unit {
 	int alt_geom;
 	char name[PD_NAMELEN];	/* pda, pdb, etc ... */
 	struct gendisk *gd;
+	struct blk_mq_tag_set tag_set;
 };
 
 static struct pd_unit pd[PD_UNITS];
@@ -355,25 +356,6 @@ enum action {Fail = 0, Ok = 1, Hold, Wait};
 static struct request *pd_req;	/* current request */
 static enum action (*phase)(void);
 
-static void run_fsm(void);
-
-static void ps_tq_int(struct work_struct *work);
-
-static DECLARE_DELAYED_WORK(fsm_tq, ps_tq_int);
-
-static void schedule_fsm(void)
-{
-	if (!nice)
-		schedule_delayed_work(&fsm_tq, 0);
-	else
-		schedule_delayed_work(&fsm_tq, nice-1);
-}
-
-static void ps_tq_int(struct work_struct *work)
-{
-	run_fsm();
-}
-
 static enum action do_pd_io_start(void);
 static enum action pd_special(void);
 static enum action do_pd_read_start(void);
@@ -387,7 +369,7 @@ static int pd_claimed;
 static struct pd_unit *pd_current; /* current request's drive */
 static PIA *pi_current; /* current request's PIA */
 
-static int set_next_request(void)
+static int run_next_queue(void)
 {
 	struct gendisk *disk;
 	struct request_queue *q;
@@ -398,11 +380,8 @@ static int set_next_request(void)
 		q = disk ? disk->queue : NULL;
 		if (++pd_queue == PD_UNITS)
 			pd_queue = 0;
-		if (q) {
-			pd_req = blk_fetch_request(q);
-			if (pd_req)
-				break;
-		}
+		if (q)
+			blk_mq_run_hw_queues(q, true);
 	} while (pd_queue != old_pos);
 
 	return pd_req != NULL;
@@ -438,17 +417,20 @@ static void run_fsm(void)
 				pd_claimed = 0;
 				phase = NULL;
 				spin_lock_irqsave(&pd_lock, saved_flags);
-				if (!__blk_end_request_cur(pd_req,
-						res == Ok ? 0 : BLK_STS_IOERR)) {
-					if (!set_next_request())
-						stop = 1;
+				if (!blk_update_request(pd_req,
+						res == Ok ? 0 : BLK_STS_IOERR,
+						blk_rq_cur_bytes(pd_req))) {
+					__blk_mq_end_request(pd_req,
+						res == Ok ? 0 : BLK_STS_IOERR);
+					run_next_queue();
+					stop = 1;
 				}
 				spin_unlock_irqrestore(&pd_lock, saved_flags);
 				if (stop)
 					return;
 				/* fall through */
 			case Hold:
-				schedule_fsm();
+				blk_mq_run_hw_queues(pd_req->q, true);
 				return;
 			case Wait:
 				pi_disconnect(pi_current);
@@ -505,11 +487,17 @@ static int pd_next_buf(void)
 	if (pd_count)
 		return 0;
 	spin_lock_irqsave(&pd_lock, saved_flags);
-	__blk_end_request_cur(pd_req, 0);
-	pd_count = blk_rq_cur_sectors(pd_req);
-	pd_buf = bio_data(pd_req->bio);
+	if (!blk_update_request(pd_req, 0, blk_rq_cur_bytes(pd_req))) {
+		__blk_mq_end_request(pd_req, 0);
+		pd_req = NULL;
+		pd_count = 0;
+		pd_buf = NULL;
+	} else {
+		pd_count = blk_rq_cur_sectors(pd_req);
+		pd_buf = bio_data(pd_req->bio);
+	}
 	spin_unlock_irqrestore(&pd_lock, saved_flags);
-	return 0;
+	return !pd_count;
 }
 
 static unsigned long pd_timeout;
@@ -726,15 +714,22 @@ static enum action pd_identify(struct pd_unit *disk)
 
 /* end of io request engine */
 
-static void do_pd_request(struct request_queue * q)
+static blk_status_t pd_queue_rq(struct blk_mq_hw_ctx *hctx,
+				const struct blk_mq_queue_data *bd)
 {
-	if (pd_req)
-		return;
-	pd_req = blk_fetch_request(q);
-	if (!pd_req)
-		return;
+	spin_lock_irq(&pd_lock);
 
-	schedule_fsm();
+	/* this should not be possible */
+	if (pd_req) {
+		spin_unlock_irq(&pd_lock);
+		return BLK_STS_DEV_RESOURCE;
+	}
+
+	pd_req = bd->rq;
+	spin_unlock_irq(&pd_lock);
+	blk_mq_start_request(bd->rq);
+	run_fsm();
+	return BLK_STS_OK;
 }
 
 static int pd_special_command(struct pd_unit *disk,
@@ -847,23 +842,42 @@ static const struct block_device_operations pd_fops = {
 
 /* probing */
 
+static const struct blk_mq_ops pd_mq_ops = {
+	.queue_rq	= pd_queue_rq,
+};
+
 static void pd_probe_drive(struct pd_unit *disk)
 {
-	struct gendisk *p = alloc_disk(1 << PD_BITS);
+	struct blk_mq_tag_set *set;
+	struct gendisk *p;
+
+	p = alloc_disk(1 << PD_BITS);
 	if (!p)
 		return;
+
 	strcpy(p->disk_name, disk->name);
 	p->fops = &pd_fops;
 	p->major = major;
 	p->first_minor = (disk - pd) << PD_BITS;
 	disk->gd = p;
 	p->private_data = disk;
-	p->queue = blk_init_queue(do_pd_request, &pd_lock);
-	if (!p->queue) {
-		disk->gd = NULL;
-		put_disk(p);
+
+	set = &disk->tag_set;
+	set->ops = &pd_mq_ops;
+	set->nr_hw_queues = 1;
+	set->queue_depth = 1;
+	set->numa_node = NUMA_NO_NODE;
+	set->flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING;
+	if (blk_mq_alloc_tag_set(set))
+		return;
+
+	p->queue = blk_mq_init_queue(set);
+	if (IS_ERR(p->queue)) {
+		blk_mq_free_tag_set(set);
+		p->queue = NULL;
 		return;
 	}
+
 	blk_queue_max_hw_sectors(p->queue, cluster);
 	blk_queue_bounce_limit(p->queue, BLK_BOUNCE_HIGH);
 
@@ -971,6 +985,7 @@ static void __exit pd_exit(void)
 		if (p) {
 			disk->gd = NULL;
 			del_gendisk(p);
+			blk_mq_free_tag_set(&disk->tag_set);
 			blk_cleanup_queue(p->queue);
 			put_disk(p);
 			pi_release(disk->pi);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 06/17] paride: convert pf to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (4 preceding siblings ...)
  2018-10-11 16:58 ` [PATCH 05/17] paride: convert pd " Jens Axboe
@ 2018-10-11 16:58 ` Jens Axboe
  2018-10-11 16:58 ` [PATCH 07/17] uml: convert ubd " Jens Axboe
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:58 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe

Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/block/paride/pf.c | 68 +++++++++++++++++++++++++++++++--------
 1 file changed, 54 insertions(+), 14 deletions(-)

diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index eef7a91f667d..58866cf495f8 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -152,7 +152,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY};
 #include <linux/hdreg.h>
 #include <linux/cdrom.h>
 #include <linux/spinlock.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/blkpg.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
@@ -206,7 +206,8 @@ module_param_array(drive3, int, NULL, 0);
 #define ATAPI_WRITE_10		0x2a
 
 static int pf_open(struct block_device *bdev, fmode_t mode);
-static void do_pf_request(struct request_queue * q);
+static blk_status_t pf_queue_rq(struct blk_mq_hw_ctx *hctx,
+				const struct blk_mq_queue_data *bd);
 static int pf_ioctl(struct block_device *bdev, fmode_t mode,
 		    unsigned int cmd, unsigned long arg);
 static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo);
@@ -238,6 +239,8 @@ struct pf_unit {
 	int present;		/* device present ? */
 	char name[PF_NAMELEN];	/* pf0, pf1, ... */
 	struct gendisk *disk;
+	struct blk_mq_tag_set tag_set;
+	struct list_head rq_list;
 };
 
 static struct pf_unit units[PF_UNITS];
@@ -277,6 +280,10 @@ static const struct block_device_operations pf_fops = {
 	.check_events	= pf_check_events,
 };
 
+static const struct blk_mq_ops pf_mq_ops = {
+	.queue_rq	= pf_queue_rq,
+};
+
 static void __init pf_init_units(void)
 {
 	struct pf_unit *pf;
@@ -284,14 +291,34 @@ static void __init pf_init_units(void)
 
 	pf_drive_count = 0;
 	for (unit = 0, pf = units; unit < PF_UNITS; unit++, pf++) {
-		struct gendisk *disk = alloc_disk(1);
+		struct blk_mq_tag_set *set;
+		struct gendisk *disk;
+
+		disk = alloc_disk(1);
 		if (!disk)
 			continue;
-		disk->queue = blk_init_queue(do_pf_request, &pf_spin_lock);
-		if (!disk->queue) {
+
+		set = &pf->tag_set;
+		set->ops = &pf_mq_ops;
+		set->nr_hw_queues = 1;
+		set->queue_depth = 1;
+		set->numa_node = NUMA_NO_NODE;
+		set->flags = BLK_MQ_F_SHOULD_MERGE;
+		if (blk_mq_alloc_tag_set(set)) {
 			put_disk(disk);
-			return;
+			continue;
 		}
+
+		disk->queue = blk_mq_init_queue(set);
+		if (IS_ERR(disk->queue)) {
+			blk_mq_free_tag_set(set);
+			put_disk(disk);
+			disk->queue = NULL;
+			continue;
+		}
+
+		INIT_LIST_HEAD(&pf->rq_list);
+		disk->queue->queuedata = pf;
 		blk_queue_max_segments(disk->queue, cluster);
 		blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
 		pf->disk = disk;
@@ -784,18 +811,18 @@ static int pf_queue;
 static int set_next_request(void)
 {
 	struct pf_unit *pf;
-	struct request_queue *q;
 	int old_pos = pf_queue;
 
 	do {
 		pf = &units[pf_queue];
-		q = pf->present ? pf->disk->queue : NULL;
 		if (++pf_queue == PF_UNITS)
 			pf_queue = 0;
-		if (q) {
-			pf_req = blk_fetch_request(q);
-			if (pf_req)
-				break;
+		if (pf->present && !list_empty(&pf->rq_list)) {
+			pf_req = list_first_entry(&pf->rq_list, struct request,
+							queuelist);
+			list_del_init(&pf_req->queuelist);
+			blk_mq_start_request(pf_req);
+			break;
 		}
 	} while (pf_queue != old_pos);
 
@@ -804,8 +831,12 @@ static int set_next_request(void)
 
 static void pf_end_request(blk_status_t err)
 {
-	if (pf_req && !__blk_end_request_cur(pf_req, err))
+	if (!pf_req)
+		return;
+	if (!blk_update_request(pf_req, err, blk_rq_cur_bytes(pf_req))) {
+		__blk_mq_end_request(pf_req, err);
 		pf_req = NULL;
+	}
 }
 
 static void pf_request(void)
@@ -842,9 +873,17 @@ static void pf_request(void)
 	}
 }
 
-static void do_pf_request(struct request_queue *q)
+static blk_status_t pf_queue_rq(struct blk_mq_hw_ctx *hctx,
+				const struct blk_mq_queue_data *bd)
 {
+	struct pf_unit *pf = hctx->queue->queuedata;
+	
+	spin_lock_irq(&pf_spin_lock);
+	list_add_tail(&bd->rq->queuelist, &pf->rq_list);
 	pf_request();
+	spin_unlock_irq(&pf_spin_lock);
+
+	return BLK_STS_OK;
 }
 
 static int pf_next_buf(void)
@@ -1023,6 +1062,7 @@ static void __exit pf_exit(void)
 		if (!pf->present)
 			continue;
 		del_gendisk(pf->disk);
+		blk_mq_free_tag_set(&pf->tag_set);
 		blk_cleanup_queue(pf->disk->queue);
 		put_disk(pf->disk);
 		pi_release(pf->pi);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 07/17] uml: convert ubd to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (5 preceding siblings ...)
  2018-10-11 16:58 ` [PATCH 06/17] paride: convert pf " Jens Axboe
@ 2018-10-11 16:58 ` Jens Axboe
  2018-10-15 10:27   ` Ming Lei
  2018-10-11 16:59 ` [PATCH 08/17] ms_block: convert " Jens Axboe
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:58 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe, Jeff Dike

Just a straight forward conversion. The retry handling could
potentially be done by blk-mq as well, but that's for another
day.

Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 arch/um/drivers/ubd_kern.c | 154 ++++++++++++++++++++++---------------
 1 file changed, 94 insertions(+), 60 deletions(-)

diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 83c470364dfb..a302962a441d 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -22,7 +22,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/ata.h>
 #include <linux/hdreg.h>
 #include <linux/cdrom.h>
@@ -156,6 +156,7 @@ struct ubd {
 	struct cow cow;
 	struct platform_device pdev;
 	struct request_queue *queue;
+	struct blk_mq_tag_set tag_set;
 	spinlock_t lock;
 	struct scatterlist sg[MAX_SG];
 	struct request *request;
@@ -436,7 +437,9 @@ __uml_help(udb_setup,
 "    in the boot output.\n\n"
 );
 
-static void do_ubd_request(struct request_queue * q);
+static void ubd_handle_request(struct ubd *dev);
+static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx,
+				 const struct blk_mq_queue_data *bd);
 
 /* Only changed by ubd_init, which is an initcall. */
 static int thread_fd = -1;
@@ -520,12 +523,12 @@ static void ubd_handler(void)
 			return;
 		}
 		for (count = 0; count < n/sizeof(struct io_thread_req *); count++) {
-			blk_end_request(
-				(*irq_req_buffer)[count]->req,
-				BLK_STS_OK,
-				(*irq_req_buffer)[count]->length
-			);
-			kfree((*irq_req_buffer)[count]);
+			struct io_thread_req *io_req = (*irq_req_buffer)[count];
+
+			if (!blk_update_request(io_req->req, BLK_STS_OK, io_req->length))
+				__blk_mq_end_request(io_req->req, BLK_STS_OK);
+
+			kfree(io_req);
 		}
 	}
 	reactivate_fd(thread_fd, UBD_IRQ);
@@ -534,7 +537,7 @@ static void ubd_handler(void)
 		ubd = container_of(list, struct ubd, restart);
 		list_del_init(&ubd->restart);
 		spin_lock_irqsave(&ubd->lock, flags);
-		do_ubd_request(ubd->queue);
+		ubd_handle_request(ubd);
 		spin_unlock_irqrestore(&ubd->lock, flags);
 	}
 }
@@ -856,6 +859,7 @@ static void ubd_device_release(struct device *dev)
 {
 	struct ubd *ubd_dev = dev_get_drvdata(dev);
 
+	blk_mq_free_tag_set(&ubd_dev->tag_set);
 	blk_cleanup_queue(ubd_dev->queue);
 	*ubd_dev = ((struct ubd) DEFAULT_UBD);
 }
@@ -897,20 +901,25 @@ static int ubd_disk_register(int major, u64 size, int unit,
 	return 0;
 }
 
+static const struct blk_mq_ops ubd_mq_ops = {
+	.queue_rq	= ubd_queue_rq,
+};
+
 #define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9))
 
 static int ubd_add(int n, char **error_out)
 {
 	struct ubd *ubd_dev = &ubd_devs[n];
+	struct blk_mq_tag_set *set;
 	int err = 0;
 
 	if(ubd_dev->file == NULL)
-		goto out;
+		goto out1;
 
 	err = ubd_file_size(ubd_dev, &ubd_dev->size);
 	if(err < 0){
 		*error_out = "Couldn't determine size of device's file";
-		goto out;
+		goto out1;
 	}
 
 	ubd_dev->size = ROUND_BLOCK(ubd_dev->size);
@@ -918,12 +927,26 @@ static int ubd_add(int n, char **error_out)
 	INIT_LIST_HEAD(&ubd_dev->restart);
 	sg_init_table(ubd_dev->sg, MAX_SG);
 
-	err = -ENOMEM;
-	ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock);
-	if (ubd_dev->queue == NULL) {
+	set = &ubd_dev->tag_set;
+	set->ops = &ubd_mq_ops;
+	set->nr_hw_queues = 1;
+	set->queue_depth = 2;
+	set->numa_node = NUMA_NO_NODE;
+	set->flags = BLK_MQ_F_SHOULD_MERGE;
+	err = blk_mq_alloc_tag_set(set);
+	if (err) {
+		*error_out = "Failed to initialize device tag set";
+		goto out1;
+	}
+
+	ubd_dev->queue = blk_mq_init_queue(set);
+	if (IS_ERR(ubd_dev->queue)) {
+		err = PTR_ERR(ubd_dev->queue);
+		ubd_dev->queue = NULL;
 		*error_out = "Failed to initialize device queue";
 		goto out;
 	}
+
 	ubd_dev->queue->queuedata = ubd_dev;
 	blk_queue_write_cache(ubd_dev->queue, true, false);
 
@@ -947,9 +970,12 @@ static int ubd_add(int n, char **error_out)
 
 	err = 0;
 out:
+	blk_mq_free_tag_set(&ubd_dev->tag_set);
+out1:
 	return err;
 
 out_cleanup:
+	blk_mq_free_tag_set(&ubd_dev->tag_set);
 	blk_cleanup_queue(ubd_dev->queue);
 	goto out;
 }
@@ -1338,10 +1364,11 @@ static bool submit_request(struct io_thread_req *io_req, struct ubd *dev)
 	int n = os_write_file(thread_fd, &io_req,
 			     sizeof(io_req));
 	if (n != sizeof(io_req)) {
-		if (n != -EAGAIN)
+		if (n != -EAGAIN) {
 			printk("write to io thread failed, "
 			       "errno = %d\n", -n);
-		else if (list_empty(&dev->restart))
+			blk_mq_end_request(io_req->req, BLK_STS_IOERR);
+		} else if (list_empty(&dev->restart))
 			list_add(&dev->restart, &restart);
 
 		kfree(io_req);
@@ -1351,62 +1378,69 @@ static bool submit_request(struct io_thread_req *io_req, struct ubd *dev)
 }
 
 /* Called with dev->lock held */
-static void do_ubd_request(struct request_queue *q)
+static void ubd_handle_request(struct ubd *dev)
 {
+	struct request *req = dev->request;
 	struct io_thread_req *io_req;
-	struct request *req;
-
-	while(1){
-		struct ubd *dev = q->queuedata;
-		if(dev->request == NULL){
-			struct request *req = blk_fetch_request(q);
-			if(req == NULL)
-				return;
 
-			dev->request = req;
-			dev->rq_pos = blk_rq_pos(req);
-			dev->start_sg = 0;
-			dev->end_sg = blk_rq_map_sg(q, req, dev->sg);
+	if (req_op(req) == REQ_OP_FLUSH) {
+		io_req = kmalloc(sizeof(struct io_thread_req), GFP_ATOMIC);
+		if (io_req == NULL) {
+			if (list_empty(&dev->restart))
+				list_add(&dev->restart, &restart);
+			return;
 		}
+		prepare_flush_request(req, io_req);
+		if (submit_request(io_req, dev) == false)
+			return;
+	}
 
-		req = dev->request;
+	while (dev->start_sg < dev->end_sg){
+		struct scatterlist *sg = &dev->sg[dev->start_sg];
 
-		if (req_op(req) == REQ_OP_FLUSH) {
-			io_req = kmalloc(sizeof(struct io_thread_req),
-					 GFP_ATOMIC);
-			if (io_req == NULL) {
-				if (list_empty(&dev->restart))
-					list_add(&dev->restart, &restart);
-				return;
-			}
-			prepare_flush_request(req, io_req);
-			if (submit_request(io_req, dev) == false)
-				return;
+		io_req = kmalloc(sizeof(struct io_thread_req), GFP_ATOMIC);
+		if (io_req == NULL){
+			if (list_empty(&dev->restart))
+				list_add(&dev->restart, &restart);
+			return;
 		}
+		prepare_request(req, io_req,
+				(unsigned long long)dev->rq_pos << 9,
+				sg->offset, sg->length, sg_page(sg));
 
-		while(dev->start_sg < dev->end_sg){
-			struct scatterlist *sg = &dev->sg[dev->start_sg];
+		if (submit_request(io_req, dev) == false)
+			return;
 
-			io_req = kmalloc(sizeof(struct io_thread_req),
-					 GFP_ATOMIC);
-			if(io_req == NULL){
-				if(list_empty(&dev->restart))
-					list_add(&dev->restart, &restart);
-				return;
-			}
-			prepare_request(req, io_req,
-					(unsigned long long)dev->rq_pos << 9,
-					sg->offset, sg->length, sg_page(sg));
+		dev->rq_pos += sg->length >> 9;
+		dev->start_sg++;
+	}
 
-			if (submit_request(io_req, dev) == false)
-				return;
+	dev->end_sg = 0;
+	dev->request = NULL;
+}
 
-			dev->rq_pos += sg->length >> 9;
-			dev->start_sg++;
-		}
-		dev->end_sg = 0;
-		dev->request = NULL;
+static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx,
+				 const struct blk_mq_queue_data *bd)
+{
+	struct ubd *dev = hctx->queue->queuedata;
+	struct request *req;
+
+	spin_lock_irq(&dev->lock);
+	if (dev->request != NULL) {
+		spin_unlock_irq(&dev->lock);
+		return BLK_STS_DEV_RESOURCE;
 	}
+
+	req = bd->rq;
+	blk_mq_start_request(req);
+	dev->request = req;
+	dev->rq_pos = blk_rq_pos(req);
+	dev->start_sg = 0;
+	dev->end_sg = blk_rq_map_sg(req->q, req, dev->sg);
+
+	ubd_handle_request(dev);
+	spin_unlock_irq(&dev->lock);
+	return BLK_STS_OK;
 }
 
 static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 08/17] ms_block: convert to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (6 preceding siblings ...)
  2018-10-11 16:58 ` [PATCH 07/17] uml: convert ubd " Jens Axboe
@ 2018-10-11 16:59 ` Jens Axboe
  2018-10-14  6:30   ` Maxim Levitsky
  2018-10-11 16:59 ` [PATCH 09/17] mspro_block: " Jens Axboe
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:59 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe, Maxim Levitsky

Straight forward conversion, room for optimization in how everything
is punted to a work queue. Also looks plenty racy all over the map,
with the state changes. I fixed a bunch of them up while doing the
conversion, but there are surely more.

Cc: Maxim Levitsky <maximlevitsky@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/memstick/core/ms_block.c | 121 ++++++++++++++++++-------------
 drivers/memstick/core/ms_block.h |   1 +
 2 files changed, 73 insertions(+), 49 deletions(-)

diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c
index 716fc8ed31d3..b829f55ff577 100644
--- a/drivers/memstick/core/ms_block.c
+++ b/drivers/memstick/core/ms_block.c
@@ -15,7 +15,7 @@
 #define pr_fmt(fmt) DRIVER_NAME ": " fmt
 
 #include <linux/module.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/memstick.h>
 #include <linux/idr.h>
 #include <linux/hdreg.h>
@@ -1873,69 +1873,65 @@ static void msb_io_work(struct work_struct *work)
 	struct msb_data *msb = container_of(work, struct msb_data, io_work);
 	int page, error, len;
 	sector_t lba;
-	unsigned long flags;
 	struct scatterlist *sg = msb->prealloc_sg;
+	struct request *req;
 
 	dbg_verbose("IO: work started");
 
 	while (1) {
-		spin_lock_irqsave(&msb->q_lock, flags);
+		spin_lock_irq(&msb->q_lock);
 
 		if (msb->need_flush_cache) {
 			msb->need_flush_cache = false;
-			spin_unlock_irqrestore(&msb->q_lock, flags);
+			spin_unlock_irq(&msb->q_lock);
 			msb_cache_flush(msb);
 			continue;
 		}
 
-		if (!msb->req) {
-			msb->req = blk_fetch_request(msb->queue);
-			if (!msb->req) {
-				dbg_verbose("IO: no more requests exiting");
-				spin_unlock_irqrestore(&msb->q_lock, flags);
-				return;
-			}
+		req = msb->req;
+		if (!req) {
+			dbg_verbose("IO: no more requests exiting");
+			spin_unlock_irq(&msb->q_lock);
+			return;
 		}
 
-		spin_unlock_irqrestore(&msb->q_lock, flags);
-
-		/* If card was removed meanwhile */
-		if (!msb->req)
-			return;
+		spin_unlock_irq(&msb->q_lock);
 
 		/* process the request */
 		dbg_verbose("IO: processing new request");
-		blk_rq_map_sg(msb->queue, msb->req, sg);
+		blk_rq_map_sg(msb->queue, req, sg);
 
-		lba = blk_rq_pos(msb->req);
+		lba = blk_rq_pos(req);
 
 		sector_div(lba, msb->page_size / 512);
 		page = sector_div(lba, msb->pages_in_block);
 
 		if (rq_data_dir(msb->req) == READ)
 			error = msb_do_read_request(msb, lba, page, sg,
-				blk_rq_bytes(msb->req), &len);
+				blk_rq_bytes(req), &len);
 		else
 			error = msb_do_write_request(msb, lba, page, sg,
-				blk_rq_bytes(msb->req), &len);
+				blk_rq_bytes(req), &len);
 
-		spin_lock_irqsave(&msb->q_lock, flags);
-
-		if (len)
-			if (!__blk_end_request(msb->req, BLK_STS_OK, len))
-				msb->req = NULL;
+		if (len && !blk_update_request(req, BLK_STS_OK, len)) {
+			__blk_mq_end_request(req, BLK_STS_OK);
+			spin_lock_irq(&msb->q_lock);
+			msb->req = NULL;
+			spin_unlock_irq(&msb->q_lock);
+		}
 
 		if (error && msb->req) {
 			blk_status_t ret = errno_to_blk_status(error);
+
 			dbg_verbose("IO: ending one sector of the request with error");
-			if (!__blk_end_request(msb->req, ret, msb->page_size))
-				msb->req = NULL;
+			blk_mq_end_request(req, ret);
+			spin_lock_irq(&msb->q_lock);
+			msb->req = NULL;
+			spin_unlock_irq(&msb->q_lock);
 		}
 
 		if (msb->req)
 			dbg_verbose("IO: request still pending");
-
-		spin_unlock_irqrestore(&msb->q_lock, flags);
 	}
 }
 
@@ -2002,29 +1998,40 @@ static int msb_bd_getgeo(struct block_device *bdev,
 	return 0;
 }
 
-static void msb_submit_req(struct request_queue *q)
+static blk_status_t msb_queue_rq(struct blk_mq_hw_ctx *hctx,
+				 const struct blk_mq_queue_data *bd)
 {
-	struct memstick_dev *card = q->queuedata;
+	struct memstick_dev *card = hctx->queue->queuedata;
 	struct msb_data *msb = memstick_get_drvdata(card);
-	struct request *req = NULL;
+	struct request *req = bd->rq;
 
 	dbg_verbose("Submit request");
 
+	spin_lock_irq(&msb->q_lock);
+
 	if (msb->card_dead) {
 		dbg("Refusing requests on removed card");
 
 		WARN_ON(!msb->io_queue_stopped);
 
-		while ((req = blk_fetch_request(q)) != NULL)
-			__blk_end_request_all(req, BLK_STS_IOERR);
-		return;
+		spin_unlock_irq(&msb->q_lock);
+		blk_mq_start_request(req);
+		return BLK_STS_IOERR;
 	}
 
-	if (msb->req)
-		return;
+	if (msb->req) {
+		spin_unlock_irq(&msb->q_lock);
+		return BLK_STS_DEV_RESOURCE;
+	}
+
+	blk_mq_start_request(req);
+	msb->req = req;
 
 	if (!msb->io_queue_stopped)
 		queue_work(msb->io_queue, &msb->io_work);
+
+	spin_unlock_irq(&msb->q_lock);
+	return BLK_STS_OK;
 }
 
 static int msb_check_card(struct memstick_dev *card)
@@ -2040,21 +2047,20 @@ static void msb_stop(struct memstick_dev *card)
 
 	dbg("Stopping all msblock IO");
 
+	blk_mq_stop_hw_queues(msb->queue);
 	spin_lock_irqsave(&msb->q_lock, flags);
-	blk_stop_queue(msb->queue);
 	msb->io_queue_stopped = true;
 	spin_unlock_irqrestore(&msb->q_lock, flags);
 
 	del_timer_sync(&msb->cache_flush_timer);
 	flush_workqueue(msb->io_queue);
 
+	spin_lock_irqsave(&msb->q_lock, flags);
 	if (msb->req) {
-		spin_lock_irqsave(&msb->q_lock, flags);
-		blk_requeue_request(msb->queue, msb->req);
+		blk_mq_requeue_request(msb->req, false);
 		msb->req = NULL;
-		spin_unlock_irqrestore(&msb->q_lock, flags);
 	}
-
+	spin_unlock_irqrestore(&msb->q_lock, flags);
 }
 
 static void msb_start(struct memstick_dev *card)
@@ -2077,9 +2083,7 @@ static void msb_start(struct memstick_dev *card)
 	msb->need_flush_cache = true;
 	msb->io_queue_stopped = false;
 
-	spin_lock_irqsave(&msb->q_lock, flags);
-	blk_start_queue(msb->queue);
-	spin_unlock_irqrestore(&msb->q_lock, flags);
+	blk_mq_start_hw_queues(msb->queue);
 
 	queue_work(msb->io_queue, &msb->io_work);
 
@@ -2092,10 +2096,15 @@ static const struct block_device_operations msb_bdops = {
 	.owner   = THIS_MODULE
 };
 
+static const struct blk_mq_ops msb_mq_ops = {
+	.queue_rq	= msb_queue_rq,
+};
+
 /* Registers the block device */
 static int msb_init_disk(struct memstick_dev *card)
 {
 	struct msb_data *msb = memstick_get_drvdata(card);
+	struct blk_mq_tag_set *set = NULL;
 	int rc;
 	unsigned long capacity;
 
@@ -2112,10 +2121,21 @@ static int msb_init_disk(struct memstick_dev *card)
 		goto out_release_id;
 	}
 
-	msb->queue = blk_init_queue(msb_submit_req, &msb->q_lock);
-	if (!msb->queue) {
-		rc = -ENOMEM;
+	set = &msb->tag_set;
+	set->ops = &msb_mq_ops;
+	set->nr_hw_queues = 1;
+	set->queue_depth = 2;
+	set->numa_node = NUMA_NO_NODE;
+	set->flags = BLK_MQ_F_SHOULD_MERGE;
+	rc = blk_mq_alloc_tag_set(set);
+	if (rc)
 		goto out_put_disk;
+
+	msb->queue = blk_mq_init_queue(set);
+	if (IS_ERR(msb->queue)) {
+		rc = PTR_ERR(msb->queue);
+		msb->queue = NULL;
+		goto out_put_tag;
 	}
 
 	msb->queue->queuedata = card;
@@ -2150,6 +2170,8 @@ static int msb_init_disk(struct memstick_dev *card)
 	dbg("Disk added");
 	return 0;
 
+out_put_tag:
+	blk_mq_free_tag_set(&msb->tag_set);
 out_put_disk:
 	put_disk(msb->disk);
 out_release_id:
@@ -2202,11 +2224,12 @@ static void msb_remove(struct memstick_dev *card)
 	/* Take care of unhandled + new requests from now on */
 	spin_lock_irqsave(&msb->q_lock, flags);
 	msb->card_dead = true;
-	blk_start_queue(msb->queue);
 	spin_unlock_irqrestore(&msb->q_lock, flags);
+	blk_mq_start_hw_queues(msb->queue);
 
 	/* Remove the disk */
 	del_gendisk(msb->disk);
+	blk_mq_free_tag_set(msb->queue->tag_set);
 	blk_cleanup_queue(msb->queue);
 	msb->queue = NULL;
 
diff --git a/drivers/memstick/core/ms_block.h b/drivers/memstick/core/ms_block.h
index 53962c3b21df..9ba84e0ced63 100644
--- a/drivers/memstick/core/ms_block.h
+++ b/drivers/memstick/core/ms_block.h
@@ -152,6 +152,7 @@ struct msb_data {
 	struct gendisk			*disk;
 	struct request_queue		*queue;
 	spinlock_t			q_lock;
+	struct blk_mq_tag_set		tag_set;
 	struct hd_geometry		geometry;
 	struct attribute_group		attr_group;
 	struct request			*req;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 09/17] mspro_block: convert to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (7 preceding siblings ...)
  2018-10-11 16:59 ` [PATCH 08/17] ms_block: convert " Jens Axboe
@ 2018-10-11 16:59 ` Jens Axboe
  2018-10-11 16:59 ` [PATCH 10/17] gdrom: " Jens Axboe
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:59 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe

Straight forward conversion, there's room for improvement.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/memstick/core/mspro_block.c | 133 ++++++++++++++++------------
 1 file changed, 78 insertions(+), 55 deletions(-)

diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index 5ee932631fae..d55b398d16c4 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -12,7 +12,7 @@
  *
  */
 
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/idr.h>
 #include <linux/hdreg.h>
 #include <linux/kthread.h>
@@ -142,6 +142,7 @@ struct mspro_block_data {
 	struct gendisk        *disk;
 	struct request_queue  *queue;
 	struct request        *block_req;
+	struct blk_mq_tag_set tag_set;
 	spinlock_t            q_lock;
 
 	unsigned short        page_size;
@@ -152,7 +153,6 @@ struct mspro_block_data {
 	unsigned char         system;
 	unsigned char         read_only:1,
 			      eject:1,
-			      has_request:1,
 			      data_dir:1,
 			      active:1;
 	unsigned char         transfer_cmd;
@@ -694,13 +694,12 @@ static void h_mspro_block_setup_cmd(struct memstick_dev *card, u64 offset,
 
 /*** Data transfer ***/
 
-static int mspro_block_issue_req(struct memstick_dev *card, int chunk)
+static int mspro_block_issue_req(struct memstick_dev *card, bool chunk)
 {
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
 	u64 t_off;
 	unsigned int count;
 
-try_again:
 	while (chunk) {
 		msb->current_page = 0;
 		msb->current_seg = 0;
@@ -709,9 +708,17 @@ static int mspro_block_issue_req(struct memstick_dev *card, int chunk)
 					       msb->req_sg);
 
 		if (!msb->seg_count) {
-			chunk = __blk_end_request_cur(msb->block_req,
-					BLK_STS_RESOURCE);
-			continue;
+			unsigned int bytes = blk_rq_cur_bytes(msb->block_req);
+
+			chunk = blk_update_request(msb->block_req,
+							BLK_STS_RESOURCE,
+							bytes);
+			if (chunk)
+				continue;
+			__blk_mq_end_request(msb->block_req,
+						BLK_STS_RESOURCE);
+			msb->block_req = NULL;
+			break;
 		}
 
 		t_off = blk_rq_pos(msb->block_req);
@@ -729,30 +736,22 @@ static int mspro_block_issue_req(struct memstick_dev *card, int chunk)
 		return 0;
 	}
 
-	dev_dbg(&card->dev, "blk_fetch\n");
-	msb->block_req = blk_fetch_request(msb->queue);
-	if (!msb->block_req) {
-		dev_dbg(&card->dev, "issue end\n");
-		return -EAGAIN;
-	}
-
-	dev_dbg(&card->dev, "trying again\n");
-	chunk = 1;
-	goto try_again;
+	return 1;
 }
 
 static int mspro_block_complete_req(struct memstick_dev *card, int error)
 {
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
-	int chunk, cnt;
+	int cnt;
+	bool chunk;
 	unsigned int t_len = 0;
 	unsigned long flags;
 
 	spin_lock_irqsave(&msb->q_lock, flags);
-	dev_dbg(&card->dev, "complete %d, %d\n", msb->has_request ? 1 : 0,
+	dev_dbg(&card->dev, "complete %d, %d\n", msb->block_req ? 1 : 0,
 		error);
 
-	if (msb->has_request) {
+	if (msb->block_req) {
 		/* Nothing to do - not really an error */
 		if (error == -EAGAIN)
 			error = 0;
@@ -777,15 +776,17 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
 		if (error && !t_len)
 			t_len = blk_rq_cur_bytes(msb->block_req);
 
-		chunk = __blk_end_request(msb->block_req,
+		chunk = blk_update_request(msb->block_req,
 				errno_to_blk_status(error), t_len);
-
-		error = mspro_block_issue_req(card, chunk);
-
-		if (!error)
-			goto out;
-		else
-			msb->has_request = 0;
+		if (chunk) {
+			error = mspro_block_issue_req(card, chunk);
+			if (!error)
+				goto out;
+		} else {
+			__blk_mq_end_request(msb->block_req,
+						errno_to_blk_status(error));
+			msb->block_req = NULL;
+		}
 	} else {
 		if (!error)
 			error = -EAGAIN;
@@ -806,8 +807,8 @@ static void mspro_block_stop(struct memstick_dev *card)
 
 	while (1) {
 		spin_lock_irqsave(&msb->q_lock, flags);
-		if (!msb->has_request) {
-			blk_stop_queue(msb->queue);
+		if (!msb->block_req) {
+			blk_mq_stop_hw_queues(msb->queue);
 			rc = 1;
 		}
 		spin_unlock_irqrestore(&msb->q_lock, flags);
@@ -822,32 +823,37 @@ static void mspro_block_stop(struct memstick_dev *card)
 static void mspro_block_start(struct memstick_dev *card)
 {
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
-	unsigned long flags;
 
-	spin_lock_irqsave(&msb->q_lock, flags);
-	blk_start_queue(msb->queue);
-	spin_unlock_irqrestore(&msb->q_lock, flags);
+	blk_mq_start_hw_queues(msb->queue);
 }
 
-static void mspro_block_submit_req(struct request_queue *q)
+static blk_status_t mspro_queue_rq(struct blk_mq_hw_ctx *hctx,
+				   const struct blk_mq_queue_data *bd)
 {
-	struct memstick_dev *card = q->queuedata;
+	struct memstick_dev *card = hctx->queue->queuedata;
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
-	struct request *req = NULL;
 
-	if (msb->has_request)
-		return;
+	spin_lock_irq(&msb->q_lock);
 
-	if (msb->eject) {
-		while ((req = blk_fetch_request(q)) != NULL)
-			__blk_end_request_all(req, BLK_STS_IOERR);
+	if (msb->block_req) {
+		spin_unlock_irq(&msb->q_lock);
+		return BLK_STS_DEV_RESOURCE;
+	}
 
-		return;
+	if (msb->eject) {
+		spin_unlock_irq(&msb->q_lock);
+		blk_mq_start_request(bd->rq);
+		return BLK_STS_IOERR;
 	}
 
-	msb->has_request = 1;
-	if (mspro_block_issue_req(card, 0))
-		msb->has_request = 0;
+	msb->block_req = bd->rq;
+	blk_mq_start_request(bd->rq);
+
+	if (mspro_block_issue_req(card, true))
+		msb->block_req = NULL;
+
+	spin_unlock_irq(&msb->q_lock);
+	return BLK_STS_OK;
 }
 
 /*** Initialization ***/
@@ -1167,12 +1173,17 @@ static int mspro_block_init_card(struct memstick_dev *card)
 
 }
 
+static const struct blk_mq_ops mspro_mq_ops = {
+	.queue_rq	= mspro_queue_rq,
+};
+
 static int mspro_block_init_disk(struct memstick_dev *card)
 {
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
 	struct mspro_devinfo *dev_info = NULL;
 	struct mspro_sys_info *sys_info = NULL;
 	struct mspro_sys_attr *s_attr = NULL;
+	struct blk_mq_tag_set *set;
 	int rc, disk_id;
 	unsigned long capacity;
 
@@ -1206,10 +1217,21 @@ static int mspro_block_init_disk(struct memstick_dev *card)
 		goto out_release_id;
 	}
 
-	msb->queue = blk_init_queue(mspro_block_submit_req, &msb->q_lock);
-	if (!msb->queue) {
-		rc = -ENOMEM;
+	set = &msb->tag_set;
+	set->ops = &mspro_mq_ops;
+	set->nr_hw_queues = 1;
+	set->queue_depth = 2;
+	set->numa_node = NUMA_NO_NODE;
+	set->flags = BLK_MQ_F_SHOULD_MERGE;
+	rc = blk_mq_alloc_tag_set(set);
+	if (rc)
 		goto out_put_disk;
+
+	msb->queue = blk_mq_init_queue(set);
+	if (IS_ERR(msb->queue)) {
+		rc = PTR_ERR(msb->queue);
+		msb->queue = NULL;
+		goto out_put_tag;
 	}
 
 	msb->queue->queuedata = card;
@@ -1240,6 +1262,8 @@ static int mspro_block_init_disk(struct memstick_dev *card)
 	msb->active = 1;
 	return 0;
 
+out_put_tag:
+	blk_mq_free_tag_set(&msb->tag_set);
 out_put_disk:
 	put_disk(msb->disk);
 out_release_id:
@@ -1318,12 +1342,13 @@ static void mspro_block_remove(struct memstick_dev *card)
 
 	spin_lock_irqsave(&msb->q_lock, flags);
 	msb->eject = 1;
-	blk_start_queue(msb->queue);
 	spin_unlock_irqrestore(&msb->q_lock, flags);
+	blk_mq_start_hw_queues(msb->queue);
 
 	del_gendisk(msb->disk);
 	dev_dbg(&card->dev, "mspro block remove\n");
 
+	blk_mq_free_tag_set(msb->queue->tag_set);
 	blk_cleanup_queue(msb->queue);
 	msb->queue = NULL;
 
@@ -1344,8 +1369,9 @@ static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state)
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
 	unsigned long flags;
 
+	blk_mq_stop_hw_queues(msb->queue);
+
 	spin_lock_irqsave(&msb->q_lock, flags);
-	blk_stop_queue(msb->queue);
 	msb->active = 0;
 	spin_unlock_irqrestore(&msb->q_lock, flags);
 
@@ -1355,7 +1381,6 @@ static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state)
 static int mspro_block_resume(struct memstick_dev *card)
 {
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
-	unsigned long flags;
 	int rc = 0;
 
 #ifdef CONFIG_MEMSTICK_UNSAFE_RESUME
@@ -1401,9 +1426,7 @@ static int mspro_block_resume(struct memstick_dev *card)
 
 #endif /* CONFIG_MEMSTICK_UNSAFE_RESUME */
 
-	spin_lock_irqsave(&msb->q_lock, flags);
-	blk_start_queue(msb->queue);
-	spin_unlock_irqrestore(&msb->q_lock, flags);
+	blk_mq_start_hw_queues(msb->queue);
 	return rc;
 }
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 10/17] gdrom: convert to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (8 preceding siblings ...)
  2018-10-11 16:59 ` [PATCH 09/17] mspro_block: " Jens Axboe
@ 2018-10-11 16:59 ` Jens Axboe
  2018-10-11 16:59 ` [PATCH 11/17] z2ram: " Jens Axboe
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:59 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe

Ditch the deffered list, lock, and workqueue handling. Just mark the
set as being blocking, so we are invoked from a workqueue already.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/cdrom/gdrom.c | 182 ++++++++++++++++++++----------------------
 1 file changed, 87 insertions(+), 95 deletions(-)

diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index ae3a7537cf0f..41b57d9c4424 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -31,12 +31,11 @@
 #include <linux/cdrom.h>
 #include <linux/genhd.h>
 #include <linux/bio.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/wait.h>
-#include <linux/workqueue.h>
 #include <linux/platform_device.h>
 #include <scsi/scsi.h>
 #include <asm/io.h>
@@ -102,11 +101,6 @@ static int gdrom_major;
 static DECLARE_WAIT_QUEUE_HEAD(command_queue);
 static DECLARE_WAIT_QUEUE_HEAD(request_queue);
 
-static DEFINE_SPINLOCK(gdrom_lock);
-static void gdrom_readdisk_dma(struct work_struct *work);
-static DECLARE_WORK(work, gdrom_readdisk_dma);
-static LIST_HEAD(gdrom_deferred);
-
 struct gdromtoc {
 	unsigned int entry[99];
 	unsigned int first, last;
@@ -122,6 +116,7 @@ static struct gdrom_unit {
 	char disk_type;
 	struct gdromtoc *toc;
 	struct request_queue *gdrom_rq;
+	struct blk_mq_tag_set tag_set;
 } gd;
 
 struct gdrom_id {
@@ -584,103 +579,83 @@ static int gdrom_set_interrupt_handlers(void)
  * 9 -> sectors >> 8
  * 10 -> sectors
  */
-static void gdrom_readdisk_dma(struct work_struct *work)
+static blk_status_t gdrom_readdisk_dma(struct request *req)
 {
 	int block, block_cnt;
 	blk_status_t err;
 	struct packet_command *read_command;
-	struct list_head *elem, *next;
-	struct request *req;
 	unsigned long timeout;
 
-	if (list_empty(&gdrom_deferred))
-		return;
 	read_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL);
 	if (!read_command)
-		return; /* get more memory later? */
+		return BLK_STS_RESOURCE;
+
 	read_command->cmd[0] = 0x30;
 	read_command->cmd[1] = 0x20;
-	spin_lock(&gdrom_lock);
-	list_for_each_safe(elem, next, &gdrom_deferred) {
-		req = list_entry(elem, struct request, queuelist);
-		spin_unlock(&gdrom_lock);
-		block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET;
-		block_cnt = blk_rq_sectors(req)/GD_TO_BLK;
-		__raw_writel(virt_to_phys(bio_data(req->bio)), GDROM_DMA_STARTADDR_REG);
-		__raw_writel(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG);
-		__raw_writel(1, GDROM_DMA_DIRECTION_REG);
-		__raw_writel(1, GDROM_DMA_ENABLE_REG);
-		read_command->cmd[2] = (block >> 16) & 0xFF;
-		read_command->cmd[3] = (block >> 8) & 0xFF;
-		read_command->cmd[4] = block & 0xFF;
-		read_command->cmd[8] = (block_cnt >> 16) & 0xFF;
-		read_command->cmd[9] = (block_cnt >> 8) & 0xFF;
-		read_command->cmd[10] = block_cnt & 0xFF;
-		/* set for DMA */
-		__raw_writeb(1, GDROM_ERROR_REG);
-		/* other registers */
-		__raw_writeb(0, GDROM_SECNUM_REG);
-		__raw_writeb(0, GDROM_BCL_REG);
-		__raw_writeb(0, GDROM_BCH_REG);
-		__raw_writeb(0, GDROM_DSEL_REG);
-		__raw_writeb(0, GDROM_INTSEC_REG);
-		/* Wait for registers to reset after any previous activity */
-		timeout = jiffies + HZ / 2;
-		while (gdrom_is_busy() && time_before(jiffies, timeout))
-			cpu_relax();
-		__raw_writeb(GDROM_COM_PACKET, GDROM_STATUSCOMMAND_REG);
-		timeout = jiffies + HZ / 2;
-		/* Wait for packet command to finish */
-		while (gdrom_is_busy() && time_before(jiffies, timeout))
-			cpu_relax();
-		gd.pending = 1;
-		gd.transfer = 1;
-		outsw(GDROM_DATA_REG, &read_command->cmd, 6);
-		timeout = jiffies + HZ / 2;
-		/* Wait for any pending DMA to finish */
-		while (__raw_readb(GDROM_DMA_STATUS_REG) &&
-			time_before(jiffies, timeout))
-			cpu_relax();
-		/* start transfer */
-		__raw_writeb(1, GDROM_DMA_STATUS_REG);
-		wait_event_interruptible_timeout(request_queue,
-			gd.transfer == 0, GDROM_DEFAULT_TIMEOUT);
-		err = gd.transfer ? BLK_STS_IOERR : BLK_STS_OK;
-		gd.transfer = 0;
-		gd.pending = 0;
-		/* now seek to take the request spinlock
-		* before handling ending the request */
-		spin_lock(&gdrom_lock);
-		list_del_init(&req->queuelist);
-		__blk_end_request_all(req, err);
-	}
-	spin_unlock(&gdrom_lock);
+	block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET;
+	block_cnt = blk_rq_sectors(req)/GD_TO_BLK;
+	__raw_writel(virt_to_phys(bio_data(req->bio)), GDROM_DMA_STARTADDR_REG);
+	__raw_writel(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG);
+	__raw_writel(1, GDROM_DMA_DIRECTION_REG);
+	__raw_writel(1, GDROM_DMA_ENABLE_REG);
+	read_command->cmd[2] = (block >> 16) & 0xFF;
+	read_command->cmd[3] = (block >> 8) & 0xFF;
+	read_command->cmd[4] = block & 0xFF;
+	read_command->cmd[8] = (block_cnt >> 16) & 0xFF;
+	read_command->cmd[9] = (block_cnt >> 8) & 0xFF;
+	read_command->cmd[10] = block_cnt & 0xFF;
+	/* set for DMA */
+	__raw_writeb(1, GDROM_ERROR_REG);
+	/* other registers */
+	__raw_writeb(0, GDROM_SECNUM_REG);
+	__raw_writeb(0, GDROM_BCL_REG);
+	__raw_writeb(0, GDROM_BCH_REG);
+	__raw_writeb(0, GDROM_DSEL_REG);
+	__raw_writeb(0, GDROM_INTSEC_REG);
+	/* Wait for registers to reset after any previous activity */
+	timeout = jiffies + HZ / 2;
+	while (gdrom_is_busy() && time_before(jiffies, timeout))
+		cpu_relax();
+	__raw_writeb(GDROM_COM_PACKET, GDROM_STATUSCOMMAND_REG);
+	timeout = jiffies + HZ / 2;
+	/* Wait for packet command to finish */
+	while (gdrom_is_busy() && time_before(jiffies, timeout))
+		cpu_relax();
+	gd.pending = 1;
+	gd.transfer = 1;
+	outsw(GDROM_DATA_REG, &read_command->cmd, 6);
+	timeout = jiffies + HZ / 2;
+	/* Wait for any pending DMA to finish */
+	while (__raw_readb(GDROM_DMA_STATUS_REG) &&
+		time_before(jiffies, timeout))
+		cpu_relax();
+	/* start transfer */
+	__raw_writeb(1, GDROM_DMA_STATUS_REG);
+	wait_event_interruptible_timeout(request_queue,
+		gd.transfer == 0, GDROM_DEFAULT_TIMEOUT);
+	err = gd.transfer ? BLK_STS_IOERR : BLK_STS_OK;
+	gd.transfer = 0;
+	gd.pending = 0;
+
+	blk_mq_end_request(req, err);
 	kfree(read_command);
+	return BLK_STS_OK;
 }
 
-static void gdrom_request(struct request_queue *rq)
-{
-	struct request *req;
-
-	while ((req = blk_fetch_request(rq)) != NULL) {
-		switch (req_op(req)) {
-		case REQ_OP_READ:
-			/*
-			 * Add to list of deferred work and then schedule
-			 * workqueue.
-			 */
-			list_add_tail(&req->queuelist, &gdrom_deferred);
-			schedule_work(&work);
-			break;
-		case REQ_OP_WRITE:
-			pr_notice("Read only device - write request ignored\n");
-			__blk_end_request_all(req, BLK_STS_IOERR);
-			break;
-		default:
-			printk(KERN_DEBUG "gdrom: Non-fs request ignored\n");
-			__blk_end_request_all(req, BLK_STS_IOERR);
-			break;
-		}
+static blk_status_t gdrom_queue_rq(struct blk_mq_hw_ctx *hctx,
+				   const struct blk_mq_queue_data *bd)
+{
+	blk_mq_start_request(bd->rq);
+
+	switch (req_op(bd->rq)) {
+	case REQ_OP_READ:
+		return gdrom_readdisk_dma(bd->rq);
+	case REQ_OP_WRITE:
+		pr_notice("Read only device - write request ignored\n");
+		return BLK_STS_IOERR;
+	default:
+		printk(KERN_DEBUG "gdrom: Non-fs request ignored\n");
+		return BLK_STS_IOERR;
 	}
 }
 
@@ -768,6 +743,10 @@ static int probe_gdrom_setupqueue(void)
 	return gdrom_init_dma_mode();
 }
 
+static const struct blk_mq_ops gdrom_mq_ops = {
+	.queue_rq	= gdrom_queue_rq,
+};
+
 /*
  * register this as a block device and as compliant with the
  * universal CD Rom driver interface
@@ -811,11 +790,23 @@ static int probe_gdrom(struct platform_device *devptr)
 	err = gdrom_set_interrupt_handlers();
 	if (err)
 		goto probe_fail_cmdirq_register;
-	gd.gdrom_rq = blk_init_queue(gdrom_request, &gdrom_lock);
-	if (!gd.gdrom_rq) {
-		err = -ENOMEM;
+
+	gd.tag_set.ops = &gdrom_mq_ops;
+	gd.tag_set.nr_hw_queues = 1;
+	gd.tag_set.queue_depth = 1;
+	gd.tag_set.numa_node = NUMA_NO_NODE;
+	gd.tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING;
+	err = blk_mq_alloc_tag_set(&td.tag_set);
+	if (err)
+		goto probe_fail_requestq;
+
+	gd.gdrom_rq = blk_mq_init_queue(set);
+	if (IS_ERR(gd.gdrom_rq)) {
+		rc = PTR_ERR(gd.gdrom_rq);
+		gd.gdrom_rq = NULL;
 		goto probe_fail_requestq;
 	}
+
 	blk_queue_bounce_limit(gd.gdrom_rq, BLK_BOUNCE_HIGH);
 
 	err = probe_gdrom_setupqueue();
@@ -831,6 +822,7 @@ static int probe_gdrom(struct platform_device *devptr)
 	return 0;
 
 probe_fail_toc:
+	blk_mq_free_tag_set(&gd.tag_set);
 	blk_cleanup_queue(gd.gdrom_rq);
 probe_fail_requestq:
 	free_irq(HW_EVENT_GDROM_DMA, &gd);
@@ -849,7 +841,7 @@ static int probe_gdrom(struct platform_device *devptr)
 
 static int remove_gdrom(struct platform_device *devptr)
 {
-	flush_work(&work);
+	blk_mq_free_tag_set(&gd.tag_set);
 	blk_cleanup_queue(gd.gdrom_rq);
 	free_irq(HW_EVENT_GDROM_CMD, &gd);
 	free_irq(HW_EVENT_GDROM_DMA, &gd);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 11/17] z2ram: convert to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (9 preceding siblings ...)
  2018-10-11 16:59 ` [PATCH 10/17] gdrom: " Jens Axboe
@ 2018-10-11 16:59 ` Jens Axboe
  2018-10-11 16:59 ` [PATCH 12/17] blk-mq-sched: export way for drivers to insert request Jens Axboe
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:59 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe

Straight forward conversion to blk-mq, nothing special about this
driver.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/block/z2ram.c | 96 ++++++++++++++++++++++++++-----------------
 1 file changed, 58 insertions(+), 38 deletions(-)

diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index d0c5bc4e0703..82a022a5297e 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -31,7 +31,7 @@
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
@@ -66,43 +66,44 @@ static DEFINE_SPINLOCK(z2ram_lock);
 
 static struct gendisk *z2ram_gendisk;
 
-static void do_z2_request(struct request_queue *q)
+static blk_status_t z2_queue_rq(struct blk_mq_hw_ctx *hctx,
+				const struct blk_mq_queue_data *bd)
 {
-	struct request *req;
-
-	req = blk_fetch_request(q);
-	while (req) {
-		unsigned long start = blk_rq_pos(req) << 9;
-		unsigned long len  = blk_rq_cur_bytes(req);
-		blk_status_t err = BLK_STS_OK;
-
-		if (start + len > z2ram_size) {
-			pr_err(DEVICE_NAME ": bad access: block=%llu, "
-			       "count=%u\n",
-			       (unsigned long long)blk_rq_pos(req),
-			       blk_rq_cur_sectors(req));
-			err = BLK_STS_IOERR;
-			goto done;
-		}
-		while (len) {
-			unsigned long addr = start & Z2RAM_CHUNKMASK;
-			unsigned long size = Z2RAM_CHUNKSIZE - addr;
-			void *buffer = bio_data(req->bio);
-
-			if (len < size)
-				size = len;
-			addr += z2ram_map[ start >> Z2RAM_CHUNKSHIFT ];
-			if (rq_data_dir(req) == READ)
-				memcpy(buffer, (char *)addr, size);
-			else
-				memcpy((char *)addr, buffer, size);
-			start += size;
-			len -= size;
-		}
-	done:
-		if (!__blk_end_request_cur(req, err))
-			req = blk_fetch_request(q);
+	struct request *req = bd->rq;
+	unsigned long start = blk_rq_pos(req) << 9;
+	unsigned long len  = blk_rq_cur_bytes(req);
+
+	blk_mq_start_request(req);
+
+	if (start + len > z2ram_size) {
+		pr_err(DEVICE_NAME ": bad access: block=%llu, "
+		       "count=%u\n",
+		       (unsigned long long)blk_rq_pos(req),
+		       blk_rq_cur_sectors(req));
+		return BLK_STS_IOERR;
 	}
+
+	spin_lock_irq(&z2ram_lock);
+
+	while (len) {
+		unsigned long addr = start & Z2RAM_CHUNKMASK;
+		unsigned long size = Z2RAM_CHUNKSIZE - addr;
+		void *buffer = bio_data(req->bio);
+
+		if (len < size)
+			size = len;
+		addr += z2ram_map[ start >> Z2RAM_CHUNKSHIFT ];
+		if (rq_data_dir(req) == READ)
+			memcpy(buffer, (char *)addr, size);
+		else
+			memcpy((char *)addr, buffer, size);
+		start += size;
+		len -= size;
+	}
+
+	spin_unlock_irq(&z2ram_lock);
+	blk_mq_end_request(req, BLK_STS_OK);
+	return BLK_STS_OK;
 }
 
 static void
@@ -337,6 +338,11 @@ static struct kobject *z2_find(dev_t dev, int *part, void *data)
 }
 
 static struct request_queue *z2_queue;
+static struct blk_mq_tag_set tag_set;
+
+static const struct blk_mq_ops z2_mq_ops = {
+	.queue_rq	= z2_queue_rq,
+};
 
 static int __init 
 z2_init(void)
@@ -355,10 +361,23 @@ z2_init(void)
     if (!z2ram_gendisk)
 	goto out_disk;
 
-    z2_queue = blk_init_queue(do_z2_request, &z2ram_lock);
-    if (!z2_queue)
+    tag_set.ops = &z2_mq_ops;
+    tag_set.nr_hw_queues = 1;
+    tag_set.queue_depth = 16; /* no hard limit */
+    tag_set.numa_node = NUMA_NO_NODE;
+    tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
+    ret = blk_mq_alloc_tag_set(&tag_set);
+    if (ret)
 	goto out_queue;
 
+    z2_queue = blk_mq_init_queue(&tag_set);
+    if (IS_ERR(z2_queue)) {
+	ret = PTR_ERR(z2_queue);
+	z2_queue = NULL;
+	blk_mq_free_tag_set(&tag_set);
+	goto out_queue;
+    }
+
     z2ram_gendisk->major = Z2RAM_MAJOR;
     z2ram_gendisk->first_minor = 0;
     z2ram_gendisk->fops = &z2_fops;
@@ -386,6 +405,7 @@ static void __exit z2_exit(void)
     unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
     del_gendisk(z2ram_gendisk);
     put_disk(z2ram_gendisk);
+    blk_mq_free_tag_set(&tag_set);
     blk_cleanup_queue(z2_queue);
 
     if ( current_device != -1 )
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 12/17] blk-mq-sched: export way for drivers to insert request
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (10 preceding siblings ...)
  2018-10-11 16:59 ` [PATCH 11/17] z2ram: " Jens Axboe
@ 2018-10-11 16:59 ` Jens Axboe
  2018-10-14 18:49   ` Christoph Hellwig
  2018-10-11 16:59 ` [PATCH 13/17] ide: convert to blk-mq Jens Axboe
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:59 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe

We'll need this for the IDE conversion, which queues sense requests.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 block/blk-mq-sched.c   | 1 +
 block/blk-mq-sched.h   | 2 --
 include/linux/blk-mq.h | 2 ++
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c
index 29bfe8017a2d..f307af1a42bc 100644
--- a/block/blk-mq-sched.c
+++ b/block/blk-mq-sched.c
@@ -395,6 +395,7 @@ void blk_mq_sched_insert_request(struct request *rq, bool at_head,
 	if (run_queue)
 		blk_mq_run_hw_queue(hctx, async);
 }
+EXPORT_SYMBOL_GPL(blk_mq_sched_insert_request);
 
 void blk_mq_sched_insert_requests(struct request_queue *q,
 				  struct blk_mq_ctx *ctx,
diff --git a/block/blk-mq-sched.h b/block/blk-mq-sched.h
index 4e028ee42430..6b3e8255f3af 100644
--- a/block/blk-mq-sched.h
+++ b/block/blk-mq-sched.h
@@ -17,8 +17,6 @@ bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio);
 bool blk_mq_sched_try_insert_merge(struct request_queue *q, struct request *rq);
 void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx);
 
-void blk_mq_sched_insert_request(struct request *rq, bool at_head,
-				 bool run_queue, bool async);
 void blk_mq_sched_insert_requests(struct request_queue *q,
 				  struct blk_mq_ctx *ctx,
 				  struct list_head *list, bool run_queue_async);
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 1da59c16f637..1d4f8588701d 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -260,6 +260,8 @@ void blk_mq_add_to_requeue_list(struct request *rq, bool at_head,
 				bool kick_requeue_list);
 void blk_mq_kick_requeue_list(struct request_queue *q);
 void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs);
+void blk_mq_sched_insert_request(struct request *rq, bool at_head,
+				 bool run_queue, bool async);
 void blk_mq_complete_request(struct request *rq);
 bool blk_mq_bio_list_merge(struct request_queue *q, struct list_head *list,
 			   struct bio *bio);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 13/17] ide: convert to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (11 preceding siblings ...)
  2018-10-11 16:59 ` [PATCH 12/17] blk-mq-sched: export way for drivers to insert request Jens Axboe
@ 2018-10-11 16:59 ` Jens Axboe
  2018-10-11 16:59 ` [PATCH 14/17] aoe: convert aoeblk " Jens Axboe
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:59 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe, David Miller

ide-disk and ide-cd tested as working just fine, ide-tape and
ide-floppy haven't. But the latter don't require changes, so they
should work without issue.

Cc: David Miller <davem@davemloft.net>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/ide/ide-atapi.c |  25 ++++--
 drivers/ide/ide-cd.c    | 175 +++++++++++++++++++++-------------------
 drivers/ide/ide-disk.c  |   8 +-
 drivers/ide/ide-io.c    |  84 ++++++++++---------
 drivers/ide/ide-park.c  |   2 +-
 drivers/ide/ide-pm.c    |  26 ++----
 drivers/ide/ide-probe.c |  43 +++++-----
 include/linux/ide.h     |   8 +-
 8 files changed, 194 insertions(+), 177 deletions(-)

diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 8b2b72b93885..d65c3b2ab2b3 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -172,8 +172,8 @@ EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd);
 void ide_prep_sense(ide_drive_t *drive, struct request *rq)
 {
 	struct request_sense *sense = &drive->sense_data;
-	struct request *sense_rq = drive->sense_rq;
-	struct scsi_request *req = scsi_req(sense_rq);
+	struct request *sense_rq;
+	struct scsi_request *req;
 	unsigned int cmd_len, sense_len;
 	int err;
 
@@ -196,9 +196,16 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
 	if (ata_sense_request(rq) || drive->sense_rq_armed)
 		return;
 
+	sense_rq = drive->sense_rq;
+	if (!sense_rq) {
+		sense_rq = blk_mq_alloc_request(drive->queue, REQ_OP_DRV_IN,
+					BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
+		drive->sense_rq = sense_rq;
+	}
+	req = scsi_req(sense_rq);
+
 	memset(sense, 0, sizeof(*sense));
 
-	blk_rq_init(rq->q, sense_rq);
 	scsi_req_init(req);
 
 	err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len,
@@ -207,6 +214,8 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
 		if (printk_ratelimit())
 			printk(KERN_WARNING PFX "%s: failed to map sense "
 					    "buffer\n", drive->name);
+		blk_mq_free_request(sense_rq);
+		drive->sense_rq = NULL;
 		return;
 	}
 
@@ -226,6 +235,8 @@ EXPORT_SYMBOL_GPL(ide_prep_sense);
 
 int ide_queue_sense_rq(ide_drive_t *drive, void *special)
 {
+	struct request *sense_rq = drive->sense_rq;
+
 	/* deferred failure from ide_prep_sense() */
 	if (!drive->sense_rq_armed) {
 		printk(KERN_WARNING PFX "%s: error queuing a sense request\n",
@@ -233,12 +244,12 @@ int ide_queue_sense_rq(ide_drive_t *drive, void *special)
 		return -ENOMEM;
 	}
 
-	drive->sense_rq->special = special;
+	sense_rq->special = special;
 	drive->sense_rq_armed = false;
 
 	drive->hwif->rq = NULL;
 
-	elv_add_request(drive->queue, drive->sense_rq, ELEVATOR_INSERT_FRONT);
+	blk_mq_sched_insert_request(sense_rq, true, true, true);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
@@ -270,10 +281,8 @@ void ide_retry_pc(ide_drive_t *drive)
 	 */
 	drive->hwif->rq = NULL;
 	ide_requeue_and_plug(drive, failed_rq);
-	if (ide_queue_sense_rq(drive, pc)) {
-		blk_start_request(failed_rq);
+	if (ide_queue_sense_rq(drive, pc))
 		ide_complete_rq(drive, BLK_STS_IOERR, blk_rq_bytes(failed_rq));
-	}
 }
 EXPORT_SYMBOL_GPL(ide_retry_pc);
 
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 44a7a255ef74..188bcfb07aac 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -258,11 +258,22 @@ static int ide_cd_breathe(ide_drive_t *drive, struct request *rq)
 		/*
 		 * take a breather
 		 */
-		blk_delay_queue(drive->queue, 1);
+		blk_mq_requeue_request(rq, false);
+		blk_mq_delay_kick_requeue_list(drive->queue, 1);
 		return 1;
 	}
 }
 
+static void ide_cd_free_sense(ide_drive_t *drive)
+{
+	if (!drive->sense_rq)
+		return;
+
+	blk_mq_free_request(drive->sense_rq);
+	drive->sense_rq = NULL;
+	drive->sense_rq_armed = false;
+}
+
 /**
  * Returns:
  * 0: if the request should be continued.
@@ -516,6 +527,82 @@ static bool ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
 	return false;
 }
 
+/* standard prep_rq_fn that builds 10 byte cmds */
+static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
+{
+	int hard_sect = queue_logical_block_size(q);
+	long block = (long)blk_rq_pos(rq) / (hard_sect >> 9);
+	unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9);
+	struct scsi_request *req = scsi_req(rq);
+
+	if (rq_data_dir(rq) == READ)
+		req->cmd[0] = GPCMD_READ_10;
+	else
+		req->cmd[0] = GPCMD_WRITE_10;
+
+	/*
+	 * fill in lba
+	 */
+	req->cmd[2] = (block >> 24) & 0xff;
+	req->cmd[3] = (block >> 16) & 0xff;
+	req->cmd[4] = (block >>  8) & 0xff;
+	req->cmd[5] = block & 0xff;
+
+	/*
+	 * and transfer length
+	 */
+	req->cmd[7] = (blocks >> 8) & 0xff;
+	req->cmd[8] = blocks & 0xff;
+	req->cmd_len = 10;
+	return BLKPREP_OK;
+}
+
+/*
+ * Most of the SCSI commands are supported directly by ATAPI devices.
+ * This transform handles the few exceptions.
+ */
+static int ide_cdrom_prep_pc(struct request *rq)
+{
+	u8 *c = scsi_req(rq)->cmd;
+
+	/* transform 6-byte read/write commands to the 10-byte version */
+	if (c[0] == READ_6 || c[0] == WRITE_6) {
+		c[8] = c[4];
+		c[5] = c[3];
+		c[4] = c[2];
+		c[3] = c[1] & 0x1f;
+		c[2] = 0;
+		c[1] &= 0xe0;
+		c[0] += (READ_10 - READ_6);
+		scsi_req(rq)->cmd_len = 10;
+		return BLKPREP_OK;
+	}
+
+	/*
+	 * it's silly to pretend we understand 6-byte sense commands, just
+	 * reject with ILLEGAL_REQUEST and the caller should take the
+	 * appropriate action
+	 */
+	if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) {
+		scsi_req(rq)->result = ILLEGAL_REQUEST;
+		return BLKPREP_KILL;
+	}
+
+	return BLKPREP_OK;
+}
+
+static int ide_cdrom_prep_fn(ide_drive_t *drive, struct request *rq)
+{
+	if (!blk_rq_is_passthrough(rq)) {
+		scsi_req_init(scsi_req(rq));
+
+		return ide_cdrom_prep_fs(drive->queue, rq);
+	} else if (blk_rq_is_scsi(rq))
+		return ide_cdrom_prep_pc(rq);
+
+	return 0;
+}
+
 static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
@@ -675,7 +762,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
 out_end:
 	if (blk_rq_is_scsi(rq) && rc == 0) {
 		scsi_req(rq)->resid_len = 0;
-		blk_end_request_all(rq, BLK_STS_OK);
+		blk_mq_end_request(rq, BLK_STS_OK);
 		hwif->rq = NULL;
 	} else {
 		if (sense && uptodate)
@@ -705,6 +792,8 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
 		if (sense && rc == 2)
 			ide_error(drive, "request sense failure", stat);
 	}
+
+	ide_cd_free_sense(drive);
 	return ide_stopped;
 }
 
@@ -729,7 +818,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
 		 * We may be retrying this request after an error.  Fix up any
 		 * weirdness which might be present in the request packet.
 		 */
-		q->prep_rq_fn(q, rq);
+		ide_cdrom_prep_fn(drive, rq);
 	}
 
 	/* fs requests *must* be hardware frame aligned */
@@ -1323,82 +1412,6 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
 	return nslots;
 }
 
-/* standard prep_rq_fn that builds 10 byte cmds */
-static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
-{
-	int hard_sect = queue_logical_block_size(q);
-	long block = (long)blk_rq_pos(rq) / (hard_sect >> 9);
-	unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9);
-	struct scsi_request *req = scsi_req(rq);
-
-	q->initialize_rq_fn(rq);
-
-	if (rq_data_dir(rq) == READ)
-		req->cmd[0] = GPCMD_READ_10;
-	else
-		req->cmd[0] = GPCMD_WRITE_10;
-
-	/*
-	 * fill in lba
-	 */
-	req->cmd[2] = (block >> 24) & 0xff;
-	req->cmd[3] = (block >> 16) & 0xff;
-	req->cmd[4] = (block >>  8) & 0xff;
-	req->cmd[5] = block & 0xff;
-
-	/*
-	 * and transfer length
-	 */
-	req->cmd[7] = (blocks >> 8) & 0xff;
-	req->cmd[8] = blocks & 0xff;
-	req->cmd_len = 10;
-	return BLKPREP_OK;
-}
-
-/*
- * Most of the SCSI commands are supported directly by ATAPI devices.
- * This transform handles the few exceptions.
- */
-static int ide_cdrom_prep_pc(struct request *rq)
-{
-	u8 *c = scsi_req(rq)->cmd;
-
-	/* transform 6-byte read/write commands to the 10-byte version */
-	if (c[0] == READ_6 || c[0] == WRITE_6) {
-		c[8] = c[4];
-		c[5] = c[3];
-		c[4] = c[2];
-		c[3] = c[1] & 0x1f;
-		c[2] = 0;
-		c[1] &= 0xe0;
-		c[0] += (READ_10 - READ_6);
-		scsi_req(rq)->cmd_len = 10;
-		return BLKPREP_OK;
-	}
-
-	/*
-	 * it's silly to pretend we understand 6-byte sense commands, just
-	 * reject with ILLEGAL_REQUEST and the caller should take the
-	 * appropriate action
-	 */
-	if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) {
-		scsi_req(rq)->result = ILLEGAL_REQUEST;
-		return BLKPREP_KILL;
-	}
-
-	return BLKPREP_OK;
-}
-
-static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq)
-{
-	if (!blk_rq_is_passthrough(rq))
-		return ide_cdrom_prep_fs(q, rq);
-	else if (blk_rq_is_scsi(rq))
-		return ide_cdrom_prep_pc(rq);
-
-	return 0;
-}
-
 struct cd_list_entry {
 	const char	*id_model;
 	const char	*id_firmware;
@@ -1508,7 +1521,7 @@ static int ide_cdrom_setup(ide_drive_t *drive)
 
 	ide_debug_log(IDE_DBG_PROBE, "enter");
 
-	blk_queue_prep_rq(q, ide_cdrom_prep_fn);
+	drive->prep_rq = ide_cdrom_prep_fn;
 	blk_queue_dma_alignment(q, 31);
 	blk_queue_update_dma_pad(q, 15);
 
@@ -1569,7 +1582,7 @@ static void ide_cd_release(struct device *dev)
 	if (devinfo->handle == drive)
 		unregister_cdrom(devinfo);
 	drive->driver_data = NULL;
-	blk_queue_prep_rq(drive->queue, NULL);
+	drive->prep_rq = NULL;
 	g->private_data = NULL;
 	put_disk(g);
 	kfree(info);
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index e3b4e659082d..b14a1446586d 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -187,6 +187,9 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
 	BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED);
 	BUG_ON(blk_rq_is_passthrough(rq));
 
+	if (drive->queue->prep_rq_fn && drive->queue->prep_rq_fn(drive->queue, rq))
+		return ide_stopped;
+
 	ledtrig_disk_activity(rq_data_dir(rq) == WRITE);
 
 	pr_debug("%s: %sing: block=%llu, sectors=%u\n",
@@ -427,9 +430,8 @@ static void ide_disk_unlock_native_capacity(ide_drive_t *drive)
 		drive->dev_flags |= IDE_DFLAG_NOHPA; /* disable HPA on resume */
 }
 
-static int idedisk_prep_fn(struct request_queue *q, struct request *rq)
+static int idedisk_prep_fn(ide_drive_t *drive, struct request *rq)
 {
-	ide_drive_t *drive = q->queuedata;
 	struct ide_cmd *cmd;
 
 	if (req_op(rq) != REQ_OP_FLUSH)
@@ -548,7 +550,7 @@ static void update_flush(ide_drive_t *drive)
 
 		if (barrier) {
 			wc = true;
-			blk_queue_prep_rq(drive->queue, idedisk_prep_fn);
+			drive->prep_rq = idedisk_prep_fn;
 		}
 	}
 
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 0d93e0cfbeaf..b583eeac7864 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -67,7 +67,15 @@ int ide_end_rq(ide_drive_t *drive, struct request *rq, blk_status_t error,
 		ide_dma_on(drive);
 	}
 
-	return blk_end_request(rq, error, nr_bytes);
+	if (!blk_update_request(rq, error, nr_bytes)) {
+		if (rq == drive->sense_rq)
+			drive->sense_rq = NULL;
+
+		__blk_mq_end_request(rq, error);
+		return 0;
+	}
+
+	return 1;
 }
 EXPORT_SYMBOL_GPL(ide_end_rq);
 
@@ -307,8 +315,6 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
 {
 	ide_startstop_t startstop;
 
-	BUG_ON(!(rq->rq_flags & RQF_STARTED));
-
 #ifdef DEBUG
 	printk("%s: start_request: current=0x%08lx\n",
 		drive->hwif->name, (unsigned long) rq);
@@ -320,6 +326,9 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
 		goto kill_rq;
 	}
 
+	if (drive->prep_rq && drive->prep_rq(drive, rq))
+		return ide_stopped;
+
 	if (ata_pm_request(rq))
 		ide_check_pm_state(drive, rq);
 
@@ -430,44 +439,38 @@ static inline void ide_unlock_host(struct ide_host *host)
 	}
 }
 
-static void __ide_requeue_and_plug(struct request_queue *q, struct request *rq)
-{
-	if (rq)
-		blk_requeue_request(q, rq);
-	if (rq || blk_peek_request(q)) {
-		/* Use 3ms as that was the old plug delay */
-		blk_delay_queue(q, 3);
-	}
-}
-
 void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
 {
 	struct request_queue *q = drive->queue;
-	unsigned long flags;
 
-	spin_lock_irqsave(q->queue_lock, flags);
-	__ide_requeue_and_plug(q, rq);
-	spin_unlock_irqrestore(q->queue_lock, flags);
+	/* Use 3ms as that was the old plug delay */
+	if (rq) {
+		blk_mq_requeue_request(rq, false);
+		blk_mq_delay_kick_requeue_list(q, 3);
+	} else
+		blk_mq_delay_run_hw_queue(q->queue_hw_ctx[0], 3);
 }
 
 /*
  * Issue a new request to a device.
  */
-void do_ide_request(struct request_queue *q)
+blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
+			  const struct blk_mq_queue_data *bd)
 {
-	ide_drive_t	*drive = q->queuedata;
+	ide_drive_t	*drive = hctx->queue->queuedata;
 	ide_hwif_t	*hwif = drive->hwif;
 	struct ide_host *host = hwif->host;
 	struct request	*rq = NULL;
 	ide_startstop_t	startstop;
 
-	spin_unlock_irq(q->queue_lock);
-
 	/* HLD do_request() callback might sleep, make sure it's okay */
 	might_sleep();
 
 	if (ide_lock_host(host, hwif))
-		goto plug_device_2;
+		return BLK_STS_DEV_RESOURCE;
+
+	rq = bd->rq;
+	blk_mq_start_request(rq);
 
 	spin_lock_irq(&hwif->lock);
 
@@ -503,21 +506,16 @@ void do_ide_request(struct request_queue *q)
 		hwif->cur_dev = drive;
 		drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
 
-		spin_unlock_irq(&hwif->lock);
-		spin_lock_irq(q->queue_lock);
 		/*
 		 * we know that the queue isn't empty, but this can happen
 		 * if the q->prep_rq_fn() decides to kill a request
 		 */
-		if (!rq)
-			rq = blk_fetch_request(drive->queue);
-
-		spin_unlock_irq(q->queue_lock);
-		spin_lock_irq(&hwif->lock);
-
 		if (!rq) {
-			ide_unlock_port(hwif);
-			goto out;
+			rq = bd->rq;
+			if (!rq) {
+				ide_unlock_port(hwif);
+				goto out;
+			}
 		}
 
 		/*
@@ -553,21 +551,19 @@ void do_ide_request(struct request_queue *q)
 			hwif->rq = NULL;
 			goto repeat;
 		}
-	} else
-		goto plug_device;
+	} else {
+plug_device:
+		spin_unlock_irq(&hwif->lock);
+		ide_unlock_host(host);
+		ide_requeue_and_plug(drive, rq);
+		return BLK_STS_OK;
+	}
+
 out:
 	spin_unlock_irq(&hwif->lock);
 	if (rq == NULL)
 		ide_unlock_host(host);
-	spin_lock_irq(q->queue_lock);
-	return;
-
-plug_device:
-	spin_unlock_irq(&hwif->lock);
-	ide_unlock_host(host);
-plug_device_2:
-	spin_lock_irq(q->queue_lock);
-	__ide_requeue_and_plug(q, rq);
+	return BLK_STS_OK;
 }
 
 static int drive_is_ready(ide_drive_t *drive)
@@ -617,6 +613,8 @@ void ide_timer_expiry (struct timer_list *t)
 	int		plug_device = 0;
 	struct request	*uninitialized_var(rq_in_flight);
 
+	return;
+
 	spin_lock_irqsave(&hwif->lock, flags);
 
 	handler = hwif->handler;
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
index 622f0edb3945..45f989792633 100644
--- a/drivers/ide/ide-park.c
+++ b/drivers/ide/ide-park.c
@@ -54,7 +54,7 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
 	scsi_req(rq)->cmd[0] = REQ_UNPARK_HEADS;
 	scsi_req(rq)->cmd_len = 1;
 	ide_req(rq)->type = ATA_PRIV_MISC;
-	elv_add_request(q, rq, ELEVATOR_INSERT_FRONT);
+	blk_mq_sched_insert_request(rq, true, true, true);
 
 out:
 	return;
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c
index 59217aa1d1fb..cca47adda527 100644
--- a/drivers/ide/ide-pm.c
+++ b/drivers/ide/ide-pm.c
@@ -40,32 +40,20 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg)
 	return ret;
 }
 
-static void ide_end_sync_rq(struct request *rq, blk_status_t error)
-{
-	complete(rq->end_io_data);
-}
-
 static int ide_pm_execute_rq(struct request *rq)
 {
 	struct request_queue *q = rq->q;
-	DECLARE_COMPLETION_ONSTACK(wait);
-
-	rq->end_io_data = &wait;
-	rq->end_io = ide_end_sync_rq;
 
 	spin_lock_irq(q->queue_lock);
 	if (unlikely(blk_queue_dying(q))) {
 		rq->rq_flags |= RQF_QUIET;
 		scsi_req(rq)->result = -ENXIO;
-		__blk_end_request_all(rq, BLK_STS_OK);
 		spin_unlock_irq(q->queue_lock);
+		blk_mq_end_request(rq, BLK_STS_OK);
 		return -ENXIO;
 	}
-	__elv_add_request(q, rq, ELEVATOR_INSERT_FRONT);
-	__blk_run_queue_uncond(q);
 	spin_unlock_irq(q->queue_lock);
-
-	wait_for_completion_io(&wait);
+	blk_execute_rq(q, NULL, rq, true);
 
 	return scsi_req(rq)->result ? -EIO : 0;
 }
@@ -226,15 +214,14 @@ void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq)
 #endif
 	spin_lock_irqsave(q->queue_lock, flags);
 	if (ide_req(rq)->type == ATA_PRIV_PM_SUSPEND)
-		blk_stop_queue(q);
+		blk_mq_stop_hw_queues(q);
 	else
 		drive->dev_flags &= ~IDE_DFLAG_BLOCKED;
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
 	drive->hwif->rq = NULL;
 
-	if (blk_end_request(rq, BLK_STS_OK, 0))
-		BUG();
+	blk_mq_end_request(rq, BLK_STS_OK);
 }
 
 void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
@@ -260,7 +247,6 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
 		ide_hwif_t *hwif = drive->hwif;
 		const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 		struct request_queue *q = drive->queue;
-		unsigned long flags;
 		int rc;
 #ifdef DEBUG_PM
 		printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
@@ -274,8 +260,6 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
 		if (rc)
 			printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
 
-		spin_lock_irqsave(q->queue_lock, flags);
-		blk_start_queue(q);
-		spin_unlock_irqrestore(q->queue_lock, flags);
+		blk_mq_start_hw_queues(q);
 	}
 }
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 3b75a7b7a284..31ed4ab90fff 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -750,6 +750,11 @@ static void ide_initialize_rq(struct request *rq)
 	req->sreq.sense = req->sense;
 }
 
+static const struct blk_mq_ops ide_mq_ops = {
+	.queue_rq		= ide_queue_rq,
+	.initialize_rq_fn	= ide_initialize_rq,
+};
+
 /*
  * init request queue
  */
@@ -759,6 +764,7 @@ static int ide_init_queue(ide_drive_t *drive)
 	ide_hwif_t *hwif = drive->hwif;
 	int max_sectors = 256;
 	int max_sg_entries = PRD_ENTRIES;
+	struct blk_mq_tag_set *set;
 
 	/*
 	 *	Our default set up assumes the normal IDE case,
@@ -767,19 +773,26 @@ static int ide_init_queue(ide_drive_t *drive)
 	 *	limits and LBA48 we could raise it but as yet
 	 *	do not.
 	 */
-	q = blk_alloc_queue_node(GFP_KERNEL, hwif_to_node(hwif), NULL);
-	if (!q)
+
+	set = &drive->tag_set;
+	set->ops = &ide_mq_ops;
+	set->nr_hw_queues = 1;
+	set->queue_depth = 32;
+	set->reserved_tags = 1;
+	set->cmd_size = sizeof(struct ide_request);
+	set->numa_node = hwif_to_node(hwif);
+	set->flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING;
+	if (blk_mq_alloc_tag_set(set))
 		return 1;
 
-	q->request_fn = do_ide_request;
-	q->initialize_rq_fn = ide_initialize_rq;
-	q->cmd_size = sizeof(struct ide_request);
-	blk_queue_flag_set(QUEUE_FLAG_SCSI_PASSTHROUGH, q);
-	if (blk_init_allocated_queue(q) < 0) {
-		blk_cleanup_queue(q);
+	q = blk_mq_init_queue(set);
+	if (IS_ERR(q)) {
+		blk_mq_free_tag_set(set);
 		return 1;
 	}
 
+	blk_queue_flag_set(QUEUE_FLAG_SCSI_PASSTHROUGH, q);
+
 	q->queuedata = drive;
 	blk_queue_segment_boundary(q, 0xffff);
 
@@ -965,6 +978,10 @@ static void drive_release_dev (struct device *dev)
 
 	ide_proc_unregister_device(drive);
 
+	if (drive->sense_rq)
+		blk_mq_free_request(drive->sense_rq);
+
+	blk_mq_free_tag_set(&drive->tag_set);
 	blk_cleanup_queue(drive->queue);
 	drive->queue = NULL;
 
@@ -1145,12 +1162,10 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)
 	ide_port_for_each_dev(i, drive, hwif) {
 		u8 j = (hwif->index * MAX_DRIVES) + i;
 		u16 *saved_id = drive->id;
-		struct request *saved_sense_rq = drive->sense_rq;
 
 		memset(drive, 0, sizeof(*drive));
 		memset(saved_id, 0, SECTOR_SIZE);
 		drive->id = saved_id;
-		drive->sense_rq = saved_sense_rq;
 
 		drive->media			= ide_disk;
 		drive->select			= (i << 4) | ATA_DEVICE_OBS;
@@ -1255,7 +1270,6 @@ static void ide_port_free_devices(ide_hwif_t *hwif)
 	int i;
 
 	ide_port_for_each_dev(i, drive, hwif) {
-		kfree(drive->sense_rq);
 		kfree(drive->id);
 		kfree(drive);
 	}
@@ -1283,17 +1297,10 @@ static int ide_port_alloc_devices(ide_hwif_t *hwif, int node)
 		if (drive->id == NULL)
 			goto out_free_drive;
 
-		drive->sense_rq = kmalloc(sizeof(struct request) +
-				sizeof(struct ide_request), GFP_KERNEL);
-		if (!drive->sense_rq)
-			goto out_free_id;
-
 		hwif->devices[i] = drive;
 	}
 	return 0;
 
-out_free_id:
-	kfree(drive->id);
 out_free_drive:
 	kfree(drive);
 out_nomem:
diff --git a/include/linux/ide.h b/include/linux/ide.h
index c74b0321922a..3e55c362ab7e 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -10,7 +10,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/ata.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/proc_fs.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
@@ -529,6 +529,10 @@ struct ide_drive_s {
 
 	struct request_queue	*queue;	/* request queue */
 
+	int (*prep_rq)(struct ide_drive_s *, struct request *);
+
+	struct blk_mq_tag_set	tag_set;
+
 	struct request		*rq;	/* current request */
 	void		*driver_data;	/* extra driver data */
 	u16			*id;	/* identification info */
@@ -1208,7 +1212,7 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
 
 extern void ide_timer_expiry(struct timer_list *t);
 extern irqreturn_t ide_intr(int irq, void *dev_id);
-extern void do_ide_request(struct request_queue *);
+extern blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *, const struct blk_mq_queue_data *);
 extern void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq);
 
 void ide_init_disk(struct gendisk *, ide_drive_t *);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 14/17] aoe: convert aoeblk to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (12 preceding siblings ...)
  2018-10-11 16:59 ` [PATCH 13/17] ide: convert to blk-mq Jens Axboe
@ 2018-10-11 16:59 ` Jens Axboe
  2018-10-12 11:28   ` Ed Cashin
  2018-10-11 16:59 ` [PATCH 15/17] xsysace: convert " Jens Axboe
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:59 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe, Ed L. Cashin

Straight forward conversion - instead of rewriting the internal buffer
retrieval logic, just replace the previous elevator peeking with an
internal list of requests.

Cc: "Ed L. Cashin" <ed.cashin@acm.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/block/aoe/aoe.h    |  4 ++++
 drivers/block/aoe/aoeblk.c | 49 ++++++++++++++++++++++++++++----------
 drivers/block/aoe/aoecmd.c | 17 +++++++++----
 drivers/block/aoe/aoedev.c | 14 ++++++-----
 4 files changed, 60 insertions(+), 24 deletions(-)

diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index c0ebda1283cc..9b9db29fe712 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,4 +1,6 @@
 /* Copyright (c) 2013 Coraid, Inc.  See COPYING for GPL terms. */
+#include <linux/blk-mq.h>
+
 #define VERSION "85"
 #define AOE_MAJOR 152
 #define DEVICE_NAME "aoe"
@@ -164,6 +166,8 @@ struct aoedev {
 	struct gendisk *gd;
 	struct dentry *debugfs;
 	struct request_queue *blkq;
+	struct list_head rq_list;
+	struct blk_mq_tag_set tag_set;
 	struct hd_geometry geo;
 	sector_t ssize;
 	struct timer_list timer;
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 429ebb84b592..ba4afa0ce1c7 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -6,7 +6,7 @@
 
 #include <linux/kernel.h>
 #include <linux/hdreg.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/backing-dev.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
@@ -274,23 +274,25 @@ aoeblk_release(struct gendisk *disk, fmode_t mode)
 	spin_unlock_irqrestore(&d->lock, flags);
 }
 
-static void
-aoeblk_request(struct request_queue *q)
+static blk_status_t aoeblk_queue_rq(struct blk_mq_hw_ctx *hctx,
+				    const struct blk_mq_queue_data *bd)
 {
-	struct aoedev *d;
-	struct request *rq;
+	struct aoedev *d = hctx->queue->queuedata;
+
+	spin_lock_irq(&d->lock);
 
-	d = q->queuedata;
 	if ((d->flags & DEVFL_UP) == 0) {
 		pr_info_ratelimited("aoe: device %ld.%d is not up\n",
 			d->aoemajor, d->aoeminor);
-		while ((rq = blk_peek_request(q))) {
-			blk_start_request(rq);
-			aoe_end_request(d, rq, 1);
-		}
-		return;
+		spin_unlock_irq(&d->lock);
+		blk_mq_start_request(bd->rq);
+		return BLK_STS_IOERR;
 	}
+
+	list_add_tail(&bd->rq->queuelist, &d->rq_list);
 	aoecmd_work(d);
+	spin_unlock_irq(&d->lock);
+	return BLK_STS_OK;
 }
 
 static int
@@ -345,6 +347,10 @@ static const struct block_device_operations aoe_bdops = {
 	.owner = THIS_MODULE,
 };
 
+static const struct blk_mq_ops aoeblk_mq_ops = {
+	.queue_rq	= aoeblk_queue_rq,
+};
+
 /* alloc_disk and add_disk can sleep */
 void
 aoeblk_gdalloc(void *vp)
@@ -353,9 +359,11 @@ aoeblk_gdalloc(void *vp)
 	struct gendisk *gd;
 	mempool_t *mp;
 	struct request_queue *q;
+	struct blk_mq_tag_set *set;
 	enum { KB = 1024, MB = KB * KB, READ_AHEAD = 2 * MB, };
 	ulong flags;
 	int late = 0;
+	int err;
 
 	spin_lock_irqsave(&d->lock, flags);
 	if (d->flags & DEVFL_GDALLOC
@@ -382,10 +390,25 @@ aoeblk_gdalloc(void *vp)
 			d->aoemajor, d->aoeminor);
 		goto err_disk;
 	}
-	q = blk_init_queue(aoeblk_request, &d->lock);
-	if (q == NULL) {
+
+	set = &d->tag_set;
+	set->ops = &aoeblk_mq_ops;
+	set->nr_hw_queues = 1;
+	set->queue_depth = 128;
+	set->numa_node = NUMA_NO_NODE;
+	set->flags = BLK_MQ_F_SHOULD_MERGE;
+	err = blk_mq_alloc_tag_set(set);
+	if (err) {
+		pr_err("aoe: cannot allocate tag set for %ld.%d\n",
+			d->aoemajor, d->aoeminor);
+		goto err_mempool;
+	}
+
+	q = blk_mq_init_queue(set);
+	if (IS_ERR(q)) {
 		pr_err("aoe: cannot allocate block queue for %ld.%d\n",
 			d->aoemajor, d->aoeminor);
+		blk_mq_free_tag_set(set);
 		goto err_mempool;
 	}
 
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 136dc507d020..fce0fc1fa7bf 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -7,7 +7,7 @@
 #include <linux/ata.h>
 #include <linux/slab.h>
 #include <linux/hdreg.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/genhd.h>
@@ -857,10 +857,12 @@ nextbuf(struct aoedev *d)
 		return d->ip.buf;
 	rq = d->ip.rq;
 	if (rq == NULL) {
-		rq = blk_peek_request(q);
+		rq = list_first_entry_or_null(&d->rq_list, struct request,
+						queuelist);
 		if (rq == NULL)
 			return NULL;
-		blk_start_request(rq);
+		list_del_init(&rq->queuelist);
+		blk_mq_start_request(rq);
 		d->ip.rq = rq;
 		d->ip.nxbio = rq->bio;
 		rq->special = (void *) rqbiocnt(rq);
@@ -1045,6 +1047,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
 	struct bio *bio;
 	int bok;
 	struct request_queue *q;
+	blk_status_t err = BLK_STS_OK;
 
 	q = d->blkq;
 	if (rq == d->ip.rq)
@@ -1052,11 +1055,15 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
 	do {
 		bio = rq->bio;
 		bok = !fastfail && !bio->bi_status;
-	} while (__blk_end_request(rq, bok ? BLK_STS_OK : BLK_STS_IOERR, bio->bi_iter.bi_size));
+		if (!bok)
+			err = BLK_STS_IOERR;
+	} while (blk_update_request(rq, bok ? BLK_STS_OK : BLK_STS_IOERR, bio->bi_iter.bi_size));
+
+	__blk_mq_end_request(rq, err);
 
 	/* cf. http://lkml.org/lkml/2006/10/31/28 */
 	if (!fastfail)
-		__blk_run_queue(q);
+		blk_mq_run_hw_queues(q, true);
 }
 
 static void
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index 41060e9cedf2..96b420ddff3f 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -5,7 +5,7 @@
  */
 
 #include <linux/hdreg.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/netdevice.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -197,7 +197,6 @@ aoedev_downdev(struct aoedev *d)
 {
 	struct aoetgt *t, **tt, **te;
 	struct list_head *head, *pos, *nx;
-	struct request *rq;
 	int i;
 
 	d->flags &= ~DEVFL_UP;
@@ -225,10 +224,11 @@ aoedev_downdev(struct aoedev *d)
 
 	/* fast fail all pending I/O */
 	if (d->blkq) {
-		while ((rq = blk_peek_request(d->blkq))) {
-			blk_start_request(rq);
-			aoe_end_request(d, rq, 1);
-		}
+		/* UP is cleared, freeze+quiesce to insure all are errored */
+		blk_mq_freeze_queue(d->blkq);
+		blk_mq_quiesce_queue(d->blkq);
+		blk_mq_unquiesce_queue(d->blkq);
+		blk_mq_unfreeze_queue(d->blkq);
 	}
 
 	if (d->gd)
@@ -278,6 +278,7 @@ freedev(struct aoedev *d)
 		aoedisk_rm_sysfs(d);
 		del_gendisk(d->gd);
 		put_disk(d->gd);
+		blk_mq_free_tag_set(&d->tag_set);
 		blk_cleanup_queue(d->blkq);
 	}
 	t = d->targets;
@@ -464,6 +465,7 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc)
 	d->ntargets = NTARGETS;
 	INIT_WORK(&d->work, aoecmd_sleepwork);
 	spin_lock_init(&d->lock);
+	INIT_LIST_HEAD(&d->rq_list);
 	skb_queue_head_init(&d->skbpool);
 	timer_setup(&d->timer, dummy_timer, 0);
 	d->timer.expires = jiffies + HZ;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 15/17] xsysace: convert to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (13 preceding siblings ...)
  2018-10-11 16:59 ` [PATCH 14/17] aoe: convert aoeblk " Jens Axboe
@ 2018-10-11 16:59 ` Jens Axboe
  2018-10-12  5:46   ` Michal Simek
  2018-10-11 16:59 ` [PATCH 16/17] mtd_blkdevs: " Jens Axboe
  2018-10-11 16:59 ` [PATCH 17/17] null_blk: remove legacy IO path Jens Axboe
  16 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:59 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe, Michal Simek

Straight forward conversion, using an internal list to enable the
driver to pull requests at will.

Cc: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/block/xsysace.c | 91 ++++++++++++++++++++++++++++++-----------
 1 file changed, 66 insertions(+), 25 deletions(-)

diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index c24589414c75..ddaa362ffe82 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -88,7 +88,7 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/mutex.h>
 #include <linux/ata.h>
 #include <linux/hdreg.h>
@@ -209,6 +209,8 @@ struct ace_device {
 	struct device *dev;
 	struct request_queue *queue;
 	struct gendisk *gd;
+	struct blk_mq_tag_set tag_set;
+	struct list_head rq_list;
 
 	/* Inserted CF card parameters */
 	u16 cf_id[ATA_ID_WORDS];
@@ -462,18 +464,26 @@ static inline void ace_fsm_yieldirq(struct ace_device *ace)
 	ace->fsm_continue_flag = 0;
 }
 
+static bool ace_has_next_request(struct request_queue *q)
+{
+	struct ace_device *ace = q->queuedata;
+
+	return !list_empty(&ace->rq_list);
+}
+
 /* Get the next read/write request; ending requests that we don't handle */
 static struct request *ace_get_next_request(struct request_queue *q)
 {
-	struct request *req;
+	struct ace_device *ace = q->queuedata;
+	struct request *rq;
 
-	while ((req = blk_peek_request(q)) != NULL) {
-		if (!blk_rq_is_passthrough(req))
-			break;
-		blk_start_request(req);
-		__blk_end_request_all(req, BLK_STS_IOERR);
+	rq = list_first_entry_or_null(&ace->rq_list, struct request, queuelist);
+	if (rq) {
+		list_del_init(&rq->queuelist);
+		blk_mq_start_request(rq);
 	}
-	return req;
+
+	return NULL;
 }
 
 static void ace_fsm_dostate(struct ace_device *ace)
@@ -499,11 +509,11 @@ static void ace_fsm_dostate(struct ace_device *ace)
 
 		/* Drop all in-flight and pending requests */
 		if (ace->req) {
-			__blk_end_request_all(ace->req, BLK_STS_IOERR);
+			blk_mq_end_request(ace->req, BLK_STS_IOERR);
 			ace->req = NULL;
 		}
-		while ((req = blk_fetch_request(ace->queue)) != NULL)
-			__blk_end_request_all(req, BLK_STS_IOERR);
+		while ((req = ace_get_next_request(ace->queue)) != NULL)
+			blk_mq_end_request(req, BLK_STS_IOERR);
 
 		/* Drop back to IDLE state and notify waiters */
 		ace->fsm_state = ACE_FSM_STATE_IDLE;
@@ -517,7 +527,7 @@ static void ace_fsm_dostate(struct ace_device *ace)
 	switch (ace->fsm_state) {
 	case ACE_FSM_STATE_IDLE:
 		/* See if there is anything to do */
-		if (ace->id_req_count || ace_get_next_request(ace->queue)) {
+		if (ace->id_req_count || ace_has_next_request(ace->queue)) {
 			ace->fsm_iter_num++;
 			ace->fsm_state = ACE_FSM_STATE_REQ_LOCK;
 			mod_timer(&ace->stall_timer, jiffies + HZ);
@@ -651,7 +661,6 @@ static void ace_fsm_dostate(struct ace_device *ace)
 			ace->fsm_state = ACE_FSM_STATE_IDLE;
 			break;
 		}
-		blk_start_request(req);
 
 		/* Okay, it's a data request, set it up for transfer */
 		dev_dbg(ace->dev,
@@ -728,7 +737,8 @@ static void ace_fsm_dostate(struct ace_device *ace)
 		}
 
 		/* bio finished; is there another one? */
-		if (__blk_end_request_cur(ace->req, BLK_STS_OK)) {
+		if (blk_update_request(ace->req, BLK_STS_OK,
+		    blk_rq_cur_bytes(ace->req))) {
 			/* dev_dbg(ace->dev, "next block; h=%u c=%u\n",
 			 *      blk_rq_sectors(ace->req),
 			 *      blk_rq_cur_sectors(ace->req));
@@ -854,17 +864,23 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id)
 /* ---------------------------------------------------------------------
  * Block ops
  */
-static void ace_request(struct request_queue * q)
+static blk_status_t ace_queue_rq(struct blk_mq_hw_ctx *hctx,
+				 const struct blk_mq_queue_data *bd)
 {
-	struct request *req;
-	struct ace_device *ace;
+	struct ace_device *ace = hctx->queue->queuedata;
+	struct request *req = bd->rq;
 
-	req = ace_get_next_request(q);
-
-	if (req) {
-		ace = req->rq_disk->private_data;
-		tasklet_schedule(&ace->fsm_tasklet);
+	if (blk_rq_is_passthrough(req)) {
+		blk_mq_start_request(req);
+		return BLK_STS_IOERR;
 	}
+
+	spin_lock_irq(&ace->lock);
+	list_add_tail(&req->queuelist, &ace->rq_list);
+	spin_unlock_irq(&ace->lock);
+
+	tasklet_schedule(&ace->fsm_tasklet);
+	return BLK_STS_OK;
 }
 
 static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing)
@@ -957,11 +973,16 @@ static const struct block_device_operations ace_fops = {
 	.getgeo = ace_getgeo,
 };
 
+static const struct blk_mq_ops ace_mq_ops = {
+	.queue_rq	= ace_queue_rq,
+};
+
 /* --------------------------------------------------------------------
  * SystemACE device setup/teardown code
  */
 static int ace_setup(struct ace_device *ace)
 {
+	struct blk_mq_tag_set *set;
 	u16 version;
 	u16 val;
 	int rc;
@@ -972,6 +993,7 @@ static int ace_setup(struct ace_device *ace)
 
 	spin_lock_init(&ace->lock);
 	init_completion(&ace->id_completion);
+	INIT_LIST_HEAD(&ace->rq_list);
 
 	/*
 	 * Map the device
@@ -989,9 +1011,25 @@ static int ace_setup(struct ace_device *ace)
 	/*
 	 * Initialize the request queue
 	 */
-	ace->queue = blk_init_queue(ace_request, &ace->lock);
-	if (ace->queue == NULL)
+	set = &ace->tag_set;
+	set->ops = &ace_mq_ops;
+	set->nr_hw_queues = 1;
+	set->queue_depth = 2;
+	set->numa_node = NUMA_NO_NODE;
+	set->flags = BLK_MQ_F_SHOULD_MERGE;
+	rc = blk_mq_alloc_tag_set(set);
+	if (rc)
 		goto err_blk_initq;
+
+	ace->queue = blk_mq_init_queue(set);
+	if (IS_ERR(ace->queue)) {
+		rc = PTR_ERR(ace->queue);
+		ace->queue = NULL;
+		blk_mq_free_tag_set(&ace->tag_set);
+		goto err_blk_initq;
+	}
+	ace->queue->queuedata = ace;
+
 	blk_queue_logical_block_size(ace->queue, 512);
 	blk_queue_bounce_limit(ace->queue, BLK_BOUNCE_HIGH);
 
@@ -1065,6 +1103,7 @@ static int ace_setup(struct ace_device *ace)
 err_read:
 	put_disk(ace->gd);
 err_alloc_disk:
+	blk_mq_free_tag_set(&ace->tag_set);
 	blk_cleanup_queue(ace->queue);
 err_blk_initq:
 	iounmap(ace->baseaddr);
@@ -1081,8 +1120,10 @@ static void ace_teardown(struct ace_device *ace)
 		put_disk(ace->gd);
 	}
 
-	if (ace->queue)
+	if (ace->queue) {
+		blk_mq_free_tag_set(&ace->tag_set);
 		blk_cleanup_queue(ace->queue);
+	}
 
 	tasklet_kill(&ace->fsm_tasklet);
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 16/17] mtd_blkdevs: convert to blk-mq
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (14 preceding siblings ...)
  2018-10-11 16:59 ` [PATCH 15/17] xsysace: convert " Jens Axboe
@ 2018-10-11 16:59 ` Jens Axboe
  2018-10-11 21:03   ` Richard Weinberger
  2018-10-11 16:59 ` [PATCH 17/17] null_blk: remove legacy IO path Jens Axboe
  16 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:59 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe, David Woodhouse, linux-mtd

Straight forward conversion, using an internal list to enable the
driver to pull requests at will.

Dynamically allocate the tag set to avoid having to pull in the
block headers for blktrans.h, since various mtd drivers use
block conflicting names for defines and functions.

Cc: David Woodhouse <dwmw2@infradead.org>
Cc: linux-mtd@lists.infradead.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/mtd/mtd_blkdevs.c    | 109 +++++++++++++++++++++++------------
 include/linux/mtd/blktrans.h |   5 +-
 2 files changed, 74 insertions(+), 40 deletions(-)

diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 29c0bfd74e8a..6a94cffbca20 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -27,6 +27,7 @@
 #include <linux/mtd/blktrans.h>
 #include <linux/mtd/mtd.h>
 #include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/blkpg.h>
 #include <linux/spinlock.h>
 #include <linux/hdreg.h>
@@ -44,6 +45,8 @@ static void blktrans_dev_release(struct kref *kref)
 		container_of(kref, struct mtd_blktrans_dev, ref);
 
 	dev->disk->private_data = NULL;
+	blk_mq_free_tag_set(dev->tag_set);
+	kfree(dev->tag_set);
 	blk_cleanup_queue(dev->rq);
 	put_disk(dev->disk);
 	list_del(&dev->list);
@@ -134,28 +137,37 @@ int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev)
 }
 EXPORT_SYMBOL_GPL(mtd_blktrans_cease_background);
 
-static void mtd_blktrans_work(struct work_struct *work)
+static struct request *mtd_next_request(struct mtd_blktrans_dev *dev)
+{
+	struct request *rq;
+
+	rq = list_first_entry_or_null(&dev->rq_list, struct request, queuelist);
+	if (rq) {
+		list_del_init(&rq->queuelist);
+		blk_mq_start_request(rq);
+		return rq;
+	}
+
+	return NULL;
+}
+
+static void mtd_blktrans_work(struct mtd_blktrans_dev *dev)
 {
-	struct mtd_blktrans_dev *dev =
-		container_of(work, struct mtd_blktrans_dev, work);
 	struct mtd_blktrans_ops *tr = dev->tr;
-	struct request_queue *rq = dev->rq;
 	struct request *req = NULL;
 	int background_done = 0;
 
-	spin_lock_irq(rq->queue_lock);
-
 	while (1) {
 		blk_status_t res;
 
 		dev->bg_stop = false;
-		if (!req && !(req = blk_fetch_request(rq))) {
+		if (!req && !(req = mtd_next_request(dev))) {
 			if (tr->background && !background_done) {
-				spin_unlock_irq(rq->queue_lock);
+				spin_unlock_irq(&dev->queue_lock);
 				mutex_lock(&dev->lock);
 				tr->background(dev);
 				mutex_unlock(&dev->lock);
-				spin_lock_irq(rq->queue_lock);
+				spin_lock_irq(&dev->queue_lock);
 				/*
 				 * Do background processing just once per idle
 				 * period.
@@ -166,35 +178,39 @@ static void mtd_blktrans_work(struct work_struct *work)
 			break;
 		}
 
-		spin_unlock_irq(rq->queue_lock);
+		spin_unlock_irq(&dev->queue_lock);
 
 		mutex_lock(&dev->lock);
 		res = do_blktrans_request(dev->tr, dev, req);
 		mutex_unlock(&dev->lock);
 
-		spin_lock_irq(rq->queue_lock);
-
-		if (!__blk_end_request_cur(req, res))
+		if (!blk_update_request(req, res, blk_rq_cur_bytes(req))) {
 			req = NULL;
+			__blk_mq_end_request(req, res);
+		}
 
 		background_done = 0;
+		spin_lock_irq(&dev->queue_lock);
 	}
-
-	spin_unlock_irq(rq->queue_lock);
 }
 
-static void mtd_blktrans_request(struct request_queue *rq)
+static blk_status_t mtd_queue_rq(struct blk_mq_hw_ctx *hctx,
+				 const struct blk_mq_queue_data *bd)
 {
 	struct mtd_blktrans_dev *dev;
-	struct request *req = NULL;
 
-	dev = rq->queuedata;
+	dev = hctx->queue->queuedata;
+	if (!dev) {
+		blk_mq_start_request(bd->rq);
+		return BLK_STS_IOERR;
+	}
+
+	spin_lock_irq(&dev->queue_lock);
+	list_add_tail(&bd->rq->queuelist, &dev->rq_list);
+	mtd_blktrans_work(dev);
+	spin_unlock_irq(&dev->queue_lock);
 
-	if (!dev)
-		while ((req = blk_fetch_request(rq)) != NULL)
-			__blk_end_request_all(req, BLK_STS_IOERR);
-	else
-		queue_work(dev->wq, &dev->work);
+	return BLK_STS_OK;
 }
 
 static int blktrans_open(struct block_device *bdev, fmode_t mode)
@@ -329,9 +345,14 @@ static const struct block_device_operations mtd_block_ops = {
 	.getgeo		= blktrans_getgeo,
 };
 
+static const struct blk_mq_ops mtd_mq_ops = {
+	.queue_rq	= mtd_queue_rq,
+};
+
 int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 {
 	struct mtd_blktrans_ops *tr = new->tr;
+	struct blk_mq_tag_set *set;
 	struct mtd_blktrans_dev *d;
 	int last_devnum = -1;
 	struct gendisk *gd;
@@ -416,11 +437,28 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 
 	/* Create the request queue */
 	spin_lock_init(&new->queue_lock);
-	new->rq = blk_init_queue(mtd_blktrans_request, &new->queue_lock);
+	INIT_LIST_HEAD(&new->rq_list);
 
-	if (!new->rq)
+	new->tag_set = kzalloc(sizeof(*new->tag_set), GFP_KERNEL);
+	if (!new->tag_set)
 		goto error3;
 
+	set = new->tag_set;
+	set->ops = &mtd_mq_ops;
+	set->nr_hw_queues = 1;
+	set->queue_depth = 2;
+	set->numa_node = NUMA_NO_NODE;
+	set->flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING;
+	ret = blk_mq_alloc_tag_set(set);
+	if (ret)
+		goto error4;
+
+	new->rq = blk_mq_init_queue(set);
+	if (!new->rq) {
+		blk_mq_free_tag_set(new->tag_set);
+		goto error5;
+	}
+
 	if (tr->flush)
 		blk_queue_write_cache(new->rq, true, false);
 
@@ -437,13 +475,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 
 	gd->queue = new->rq;
 
-	/* Create processing workqueue */
-	new->wq = alloc_workqueue("%s%d", 0, 0,
-				  tr->name, new->mtd->index);
-	if (!new->wq)
-		goto error4;
-	INIT_WORK(&new->work, mtd_blktrans_work);
-
 	if (new->readonly)
 		set_disk_ro(gd, 1);
 
@@ -455,8 +486,10 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 		WARN_ON(ret);
 	}
 	return 0;
+error5:
+	blk_mq_free_tag_set(new->tag_set);
 error4:
-	blk_cleanup_queue(new->rq);
+	kfree(new->tag_set);
 error3:
 	put_disk(new->disk);
 error2:
@@ -481,15 +514,17 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
 	/* Stop new requests to arrive */
 	del_gendisk(old->disk);
 
-	/* Stop workqueue. This will perform any pending request. */
-	destroy_workqueue(old->wq);
-
 	/* Kill current requests */
 	spin_lock_irqsave(&old->queue_lock, flags);
 	old->rq->queuedata = NULL;
-	blk_start_queue(old->rq);
 	spin_unlock_irqrestore(&old->queue_lock, flags);
 
+	/* freeze+quiesce queue to ensure all requests are flushed */
+	blk_mq_freeze_queue(old->rq);
+	blk_mq_quiesce_queue(old->rq);
+	blk_mq_unquiesce_queue(old->rq);
+	blk_mq_unfreeze_queue(old->rq);
+
 	/* If the device is currently open, tell trans driver to close it,
 		then put mtd device, and don't touch it again */
 	mutex_lock(&old->lock);
diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
index e93837f647de..1d3ade69d39a 100644
--- a/include/linux/mtd/blktrans.h
+++ b/include/linux/mtd/blktrans.h
@@ -23,7 +23,6 @@
 #include <linux/mutex.h>
 #include <linux/kref.h>
 #include <linux/sysfs.h>
-#include <linux/workqueue.h>
 
 struct hd_geometry;
 struct mtd_info;
@@ -44,9 +43,9 @@ struct mtd_blktrans_dev {
 	struct kref ref;
 	struct gendisk *disk;
 	struct attribute_group *disk_attributes;
-	struct workqueue_struct *wq;
-	struct work_struct work;
 	struct request_queue *rq;
+	struct list_head rq_list;
+	struct blk_mq_tag_set *tag_set;
 	spinlock_t queue_lock;
 	void *priv;
 	fmode_t file_mode;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 17/17] null_blk: remove legacy IO path
  2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
                   ` (15 preceding siblings ...)
  2018-10-11 16:59 ` [PATCH 16/17] mtd_blkdevs: " Jens Axboe
@ 2018-10-11 16:59 ` Jens Axboe
  2018-10-12  6:56   ` Dongli Zhang
  2018-10-12 17:24   ` Sébastien Boisvert
  16 siblings, 2 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 16:59 UTC (permalink / raw)
  To: linux-block; +Cc: Jens Axboe

We're planning on removing this code completely, kill the old
path.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 drivers/block/null_blk_main.c | 96 +++--------------------------------
 1 file changed, 6 insertions(+), 90 deletions(-)

diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c
index 093b614d6524..8142cc8ff952 100644
--- a/drivers/block/null_blk_main.c
+++ b/drivers/block/null_blk_main.c
@@ -616,10 +616,6 @@ static void end_cmd(struct nullb_cmd *cmd)
 	case NULL_Q_MQ:
 		blk_mq_end_request(cmd->rq, cmd->error);
 		return;
-	case NULL_Q_RQ:
-		INIT_LIST_HEAD(&cmd->rq->queuelist);
-		blk_end_request_all(cmd->rq, cmd->error);
-		break;
 	case NULL_Q_BIO:
 		cmd->bio->bi_status = cmd->error;
 		bio_endio(cmd->bio);
@@ -627,15 +623,6 @@ static void end_cmd(struct nullb_cmd *cmd)
 	}
 
 	free_cmd(cmd);
-
-	/* Restart queue if needed, as we are freeing a tag */
-	if (queue_mode == NULL_Q_RQ && blk_queue_stopped(q)) {
-		unsigned long flags;
-
-		spin_lock_irqsave(q->queue_lock, flags);
-		blk_start_queue_async(q);
-		spin_unlock_irqrestore(q->queue_lock, flags);
-	}
 }
 
 static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer)
@@ -1197,17 +1184,8 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd)
 			/* race with timer */
 			if (atomic_long_read(&nullb->cur_bytes) > 0)
 				null_restart_queue_async(nullb);
-			if (dev->queue_mode == NULL_Q_RQ) {
-				struct request_queue *q = nullb->q;
-
-				spin_lock_irq(q->queue_lock);
-				rq->rq_flags |= RQF_DONTPREP;
-				blk_requeue_request(q, rq);
-				spin_unlock_irq(q->queue_lock);
-				return BLK_STS_OK;
-			} else
-				/* requeue request */
-				return BLK_STS_DEV_RESOURCE;
+			/* requeue request */
+			return BLK_STS_DEV_RESOURCE;
 		}
 	}
 
@@ -1278,9 +1256,6 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd)
 		case NULL_Q_MQ:
 			blk_mq_complete_request(cmd->rq);
 			break;
-		case NULL_Q_RQ:
-			blk_complete_request(cmd->rq);
-			break;
 		case NULL_Q_BIO:
 			/*
 			 * XXX: no proper submitting cpu information available.
@@ -1349,30 +1324,6 @@ static blk_qc_t null_queue_bio(struct request_queue *q, struct bio *bio)
 	return BLK_QC_T_NONE;
 }
 
-static enum blk_eh_timer_return null_rq_timed_out_fn(struct request *rq)
-{
-	pr_info("null: rq %p timed out\n", rq);
-	__blk_complete_request(rq);
-	return BLK_EH_DONE;
-}
-
-static int null_rq_prep_fn(struct request_queue *q, struct request *req)
-{
-	struct nullb *nullb = q->queuedata;
-	struct nullb_queue *nq = nullb_to_queue(nullb);
-	struct nullb_cmd *cmd;
-
-	cmd = alloc_cmd(nq, 0);
-	if (cmd) {
-		cmd->rq = req;
-		req->special = cmd;
-		return BLKPREP_OK;
-	}
-	blk_stop_queue(q);
-
-	return BLKPREP_DEFER;
-}
-
 static bool should_timeout_request(struct request *rq)
 {
 #ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION
@@ -1391,27 +1342,6 @@ static bool should_requeue_request(struct request *rq)
 	return false;
 }
 
-static void null_request_fn(struct request_queue *q)
-{
-	struct request *rq;
-
-	while ((rq = blk_fetch_request(q)) != NULL) {
-		struct nullb_cmd *cmd = rq->special;
-
-		/* just ignore the request */
-		if (should_timeout_request(rq))
-			continue;
-		if (should_requeue_request(rq)) {
-			blk_requeue_request(q, rq);
-			continue;
-		}
-
-		spin_unlock_irq(q->queue_lock);
-		null_handle_cmd(cmd);
-		spin_lock_irq(q->queue_lock);
-	}
-}
-
 static enum blk_eh_timer_return null_timeout_rq(struct request *rq, bool res)
 {
 	pr_info("null: rq %p timed out\n", rq);
@@ -1766,24 +1696,6 @@ static int null_add_dev(struct nullb_device *dev)
 		rv = init_driver_queues(nullb);
 		if (rv)
 			goto out_cleanup_blk_queue;
-	} else {
-		nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock,
-						dev->home_node);
-		if (!nullb->q) {
-			rv = -ENOMEM;
-			goto out_cleanup_queues;
-		}
-
-		if (!null_setup_fault())
-			goto out_cleanup_blk_queue;
-
-		blk_queue_prep_rq(nullb->q, null_rq_prep_fn);
-		blk_queue_softirq_done(nullb->q, null_softirq_done_fn);
-		blk_queue_rq_timed_out(nullb->q, null_rq_timed_out_fn);
-		nullb->q->rq_timeout = 5 * HZ;
-		rv = init_driver_queues(nullb);
-		if (rv)
-			goto out_cleanup_blk_queue;
 	}
 
 	if (dev->mbps) {
@@ -1865,6 +1777,10 @@ static int __init null_init(void)
 		return -EINVAL;
 	}
 
+	if (g_queue_mode == NULL_Q_RQ) {
+		pr_err("null_blk: legacy IO path no longer available\n");
+		return -EINVAL;
+	}
 	if (g_queue_mode == NULL_Q_MQ && g_use_per_node_hctx) {
 		if (g_submit_queues != nr_online_nodes) {
 			pr_warn("null_blk: submit_queues param is set to %u.\n",
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH 16/17] mtd_blkdevs: convert to blk-mq
  2018-10-11 16:59 ` [PATCH 16/17] mtd_blkdevs: " Jens Axboe
@ 2018-10-11 21:03   ` Richard Weinberger
  2018-10-11 21:14     ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Weinberger @ 2018-10-11 21:03 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-block, linux-mtd @ lists . infradead . org, David Woodhouse

Jens,

On Thu, Oct 11, 2018 at 7:00 PM Jens Axboe <axboe@kernel.dk> wrote:
>
> Straight forward conversion, using an internal list to enable the
> driver to pull requests at will.
>
> Dynamically allocate the tag set to avoid having to pull in the
> block headers for blktrans.h, since various mtd drivers use
> block conflicting names for defines and functions.

This explodes on my test system. :-/

[    2.236594] BUG: unable to handle kernel NULL pointer dereference
at 000000000000001a
[    2.237621] PGD 0 P4D 0
[    2.237968] Oops: 0000 [#1] SMP PTI
[    2.238425] CPU: 3 PID: 1110 Comm: kworker/3:1H Not tainted 4.19.0-rc7+ #143
[    2.239331] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
BIOS 1.0.0-prebuilt.qemu-project.org 04/01/2014
[    2.240893] Workqueue: kblockd blk_mq_run_work_fn
[    2.241533] RIP: 0010:__blk_mq_end_request+0xe/0xb0
[    2.242212] Code: 44 21 c2 48 0f a3 10 73 02 f3 c3 f0 48 0f ab 10
c3 90 66 2e 0f 1f 84 00 00 00 00 00 41 54 55 89 f5 53 48 89 fb e8 f2
80 d6 ff <f6> 43 1a 02 49 89 c4 75 4f 4c 89 e6 48 89 df e8 4e 69 ff ff
48 83
[    2.244798] RSP: 0018:ffffac65c2c43d20 EFLAGS: 00010216
[    2.245469] RAX: 000000007caad848 RBX: 0000000000000000 RCX: 0000000000000017
[    2.246382] RDX: 0000031c57000000 RSI: 001778d956000000 RDI: ffffffffa4cc70c0
[    2.247296] RBP: 0000000000000000 R08: 00000000d2a4b8d8 R09: ffffffffa355ead3
[    2.248208] R10: fffff1a2c5e46740 R11: ffffffffff76acba R12: 0000000000000000
[    2.249123] R13: ffffa117793ff720 R14: ffffffffa46c7120 R15: 000000000007ff88
[    2.259551] FS:  0000000000000000(0000) GS:ffffa1177ab80000(0000)
knlGS:0000000000000000
[    2.259552] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    2.259553] CR2: 000000000000001a CR3: 0000000177d44000 CR4: 00000000000006e0
[    2.259560] Call Trace:
[    2.259630]  mtd_queue_rq+0x1fa/0x400
[    2.259661]  blk_mq_dispatch_rq_list+0x8b/0x510
[    2.259672]  ? elv_rqhash_add+0x1/0x60
[    2.259680]  ? deadline_remove_request+0x44/0xa0
[    2.259684]  blk_mq_do_dispatch_sched+0x5a/0xf0
[    2.259690]  blk_mq_sched_dispatch_requests+0xf0/0x160
[    2.259697]  __blk_mq_run_hw_queue+0x49/0xc0
[    2.259705]  process_one_work+0x1e9/0x3d0
[    2.259726]  worker_thread+0x28/0x3d0
[    2.259728]  ? process_one_work+0x3d0/0x3d0
[    2.259732]  kthread+0x10e/0x130
[    2.259740]  ? kthread_create_worker_on_cpu+0x70/0x70
[    2.259750]  ret_from_fork+0x35/0x40
[    2.259763] Modules linked in:
[    2.259767] CR2: 000000000000001a
[    2.259772] ---[ end trace b08076f7e1ed1f91 ]---
[    2.259774] RIP: 0010:__blk_mq_end_request+0xe/0xb0
[    2.259776] Code: 44 21 c2 48 0f a3 10 73 02 f3 c3 f0 48 0f ab 10
c3 90 66 2e 0f 1f 84 00 00 00 00 00 41 54 55 89 f5 53 48 89 fb e8 f2
80 d6 ff <f6> 43 1a 02 49 89 c4 75 4f 4c 89 e6 48 89 df e8 4e 69 ff ff
48 83
[    2.259777] RSP: 0018:ffffac65c2c43d20 EFLAGS: 00010216
[    2.259778] RAX: 000000007caad848 RBX: 0000000000000000 RCX: 0000000000000017
[    2.259779] RDX: 0000031c57000000 RSI: 001778d956000000 RDI: ffffffffa4cc70c0
[    2.259780] RBP: 0000000000000000 R08: 00000000d2a4b8d8 R09: ffffffffa355ead3
[    2.259780] R10: fffff1a2c5e46740 R11: ffffffffff76acba R12: 0000000000000000
[    2.259781] R13: ffffa117793ff720 R14: ffffffffa46c7120 R15: 000000000007ff88
[    2.259782] FS:  0000000000000000(0000) GS:ffffa1177ab80000(0000)
knlGS:0000000000000000
[    2.259783] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    2.259784] CR2: 000000000000001a CR3: 0000000177d44000 CR4: 00000000000006e0
[    2.259786] Kernel panic - not syncing: Fatal exception
[    2.261997] Kernel Offset: 0x22200000 from 0xffffffff81000000
(relocation range: 0xffffffff80000000-0xffffffffbfffffff)

-- 
Thanks,
//richard

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 16/17] mtd_blkdevs: convert to blk-mq
  2018-10-11 21:03   ` Richard Weinberger
@ 2018-10-11 21:14     ` Jens Axboe
  2018-10-11 21:18       ` Richard Weinberger
  0 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 21:14 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: linux-block, linux-mtd @ lists . infradead . org, David Woodhouse

On 10/11/18 3:03 PM, Richard Weinberger wrote:
> Jens,
> 
> On Thu, Oct 11, 2018 at 7:00 PM Jens Axboe <axboe@kernel.dk> wrote:
>>
>> Straight forward conversion, using an internal list to enable the
>> driver to pull requests at will.
>>
>> Dynamically allocate the tag set to avoid having to pull in the
>> block headers for blktrans.h, since various mtd drivers use
>> block conflicting names for defines and functions.
> 
> This explodes on my test system. :-/

I think I see it, that was pretty stupid... Can you try with this one
on top as well?

diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index c26d692781af..e8f8fddce063 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -187,8 +187,8 @@ static void mtd_blktrans_work(struct mtd_blktrans_dev *dev)
 		mutex_unlock(&dev->lock);
 
 		if (!blk_update_request(req, res, blk_rq_cur_bytes(req))) {
-			req = NULL;
 			__blk_mq_end_request(req, res);
+			req = NULL;
 		}
 
 		background_done = 0;

-- 
Jens Axboe

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH 16/17] mtd_blkdevs: convert to blk-mq
  2018-10-11 21:14     ` Jens Axboe
@ 2018-10-11 21:18       ` Richard Weinberger
  2018-10-11 21:21         ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Richard Weinberger @ 2018-10-11 21:18 UTC (permalink / raw)
  To: Jens Axboe, linux-block; +Cc: linux-mtd, David Woodhouse

Jens,

Am Donnerstag, 11. Oktober 2018, 23:14:07 CEST schrieb Jens Axboe:
> On 10/11/18 3:03 PM, Richard Weinberger wrote:
> > Jens,
> > 
> > On Thu, Oct 11, 2018 at 7:00 PM Jens Axboe <axboe@kernel.dk> wrote:
> >>
> >> Straight forward conversion, using an internal list to enable the
> >> driver to pull requests at will.
> >>
> >> Dynamically allocate the tag set to avoid having to pull in the
> >> block headers for blktrans.h, since various mtd drivers use
> >> block conflicting names for defines and functions.
> > 
> > This explodes on my test system. :-/
> 
> I think I see it, that was pretty stupid... Can you try with this one
> on top as well?
> 
> diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
> index c26d692781af..e8f8fddce063 100644
> --- a/drivers/mtd/mtd_blkdevs.c
> +++ b/drivers/mtd/mtd_blkdevs.c
> @@ -187,8 +187,8 @@ static void mtd_blktrans_work(struct mtd_blktrans_dev *dev)
>  		mutex_unlock(&dev->lock);
>  
>  		if (!blk_update_request(req, res, blk_rq_cur_bytes(req))) {
> -			req = NULL;
>  			__blk_mq_end_request(req, res);
> +			req = NULL;

Hehe. :-)
With this fix applied it works and passes my trivial test.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 16/17] mtd_blkdevs: convert to blk-mq
  2018-10-11 21:18       ` Richard Weinberger
@ 2018-10-11 21:21         ` Jens Axboe
  2018-10-11 21:31           ` Richard Weinberger
  0 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-11 21:21 UTC (permalink / raw)
  To: Richard Weinberger, linux-block; +Cc: linux-mtd, David Woodhouse

On 10/11/18 3:18 PM, Richard Weinberger wrote:
> Jens,
> 
> Am Donnerstag, 11. Oktober 2018, 23:14:07 CEST schrieb Jens Axboe:
>> On 10/11/18 3:03 PM, Richard Weinberger wrote:
>>> Jens,
>>>
>>> On Thu, Oct 11, 2018 at 7:00 PM Jens Axboe <axboe@kernel.dk> wrote:
>>>>
>>>> Straight forward conversion, using an internal list to enable the
>>>> driver to pull requests at will.
>>>>
>>>> Dynamically allocate the tag set to avoid having to pull in the
>>>> block headers for blktrans.h, since various mtd drivers use
>>>> block conflicting names for defines and functions.
>>>
>>> This explodes on my test system. :-/
>>
>> I think I see it, that was pretty stupid... Can you try with this one
>> on top as well?
>>
>> diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
>> index c26d692781af..e8f8fddce063 100644
>> --- a/drivers/mtd/mtd_blkdevs.c
>> +++ b/drivers/mtd/mtd_blkdevs.c
>> @@ -187,8 +187,8 @@ static void mtd_blktrans_work(struct mtd_blktrans_dev *dev)
>>  		mutex_unlock(&dev->lock);
>>  
>>  		if (!blk_update_request(req, res, blk_rq_cur_bytes(req))) {
>> -			req = NULL;
>>  			__blk_mq_end_request(req, res);
>> +			req = NULL;
> 
> Hehe. :-)
> With this fix applied it works and passes my trivial test.

Great, thanks for testing! Can I add your tested-by to it?

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 16/17] mtd_blkdevs: convert to blk-mq
  2018-10-11 21:21         ` Jens Axboe
@ 2018-10-11 21:31           ` Richard Weinberger
  0 siblings, 0 replies; 56+ messages in thread
From: Richard Weinberger @ 2018-10-11 21:31 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block, linux-mtd, David Woodhouse

Am Donnerstag, 11. Oktober 2018, 23:21:56 CEST schrieb Jens Axboe:
> >>  		if (!blk_update_request(req, res, blk_rq_cur_bytes(req))) {
> >> -			req = NULL;
> >>  			__blk_mq_end_request(req, res);
> >> +			req = NULL;
> > 
> > Hehe. :-)
> > With this fix applied it works and passes my trivial test.
> 
> Great, thanks for testing! Can I add your tested-by to it?

Sure.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 15/17] xsysace: convert to blk-mq
  2018-10-11 16:59 ` [PATCH 15/17] xsysace: convert " Jens Axboe
@ 2018-10-12  5:46   ` Michal Simek
  0 siblings, 0 replies; 56+ messages in thread
From: Michal Simek @ 2018-10-12  5:46 UTC (permalink / raw)
  To: Jens Axboe, linux-block; +Cc: Michal Simek

On 11.10.2018 18:59, Jens Axboe wrote:
> Straight forward conversion, using an internal list to enable the
> driver to pull requests at will.
> 
> Cc: Michal Simek <michal.simek@xilinx.com>
> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> ---
>  drivers/block/xsysace.c | 91 ++++++++++++++++++++++++++++++-----------
>  1 file changed, 66 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
> index c24589414c75..ddaa362ffe82 100644
> --- a/drivers/block/xsysace.c
> +++ b/drivers/block/xsysace.c
> @@ -88,7 +88,7 @@
>  #include <linux/kernel.h>
>  #include <linux/delay.h>
>  #include <linux/slab.h>
> -#include <linux/blkdev.h>
> +#include <linux/blk-mq.h>
>  #include <linux/mutex.h>
>  #include <linux/ata.h>
>  #include <linux/hdreg.h>
> @@ -209,6 +209,8 @@ struct ace_device {
>  	struct device *dev;
>  	struct request_queue *queue;
>  	struct gendisk *gd;
> +	struct blk_mq_tag_set tag_set;
> +	struct list_head rq_list;
>  
>  	/* Inserted CF card parameters */
>  	u16 cf_id[ATA_ID_WORDS];
> @@ -462,18 +464,26 @@ static inline void ace_fsm_yieldirq(struct ace_device *ace)
>  	ace->fsm_continue_flag = 0;
>  }
>  
> +static bool ace_has_next_request(struct request_queue *q)
> +{
> +	struct ace_device *ace = q->queuedata;
> +
> +	return !list_empty(&ace->rq_list);
> +}
> +
>  /* Get the next read/write request; ending requests that we don't handle */
>  static struct request *ace_get_next_request(struct request_queue *q)
>  {
> -	struct request *req;
> +	struct ace_device *ace = q->queuedata;
> +	struct request *rq;
>  
> -	while ((req = blk_peek_request(q)) != NULL) {
> -		if (!blk_rq_is_passthrough(req))
> -			break;
> -		blk_start_request(req);
> -		__blk_end_request_all(req, BLK_STS_IOERR);
> +	rq = list_first_entry_or_null(&ace->rq_list, struct request, queuelist);
> +	if (rq) {
> +		list_del_init(&rq->queuelist);
> +		blk_mq_start_request(rq);
>  	}
> -	return req;
> +
> +	return NULL;
>  }
>  
>  static void ace_fsm_dostate(struct ace_device *ace)
> @@ -499,11 +509,11 @@ static void ace_fsm_dostate(struct ace_device *ace)
>  
>  		/* Drop all in-flight and pending requests */
>  		if (ace->req) {
> -			__blk_end_request_all(ace->req, BLK_STS_IOERR);
> +			blk_mq_end_request(ace->req, BLK_STS_IOERR);
>  			ace->req = NULL;
>  		}
> -		while ((req = blk_fetch_request(ace->queue)) != NULL)
> -			__blk_end_request_all(req, BLK_STS_IOERR);
> +		while ((req = ace_get_next_request(ace->queue)) != NULL)
> +			blk_mq_end_request(req, BLK_STS_IOERR);
>  
>  		/* Drop back to IDLE state and notify waiters */
>  		ace->fsm_state = ACE_FSM_STATE_IDLE;
> @@ -517,7 +527,7 @@ static void ace_fsm_dostate(struct ace_device *ace)
>  	switch (ace->fsm_state) {
>  	case ACE_FSM_STATE_IDLE:
>  		/* See if there is anything to do */
> -		if (ace->id_req_count || ace_get_next_request(ace->queue)) {
> +		if (ace->id_req_count || ace_has_next_request(ace->queue)) {
>  			ace->fsm_iter_num++;
>  			ace->fsm_state = ACE_FSM_STATE_REQ_LOCK;
>  			mod_timer(&ace->stall_timer, jiffies + HZ);
> @@ -651,7 +661,6 @@ static void ace_fsm_dostate(struct ace_device *ace)
>  			ace->fsm_state = ACE_FSM_STATE_IDLE;
>  			break;
>  		}
> -		blk_start_request(req);
>  
>  		/* Okay, it's a data request, set it up for transfer */
>  		dev_dbg(ace->dev,
> @@ -728,7 +737,8 @@ static void ace_fsm_dostate(struct ace_device *ace)
>  		}
>  
>  		/* bio finished; is there another one? */
> -		if (__blk_end_request_cur(ace->req, BLK_STS_OK)) {
> +		if (blk_update_request(ace->req, BLK_STS_OK,
> +		    blk_rq_cur_bytes(ace->req))) {
>  			/* dev_dbg(ace->dev, "next block; h=%u c=%u\n",
>  			 *      blk_rq_sectors(ace->req),
>  			 *      blk_rq_cur_sectors(ace->req));
> @@ -854,17 +864,23 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id)
>  /* ---------------------------------------------------------------------
>   * Block ops
>   */
> -static void ace_request(struct request_queue * q)
> +static blk_status_t ace_queue_rq(struct blk_mq_hw_ctx *hctx,
> +				 const struct blk_mq_queue_data *bd)
>  {
> -	struct request *req;
> -	struct ace_device *ace;
> +	struct ace_device *ace = hctx->queue->queuedata;
> +	struct request *req = bd->rq;
>  
> -	req = ace_get_next_request(q);
> -
> -	if (req) {
> -		ace = req->rq_disk->private_data;
> -		tasklet_schedule(&ace->fsm_tasklet);
> +	if (blk_rq_is_passthrough(req)) {
> +		blk_mq_start_request(req);
> +		return BLK_STS_IOERR;
>  	}
> +
> +	spin_lock_irq(&ace->lock);
> +	list_add_tail(&req->queuelist, &ace->rq_list);
> +	spin_unlock_irq(&ace->lock);
> +
> +	tasklet_schedule(&ace->fsm_tasklet);
> +	return BLK_STS_OK;
>  }
>  
>  static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing)
> @@ -957,11 +973,16 @@ static const struct block_device_operations ace_fops = {
>  	.getgeo = ace_getgeo,
>  };
>  
> +static const struct blk_mq_ops ace_mq_ops = {
> +	.queue_rq	= ace_queue_rq,
> +};
> +
>  /* --------------------------------------------------------------------
>   * SystemACE device setup/teardown code
>   */
>  static int ace_setup(struct ace_device *ace)
>  {
> +	struct blk_mq_tag_set *set;
>  	u16 version;
>  	u16 val;
>  	int rc;
> @@ -972,6 +993,7 @@ static int ace_setup(struct ace_device *ace)
>  
>  	spin_lock_init(&ace->lock);
>  	init_completion(&ace->id_completion);
> +	INIT_LIST_HEAD(&ace->rq_list);
>  
>  	/*
>  	 * Map the device
> @@ -989,9 +1011,25 @@ static int ace_setup(struct ace_device *ace)
>  	/*
>  	 * Initialize the request queue
>  	 */
> -	ace->queue = blk_init_queue(ace_request, &ace->lock);
> -	if (ace->queue == NULL)
> +	set = &ace->tag_set;
> +	set->ops = &ace_mq_ops;
> +	set->nr_hw_queues = 1;
> +	set->queue_depth = 2;
> +	set->numa_node = NUMA_NO_NODE;
> +	set->flags = BLK_MQ_F_SHOULD_MERGE;
> +	rc = blk_mq_alloc_tag_set(set);
> +	if (rc)
>  		goto err_blk_initq;
> +
> +	ace->queue = blk_mq_init_queue(set);
> +	if (IS_ERR(ace->queue)) {
> +		rc = PTR_ERR(ace->queue);
> +		ace->queue = NULL;
> +		blk_mq_free_tag_set(&ace->tag_set);
> +		goto err_blk_initq;
> +	}
> +	ace->queue->queuedata = ace;
> +
>  	blk_queue_logical_block_size(ace->queue, 512);
>  	blk_queue_bounce_limit(ace->queue, BLK_BOUNCE_HIGH);
>  
> @@ -1065,6 +1103,7 @@ static int ace_setup(struct ace_device *ace)
>  err_read:
>  	put_disk(ace->gd);
>  err_alloc_disk:
> +	blk_mq_free_tag_set(&ace->tag_set);
>  	blk_cleanup_queue(ace->queue);
>  err_blk_initq:
>  	iounmap(ace->baseaddr);
> @@ -1081,8 +1120,10 @@ static void ace_teardown(struct ace_device *ace)
>  		put_disk(ace->gd);
>  	}
>  
> -	if (ace->queue)
> +	if (ace->queue) {
> +		blk_mq_free_tag_set(&ace->tag_set);
>  		blk_cleanup_queue(ace->queue);
> +	}
>  
>  	tasklet_kill(&ace->fsm_tasklet);
>  
> 

None is testing this driver anymore that's why feel free to do this
change and if there is any issue this patch can be reverted back.

That's why
Acked-by: Michal Simek <michal.simek@xilinx.com>

Thanks,
Michal

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 17/17] null_blk: remove legacy IO path
  2018-10-11 16:59 ` [PATCH 17/17] null_blk: remove legacy IO path Jens Axboe
@ 2018-10-12  6:56   ` Dongli Zhang
  2018-10-12  8:51     ` Johannes Thumshirn
  2018-10-12 17:24   ` Sébastien Boisvert
  1 sibling, 1 reply; 56+ messages in thread
From: Dongli Zhang @ 2018-10-12  6:56 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block

Hi Jens,

Will the legacy path be fully deprecated?

In addition to performance measurement, null_blk is a very good tutorial for
beginners to understand how to implement a legacy path based block driver from
scratch. Unless legacy path is not used any longer, why not keep it in the code
as a tutorial?

Dongli Zhang

On 10/12/2018 12:59 AM, Jens Axboe wrote:
> We're planning on removing this code completely, kill the old
> path.
> 
> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> ---
>  drivers/block/null_blk_main.c | 96 +++--------------------------------
>  1 file changed, 6 insertions(+), 90 deletions(-)
> 
> diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c
> index 093b614d6524..8142cc8ff952 100644
> --- a/drivers/block/null_blk_main.c
> +++ b/drivers/block/null_blk_main.c
> @@ -616,10 +616,6 @@ static void end_cmd(struct nullb_cmd *cmd)
>  	case NULL_Q_MQ:
>  		blk_mq_end_request(cmd->rq, cmd->error);
>  		return;
> -	case NULL_Q_RQ:
> -		INIT_LIST_HEAD(&cmd->rq->queuelist);
> -		blk_end_request_all(cmd->rq, cmd->error);
> -		break;
>  	case NULL_Q_BIO:
>  		cmd->bio->bi_status = cmd->error;
>  		bio_endio(cmd->bio);
> @@ -627,15 +623,6 @@ static void end_cmd(struct nullb_cmd *cmd)
>  	}
>  
>  	free_cmd(cmd);
> -
> -	/* Restart queue if needed, as we are freeing a tag */
> -	if (queue_mode == NULL_Q_RQ && blk_queue_stopped(q)) {
> -		unsigned long flags;
> -
> -		spin_lock_irqsave(q->queue_lock, flags);
> -		blk_start_queue_async(q);
> -		spin_unlock_irqrestore(q->queue_lock, flags);
> -	}
>  }
>  
>  static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer)
> @@ -1197,17 +1184,8 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd)
>  			/* race with timer */
>  			if (atomic_long_read(&nullb->cur_bytes) > 0)
>  				null_restart_queue_async(nullb);
> -			if (dev->queue_mode == NULL_Q_RQ) {
> -				struct request_queue *q = nullb->q;
> -
> -				spin_lock_irq(q->queue_lock);
> -				rq->rq_flags |= RQF_DONTPREP;
> -				blk_requeue_request(q, rq);
> -				spin_unlock_irq(q->queue_lock);
> -				return BLK_STS_OK;
> -			} else
> -				/* requeue request */
> -				return BLK_STS_DEV_RESOURCE;
> +			/* requeue request */
> +			return BLK_STS_DEV_RESOURCE;
>  		}
>  	}
>  
> @@ -1278,9 +1256,6 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd)
>  		case NULL_Q_MQ:
>  			blk_mq_complete_request(cmd->rq);
>  			break;
> -		case NULL_Q_RQ:
> -			blk_complete_request(cmd->rq);
> -			break;
>  		case NULL_Q_BIO:
>  			/*
>  			 * XXX: no proper submitting cpu information available.
> @@ -1349,30 +1324,6 @@ static blk_qc_t null_queue_bio(struct request_queue *q, struct bio *bio)
>  	return BLK_QC_T_NONE;
>  }
>  
> -static enum blk_eh_timer_return null_rq_timed_out_fn(struct request *rq)
> -{
> -	pr_info("null: rq %p timed out\n", rq);
> -	__blk_complete_request(rq);
> -	return BLK_EH_DONE;
> -}
> -
> -static int null_rq_prep_fn(struct request_queue *q, struct request *req)
> -{
> -	struct nullb *nullb = q->queuedata;
> -	struct nullb_queue *nq = nullb_to_queue(nullb);
> -	struct nullb_cmd *cmd;
> -
> -	cmd = alloc_cmd(nq, 0);
> -	if (cmd) {
> -		cmd->rq = req;
> -		req->special = cmd;
> -		return BLKPREP_OK;
> -	}
> -	blk_stop_queue(q);
> -
> -	return BLKPREP_DEFER;
> -}
> -
>  static bool should_timeout_request(struct request *rq)
>  {
>  #ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION
> @@ -1391,27 +1342,6 @@ static bool should_requeue_request(struct request *rq)
>  	return false;
>  }
>  
> -static void null_request_fn(struct request_queue *q)
> -{
> -	struct request *rq;
> -
> -	while ((rq = blk_fetch_request(q)) != NULL) {
> -		struct nullb_cmd *cmd = rq->special;
> -
> -		/* just ignore the request */
> -		if (should_timeout_request(rq))
> -			continue;
> -		if (should_requeue_request(rq)) {
> -			blk_requeue_request(q, rq);
> -			continue;
> -		}
> -
> -		spin_unlock_irq(q->queue_lock);
> -		null_handle_cmd(cmd);
> -		spin_lock_irq(q->queue_lock);
> -	}
> -}
> -
>  static enum blk_eh_timer_return null_timeout_rq(struct request *rq, bool res)
>  {
>  	pr_info("null: rq %p timed out\n", rq);
> @@ -1766,24 +1696,6 @@ static int null_add_dev(struct nullb_device *dev)
>  		rv = init_driver_queues(nullb);
>  		if (rv)
>  			goto out_cleanup_blk_queue;
> -	} else {
> -		nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock,
> -						dev->home_node);
> -		if (!nullb->q) {
> -			rv = -ENOMEM;
> -			goto out_cleanup_queues;
> -		}
> -
> -		if (!null_setup_fault())
> -			goto out_cleanup_blk_queue;
> -
> -		blk_queue_prep_rq(nullb->q, null_rq_prep_fn);
> -		blk_queue_softirq_done(nullb->q, null_softirq_done_fn);
> -		blk_queue_rq_timed_out(nullb->q, null_rq_timed_out_fn);
> -		nullb->q->rq_timeout = 5 * HZ;
> -		rv = init_driver_queues(nullb);
> -		if (rv)
> -			goto out_cleanup_blk_queue;
>  	}
>  
>  	if (dev->mbps) {
> @@ -1865,6 +1777,10 @@ static int __init null_init(void)
>  		return -EINVAL;
>  	}
>  
> +	if (g_queue_mode == NULL_Q_RQ) {
> +		pr_err("null_blk: legacy IO path no longer available\n");
> +		return -EINVAL;
> +	}
>  	if (g_queue_mode == NULL_Q_MQ && g_use_per_node_hctx) {
>  		if (g_submit_queues != nr_online_nodes) {
>  			pr_warn("null_blk: submit_queues param is set to %u.\n",
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 17/17] null_blk: remove legacy IO path
  2018-10-12  6:56   ` Dongli Zhang
@ 2018-10-12  8:51     ` Johannes Thumshirn
  2018-10-12 14:18       ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Johannes Thumshirn @ 2018-10-12  8:51 UTC (permalink / raw)
  To: Dongli Zhang, Jens Axboe; +Cc: linux-block

On 12/10/18 08:56, Dongli Zhang wrote:
> Hi Jens,
> 
> Will the legacy path be fully deprecated?
> 
> In addition to performance measurement, null_blk is a very good tutorial for
> beginners to understand how to implement a legacy path based block driver from
> scratch. Unless legacy path is not used any longer, why not keep it in the code
> as a tutorial?

But when there is no tutorial on how to write drivers for the legacy
path no one will write drivers for the legacy path and will be upset
when we remove it.

	Johannes

-- 
Johannes Thumshirn                                        SUSE Labs
jthumshirn@suse.de                                +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N�rnberg
GF: Felix Imend�rffer, Jane Smithard, Graham Norton
HRB 21284 (AG N�rnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq
  2018-10-11 16:59 ` [PATCH 14/17] aoe: convert aoeblk " Jens Axboe
@ 2018-10-12 11:28   ` Ed Cashin
  2018-10-12 14:20     ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Ed Cashin @ 2018-10-12 11:28 UTC (permalink / raw)
  To: axboe; +Cc: linux-block, Ed L. Cashin

OK.  We always tried to avoid putting includes in the .h file, so
if you wouldn't mind moving the include to the C files, that would
be nice.  I wouldn't insist, though.

On Thu, Oct 11, 2018 at 12:59 PM Jens Axboe <axboe@kernel.dk> wrote:
>
> Straight forward conversion - instead of rewriting the internal buffer
> retrieval logic, just replace the previous elevator peeking with an
> internal list of requests.
>
> Cc: "Ed L. Cashin" <ed.cashin@acm.org>
> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> ---
>  drivers/block/aoe/aoe.h    |  4 ++++
>  drivers/block/aoe/aoeblk.c | 49 ++++++++++++++++++++++++++++----------
>  drivers/block/aoe/aoecmd.c | 17 +++++++++----
>  drivers/block/aoe/aoedev.c | 14 ++++++-----
>  4 files changed, 60 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
> index c0ebda1283cc..9b9db29fe712 100644
> --- a/drivers/block/aoe/aoe.h
> +++ b/drivers/block/aoe/aoe.h
> @@ -1,4 +1,6 @@
>  /* Copyright (c) 2013 Coraid, Inc.  See COPYING for GPL terms. */
> +#include <linux/blk-mq.h>
> +
>  #define VERSION "85"
>  #define AOE_MAJOR 152
>  #define DEVICE_NAME "aoe"
> @@ -164,6 +166,8 @@ struct aoedev {
>         struct gendisk *gd;
>         struct dentry *debugfs;
>         struct request_queue *blkq;
> +       struct list_head rq_list;
> +       struct blk_mq_tag_set tag_set;
>         struct hd_geometry geo;
>         sector_t ssize;
>         struct timer_list timer;
> diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
> index 429ebb84b592..ba4afa0ce1c7 100644
> --- a/drivers/block/aoe/aoeblk.c
> +++ b/drivers/block/aoe/aoeblk.c
> @@ -6,7 +6,7 @@
>
>  #include <linux/kernel.h>
>  #include <linux/hdreg.h>
> -#include <linux/blkdev.h>
> +#include <linux/blk-mq.h>
>  #include <linux/backing-dev.h>
>  #include <linux/fs.h>
>  #include <linux/ioctl.h>
> @@ -274,23 +274,25 @@ aoeblk_release(struct gendisk *disk, fmode_t mode)
>         spin_unlock_irqrestore(&d->lock, flags);
>  }
>
> -static void
> -aoeblk_request(struct request_queue *q)
> +static blk_status_t aoeblk_queue_rq(struct blk_mq_hw_ctx *hctx,
> +                                   const struct blk_mq_queue_data *bd)
>  {
> -       struct aoedev *d;
> -       struct request *rq;
> +       struct aoedev *d = hctx->queue->queuedata;
> +
> +       spin_lock_irq(&d->lock);
>
> -       d = q->queuedata;
>         if ((d->flags & DEVFL_UP) == 0) {
>                 pr_info_ratelimited("aoe: device %ld.%d is not up\n",
>                         d->aoemajor, d->aoeminor);
> -               while ((rq = blk_peek_request(q))) {
> -                       blk_start_request(rq);
> -                       aoe_end_request(d, rq, 1);
> -               }
> -               return;
> +               spin_unlock_irq(&d->lock);
> +               blk_mq_start_request(bd->rq);
> +               return BLK_STS_IOERR;
>         }
> +
> +       list_add_tail(&bd->rq->queuelist, &d->rq_list);
>         aoecmd_work(d);
> +       spin_unlock_irq(&d->lock);
> +       return BLK_STS_OK;
>  }
>
>  static int
> @@ -345,6 +347,10 @@ static const struct block_device_operations aoe_bdops = {
>         .owner = THIS_MODULE,
>  };
>
> +static const struct blk_mq_ops aoeblk_mq_ops = {
> +       .queue_rq       = aoeblk_queue_rq,
> +};
> +
>  /* alloc_disk and add_disk can sleep */
>  void
>  aoeblk_gdalloc(void *vp)
> @@ -353,9 +359,11 @@ aoeblk_gdalloc(void *vp)
>         struct gendisk *gd;
>         mempool_t *mp;
>         struct request_queue *q;
> +       struct blk_mq_tag_set *set;
>         enum { KB = 1024, MB = KB * KB, READ_AHEAD = 2 * MB, };
>         ulong flags;
>         int late = 0;
> +       int err;
>
>         spin_lock_irqsave(&d->lock, flags);
>         if (d->flags & DEVFL_GDALLOC
> @@ -382,10 +390,25 @@ aoeblk_gdalloc(void *vp)
>                         d->aoemajor, d->aoeminor);
>                 goto err_disk;
>         }
> -       q = blk_init_queue(aoeblk_request, &d->lock);
> -       if (q == NULL) {
> +
> +       set = &d->tag_set;
> +       set->ops = &aoeblk_mq_ops;
> +       set->nr_hw_queues = 1;
> +       set->queue_depth = 128;
> +       set->numa_node = NUMA_NO_NODE;
> +       set->flags = BLK_MQ_F_SHOULD_MERGE;
> +       err = blk_mq_alloc_tag_set(set);
> +       if (err) {
> +               pr_err("aoe: cannot allocate tag set for %ld.%d\n",
> +                       d->aoemajor, d->aoeminor);
> +               goto err_mempool;
> +       }
> +
> +       q = blk_mq_init_queue(set);
> +       if (IS_ERR(q)) {
>                 pr_err("aoe: cannot allocate block queue for %ld.%d\n",
>                         d->aoemajor, d->aoeminor);
> +               blk_mq_free_tag_set(set);
>                 goto err_mempool;
>         }
>
> diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
> index 136dc507d020..fce0fc1fa7bf 100644
> --- a/drivers/block/aoe/aoecmd.c
> +++ b/drivers/block/aoe/aoecmd.c
> @@ -7,7 +7,7 @@
>  #include <linux/ata.h>
>  #include <linux/slab.h>
>  #include <linux/hdreg.h>
> -#include <linux/blkdev.h>
> +#include <linux/blk-mq.h>
>  #include <linux/skbuff.h>
>  #include <linux/netdevice.h>
>  #include <linux/genhd.h>
> @@ -857,10 +857,12 @@ nextbuf(struct aoedev *d)
>                 return d->ip.buf;
>         rq = d->ip.rq;
>         if (rq == NULL) {
> -               rq = blk_peek_request(q);
> +               rq = list_first_entry_or_null(&d->rq_list, struct request,
> +                                               queuelist);
>                 if (rq == NULL)
>                         return NULL;
> -               blk_start_request(rq);
> +               list_del_init(&rq->queuelist);
> +               blk_mq_start_request(rq);
>                 d->ip.rq = rq;
>                 d->ip.nxbio = rq->bio;
>                 rq->special = (void *) rqbiocnt(rq);
> @@ -1045,6 +1047,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
>         struct bio *bio;
>         int bok;
>         struct request_queue *q;
> +       blk_status_t err = BLK_STS_OK;
>
>         q = d->blkq;
>         if (rq == d->ip.rq)
> @@ -1052,11 +1055,15 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
>         do {
>                 bio = rq->bio;
>                 bok = !fastfail && !bio->bi_status;
> -       } while (__blk_end_request(rq, bok ? BLK_STS_OK : BLK_STS_IOERR, bio->bi_iter.bi_size));
> +               if (!bok)
> +                       err = BLK_STS_IOERR;
> +       } while (blk_update_request(rq, bok ? BLK_STS_OK : BLK_STS_IOERR, bio->bi_iter.bi_size));
> +
> +       __blk_mq_end_request(rq, err);
>
>         /* cf. http://lkml.org/lkml/2006/10/31/28 */
>         if (!fastfail)
> -               __blk_run_queue(q);
> +               blk_mq_run_hw_queues(q, true);
>  }
>
>  static void
> diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
> index 41060e9cedf2..96b420ddff3f 100644
> --- a/drivers/block/aoe/aoedev.c
> +++ b/drivers/block/aoe/aoedev.c
> @@ -5,7 +5,7 @@
>   */
>
>  #include <linux/hdreg.h>
> -#include <linux/blkdev.h>
> +#include <linux/blk-mq.h>
>  #include <linux/netdevice.h>
>  #include <linux/delay.h>
>  #include <linux/slab.h>
> @@ -197,7 +197,6 @@ aoedev_downdev(struct aoedev *d)
>  {
>         struct aoetgt *t, **tt, **te;
>         struct list_head *head, *pos, *nx;
> -       struct request *rq;
>         int i;
>
>         d->flags &= ~DEVFL_UP;
> @@ -225,10 +224,11 @@ aoedev_downdev(struct aoedev *d)
>
>         /* fast fail all pending I/O */
>         if (d->blkq) {
> -               while ((rq = blk_peek_request(d->blkq))) {
> -                       blk_start_request(rq);
> -                       aoe_end_request(d, rq, 1);
> -               }
> +               /* UP is cleared, freeze+quiesce to insure all are errored */
> +               blk_mq_freeze_queue(d->blkq);
> +               blk_mq_quiesce_queue(d->blkq);
> +               blk_mq_unquiesce_queue(d->blkq);
> +               blk_mq_unfreeze_queue(d->blkq);
>         }
>
>         if (d->gd)
> @@ -278,6 +278,7 @@ freedev(struct aoedev *d)
>                 aoedisk_rm_sysfs(d);
>                 del_gendisk(d->gd);
>                 put_disk(d->gd);
> +               blk_mq_free_tag_set(&d->tag_set);
>                 blk_cleanup_queue(d->blkq);
>         }
>         t = d->targets;
> @@ -464,6 +465,7 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc)
>         d->ntargets = NTARGETS;
>         INIT_WORK(&d->work, aoecmd_sleepwork);
>         spin_lock_init(&d->lock);
> +       INIT_LIST_HEAD(&d->rq_list);
>         skb_queue_head_init(&d->skbpool);
>         timer_setup(&d->timer, dummy_timer, 0);
>         d->timer.expires = jiffies + HZ;
> --
> 2.17.1
>


-- 
  Ed Cashin <ecashin@noserose.net>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 17/17] null_blk: remove legacy IO path
  2018-10-12  8:51     ` Johannes Thumshirn
@ 2018-10-12 14:18       ` Jens Axboe
  0 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-12 14:18 UTC (permalink / raw)
  To: Johannes Thumshirn, Dongli Zhang; +Cc: linux-block

On 10/12/18 2:51 AM, Johannes Thumshirn wrote:
> On 12/10/18 08:56, Dongli Zhang wrote:
>> Hi Jens,
>>
>> Will the legacy path be fully deprecated?
>>
>> In addition to performance measurement, null_blk is a very good tutorial for
>> beginners to understand how to implement a legacy path based block driver from
>> scratch. Unless legacy path is not used any longer, why not keep it in the code
>> as a tutorial?
> 
> But when there is no tutorial on how to write drivers for the legacy
> path no one will write drivers for the legacy path and will be upset
> when we remove it.

Plus the legacy path is going away right now, that's the whole point of
this series of patches. Once this is done, I'm killing all that code.

The whole point of legacy is that it's, well, legacy. Nobody should
be writing that style of driver anymore. null_blk has a clean blk-mq
implementation, that's what people can look at if they want to learn
how to write a new blk-mq driver.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq
  2018-10-12 11:28   ` Ed Cashin
@ 2018-10-12 14:20     ` Jens Axboe
  2018-10-12 16:17       ` Ed Cashin
  0 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-12 14:20 UTC (permalink / raw)
  To: Ed Cashin; +Cc: linux-block, Ed L. Cashin

On 10/12/18 5:28 AM, Ed Cashin wrote:
> OK.  We always tried to avoid putting includes in the .h file, so
> if you wouldn't mind moving the include to the C files, that would
> be nice.  I wouldn't insist, though.

There's really no way around it, since I'm embedding the tag_set
in the device.

Is that OK with you?

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq
  2018-10-12 14:20     ` Jens Axboe
@ 2018-10-12 16:17       ` Ed Cashin
  2018-10-12 16:23         ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Ed Cashin @ 2018-10-12 16:17 UTC (permalink / raw)
  To: axboe; +Cc: linux-block, Ed L. Cashin

On Fri, Oct 12, 2018 at 10:20 AM Jens Axboe <axboe@kernel.dk> wrote:
>
> On 10/12/18 5:28 AM, Ed Cashin wrote:
> > OK.  We always tried to avoid putting includes in the .h file, so
> > if you wouldn't mind moving the include to the C files, that would
> > be nice.  I wouldn't insist, though.
>
> There's really no way around it, since I'm embedding the tag_set
> in the device.
>
> Is that OK with you?

Yes, it's fine.  Thank you.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq
  2018-10-12 16:17       ` Ed Cashin
@ 2018-10-12 16:23         ` Jens Axboe
  2018-10-12 16:26           ` Ed Cashin
  0 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-12 16:23 UTC (permalink / raw)
  To: Ed Cashin; +Cc: linux-block

On 10/12/18 10:17 AM, Ed Cashin wrote:
> On Fri, Oct 12, 2018 at 10:20 AM Jens Axboe <axboe@kernel.dk> wrote:
>>
>> On 10/12/18 5:28 AM, Ed Cashin wrote:
>>> OK.  We always tried to avoid putting includes in the .h file, so
>>> if you wouldn't mind moving the include to the C files, that would
>>> be nice.  I wouldn't insist, though.
>>
>> There's really no way around it, since I'm embedding the tag_set
>> in the device.
>>
>> Is that OK with you?
> 
> Yes, it's fine.  Thank you.

Can I add a reviewed-by?

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq
  2018-10-12 16:23         ` Jens Axboe
@ 2018-10-12 16:26           ` Ed Cashin
  2018-10-14  0:48             ` Ed Cashin
  0 siblings, 1 reply; 56+ messages in thread
From: Ed Cashin @ 2018-10-12 16:26 UTC (permalink / raw)
  To: axboe; +Cc: Ed L. Cashin, linux-block

On Fri, Oct 12, 2018 at 12:23 PM Jens Axboe <axboe@kernel.dk> wrote:
>
> On 10/12/18 10:17 AM, Ed Cashin wrote:
> > On Fri, Oct 12, 2018 at 10:20 AM Jens Axboe <axboe@kernel.dk> wrote:
> >>
> >> On 10/12/18 5:28 AM, Ed Cashin wrote:
> >>> OK.  We always tried to avoid putting includes in the .h file, so
> >>> if you wouldn't mind moving the include to the C files, that would
> >>> be nice.  I wouldn't insist, though.
> >>
> >> There's really no way around it, since I'm embedding the tag_set
> >> in the device.
> >>
> >> Is that OK with you?
> >
> > Yes, it's fine.  Thank you.
>
> Can I add a reviewed-by?

Acked-by is already fine, but I can give it more attention tomorrow, and after
that a reviewed-by would be appropriate.

-- 
  Ed

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 17/17] null_blk: remove legacy IO path
  2018-10-11 16:59 ` [PATCH 17/17] null_blk: remove legacy IO path Jens Axboe
  2018-10-12  6:56   ` Dongli Zhang
@ 2018-10-12 17:24   ` Sébastien Boisvert
  2018-10-12 17:30     ` Jens Axboe
  1 sibling, 1 reply; 56+ messages in thread
From: Sébastien Boisvert @ 2018-10-12 17:24 UTC (permalink / raw)
  To: Jens Axboe, linux-block

Hello Jens,

On 2018-10-11 12:59 PM, Jens Axboe wrote:
> We're planning on removing this code completely, kill the old
> path.
> 
> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> ---
>  drivers/block/null_blk_main.c | 96 +++--------------------------------
>  1 file changed, 6 insertions(+), 90 deletions(-)
> 
> diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c
> index 093b614d6524..8142cc8ff952 100644
> --- a/drivers/block/null_blk_main.c
> +++ b/drivers/block/null_blk_main.c
> @@ -616,10 +616,6 @@ static void end_cmd(struct nullb_cmd *cmd)
>  	case NULL_Q_MQ:
>  		blk_mq_end_request(cmd->rq, cmd->error);
>  		return;
> -	case NULL_Q_RQ:
> -		INIT_LIST_HEAD(&cmd->rq->queuelist);
> -		blk_end_request_all(cmd->rq, cmd->error);
> -		break;
>  	case NULL_Q_BIO:
>  		cmd->bio->bi_status = cmd->error;
>  		bio_endio(cmd->bio);
> @@ -627,15 +623,6 @@ static void end_cmd(struct nullb_cmd *cmd)
>  	}
>  
>  	free_cmd(cmd);
> -
> -	/* Restart queue if needed, as we are freeing a tag */
> -	if (queue_mode == NULL_Q_RQ && blk_queue_stopped(q)) {
> -		unsigned long flags;
> -
> -		spin_lock_irqsave(q->queue_lock, flags);
> -		blk_start_queue_async(q);
> -		spin_unlock_irqrestore(q->queue_lock, flags);
> -	}
>  }
>  
>  static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer)
> @@ -1197,17 +1184,8 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd)
>  			/* race with timer */
>  			if (atomic_long_read(&nullb->cur_bytes) > 0)
>  				null_restart_queue_async(nullb);
> -			if (dev->queue_mode == NULL_Q_RQ) {
> -				struct request_queue *q = nullb->q;
> -
> -				spin_lock_irq(q->queue_lock);
> -				rq->rq_flags |= RQF_DONTPREP;
> -				blk_requeue_request(q, rq);
> -				spin_unlock_irq(q->queue_lock);
> -				return BLK_STS_OK;
> -			} else
> -				/* requeue request */
> -				return BLK_STS_DEV_RESOURCE;
> +			/* requeue request */
> +			return BLK_STS_DEV_RESOURCE;
>  		}
>  	}
>  
> @@ -1278,9 +1256,6 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd)
>  		case NULL_Q_MQ:
>  			blk_mq_complete_request(cmd->rq);
>  			break;
> -		case NULL_Q_RQ:
> -			blk_complete_request(cmd->rq);
> -			break;
>  		case NULL_Q_BIO:
>  			/*
>  			 * XXX: no proper submitting cpu information available.
> @@ -1349,30 +1324,6 @@ static blk_qc_t null_queue_bio(struct request_queue *q, struct bio *bio)
>  	return BLK_QC_T_NONE;
>  }
>  
> -static enum blk_eh_timer_return null_rq_timed_out_fn(struct request *rq)
> -{
> -	pr_info("null: rq %p timed out\n", rq);
> -	__blk_complete_request(rq);
> -	return BLK_EH_DONE;
> -}
> -
> -static int null_rq_prep_fn(struct request_queue *q, struct request *req)
> -{
> -	struct nullb *nullb = q->queuedata;
> -	struct nullb_queue *nq = nullb_to_queue(nullb);
> -	struct nullb_cmd *cmd;
> -
> -	cmd = alloc_cmd(nq, 0);
> -	if (cmd) {
> -		cmd->rq = req;
> -		req->special = cmd;
> -		return BLKPREP_OK;
> -	}
> -	blk_stop_queue(q);
> -
> -	return BLKPREP_DEFER;
> -}
> -
>  static bool should_timeout_request(struct request *rq)
>  {
>  #ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION
> @@ -1391,27 +1342,6 @@ static bool should_requeue_request(struct request *rq)
>  	return false;
>  }
>  
> -static void null_request_fn(struct request_queue *q)
> -{
> -	struct request *rq;
> -
> -	while ((rq = blk_fetch_request(q)) != NULL) {
> -		struct nullb_cmd *cmd = rq->special;
> -
> -		/* just ignore the request */
> -		if (should_timeout_request(rq))
> -			continue;
> -		if (should_requeue_request(rq)) {
> -			blk_requeue_request(q, rq);
> -			continue;
> -		}
> -
> -		spin_unlock_irq(q->queue_lock);
> -		null_handle_cmd(cmd);
> -		spin_lock_irq(q->queue_lock);
> -	}
> -}
> -
>  static enum blk_eh_timer_return null_timeout_rq(struct request *rq, bool res)
>  {
>  	pr_info("null: rq %p timed out\n", rq);
> @@ -1766,24 +1696,6 @@ static int null_add_dev(struct nullb_device *dev)
>  		rv = init_driver_queues(nullb);
>  		if (rv)
>  			goto out_cleanup_blk_queue;
> -	} else {
> -		nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock,
> -						dev->home_node);
> -		if (!nullb->q) {
> -			rv = -ENOMEM;
> -			goto out_cleanup_queues;
> -		}
> -
> -		if (!null_setup_fault())
> -			goto out_cleanup_blk_queue;
> -
> -		blk_queue_prep_rq(nullb->q, null_rq_prep_fn);
> -		blk_queue_softirq_done(nullb->q, null_softirq_done_fn);
> -		blk_queue_rq_timed_out(nullb->q, null_rq_timed_out_fn);
> -		nullb->q->rq_timeout = 5 * HZ;
> -		rv = init_driver_queues(nullb);
> -		if (rv)
> -			goto out_cleanup_blk_queue;
>  	}
>  
>  	if (dev->mbps) {
> @@ -1865,6 +1777,10 @@ static int __init null_init(void)
>  		return -EINVAL;
>  	}
>  
> +	if (g_queue_mode == NULL_Q_RQ) {
> +		pr_err("null_blk: legacy IO path no longer available\n");
> +		return -EINVAL;
> +	}

Is this the only location where the value NULL_Q_RQ has be checked ?


Since the enum that contains NULL_Q_RQ is in drivers/block/null_blk_main.c, and not in a linux header file,
would it be thinkable to remove NULL_Q_RQ from the enum too, and not adding this legacy check ?

Would that break user space (the number one rule) ?

See in 0778a9f2dd924c3af41971ba40eec44793aea531 from remotes/axboe-linux-block/master :

drivers/block/null_blk_main.c-79-enum {
drivers/block/null_blk_main.c-80-	NULL_Q_BIO		= 0,
drivers/block/null_blk_main.c:81:	NULL_Q_RQ		= 1,
drivers/block/null_blk_main.c-82-	NULL_Q_MQ		= 2,
drivers/block/null_blk_main.c-83-};


>  	if (g_queue_mode == NULL_Q_MQ && g_use_per_node_hctx) {
>  		if (g_submit_queues != nr_online_nodes) {
>  			pr_warn("null_blk: submit_queues param is set to %u.\n",
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 17/17] null_blk: remove legacy IO path
  2018-10-12 17:24   ` Sébastien Boisvert
@ 2018-10-12 17:30     ` Jens Axboe
  2018-10-12 17:37       ` Sébastien Boisvert
  0 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-12 17:30 UTC (permalink / raw)
  To: Sébastien Boisvert, linux-block

On 10/12/18 11:24 AM, Sébastien Boisvert wrote:
>> +	if (g_queue_mode == NULL_Q_RQ) {
>> +		pr_err("null_blk: legacy IO path no longer available\n");
>> +		return -EINVAL;
>> +	}
> 
> Is this the only location where the value NULL_Q_RQ has be checked ?

I've since fixed a few more, all should be well now. The updated version
is here:

http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=d6fd3bd94a7333a8cd0bf7ef18f719ef7e052dc4

> Since the enum that contains NULL_Q_RQ is in
> drivers/block/null_blk_main.c, and not in a linux header file, would
> it be thinkable to remove NULL_Q_RQ from the enum too, and not adding
> this legacy check ?
>
> Would that break user space (the number one rule) ?

It wouldn't break user space. In any case, if someone is currently using
queue_mode=1, it'd fail to load after this patch.

I'm checking that at the bottom, we could remove NULL_Q_RQ if we just
made that check == 1 instead. But cleaner to keep it, imho.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 17/17] null_blk: remove legacy IO path
  2018-10-12 17:30     ` Jens Axboe
@ 2018-10-12 17:37       ` Sébastien Boisvert
  2018-10-12 17:50         ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Sébastien Boisvert @ 2018-10-12 17:37 UTC (permalink / raw)
  To: Jens Axboe, linux-block



On 2018-10-12 01:30 PM, Jens Axboe wrote:
> On 10/12/18 11:24 AM, Sébastien Boisvert wrote:
>>> +	if (g_queue_mode == NULL_Q_RQ) {
>>> +		pr_err("null_blk: legacy IO path no longer available\n");
>>> +		return -EINVAL;
>>> +	}
>>
>> Is this the only location where the value NULL_Q_RQ has be checked ?
> 
> I've since fixed a few more, all should be well now. The updated version
> is here:
> 
> http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=d6fd3bd94a7333a8cd0bf7ef18f719ef7e052dc4
> 
>> Since the enum that contains NULL_Q_RQ is in
>> drivers/block/null_blk_main.c, and not in a linux header file, would
>> it be thinkable to remove NULL_Q_RQ from the enum too, and not adding
>> this legacy check ?
>>
>> Would that break user space (the number one rule) ?
> 
> It wouldn't break user space. In any case, if someone is currently using
> queue_mode=1, it'd fail to load after this patch.
> 

Just curious, where can this be passed (mount option, boot option, /sys, /proc, driver code, or whatnot) ?

> I'm checking that at the bottom, we could remove NULL_Q_RQ if we just
> made that check == 1 instead. But cleaner to keep it, imho.
> 

I agree, if queue_mode=1 can be passed.


Reviewed-by: Sébastien Boisvert <sboisvert@gydle.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 17/17] null_blk: remove legacy IO path
  2018-10-12 17:37       ` Sébastien Boisvert
@ 2018-10-12 17:50         ` Jens Axboe
  0 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-12 17:50 UTC (permalink / raw)
  To: Sébastien Boisvert, linux-block

On 10/12/18 11:37 AM, Sébastien Boisvert wrote:
> On 2018-10-12 01:30 PM, Jens Axboe wrote:
>> On 10/12/18 11:24 AM, Sébastien Boisvert wrote:
>>>> +	if (g_queue_mode == NULL_Q_RQ) {
>>>> +		pr_err("null_blk: legacy IO path no longer available\n");
>>>> +		return -EINVAL;
>>>> +	}
>>>
>>> Is this the only location where the value NULL_Q_RQ has be checked ?
>>
>> I've since fixed a few more, all should be well now. The updated version
>> is here:
>>
>> http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=d6fd3bd94a7333a8cd0bf7ef18f719ef7e052dc4
>>
>>> Since the enum that contains NULL_Q_RQ is in
>>> drivers/block/null_blk_main.c, and not in a linux header file, would
>>> it be thinkable to remove NULL_Q_RQ from the enum too, and not adding
>>> this legacy check ?
>>>
>>> Would that break user space (the number one rule) ?
>>
>> It wouldn't break user space. In any case, if someone is currently using
>> queue_mode=1, it'd fail to load after this patch.
>>
> 
> Just curious, where can this be passed (mount option, boot option,
> /sys, /proc, driver code, or whatnot) ?

It's a module parameter, so through modprobe or (if builtin), using a
command line option.

>> I'm checking that at the bottom, we could remove NULL_Q_RQ if we just
>> made that check == 1 instead. But cleaner to keep it, imho.
>>
> 
> I agree, if queue_mode=1 can be passed.

It'll have to fail it. If the user asks for this specific mode, and that
mode no longer exists, then it has to fail. It's not like this is root
device or anything like that, it's just for testing. It'd be worse NOT
to fail the modprobe, since then the user/scripts/tests will think they
are testing one thing, but in fact testing something else.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 03/17] ps3disk: convert to blk-mq
  2018-10-11 16:58 ` [PATCH 03/17] ps3disk: " Jens Axboe
@ 2018-10-12 22:47   ` Geoff Levand
  2018-10-13  0:58     ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Geoff Levand @ 2018-10-12 22:47 UTC (permalink / raw)
  To: Jens Axboe, linux-block; +Cc: Benjamin Herrenschmidt

Hi Jens,

On 10/11/2018 09:58 AM, Jens Axboe wrote:
> Convert from the old request_fn style driver to blk-mq.

I tested this on PS3 applied to v4.19-rc7, and on boot it either
gets a deadlock message or becomes unstable with various other
block related error messages.

For what its worth, I put an image of the deadlock message here:

  https://storage.googleapis.com/public-tmp-files/blk-deadlock.jpg

-Geoff

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 03/17] ps3disk: convert to blk-mq
  2018-10-12 22:47   ` Geoff Levand
@ 2018-10-13  0:58     ` Jens Axboe
  2018-10-15 16:22       ` Geoff Levand
  0 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-13  0:58 UTC (permalink / raw)
  To: Geoff Levand, linux-block; +Cc: Benjamin Herrenschmidt

On 10/12/18 4:47 PM, Geoff Levand wrote:
> Hi Jens,
> 
> On 10/11/2018 09:58 AM, Jens Axboe wrote:
>> Convert from the old request_fn style driver to blk-mq.
> 
> I tested this on PS3 applied to v4.19-rc7, and on boot it either
> gets a deadlock message or becomes unstable with various other
> block related error messages.
> 
> For what its worth, I put an image of the deadlock message here:
> 
>   https://storage.googleapis.com/public-tmp-files/blk-deadlock.jpg

Thanks for testing! Can you try this incremental? It's mostly just
a cleanup on top, but the last hunk should be the thing that
hopefully makes this tick again. If you prefer just using a new
patch, this one is updated:

http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=5c86f76f45e7c8d5a47a1f20b3e7b93fc945168a


diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index 5f777b694f3c..338ea9dc3393 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -119,8 +119,8 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
 	}
 }
 
-static void ps3disk_submit_request_sg(struct ps3_storage_device *dev,
-				      struct request *req)
+static blk_status_t ps3disk_submit_request_sg(struct ps3_storage_device *dev,
+					      struct request *req)
 {
 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 	int write = rq_data_dir(req), res;
@@ -159,15 +159,15 @@ static void ps3disk_submit_request_sg(struct ps3_storage_device *dev,
 	if (res) {
 		dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
 			__LINE__, op, res);
-		blk_mq_end_request(req, BLK_STS_IOERR);
-		return;
+		return BLK_STS_IOERR;
 	}
 
 	priv->req = req;
+	return BLK_STS_OK;
 }
 
-static void ps3disk_submit_flush_request(struct ps3_storage_device *dev,
-					 struct request *req)
+static blk_status_t ps3disk_submit_flush_request(struct ps3_storage_device *dev,
+						 struct request *req)
 {
 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 	u64 res;
@@ -180,29 +180,27 @@ static void ps3disk_submit_flush_request(struct ps3_storage_device *dev,
 	if (res) {
 		dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
 			__func__, __LINE__, res);
-		blk_mq_end_request(req, BLK_STS_IOERR);
-		return;
+		return BLK_STS_IOERR;
 	}
 
 	priv->req = req;
+	return BLK_STS_OK;
 }
 
-static void ps3disk_do_request(struct ps3_storage_device *dev,
-			       struct request *req)
+static blk_status_t ps3disk_do_request(struct ps3_storage_device *dev,
+				       struct request *req)
 {
 	dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
 
 	switch (req_op(req)) {
 	case REQ_OP_FLUSH:
-		ps3disk_submit_flush_request(dev, req);
-		break;
+		return ps3disk_submit_flush_request(dev, req);
 	case REQ_OP_READ:
 	case REQ_OP_WRITE:
-		ps3disk_submit_request_sg(dev, req);
-		break;
+		return ps3disk_submit_request_sg(dev, req);
 	default:
 		blk_dump_rq_flags(req, DEVICE_NAME " bad request");
-		blk_mq_end_request(req, BLK_STS_IOERR);
+		return BLK_STS_IOERR;
 	}
 }
 
@@ -212,14 +210,15 @@ static blk_status_t ps3disk_queue_rq(struct blk_mq_hw_ctx *hctx,
 	struct request_queue *q = hctx->queue;
 	struct ps3_storage_device *dev = q->queuedata;
 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
+	blk_status_t ret;
 
 	blk_mq_start_request(bd->rq);
 
 	spin_lock_irq(&priv->lock);
-	ps3disk_do_request(dev, bd->rq);
+	ret = ps3disk_do_request(dev, bd->rq);
 	spin_unlock_irq(&priv->lock);
 
-	return BLK_STS_OK;
+	return ret;
 }
 
 static irqreturn_t ps3disk_interrupt(int irq, void *data)
@@ -281,7 +280,7 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
 	priv->req = NULL;
 	spin_unlock(&priv->lock);
 
-	blk_mq_start_hw_queues(priv->queue);
+	blk_mq_run_hw_queues(priv->queue, true);
 	return IRQ_HANDLED;
 }
 

-- 
Jens Axboe

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq
  2018-10-12 16:26           ` Ed Cashin
@ 2018-10-14  0:48             ` Ed Cashin
  2018-10-14 18:44               ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Ed Cashin @ 2018-10-14  0:48 UTC (permalink / raw)
  To: Ed Cashin; +Cc: axboe, linux-block

[-- Attachment #1: Type: text/plain, Size: 945 bytes --]

I reviewed the changes. They looked good.

On Fri, Oct 12, 2018 at 12:26 PM Ed Cashin <ed.cashin@acm.org> wrote:

> On Fri, Oct 12, 2018 at 12:23 PM Jens Axboe <axboe@kernel.dk> wrote:
> >
> > On 10/12/18 10:17 AM, Ed Cashin wrote:
> > > On Fri, Oct 12, 2018 at 10:20 AM Jens Axboe <axboe@kernel.dk> wrote:
> > >>
> > >> On 10/12/18 5:28 AM, Ed Cashin wrote:
> > >>> OK.  We always tried to avoid putting includes in the .h file, so
> > >>> if you wouldn't mind moving the include to the C files, that would
> > >>> be nice.  I wouldn't insist, though.
> > >>
> > >> There's really no way around it, since I'm embedding the tag_set
> > >> in the device.
> > >>
> > >> Is that OK with you?
> > >
> > > Yes, it's fine.  Thank you.
> >
> > Can I add a reviewed-by?
>
> Acked-by is already fine, but I can give it more attention tomorrow, and
> after
> that a reviewed-by would be appropriate.
>
> --
>   Ed
>
-- 
  Ed Cashin <ecashin@noserose.net>

[-- Attachment #2: Type: text/html, Size: 1715 bytes --]

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 08/17] ms_block: convert to blk-mq
  2018-10-11 16:59 ` [PATCH 08/17] ms_block: convert " Jens Axboe
@ 2018-10-14  6:30   ` Maxim Levitsky
  0 siblings, 0 replies; 56+ messages in thread
From: Maxim Levitsky @ 2018-10-14  6:30 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block

Hi!

I haven't yet had  a chance to test this patch but I will do during this week.
Thanks!

Best regards,
       Maxim Levitsky


On Thu, Oct 11, 2018 at 7:59 PM Jens Axboe <axboe@kernel.dk> wrote:
>
> Straight forward conversion, room for optimization in how everything
> is punted to a work queue. Also looks plenty racy all over the map,
> with the state changes. I fixed a bunch of them up while doing the
> conversion, but there are surely more.
>
> Cc: Maxim Levitsky <maximlevitsky@gmail.com>
> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> ---
>  drivers/memstick/core/ms_block.c | 121 ++++++++++++++++++-------------
>  drivers/memstick/core/ms_block.h |   1 +
>  2 files changed, 73 insertions(+), 49 deletions(-)
>
> diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c
> index 716fc8ed31d3..b829f55ff577 100644
> --- a/drivers/memstick/core/ms_block.c
> +++ b/drivers/memstick/core/ms_block.c
> @@ -15,7 +15,7 @@
>  #define pr_fmt(fmt) DRIVER_NAME ": " fmt
>
>  #include <linux/module.h>
> -#include <linux/blkdev.h>
> +#include <linux/blk-mq.h>
>  #include <linux/memstick.h>
>  #include <linux/idr.h>
>  #include <linux/hdreg.h>
> @@ -1873,69 +1873,65 @@ static void msb_io_work(struct work_struct *work)
>         struct msb_data *msb = container_of(work, struct msb_data, io_work);
>         int page, error, len;
>         sector_t lba;
> -       unsigned long flags;
>         struct scatterlist *sg = msb->prealloc_sg;
> +       struct request *req;
>
>         dbg_verbose("IO: work started");
>
>         while (1) {
> -               spin_lock_irqsave(&msb->q_lock, flags);
> +               spin_lock_irq(&msb->q_lock);
>
>                 if (msb->need_flush_cache) {
>                         msb->need_flush_cache = false;
> -                       spin_unlock_irqrestore(&msb->q_lock, flags);
> +                       spin_unlock_irq(&msb->q_lock);
>                         msb_cache_flush(msb);
>                         continue;
>                 }
>
> -               if (!msb->req) {
> -                       msb->req = blk_fetch_request(msb->queue);
> -                       if (!msb->req) {
> -                               dbg_verbose("IO: no more requests exiting");
> -                               spin_unlock_irqrestore(&msb->q_lock, flags);
> -                               return;
> -                       }
> +               req = msb->req;
> +               if (!req) {
> +                       dbg_verbose("IO: no more requests exiting");
> +                       spin_unlock_irq(&msb->q_lock);
> +                       return;
>                 }
>
> -               spin_unlock_irqrestore(&msb->q_lock, flags);
> -
> -               /* If card was removed meanwhile */
> -               if (!msb->req)
> -                       return;
> +               spin_unlock_irq(&msb->q_lock);
>
>                 /* process the request */
>                 dbg_verbose("IO: processing new request");
> -               blk_rq_map_sg(msb->queue, msb->req, sg);
> +               blk_rq_map_sg(msb->queue, req, sg);
>
> -               lba = blk_rq_pos(msb->req);
> +               lba = blk_rq_pos(req);
>
>                 sector_div(lba, msb->page_size / 512);
>                 page = sector_div(lba, msb->pages_in_block);
>
>                 if (rq_data_dir(msb->req) == READ)
>                         error = msb_do_read_request(msb, lba, page, sg,
> -                               blk_rq_bytes(msb->req), &len);
> +                               blk_rq_bytes(req), &len);
>                 else
>                         error = msb_do_write_request(msb, lba, page, sg,
> -                               blk_rq_bytes(msb->req), &len);
> +                               blk_rq_bytes(req), &len);
>
> -               spin_lock_irqsave(&msb->q_lock, flags);
> -
> -               if (len)
> -                       if (!__blk_end_request(msb->req, BLK_STS_OK, len))
> -                               msb->req = NULL;
> +               if (len && !blk_update_request(req, BLK_STS_OK, len)) {
> +                       __blk_mq_end_request(req, BLK_STS_OK);
> +                       spin_lock_irq(&msb->q_lock);
> +                       msb->req = NULL;
> +                       spin_unlock_irq(&msb->q_lock);
> +               }
>
>                 if (error && msb->req) {
>                         blk_status_t ret = errno_to_blk_status(error);
> +
>                         dbg_verbose("IO: ending one sector of the request with error");
> -                       if (!__blk_end_request(msb->req, ret, msb->page_size))
> -                               msb->req = NULL;
> +                       blk_mq_end_request(req, ret);
> +                       spin_lock_irq(&msb->q_lock);
> +                       msb->req = NULL;
> +                       spin_unlock_irq(&msb->q_lock);
>                 }
>
>                 if (msb->req)
>                         dbg_verbose("IO: request still pending");
> -
> -               spin_unlock_irqrestore(&msb->q_lock, flags);
>         }
>  }
>
> @@ -2002,29 +1998,40 @@ static int msb_bd_getgeo(struct block_device *bdev,
>         return 0;
>  }
>
> -static void msb_submit_req(struct request_queue *q)
> +static blk_status_t msb_queue_rq(struct blk_mq_hw_ctx *hctx,
> +                                const struct blk_mq_queue_data *bd)
>  {
> -       struct memstick_dev *card = q->queuedata;
> +       struct memstick_dev *card = hctx->queue->queuedata;
>         struct msb_data *msb = memstick_get_drvdata(card);
> -       struct request *req = NULL;
> +       struct request *req = bd->rq;
>
>         dbg_verbose("Submit request");
>
> +       spin_lock_irq(&msb->q_lock);
> +
>         if (msb->card_dead) {
>                 dbg("Refusing requests on removed card");
>
>                 WARN_ON(!msb->io_queue_stopped);
>
> -               while ((req = blk_fetch_request(q)) != NULL)
> -                       __blk_end_request_all(req, BLK_STS_IOERR);
> -               return;
> +               spin_unlock_irq(&msb->q_lock);
> +               blk_mq_start_request(req);
> +               return BLK_STS_IOERR;
>         }
>
> -       if (msb->req)
> -               return;
> +       if (msb->req) {
> +               spin_unlock_irq(&msb->q_lock);
> +               return BLK_STS_DEV_RESOURCE;
> +       }
> +
> +       blk_mq_start_request(req);
> +       msb->req = req;
>
>         if (!msb->io_queue_stopped)
>                 queue_work(msb->io_queue, &msb->io_work);
> +
> +       spin_unlock_irq(&msb->q_lock);
> +       return BLK_STS_OK;
>  }
>
>  static int msb_check_card(struct memstick_dev *card)
> @@ -2040,21 +2047,20 @@ static void msb_stop(struct memstick_dev *card)
>
>         dbg("Stopping all msblock IO");
>
> +       blk_mq_stop_hw_queues(msb->queue);
>         spin_lock_irqsave(&msb->q_lock, flags);
> -       blk_stop_queue(msb->queue);
>         msb->io_queue_stopped = true;
>         spin_unlock_irqrestore(&msb->q_lock, flags);
>
>         del_timer_sync(&msb->cache_flush_timer);
>         flush_workqueue(msb->io_queue);
>
> +       spin_lock_irqsave(&msb->q_lock, flags);
>         if (msb->req) {
> -               spin_lock_irqsave(&msb->q_lock, flags);
> -               blk_requeue_request(msb->queue, msb->req);
> +               blk_mq_requeue_request(msb->req, false);
>                 msb->req = NULL;
> -               spin_unlock_irqrestore(&msb->q_lock, flags);
>         }
> -
> +       spin_unlock_irqrestore(&msb->q_lock, flags);
>  }
>
>  static void msb_start(struct memstick_dev *card)
> @@ -2077,9 +2083,7 @@ static void msb_start(struct memstick_dev *card)
>         msb->need_flush_cache = true;
>         msb->io_queue_stopped = false;
>
> -       spin_lock_irqsave(&msb->q_lock, flags);
> -       blk_start_queue(msb->queue);
> -       spin_unlock_irqrestore(&msb->q_lock, flags);
> +       blk_mq_start_hw_queues(msb->queue);
>
>         queue_work(msb->io_queue, &msb->io_work);
>
> @@ -2092,10 +2096,15 @@ static const struct block_device_operations msb_bdops = {
>         .owner   = THIS_MODULE
>  };
>
> +static const struct blk_mq_ops msb_mq_ops = {
> +       .queue_rq       = msb_queue_rq,
> +};
> +
>  /* Registers the block device */
>  static int msb_init_disk(struct memstick_dev *card)
>  {
>         struct msb_data *msb = memstick_get_drvdata(card);
> +       struct blk_mq_tag_set *set = NULL;
>         int rc;
>         unsigned long capacity;
>
> @@ -2112,10 +2121,21 @@ static int msb_init_disk(struct memstick_dev *card)
>                 goto out_release_id;
>         }
>
> -       msb->queue = blk_init_queue(msb_submit_req, &msb->q_lock);
> -       if (!msb->queue) {
> -               rc = -ENOMEM;
> +       set = &msb->tag_set;
> +       set->ops = &msb_mq_ops;
> +       set->nr_hw_queues = 1;
> +       set->queue_depth = 2;
> +       set->numa_node = NUMA_NO_NODE;
> +       set->flags = BLK_MQ_F_SHOULD_MERGE;
> +       rc = blk_mq_alloc_tag_set(set);
> +       if (rc)
>                 goto out_put_disk;
> +
> +       msb->queue = blk_mq_init_queue(set);
> +       if (IS_ERR(msb->queue)) {
> +               rc = PTR_ERR(msb->queue);
> +               msb->queue = NULL;
> +               goto out_put_tag;
>         }
>
>         msb->queue->queuedata = card;
> @@ -2150,6 +2170,8 @@ static int msb_init_disk(struct memstick_dev *card)
>         dbg("Disk added");
>         return 0;
>
> +out_put_tag:
> +       blk_mq_free_tag_set(&msb->tag_set);
>  out_put_disk:
>         put_disk(msb->disk);
>  out_release_id:
> @@ -2202,11 +2224,12 @@ static void msb_remove(struct memstick_dev *card)
>         /* Take care of unhandled + new requests from now on */
>         spin_lock_irqsave(&msb->q_lock, flags);
>         msb->card_dead = true;
> -       blk_start_queue(msb->queue);
>         spin_unlock_irqrestore(&msb->q_lock, flags);
> +       blk_mq_start_hw_queues(msb->queue);
>
>         /* Remove the disk */
>         del_gendisk(msb->disk);
> +       blk_mq_free_tag_set(msb->queue->tag_set);
>         blk_cleanup_queue(msb->queue);
>         msb->queue = NULL;
>
> diff --git a/drivers/memstick/core/ms_block.h b/drivers/memstick/core/ms_block.h
> index 53962c3b21df..9ba84e0ced63 100644
> --- a/drivers/memstick/core/ms_block.h
> +++ b/drivers/memstick/core/ms_block.h
> @@ -152,6 +152,7 @@ struct msb_data {
>         struct gendisk                  *disk;
>         struct request_queue            *queue;
>         spinlock_t                      q_lock;
> +       struct blk_mq_tag_set           tag_set;
>         struct hd_geometry              geometry;
>         struct attribute_group          attr_group;
>         struct request                  *req;
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq
  2018-10-14  0:48             ` Ed Cashin
@ 2018-10-14 18:44               ` Jens Axboe
  0 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-14 18:44 UTC (permalink / raw)
  To: Ed Cashin, Ed Cashin; +Cc: linux-block

On 10/13/18 6:48 PM, Ed Cashin wrote:
> I reviewed the changes. They looked good.

Thanks Ed!

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 12/17] blk-mq-sched: export way for drivers to insert request
  2018-10-11 16:59 ` [PATCH 12/17] blk-mq-sched: export way for drivers to insert request Jens Axboe
@ 2018-10-14 18:49   ` Christoph Hellwig
  2018-10-14 18:56     ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Christoph Hellwig @ 2018-10-14 18:49 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block

On Thu, Oct 11, 2018 at 10:59:04AM -0600, Jens Axboe wrote:
> We'll need this for the IDE conversion, which queues sense requests.

Why can't the ide code use blk_execute_rq_nowait?

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 12/17] blk-mq-sched: export way for drivers to insert request
  2018-10-14 18:49   ` Christoph Hellwig
@ 2018-10-14 18:56     ` Jens Axboe
  0 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-14 18:56 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-block

On 10/14/18 12:49 PM, Christoph Hellwig wrote:
> On Thu, Oct 11, 2018 at 10:59:04AM -0600, Jens Axboe wrote:
>> We'll need this for the IDE conversion, which queues sense requests.
> 
> Why can't the ide code use blk_execute_rq_nowait?

Yeah it can, I made that change and dropped this patch.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/17] uml: convert ubd to blk-mq
  2018-10-11 16:58 ` [PATCH 07/17] uml: convert ubd " Jens Axboe
@ 2018-10-15 10:27   ` Ming Lei
  2018-10-15 14:16     ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Ming Lei @ 2018-10-15 10:27 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block, Jeff Dike

On Thu, Oct 11, 2018 at 10:58:59AM -0600, Jens Axboe wrote:
> Just a straight forward conversion. The retry handling could
> potentially be done by blk-mq as well, but that's for another
> day.
> 
> Cc: Jeff Dike <jdike@addtoit.com>
> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> ---
>  arch/um/drivers/ubd_kern.c | 154 ++++++++++++++++++++++---------------
>  1 file changed, 94 insertions(+), 60 deletions(-)
> 
> diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
> index 83c470364dfb..a302962a441d 100644
> --- a/arch/um/drivers/ubd_kern.c
> +++ b/arch/um/drivers/ubd_kern.c
> @@ -22,7 +22,7 @@
>  
>  #include <linux/module.h>
>  #include <linux/init.h>
> -#include <linux/blkdev.h>
> +#include <linux/blk-mq.h>
>  #include <linux/ata.h>
>  #include <linux/hdreg.h>
>  #include <linux/cdrom.h>
> @@ -156,6 +156,7 @@ struct ubd {
>  	struct cow cow;
>  	struct platform_device pdev;
>  	struct request_queue *queue;
> +	struct blk_mq_tag_set tag_set;
>  	spinlock_t lock;
>  	struct scatterlist sg[MAX_SG];
>  	struct request *request;
> @@ -436,7 +437,9 @@ __uml_help(udb_setup,
>  "    in the boot output.\n\n"
>  );
>  
> -static void do_ubd_request(struct request_queue * q);
> +static void ubd_handle_request(struct ubd *dev);
> +static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx,
> +				 const struct blk_mq_queue_data *bd);
>  
>  /* Only changed by ubd_init, which is an initcall. */
>  static int thread_fd = -1;
> @@ -520,12 +523,12 @@ static void ubd_handler(void)
>  			return;
>  		}
>  		for (count = 0; count < n/sizeof(struct io_thread_req *); count++) {
> -			blk_end_request(
> -				(*irq_req_buffer)[count]->req,
> -				BLK_STS_OK,
> -				(*irq_req_buffer)[count]->length
> -			);
> -			kfree((*irq_req_buffer)[count]);
> +			struct io_thread_req *io_req = (*irq_req_buffer)[count];
> +
> +			if (!blk_update_request(io_req->req, BLK_STS_OK, io_req->length))
> +				__blk_mq_end_request(io_req->req, BLK_STS_OK);
> +
> +			kfree(io_req);
>  		}
>  	}
>  	reactivate_fd(thread_fd, UBD_IRQ);
> @@ -534,7 +537,7 @@ static void ubd_handler(void)
>  		ubd = container_of(list, struct ubd, restart);
>  		list_del_init(&ubd->restart);
>  		spin_lock_irqsave(&ubd->lock, flags);
> -		do_ubd_request(ubd->queue);
> +		ubd_handle_request(ubd);
>  		spin_unlock_irqrestore(&ubd->lock, flags);
>  	}
>  }
> @@ -856,6 +859,7 @@ static void ubd_device_release(struct device *dev)
>  {
>  	struct ubd *ubd_dev = dev_get_drvdata(dev);
>  
> +	blk_mq_free_tag_set(&ubd_dev->tag_set);
>  	blk_cleanup_queue(ubd_dev->queue);
>  	*ubd_dev = ((struct ubd) DEFAULT_UBD);
>  }
> @@ -897,20 +901,25 @@ static int ubd_disk_register(int major, u64 size, int unit,
>  	return 0;
>  }
>  
> +static const struct blk_mq_ops ubd_mq_ops = {
> +	.queue_rq	= ubd_queue_rq,
> +};
> +
>  #define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9))
>  
>  static int ubd_add(int n, char **error_out)
>  {
>  	struct ubd *ubd_dev = &ubd_devs[n];
> +	struct blk_mq_tag_set *set;
>  	int err = 0;
>  
>  	if(ubd_dev->file == NULL)
> -		goto out;
> +		goto out1;
>  
>  	err = ubd_file_size(ubd_dev, &ubd_dev->size);
>  	if(err < 0){
>  		*error_out = "Couldn't determine size of device's file";
> -		goto out;
> +		goto out1;
>  	}
>  
>  	ubd_dev->size = ROUND_BLOCK(ubd_dev->size);
> @@ -918,12 +927,26 @@ static int ubd_add(int n, char **error_out)
>  	INIT_LIST_HEAD(&ubd_dev->restart);
>  	sg_init_table(ubd_dev->sg, MAX_SG);
>  
> -	err = -ENOMEM;
> -	ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock);
> -	if (ubd_dev->queue == NULL) {
> +	set = &ubd_dev->tag_set;
> +	set->ops = &ubd_mq_ops;
> +	set->nr_hw_queues = 1;
> +	set->queue_depth = 2;
> +	set->numa_node = NUMA_NO_NODE;
> +	set->flags = BLK_MQ_F_SHOULD_MERGE;
> +	err = blk_mq_alloc_tag_set(set);
> +	if (err) {
> +		*error_out = "Failed to initialize device tag set";
> +		goto out1;
> +	}
> +
> +	ubd_dev->queue = blk_mq_init_queue(set);
> +	if (IS_ERR(ubd_dev->queue)) {
> +		err = PTR_ERR(ubd_dev->queue);
> +		ubd_dev->queue = NULL;
>  		*error_out = "Failed to initialize device queue";
>  		goto out;
>  	}
> +
>  	ubd_dev->queue->queuedata = ubd_dev;
>  	blk_queue_write_cache(ubd_dev->queue, true, false);
>  
> @@ -947,9 +970,12 @@ static int ubd_add(int n, char **error_out)
>  
>  	err = 0;
>  out:
> +	blk_mq_free_tag_set(&ubd_dev->tag_set);
> +out1:
>  	return err;
>  
>  out_cleanup:
> +	blk_mq_free_tag_set(&ubd_dev->tag_set);
>  	blk_cleanup_queue(ubd_dev->queue);

blk_mq_free_tag_set() should have been put after blk_cleanup_queue().

-- 
Ming

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/17] sunvdc: convert to blk-mq
  2018-10-11 16:58 ` [PATCH 01/17] sunvdc: convert " Jens Axboe
@ 2018-10-15 10:38   ` Ming Lei
  2018-10-15 14:19     ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Ming Lei @ 2018-10-15 10:38 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block, David Miller

On Thu, Oct 11, 2018 at 10:58:53AM -0600, Jens Axboe wrote:
> Convert from the old request_fn style driver to blk-mq.
> 
> Cc: David Miller <davem@davemloft.net>
> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> ---
>  drivers/block/sunvdc.c | 161 ++++++++++++++++++++++++++++-------------
>  1 file changed, 110 insertions(+), 51 deletions(-)
> 
> diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
> index f68e9baffad7..bf51a2307ce1 100644
> --- a/drivers/block/sunvdc.c
> +++ b/drivers/block/sunvdc.c
> @@ -6,7 +6,7 @@
>  #include <linux/module.h>
>  #include <linux/kernel.h>
>  #include <linux/types.h>
> -#include <linux/blkdev.h>
> +#include <linux/blk-mq.h>
>  #include <linux/hdreg.h>
>  #include <linux/genhd.h>
>  #include <linux/cdrom.h>
> @@ -66,9 +66,10 @@ struct vdc_port {
>  
>  	u64			max_xfer_size;
>  	u32			vdisk_block_size;
> +	u32			drain;
>  
>  	u64			ldc_timeout;
> -	struct timer_list	ldc_reset_timer;
> +	struct delayed_work	ldc_reset_timer_work;
>  	struct work_struct	ldc_reset_work;
>  
>  	/* The server fills these in for us in the disk attribute
> @@ -80,12 +81,14 @@ struct vdc_port {
>  	u8			vdisk_mtype;
>  	u32			vdisk_phys_blksz;
>  
> +	struct blk_mq_tag_set	tag_set;
> +
>  	char			disk_name[32];
>  };
>  
>  static void vdc_ldc_reset(struct vdc_port *port);
>  static void vdc_ldc_reset_work(struct work_struct *work);
> -static void vdc_ldc_reset_timer(struct timer_list *t);
> +static void vdc_ldc_reset_timer_work(struct work_struct *work);
>  
>  static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio)
>  {
> @@ -175,11 +178,8 @@ static void vdc_blk_queue_start(struct vdc_port *port)
>  	 * handshake completes, so check for initial handshake before we've
>  	 * allocated a disk.
>  	 */
> -	if (port->disk && blk_queue_stopped(port->disk->queue) &&
> -	    vdc_tx_dring_avail(dr) * 100 / VDC_TX_RING_SIZE >= 50) {
> -		blk_start_queue(port->disk->queue);
> -	}
> -
> +	if (port->disk && vdc_tx_dring_avail(dr) * 100 / VDC_TX_RING_SIZE >= 50)
> +		blk_mq_start_hw_queues(port->disk->queue);
>  }
>  
>  static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for)
> @@ -197,7 +197,7 @@ static void vdc_handshake_complete(struct vio_driver_state *vio)
>  {
>  	struct vdc_port *port = to_vdc_port(vio);
>  
> -	del_timer(&port->ldc_reset_timer);
> +	cancel_delayed_work(&port->ldc_reset_timer_work);
>  	vdc_finish(vio, 0, WAITING_FOR_LINK_UP);
>  	vdc_blk_queue_start(port);
>  }
> @@ -320,7 +320,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
>  
>  	rqe->req = NULL;
>  
> -	__blk_end_request(req, (desc->status ? BLK_STS_IOERR : 0), desc->size);
> +	blk_mq_end_request(req, desc->status ? BLK_STS_IOERR : 0);

blk_mq_end_request() may trigger BUG in case of partial completion,
however looks it is fine for __blk_end_request().

>  
>  	vdc_blk_queue_start(port);
>  }
> @@ -525,29 +525,40 @@ static int __send_request(struct request *req)
>  	return err;
>  }
>  
> -static void do_vdc_request(struct request_queue *rq)
> +static blk_status_t vdc_queue_rq(struct blk_mq_hw_ctx *hctx,
> +				 const struct blk_mq_queue_data *bd)
>  {
> -	struct request *req;
> +	struct vdc_port *port = hctx->queue->queuedata;
> +	struct vio_dring_state *dr;
> +	unsigned long flags;
>  
> -	while ((req = blk_peek_request(rq)) != NULL) {
> -		struct vdc_port *port;
> -		struct vio_dring_state *dr;
> +	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
>  
> -		port = req->rq_disk->private_data;
> -		dr = &port->vio.drings[VIO_DRIVER_TX_RING];
> -		if (unlikely(vdc_tx_dring_avail(dr) < 1))
> -			goto wait;
> +	blk_mq_start_request(bd->rq);
>  
> -		blk_start_request(req);
> +	spin_lock_irqsave(&port->vio.lock, flags);
>  
> -		if (__send_request(req) < 0) {
> -			blk_requeue_request(rq, req);
> -wait:
> -			/* Avoid pointless unplugs. */
> -			blk_stop_queue(rq);
> -			break;
> -		}
> +	/*
> +	 * Doing drain, just end the request in error
> +	 */
> +	if (unlikely(port->drain)) {
> +		spin_unlock_irqrestore(&port->vio.lock, flags);
> +		return BLK_STS_IOERR;
>  	}
> +
> +	if (unlikely(vdc_tx_dring_avail(dr) < 1)) {
> +		spin_unlock_irqrestore(&port->vio.lock, flags);
> +		blk_mq_stop_hw_queue(hctx);
> +		return BLK_STS_DEV_RESOURCE;
> +	}
> +
> +	if (__send_request(bd->rq) < 0) {
> +		spin_unlock_irqrestore(&port->vio.lock, flags);
> +		return BLK_STS_IOERR;
> +	}
> +
> +	spin_unlock_irqrestore(&port->vio.lock, flags);
> +	return BLK_STS_OK;
>  }
>  
>  static int generic_request(struct vdc_port *port, u8 op, void *buf, int len)
> @@ -759,6 +770,44 @@ static void vdc_port_down(struct vdc_port *port)
>  	vio_ldc_free(&port->vio);
>  }
>  
> +static const struct blk_mq_ops vdc_mq_ops = {
> +	.queue_rq	= vdc_queue_rq,
> +};
> +
> +static void cleanup_queue(struct request_queue *q)
> +{
> +	struct vdc_port *port = q->queuedata;
> +
> +	blk_mq_free_tag_set(&port->tag_set);
> +	blk_cleanup_queue(q);

blk_mq_free_tag_set() need to be put after blk_cleanup_queue().

> +}
> +
> +static struct request_queue *init_queue(struct vdc_port *port)
> +{
> +	struct blk_mq_tag_set *set = &port->tag_set;
> +	struct request_queue *q;
> +	int ret;
> +
> +	set->ops = &vdc_mq_ops;
> +	set->nr_hw_queues = 1;
> +	set->queue_depth = VDC_TX_RING_SIZE;
> +	set->numa_node = NUMA_NO_NODE;
> +	set->flags = BLK_MQ_F_SHOULD_MERGE;
> +
> +	ret = blk_mq_alloc_tag_set(set);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	q = blk_mq_init_queue(set);
> +	if (IS_ERR(q)) {
> +		blk_mq_free_tag_set(set);
> +		return q;
> +	}

Most of conversions have the above pattern, maybe it is easier to
introduce the following block API:

	struct reuqest_queue *blk_mq_alloc_and_init_sq(set, ops, queue_depth)


-- 
Ming

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/17] uml: convert ubd to blk-mq
  2018-10-15 10:27   ` Ming Lei
@ 2018-10-15 14:16     ` Jens Axboe
  0 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-15 14:16 UTC (permalink / raw)
  To: Ming Lei; +Cc: linux-block, Jeff Dike

On 10/15/18 4:27 AM, Ming Lei wrote:
> On Thu, Oct 11, 2018 at 10:58:59AM -0600, Jens Axboe wrote:
>> @@ -947,9 +970,12 @@ static int ubd_add(int n, char **error_out)
>>  
>>  	err = 0;
>>  out:
>> +	blk_mq_free_tag_set(&ubd_dev->tag_set);
>> +out1:
>>  	return err;
>>  
>>  out_cleanup:
>> +	blk_mq_free_tag_set(&ubd_dev->tag_set);
>>  	blk_cleanup_queue(ubd_dev->queue);
> 
> blk_mq_free_tag_set() should have been put after blk_cleanup_queue().

Doesn't matter for this error path, but I do agree in general that
should be the case. I'll fix those up.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/17] sunvdc: convert to blk-mq
  2018-10-15 10:38   ` Ming Lei
@ 2018-10-15 14:19     ` Jens Axboe
  2018-10-15 14:50       ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Jens Axboe @ 2018-10-15 14:19 UTC (permalink / raw)
  To: Ming Lei; +Cc: linux-block, David Miller

On 10/15/18 4:38 AM, Ming Lei wrote:
>> @@ -320,7 +320,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
>>  
>>  	rqe->req = NULL;
>>  
>> -	__blk_end_request(req, (desc->status ? BLK_STS_IOERR : 0), desc->size);
>> +	blk_mq_end_request(req, desc->status ? BLK_STS_IOERR : 0);
> 
> blk_mq_end_request() may trigger BUG in case of partial completion,
> however looks it is fine for __blk_end_request().

True, I'll change this to the blk_update_request() +
__blk_mq_end_request() combo instead.

> Most of conversions have the above pattern, maybe it is easier to
> introduce the following block API:
> 
> 	struct reuqest_queue *blk_mq_alloc_and_init_sq(set, ops, queue_depth)

Yeah I did consider that, I'll make that addition.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/17] sunvdc: convert to blk-mq
  2018-10-15 14:19     ` Jens Axboe
@ 2018-10-15 14:50       ` Jens Axboe
  0 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-15 14:50 UTC (permalink / raw)
  To: Ming Lei; +Cc: linux-block, David Miller

On 10/15/18 8:19 AM, Jens Axboe wrote:
> On 10/15/18 4:38 AM, Ming Lei wrote:
>>> @@ -320,7 +320,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
>>>  
>>>  	rqe->req = NULL;
>>>  
>>> -	__blk_end_request(req, (desc->status ? BLK_STS_IOERR : 0), desc->size);
>>> +	blk_mq_end_request(req, desc->status ? BLK_STS_IOERR : 0);
>>
>> blk_mq_end_request() may trigger BUG in case of partial completion,
>> however looks it is fine for __blk_end_request().
> 
> True, I'll change this to the blk_update_request() +
> __blk_mq_end_request() combo instead.

I take that back, it's correct as is. This isn't a partial completion,
it's completing the request. The BUG() inside blk_mq_end_request() would
indicate a bug in the internal code, we don't expect a not-done return
when we ask to complete the whole thing.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 03/17] ps3disk: convert to blk-mq
  2018-10-13  0:58     ` Jens Axboe
@ 2018-10-15 16:22       ` Geoff Levand
  2018-10-15 16:27         ` Jens Axboe
  0 siblings, 1 reply; 56+ messages in thread
From: Geoff Levand @ 2018-10-15 16:22 UTC (permalink / raw)
  To: Jens Axboe, linux-block; +Cc: Benjamin Herrenschmidt, Geert Uytterhoeven

Hi Jens,

On 10/12/2018 05:58 PM, Jens Axboe wrote:
> On 10/12/18 4:47 PM, Geoff Levand wrote:
>> On 10/11/2018 09:58 AM, Jens Axboe wrote:
>>> Convert from the old request_fn style driver to blk-mq.
>>
>> I tested this on PS3 applied to v4.19-rc7, and on boot it either
>> gets a deadlock message or becomes unstable with various other
>> block related error messages.
>>
>> For what its worth, I put an image of the deadlock message here:
>>
>>   https://storage.googleapis.com/public-tmp-files/blk-deadlock.jpg
> 
> Thanks for testing! Can you try this incremental? It's mostly just
> a cleanup on top, but the last hunk should be the thing that
> hopefully makes this tick again. If you prefer just using a new
> patch, this one is updated:
> 
> http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=5c86f76f45e7c8d5a47a1f20b3e7b93fc945168a

I tested your V2 applied to v4.19-rc8 and it works a little
better, in that the system will now boot up, but the ps3disk
still gets hung up.

I added a '#define DEBUG' to ps3disk.c and saved the dmesg
output with and without the patch here:

  https://storage.googleapis.com/public-tmp-files/dmesg-ok.txt
  https://storage.googleapis.com/public-tmp-files/dmesg-ng.txt

Looking at dmesg-ng.txt, it seems things are going OK, but then
go wrong with a 'tag mismatch':

[    6.068298] ps3disk sb_03: ps3disk_do_request:193
[    6.068318] ps3disk sb_03: ps3disk_submit_request_sg:140: read req has 2 bvecs for 16 sectors
[    6.068339] ps3disk sb_03: ps3disk_submit_request_sg:146: read 16 sectors starting at 256
[    6.074231] ps3disk sb_03: ps3disk_interrupt:239: tag mismatch, got 0, expected 1
[    6.084125] ps3disk sb_03: ps3disk_interrupt:271: read completed
[    6.084147] ps3disk sb_03: ps3disk_scatter_gather:107: bio 0: 16 sectors from 256
[    6.084174] ps3disk sb_03: ps3disk_scatter_gather:107: bio 1: 16 sectors from 256
[    6.084405] ps3disk sb_03: ps3disk_interrupt:252 non-block layer request completed
...
[  242.657694] INFO: task blkid:563 blocked for more than 120 seconds.

Geert is the original author of the PS3 disk support.  Geert,
can you see anything wrong in the patch?

-Geoff

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 03/17] ps3disk: convert to blk-mq
  2018-10-15 16:22       ` Geoff Levand
@ 2018-10-15 16:27         ` Jens Axboe
  2018-10-15 16:47           ` Jens Axboe
  2018-10-15 18:23           ` Geoff Levand
  0 siblings, 2 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-15 16:27 UTC (permalink / raw)
  To: Geoff Levand, linux-block; +Cc: Benjamin Herrenschmidt, Geert Uytterhoeven

On 10/15/18 10:22 AM, Geoff Levand wrote:
> Hi Jens,
> 
> On 10/12/2018 05:58 PM, Jens Axboe wrote:
>> On 10/12/18 4:47 PM, Geoff Levand wrote:
>>> On 10/11/2018 09:58 AM, Jens Axboe wrote:
>>>> Convert from the old request_fn style driver to blk-mq.
>>>
>>> I tested this on PS3 applied to v4.19-rc7, and on boot it either
>>> gets a deadlock message or becomes unstable with various other
>>> block related error messages.
>>>
>>> For what its worth, I put an image of the deadlock message here:
>>>
>>>   https://storage.googleapis.com/public-tmp-files/blk-deadlock.jpg
>>
>> Thanks for testing! Can you try this incremental? It's mostly just
>> a cleanup on top, but the last hunk should be the thing that
>> hopefully makes this tick again. If you prefer just using a new
>> patch, this one is updated:
>>
>> http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=5c86f76f45e7c8d5a47a1f20b3e7b93fc945168a
> 
> I tested your V2 applied to v4.19-rc8 and it works a little
> better, in that the system will now boot up, but the ps3disk
> still gets hung up.
> 
> I added a '#define DEBUG' to ps3disk.c and saved the dmesg
> output with and without the patch here:
> 
>   https://storage.googleapis.com/public-tmp-files/dmesg-ok.txt
>   https://storage.googleapis.com/public-tmp-files/dmesg-ng.txt
> 
> Looking at dmesg-ng.txt, it seems things are going OK, but then
> go wrong with a 'tag mismatch':
> 
> [    6.068298] ps3disk sb_03: ps3disk_do_request:193
> [    6.068318] ps3disk sb_03: ps3disk_submit_request_sg:140: read req has 2 bvecs for 16 sectors
> [    6.068339] ps3disk sb_03: ps3disk_submit_request_sg:146: read 16 sectors starting at 256
> [    6.074231] ps3disk sb_03: ps3disk_interrupt:239: tag mismatch, got 0, expected 1
> [    6.084125] ps3disk sb_03: ps3disk_interrupt:271: read completed
> [    6.084147] ps3disk sb_03: ps3disk_scatter_gather:107: bio 0: 16 sectors from 256
> [    6.084174] ps3disk sb_03: ps3disk_scatter_gather:107: bio 1: 16 sectors from 256
> [    6.084405] ps3disk sb_03: ps3disk_interrupt:252 non-block layer request completed
> ...
> [  242.657694] INFO: task blkid:563 blocked for more than 120 seconds.
> 
> Geert is the original author of the PS3 disk support.  Geert,
> can you see anything wrong in the patch?

Can you try and change the queue depth to 1 instead of 2? It's set in
the tag_set, as ->queue_depth.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 03/17] ps3disk: convert to blk-mq
  2018-10-15 16:27         ` Jens Axboe
@ 2018-10-15 16:47           ` Jens Axboe
  2018-10-15 18:23           ` Geoff Levand
  1 sibling, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-15 16:47 UTC (permalink / raw)
  To: Geoff Levand, linux-block; +Cc: Benjamin Herrenschmidt, Geert Uytterhoeven

On 10/15/18 10:27 AM, Jens Axboe wrote:
> On 10/15/18 10:22 AM, Geoff Levand wrote:
>> Hi Jens,
>>
>> On 10/12/2018 05:58 PM, Jens Axboe wrote:
>>> On 10/12/18 4:47 PM, Geoff Levand wrote:
>>>> On 10/11/2018 09:58 AM, Jens Axboe wrote:
>>>>> Convert from the old request_fn style driver to blk-mq.
>>>>
>>>> I tested this on PS3 applied to v4.19-rc7, and on boot it either
>>>> gets a deadlock message or becomes unstable with various other
>>>> block related error messages.
>>>>
>>>> For what its worth, I put an image of the deadlock message here:
>>>>
>>>>   https://storage.googleapis.com/public-tmp-files/blk-deadlock.jpg
>>>
>>> Thanks for testing! Can you try this incremental? It's mostly just
>>> a cleanup on top, but the last hunk should be the thing that
>>> hopefully makes this tick again. If you prefer just using a new
>>> patch, this one is updated:
>>>
>>> http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=5c86f76f45e7c8d5a47a1f20b3e7b93fc945168a
>>
>> I tested your V2 applied to v4.19-rc8 and it works a little
>> better, in that the system will now boot up, but the ps3disk
>> still gets hung up.
>>
>> I added a '#define DEBUG' to ps3disk.c and saved the dmesg
>> output with and without the patch here:
>>
>>   https://storage.googleapis.com/public-tmp-files/dmesg-ok.txt
>>   https://storage.googleapis.com/public-tmp-files/dmesg-ng.txt
>>
>> Looking at dmesg-ng.txt, it seems things are going OK, but then
>> go wrong with a 'tag mismatch':
>>
>> [    6.068298] ps3disk sb_03: ps3disk_do_request:193
>> [    6.068318] ps3disk sb_03: ps3disk_submit_request_sg:140: read req has 2 bvecs for 16 sectors
>> [    6.068339] ps3disk sb_03: ps3disk_submit_request_sg:146: read 16 sectors starting at 256
>> [    6.074231] ps3disk sb_03: ps3disk_interrupt:239: tag mismatch, got 0, expected 1
>> [    6.084125] ps3disk sb_03: ps3disk_interrupt:271: read completed
>> [    6.084147] ps3disk sb_03: ps3disk_scatter_gather:107: bio 0: 16 sectors from 256
>> [    6.084174] ps3disk sb_03: ps3disk_scatter_gather:107: bio 1: 16 sectors from 256
>> [    6.084405] ps3disk sb_03: ps3disk_interrupt:252 non-block layer request completed
>> ...
>> [  242.657694] INFO: task blkid:563 blocked for more than 120 seconds.
>>
>> Geert is the original author of the PS3 disk support.  Geert,
>> can you see anything wrong in the patch?
> 
> Can you try and change the queue depth to 1 instead of 2? It's set in
> the tag_set, as ->queue_depth.

I took a closer look at it, and I think that's it. The driver doesn't
support any queueing, so we must limit the depth to 1. Either artificially
like it did before, or just by setting the depth to 1. The latter is cleaner
imho. If you make the above mentioned edit, changing the 2 to a 1, it should
work.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 03/17] ps3disk: convert to blk-mq
  2018-10-15 16:27         ` Jens Axboe
  2018-10-15 16:47           ` Jens Axboe
@ 2018-10-15 18:23           ` Geoff Levand
  2018-10-15 18:38             ` Jens Axboe
  1 sibling, 1 reply; 56+ messages in thread
From: Geoff Levand @ 2018-10-15 18:23 UTC (permalink / raw)
  To: Jens Axboe, linux-block; +Cc: Benjamin Herrenschmidt, Geert Uytterhoeven

Hi Jens,

On 10/15/2018 09:27 AM, Jens Axboe wrote:> Can you try and change the queue depth to 1 instead of 2? It's set in> the tag_set, as ->queue_depth.

With this change:

-       set->queue_depth = 2;
+       set->queue_depth = 1;

Something is still wrong.  It can sometimes boot, sometimes udevd hangs
up on /sbin/blkid.  If it boots I can sometimes mount a ps3disk
partition, but then cat or echo to a file will hang.  Other times the
mount command will hang. I saw this error appear in the system log:

Oct 15 10:51:47 ps3 kernel: jbd2/ps3da2-8   D    0  2463      2 0x00000800
Oct 15 10:51:47 ps3 kernel: Call Trace:
Oct 15 10:51:47 ps3 kernel: [c00000000d3c36b0] [c00000000d3c3750] 0xc00000000d3c3750 (unreliable)
Oct 15 10:51:47 ps3 kernel: [c00000000d3c3880] [c0000000000152d0] .__switch_to+0x290/0x300
Oct 15 10:51:47 ps3 kernel: [c00000000d3c3930] [c000000000571d3c] .__schedule+0x904/0x958
Oct 15 10:51:47 ps3 kernel: [c00000000d3c3a10] [c000000000571e0c] .schedule+0x7c/0x90
Oct 15 10:51:47 ps3 kernel: [c00000000d3c3a90] [c0000000002553c4] .jbd2_journal_commit_transaction+0xb84/0x1f68
Oct 15 10:51:47 ps3 kernel: [c00000000d3c3ca0] [c00000000025ad94] .kjournald2+0xc8/0x230
Oct 15 10:51:47 ps3 kernel: [c00000000d3c3d70] [c0000000000713c4] .kthread+0x14c/0x154
Oct 15 10:51:47 ps3 kernel: [c00000000d3c3e30] [c00000000000a83c] .ret_from_kernel_thread+0x58/0x7c
Oct 15 10:51:47 ps3 kernel: ext4lazyinit    D    0  2465      2 0x00000800
Oct 15 10:51:47 ps3 kernel: Call Trace:
Oct 15 10:51:47 ps3 kernel: [c00000000a12f130] [c00000000a12f1b0] 0xc00000000a12f1b0 (unreliable)
Oct 15 10:51:47 ps3 kernel: [c00000000a12f300] [c0000000000152d0] .__switch_to+0x290/0x300
Oct 15 10:51:47 ps3 kernel: [c00000000a12f3b0] [c000000000571d3c] .__schedule+0x904/0x958
Oct 15 10:51:47 ps3 kernel: [c00000000a12f490] [c000000000571e0c] .schedule+0x7c/0x90
Oct 15 10:51:47 ps3 kernel: [c00000000a12f510] [c00000000007e1b0] .io_schedule+0x1c/0x34
Oct 15 10:51:47 ps3 kernel: [c00000000a12f590] [c0000000002fbc60] .blk_mq_get_tag+0x180/0x2a0
Oct 15 10:51:47 ps3 kernel: [c00000000a12f660] [c0000000002f59c0] .blk_mq_get_request+0x230/0x4c4
Oct 15 10:51:47 ps3 kernel: [c00000000a12f700] [c0000000002f88b8] .blk_mq_make_request+0x1c0/0x6ec
Oct 15 10:51:47 ps3 kernel: [c00000000a12f7f0] [c0000000002e9b10] .generic_make_request+0x3a0/0x450
Oct 15 10:51:47 ps3 kernel: [c00000000a12f8b0] [c0000000002e9c08] .submit_bio+0x48/0x148
Oct 15 10:51:47 ps3 kernel: [c00000000a12f970] [c0000000002f49e0] .next_bio+0x50/0x60
Oct 15 10:51:47 ps3 kernel: [c00000000a12f9f0] [c0000000002f5074] .__blkdev_issue_zero_pages+0xa4/0x168
Oct 15 10:51:47 ps3 kernel: [c00000000a12fac0] [c0000000002f5360] .blkdev_issue_zeroout+0x168/0x16c
Oct 15 10:51:47 ps3 kernel: [c00000000a12fbb0] [c00000000020edb8] .ext4_init_inode_table+0x230/0x34c
Oct 15 10:51:47 ps3 kernel: [c00000000a12fc90] [c000000000242c30] .ext4_lazyinit_thread+0x21c/0x2f8
Oct 15 10:51:47 ps3 kernel: [c00000000a12fd70] [c0000000000713c4] .kthread+0x14c/0x154
Oct 15 10:51:47 ps3 kernel: [c00000000a12fe30] [c00000000000a83c] .ret_from_kernel_thread+0x58/0x7c
Oct 15 10:51:47 ps3 kernel: kworker/u4:11   D    0  2478      2 0x00000800
Oct 15 10:51:47 ps3 kernel: Workqueue: writeback .wb_workfn (flush-254:0)
Oct 15 10:51:47 ps3 kernel: Call Trace:
Oct 15 10:51:47 ps3 kernel: [c00000000d5928f0] [c00000000d592990] 0xc00000000d592990 (unreliable)
Oct 15 10:51:47 ps3 kernel: [c00000000d592ac0] [c0000000000152d0] .__switch_to+0x290/0x300
Oct 15 10:51:47 ps3 kernel: [c00000000d592b70] [c000000000571d3c] .__schedule+0x904/0x958
Oct 15 10:51:47 ps3 kernel: [c00000000d592c50] [c000000000571e0c] .schedule+0x7c/0x90
Oct 15 10:51:47 ps3 kernel: [c00000000d592cd0] [c00000000007e1b0] .io_schedule+0x1c/0x34
Oct 15 10:51:47 ps3 kernel: [c00000000d592d50] [c0000000002fbc60] .blk_mq_get_tag+0x180/0x2a0
Oct 15 10:51:47 ps3 kernel: [c00000000d592e20] [c0000000002f59c0] .blk_mq_get_request+0x230/0x4c4
Oct 15 10:51:47 ps3 kernel: [c00000000d592ec0] [c0000000002f88b8] .blk_mq_make_request+0x1c0/0x6ec
Oct 15 10:51:47 ps3 kernel: [c00000000d592fb0] [c0000000002e9b10] .generic_make_request+0x3a0/0x450
Oct 15 10:51:47 ps3 kernel: [c00000000d593070] [c0000000002e9c08] .submit_bio+0x48/0x148
Oct 15 10:51:47 ps3 kernel: [c00000000d593130] [c0000000001aa2f8] .submit_bh_wbc.isra.9+0x198/0x1a8
Oct 15 10:51:47 ps3 kernel: [c00000000d5931d0] [c0000000001aa594] .__block_write_full_page+0x28c/0x430
Oct 15 10:51:47 ps3 kernel: [c00000000d5932c0] [c0000000001adc1c] .blkdev_writepage+0x1c/0x30
Oct 15 10:51:47 ps3 kernel: [c00000000d593330] [c000000000118fbc] .__writepage+0x34/0x80
Oct 15 10:51:47 ps3 kernel: [c00000000d5933b0] [c000000000118920] .write_cache_pages+0x39c/0x47c
Oct 15 10:51:47 ps3 kernel: [c00000000d593550] [c000000000118a54] .generic_writepages+0x54/0x70
Oct 15 10:51:47 ps3 kernel: [c00000000d593600] [c0000000001adbbc] .blkdev_writepages+0x10/0x24
Oct 15 10:51:47 ps3 kernel: [c00000000d593670] [c00000000011ab80] .do_writepages+0x54/0xa0
Oct 15 10:51:47 ps3 kernel: [c00000000d5936f0] [c00000000019d84c] .__writeback_single_inode+0x104/0x698
Oct 15 10:51:47 ps3 kernel: [c00000000d5937b0] [c00000000019e0b8] .writeback_sb_inodes+0x2d8/0x480
Oct 15 10:51:47 ps3 kernel: [c00000000d5938e0] [c00000000019e2d4] .__writeback_inodes_wb+0x74/0xb0
Oct 15 10:51:47 ps3 kernel: [c00000000d593990] [c00000000019e7b8] .wb_writeback+0x3f8/0x464
Oct 15 10:51:47 ps3 kernel: [c00000000d593ab0] [c00000000019f388] .wb_workfn+0x43c/0x5ac
Oct 15 10:51:47 ps3 kernel: [c00000000d593be0] [c00000000006aae0] .process_one_work+0x30c/0x588
Oct 15 10:51:47 ps3 kernel: [c00000000d593cb0] [c00000000006b2b4] .worker_thread+0x294/0x33c
Oct 15 10:51:47 ps3 kernel: [c00000000d593d70] [c0000000000713c4] .kthread+0x14c/0x154
Oct 15 10:51:47 ps3 kernel: [c00000000d593e30] [c00000000000a83c] .ret_from_kernel_thread+0x58/0x7c
Oct 15 10:51:47 ps3 kernel: cat             D    0  2481      1 0x00000012
Oct 15 10:51:47 ps3 kernel: Call Trace:
Oct 15 10:51:47 ps3 kernel: [c00000000b6a3130] [c00000000b6a31d0] 0xc00000000b6a31d0 (unreliable)
Oct 15 10:51:47 ps3 kernel: [c00000000b6a3300] [c0000000000152d0] .__switch_to+0x290/0x300
Oct 15 10:51:47 ps3 kernel: [c00000000b6a33b0] [c000000000571d3c] .__schedule+0x904/0x958
Oct 15 10:51:47 ps3 kernel: [c00000000b6a3490] [c000000000571e0c] .schedule+0x7c/0x90
Oct 15 10:51:47 ps3 kernel: [c00000000b6a3510] [c000000000250dac] .wait_transaction_locked+0xd8/0xf4
Oct 15 10:51:47 ps3 kernel: [c00000000b6a35d0] [c000000000250e3c] .add_transaction_credits+0x2c/0x370
Oct 15 10:51:47 ps3 kernel: [c00000000b6a36a0] [c0000000002519a0] .start_this_handle+0x2f0/0x3bc
Oct 15 10:51:47 ps3 kernel: [c00000000b6a37d0] [c000000000251b5c] .jbd2__journal_start+0xf0/0x27c
Oct 15 10:51:47 ps3 kernel: [c00000000b6a3890] [c0000000001fd828] .__ext4_journal_start_sb+0x1b4/0x1ec
Oct 15 10:51:47 ps3 kernel: [c00000000b6a3950] [c000000000209b90] .ext4_file_open+0xc8/0x1c8
Oct 15 10:51:47 ps3 kernel: [c00000000b6a3a50] [c000000000167b18] .do_dentry_open+0x2a0/0x380
Oct 15 10:51:47 ps3 kernel: [c00000000b6a3af0] [c00000000017c7b0] .path_openat+0x4a4/0x904
Oct 15 10:51:47 ps3 kernel: [c00000000b6a3bf0] [c00000000017cc50] .do_filp_open+0x40/0x88
Oct 15 10:51:47 ps3 kernel: [c00000000b6a3d60] [c000000000169074] .do_sys_open+0x13c/0x228
Oct 15 10:51:47 ps3 kernel: [c00000000b6a3e30] [c00000000000a4a4] system_call+0x5c/0x70
Oct 15 10:51:47 ps3 kernel: 
Oct 15 10:51:47 ps3 kernel: Showing all locks held in the system:
Oct 15 10:51:47 ps3 kernel: 1 lock held by khungtaskd/148:
Oct 15 10:51:47 ps3 kernel: #0: 000000003bcb2a3a (rcu_read_lock){....}, at: .debug_show_all_locks+0x38/0x1ac
Oct 15 10:51:47 ps3 kernel: 2 locks held by ps3fb/301:
Oct 15 10:51:47 ps3 kernel: 1 lock held by in:imklog/1779:
Oct 15 10:51:47 ps3 kernel: #0: 00000000713da15f (&f->f_pos_lock){+.+.}, at: .__fdget_pos+0x48/0x58
Oct 15 10:51:47 ps3 kernel: 2 locks held by getty/2404:
Oct 15 10:51:47 ps3 kernel: #0: 00000000ced8d07b (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54
Oct 15 10:51:47 ps3 kernel: #1: 00000000fd462e7d (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724
Oct 15 10:51:47 ps3 kernel: 2 locks held by getty/2405:
Oct 15 10:51:47 ps3 kernel: #0: 000000009e9dff48 (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54
Oct 15 10:51:47 ps3 kernel: #1: 0000000098475abc (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724
Oct 15 10:51:47 ps3 kernel: 2 locks held by getty/2406:
Oct 15 10:51:47 ps3 kernel: #0: 00000000f060a6f0 (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54
Oct 15 10:51:47 ps3 kernel: #1: 00000000efce01c3 (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724
Oct 15 10:51:47 ps3 kernel: 2 locks held by getty/2407:
Oct 15 10:51:47 ps3 kernel: #0: 00000000935f3792 (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54
Oct 15 10:51:47 ps3 kernel: #1: 00000000efa3bee7 (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724
Oct 15 10:51:47 ps3 kernel: 2 locks held by getty/2408:
Oct 15 10:51:47 ps3 kernel: #0: 00000000111a56ee (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54
Oct 15 10:51:47 ps3 kernel: #1: 00000000f219e2ab (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724
Oct 15 10:51:47 ps3 kernel: 2 locks held by getty/2409:
Oct 15 10:51:47 ps3 kernel: #0: 0000000045df3048 (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54
Oct 15 10:51:47 ps3 kernel: #1: 00000000deede503 (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724
Oct 15 10:51:47 ps3 kernel: 4 locks held by ext4lazyinit/2465:
Oct 15 10:51:47 ps3 kernel: #0: 000000001603d342 (&type->s_umount_key#26){.+.+}, at: .ext4_lazyinit_thread+0x12c/0x2f8
Oct 15 10:51:47 ps3 kernel: #1: 00000000c857701f (sb_writers#10){.+.+}, at: .ext4_lazyinit_thread+0x14c/0x2f8
Oct 15 10:51:47 ps3 kernel: #2: 000000004c766729 (jbd2_handle){++++}, at: .start_this_handle+0x2f8/0x3bc
Oct 15 10:51:47 ps3 kernel: #3: 000000001c56823b (&meta_group_info[i]->alloc_sem){+.+.}, at: .ext4_init_inode_table+0xcc/0x34c
Oct 15 10:51:47 ps3 kernel: 3 locks held by kworker/u4:11/2478:
Oct 15 10:51:47 ps3 kernel: #0: 0000000030f3b24b ((wq_completion)"writeback"){+.+.}, at: .process_one_work+0x1bc/0x588
Oct 15 10:51:47 ps3 kernel: #1: 00000000a1fc5fc0 ((work_completion)(&(&wb->dwork)->work)){+.+.}, at: .process_one_work+0x1bc/0x588
Oct 15 10:51:47 ps3 kernel: #2: 000000007f2fe323 (&type->s_umount_key#27){.+.+}, at: .trylock_super+0x24/0x70
Oct 15 10:51:47 ps3 kernel: 1 lock held by cat/2481:
Oct 15 10:51:47 ps3 kernel: #0: 00000000aa6085f9 (sb_internal){.+.+}, at: .ext4_file_open+0x54/0x1c8
Oct 15 10:51:47 ps3 kernel: 2 locks held by bash/2490:
Oct 15 10:51:47 ps3 kernel: #0: 0000000077655c1f (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54
Oct 15 10:51:47 ps3 kernel: #1: 000000006f4f8843 (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724
Oct 15 10:51:47 ps3 kernel: 2 locks held by touch/2518:
Oct 15 10:51:47 ps3 kernel: #0: 00000000c857701f (sb_writers#10){.+.+}, at: .mnt_want_write+0x28/0x58
Oct 15 10:51:47 ps3 kernel: #1: 00000000957b6825 (&type->i_mutex_dir_key#4){++++}, at: .path_openat+0x308/0x904
Oct 15 10:51:47 ps3 kernel: 
Oct 15 10:51:47 ps3 kernel: =============================================

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 03/17] ps3disk: convert to blk-mq
  2018-10-15 18:23           ` Geoff Levand
@ 2018-10-15 18:38             ` Jens Axboe
  2018-10-15 19:09               ` Jens Axboe
  2018-10-15 19:24               ` Geoff Levand
  0 siblings, 2 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-15 18:38 UTC (permalink / raw)
  To: Geoff Levand, linux-block; +Cc: Benjamin Herrenschmidt, Geert Uytterhoeven

On 10/15/18 12:23 PM, Geoff Levand wrote:
> Hi Jens,
> 
> On 10/15/2018 09:27 AM, Jens Axboe wrote:> Can you try and change the queue depth to 1 instead of 2? It's set in> the tag_set, as ->queue_depth.
> 
> With this change:
> 
> -       set->queue_depth = 2;
> +       set->queue_depth = 1;
> 
> Something is still wrong.  It can sometimes boot, sometimes udevd hangs
> up on /sbin/blkid.  If it boots I can sometimes mount a ps3disk
> partition, but then cat or echo to a file will hang.  Other times the
> mount command will hang. I saw this error appear in the system log:

Weird, it looks like we're waiting for something to complete, and then
we have a few others waiting for queue new IO.

Can you try and move the blk_mq_end_request() inside the priv->lock
section and see if that helps?

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 03/17] ps3disk: convert to blk-mq
  2018-10-15 18:38             ` Jens Axboe
@ 2018-10-15 19:09               ` Jens Axboe
  2018-10-15 19:24               ` Geoff Levand
  1 sibling, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-15 19:09 UTC (permalink / raw)
  To: Geoff Levand, linux-block; +Cc: Benjamin Herrenschmidt, Geert Uytterhoeven

On 10/15/18 12:38 PM, Jens Axboe wrote:
> On 10/15/18 12:23 PM, Geoff Levand wrote:
>> Hi Jens,
>>
>> On 10/15/2018 09:27 AM, Jens Axboe wrote:> Can you try and change the queue depth to 1 instead of 2? It's set in> the tag_set, as ->queue_depth.
>>
>> With this change:
>>
>> -       set->queue_depth = 2;
>> +       set->queue_depth = 1;
>>
>> Something is still wrong.  It can sometimes boot, sometimes udevd hangs
>> up on /sbin/blkid.  If it boots I can sometimes mount a ps3disk
>> partition, but then cat or echo to a file will hang.  Other times the
>> mount command will hang. I saw this error appear in the system log:
> 
> Weird, it looks like we're waiting for something to complete, and then
> we have a few others waiting for queue new IO.
> 
> Can you try and move the blk_mq_end_request() inside the priv->lock
> section and see if that helps?

If that still fails, replace with this version. It's closer to the original
logic.

Thanks for testing!!

diff --git a/block/blk-mq.c b/block/blk-mq.c
index c2ecd64a2403..dcf10e39995a 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -2507,6 +2507,39 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set)
 }
 EXPORT_SYMBOL(blk_mq_init_queue);
 
+/*
+ * Helper for setting up a queue with mq ops, given queue depth, and
+ * the passed in mq ops flags.
+ */
+struct request_queue *blk_mq_init_sq_queue(struct blk_mq_tag_set *set,
+					   const struct blk_mq_ops *ops,
+					   unsigned int queue_depth,
+					   unsigned int set_flags)
+{
+	struct request_queue *q;
+	int ret;
+
+	memset(set, 0, sizeof(*set));
+	set->ops = ops;
+	set->nr_hw_queues = 1;
+	set->queue_depth = queue_depth;
+	set->numa_node = NUMA_NO_NODE;
+	set->flags = set_flags;
+
+	ret = blk_mq_alloc_tag_set(set);
+	if (ret)
+		return ERR_PTR(ret);
+
+	q = blk_mq_init_queue(set);
+	if (IS_ERR(q)) {
+		blk_mq_free_tag_set(set);
+		return q;
+	}
+
+	return q;
+}
+EXPORT_SYMBOL(blk_mq_init_sq_queue);
+
 static int blk_mq_hw_ctx_size(struct blk_mq_tag_set *tag_set)
 {
 	int hw_ctx_size = sizeof(struct blk_mq_hw_ctx);
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 1da59c16f637..2286dc12c6bc 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -203,6 +203,10 @@ enum {
 struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *);
 struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
 						  struct request_queue *q);
+struct request_queue *blk_mq_init_sq_queue(struct blk_mq_tag_set *set,
+						const struct blk_mq_ops *ops,
+						unsigned int queue_depth,
+						unsigned int set_flags);
 int blk_mq_register_dev(struct device *, struct request_queue *);
 void blk_mq_unregister_dev(struct device *, struct request_queue *);
 

diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index 29a4419e8ba3..affc25a431e2 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -19,7 +19,7 @@
  */
 
 #include <linux/ata.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 
@@ -42,6 +42,8 @@
 struct ps3disk_private {
 	spinlock_t lock;		/* Request queue spinlock */
 	struct request_queue *queue;
+	struct blk_mq_tag_set tag_set;
+	struct list_head rq_list;
 	struct gendisk *gendisk;
 	unsigned int blocking_factor;
 	struct request *req;
@@ -118,8 +120,8 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
 	}
 }
 
-static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
-				     struct request *req)
+static blk_status_t ps3disk_submit_request_sg(struct ps3_storage_device *dev,
+					      struct request *req)
 {
 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 	int write = rq_data_dir(req), res;
@@ -158,16 +160,15 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
 	if (res) {
 		dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
 			__LINE__, op, res);
-		__blk_end_request_all(req, BLK_STS_IOERR);
-		return 0;
+		return BLK_STS_IOERR;
 	}
 
 	priv->req = req;
-	return 1;
+	return BLK_STS_OK;
 }
 
-static int ps3disk_submit_flush_request(struct ps3_storage_device *dev,
-					struct request *req)
+static blk_status_t ps3disk_submit_flush_request(struct ps3_storage_device *dev,
+						 struct request *req)
 {
 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 	u64 res;
@@ -180,50 +181,63 @@ static int ps3disk_submit_flush_request(struct ps3_storage_device *dev,
 	if (res) {
 		dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
 			__func__, __LINE__, res);
-		__blk_end_request_all(req, BLK_STS_IOERR);
-		return 0;
+		return BLK_STS_IOERR;
 	}
 
 	priv->req = req;
-	return 1;
+	return BLK_STS_OK;
 }
 
-static void ps3disk_do_request(struct ps3_storage_device *dev,
-			       struct request_queue *q)
+static blk_status_t __ps3disk_do_request(struct ps3_storage_device *dev,
+					 struct request *req)
 {
+	dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
+
+	switch (req_op(req)) {
+	case REQ_OP_FLUSH:
+		return ps3disk_submit_flush_request(dev, req);
+	case REQ_OP_READ:
+	case REQ_OP_WRITE:
+		return ps3disk_submit_request_sg(dev, req);
+	default:
+		blk_dump_rq_flags(req, DEVICE_NAME " bad request");
+		return BLK_STS_IOERR;
+	}
+}
+
+static void ps3disk_do_request(struct ps3_storage_device *dev)
+{
+	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 	struct request *req;
+	blk_status_t ret;
 
-	dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
+	while (!list_empty(&priv->rq_list)) {
+		req = list_first_entry(&priv->rq_list, struct request, queuelist);
+		list_del_init(&req->queuelist);
+		blk_mq_start_request(req);
 
-	while ((req = blk_fetch_request(q))) {
-		switch (req_op(req)) {
-		case REQ_OP_FLUSH:
-			if (ps3disk_submit_flush_request(dev, req))
-				return;
-			break;
-		case REQ_OP_READ:
-		case REQ_OP_WRITE:
-			if (ps3disk_submit_request_sg(dev, req))
-				return;
-			break;
-		default:
-			blk_dump_rq_flags(req, DEVICE_NAME " bad request");
-			__blk_end_request_all(req, BLK_STS_IOERR);
+		ret = __ps3disk_do_request(dev, req);
+		if (ret == BLK_STS_IOERR) {
+			blk_mq_end_request(req, BLK_STS_IOERR);
+			continue;
 		}
+		break;
 	}
 }
 
-static void ps3disk_request(struct request_queue *q)
+static blk_status_t ps3disk_queue_rq(struct blk_mq_hw_ctx *hctx,
+				     const struct blk_mq_queue_data *bd)
 {
-	struct ps3_storage_device *dev = q->queuedata;
+	struct ps3_storage_device *dev = hctx->queue->queuedata;
 	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 
-	if (priv->req) {
-		dev_dbg(&dev->sbd.core, "%s:%u busy\n", __func__, __LINE__);
-		return;
-	}
+	spin_lock_irq(&priv->lock);
+	list_add_tail(&bd->rq->queuelist, &priv->rq_list);
+	if (!priv->req)
+		ps3disk_do_request(dev);
+	spin_unlock_irq(&priv->lock);
 
-	ps3disk_do_request(dev, q);
+	return BLK_STS_OK;
 }
 
 static irqreturn_t ps3disk_interrupt(int irq, void *data)
@@ -280,9 +294,9 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
 	}
 
 	spin_lock(&priv->lock);
-	__blk_end_request_all(req, error);
+	blk_mq_end_request(req, error);
 	priv->req = NULL;
-	ps3disk_do_request(dev, priv->queue);
+	ps3disk_do_request(dev);
 	spin_unlock(&priv->lock);
 
 	return IRQ_HANDLED;
@@ -404,6 +418,10 @@ static unsigned long ps3disk_mask;
 
 static DEFINE_MUTEX(ps3disk_mask_mutex);
 
+static const struct blk_mq_ops ps3disk_mq_ops = {
+	.queue_rq	= ps3disk_queue_rq,
+};
+
 static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 {
 	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
@@ -440,6 +458,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 
 	ps3_system_bus_set_drvdata(_dev, priv);
 	spin_lock_init(&priv->lock);
+	INIT_LIST_HEAD(&priv->rq_list);
 
 	dev->bounce_size = BOUNCE_SIZE;
 	dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA);
@@ -454,11 +473,12 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 
 	ps3disk_identify(dev);
 
-	queue = blk_init_queue(ps3disk_request, &priv->lock);
-	if (!queue) {
-		dev_err(&dev->sbd.core, "%s:%u: blk_init_queue failed\n",
+	queue = blk_mq_init_sq_queue(&priv->tag_set, &ps3disk_mq_ops, 16,
+					BLK_MQ_F_SHOULD_MERGE);
+	if (IS_ERR(queue)) {
+		dev_err(&dev->sbd.core, "%s:%u: blk_mq_init_queue failed\n",
 			__func__, __LINE__);
-		error = -ENOMEM;
+		error = PTR_ERR(queue);
 		goto fail_teardown;
 	}
 
@@ -505,6 +525,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 
 fail_cleanup_queue:
 	blk_cleanup_queue(queue);
+	blk_mq_free_tag_set(&priv->tag_set);
 fail_teardown:
 	ps3stor_teardown(dev);
 fail_free_bounce:
@@ -530,6 +551,7 @@ static int ps3disk_remove(struct ps3_system_bus_device *_dev)
 	mutex_unlock(&ps3disk_mask_mutex);
 	del_gendisk(priv->gendisk);
 	blk_cleanup_queue(priv->queue);
+	blk_mq_free_tag_set(&priv->tag_set);
 	put_disk(priv->gendisk);
 	dev_notice(&dev->sbd.core, "Synchronizing disk cache\n");
 	ps3disk_sync_cache(dev);

-- 
Jens Axboe

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH 03/17] ps3disk: convert to blk-mq
  2018-10-15 18:38             ` Jens Axboe
  2018-10-15 19:09               ` Jens Axboe
@ 2018-10-15 19:24               ` Geoff Levand
  2018-10-15 19:30                 ` Jens Axboe
  1 sibling, 1 reply; 56+ messages in thread
From: Geoff Levand @ 2018-10-15 19:24 UTC (permalink / raw)
  To: Jens Axboe, linux-block; +Cc: Benjamin Herrenschmidt, Geert Uytterhoeven

Hi Jens,

On 10/15/2018 11:38 AM, Jens Axboe wrote:
> Weird, it looks like we're waiting for something to complete, and then
> we have a few others waiting for queue new IO.
> 
> Can you try and move the blk_mq_end_request() inside the priv->lock
> section and see if that helps?

With the change below to your V2 I can't get it to have an
error.  I did mkfs.ext4, some big file downloads, and ran
'fsck.ext3 -c' for a while.

Thanks for working late on it.

-Geoff

--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -274,10 +274,9 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
                        ps3disk_scatter_gather(dev, req, 0);
        }
 
-       blk_mq_end_request(req, error);
-
        spin_lock(&priv->lock);
        priv->req = NULL;
+       blk_mq_end_request(req, error);
        spin_unlock(&priv->lock);
 
        blk_mq_run_hw_queues(priv->queue, true);
@@ -458,7 +457,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
        set = &priv->tag_set;
        set->ops = &ps3disk_mq_ops;
        set->nr_hw_queues = 1;
-       set->queue_depth = 2;
+       set->queue_depth = 1;
        set->numa_node = NUMA_NO_NODE;
        set->flags = BLK_MQ_F_SHOULD_MERGE;
        error = blk_mq_alloc_tag_set(set);

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 03/17] ps3disk: convert to blk-mq
  2018-10-15 19:24               ` Geoff Levand
@ 2018-10-15 19:30                 ` Jens Axboe
  0 siblings, 0 replies; 56+ messages in thread
From: Jens Axboe @ 2018-10-15 19:30 UTC (permalink / raw)
  To: Geoff Levand, linux-block; +Cc: Benjamin Herrenschmidt, Geert Uytterhoeven

On 10/15/18 1:24 PM, Geoff Levand wrote:
> Hi Jens,
> 
> On 10/15/2018 11:38 AM, Jens Axboe wrote:
>> Weird, it looks like we're waiting for something to complete, and then
>> we have a few others waiting for queue new IO.
>>
>> Can you try and move the blk_mq_end_request() inside the priv->lock
>> section and see if that helps?
> 
> With the change below to your V2 I can't get it to have an
> error.  I did mkfs.ext4, some big file downloads, and ran
> 'fsck.ext3 -c' for a while.

OK good, that's better than having to make the bigger change I
just sent out.

> Thanks for working late on it.

Thanks for testing! I'll add your tested-by.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2018-10-16  0:08 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-11 16:58 [PATCHSET 0/17] Convert drivers to blk-mq Jens Axboe
2018-10-11 16:58 ` [PATCH 01/17] sunvdc: convert " Jens Axboe
2018-10-15 10:38   ` Ming Lei
2018-10-15 14:19     ` Jens Axboe
2018-10-15 14:50       ` Jens Axboe
2018-10-11 16:58 ` [PATCH 02/17] sx8: " Jens Axboe
2018-10-11 16:58 ` [PATCH 03/17] ps3disk: " Jens Axboe
2018-10-12 22:47   ` Geoff Levand
2018-10-13  0:58     ` Jens Axboe
2018-10-15 16:22       ` Geoff Levand
2018-10-15 16:27         ` Jens Axboe
2018-10-15 16:47           ` Jens Axboe
2018-10-15 18:23           ` Geoff Levand
2018-10-15 18:38             ` Jens Axboe
2018-10-15 19:09               ` Jens Axboe
2018-10-15 19:24               ` Geoff Levand
2018-10-15 19:30                 ` Jens Axboe
2018-10-11 16:58 ` [PATCH 04/17] paride: convert pcd " Jens Axboe
2018-10-11 16:58 ` [PATCH 05/17] paride: convert pd " Jens Axboe
2018-10-11 16:58 ` [PATCH 06/17] paride: convert pf " Jens Axboe
2018-10-11 16:58 ` [PATCH 07/17] uml: convert ubd " Jens Axboe
2018-10-15 10:27   ` Ming Lei
2018-10-15 14:16     ` Jens Axboe
2018-10-11 16:59 ` [PATCH 08/17] ms_block: convert " Jens Axboe
2018-10-14  6:30   ` Maxim Levitsky
2018-10-11 16:59 ` [PATCH 09/17] mspro_block: " Jens Axboe
2018-10-11 16:59 ` [PATCH 10/17] gdrom: " Jens Axboe
2018-10-11 16:59 ` [PATCH 11/17] z2ram: " Jens Axboe
2018-10-11 16:59 ` [PATCH 12/17] blk-mq-sched: export way for drivers to insert request Jens Axboe
2018-10-14 18:49   ` Christoph Hellwig
2018-10-14 18:56     ` Jens Axboe
2018-10-11 16:59 ` [PATCH 13/17] ide: convert to blk-mq Jens Axboe
2018-10-11 16:59 ` [PATCH 14/17] aoe: convert aoeblk " Jens Axboe
2018-10-12 11:28   ` Ed Cashin
2018-10-12 14:20     ` Jens Axboe
2018-10-12 16:17       ` Ed Cashin
2018-10-12 16:23         ` Jens Axboe
2018-10-12 16:26           ` Ed Cashin
2018-10-14  0:48             ` Ed Cashin
2018-10-14 18:44               ` Jens Axboe
2018-10-11 16:59 ` [PATCH 15/17] xsysace: convert " Jens Axboe
2018-10-12  5:46   ` Michal Simek
2018-10-11 16:59 ` [PATCH 16/17] mtd_blkdevs: " Jens Axboe
2018-10-11 21:03   ` Richard Weinberger
2018-10-11 21:14     ` Jens Axboe
2018-10-11 21:18       ` Richard Weinberger
2018-10-11 21:21         ` Jens Axboe
2018-10-11 21:31           ` Richard Weinberger
2018-10-11 16:59 ` [PATCH 17/17] null_blk: remove legacy IO path Jens Axboe
2018-10-12  6:56   ` Dongli Zhang
2018-10-12  8:51     ` Johannes Thumshirn
2018-10-12 14:18       ` Jens Axboe
2018-10-12 17:24   ` Sébastien Boisvert
2018-10-12 17:30     ` Jens Axboe
2018-10-12 17:37       ` Sébastien Boisvert
2018-10-12 17:50         ` Jens Axboe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.