aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r--drivers/scsi/scsi_debug.c116
1 files changed, 50 insertions, 66 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 70bcee6516c2..c98559eceade 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1468,25 +1468,53 @@ static int resp_log_sense(struct scsi_cmnd * scp,
1468 min(len, SDEBUG_MAX_INQ_ARR_SZ)); 1468 min(len, SDEBUG_MAX_INQ_ARR_SZ));
1469} 1469}
1470 1470
1471static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba, 1471static int check_device_access_params(struct sdebug_dev_info *devi,
1472 unsigned int num, struct sdebug_dev_info * devip) 1472 unsigned long long lba, unsigned int num)
1473{ 1473{
1474 unsigned long iflags;
1475 unsigned int block, from_bottom;
1476 unsigned long long u;
1477 int ret;
1478
1479 if (lba + num > sdebug_capacity) { 1474 if (lba + num > sdebug_capacity) {
1480 mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 1475 mk_sense_buffer(devi, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0);
1481 0);
1482 return check_condition_result; 1476 return check_condition_result;
1483 } 1477 }
1484 /* transfer length excessive (tie in to block limits VPD page) */ 1478 /* transfer length excessive (tie in to block limits VPD page) */
1485 if (num > sdebug_store_sectors) { 1479 if (num > sdebug_store_sectors) {
1486 mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 1480 mk_sense_buffer(devi, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
1487 0);
1488 return check_condition_result; 1481 return check_condition_result;
1489 } 1482 }
1483 return 0;
1484}
1485
1486static int do_device_access(struct scsi_cmnd *scmd,
1487 struct sdebug_dev_info *devi,
1488 unsigned long long lba, unsigned int num, int write)
1489{
1490 int ret;
1491 unsigned int block, rest = 0;
1492 int (*func)(struct scsi_cmnd *, unsigned char *, int);
1493
1494 func = write ? fetch_to_dev_buffer : fill_from_dev_buffer;
1495
1496 block = do_div(lba, sdebug_store_sectors);
1497 if (block + num > sdebug_store_sectors)
1498 rest = block + num - sdebug_store_sectors;
1499
1500 ret = func(scmd, fake_storep + (block * SECT_SIZE),
1501 (num - rest) * SECT_SIZE);
1502 if (!ret && rest)
1503 ret = func(scmd, fake_storep, rest * SECT_SIZE);
1504
1505 return ret;
1506}
1507
1508static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
1509 unsigned int num, struct sdebug_dev_info *devip)
1510{
1511 unsigned long iflags;
1512 int ret;
1513
1514 ret = check_device_access_params(devip, lba, num);
1515 if (ret)
1516 return ret;
1517
1490 if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && 1518 if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
1491 (lba <= OPT_MEDIUM_ERR_ADDR) && 1519 (lba <= OPT_MEDIUM_ERR_ADDR) &&
1492 ((lba + num) > OPT_MEDIUM_ERR_ADDR)) { 1520 ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
@@ -1505,74 +1533,30 @@ static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
1505 return check_condition_result; 1533 return check_condition_result;
1506 } 1534 }
1507 read_lock_irqsave(&atomic_rw, iflags); 1535 read_lock_irqsave(&atomic_rw, iflags);
1508 if ((lba + num) <= sdebug_store_sectors) 1536 ret = do_device_access(SCpnt, devip, lba, num, 0);
1509 ret = fill_from_dev_buffer(SCpnt,
1510 fake_storep + (lba * SECT_SIZE),
1511 num * SECT_SIZE);
1512 else {
1513 /* modulo when one arg is 64 bits needs do_div() */
1514 u = lba;
1515 block = do_div(u, sdebug_store_sectors);
1516 from_bottom = 0;
1517 if ((block + num) > sdebug_store_sectors)
1518 from_bottom = (block + num) - sdebug_store_sectors;
1519 ret = fill_from_dev_buffer(SCpnt,
1520 fake_storep + (block * SECT_SIZE),
1521 (num - from_bottom) * SECT_SIZE);
1522 if ((0 == ret) && (from_bottom > 0))
1523 ret = fill_from_dev_buffer(SCpnt, fake_storep,
1524 from_bottom * SECT_SIZE);
1525 }
1526 read_unlock_irqrestore(&atomic_rw, iflags); 1537 read_unlock_irqrestore(&atomic_rw, iflags);
1527 return ret; 1538 return ret;
1528} 1539}
1529 1540
1530static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba, 1541static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
1531 unsigned int num, struct sdebug_dev_info * devip) 1542 unsigned int num, struct sdebug_dev_info *devip)
1532{ 1543{
1533 unsigned long iflags; 1544 unsigned long iflags;
1534 unsigned int block, to_bottom; 1545 int ret;
1535 unsigned long long u;
1536 int res;
1537 1546
1538 if (lba + num > sdebug_capacity) { 1547 ret = check_device_access_params(devip, lba, num);
1539 mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 1548 if (ret)
1540 0); 1549 return ret;
1541 return check_condition_result;
1542 }
1543 /* transfer length excessive (tie in to block limits VPD page) */
1544 if (num > sdebug_store_sectors) {
1545 mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
1546 0);
1547 return check_condition_result;
1548 }
1549 1550
1550 write_lock_irqsave(&atomic_rw, iflags); 1551 write_lock_irqsave(&atomic_rw, iflags);
1551 if ((lba + num) <= sdebug_store_sectors) 1552 ret = do_device_access(SCpnt, devip, lba, num, 1);
1552 res = fetch_to_dev_buffer(SCpnt,
1553 fake_storep + (lba * SECT_SIZE),
1554 num * SECT_SIZE);
1555 else {
1556 /* modulo when one arg is 64 bits needs do_div() */
1557 u = lba;
1558 block = do_div(u, sdebug_store_sectors);
1559 to_bottom = 0;
1560 if ((block + num) > sdebug_store_sectors)
1561 to_bottom = (block + num) - sdebug_store_sectors;
1562 res = fetch_to_dev_buffer(SCpnt,
1563 fake_storep + (block * SECT_SIZE),
1564 (num - to_bottom) * SECT_SIZE);
1565 if ((0 == res) && (to_bottom > 0))
1566 res = fetch_to_dev_buffer(SCpnt, fake_storep,
1567 to_bottom * SECT_SIZE);
1568 }
1569 write_unlock_irqrestore(&atomic_rw, iflags); 1553 write_unlock_irqrestore(&atomic_rw, iflags);
1570 if (-1 == res) 1554 if (-1 == ret)
1571 return (DID_ERROR << 16); 1555 return (DID_ERROR << 16);
1572 else if ((res < (num * SECT_SIZE)) && 1556 else if ((ret < (num * SECT_SIZE)) &&
1573 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) 1557 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
1574 printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, " 1558 printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "
1575 " IO sent=%d bytes\n", num * SECT_SIZE, res); 1559 " IO sent=%d bytes\n", num * SECT_SIZE, ret);
1576 return 0; 1560 return 0;
1577} 1561}
1578 1562