Convert drivers to blk-mq
Subsystems (7)
Jens Axboe
maintainercover Convert drivers to blk-mq
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.
Signature · 1 line
Jens Axboe
Jens Axboe
maintainerPATCH 1/17 sunvdc: convert to blk-mq
Convert from the old request_fn style driver to blk-mq.
--- drivers/block/sunvdc.c | 161 ++++++++++++++++++++++++++++------------- 1 file changed, 110 insertions(+), 51 deletions(-)
drivers/block/sunvdc.c +110 -51
@@ -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 ;
Signature · 1 line
2.17.1
Re: [PATCH 01/17] sunvdc: convert to blk-mq
Quoted 73 lines · Jens Axboe
Convert from the old
request_fnstyle driver to blk-mq.Cc David Miller <[email protected]>Signed-off-by Jens Axboe <[email protected]>--- drivers/block/sunvdc.c | 161 ++++++++++++++++++++++++++++------------- 1 file changed, 110 insertions(+), 51 deletions(-)drivers/block/sunvdc.c +9
-9@@ -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); }
drivers/block/sunvdc.c static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, · line 323
Quoted 5 lines
drivers/block/sunvdc.c +1
-1@@ -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().
Quoted 65 lines
drivers/block/sunvdc.c +28
-17vdc_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); }
drivers/block/sunvdc.c static void vdc_port_down(struct vdc_port *port) · line 782
Quoted 10 lines
drivers/block/sunvdc.c +10
-0+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().
Quoted 13 lines
drivers/block/sunvdc.c +13
-0+} + +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 ;
drivers/block/sunvdc.c static void vdc_port_down(struct vdc_port *port) · line 805
Quoted 10 lines
drivers/block/sunvdc.c +10
-0+ + 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)
Signature · 1 line
Ming
Jens Axboe
maintainerRe: [PATCH 01/17] sunvdc: convert to blk-mq
Quoted 9 lines · Ming Lei
drivers/block/sunvdc.c static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, · line 323
Quoted 6 lines
drivers/block/sunvdc.c +1
-1@@ -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.
Quoted 4 lines
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.
Signature · 1 line
Jens Axboe
Jens Axboe
maintainerRe: [PATCH 01/17] sunvdc: convert to blk-mq
Quoted 5 lines · Jens Axboe
Quoted 4 lines · Ming Lei
Quoted 4 lines
drivers/block/sunvdc.c +0
-0@@ -320,7 +320,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, rqe->req =NULL ;
Quoted 8 lines
Quoted 5 lines
drivers/block/sunvdc.c static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, · line 323
Quoted 2 lines
drivers/block/sunvdc.c +1
-1-__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.
Signature · 1 line
Jens Axboe
Jens Axboe
maintainerPATCH 2/17 sx8: convert to blk-mq
In reply to Jens AxboeConvert from the old request_fn style driver to blk-mq.
--- drivers/block/sx8.c | 133 +++++++++++++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 45 deletions(-)
drivers/block/sx8.c +88 -45
@@ -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);
Signature · 1 line
2.17.1
Jens Axboe
maintainerPATCH 3/17 ps3disk: convert to blk-mq
In reply to Jens AxboeConvert from the old request_fn style driver to blk-mq.
--- drivers/block/ps3disk.c | 95 +++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 41 deletions(-)
drivers/block/ps3disk.c +54 -41
@@ -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);
Signature · 1 line
2.17.1
Geoff Levand
maintainerRe: [PATCH 03/17] ps3disk: convert to blk-mq
Hi Jens,
Quoted 1 line · Jens Axboe
Convert from the old
request_fnstyle 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
Jens Axboe
maintainerRe: [PATCH 03/17] ps3disk: convert to blk-mq
Quoted 5 lines · Geoff Levand
Hi Jens,
Quoted 1 line · Jens Axboe
Convert from the old
request_fnstyle driver to blk-mq.
Quoted 7 lines
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:
drivers/block/ps3disk.c +17 -18
@@ -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 ; }
Signature · 1 line
Jens Axboe
Geoff Levand
maintainerRe: [PATCH 03/17] ps3disk: convert to blk-mq
Hi Jens,
Quoted 10 lines · Jens Axboe
Quoted 9 lines · Geoff Levand
Quoted 1 line · Jens Axboe
Convert from the old
request_fnstyle 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:
Quoted 8 lines
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:
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
Jens Axboe
maintainerRe: [PATCH 03/17] ps3disk: convert to blk-mq
Quoted 46 lines · Geoff Levand
Hi Jens,
Quoted 10 lines · Jens Axboe
Quoted 9 lines · Geoff Levand
Quoted 1 line · Jens Axboe
Convert from the old
request_fnstyle 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:
Quoted 8 lines
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:
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.cand 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.txtLooking 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.
Quoted 2 lines
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.
Signature · 1 line
Jens Axboe
Jens Axboe
maintainerRe: [PATCH 03/17] ps3disk: convert to blk-mq
Quoted 47 lines · Jens Axboe
Quoted 46 lines · Geoff Levand
Hi Jens,
Quoted 10 lines · Jens Axboe
Quoted 9 lines · Geoff Levand
Quoted 1 line · Jens Axboe
Convert from the old
request_fnstyle 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:
Quoted 8 lines
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:
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.cand 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.txtLooking 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.
Quoted 5 lines
Quoted 2 lines
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.
Signature · 1 line
Jens Axboe
Geoff Levand
maintainerRe: [PATCH 03/17] ps3disk: convert to blk-mq
In reply to Jens AxboeHi 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: =============================================Jens Axboe
maintainerRe: [PATCH 03/17] ps3disk: convert to blk-mq
Quoted 9 lines · Geoff Levand
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:
(quoted diff) +1
-1- set->queue_depth = 2; + set->queue_depth = 1;
Quoted 4 lines
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?
Signature · 1 line
Jens Axboe
Jens Axboe
maintainerRe: [PATCH 03/17] ps3disk: convert to blk-mq
Quoted 15 lines · Jens Axboe
Quoted 9 lines · Geoff Levand
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:
(quoted diff) +1
-1- set->queue_depth = 2; + set->queue_depth = 1;Quoted 4 lines
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:
Quoted 5 lines
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 thepriv->locksection and see if that helps?
If that still fails, replace with this version. It's closer to the original logic.
Thanks for testing!!
block/blk-mq.c +33 -0
@@ -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 );
include/linux/blk-mq.h +4 -0
@@ -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 *);
drivers/block/ps3disk.c +63 -41
194 lines not on this page · raw message
Signature · 1 line
Jens Axboe
Geoff Levand
maintainerRe: [PATCH 03/17] ps3disk: convert to blk-mq
In reply to Jens AxboeHi Jens,
Quoted 5 lines · Jens Axboe
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 thepriv->locksection 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
drivers/block/ps3disk.c +2 -3
@@ -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);
Jens Axboe
maintainerRe: [PATCH 03/17] ps3disk: convert to blk-mq
Quoted 6 lines · Geoff Levand
Hi Jens,
Quoted 3 lines · Jens Axboe
Weird, it looks like we're waiting for something to complete, and then we have a few others waiting for queue new IO.
Quoted 6 lines
Quoted 2 lines
Can you try and move the
blk_mq_end_request()inside thepriv->locksection 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.
Quoted 1 line
Thanks for working late on it.
Thanks for testing! I'll add your tested-by.
Signature · 1 line
Jens Axboe
Jens Axboe
maintainerPATCH 4/17 paride: convert pcd to blk-mq
In reply to Jens Axboe--- drivers/block/paride/pcd.c | 98 +++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 32 deletions(-)
drivers/block/paride/pcd.c +66 -32
@@ -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); }
Signature · 1 line
2.17.1
Jens Axboe
maintainerPATCH 5/17 paride: convert pd to blk-mq
In reply to Jens Axboe--- drivers/block/paride/pd.c | 109 ++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 47 deletions(-)
drivers/block/paride/pd.c +62 -47
@@ -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);
Signature · 1 line
2.17.1
Jens Axboe
maintainerPATCH 6/17 paride: convert pf to blk-mq
In reply to Jens Axboe--- drivers/block/paride/pf.c | 68 +++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 14 deletions(-)
drivers/block/paride/pf.c +54 -14
@@ -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 0x2astatic 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);
Signature · 1 line
2.17.1
Jens Axboe
maintainerPATCH 7/17 uml: convert ubd to blk-mq
In reply to Jens AxboeJust a straight forward conversion. The retry handling could potentially be done by blk-mq as well, but that's for another day.
--- arch/um/drivers/ubd_kern.c | 154 ++++++++++++++++++++++--------------- 1 file changed, 94 insertions(+), 60 deletions(-)
arch/um/drivers/ubd_kern.c +94 -60
@@ -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)
Signature · 1 line
2.17.1
Re: [PATCH 07/17] uml: convert ubd to blk-mq
Quoted 137 lines · Jens Axboe
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 <[email protected]>Signed-off-by Jens Axboe <[email protected]>--- arch/um/drivers/ubd_kern.c | 154 ++++++++++++++++++++++--------------- 1 file changed, 94 insertions(+), 60 deletions(-)arch/um/drivers/ubd_kern.c +37
-14@@ -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);
arch/um/drivers/ubd_kern.c static int ubd_add(int n, char **error_out) · line 979
Quoted 10 lines
arch/um/drivers/ubd_kern.c +3
-0@@ -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().
Signature · 1 line
Ming
Jens Axboe
maintainerRe: [PATCH 07/17] uml: convert ubd to blk-mq
Quoted 9 lines · Ming Lei
Quoted 8 lines · Jens Axboe
arch/um/drivers/ubd_kern.c +2
-0@@ -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;
Quoted 5 lines
arch/um/drivers/ubd_kern.c static int ubd_add(int n, char **error_out) · line 979
Quoted 3 lines
arch/um/drivers/ubd_kern.c +1
-0out_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 afterblk_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.
Signature · 1 line
Jens Axboe
Jens Axboe
maintainerPATCH 8/17 ms_block: convert to blk-mq
In reply to Jens AxboeStraight 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.
--- drivers/memstick/core/ms_block.c | 121 ++++++++++++++++++------------- drivers/memstick/core/ms_block.h | 1 + 2 files changed, 73 insertions(+), 49 deletions(-)
drivers/memstick/core/ms_block.c +72 -49
@@ -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 ;
drivers/memstick/core/ms_block.h +1 -0
@@ -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;
Signature · 1 line
2.17.1
Maxim Levitsky
maintainerRe: [PATCH 08/17] ms_block: convert to blk-mq
Hi!
I haven't yet had a chance to test this patch but I will do during this week. Thanks!
Best regards,
Maxim Levitsky
Quoted 285 lines · Jens Axboe
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 <[email protected]>Signed-off-by Jens Axboe <[email protected]>--- drivers/memstick/core/ms_block.c | 121 ++++++++++++++++++------------- drivers/memstick/core/ms_block.h | 1 + 2 files changed, 73 insertions(+), 49 deletions(-)drivers/memstick/core/ms_block.c +72
-49@@ -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 ;drivers/memstick/core/ms_block.h +1
-1@@ -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
Jens Axboe
maintainerPATCH 9/17 mspro_block: convert to blk-mq
In reply to Jens AxboeStraight forward conversion, there's room for improvement.
--- drivers/memstick/core/mspro_block.c | 133 ++++++++++++++++------------ 1 file changed, 78 insertions(+), 55 deletions(-)
drivers/memstick/core/mspro_block.c +78 -55
@@ -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; }
Signature · 1 line
2.17.1
Jens Axboe
maintainerPATCH 10/17 gdrom: convert to blk-mq
In reply to Jens AxboeDitch the deffered list, lock, and workqueue handling. Just mark the set as being blocking, so we are invoked from a workqueue already.
--- drivers/cdrom/gdrom.c | 182 ++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 95 deletions(-)
drivers/cdrom/gdrom.c +87 -95
@@ -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);
Signature · 1 line
2.17.1
Jens Axboe
maintainerPATCH 11/17 z2ram: convert to blk-mq
In reply to Jens AxboeStraight forward conversion to blk-mq, nothing special about this driver.
--- drivers/block/z2ram.c | 96 ++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 38 deletions(-)
drivers/block/z2ram.c +58 -38
@@ -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 )
Signature · 1 line
2.17.1
Jens Axboe
maintainerPATCH 12/17 blk-mq-sched: export way for drivers to insert request
In reply to Jens AxboeWe'll need this for the IDE conversion, which queues sense requests.
--- 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(-)
block/blk-mq-sched.c +1 -0
@@ -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,
block/blk-mq-sched.h +0 -2
@@ -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);
include/linux/blk-mq.h +2 -0
@@ -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);
Signature · 1 line
2.17.1
Re: [PATCH 12/17] blk-mq-sched: export way for drivers to insert request
Quoted 1 line · Jens Axboe
We'll need this for the IDE conversion, which queues sense requests.
Why can't the ide code use blk_execute_rq_nowait?
Jens Axboe
maintainerRe: [PATCH 12/17] blk-mq-sched: export way for drivers to insert request
Quoted 4 lines · Christoph Hellwig
Quoted 1 line · Jens Axboe
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.
Signature · 1 line
Jens Axboe
Jens Axboe
maintainerPATCH 13/17 ide: convert to blk-mq
In reply to Jens Axboeide-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.
--- 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(-)
drivers/ide/ide-atapi.c +17 -8
@@ -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);
drivers/ide/ide-cd.c +94 -81
227 lines not on this page · raw message
drivers/ide/ide-disk.c +5 -3
@@ -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; } }
drivers/ide/ide-io.c +41 -43
154 lines not on this page · raw message
drivers/ide/ide-park.c +1 -1
@@ -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 ;
drivers/ide/ide-pm.c +5 -21
@@ -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); } }
drivers/ide/ide-probe.c +25 -18
98 lines not on this page · raw message
include/linux/ide.h +6 -2
@@ -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 *);
Signature · 1 line
2.17.1
Jens Axboe
maintainerPATCH 14/17 aoe: convert aoeblk to blk-mq
In reply to Jens AxboeStraight forward conversion - instead of rewriting the internal buffer retrieval logic, just replace the previous elevator peeking with an internal list of requests.
--- 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(-)
drivers/block/aoe/aoe.h +4 -0
@@ -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;
drivers/block/aoe/aoeblk.c +36 -13
91 lines not on this page · raw message
drivers/block/aoe/aoecmd.c +12 -5
@@ -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
drivers/block/aoe/aoedev.c +8 -6
@@ -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 ;
Signature · 1 line
2.17.1
Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq
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.
Quoted 244 lines · Jens Axboe
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" <[email protected]>Signed-off-by Jens Axboe <[email protected]>--- 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(-)drivers/block/aoe/aoe.h +4
-0@@ -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;drivers/block/aoe/aoeblk.c +36
-13@@ -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; }drivers/block/aoe/aoecmd.c +12
-5@@ -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 voiddrivers/block/aoe/aoedev.c +8
-7@@ -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
Signature · 1 line
Ed Cashin <[email protected]>
Jens Axboe
maintainerRe: [PATCH 14/17] aoe: convert aoeblk to blk-mq
Quoted 3 lines · Ed 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.
There's really no way around it, since I'm embedding the tag_set in the device.
Is that OK with you?
Signature · 1 line
Jens Axboe
Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq
Quoted 10 lines · Jens Axboe
Quoted 3 lines · Ed 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.
There's really no way around it, since I'm embedding the
tag_setin the device.Is that OK with you?
Yes, it's fine. Thank you.
Jens Axboe
maintainerRe: [PATCH 14/17] aoe: convert aoeblk to blk-mq
Quoted 7 lines · Ed Cashin
Quoted 6 lines · Jens Axboe
Quoted 3 lines · Ed 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.
Quoted 6 lines
Quoted 4 lines
There's really no way around it, since I'm embedding the
tag_setin the device.Is that OK with you?
Yes, it's fine. Thank you.
Can I add a reviewed-by?
Signature · 1 line
Jens Axboe
Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq
Quoted 9 lines · Jens Axboe
Quoted 7 lines · Ed Cashin
Quoted 6 lines · Jens Axboe
Quoted 3 lines · Ed 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.
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
There's really no way around it, since I'm embedding the
tag_setin 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.
Signature · 1 line
Ed
Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq
I reviewed the changes. They looked good.
Quoted 26 lines · Ed Cashin
Quoted 9 lines · Jens Axboe
Quoted 7 lines · Ed Cashin
Quoted 6 lines · Jens Axboe
Quoted 3 lines · Ed 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.
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
There's really no way around it, since I'm embedding the
tag_setin 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
Signature · 1 line
Ed Cashin <[email protected]>
Jens Axboe
maintainerRe: [PATCH 14/17] aoe: convert aoeblk to blk-mq
Quoted 1 line · Ed Cashin
I reviewed the changes. They looked good.
Thanks Ed!
Signature · 1 line
Jens Axboe
Jens Axboe
maintainerPATCH 15/17 xsysace: convert to blk-mq
In reply to Jens AxboeStraight forward conversion, using an internal list to enable the driver to pull requests at will.
--- drivers/block/xsysace.c | 91 ++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 25 deletions(-)
drivers/block/xsysace.c +66 -25
@@ -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);
Signature · 1 line
2.17.1
Re: [PATCH 15/17] xsysace: convert to blk-mq
Quoted 203 lines · Jens Axboe
Straight forward conversion, using an internal list to enable the driver to pull requests at will.
Cc Michal Simek <[email protected]>Signed-off-by Jens Axboe <[email protected]>--- drivers/block/xsysace.c | 91 ++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 25 deletions(-)drivers/block/xsysace.c +63
-24@@ -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);
drivers/block/xsysace.c static void ace_teardown(struct ace_device *ace) · line 1129
Quoted 10 lines
drivers/block/xsysace.c +3
-1} -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
Thanks,
Michal
Jens Axboe
maintainerPATCH 16/17 mtd_blkdevs: convert to blk-mq
In reply to Jens AxboeStraight 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.
--- drivers/mtd/mtd_blkdevs.c | 109 +++++++++++++++++++++++------------ include/linux/mtd/blktrans.h | 5 +- 2 files changed, 74 insertions(+), 40 deletions(-)
drivers/mtd/mtd_blkdevs.c +72 -37
@@ -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);
include/linux/mtd/blktrans.h +2 -3
@@ -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;
Signature · 1 line
2.17.1
Re: [PATCH 16/17] mtd_blkdevs: convert to blk-mq
Jens,
Quoted 7 lines · Jens Axboe
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)
Signature · 2 lines
Thanks, //richard
Jens Axboe
maintainerRe: [PATCH 16/17] mtd_blkdevs: convert to blk-mq
Quoted 4 lines · Richard Weinberger
Jens,
Quoted 1 line · Jens Axboe
Quoted 8 lines
Quoted 6 lines
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?
drivers/mtd/mtd_blkdevs.c +1 -1
@@ -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 ;
Signature · 1 line
Jens Axboe
Richard Weinberger
maintainerRe: [PATCH 16/17] mtd_blkdevs: convert to blk-mq
Jens,
Am Donnerstag, 11. Oktober 2018, 23:14:07 CEST schrieb Jens Axboe:
Quoted 22 lines · Richard Weinberger
Quoted 4 lines
Jens,
Quoted 1 line · Jens Axboe
Quoted 8 lines
Quoted 6 lines
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?
drivers/mtd/mtd_blkdevs.c +0
-0
drivers/mtd/mtd_blkdevs.c static void mtd_blktrans_work(struct mtd_blktrans_dev *dev) · line 191
Quoted 6 lines
drivers/mtd/mtd_blkdevs.c +1
-1@@ -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
Jens Axboe
maintainerRe: [PATCH 16/17] mtd_blkdevs: convert to blk-mq
Quoted 27 lines · Richard Weinberger
Jens,
Am Donnerstag, 11. Oktober 2018, 23:14:07 CEST schrieb Jens Axboe:
Quoted 24 lines · Richard Weinberger
Quoted 4 lines
Jens,
Quoted 1 line · Jens Axboe
Quoted 8 lines
Quoted 6 lines
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?
drivers/mtd/mtd_blkdevs.c +0
-0@@ -187,8 +187,8 @@ static void mtd_blktrans_work(struct mtd_blktrans_dev *dev)mutex_unlock (&dev->lock);
Quoted 7 lines
drivers/mtd/mtd_blkdevs.c static void mtd_blktrans_work(struct mtd_blktrans_dev *dev) · line 191
Quoted 4 lines
drivers/mtd/mtd_blkdevs.c +1
-1if (!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?
Signature · 1 line
Jens Axboe
Richard Weinberger
maintainerRe: [PATCH 16/17] mtd_blkdevs: convert to blk-mq
Am Donnerstag, 11. Oktober 2018, 23:21:56 CEST schrieb Jens Axboe:
Quoted 9 lines
Quoted 7 lines
drivers/mtd/mtd_blkdevs.c static void mtd_blktrans_work(struct mtd_blktrans_dev *dev) · line 191
Quoted 4 lines
drivers/mtd/mtd_blkdevs.c +1
-1if (!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
Jens Axboe
maintainerPATCH 17/17 null_blk: remove legacy IO path
In reply to Jens AxboeWe're planning on removing this code completely, kill the old path.
--- drivers/block/null_blk_main.c | 96 +++-------------------------------- 1 file changed, 6 insertions(+), 90 deletions(-)
drivers/block/null_blk_main.c +6 -90
@@ -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",
Signature · 1 line
2.17.1
Re: [PATCH 17/17] null_blk: remove legacy IO path
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
Quoted 165 lines · Jens Axboe
We're planning on removing this code completely, kill the old path.
Signed-off-by Jens Axboe <[email protected]>--- drivers/block/null_blk_main.c | 96 +++-------------------------------- 1 file changed, 6 insertions(+), 90 deletions(-)drivers/block/null_blk_main.c +6
-90@@ -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",
Re: [PATCH 17/17] null_blk: remove legacy IO path
Quoted 8 lines · Dongli Zhang
Hi Jens,
Will the legacy path be fully deprecated?
In addition to performance measurement,
null_blkis 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
Signature · 6 lines
Johannes Thumshirn SUSE Labs [email protected] +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
Jens Axboe
maintainerRe: [PATCH 17/17] null_blk: remove legacy IO path
Quoted 5 lines · Johannes Thumshirn
Quoted 4 lines · Dongli Zhang
Hi Jens,
Will the legacy path be fully deprecated?
Quoted 8 lines
Quoted 4 lines
In addition to performance measurement,
null_blkis 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.
Signature · 1 line
Jens Axboe
Re: [PATCH 17/17] null_blk: remove legacy IO path
In reply to Jens AxboeHello Jens,
Quoted 154 lines · Jens Axboe
We're planning on removing this code completely, kill the old path.
Signed-off-by Jens Axboe <[email protected]>--- drivers/block/null_blk_main.c | 96 +++-------------------------------- 1 file changed, 6 insertions(+), 90 deletions(-)drivers/block/null_blk_main.c +2
-90@@ -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) {
drivers/block/null_blk_main.c static int __init null_init(void) · line 1783
Quoted 7 lines
drivers/block/null_blk_main.c +4
-0@@ -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-};
Quoted 4 lines
drivers/block/null_blk_main.c +0
-0if (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",
Jens Axboe
maintainerRe: [PATCH 17/17] null_blk: remove legacy IO path
Quoted 6 lines · Sébastien Boisvert
drivers/block/null_blk_main.c static int __init null_init(void) · line 1783
Quoted 4 lines
drivers/block/null_blk_main.c +4
-0+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_RQhas be checked ?
I've since fixed a few more, all should be well now. The updated version is here:
Quoted 6 lines
Since the enum that contains
NULL_Q_RQis indrivers/block/null_blk_main.c, and not in a linux header file, would it be thinkable to removeNULL_Q_RQfrom 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.
Signature · 1 line
Jens Axboe
Sébastien Boisvert
Reviewed-byRe: [PATCH 17/17] null_blk: remove legacy IO path
Quoted 18 lines · Jens Axboe
Quoted 6 lines · Sébastien Boisvert
drivers/block/null_blk_main.c static int __init null_init(void) · line 1783
Quoted 4 lines
drivers/block/null_blk_main.c +4
-0+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_RQhas be checked ?I've since fixed a few more, all should be well now. The updated version is here:
Quoted 5 lines
Since the enum that contains
NULL_Q_RQis indrivers/block/null_blk_main.c, and not in a linux header file, would it be thinkable to removeNULL_Q_RQfrom the enum too, and not adding this legacy check ?
Quoted 5 lines
Quoted 1 line
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) ?
Quoted 3 lines
I'm checking that at the bottom, we could remove
NULL_Q_RQif we just made that check == 1 instead. But cleaner to keep it, imho.
I agree, if queue_mode=1 can be passed.
Jens Axboe
maintainerRe: [PATCH 17/17] null_blk: remove legacy IO path
Quoted 19 lines · Sébastien Boisvert
Quoted 18 lines · Jens Axboe
Quoted 6 lines · Sébastien Boisvert
drivers/block/null_blk_main.c static int __init null_init(void) · line 1783
Quoted 4 lines
drivers/block/null_blk_main.c +4
-0+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_RQhas be checked ?I've since fixed a few more, all should be well now. The updated version is here:
Quoted 5 lines
Since the enum that contains
NULL_Q_RQis indrivers/block/null_blk_main.c, and not in a linux header file, would it be thinkable to removeNULL_Q_RQfrom the enum too, and not adding this legacy check ?
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
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.
Quoted 5 lines
Quoted 3 lines
I'm checking that at the bottom, we could remove
NULL_Q_RQif 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.
Signature · 1 line
Jens Axboe