Re: [PATCH v4 17/25] ibnbd: client: main functionality

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 9/17/19 6:09 AM, Jinpu Wang wrote:
+static void ibnbd_softirq_done_fn(struct request *rq)
+{
+     struct ibnbd_clt_dev *dev       = rq->rq_disk->private_data;
+     struct ibnbd_clt_session *sess  = dev->sess;
+     struct ibnbd_iu *iu;
+
+     iu = blk_mq_rq_to_pdu(rq);
+     ibnbd_put_tag(sess, iu->tag);
+     blk_mq_end_request(rq, iu->status);
+}
+
+static void msg_io_conf(void *priv, int errno)
+{
+     struct ibnbd_iu *iu = (struct ibnbd_iu *)priv;
+     struct ibnbd_clt_dev *dev = iu->dev;
+     struct request *rq = iu->rq;
+
+     iu->status = errno ? BLK_STS_IOERR : BLK_STS_OK;
+
+     if (softirq_enable) {
+             blk_mq_complete_request(rq);
+     } else {
+             ibnbd_put_tag(dev->sess, iu->tag);
+             blk_mq_end_request(rq, iu->status);
+     }

Block drivers must call blk_mq_complete_request() instead of
blk_mq_end_request() to complete a request after processing of the
request has been started. Calling blk_mq_end_request() to complete a
request is racy in case a timeout occurs while blk_mq_end_request() is
in progress.

Could you elaborate a bit more, blk_mq_end_request is exported function and
used by a lot of block drivers: scsi, dm, etc.
Is there an open bug report for the problem?

Hi Jinpu,

There is only one blk_mq_end_request() call in the SCSI code and it's inside the FC timeout handler (fc_bsg_job_timeout()). Calling blk_mq_end_request() from inside a timeout handler is fine but not to report to the block layer that a request has completed from outside the timeout handler after a request has started.

The device mapper calls blk_mq_complete_request() to report request completion to the block layer. See also dm_complete_request(). blk_mq_end_request() is only called by the device mapper from inside dm_softirq_done(). That last function is called from inside blk_mq_complete_request() and is not called directly.

The NVMe PCIe driver only calls blk_mq_end_request() from inside nvme_complete_rq(). nvme_complete_rq() is called by the PCIe driver from inside nvme_pci_complete_rq() and that last function is called from inside blk_mq_complete_request().

In other words, the SCSI core, the device mapper and the NVMe PCIe driver all use blk_mq_complete_request() to report request completion to the block layer from outside timeout handlers after a request has been started.

This is not a new requirement. I think that the legacy block layer equivalent, blk_complete_request(), was introduced in 2006 and that since then block drivers are required to call blk_complete_request() to report completion of requests from outside a timeout handler after these have been started.

Bart.



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux