Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19789100 authored by FUJITA Tomonori's avatar FUJITA Tomonori Committed by James Bottomley
Browse files

[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: default avatarFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Acked-by: default avatarDouglas Gilbert <dougg@torque.net>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 28898873
Loading
Loading
Loading
Loading
+50 −66
Original line number Diff line number Diff line
@@ -1468,25 +1468,53 @@ static int resp_log_sense(struct scsi_cmnd * scp,
		    min(len, SDEBUG_MAX_INQ_ARR_SZ));
}

static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
		     unsigned int num, struct sdebug_dev_info * devip)
static int check_device_access_params(struct sdebug_dev_info *devi,
				      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) {
		mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
				0);
		mk_sense_buffer(devi, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0);
		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);
		mk_sense_buffer(devi, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
		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) &&
	    (lba <= OPT_MEDIUM_ERR_ADDR) &&
	    ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
@@ -1505,24 +1533,7 @@ static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
		return check_condition_result;
	}
	read_lock_irqsave(&atomic_rw, iflags);
	if ((lba + num) <= sdebug_store_sectors)
		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);
	}
	ret = do_device_access(SCpnt, devip, lba, num, 0);
	read_unlock_irqrestore(&atomic_rw, iflags);
	return ret;
}
@@ -1531,48 +1542,21 @@ static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
		      unsigned int num, struct sdebug_dev_info *devip)
{
	unsigned long iflags;
	unsigned int block, to_bottom;
	unsigned long long u;
	int res;
	int ret;

	if (lba + num > sdebug_capacity) {
		mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
			       	0);
		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;
	}
	ret = check_device_access_params(devip, lba, num);
	if (ret)
		return ret;

	write_lock_irqsave(&atomic_rw, iflags);
	if ((lba + num) <= sdebug_store_sectors)
		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);
	}
	ret = do_device_access(SCpnt, devip, lba, num, 1);
	write_unlock_irqrestore(&atomic_rw, iflags);
	if (-1 == res)
	if (-1 == ret)
		return (DID_ERROR << 16);
	else if ((res < (num * SECT_SIZE)) &&
	else if ((ret < (num * SECT_SIZE)) &&
		 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
		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;
}