[SCSI] scsi_debug: remove the duplicated code in resp_read and resp_write
resp_read and resp_write performs READ_* and WRITE_* commands respectively. This sweeps up the similar code in them. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Acked-by: Douglas Gilbert <dougg@torque.net> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
28898873b0
commit
1978910062
|
@ -1468,25 +1468,53 @@ static int resp_log_sense(struct scsi_cmnd * scp,
|
||||||
min(len, SDEBUG_MAX_INQ_ARR_SZ));
|
min(len, SDEBUG_MAX_INQ_ARR_SZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
|
static int check_device_access_params(struct sdebug_dev_info *devi,
|
||||||
unsigned int num, struct sdebug_dev_info * devip)
|
unsigned long long lba, unsigned int num)
|
||||||
{
|
{
|
||||||
unsigned long iflags;
|
|
||||||
unsigned int block, from_bottom;
|
|
||||||
unsigned long long u;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (lba + num > sdebug_capacity) {
|
if (lba + num > sdebug_capacity) {
|
||||||
mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
|
mk_sense_buffer(devi, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0);
|
||||||
0);
|
|
||||||
return check_condition_result;
|
return check_condition_result;
|
||||||
}
|
}
|
||||||
/* transfer length excessive (tie in to block limits VPD page) */
|
/* transfer length excessive (tie in to block limits VPD page) */
|
||||||
if (num > sdebug_store_sectors) {
|
if (num > sdebug_store_sectors) {
|
||||||
mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
|
mk_sense_buffer(devi, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
|
||||||
0);
|
|
||||||
return check_condition_result;
|
return check_condition_result;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_device_access(struct scsi_cmnd *scmd,
|
||||||
|
struct sdebug_dev_info *devi,
|
||||||
|
unsigned long long lba, unsigned int num, int write)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned int block, rest = 0;
|
||||||
|
int (*func)(struct scsi_cmnd *, unsigned char *, int);
|
||||||
|
|
||||||
|
func = write ? fetch_to_dev_buffer : fill_from_dev_buffer;
|
||||||
|
|
||||||
|
block = do_div(lba, sdebug_store_sectors);
|
||||||
|
if (block + num > sdebug_store_sectors)
|
||||||
|
rest = block + num - sdebug_store_sectors;
|
||||||
|
|
||||||
|
ret = func(scmd, fake_storep + (block * SECT_SIZE),
|
||||||
|
(num - rest) * SECT_SIZE);
|
||||||
|
if (!ret && rest)
|
||||||
|
ret = func(scmd, fake_storep, rest * SECT_SIZE);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
|
||||||
|
unsigned int num, struct sdebug_dev_info *devip)
|
||||||
|
{
|
||||||
|
unsigned long iflags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = check_device_access_params(devip, lba, num);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
|
if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
|
||||||
(lba <= OPT_MEDIUM_ERR_ADDR) &&
|
(lba <= OPT_MEDIUM_ERR_ADDR) &&
|
||||||
((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
|
((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
|
||||||
|
@ -1505,74 +1533,30 @@ static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
|
||||||
return check_condition_result;
|
return check_condition_result;
|
||||||
}
|
}
|
||||||
read_lock_irqsave(&atomic_rw, iflags);
|
read_lock_irqsave(&atomic_rw, iflags);
|
||||||
if ((lba + num) <= sdebug_store_sectors)
|
ret = do_device_access(SCpnt, devip, lba, num, 0);
|
||||||
ret = fill_from_dev_buffer(SCpnt,
|
|
||||||
fake_storep + (lba * SECT_SIZE),
|
|
||||||
num * SECT_SIZE);
|
|
||||||
else {
|
|
||||||
/* modulo when one arg is 64 bits needs do_div() */
|
|
||||||
u = lba;
|
|
||||||
block = do_div(u, sdebug_store_sectors);
|
|
||||||
from_bottom = 0;
|
|
||||||
if ((block + num) > sdebug_store_sectors)
|
|
||||||
from_bottom = (block + num) - sdebug_store_sectors;
|
|
||||||
ret = fill_from_dev_buffer(SCpnt,
|
|
||||||
fake_storep + (block * SECT_SIZE),
|
|
||||||
(num - from_bottom) * SECT_SIZE);
|
|
||||||
if ((0 == ret) && (from_bottom > 0))
|
|
||||||
ret = fill_from_dev_buffer(SCpnt, fake_storep,
|
|
||||||
from_bottom * SECT_SIZE);
|
|
||||||
}
|
|
||||||
read_unlock_irqrestore(&atomic_rw, iflags);
|
read_unlock_irqrestore(&atomic_rw, iflags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
|
static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
|
||||||
unsigned int num, struct sdebug_dev_info * devip)
|
unsigned int num, struct sdebug_dev_info *devip)
|
||||||
{
|
{
|
||||||
unsigned long iflags;
|
unsigned long iflags;
|
||||||
unsigned int block, to_bottom;
|
int ret;
|
||||||
unsigned long long u;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
if (lba + num > sdebug_capacity) {
|
ret = check_device_access_params(devip, lba, num);
|
||||||
mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
|
if (ret)
|
||||||
0);
|
return ret;
|
||||||
return check_condition_result;
|
|
||||||
}
|
|
||||||
/* transfer length excessive (tie in to block limits VPD page) */
|
|
||||||
if (num > sdebug_store_sectors) {
|
|
||||||
mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
|
|
||||||
0);
|
|
||||||
return check_condition_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_lock_irqsave(&atomic_rw, iflags);
|
write_lock_irqsave(&atomic_rw, iflags);
|
||||||
if ((lba + num) <= sdebug_store_sectors)
|
ret = do_device_access(SCpnt, devip, lba, num, 1);
|
||||||
res = fetch_to_dev_buffer(SCpnt,
|
|
||||||
fake_storep + (lba * SECT_SIZE),
|
|
||||||
num * SECT_SIZE);
|
|
||||||
else {
|
|
||||||
/* modulo when one arg is 64 bits needs do_div() */
|
|
||||||
u = lba;
|
|
||||||
block = do_div(u, sdebug_store_sectors);
|
|
||||||
to_bottom = 0;
|
|
||||||
if ((block + num) > sdebug_store_sectors)
|
|
||||||
to_bottom = (block + num) - sdebug_store_sectors;
|
|
||||||
res = fetch_to_dev_buffer(SCpnt,
|
|
||||||
fake_storep + (block * SECT_SIZE),
|
|
||||||
(num - to_bottom) * SECT_SIZE);
|
|
||||||
if ((0 == res) && (to_bottom > 0))
|
|
||||||
res = fetch_to_dev_buffer(SCpnt, fake_storep,
|
|
||||||
to_bottom * SECT_SIZE);
|
|
||||||
}
|
|
||||||
write_unlock_irqrestore(&atomic_rw, iflags);
|
write_unlock_irqrestore(&atomic_rw, iflags);
|
||||||
if (-1 == res)
|
if (-1 == ret)
|
||||||
return (DID_ERROR << 16);
|
return (DID_ERROR << 16);
|
||||||
else if ((res < (num * SECT_SIZE)) &&
|
else if ((ret < (num * SECT_SIZE)) &&
|
||||||
(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
|
(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
|
||||||
printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "
|
printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "
|
||||||
" IO sent=%d bytes\n", num * SECT_SIZE, res);
|
" IO sent=%d bytes\n", num * SECT_SIZE, ret);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue