* [PATCH 3/4] scsi: reintroduce scsi_driver.init_command
2014-03-27 16:14 misc scsi midlayer updates Christoph Hellwig
@ 2014-03-27 16:14 ` Christoph Hellwig
2014-03-31 5:45 ` Nicholas A. Bellinger
2014-03-31 6:56 ` Mike Christie
0 siblings, 2 replies; 16+ messages in thread
From: Christoph Hellwig @ 2014-03-27 16:14 UTC (permalink / raw)
To: James Bottomley; +Cc: linux-scsi
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 <hch@lst.de>
---
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
@@ -456,6 +456,16 @@ void scsi_requeue_run_queue(struct work_struct *work)
scsi_run_queue(q);
}
+static void scsi_uninit_command(struct scsi_cmnd *cmd)
+{
+ if (cmd->request->cmd_type == REQ_TYPE_FS) {
+ struct scsi_driver *drv = scsi_cmd_to_driver(cmd);
+
+ if (drv->uninit_command)
+ drv->uninit_command(cmd);
+ }
+}
+
/*
* Function: scsi_requeue_command()
*
@@ -480,6 +490,8 @@ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
struct request *req = cmd->request;
unsigned long flags;
+ scsi_uninit_command(cmd);
+
spin_lock_irqsave(q->queue_lock, flags);
blk_unprep_request(req);
req->special = NULL;
@@ -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;
/*
* 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;
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;
+ }
+
+ 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
@@ -109,6 +109,8 @@ static int sd_suspend_system(struct device *);
static int sd_suspend_runtime(struct device *);
static int sd_resume(struct device *);
static void sd_rescan(struct device *);
+static int sd_init_command(struct scsi_cmnd *SCpnt);
+static void sd_uninit_command(struct scsi_cmnd *SCpnt);
static int sd_done(struct scsi_cmnd *);
static int sd_eh_action(struct scsi_cmnd *, int);
static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
@@ -503,6 +505,8 @@ static struct scsi_driver sd_template = {
.pm = &sd_pm_ops,
},
.rescan = sd_rescan,
+ .init_command = sd_init_command,
+ .uninit_command = sd_uninit_command,
.done = sd_done,
.eh_action = sd_eh_action,
};
@@ -838,9 +842,9 @@ static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
return scsi_setup_blk_pc_cmnd(sdp, rq);
}
-static void sd_unprep_fn(struct request_queue *q, struct request *rq)
+static void sd_uninit_command(struct scsi_cmnd *SCpnt)
{
- struct scsi_cmnd *SCpnt = rq->special;
+ struct request *rq = SCpnt->request;
if (rq->cmd_flags & REQ_DISCARD) {
free_page((unsigned long)rq->buffer);
@@ -853,18 +857,10 @@ static void sd_unprep_fn(struct request_queue *q, struct request *rq)
}
}
-/**
- * sd_prep_fn - build a scsi (read or write) command from
- * information in the request structure.
- * @SCpnt: pointer to mid-level's per scsi command structure that
- * contains request and into which the scsi command is written
- *
- * Returns 1 if successful and 0 if error (or cannot be done now).
- **/
-static int sd_prep_fn(struct request_queue *q, struct request *rq)
+static int sd_init_command(struct scsi_cmnd *SCpnt)
{
- struct scsi_cmnd *SCpnt;
- struct scsi_device *sdp = q->queuedata;
+ struct request *rq = SCpnt->request;
+ struct scsi_device *sdp = SCpnt->device;
struct gendisk *disk = rq->rq_disk;
struct scsi_disk *sdkp;
sector_t block = blk_rq_pos(rq);
@@ -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)
@@ -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
@@ -79,6 +79,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM);
static DEFINE_MUTEX(sr_mutex);
static int sr_probe(struct device *);
static int sr_remove(struct device *);
+static int sr_init_command(struct scsi_cmnd *SCpnt);
static int sr_done(struct scsi_cmnd *);
static int sr_runtime_suspend(struct device *dev);
@@ -94,6 +95,7 @@ static struct scsi_driver sr_template = {
.remove = sr_remove,
.pm = &sr_pm_ops,
},
+ .init_command = sr_init_command,
.done = sr_done,
};
@@ -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;
@@ -517,7 +512,7 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
*/
ret = BLKPREP_OK;
out:
- return scsi_prep_return(q, rq, ret);
+ return ret;
}
static int sr_block_open(struct block_device *bdev, fmode_t mode)
@@ -718,7 +713,6 @@ static int sr_probe(struct device *dev)
/* FIXME: need to handle a get_capabilities failure properly ?? */
get_capabilities(cd);
- blk_queue_prep_rq(sdev->request_queue, sr_prep_fn);
sr_vendor_init(cd);
disk->driverfs_dev = &sdev->sdev_gendev;
@@ -993,7 +987,6 @@ static int sr_remove(struct device *dev)
scsi_autopm_get_device(cd->device);
- blk_queue_prep_rq(cd->device->request_queue, scsi_prep_fn);
del_gendisk(cd->disk);
mutex_lock(&sr_ref_mutex);
diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h
index 20fdfc2..b507729 100644
--- a/include/scsi/scsi_driver.h
+++ b/include/scsi/scsi_driver.h
@@ -6,15 +6,14 @@
struct module;
struct scsi_cmnd;
struct scsi_device;
-struct request;
-struct request_queue;
-
struct scsi_driver {
struct module *owner;
struct device_driver gendrv;
void (*rescan)(struct device *);
+ int (*init_command)(struct scsi_cmnd *);
+ void (*uninit_command)(struct scsi_cmnd *);
int (*done)(struct scsi_cmnd *);
int (*eh_action)(struct scsi_cmnd *, int);
};
@@ -31,8 +30,5 @@ extern int scsi_register_interface(struct class_interface *);
int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req);
int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req);
-int scsi_prep_state_check(struct scsi_device *sdev, struct request *req);
-int scsi_prep_return(struct request_queue *q, struct request *req, int ret);
-int scsi_prep_fn(struct request_queue *, struct request *);
#endif /* _SCSI_SCSI_DRIVER_H */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] scsi: reintroduce scsi_driver.init_command
2014-03-27 16:14 ` [PATCH 3/4] scsi: reintroduce scsi_driver.init_command Christoph Hellwig
@ 2014-03-31 5:45 ` Nicholas A. Bellinger
2014-03-31 6:08 ` Christoph Hellwig
2014-03-31 6:56 ` Mike Christie
1 sibling, 1 reply; 16+ messages in thread
From: Nicholas A. Bellinger @ 2014-03-31 5:45 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: James Bottomley, linux-scsi
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 <hch@lst.de>
> ---
> 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
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] scsi: reintroduce scsi_driver.init_command
2014-03-31 5:45 ` Nicholas A. Bellinger
@ 2014-03-31 6:08 ` Christoph Hellwig
2014-03-31 6:20 ` Nicholas A. Bellinger
0 siblings, 1 reply; 16+ messages in thread
From: Christoph Hellwig @ 2014-03-31 6:08 UTC (permalink / raw)
To: Nicholas A. Bellinger; +Cc: Christoph Hellwig, James Bottomley, linux-scsi
On Sun, Mar 30, 2014 at 10:45:04PM -0700, Nicholas A. Bellinger wrote:
> > 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..?
For the mq case the block layer sets up req->special. For the old case
scsi_get_cmd_from_req sets up req->special the first it is called, and
leaves it in there until the command is done.
> > + 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..?
a) there is no blk-mq support yet in James tree (+ these patches)
b) even in my scsi-mq tree this code path won't be called for the mq case
c) after scsi_get_cmd_from_req returns req->special will always be set up
to point to the scsi_cmnd:
static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
struct request *req)
{
struct scsi_cmnd *cmd;
if (!req->special) {
...
req->special = cmd;
} else {
cmd = req->special;
}
/* pull a tag out of the request if we have one */
cmd->tag = req->tag;
cmd->request = req;
cmd->cmnd = req->cmd;
cmd->prot_op = SCSI_PROT_NORMAL;
return cmd;
}
> > }
> > 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()
That is the case both before and after this patch.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] scsi: reintroduce scsi_driver.init_command
2014-03-31 6:08 ` Christoph Hellwig
@ 2014-03-31 6:20 ` Nicholas A. Bellinger
0 siblings, 0 replies; 16+ messages in thread
From: Nicholas A. Bellinger @ 2014-03-31 6:20 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: James Bottomley, linux-scsi
On Mon, 2014-03-31 at 08:08 +0200, Christoph Hellwig wrote:
> On Sun, Mar 30, 2014 at 10:45:04PM -0700, Nicholas A. Bellinger wrote:
> > > 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..?
>
> For the mq case the block layer sets up req->special. For the old case
> scsi_get_cmd_from_req sets up req->special the first it is called, and
> leaves it in there until the command is done.
Er, yes of course.
Reviewed-by: Nicholas Bellinger <nab@linux-iscsi.org>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] scsi: reintroduce scsi_driver.init_command
2014-03-27 16:14 ` [PATCH 3/4] scsi: reintroduce scsi_driver.init_command Christoph Hellwig
2014-03-31 5:45 ` Nicholas A. Bellinger
@ 2014-03-31 6:56 ` Mike Christie
2014-03-31 8:09 ` Christoph Hellwig
1 sibling, 1 reply; 16+ messages in thread
From: Mike Christie @ 2014-03-31 6:56 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: James Bottomley, linux-scsi
On 03/27/2014 11:14 AM, Christoph Hellwig wrote:
> @@ -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);
> +
The above call would free the cmnd->cmnd and set it to null. If then
scsi_io_completion was going to do some error processing it looks like
it could try to access the scsi_cmnd->cmnd field.
With the current code that would not be a problem because the blk unprep
callback is not called until the block layer does its request cleanup in
blk_finish_request which as you know is after
scsi_io_completion/scsi_end_request is done with the cmnd.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] scsi: reintroduce scsi_driver.init_command
2014-03-31 6:56 ` Mike Christie
@ 2014-03-31 8:09 ` Christoph Hellwig
0 siblings, 0 replies; 16+ messages in thread
From: Christoph Hellwig @ 2014-03-31 8:09 UTC (permalink / raw)
To: Mike Christie; +Cc: Christoph Hellwig, James Bottomley, linux-scsi
On Mon, Mar 31, 2014 at 01:56:13AM -0500, Mike Christie wrote:
> The above call would free the cmnd->cmnd and set it to null. If then
> scsi_io_completion was going to do some error processing it looks like
> it could try to access the scsi_cmnd->cmnd field.
>
> With the current code that would not be a problem because the blk unprep
> callback is not called until the block layer does its request cleanup in
> blk_finish_request which as you know is after
> scsi_io_completion/scsi_end_request is done with the cmnd.
Right, we should probabl call ->uninit_command at that place as well
instead of calling it internall in ->done.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] scsi: reintroduce scsi_driver.init_command
@ 2014-03-31 10:45 Christoph Hellwig
0 siblings, 0 replies; 16+ messages in thread
From: Christoph Hellwig @ 2014-03-31 10:45 UTC (permalink / raw)
To: Mike Christie; +Cc: James Bottomley, linux-scsi
> The above call would free the cmnd->cmnd and set it to null. If then
> scsi_io_completion was going to do some error processing it looks like
> it could try to access the scsi_cmnd->cmnd field.
>
> With the current code that would not be a problem because the blk unprep
> callback is not called until the block layer does its request cleanup in
> blk_finish_request which as you know is after
> scsi_io_completion/scsi_end_request is done with the cmnd.
This incremental patches fixes the issue, and makes sure the uninit calls are
nicely paired like the rest of the I/O completion routines after patch 2:
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 48c5c77..8e79612 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -490,8 +490,6 @@ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
struct request *req = cmd->request;
unsigned long flags;
- scsi_uninit_command(cmd);
-
spin_lock_irqsave(q->queue_lock, flags);
blk_unprep_request(req);
req->special = NULL;
@@ -941,6 +939,7 @@ requeue:
/* Unprep the request and put it back at the head of the queue.
* A new command will be prepared and issued.
*/
+ scsi_uninit_command(cmd);
scsi_release_buffers(cmd);
scsi_requeue_command(q, cmd);
break;
@@ -956,6 +955,7 @@ requeue:
return;
next_command:
+ scsi_uninit_command(cmd);
scsi_release_buffers(cmd);
scsi_next_command(cmd);
}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index d95c4fd..d99cb3f 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1652,8 +1652,6 @@ 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);
^ permalink raw reply related [flat|nested] 16+ messages in thread
* scsi midlayer updates for 3.15 (resend)
@ 2014-05-01 14:51 Christoph Hellwig
2014-05-01 14:51 ` [PATCH 1/4] scsi: explicitly release bidi buffers Christoph Hellwig
` (4 more replies)
0 siblings, 5 replies; 16+ messages in thread
From: Christoph Hellwig @ 2014-05-01 14:51 UTC (permalink / raw)
To: James Bottomley; +Cc: linux-scsi
Various patches from the scsi multiqueue development that make sense on their
own.
Changes since the version from 5 weeks ago:
- rebase on top of minor changes in 3.15-rc3
- add a struct request forward declaration to avoid a warning in
the OSD ULD.
- add the reviewed-by tags from Nic and Mike from the last round.
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 1/4] scsi: explicitly release bidi buffers
2014-05-01 14:51 scsi midlayer updates for 3.15 (resend) Christoph Hellwig
@ 2014-05-01 14:51 ` Christoph Hellwig
2014-05-01 14:51 ` [PATCH 2/4] scsi: remove scsi_end_request Christoph Hellwig
` (3 subsequent siblings)
4 siblings, 0 replies; 16+ messages in thread
From: Christoph Hellwig @ 2014-05-01 14:51 UTC (permalink / raw)
To: James Bottomley; +Cc: linux-scsi
Instead of trying to guess when we have a BIDI buffer in scsi_release_buffers
add a function to explicitly free the BIDI ressoures in the one place that
handles them. This avoids needing a special __scsi_release_buffers for the
case where we already have freed the request as well.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
---
drivers/scsi/scsi_lib.c | 47 ++++++++++++++++++++---------------------------
1 file changed, 20 insertions(+), 27 deletions(-)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 9db097a..f416b59 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -512,8 +512,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost)
scsi_run_queue(sdev->request_queue);
}
-static void __scsi_release_buffers(struct scsi_cmnd *, int);
-
/*
* Function: scsi_end_request()
*
@@ -569,7 +567,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
* This will goose the queue request function at the end, so we don't
* need to worry about launching another command.
*/
- __scsi_release_buffers(cmd, 0);
+ scsi_release_buffers(cmd);
scsi_next_command(cmd);
return NULL;
}
@@ -625,30 +623,10 @@ static void scsi_free_sgtable(struct scsi_data_buffer *sdb)
__sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, scsi_sg_free);
}
-static void __scsi_release_buffers(struct scsi_cmnd *cmd, int do_bidi_check)
-{
-
- if (cmd->sdb.table.nents)
- scsi_free_sgtable(&cmd->sdb);
-
- memset(&cmd->sdb, 0, sizeof(cmd->sdb));
-
- if (do_bidi_check && scsi_bidi_cmnd(cmd)) {
- struct scsi_data_buffer *bidi_sdb =
- cmd->request->next_rq->special;
- scsi_free_sgtable(bidi_sdb);
- kmem_cache_free(scsi_sdb_cache, bidi_sdb);
- cmd->request->next_rq->special = NULL;
- }
-
- if (scsi_prot_sg_count(cmd))
- scsi_free_sgtable(cmd->prot_sdb);
-}
-
/*
* Function: scsi_release_buffers()
*
- * Purpose: Completion processing for block device I/O requests.
+ * Purpose: Free resources allocate for a scsi_command.
*
* Arguments: cmd - command that we are bailing.
*
@@ -659,15 +637,29 @@ static void __scsi_release_buffers(struct scsi_cmnd *cmd, int do_bidi_check)
* Notes: In the event that an upper level driver rejects a
* command, we must release resources allocated during
* the __init_io() function. Primarily this would involve
- * the scatter-gather table, and potentially any bounce
- * buffers.
+ * the scatter-gather table.
*/
void scsi_release_buffers(struct scsi_cmnd *cmd)
{
- __scsi_release_buffers(cmd, 1);
+ if (cmd->sdb.table.nents)
+ scsi_free_sgtable(&cmd->sdb);
+
+ memset(&cmd->sdb, 0, sizeof(cmd->sdb));
+
+ if (scsi_prot_sg_count(cmd))
+ scsi_free_sgtable(cmd->prot_sdb);
}
EXPORT_SYMBOL(scsi_release_buffers);
+static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd)
+{
+ struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special;
+
+ scsi_free_sgtable(bidi_sdb);
+ kmem_cache_free(scsi_sdb_cache, bidi_sdb);
+ cmd->request->next_rq->special = NULL;
+}
+
/**
* __scsi_error_from_host_byte - translate SCSI error code into errno
* @cmd: SCSI command (unused)
@@ -801,6 +793,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
req->next_rq->resid_len = scsi_in(cmd)->resid;
scsi_release_buffers(cmd);
+ scsi_release_bidi_buffers(cmd);
blk_end_request_all(req, 0);
scsi_next_command(cmd);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 2/4] scsi: remove scsi_end_request
2014-05-01 14:51 scsi midlayer updates for 3.15 (resend) Christoph Hellwig
2014-05-01 14:51 ` [PATCH 1/4] scsi: explicitly release bidi buffers Christoph Hellwig
@ 2014-05-01 14:51 ` Christoph Hellwig
2014-05-08 7:06 ` Hannes Reinecke
2014-05-01 14:51 ` [PATCH 3/4] scsi: reintroduce scsi_driver.init_command Christoph Hellwig
` (2 subsequent siblings)
4 siblings, 1 reply; 16+ messages in thread
From: Christoph Hellwig @ 2014-05-01 14:51 UTC (permalink / raw)
To: James Bottomley; +Cc: linux-scsi
By folding scsi_end_request into its only caller we can significantly clean
up the completion logic. We can use simple goto labels now to only have
a single place to finish or requeue command there instead of the previous
convoluted logic.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Nicholas Bellinger <nab@linux-iscsi.org>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
---
drivers/scsi/scsi_lib.c | 114 +++++++++++++----------------------------------
1 file changed, 32 insertions(+), 82 deletions(-)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index f416b59..045822b 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -512,66 +512,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost)
scsi_run_queue(sdev->request_queue);
}
-/*
- * Function: scsi_end_request()
- *
- * Purpose: Post-processing of completed commands (usually invoked at end
- * of upper level post-processing and scsi_io_completion).
- *
- * Arguments: cmd - command that is complete.
- * error - 0 if I/O indicates success, < 0 for I/O error.
- * bytes - number of bytes of completed I/O
- * requeue - indicates whether we should requeue leftovers.
- *
- * Lock status: Assumed that lock is not held upon entry.
- *
- * Returns: cmd if requeue required, NULL otherwise.
- *
- * Notes: This is called for block device requests in order to
- * mark some number of sectors as complete.
- *
- * We are guaranteeing that the request queue will be goosed
- * at some point during this call.
- * Notes: If cmd was requeued, upon return it will be a stale pointer.
- */
-static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
- int bytes, int requeue)
-{
- struct request_queue *q = cmd->device->request_queue;
- struct request *req = cmd->request;
-
- /*
- * If there are blocks left over at the end, set up the command
- * to queue the remainder of them.
- */
- if (blk_end_request(req, error, bytes)) {
- /* kill remainder if no retrys */
- if (error && scsi_noretry_cmd(cmd))
- blk_end_request_all(req, error);
- else {
- if (requeue) {
- /*
- * Bleah. Leftovers again. Stick the
- * leftovers in the front of the
- * queue, and goose the queue again.
- */
- scsi_release_buffers(cmd);
- scsi_requeue_command(q, cmd);
- cmd = NULL;
- }
- return cmd;
- }
- }
-
- /*
- * This will goose the queue request function at the end, so we don't
- * need to worry about launching another command.
- */
- scsi_release_buffers(cmd);
- scsi_next_command(cmd);
- return NULL;
-}
-
static inline unsigned int scsi_sgtable_index(unsigned short nents)
{
unsigned int index;
@@ -717,16 +657,9 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
*
* Returns: Nothing
*
- * Notes: This function is matched in terms of capabilities to
- * the function that created the scatter-gather list.
- * In other words, if there are no bounce buffers
- * (the normal case for most drivers), we don't need
- * the logic to deal with cleaning up afterwards.
- *
- * We must call scsi_end_request(). This will finish off
- * the specified number of sectors. If we are done, the
- * command block will be released and the queue function
- * will be goosed. If we are not done then we have to
+ * Notes: We will finish off the specified number of sectors. If we
+ * are done, the command block will be released and the queue
+ * function will be goosed. If we are not done then we have to
* figure out what to do next:
*
* a) We can call scsi_requeue_command(). The request
@@ -735,7 +668,7 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
* be used if we made forward progress, or if we want
* to switch from READ(10) to READ(6) for example.
*
- * b) We can call scsi_queue_insert(). The request will
+ * b) We can call __scsi_queue_insert(). The request will
* be put back on the queue and retried using the same
* command as before, possibly after a delay.
*
@@ -794,6 +727,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
scsi_release_buffers(cmd);
scsi_release_bidi_buffers(cmd);
+
blk_end_request_all(req, 0);
scsi_next_command(cmd);
@@ -833,12 +767,25 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
}
/*
- * A number of bytes were successfully read. If there
- * are leftovers and there is some kind of error
- * (result != 0), retry the rest.
+ * If we finished all bytes in the request we are done now.
*/
- if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
- return;
+ if (!blk_end_request(req, error, good_bytes))
+ goto next_command;
+
+ /*
+ * Kill remainder if no retrys.
+ */
+ if (error && scsi_noretry_cmd(cmd)) {
+ blk_end_request_all(req, error);
+ goto next_command;
+ }
+
+ /*
+ * If there had been no error, but we have leftover bytes in the
+ * requeues just queue the command up again.
+ */
+ if (result == 0)
+ goto requeue;
error = __scsi_error_from_host_byte(cmd, result);
@@ -966,7 +913,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
switch (action) {
case ACTION_FAIL:
/* Give up and fail the remainder of the request */
- scsi_release_buffers(cmd);
if (!(req->cmd_flags & REQ_QUIET)) {
if (description)
scmd_printk(KERN_INFO, cmd, "%s\n",
@@ -976,12 +922,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
scsi_print_sense("", cmd);
scsi_print_command(cmd);
}
- if (blk_end_request_err(req, error))
- scsi_requeue_command(q, cmd);
- else
- scsi_next_command(cmd);
- break;
+ if (!blk_end_request_err(req, error))
+ goto next_command;
+ /*FALLTHRU*/
case ACTION_REPREP:
+ requeue:
/* Unprep the request and put it back at the head of the queue.
* A new command will be prepared and issued.
*/
@@ -997,6 +942,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
__scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY, 0);
break;
}
+ return;
+
+next_command:
+ scsi_release_buffers(cmd);
+ scsi_next_command(cmd);
}
static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
--
1.7.10.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 3/4] scsi: reintroduce scsi_driver.init_command
2014-05-01 14:51 scsi midlayer updates for 3.15 (resend) Christoph Hellwig
2014-05-01 14:51 ` [PATCH 1/4] scsi: explicitly release bidi buffers Christoph Hellwig
2014-05-01 14:51 ` [PATCH 2/4] scsi: remove scsi_end_request Christoph Hellwig
@ 2014-05-01 14:51 ` Christoph Hellwig
2014-05-08 7:11 ` Hannes Reinecke
2014-05-01 14:51 ` [PATCH 4/4] scsi: handle command allocation failure in scsi_reset_provider Christoph Hellwig
2014-05-01 18:42 ` scsi midlayer updates for 3.15 (resend) Christoph Hellwig
4 siblings, 1 reply; 16+ messages in thread
From: Christoph Hellwig @ 2014-05-01 14:51 UTC (permalink / raw)
To: James Bottomley; +Cc: linux-scsi
Instead of letting the ULD play games with the prep_fn move back to
the model of a central prep_fn with a callback to the ULD. This
already cleans up and shortens the code by itself, and will be required
to properly support blk-mq in the SCSI midlayer.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Nicholas Bellinger <nab@linux-iscsi.org>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
---
drivers/scsi/scsi_lib.c | 66 ++++++++++++++++++++++++++------------------
drivers/scsi/sd.c | 44 ++++++++++-------------------
drivers/scsi/sr.c | 19 ++++---------
include/scsi/scsi_driver.h | 9 ++----
4 files changed, 62 insertions(+), 76 deletions(-)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 045822b..9f841df 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1073,15 +1073,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;
/*
* BLOCK_PC requests may transfer data, in which case they must
@@ -1125,15 +1117,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;
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;
}
@@ -1143,16 +1131,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;
@@ -1204,9 +1189,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;
@@ -1237,18 +1222,44 @@ 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;
+ }
+
+ 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);
+
+static void scsi_unprep_fn(struct request_queue *q, struct request *req)
+{
+ if (req->cmd_type == REQ_TYPE_FS) {
+ struct scsi_cmnd *cmd = req->special;
+ struct scsi_driver *drv = scsi_cmd_to_driver(cmd);
+
+ if (drv->uninit_command)
+ drv->uninit_command(cmd);
+ }
+}
/*
* scsi_dev_queue_ready: if we can send requests to sdev, return 1 else
@@ -1669,6 +1680,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
return NULL;
blk_queue_prep_rq(q, scsi_prep_fn);
+ blk_queue_unprep_rq(q, scsi_unprep_fn);
blk_queue_softirq_done(q, scsi_softirq_done);
blk_queue_rq_timed_out(q, scsi_times_out);
blk_queue_lld_busy(q, scsi_lld_busy);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index efcbcd1..1c1253b 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -109,6 +109,8 @@ static int sd_suspend_system(struct device *);
static int sd_suspend_runtime(struct device *);
static int sd_resume(struct device *);
static void sd_rescan(struct device *);
+static int sd_init_command(struct scsi_cmnd *SCpnt);
+static void sd_uninit_command(struct scsi_cmnd *SCpnt);
static int sd_done(struct scsi_cmnd *);
static int sd_eh_action(struct scsi_cmnd *, int);
static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
@@ -503,6 +505,8 @@ static struct scsi_driver sd_template = {
.pm = &sd_pm_ops,
},
.rescan = sd_rescan,
+ .init_command = sd_init_command,
+ .uninit_command = sd_uninit_command,
.done = sd_done,
.eh_action = sd_eh_action,
};
@@ -838,9 +842,9 @@ static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
return scsi_setup_blk_pc_cmnd(sdp, rq);
}
-static void sd_unprep_fn(struct request_queue *q, struct request *rq)
+static void sd_uninit_command(struct scsi_cmnd *SCpnt)
{
- struct scsi_cmnd *SCpnt = rq->special;
+ struct request *rq = SCpnt->request;
if (rq->cmd_flags & REQ_DISCARD) {
free_page((unsigned long)rq->buffer);
@@ -853,18 +857,10 @@ static void sd_unprep_fn(struct request_queue *q, struct request *rq)
}
}
-/**
- * sd_prep_fn - build a scsi (read or write) command from
- * information in the request structure.
- * @SCpnt: pointer to mid-level's per scsi command structure that
- * contains request and into which the scsi command is written
- *
- * Returns 1 if successful and 0 if error (or cannot be done now).
- **/
-static int sd_prep_fn(struct request_queue *q, struct request *rq)
+static int sd_init_command(struct scsi_cmnd *SCpnt)
{
- struct scsi_cmnd *SCpnt;
- struct scsi_device *sdp = q->queuedata;
+ struct request *rq = SCpnt->request;
+ struct scsi_device *sdp = SCpnt->device;
struct gendisk *disk = rq->rq_disk;
struct scsi_disk *sdkp;
sector_t block = blk_rq_pos(rq);
@@ -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)
@@ -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;
}
/**
@@ -2878,9 +2867,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) {
@@ -3028,8 +3014,6 @@ static int sd_remove(struct device *dev)
async_synchronize_full_domain(&scsi_sd_pm_domain);
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
@@ -79,6 +79,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM);
static DEFINE_MUTEX(sr_mutex);
static int sr_probe(struct device *);
static int sr_remove(struct device *);
+static int sr_init_command(struct scsi_cmnd *SCpnt);
static int sr_done(struct scsi_cmnd *);
static int sr_runtime_suspend(struct device *dev);
@@ -94,6 +95,7 @@ static struct scsi_driver sr_template = {
.remove = sr_remove,
.pm = &sr_pm_ops,
},
+ .init_command = sr_init_command,
.done = sr_done,
};
@@ -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;
@@ -517,7 +512,7 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
*/
ret = BLKPREP_OK;
out:
- return scsi_prep_return(q, rq, ret);
+ return ret;
}
static int sr_block_open(struct block_device *bdev, fmode_t mode)
@@ -718,7 +713,6 @@ static int sr_probe(struct device *dev)
/* FIXME: need to handle a get_capabilities failure properly ?? */
get_capabilities(cd);
- blk_queue_prep_rq(sdev->request_queue, sr_prep_fn);
sr_vendor_init(cd);
disk->driverfs_dev = &sdev->sdev_gendev;
@@ -993,7 +987,6 @@ static int sr_remove(struct device *dev)
scsi_autopm_get_device(cd->device);
- blk_queue_prep_rq(cd->device->request_queue, scsi_prep_fn);
del_gendisk(cd->disk);
mutex_lock(&sr_ref_mutex);
diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h
index 20fdfc2..36c4114 100644
--- a/include/scsi/scsi_driver.h
+++ b/include/scsi/scsi_driver.h
@@ -4,17 +4,17 @@
#include <linux/device.h>
struct module;
+struct request;
struct scsi_cmnd;
struct scsi_device;
-struct request;
-struct request_queue;
-
struct scsi_driver {
struct module *owner;
struct device_driver gendrv;
void (*rescan)(struct device *);
+ int (*init_command)(struct scsi_cmnd *);
+ void (*uninit_command)(struct scsi_cmnd *);
int (*done)(struct scsi_cmnd *);
int (*eh_action)(struct scsi_cmnd *, int);
};
@@ -31,8 +31,5 @@ extern int scsi_register_interface(struct class_interface *);
int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req);
int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req);
-int scsi_prep_state_check(struct scsi_device *sdev, struct request *req);
-int scsi_prep_return(struct request_queue *q, struct request *req, int ret);
-int scsi_prep_fn(struct request_queue *, struct request *);
#endif /* _SCSI_SCSI_DRIVER_H */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 4/4] scsi: handle command allocation failure in scsi_reset_provider
2014-05-01 14:51 scsi midlayer updates for 3.15 (resend) Christoph Hellwig
` (2 preceding siblings ...)
2014-05-01 14:51 ` [PATCH 3/4] scsi: reintroduce scsi_driver.init_command Christoph Hellwig
@ 2014-05-01 14:51 ` Christoph Hellwig
2014-05-08 7:11 ` Hannes Reinecke
2014-05-01 18:42 ` scsi midlayer updates for 3.15 (resend) Christoph Hellwig
4 siblings, 1 reply; 16+ messages in thread
From: Christoph Hellwig @ 2014-05-01 14:51 UTC (permalink / raw)
To: James Bottomley; +Cc: linux-scsi
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Nicholas Bellinger <nab@linux-iscsi.org>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
---
drivers/scsi/scsi_error.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index f17aa7a..abe51ea 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -2306,6 +2306,12 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
}
scmd = scsi_get_command(dev, GFP_KERNEL);
+ if (!scmd) {
+ rtn = FAILED;
+ put_device(&dev->sdev_gendev);
+ goto out_put_autopm_host;
+ }
+
blk_rq_init(NULL, &req);
scmd->request = &req;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: scsi midlayer updates for 3.15 (resend)
2014-05-01 14:51 scsi midlayer updates for 3.15 (resend) Christoph Hellwig
` (3 preceding siblings ...)
2014-05-01 14:51 ` [PATCH 4/4] scsi: handle command allocation failure in scsi_reset_provider Christoph Hellwig
@ 2014-05-01 18:42 ` Christoph Hellwig
4 siblings, 0 replies; 16+ messages in thread
From: Christoph Hellwig @ 2014-05-01 18:42 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: James Bottomley, linux-scsi
The subject line should of course read "... for 3.16", sorry.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 2/4] scsi: remove scsi_end_request
2014-05-01 14:51 ` [PATCH 2/4] scsi: remove scsi_end_request Christoph Hellwig
@ 2014-05-08 7:06 ` Hannes Reinecke
0 siblings, 0 replies; 16+ messages in thread
From: Hannes Reinecke @ 2014-05-08 7:06 UTC (permalink / raw)
To: Christoph Hellwig, James Bottomley; +Cc: linux-scsi
On 05/01/2014 04:51 PM, Christoph Hellwig wrote:
> By folding scsi_end_request into its only caller we can significantly clean
> up the completion logic. We can use simple goto labels now to only have
> a single place to finish or requeue command there instead of the previous
> convoluted logic.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Nicholas Bellinger <nab@linux-iscsi.org>
> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] scsi: reintroduce scsi_driver.init_command
2014-05-01 14:51 ` [PATCH 3/4] scsi: reintroduce scsi_driver.init_command Christoph Hellwig
@ 2014-05-08 7:11 ` Hannes Reinecke
0 siblings, 0 replies; 16+ messages in thread
From: Hannes Reinecke @ 2014-05-08 7:11 UTC (permalink / raw)
To: Christoph Hellwig, James Bottomley; +Cc: linux-scsi
On 05/01/2014 04:51 PM, Christoph Hellwig wrote:
> Instead of letting the ULD play games with the prep_fn move back to
> the model of a central prep_fn with a callback to the ULD. This
> already cleans up and shortens the code by itself, and will be required
> to properly support blk-mq in the SCSI midlayer.
>
... And leaving the device handler to still provide a prep_fn().
But that's for another day.
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Nicholas Bellinger <nab@linux-iscsi.org>
> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 4/4] scsi: handle command allocation failure in scsi_reset_provider
2014-05-01 14:51 ` [PATCH 4/4] scsi: handle command allocation failure in scsi_reset_provider Christoph Hellwig
@ 2014-05-08 7:11 ` Hannes Reinecke
0 siblings, 0 replies; 16+ messages in thread
From: Hannes Reinecke @ 2014-05-08 7:11 UTC (permalink / raw)
To: Christoph Hellwig, James Bottomley; +Cc: linux-scsi
On 05/01/2014 04:51 PM, Christoph Hellwig wrote:
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Nicholas Bellinger <nab@linux-iscsi.org>
> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2014-05-08 7:11 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-01 14:51 scsi midlayer updates for 3.15 (resend) Christoph Hellwig
2014-05-01 14:51 ` [PATCH 1/4] scsi: explicitly release bidi buffers Christoph Hellwig
2014-05-01 14:51 ` [PATCH 2/4] scsi: remove scsi_end_request Christoph Hellwig
2014-05-08 7:06 ` Hannes Reinecke
2014-05-01 14:51 ` [PATCH 3/4] scsi: reintroduce scsi_driver.init_command Christoph Hellwig
2014-05-08 7:11 ` Hannes Reinecke
2014-05-01 14:51 ` [PATCH 4/4] scsi: handle command allocation failure in scsi_reset_provider Christoph Hellwig
2014-05-08 7:11 ` Hannes Reinecke
2014-05-01 18:42 ` scsi midlayer updates for 3.15 (resend) Christoph Hellwig
-- strict thread matches above, loose matches on Subject: below --
2014-03-31 10:45 [PATCH 3/4] scsi: reintroduce scsi_driver.init_command Christoph Hellwig
2014-03-27 16:14 misc scsi midlayer updates Christoph Hellwig
2014-03-27 16:14 ` [PATCH 3/4] scsi: reintroduce scsi_driver.init_command Christoph Hellwig
2014-03-31 5:45 ` Nicholas A. Bellinger
2014-03-31 6:08 ` Christoph Hellwig
2014-03-31 6:20 ` Nicholas A. Bellinger
2014-03-31 6:56 ` Mike Christie
2014-03-31 8:09 ` Christoph Hellwig
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.