On Thu, 2014-03-27 at 17:14 +0100, Christoph Hellwig wrote:
> Move control of the prep_fn back from the ULDs into the scsi layer. Besides
> cleaning up the code and removing the only use of the unprep_fn
> requeuest_queue method this also prepares for usinng blk-mq, which doesn't
> have equivalent functionality to the prep_fn method and requires the driver
> to provide just a single I/O submission method.
>
> Signed-off-by: Christoph Hellwig <[email protected]>
> ---
> drivers/scsi/scsi_lib.c | 66
> ++++++++++++++++++++++++++------------------
> drivers/scsi/sd.c | 46 +++++++++++-------------------
> drivers/scsi/sr.c | 19 ++++---------
> include/scsi/scsi_driver.h | 8 ++----
> 4 files changed, 63 insertions(+), 76 deletions(-)
>
> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> index a73751b..48c5c77 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
<SNIP>
> @@ -1071,15 +1083,7 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct
> scsi_device *sdev,
>
> int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
> {
> - struct scsi_cmnd *cmd;
> - int ret = scsi_prep_state_check(sdev, req);
> -
> - if (ret != BLKPREP_OK)
> - return ret;
> -
> - cmd = scsi_get_cmd_from_req(sdev, req);
> - if (unlikely(!cmd))
> - return BLKPREP_DEFER;
> + struct scsi_cmnd *cmd = req->special;
>
Mmm, I thought that req->special was only holding a pointer to a
pre-allocated scsi_cmnd during mq operation, no..?
> /*
> * BLOCK_PC requests may transfer data, in which case they must
> @@ -1123,15 +1127,11 @@ EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd);
> */
> int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
> {
> - struct scsi_cmnd *cmd;
> - int ret = scsi_prep_state_check(sdev, req);
> -
> - if (ret != BLKPREP_OK)
> - return ret;
> + struct scsi_cmnd *cmd = req->special;
>
Ditto here for REQ_TYPE_FS_CMND
> if (unlikely(sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh
> && sdev->scsi_dh_data->scsi_dh->prep_fn)) {
> - ret = sdev->scsi_dh_data->scsi_dh->prep_fn(sdev, req);
> + int ret = sdev->scsi_dh_data->scsi_dh->prep_fn(sdev, req);
> if (ret != BLKPREP_OK)
> return ret;
> }
> @@ -1141,16 +1141,13 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev,
> struct request *req)
> */
> BUG_ON(!req->nr_phys_segments);
>
> - cmd = scsi_get_cmd_from_req(sdev, req);
> - if (unlikely(!cmd))
> - return BLKPREP_DEFER;
> -
> memset(cmd->cmnd, 0, BLK_MAX_CDB);
> return scsi_init_io(cmd, GFP_ATOMIC);
> }
> EXPORT_SYMBOL(scsi_setup_fs_cmnd);
>
> -int scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
> +static int
> +scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
> {
> int ret = BLKPREP_OK;
>
> @@ -1202,9 +1199,9 @@ int scsi_prep_state_check(struct scsi_device *sdev,
> struct request *req)
> }
> return ret;
> }
> -EXPORT_SYMBOL(scsi_prep_state_check);
>
> -int scsi_prep_return(struct request_queue *q, struct request *req, int ret)
> +static int
> +scsi_prep_return(struct request_queue *q, struct request *req, int ret)
> {
> struct scsi_device *sdev = q->queuedata;
>
> @@ -1235,18 +1232,33 @@ int scsi_prep_return(struct request_queue *q, struct
> request *req, int ret)
>
> return ret;
> }
> -EXPORT_SYMBOL(scsi_prep_return);
>
> -int scsi_prep_fn(struct request_queue *q, struct request *req)
> +static int scsi_prep_fn(struct request_queue *q, struct request *req)
> {
> struct scsi_device *sdev = q->queuedata;
> - int ret = BLKPREP_KILL;
> + struct scsi_cmnd *cmd;
> + int ret;
>
> - if (req->cmd_type == REQ_TYPE_BLOCK_PC)
> + ret = scsi_prep_state_check(sdev, req);
> + if (ret != BLKPREP_OK)
> + goto out;
> +
> + cmd = scsi_get_cmd_from_req(sdev, req);
> + if (unlikely(!cmd)) {
> + ret = BLKPREP_DEFER;
> + goto out;
> + }
> +
>From here the req->special pointer may or may not be set depending on mq
operation, no..?
> + if (req->cmd_type == REQ_TYPE_FS)
> + ret = scsi_cmd_to_driver(cmd)->init_command(cmd);
> + else if (req->cmd_type == REQ_TYPE_BLOCK_PC)
> ret = scsi_setup_blk_pc_cmnd(sdev, req);
> + else
> + ret = BLKPREP_KILL;
> +
> +out:
> return scsi_prep_return(q, req, ret);
> }
> -EXPORT_SYMBOL(scsi_prep_fn);
>
> /*
> * scsi_dev_queue_ready: if we can send requests to sdev, return 1 else
> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
> index 89e6c04..d95c4fd 100644
> --- a/drivers/scsi/sd.c
> +++ b/drivers/scsi/sd.c
<SNIP>
> @@ -886,12 +882,6 @@ static int sd_prep_fn(struct request_queue *q, struct
> request *rq)
> } else if (rq->cmd_flags & REQ_FLUSH) {
> ret = scsi_setup_flush_cmnd(sdp, rq);
> goto out;
> - } else if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
> - ret = scsi_setup_blk_pc_cmnd(sdp, rq);
> - goto out;
> - } else if (rq->cmd_type != REQ_TYPE_FS) {
> - ret = BLKPREP_KILL;
> - goto out;
> }
> ret = scsi_setup_fs_cmnd(sdp, rq);
> if (ret != BLKPREP_OK)
And this currently assumes req->special is always set when calling
scsi_setup_fs_cmnd()
> @@ -903,11 +893,10 @@ static int sd_prep_fn(struct request_queue *q, struct
> request *rq)
> * is used for a killable error condition */
> ret = BLKPREP_KILL;
>
> - SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt,
> - "sd_prep_fn: block=%llu, "
> - "count=%d\n",
> - (unsigned long long)block,
> - this_count));
> + SCSI_LOG_HLQUEUE(1,
> + scmd_printk(KERN_INFO, SCpnt,
> + "%s: block=%llu, count=%d\n",
> + __func__, (unsigned long long)block, this_count));
>
> if (!sdp || !scsi_device_online(sdp) ||
> block + blk_rq_sectors(rq) > get_capacity(disk)) {
> @@ -1127,7 +1116,7 @@ static int sd_prep_fn(struct request_queue *q, struct
> request *rq)
> */
> ret = BLKPREP_OK;
> out:
> - return scsi_prep_return(q, rq, ret);
> + return ret;
> }
>
> /**
> @@ -1663,6 +1652,8 @@ static int sd_done(struct scsi_cmnd *SCpnt)
> unsigned char op = SCpnt->cmnd[0];
> unsigned char unmap = SCpnt->cmnd[1] & 8;
>
> + sd_uninit_command(SCpnt);
> +
> if (req->cmd_flags & REQ_DISCARD || req->cmd_flags & REQ_WRITE_SAME) {
> if (!result) {
> good_bytes = blk_rq_bytes(req);
> @@ -2878,9 +2869,6 @@ static void sd_probe_async(void *data, async_cookie_t
> cookie)
>
> sd_revalidate_disk(gd);
>
> - blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
> - blk_queue_unprep_rq(sdp->request_queue, sd_unprep_fn);
> -
> gd->driverfs_dev = &sdp->sdev_gendev;
> gd->flags = GENHD_FL_EXT_DEVT;
> if (sdp->removable) {
> @@ -3027,8 +3015,6 @@ static int sd_remove(struct device *dev)
> scsi_autopm_get_device(sdkp->device);
>
> async_synchronize_full_domain(&scsi_sd_probe_domain);
> - blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn);
> - blk_queue_unprep_rq(sdkp->device->request_queue, NULL);
> device_del(&sdkp->dev);
> del_gendisk(sdkp->disk);
> sd_shutdown(dev);
> diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
> index 40d8592..93cbd36 100644
> --- a/drivers/scsi/sr.c
> +++ b/drivers/scsi/sr.c
<SNIP>
> @@ -378,21 +380,14 @@ static int sr_done(struct scsi_cmnd *SCpnt)
> return good_bytes;
> }
>
> -static int sr_prep_fn(struct request_queue *q, struct request *rq)
> +static int sr_init_command(struct scsi_cmnd *SCpnt)
> {
> int block = 0, this_count, s_size;
> struct scsi_cd *cd;
> - struct scsi_cmnd *SCpnt;
> - struct scsi_device *sdp = q->queuedata;
> + struct request *rq = SCpnt->request;
> + struct scsi_device *sdp = SCpnt->device;
> int ret;
>
> - if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
> - ret = scsi_setup_blk_pc_cmnd(sdp, rq);
> - goto out;
> - } else if (rq->cmd_type != REQ_TYPE_FS) {
> - ret = BLKPREP_KILL;
> - goto out;
> - }
> ret = scsi_setup_fs_cmnd(sdp, rq);
> if (ret != BLKPREP_OK)
> goto out;
Ditto to the scsi_setup_fs_cmnd() call here as well.
--nab
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html