[SCSI] always handle REQ_BLOCK_PC requests in common code
LLDDs should never see REQ_BLOCK_PC requests, we can handle them just fine in the core code. There is a small behaviour change in that some check in sr's rw_intr are bypassed, but I consider the old behaviour a bug. Mike found this cleanup opportunity and provdided early patches, so all the credit goes to him, even if I redid the patches from scratch beause that was easier than forward-porting the old patches. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
committed by
James Bottomley
parent
d405423992
commit
776b23a036
@@ -1212,7 +1212,7 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scsi_generic_done(struct scsi_cmnd *cmd)
|
static void scsi_blk_pc_done(struct scsi_cmnd *cmd)
|
||||||
{
|
{
|
||||||
BUG_ON(!blk_pc_request(cmd->request));
|
BUG_ON(!blk_pc_request(cmd->request));
|
||||||
/*
|
/*
|
||||||
@@ -1224,7 +1224,7 @@ static void scsi_generic_done(struct scsi_cmnd *cmd)
|
|||||||
scsi_io_completion(cmd, cmd->bufflen, 0);
|
scsi_io_completion(cmd, cmd->bufflen, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
|
static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
|
||||||
{
|
{
|
||||||
struct request *req = cmd->request;
|
struct request *req = cmd->request;
|
||||||
|
|
||||||
@@ -1241,8 +1241,8 @@ void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
|
|||||||
cmd->transfersize = req->data_len;
|
cmd->transfersize = req->data_len;
|
||||||
cmd->allowed = req->retries;
|
cmd->allowed = req->retries;
|
||||||
cmd->timeout_per_command = req->timeout;
|
cmd->timeout_per_command = req->timeout;
|
||||||
|
cmd->done = scsi_blk_pc_done;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd);
|
|
||||||
|
|
||||||
static int scsi_prep_fn(struct request_queue *q, struct request *req)
|
static int scsi_prep_fn(struct request_queue *q, struct request *req)
|
||||||
{
|
{
|
||||||
@@ -1339,7 +1339,6 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
|
|||||||
* happening now.
|
* happening now.
|
||||||
*/
|
*/
|
||||||
if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
|
if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
|
||||||
struct scsi_driver *drv;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1371,16 +1370,17 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
|
|||||||
/*
|
/*
|
||||||
* Initialize the actual SCSI command for this request.
|
* Initialize the actual SCSI command for this request.
|
||||||
*/
|
*/
|
||||||
if (req->rq_disk) {
|
if (req->flags & REQ_BLOCK_PC) {
|
||||||
|
scsi_setup_blk_pc_cmnd(cmd);
|
||||||
|
} else if (req->rq_disk) {
|
||||||
|
struct scsi_driver *drv;
|
||||||
|
|
||||||
drv = *(struct scsi_driver **)req->rq_disk->private_data;
|
drv = *(struct scsi_driver **)req->rq_disk->private_data;
|
||||||
if (unlikely(!drv->init_command(cmd))) {
|
if (unlikely(!drv->init_command(cmd))) {
|
||||||
scsi_release_buffers(cmd);
|
scsi_release_buffers(cmd);
|
||||||
scsi_put_command(cmd);
|
scsi_put_command(cmd);
|
||||||
goto kill;
|
goto kill;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
scsi_setup_blk_pc_cmnd(cmd);
|
|
||||||
cmd->done = scsi_generic_done;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -232,34 +232,12 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
|
|||||||
**/
|
**/
|
||||||
static int sd_init_command(struct scsi_cmnd * SCpnt)
|
static int sd_init_command(struct scsi_cmnd * SCpnt)
|
||||||
{
|
{
|
||||||
unsigned int this_count, timeout;
|
|
||||||
struct gendisk *disk;
|
|
||||||
sector_t block;
|
|
||||||
struct scsi_device *sdp = SCpnt->device;
|
struct scsi_device *sdp = SCpnt->device;
|
||||||
struct request *rq = SCpnt->request;
|
struct request *rq = SCpnt->request;
|
||||||
|
struct gendisk *disk = rq->rq_disk;
|
||||||
timeout = sdp->timeout;
|
sector_t block = rq->sector;
|
||||||
|
unsigned int this_count = SCpnt->request_bufflen >> 9;
|
||||||
/*
|
unsigned int timeout = sdp->timeout;
|
||||||
* SG_IO from block layer already setup, just copy cdb basically
|
|
||||||
*/
|
|
||||||
if (blk_pc_request(rq)) {
|
|
||||||
scsi_setup_blk_pc_cmnd(SCpnt);
|
|
||||||
if (rq->timeout)
|
|
||||||
timeout = rq->timeout;
|
|
||||||
|
|
||||||
goto queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* we only do REQ_CMD and REQ_BLOCK_PC
|
|
||||||
*/
|
|
||||||
if (!blk_fs_request(rq))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
disk = rq->rq_disk;
|
|
||||||
block = rq->sector;
|
|
||||||
this_count = SCpnt->request_bufflen >> 9;
|
|
||||||
|
|
||||||
SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "
|
SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "
|
||||||
"count=%d\n", disk->disk_name,
|
"count=%d\n", disk->disk_name,
|
||||||
@@ -402,8 +380,6 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
|
|||||||
SCpnt->transfersize = sdp->sector_size;
|
SCpnt->transfersize = sdp->sector_size;
|
||||||
SCpnt->underflow = this_count << 9;
|
SCpnt->underflow = this_count << 9;
|
||||||
SCpnt->allowed = SD_MAX_RETRIES;
|
SCpnt->allowed = SD_MAX_RETRIES;
|
||||||
|
|
||||||
queue:
|
|
||||||
SCpnt->timeout_per_command = timeout;
|
SCpnt->timeout_per_command = timeout;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -837,15 +813,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
|
|||||||
relatively rare error condition, no care is taken to avoid
|
relatively rare error condition, no care is taken to avoid
|
||||||
unnecessary additional work such as memcpy's that could be avoided.
|
unnecessary additional work such as memcpy's that could be avoided.
|
||||||
*/
|
*/
|
||||||
|
if (driver_byte(result) != 0 &&
|
||||||
/*
|
|
||||||
* If SG_IO from block layer then set good_bytes to stop retries;
|
|
||||||
* else if errors, check them, and if necessary prepare for
|
|
||||||
* (partial) retries.
|
|
||||||
*/
|
|
||||||
if (blk_pc_request(SCpnt->request))
|
|
||||||
good_bytes = this_count;
|
|
||||||
else if (driver_byte(result) != 0 &&
|
|
||||||
sense_valid && !sense_deferred) {
|
sense_valid && !sense_deferred) {
|
||||||
switch (sshdr.sense_key) {
|
switch (sshdr.sense_key) {
|
||||||
case MEDIUM_ERROR:
|
case MEDIUM_ERROR:
|
||||||
|
@@ -238,8 +238,6 @@ static void rw_intr(struct scsi_cmnd * SCpnt)
|
|||||||
case ILLEGAL_REQUEST:
|
case ILLEGAL_REQUEST:
|
||||||
if (!(SCpnt->sense_buffer[0] & 0x90))
|
if (!(SCpnt->sense_buffer[0] & 0x90))
|
||||||
break;
|
break;
|
||||||
if (!blk_fs_request(SCpnt->request))
|
|
||||||
break;
|
|
||||||
error_sector = (SCpnt->sense_buffer[3] << 24) |
|
error_sector = (SCpnt->sense_buffer[3] << 24) |
|
||||||
(SCpnt->sense_buffer[4] << 16) |
|
(SCpnt->sense_buffer[4] << 16) |
|
||||||
(SCpnt->sense_buffer[5] << 8) |
|
(SCpnt->sense_buffer[5] << 8) |
|
||||||
@@ -317,23 +315,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* these are already setup, just copy cdb basically
|
|
||||||
*/
|
|
||||||
if (SCpnt->request->flags & REQ_BLOCK_PC) {
|
|
||||||
scsi_setup_blk_pc_cmnd(SCpnt);
|
|
||||||
|
|
||||||
if (SCpnt->timeout_per_command)
|
|
||||||
timeout = SCpnt->timeout_per_command;
|
|
||||||
|
|
||||||
goto queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(SCpnt->request->flags & REQ_CMD)) {
|
|
||||||
blk_dump_rq_flags(SCpnt->request, "sr unsup command");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we do lazy blocksize switching (when reading XA sectors,
|
* we do lazy blocksize switching (when reading XA sectors,
|
||||||
* see CDROMREADMODE2 ioctl)
|
* see CDROMREADMODE2 ioctl)
|
||||||
@@ -422,8 +403,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
|
|||||||
*/
|
*/
|
||||||
SCpnt->transfersize = cd->device->sector_size;
|
SCpnt->transfersize = cd->device->sector_size;
|
||||||
SCpnt->underflow = this_count << 9;
|
SCpnt->underflow = this_count << 9;
|
||||||
|
|
||||||
queue:
|
|
||||||
SCpnt->allowed = MAX_RETRIES;
|
SCpnt->allowed = MAX_RETRIES;
|
||||||
SCpnt->timeout_per_command = timeout;
|
SCpnt->timeout_per_command = timeout;
|
||||||
|
|
||||||
|
@@ -194,7 +194,6 @@ static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);
|
|||||||
|
|
||||||
static int st_probe(struct device *);
|
static int st_probe(struct device *);
|
||||||
static int st_remove(struct device *);
|
static int st_remove(struct device *);
|
||||||
static int st_init_command(struct scsi_cmnd *);
|
|
||||||
|
|
||||||
static void do_create_driverfs_files(void);
|
static void do_create_driverfs_files(void);
|
||||||
static void do_remove_driverfs_files(void);
|
static void do_remove_driverfs_files(void);
|
||||||
@@ -207,7 +206,6 @@ static struct scsi_driver st_template = {
|
|||||||
.probe = st_probe,
|
.probe = st_probe,
|
||||||
.remove = st_remove,
|
.remove = st_remove,
|
||||||
},
|
},
|
||||||
.init_command = st_init_command,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int st_compression(struct scsi_tape *, int);
|
static int st_compression(struct scsi_tape *, int);
|
||||||
@@ -4181,29 +4179,6 @@ static void scsi_tape_release(struct kref *kref)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void st_intr(struct scsi_cmnd *SCpnt)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The caller should be checking the request's errors
|
|
||||||
* value.
|
|
||||||
*/
|
|
||||||
scsi_io_completion(SCpnt, SCpnt->bufflen, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* st_init_command: only called via the scsi_cmd_ioctl (block SG_IO)
|
|
||||||
* interface for REQ_BLOCK_PC commands.
|
|
||||||
*/
|
|
||||||
static int st_init_command(struct scsi_cmnd *SCpnt)
|
|
||||||
{
|
|
||||||
if (!(SCpnt->request->flags & REQ_BLOCK_PC))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
scsi_setup_blk_pc_cmnd(SCpnt);
|
|
||||||
SCpnt->done = st_intr;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __init init_st(void)
|
static int __init init_st(void)
|
||||||
{
|
{
|
||||||
validate_options();
|
validate_options();
|
||||||
|
@@ -151,6 +151,5 @@ extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
|
|||||||
extern void scsi_put_command(struct scsi_cmnd *);
|
extern void scsi_put_command(struct scsi_cmnd *);
|
||||||
extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
|
extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
|
||||||
extern void scsi_finish_command(struct scsi_cmnd *cmd);
|
extern void scsi_finish_command(struct scsi_cmnd *cmd);
|
||||||
extern void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd);
|
|
||||||
|
|
||||||
#endif /* _SCSI_SCSI_CMND_H */
|
#endif /* _SCSI_SCSI_CMND_H */
|
||||||
|
Reference in New Issue
Block a user