Пример #1
0
void readcapacity10_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)
{
	struct client_state *clnt = (struct client_state *)private_data;
	struct scsi_task *task = command_data;
	struct scsi_readcapacity10 *rc10;
	int full_size;

	if (status == ISCSI_STATUS_CHECK_CONDITION) {
		printf("Readcapacity10 failed with sense key:%d ascq:%04x\n", task->sense.key, task->sense.ascq);
		exit(10);
	}

	full_size = scsi_datain_getfullsize(task);
	if (full_size < task->datain.size) {
		printf("not enough data for full size readcapacity10\n");
		exit(10);
	}

	rc10 = scsi_datain_unmarshall(task);
	if (rc10 == NULL) {
		printf("failed to unmarshall readcapacity10 data\n");
		exit(10);
	}
	clnt->block_size = rc10->block_size;
	printf("READCAPACITY10 successful. Size:%d blocks  blocksize:%d. Read first block\n", rc10->lba, rc10->block_size);
	free(rc10);

	if (iscsi_read10_async(iscsi, clnt->lun, read10_cb, 0, clnt->block_size, clnt->block_size, private_data) != 0) {
		printf("failed to send read10 command\n");
		exit(10);
	}
}
Пример #2
0
void list_luns(const char *target, const char *portal)
{
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_reportluns_list *list;
	int full_report_size;
	int i;

	iscsi = iscsi_create_context(initiator);
	if (iscsi == NULL) {
		printf("Failed to create context\n");
		exit(10);
	}
	if (iscsi_set_targetname(iscsi, target)) {
		fprintf(stderr, "Failed to set target name\n");
		exit(10);
	}
	iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
	iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
	if (iscsi_connect_sync(iscsi, portal) != 0) {
		printf("iscsi_connect failed. %s\n", iscsi_get_error(iscsi));
		exit(10);
	}

	if (iscsi_login_sync(iscsi) != 0) {
		fprintf(stderr, "login failed :%s\n", iscsi_get_error(iscsi));
		exit(10);
	}


	/* get initial reportluns data, all targets can report 16 bytes but some
	 * fail if we ask for too much.
	 */
	if ((task = iscsi_reportluns_sync(iscsi, 0, 16)) == NULL) {
		fprintf(stderr, "reportluns failed : %s\n", iscsi_get_error(iscsi));
		exit(10);
	}
	full_report_size = scsi_datain_getfullsize(task);
	if (full_report_size > task->datain.size) {
		scsi_free_scsi_task(task);

		/* we need more data for the full list */
		if ((task = iscsi_reportluns_sync(iscsi, 0, full_report_size)) == NULL) {
			fprintf(stderr, "reportluns failed : %s\n", iscsi_get_error(iscsi));
			exit(10);
		}
	}

	list = scsi_datain_unmarshall(task);
	if (list == NULL) {
		fprintf(stderr, "failed to unmarshall reportluns datain blob\n");
		exit(10);
	}
	for (i=0; i < (int)list->num; i++) {
		show_lun(iscsi, list->luns[i]);
	}

	scsi_free_scsi_task(task);
	iscsi_destroy_context(iscsi);
}
Пример #3
0
void modesense6_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)
{
	struct client_state *clnt = (struct client_state *)private_data;
	struct scsi_task *task = command_data;
	int full_size;

	if (status == ISCSI_STATUS_CHECK_CONDITION) {
		printf("Modesense6 failed with sense key:%d ascq:%04x\n", task->sense.key, task->sense.ascq);
		exit(10);
	}

	full_size = scsi_datain_getfullsize(task);
	if (full_size > task->datain.size) {
		printf("did not get enough data for mode sense, sening modesense again asking for bigger buffer\n");
		if (iscsi_modesense6_async(iscsi, clnt->lun, modesense6_cb, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES, 0, full_size, private_data) != 0) {
			printf("failed to send modesense6 command\n");
			exit(10);
		}
		return;
	}

	printf("MODESENSE6 successful.\n");
	printf("Send READCAPACITY10\n");
	if (iscsi_readcapacity10_async(iscsi, clnt->lun, readcapacity10_cb, 0, 0, private_data) != 0) {
		printf("failed to send readcapacity command\n");
		exit(10);
	}
}
Пример #4
0
void do_inquiry(struct iscsi_context *iscsi, int lun, int evpd, int pc)
{
	struct scsi_task *task;
	int full_size;
	void *inq;

	/* See how big this inquiry data is */
	task = iscsi_inquiry_sync(iscsi, lun, evpd, pc, 64);
	if (task == NULL || task->status != SCSI_STATUS_GOOD) {
		fprintf(stderr, "Inquiry command failed : %s\n", iscsi_get_error(iscsi));
		exit(10);
	}

	full_size = scsi_datain_getfullsize(task);
	if (full_size > task->datain.size) {
		scsi_free_scsi_task(task);

		/* we need more data for the full list */
		if ((task = iscsi_inquiry_sync(iscsi, lun, evpd, pc, full_size)) == NULL) {
			fprintf(stderr, "Inquiry command failed : %s\n", iscsi_get_error(iscsi));
			exit(10);
		}
	}

	inq = scsi_datain_unmarshall(task);
	if (inq == NULL) {
		fprintf(stderr, "failed to unmarshall inquiry datain blob\n");
		exit(10);
	}

	if (evpd == 0) {
		inquiry_standard(inq);
	} else {
		switch (pc) {
		case SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES:
			inquiry_supported_pages(inq);
			break;
		case SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER:
			inquiry_unit_serial_number(inq);
			break;
		case SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION:
			inquiry_device_identification(inq);
			break;
		case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:
			inquiry_block_limits(inq);
			break;
		case SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS:
			inquiry_block_device_characteristics(inq);
			break;
		case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:
			inquiry_logical_block_provisioning(inq);
			break;
		default:
			fprintf(stderr, "Usupported pagecode:0x%02x\n", pc);
		}
	}
	scsi_free_scsi_task(task);
}
Пример #5
0
void reportluns_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)
{
	struct client_state *clnt = (struct client_state *)private_data;
	struct scsi_task *task = command_data;
	struct scsi_reportluns_list *list;
	uint32_t full_report_size;
	int i;

	if (status != ISCSI_STATUS_GOOD) {
		printf("Reportluns failed with unknown status code :%d\n", status);
		return;
	}

	full_report_size = scsi_datain_getfullsize(task);

	printf("REPORTLUNS status:%d   data size:%d,   full reports luns data size:%d\n", status, task->datain.size, full_report_size);
	if (full_report_size > task->datain.size) {
		printf("We did not get all the data we need in reportluns, ask again\n");
		if (iscsi_reportluns_async(iscsi, reportluns_cb, 0, full_report_size, private_data) != 0) {
			printf("failed to send reportluns command\n");
			exit(10);
		}
		return;
	}

	
	list = scsi_datain_unmarshall(task);
	if (list == NULL) {
		printf("failed to unmarshall reportluns datain blob\n");
		exit(10);
	}
	for (i=0; i < list->num; i++) {
		printf("LUN:%d found\n", list->luns[i]);
		clnt->lun = list->luns[i];
	}

	printf("Will use LUN:%d\n", clnt->lun);
	printf("Send testunitready to lun %d\n", clnt->lun);
	if (iscsi_testunitready_async(iscsi, clnt->lun, testunitready_cb, private_data) != 0) {
		printf("failed to send testunitready command\n");
		exit(10);
	}
}
Пример #6
0
int T0300_readonly(const char *initiator, const char *url)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_mode_sense *ms;
	int ret, lun;
	unsigned char data[4096];
	struct unmap_list list[1];
	int full_size;

	ret = -1;

	printf("0300_readonly:\n");
	printf("==============\n");
	if (show_info) {
		printf("Test that all commands that modify the medium fail for readonly devices\n");
		printf("1, WRITE10 at LUN 0 should fail.\n");
		printf("2, WRITE12 at LUN 0 should fail.\n");
		printf("3, WRITE16 at LUN 0 should fail.\n");
		printf("4, WRITESAME10 at LUN 0 should fail.\n");
		printf("5, WRITESAME16 at LUN 0 should fail.\n");
		printf("6, WRITESAME10 with UNMAP at LUN 0 should fail (skipped if not thin-provisioned).\n");
		printf("7, WRITESAME16 with UNMAP at LUN 0 should fail (skipped if not thin-provisioned).\n");
		printf("8, UNMAP at LUN 0 should fail (skipped if not thin-provisioned).\n");
		printf("9, WRITEVERIFY10 at LUN 0 should fail.\n");
		printf("10, WRITEVERIFY12 at LUN 0 should fail.\n");
		printf("11, WRITEVERIFY16 at LUN 0 should fail.\n");
		printf("12, COMPAREANDWRITE at LUN 0 should fail.\n");
		printf("13, ORWRITE at LUN 0 should fail.\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	if (!data_loss) {
		printf("--dataloss flag is not set. Skipping test\n");
		ret = -2;
		goto finished;
	}

	/* This test is only valid for SBC devices */
	if (device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
		printf("LUN is not SBC device. Skipping test\n");
		return -2;
	}

	/* verify the device is readonly */
	task = iscsi_modesense6_sync(iscsi, lun, 0, SCSI_MODESENSE_PC_CURRENT,
				     SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES, 0,
				     4);
	if (task == NULL) {
		printf("Failed to send modesense6 command: %s\n", iscsi_get_error(iscsi));
		goto finished;
	}
	full_size = scsi_datain_getfullsize(task);
	if (full_size > task->datain.size) {
		scsi_free_scsi_task(task);
		task = iscsi_modesense6_sync(iscsi, lun, 0, SCSI_MODESENSE_PC_CURRENT,
					     SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES, 0,
					     full_size);
		if (task == NULL) {
			printf("Failed to send modesense6 command: %s\n", iscsi_get_error(iscsi));
			goto finished;
		}
	}
	ms = scsi_datain_unmarshall(task);
	if (ms == NULL) {
		printf("failed to unmarshall mode sense datain blob\n");
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (!(ms->device_specific_parameter & 0x80)) {
		printf("Device is not read-only. Skipping test\n");
		ret = -2;
		goto finished;
	}
	scsi_free_scsi_task(task);


	ret = 0;


	/* Write one block at lba 0 */
	printf("WRITE10 to LUN 0 ... ");
	task = iscsi_write10_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITE10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITE10 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITE10 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITE12 to LUN 0 ... ");
	task = iscsi_write12_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITE12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITE12 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITE12 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITE16 to LUN 0 ... ");
	task = iscsi_write16_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITE16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITE16 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITE16 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITESAME10 to LUN 0 ... ");
	task = iscsi_writesame10_sync(iscsi, lun, data, block_size, 0, 1, 0, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITESAME10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITESAME10 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITESAME10 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITESAME16 to LUN 0 ... ");
	task = iscsi_writesame16_sync(iscsi, lun, data, block_size, 0, 1, 0, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITESAME16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITESAME16 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITESAME16 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* UNMAP one block at lba 0 */
	printf("WRITESAME10 to UNMAP LUN 0 ... ");
	if (lbpme == 0) {
		printf("LUN is not thin-provisioned. [SKIPPED]\n");
		goto finished;
	}
	task = iscsi_writesame10_sync(iscsi, lun, data, block_size, 0, 1, 0, 1, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITESAME10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITESAME10 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITESAME10 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* UNMAP one block at lba 0 */
	printf("WRITESAME16 to UNMAP LUN 0 ... ");
	if (lbpme == 0) {
		printf("LUN is not thin-provisioned. [SKIPPED]\n");
		goto finished;
	}
	task = iscsi_writesame16_sync(iscsi, lun, data, block_size, 0, 1, 0, 1, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITESAME16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITESAME16 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITESAME16 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* UNMAP one block at lba 0 */
	printf("UNMAP LUN 0 ... ");
	if (lbpme == 0) {
		printf("LUN is not thin-provisioned. [SKIPPED]\n");
		goto finished;
	}
	list[0].lba = 0;
	list[0].num = 1;
	task = iscsi_unmap_sync(iscsi, lun, 0, 0, &list[0], 1);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send UNMAP command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("UNMAP command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("UNMAP failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITEVERIFY10 to LUN 0 ... ");
	task = iscsi_writeverify10_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITEVERIFY10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITEVERIFY10 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITEVERIFY10 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITEVERIFY12 to LUN 0 ... ");
	task = iscsi_writeverify12_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITEVERIFY12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITEVERIFY12 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITEVERIFY12 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITEVERIFY16 to LUN 0 ... ");
	task = iscsi_writeverify16_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITEVERIFY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITEVERIFY16 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITEVERIFY16 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("COMPAREWRITE to LUN 0 ... ");
	task = iscsi_compareandwrite_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send COMPAREANDWRITE command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("COMPAREANDWRITE command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("COMPAREANDWRITE failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("ORWRITE to LUN 0 ... ");
	task = iscsi_orwrite_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send ORWRITE command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("ORWRITE command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("ORWRITE failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Пример #7
0
static int
mpath_check_matching_ids_serial_vpd(int num_sds,
				    struct scsi_device **sds)
{
	int i;
	int num_sds_with_valid_id = 0;
	struct scsi_task *inq_task = NULL;
	char *usn_saved = NULL;

	for (i = 0; i < num_sds; i++) {
		int full_size;
		struct scsi_inquiry_unit_serial_number *inq_serial;

		/*
		 * inquiry to confirm that all multipath devices carry an
		 * identical unit serial number.
		 */
		inq_task = NULL;
		inquiry(sds[i], &inq_task, 1,
			SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER, 64,
			EXPECT_STATUS_GOOD);
		if (inq_task && inq_task->status != SCSI_STATUS_GOOD) {
			printf("Inquiry command failed : %s\n",
			       sds[i]->error_str);
			goto err_cleanup;
		}
		full_size = scsi_datain_getfullsize(inq_task);
		if (full_size > inq_task->datain.size) {
			scsi_free_scsi_task(inq_task);

			/* we need more data */
			inq_task = NULL;
			inquiry(sds[i], &inq_task, 1,
				SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER,
				full_size,
				EXPECT_STATUS_GOOD);
			if (inq_task == NULL) {
				printf("Inquiry command failed : %s\n",
				       sds[i]->error_str);
				goto err_cleanup;
			}
		}

		inq_serial = scsi_datain_unmarshall(inq_task);
		if (inq_serial == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			goto err_cleanup;
		}

		if (inq_serial->qualifier
			       != SCSI_INQUIRY_PERIPHERAL_QUALIFIER_CONNECTED) {
			printf("error: multipath device not connected\n");
			goto err_cleanup;
		}

		if (inq_serial->device_type
			 != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
			printf("error: multipath devices must be SBC\n");
			goto err_cleanup;
		}

		if (inq_serial->usn == NULL) {
			printf("error: empty usn for multipath device\n");
			goto err_cleanup;
		}

		if (usn_saved == NULL) {
			usn_saved = strdup(inq_serial->usn);
			if (usn_saved == NULL) {
				goto err_cleanup;
			}
			num_sds_with_valid_id++;
		} else if (strcmp(usn_saved, inq_serial->usn) == 0) {
			num_sds_with_valid_id++;
		} else {
			printf("multipath unit serial mismatch: %s != %s\n",
			       usn_saved, inq_serial->usn);
		}

		scsi_free_scsi_task(inq_task);
		inq_task = NULL;
	}

	if (num_sds_with_valid_id != num_sds) {
		printf("failed to find matching serial number for all paths\n");
		goto err_cleanup;
	}

	printf("found matching serial number for all (%d) paths: %s\n",
	       num_sds, usn_saved);
	free(usn_saved);

	return 0;

err_cleanup:
	free(usn_saved);
	scsi_free_scsi_task(inq_task);
	return -1;
}
Пример #8
0
static int
mpath_check_matching_ids_devid_vpd(int num_sds,
				   struct scsi_device **sds)
{
	int i;
	int num_sds_with_valid_id = 0;
	struct scsi_task *inq_task = NULL;
	struct scsi_inquiry_device_designator *des_saved = NULL;

	for (i = 0; i < num_sds; i++) {
		int ret;
		int full_size;
		struct scsi_inquiry_device_identification *inq_id_data;
		struct scsi_inquiry_device_designator *des;

		/*
		 * dev ID inquiry to confirm that all multipath devices carry
		 * an identical logical unit identifier.
		 */
		inquiry(sds[i], &inq_task, 1,
			SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION,
			64,
			EXPECT_STATUS_GOOD);
		if (inq_task && inq_task->status != SCSI_STATUS_GOOD) {
			printf("Inquiry command failed : %s\n",
			       sds[i]->error_str);
			goto err_cleanup;
		}
		full_size = scsi_datain_getfullsize(inq_task);
		if (full_size > inq_task->datain.size) {
			/* we need more data */
			scsi_free_scsi_task(inq_task);
			inq_task = NULL;
			inquiry(sds[i], &inq_task, 1,
				SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION,
				full_size,
				EXPECT_STATUS_GOOD);
			if (inq_task == NULL) {
				printf("Inquiry command failed : %s\n",
				       sds[i]->error_str);
				goto err_cleanup;
			}
		}

		inq_id_data = scsi_datain_unmarshall(inq_task);
		if (inq_id_data == NULL) {
			printf("failed to unmarshall inquiry ID datain blob\n");
			goto err_cleanup;
		}

		if (inq_id_data->qualifier
			       != SCSI_INQUIRY_PERIPHERAL_QUALIFIER_CONNECTED) {
			printf("error: multipath device not connected\n");
			goto err_cleanup;
		}

		if (inq_id_data->device_type
			 != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
			printf("error: multipath devices must be SBC\n");
			goto err_cleanup;
		}

		/* walk the list of IDs, and find a suitable LU candidate */
		for (des = inq_id_data->designators;
		     des != NULL;
		     des = des->next) {
			if (des->association != SCSI_ASSOCIATION_LOGICAL_UNIT) {
				printf("skipping non-LU designator: %d\n",
				       des->association);
				continue;
			}

			if ((des->designator_type != SCSI_DESIGNATOR_TYPE_EUI_64)
			 && (des->designator_type != SCSI_DESIGNATOR_TYPE_NAA)
			 && (des->designator_type != SCSI_DESIGNATOR_TYPE_MD5_LOGICAL_UNIT_IDENTIFIER)
			 && (des->designator_type != SCSI_DESIGNATOR_TYPE_SCSI_NAME_STRING)) {
				printf("skipping unsupported des type: %d\n",
				       des->designator_type);
				continue;
			}

			if (des->designator_length <= 0) {
				printf("skipping designator with bad len: %d\n",
				       des->designator_length);
				continue;
			}

			if (des_saved == NULL) {
				ret = mpath_des_copy(des, &des_saved);
				if (ret < 0) {
					goto err_cleanup;
				}
				/*
				 * we now have a reference to look for in all
				 * subsequent paths.
				 */
				num_sds_with_valid_id++;
				break;
			} else if (mpath_des_cmp(des, des_saved) == 0) {
				/* found match for previous path designator */
				num_sds_with_valid_id++;
				break;
			}
			/* no match yet, keep checking other designators */
		}

		scsi_free_scsi_task(inq_task);
		inq_task = NULL;
	}
	mpath_des_free(des_saved);

	if (num_sds_with_valid_id != num_sds) {
		printf("failed to find matching LU device ID for all paths\n");
		return -1;
	}

	printf("found matching LU device identifier for all (%d) paths\n",
	       num_sds);
	return 0;

err_cleanup:
	mpath_des_free(des_saved);
	scsi_free_scsi_task(inq_task);
	return -1;
}
Пример #9
0
int T0400_inquiry_basic(const char *initiator, const char *url)
{
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_inquiry_standard *inq;
	int ret, lun, i;
	int full_size;

	printf("0400_inquiry_basic:\n");
	printf("===================\n");
	if (show_info) {
		printf("Test the standard INQUIRY data format.\n");
		printf("1, Check we can read the standard INQUIRY data.\n");
		printf("2, Standard data must be at least 36 bytes in size.\n");
		printf("3, Device-type must be either of DISK/TAPE/CDROM.\n");
		printf("4, Check that peripheral-qualifier field is 0.\n");
		printf("5, Check that the version field is valid.\n");
		printf("6, Check that response-data-format is valid.\n");
		printf("7, Check that additional-length is valid.\n");
		printf("8, Verify HiSup flag is set.\n");
		printf("9, Verify vendor-identification is in ASCII.\n");
		printf("10, Verify product-identification is in ASCII.\n");
		printf("11, Verify product-revision-level is in ASCII.\n");
		printf("12, Verify AERC is clear in SPC-3 and later.\n");
		printf("13, Verify TrmTsk is clear in SPC-2 and later.\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}


	ret = 0;



	printf("Read standard INQUIRY data ... ");
	/* See how big this inquiry data is */
	task = iscsi_inquiry_sync(iscsi, lun, 0, 0, 255);
	if (task == NULL) {
		printf("[FAILED]\n");
		printf("Failed to send INQUIRY command : %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("[FAILED]\n");
		printf("INQUIRY command failed : %s\n", iscsi_get_error(iscsi));
		scsi_free_scsi_task(task);
		ret = -1;
		goto finished;
	}
	full_size = scsi_datain_getfullsize(task);
	if (full_size > task->datain.size) {
		scsi_free_scsi_task(task);

		/* we need more data for the full list */
		if ((task = iscsi_inquiry_sync(iscsi, lun, 0, 0, full_size)) == NULL) {
			printf("[FAILED]\n");
			printf("Inquiry command failed : %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto finished;
		}
	}
	inq = scsi_datain_unmarshall(task);
	if (inq == NULL) {
		printf("[FAILED]\n");
		printf("failed to unmarshall inquiry datain blob\n");
		scsi_free_scsi_task(task);
		ret = -1;
		goto finished;
	}
	printf("[OK]\n");

	printf("Check that standard data is >= 36 bytes in size ... ");
	if (full_size < 36) {
		printf("[FAILED]\n");
		printf("Standard INQUIRY data is less than 36 bytes.\n");
		scsi_free_scsi_task(task);
		ret = -1;
		goto finished;
	}
	printf("[OK]\n");

	printf("Check device-type is either of DISK, TAPE or CD/DVD  ... ");
	switch (inq->device_type) {
	case SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS:
	case SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_SEQUENTIAL_ACCESS:
	case SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_MMC:
		break;
	default:
		printf("[FAILED]\n");
		printf("Device-type is not DISK, TAPE or CD/DVD. Device reported:%s\n", scsi_devtype_to_str(inq->device_type));
		ret = -1;
		goto test4;
	}
	printf("[OK]\n");


test4:
	printf("Check PREIPHERAL QUALIFIER FIELD is 0  ... ");
	if (inq->qualifier != 0) {
		printf("[FAILED]\n");
		printf("QUALIFIER was not 0, it was %d\n", inq->qualifier);
		ret = -1;
		goto test5;
	}
	printf("[OK]\n");

test5:
	printf("Check VERSION field is either 0x4, 0x5 or 0x6 ... ");
	switch (inq->version) {
	case 0x4: /* SPC-2 */
	case 0x5: /* SPC-3 */
	case 0x6: /* SPC-4 */
		break;
	default:
		printf("[FAILED]\n");
		printf("Invalid VERSION:%d. Should be 0x4, 0x5 or 0x6\n", inq->version);
		ret = -1;
		goto test6;
	}
	printf("[OK]\n");

test6:
	printf("Check RESPONSE DATA FORMAT is 2 ... ");
	if (inq->response_data_format != 2) {
		printf("[FAILED]\n");
		printf("Invalid RESPONSE_DATA_FORMAT:%d. Should be 2\n", inq->response_data_format);
		ret = -1;
		goto test7;
	}
	printf("[OK]\n");

test7:
	printf("Verify Additional-Length ... ");
	if (inq->additional_length + 5 != full_size) {
		printf("[FAILED]\n");
		printf("Invalid additional-length. Was %d but should be %d\n", inq->additional_length, full_size-5);
		ret = -1;
		goto test8;
	}
	printf("[OK]\n");

test8:
	printf("Verify HiSup is set ... ");
	if (!inq->hisup) {
		printf("[FAILED]\n");
		printf("HiSup flag is not set.\n");
		ret = -1;
		goto test9;
	}
	printf("[OK]\n");

test9:
	printf("Verify VENDOR_IDENTIFICATION is in ASCII ... ");
	for (i = 8; i < 16; i++) {
		/* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */
		if (task->datain.data[i] == 0) {
			continue;
		}
		if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) {
			continue;
		}

		printf("[FAILED]\n");
		printf("VENDOR_IDENTIFICATION contains non-ASCII characters\n");
		ret = -1;
		goto test10;
	}
	printf("[OK]\n");

test10:
	printf("Verify PRODUCT_IDENTIFICATION is in ASCII ... ");
	for (i = 16; i < 32; i++) {
		/* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */
		if (task->datain.data[i] == 0) {
			continue;
		}
		if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) {
			continue;
		}

		printf("[FAILED]\n");
		printf("PRODUCT_IDENTIFICATION contains non-ASCII characters\n");
		ret = -1;
		goto test11;
	}
	printf("[OK]\n");

test11:
	printf("Verify PRODUCT_REVISION_LEVEL is in ASCII ... ");
	for (i = 32; i < 36; i++) {
		/* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */
		if (task->datain.data[i] == 0) {
			continue;
		}
		if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) {
			continue;
		}

		printf("[FAILED]\n");
		printf("PRODUCT_REVISION_LEVEL contains non-ASCII characters\n");
		ret = -1;
		goto test12;
	}
	printf("[OK]\n");

test12:
	printf("Verify AERC is clear in SPC-3 and later ... ");
	if (task->datain.data[3] & 0x80 && inq->version >= 5) {
		printf("[FAILED]\n");
		printf("AERC is set but this device reports SPC-3 or later\n");
		ret = -1;
		goto test13;
	}
	printf("[OK]\n");

test13:
	printf("Verify TrmTsk is clear in SPC-2 and later ... ");
	if (task->datain.data[3] & 0x40 && inq->version >= 4) {
		printf("[FAILED]\n");
		printf("TrmTsk is set but this device reports SPC-2 or later\n");
		ret = -1;
		goto test14;
	}
	printf("[OK]\n");

test14:



	scsi_free_scsi_task(task);


finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
int T0430_report_all_supported_ops(const char *initiator, const char *url, int data_loss, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_report_supported_op_codes *rsoc;
	struct scsi_command_descriptor *desc;
	int ret, lun, i;
	int full_size, desc_size;

	printf("0430_report_all_supported_ops:\n");
	printf("===================\n");
	if (show_info) {
		printf("Test MaintenanceIn: Report Supported Operations.\n");
		printf("1, Report Supported Ops (no timeout information).\n");
		printf("2, Report Supported Ops (with timeout information).\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	ret = 0;

	printf("See if Report Supported Opcodes is supported... ");
	/* See how big data is */
	task = iscsi_report_supported_opcodes_sync(iscsi, lun, 0, 4);
	if (task == NULL) {
		printf("[FAILED]\n");
		printf("Failed to send Report Supported Opcodes command : %s\n", 
		       iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_CHECK_CONDITION
	    && task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST
	    && task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
		printf("[SKIPPED]\n");
		printf("REPORT SUPPORTED OPCODES command failed : %s\n", 
		       iscsi_get_error(iscsi));
		scsi_free_scsi_task(task);
		ret = -2;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("[FAILED]\n");
		printf("REPORT SUPPORTED OPCODES command failed : %s\n", 
		       iscsi_get_error(iscsi));
		scsi_free_scsi_task(task);
		ret = -1;
		goto finished;
	}
	full_size = scsi_datain_getfullsize(task);

	if (full_size > task->datain.size) {
		scsi_free_scsi_task(task);
		/* we need more data for the full list */
		if ((task = iscsi_report_supported_opcodes_sync(iscsi, lun,  0, full_size)) == NULL) {
			printf("[FAILED]\n");
			printf("REPORT SUPPORTED OPCODES failed : %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto finished;
		}
	}
	rsoc = scsi_datain_unmarshall(task);
	if (rsoc == NULL) {
		printf("[FAILED]\n");
		printf("failed to unmarshall REPORT SUPPORTED OPCODES datain blob\n");
		scsi_free_scsi_task(task);
		ret = -1;
		goto finished;
	}

	printf("Supported Commands: %d\n", rsoc->num_descriptors);
	printf("=======================\n");
	for (i=0; i < rsoc->num_descriptors; i++) {
		printf("op:%x\tsa:%x\tcdb length:%d\n",
		       rsoc->descriptors[i].op_code,
		       rsoc->descriptors[i].service_action,
		       rsoc->descriptors[i].cdb_length);
	}

	printf("\n[OK]\n");
	scsi_free_scsi_task(task);


test2:
	/*Report All Supported Operations including timeout info.*/
	printf("See if Report Supported Opcodes with Timeouts is supported... ");
	/* See how big data is */
	task = iscsi_report_supported_opcodes_sync(iscsi, lun, 1, 4);
	if (task == NULL) {
		printf("[FAILED]\n");
		printf("Failed to send Report Supported Opcodes command : %s\n", 
		       iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_CHECK_CONDITION
	    && task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST
	    && (task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE 
		|| task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB)) {
		printf("[SKIPPED]\n");
		printf("REPORT SUPPORTED OPCODES command failed : %s\n", 
		       iscsi_get_error(iscsi));
		scsi_free_scsi_task(task);
		ret = -2;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("[FAILED]\n");
		printf("REPORT SUPPORTED OPCODES command failed : %s\n", 
		       iscsi_get_error(iscsi));
		scsi_free_scsi_task(task);
		ret = -1;
		goto finished;
	}
	full_size = scsi_datain_getfullsize(task);

	if (full_size > task->datain.size) {
		scsi_free_scsi_task(task);

		/* we need more data for the full list */
		if ((task = iscsi_report_supported_opcodes_sync(iscsi, lun,  1, full_size)) == NULL) {
			printf("[FAILED]\n");
			printf("REPORT SUPPORTED OPCODES failed : %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto finished;
		}
	}
	rsoc = scsi_datain_unmarshall(task);
	if (rsoc == NULL) {
		printf("[FAILED]\n");
		printf("failed to unmarshall REPORT SUPPORTED OPCODES datain blob\n");
		scsi_free_scsi_task(task);
		ret = -1;
		goto finished;
	}

	printf("Supported Commands (with timeout information): %d\n", rsoc->num_descriptors);
	printf("=======================\n");
	desc_size = sizeof (struct scsi_command_descriptor)
		+  sizeof (struct scsi_op_timeout_descriptor);
	desc = &rsoc->descriptors[0];
	for (i=0; i < rsoc->num_descriptors; i++) {
		printf("op:%x\tsa:%x\tcdb_length:%d\ttimeout info: length:%d\tcommand specific:%x\tnominal processing%d\trecommended%d\n",
		       desc->op_code,
		       desc->service_action,
		       desc->cdb_length,
		       desc->to[0].descriptor_length,
		       desc->to[0].command_specific,
		       desc->to[0].nominal_processing_timeout,
		       desc->to[0].recommended_timeout);
		desc = (struct scsi_command_descriptor *)((char *)desc + 
							  desc_size);
	}

	printf("\n[OK]\n");
	scsi_free_scsi_task(task);

finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Пример #11
0
int
main(int argc, char *argv[])
{
	char *testname_re = NULL;
	int lun;
	CU_BasicRunMode mode = CU_BRM_VERBOSE;
	CU_ErrorAction error_action = CUEA_IGNORE;
	int res;
	struct scsi_readcapacity10 *rc10;
	struct scsi_task *inq_task = NULL;
	struct scsi_task *inq_lbp_task = NULL;
	struct scsi_task *inq_bdc_task = NULL;
	struct scsi_task *inq_bl_task = NULL;
	struct scsi_task *rc16_task = NULL;
	struct scsi_task *rsop_task = NULL;
	int full_size;
	int is_usb = 0;
	int xml_mode = 0;
	static struct option long_opts[] = {
		{ "help", no_argument, 0, '?' },
		{ "list", no_argument, 0, 'l' },
		{ "initiator-name", required_argument, 0, 'i' },
		{ "initiator-name-2", required_argument, 0, 'I' },
		{ "test", required_argument, 0, 't' },
		{ "dataloss", no_argument, 0, 'd' },
		{ "allow-sanitize", no_argument, 0, 'S' },
		{ "ignore", no_argument, 0, 'g' },
		{ "fail", no_argument, 0, 'f' },
		{ "abort", no_argument, 0, 'A' },
		{ "silent", no_argument, 0, 's' },
		{ "normal", no_argument, 0, 'n' },
		{ "usb", no_argument, 0, 'u' },
		{ "verbose", no_argument, 0, 'v' },
		{ "xml", no_argument, 0, 'x' },
		{ "Verbose-scsi", no_argument, 0, 'V' },
		{ NULL, 0, 0, 0 }
	};
	int i, c;
	int opt_idx = 0;

	while ((c = getopt_long(argc, argv, "?hli:I:t:sdgfAsSnuvxV", long_opts,
		    &opt_idx)) > 0) {
		switch (c) {
		case 'h':
		case '?':
			print_usage();
			return 0;
		case 'l':
			list_all_tests();
			return 0;
		case 'i':
			initiatorname1 = strdup(optarg);
			break;
		case 'I':
			initiatorname2 = strdup(optarg);
			break;
		case 't':
			testname_re = strdup(optarg);
			break;
		case 'd':
			data_loss++;
			break;
		case 'g':
			error_action = CUEA_IGNORE; /* default */
			break;
		case 'f':
			error_action = CUEA_FAIL;
			break;
		case 'A':
			error_action = CUEA_ABORT;
			break;
		case 's':
			mode = CU_BRM_SILENT;
			break;
		case 'S':
			allow_sanitize = 1;
			break;
		case 'n':
			mode = CU_BRM_NORMAL;
			break;
		case 'u':
			is_usb = 1;
			break;
		case 'v':
			mode = CU_BRM_VERBOSE;	/* default */
			break;
		case 'x':
		        xml_mode = 1;
			break;
		case 'V':
			loglevel = LOG_VERBOSE;
			break;
		default:
			fprintf(stderr,
			    "error: unknown option return: %c (option %s)\n",
			    c, argv[optind]);
			return 1;
		}
	}

	if (optind < argc) {
		tgt_url = strdup(argv[optind++]);
	}
	if (optind < argc) {
		fprintf(stderr, "error: too many arguments\n");
		print_usage();
		return 1;
	}

	/* XXX why is this done? */
	real_iscsi_queue_pdu = dlsym(RTLD_NEXT, "iscsi_queue_pdu");

	if (tgt_url == NULL) {
		fprintf(stderr, "You must specify the URL\n");
		print_usage();
		if (testname_re)
			free(testname_re);
		return 10;
	}

	iscsic = iscsi_context_login(initiatorname1, tgt_url, &lun);
	if (iscsic == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	/*
	 * find the size of the LUN
	 * All devices support readcapacity10 but only some support
	 * readcapacity16
	 */
	task = iscsi_readcapacity10_sync(iscsic, lun, 0, 0);
	if (task == NULL) {
		printf("Failed to send READCAPACITY10 command: %s\n",
		    iscsi_get_error(iscsic));
		iscsi_destroy_context(iscsic);
		return -1;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY10 command: failed with sense. %s\n",
		    iscsi_get_error(iscsic));
		scsi_free_scsi_task(task);
		iscsi_destroy_context(iscsic);
		return -1;
	}
	rc10 = scsi_datain_unmarshall(task);
	if (rc10 == NULL) {
		printf("failed to unmarshall READCAPACITY10 data. %s\n",
		    iscsi_get_error(iscsic));
		scsi_free_scsi_task(task);
		iscsi_destroy_context(iscsic);
		return -1;
	}
	block_size = rc10->block_size;
	num_blocks = rc10->lba + 1;
	scsi_free_scsi_task(task);

	rc16_task = iscsi_readcapacity16_sync(iscsic, lun);
	if (rc16_task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n",
		    iscsi_get_error(iscsic));
		iscsi_destroy_context(iscsic);
		return -1;
	}
	if (rc16_task->status == SCSI_STATUS_GOOD) {
		rc16 = scsi_datain_unmarshall(rc16_task);
		if (rc16 == NULL) {
			printf("failed to unmarshall READCAPACITY16 data. %s\n",
			    iscsi_get_error(iscsic));
			scsi_free_scsi_task(rc16_task);
			iscsi_destroy_context(iscsic);
			return -1;
		}
		block_size = rc16->block_length;
		num_blocks = rc16->returned_lba + 1;
		lbppb = 1 << rc16->lbppbe;
	}

	inq_task = iscsi_inquiry_sync(iscsic, lun, 0, 0, 64);
	if (inq_task == NULL || inq_task->status != SCSI_STATUS_GOOD) {
		printf("Inquiry command failed : %s\n", iscsi_get_error(iscsic));
		return -1;
	}
	full_size = scsi_datain_getfullsize(inq_task);
	if (full_size > inq_task->datain.size) {
		scsi_free_scsi_task(inq_task);

		/* we need more data for the full list */
		inq_task = iscsi_inquiry_sync(iscsic, lun, 0, 0, full_size);
		if (inq_task == NULL) {
			printf("Inquiry command failed : %s\n",
			    iscsi_get_error(iscsic));
			return -1;
		}
	}
	inq = scsi_datain_unmarshall(inq_task);
	if (inq == NULL) {
		printf("failed to unmarshall inquiry datain blob\n");
		scsi_free_scsi_task(inq_task);
		return -1;
	}

	sbc3_support = 0;
	for (i = 0; i < 8; i++) {
		if (inq->version_descriptor[i] == 0x04C0) {
			sbc3_support = 1;
		}
	}

	/* try reading block limits vpd */
	inq_bl_task = iscsi_inquiry_sync(iscsic, lun, 1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, 64);
	if (inq_bl_task && inq_bl_task->status != SCSI_STATUS_GOOD) {
		scsi_free_scsi_task(inq_bl_task);
		inq_bl_task = NULL;
	}
	if (inq_bl_task) {
		full_size = scsi_datain_getfullsize(inq_bl_task);
		if (full_size > inq_bl_task->datain.size) {
			scsi_free_scsi_task(inq_bl_task);

			if ((inq_bl_task = iscsi_inquiry_sync(iscsic, lun, 1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, full_size)) == NULL) {
				printf("Inquiry command failed : %s\n", iscsi_get_error(iscsic));
				return -1;
			}
		}

		inq_bl = scsi_datain_unmarshall(inq_bl_task);
		if (inq_bl == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			return -1;
		}
	}

	/* try reading block device characteristics vpd */
	inq_bdc_task = iscsi_inquiry_sync(iscsic, lun, 1, SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS, 255);
	if (inq_bdc_task == NULL) {
		printf("Failed to read Block Device Characteristics page\n");
	}
	if (inq_bdc_task) {
		inq_bdc = scsi_datain_unmarshall(inq_bdc_task);
		if (inq_bdc == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			return -1;
		}
	}

	/* if thin provisioned we also need to read the VPD page for it */
	if (rc16 && rc16->lbpme != 0){
		inq_lbp_task = iscsi_inquiry_sync(iscsic, lun, 1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, 64);
		if (inq_lbp_task == NULL || inq_lbp_task->status != SCSI_STATUS_GOOD) {
			printf("Inquiry command failed : %s\n", iscsi_get_error(iscsic));
			return -1;
		}
		full_size = scsi_datain_getfullsize(inq_lbp_task);
		if (full_size > inq_lbp_task->datain.size) {
			scsi_free_scsi_task(inq_lbp_task);

			/* we need more data for the full list */
			if ((inq_lbp_task = iscsi_inquiry_sync(iscsic, lun, 1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, full_size)) == NULL) {
				printf("Inquiry command failed : %s\n", iscsi_get_error(iscsic));
				return -1;
			}
		}

		inq_lbp = scsi_datain_unmarshall(inq_lbp_task);
		if (inq_lbp == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			return -1;
		}
	}

	rsop_task = iscsi_report_supported_opcodes_sync(iscsic, lun,
		1, SCSI_REPORT_SUPPORTING_OPS_ALL, 0, 0, 65535);
	if (rsop_task == NULL) {
		printf("Failed to send REPORT_SUPPORTED_OPCODES command: %s\n",
		    iscsi_get_error(iscsic));
		iscsi_destroy_context(iscsic);
		return -1;
	}
	if (rsop_task->status == SCSI_STATUS_GOOD) {
		rsop = scsi_datain_unmarshall(rsop_task);
		if (rsop == NULL) {
			printf("failed to unmarshall REPORT_SUPPORTED_OPCODES "
			       "data. %s\n",
			       iscsi_get_error(iscsic));
			scsi_free_scsi_task(rsop_task);
		}
	}

	/* check if the device is write protected or not */
	task = iscsi_modesense6_sync(iscsic, lun, 0, SCSI_MODESENSE_PC_CURRENT,
				     SCSI_MODEPAGE_RETURN_ALL_PAGES,
				     0, 255);
	if (task == NULL) {
		printf("Failed to send MODE_SENSE6 command: %s\n",
		    iscsi_get_error(iscsic));
		iscsi_destroy_context(iscsic);
		return -1;
	}
	if (task->status == SCSI_STATUS_GOOD) {
		struct scsi_mode_sense *ms;

		ms = scsi_datain_unmarshall(task);
		if (ms == NULL) {
			printf("failed to unmarshall mode sense datain blob\n");
			scsi_free_scsi_task(task);
			return -1;
		}
		readonly = !!(ms->device_specific_parameter & 0x80);
	}
	scsi_free_scsi_task(task);

	iscsi_logout_sync(iscsic);
	iscsi_destroy_context(iscsic);

	if (is_usb) {
		printf("USB device. Clamping maximum transfer length to 120k\n");
		maximum_transfer_length = 120 *1024 / block_size;
	}

	if (CU_initialize_registry() != 0) {
		fprintf(stderr, "error: unable to initialize test registry\n");
		return 1;
	}
	if (CU_is_test_running()) {
		fprintf(stderr, "error: test suite(s) already running!?\n");
		exit(1);
	}

	parse_and_add_tests(testname_re);
	if (testname_re)
		free(testname_re);

	CU_basic_set_mode(mode);
	CU_set_error_action(error_action);
	printf("\n");

	/*
	 * this actually runs the tests ...
	 */

	if (xml_mode) {
	  CU_list_tests_to_file();
	  CU_automated_run_tests();
	} else {
	  res = CU_basic_run_tests();
	  printf("Tests completed with return value: %d\n", res);
	}

	CU_cleanup_registry();
	free(discard_const(tgt_url));

	if (inq_task != NULL) {
		scsi_free_scsi_task(inq_task);
	}
	if (inq_bl_task != NULL) {
		scsi_free_scsi_task(inq_bl_task);
	}
	if (inq_lbp_task != NULL) {
		scsi_free_scsi_task(inq_lbp_task);
	}
	if (inq_bdc_task != NULL) {
		scsi_free_scsi_task(inq_bdc_task);
	}
	if (rc16_task != NULL) {
		scsi_free_scsi_task(rc16_task);
	}
	if (rsop_task != NULL) {
		scsi_free_scsi_task(rsop_task);
	}

	return 0;
}
Пример #12
0
int T0180_writesame10_unmap(const char *initiator, const char *url)
{
    struct iscsi_context *iscsi;
    struct scsi_task *task;
    int full_size;
    struct scsi_inquiry_logical_block_provisioning *lbp;
    int ret, i, lun;

    printf("0180_writesame10_unmap:\n");
    printf("=======================\n");
    if (show_info) {
        printf("Test basic WRITESAME10-UNMAP functionality.\n");
        printf("1, If LBPME==1 we should have VPD page 0xB2\n");
        printf("2, UNMAP the first 1-256 blocks at the start of the LUN\n");
        printf("3, UNMAP the last 1-256 blocks at the end of the LUN\n");
        printf("4, Verify that UNMAP == 0 and ANCHOR == 1 is invalid\n");
        printf("5, UNMAP == 1 and ANCHOR == 1\n");
        printf("\n");
        return 0;
    }

    iscsi = iscsi_context_login(initiator, url, &lun);
    if (iscsi == NULL) {
        printf("Failed to login to target\n");
        return -1;
    }

    ret = 0;

    if (rc16 == NULL || rc16->lbpme == 0) {
        printf("Logical unit is fully provisioned. All commands should fail with check condition.\n");
    }

    /* Check that id we have logical block provisioning we also have the VPD page for it */
    printf("Logical Block Provisioning is available. Check that VPD page 0xB2 exists ... ");

    /* See how big this inquiry data is */
    task = iscsi_inquiry_sync(iscsi, lun, 1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, 64);
    if (task == NULL || task->status != SCSI_STATUS_GOOD) {
        printf("[FAILED]\n");
        printf("Inquiry command failed : %s\n", iscsi_get_error(iscsi));
        ret = -1;
        goto finished;
    }
    full_size = scsi_datain_getfullsize(task);
    if (full_size > task->datain.size) {
        scsi_free_scsi_task(task);

        /* we need more data for the full list */
        if ((task = iscsi_inquiry_sync(iscsi, lun, 1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, full_size)) == NULL) {
            printf("[FAILED]\n");
            printf("Inquiry command failed : %s\n", iscsi_get_error(iscsi));
            ret = -1;
            goto finished;
        }
    }

    lbp = scsi_datain_unmarshall(task);
    if (lbp == NULL) {
        printf("failed to unmarshall inquiry datain blob\n");
        scsi_free_scsi_task(task);
        ret = -1;
        goto finished;
    }
    printf("[OK]\n");

    if (lbp->lbpws10 == 0) {
        printf("Device does not support WRITE_SAME10 for UNMAP. All WRITE_SAME10 commands to unmap should fail.\n");
    }

    if (!data_loss) {
        printf("--dataloss flag is not set. Skipping test\n");
        ret = -2;
        goto finished;
    }

    ret = 0;

    /* unmap the first 1 - 256 blocks at the start of the LUN */
    printf("Unmapping first 1-256 blocks ... ");
    if (lbp->lbpws10 == 0) {
        printf("(Should all fail since LBPWS10 is 0) ");
    }
    for (i=1; i<=256; i++) {
        /* only try unmapping whole physical blocks, of if unmap using ws10 is not supported
           we test for all and they should all fail */
        if (lbp->lbpws10 == 1 && i % lbppb) {
            continue;
        }
        task = iscsi_writesame10_sync(iscsi, lun, 0,
                                      NULL, 0,
                                      i,
                                      0, 1, 0, 0);
        if (task == NULL) {
            printf("[FAILED]\n");
            printf("Failed to send WRITESAME10 command: %s\n", iscsi_get_error(iscsi));
            ret = -1;
            goto finished;
        }
        if (task->status        == SCSI_STATUS_CHECK_CONDITION
                && task->sense.key  == SCSI_SENSE_ILLEGAL_REQUEST
                && task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
            printf("[SKIPPED]\n");
            printf("Opcode is not implemented on target\n");
            scsi_free_scsi_task(task);
            ret = -2;
            goto finished;
        }
        if (lbp->lbpws10) {
            if (task->status != SCSI_STATUS_GOOD) {
                printf("[FAILED]\n");
                printf("WRITESAME10 command: failed with sense. %s\n", iscsi_get_error(iscsi));
                scsi_free_scsi_task(task);
                ret = -1;
                goto finished;
            }
        } else {
            if (task->status        != SCSI_STATUS_CHECK_CONDITION
                    || task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
                    || task->sense.ascq != SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB) {
                printf("[FAILED]\n");
                printf("WRITESAME10 command should fail since LBPWS10 is 0 but failed with wrong sense code %s\n", iscsi_get_error(iscsi));
                scsi_free_scsi_task(task);
                ret = -1;
                goto finished;
            }
        }

        scsi_free_scsi_task(task);
    }
    printf("[OK]\n");


    /* unmap the last 1 - 256 blocks at the end of the LUN */
    printf("Unmapping last 1-256 blocks ... ");
    if (lbp->lbpws10 == 0) {
        printf("(Should all fail since LBPWS10 is 0) ");
    }
    for (i=1; i<=256; i++) {
        /* only try unmapping whole physical blocks, of if unmap using ws10 is not supported
           we test for all and they should all fail */
        if (lbp->lbpws10 == 1 && i % lbppb) {
            continue;
        }

        task = iscsi_writesame10_sync(iscsi, lun, num_blocks + 1 - i,
                                      NULL, 0,
                                      i,
                                      0, 1, 0, 0);
        if (task == NULL) {
            printf("[FAILED]\n");
            printf("Failed to send WRITESAME10 command: %s\n", iscsi_get_error(iscsi));
            ret = -1;
            goto finished;
        }
        if (lbp->lbpws10) {
            if (task->status != SCSI_STATUS_GOOD) {
                printf("[FAILED]\n");
                printf("WRITESAME10 command: failed with sense. %s\n", iscsi_get_error(iscsi));
                scsi_free_scsi_task(task);
                ret = -1;
                goto finished;
            }
        } else {
            if (task->status        != SCSI_STATUS_CHECK_CONDITION
                    || task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
                    || task->sense.ascq != SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB) {
                printf("[FAILED]\n");
                printf("WRITESAME10 command should fail since LBPWS10 is 0 but failed with wrong sense code %s\n", iscsi_get_error(iscsi));
                scsi_free_scsi_task(task);
                ret = -1;
                goto finished;
            }
        }
        scsi_free_scsi_task(task);
    }
    printf("[OK]\n");


    /* Test that UNMAP=0 and ANCHOR==1 fails with check condition */
    printf("Try UNMAP==0 and ANCHOR==1 ... ");
    task = iscsi_writesame10_sync(iscsi, lun, 0,
                                  NULL, 0,
                                  64,
                                  1, 0, 0, 0);
    if (task == NULL) {
        printf("[FAILED]\n");
        printf("Failed to send WRITESAME10 command: %s\n", iscsi_get_error(iscsi));
        ret = -1;
        goto finished;
    }
    if (task->status        != SCSI_STATUS_CHECK_CONDITION
            || task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
            || task->sense.ascq != SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB) {
        printf("[FAILED]\n");
        printf("WRITESAME10 with UNMAP=0 ANCHOR=1 failed with wrong sense code %d %s(%d) %s(0x%04x)   should be CHECK_CONDITION/ILLEGAL_REQUEST/INVALID_FIELD_IN_CDB\n",
               task->status,
               scsi_sense_key_str(task->sense.key), task->sense.key,
               scsi_sense_ascq_str(task->sense.ascq), task->sense.ascq);
        scsi_free_scsi_task(task);
        ret = -1;
        goto finished;
    }
    scsi_free_scsi_task(task);
    printf("[OK]\n");


    /* Test UNMAP=1 and ANCHOR==1 */
    printf("Try UNMAP==1 and ANCHOR==1 ... ");
    if (lbp->anc_sup == 0) {
        printf("(ANC_SUP==0 so check condition expected) ");
    }
    task = iscsi_writesame10_sync(iscsi, lun, 0,
                                  NULL, 0,
                                  64,
                                  1, 1, 0, 0);
    if (task == NULL) {
        printf("[FAILED]\n");
        printf("Failed to send WRITESAME10 command: %s\n", iscsi_get_error(iscsi));
        ret = -1;
        goto finished;
    }
    if (lbp->anc_sup == 0) {
        if (task->status        != SCSI_STATUS_CHECK_CONDITION
                || task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
                || task->sense.ascq != SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB) {
            printf("[FAILED]\n");
            printf("WRITESAME10 with UNMAP=1 ANCHOR=1 failed with wrong sense code %d %s(%d) %s(0x%04x)   should be CHECK_CONDITION/ILLEGAL_REQUEST/INVALID_FIELD_IN_CDB\n",
                   task->status,
                   scsi_sense_key_str(task->sense.key), task->sense.key,
                   scsi_sense_ascq_str(task->sense.ascq), task->sense.ascq);
            scsi_free_scsi_task(task);
            ret = -1;
            goto finished;
        }
    } else {
        if (task->status != SCSI_STATUS_GOOD) {
            printf("[FAILED]\n");
            printf("WRITESAME10 command: failed with sense. %s\n", iscsi_get_error(iscsi));
            scsi_free_scsi_task(task);
            ret = -1;
            goto finished;
        }
    }
    scsi_free_scsi_task(task);
    printf("[OK]\n");


finished:
    iscsi_logout_sync(iscsi);
    iscsi_destroy_context(iscsi);
    return ret;
}
Пример #13
0
int
main(int argc, char *argv[])
{
	char *testname_re = NULL;
	CU_BasicRunMode mode = CU_BRM_VERBOSE;
	CU_ErrorAction error_action = CUEA_IGNORE;
	int res;
	struct scsi_readcapacity10 *rc10;
	struct scsi_task *inq_task = NULL;
	struct scsi_task *inq_lbp_task = NULL;
	struct scsi_task *inq_bdc_task = NULL;
	struct scsi_task *inq_bl_task = NULL;
	struct scsi_task *rc16_task = NULL;
	struct scsi_task *rsop_task = NULL;
	int full_size;
	int xml_mode = 0;
	static struct option long_opts[] = {
		{ "help", no_argument, 0, '?' },
		{ "list", no_argument, 0, 'l' },
		{ "initiator-name", required_argument, 0, 'i' },
		{ "initiator-name-2", required_argument, 0, 'I' },
		{ "test", required_argument, 0, 't' },
		{ "dataloss", no_argument, 0, 'd' },
		{ "allow-sanitize", no_argument, 0, 'S' },
		{ "ignore", no_argument, 0, 'g' },
		{ "fail", no_argument, 0, 'f' },
		{ "abort", no_argument, 0, 'A' },
		{ "silent", no_argument, 0, 's' },
		{ "normal", no_argument, 0, 'n' },
		{ "verbose", no_argument, 0, 'v' },
		{ "xml", no_argument, 0, 'x' },
		{ "Verbose-scsi", no_argument, 0, 'V' },
		{ NULL, 0, 0, 0 }
	};
	int i, c;
	int opt_idx = 0;

	while ((c = getopt_long(argc, argv, "?hli:I:t:sdgfAsSnvxV", long_opts,
		    &opt_idx)) > 0) {
		switch (c) {
		case 'h':
		case '?':
			print_usage();
			return 0;
		case 'l':
			list_all_tests();
			return 0;
		case 'i':
			initiatorname1 = strdup(optarg);
			break;
		case 'I':
			initiatorname2 = strdup(optarg);
			break;
		case 't':
			testname_re = strdup(optarg);
			break;
		case 'd':
			data_loss++;
			break;
		case 'g':
			error_action = CUEA_IGNORE; /* default */
			break;
		case 'f':
			error_action = CUEA_FAIL;
			break;
		case 'A':
			error_action = CUEA_ABORT;
			break;
		case 's':
			mode = CU_BRM_SILENT;
			break;
		case 'S':
			allow_sanitize = 1;
			break;
		case 'n':
			mode = CU_BRM_NORMAL;
			break;
		case 'v':
			mode = CU_BRM_VERBOSE;	/* default */
			break;
		case 'x':
		        xml_mode = 1;
			break;
		case 'V':
			loglevel = LOG_VERBOSE;
			break;
		default:
			fprintf(stderr,
			    "error: unknown option return: %c (option %s)\n",
			    c, argv[optind]);
			return 1;
		}
	}

	/* parse all trailing arguments as device paths */
	mp_num_sds = 0;
	while (optind < argc) {
		if (mp_num_sds >= MPATH_MAX_DEVS) {
			fprintf(stderr, "Too many multipath device URLs\n");
			print_usage();
			free(testname_re);
			return 10;
		}

		mp_sds[mp_num_sds] = malloc(sizeof(struct scsi_device));
		memset(mp_sds[mp_num_sds], '\0', sizeof(struct scsi_device));
		mp_sds[mp_num_sds]->sgio_fd = -1;

		if (!strncmp(argv[optind], "iscsi://", 8)) {
			mp_sds[mp_num_sds]->iscsi_url = strdup(argv[optind++]);
#ifdef HAVE_SG_IO
		} else {
			mp_sds[mp_num_sds]->sgio_dev = strdup(argv[optind++]);
#endif
		}
		mp_num_sds++;
	}

	/* So that we can override iscsi_queue_pdu in tests
	 * and replace or mutate the blob that we are about to write to the
	 * wire.
	 * This allows such tests to do their mutates and then call out
	 * to the real queueing function once they have modified the data.
	 */
	real_iscsi_queue_pdu = dlsym(RTLD_NEXT, "iscsi_queue_pdu");

	if ((mp_num_sds == 0) || (mp_sds[0]->iscsi_url == NULL
					&& mp_sds[0]->sgio_dev == NULL)) {
#ifdef HAVE_SG_IO
		fprintf(stderr, "You must specify either an iSCSI URL or a device file\n");
#else
		fprintf(stderr, "You must specify an iSCSI URL\n");
#endif
		print_usage();
		if (testname_re)
			free(testname_re);
		return 10;
	}

	/* sd remains an alias for the first device */
	sd = mp_sds[0];

	for (i = 0; i < mp_num_sds; i++) {
		res = connect_scsi_device(mp_sds[i], initiatorname1);
		if (res < 0) {
			fprintf(stderr,
				"Failed to connect to SCSI device %d\n", i);
			goto err_sds_free;
		}
	}

	if (mp_num_sds > 1) {
		/* check that all multipath sds identify as the same LU */
		res = mpath_check_matching_ids(mp_num_sds, mp_sds);
		if (res < 0) {
			fprintf(stderr, "multipath devices don't match\n");
			goto err_sds_free;
		}
	}

	/*
	 * find the size of the LUN
	 * All devices support readcapacity10 but only some support
	 * readcapacity16
	 */
	task = NULL;
	readcapacity10(sd, &task, 0, 0, EXPECT_STATUS_GOOD);
	if (task == NULL) {
		printf("Failed to send READCAPACITY10 command: %s\n", sd->error_str);
		goto err_sds_free;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY10 command: failed with sense. %s\n", sd->error_str);
		scsi_free_scsi_task(task);
		goto err_sds_free;
	}
	rc10 = scsi_datain_unmarshall(task);
	if (rc10 == NULL) {
		printf("failed to unmarshall READCAPACITY10 data.\n");
		scsi_free_scsi_task(task);
		goto err_sds_free;
	}
	block_size = rc10->block_size;
	num_blocks = rc10->lba + 1;
	scsi_free_scsi_task(task);

	rc16_task = NULL;
	readcapacity16(sd, &rc16_task, 96, EXPECT_STATUS_GOOD);
	if (rc16_task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", sd->error_str);
		goto err_sds_free;
	}
	if (rc16_task->status == SCSI_STATUS_GOOD) {
		rc16 = scsi_datain_unmarshall(rc16_task);
		if (rc16 == NULL) {
			printf("failed to unmarshall READCAPACITY16 data. %s\n", sd->error_str);
			scsi_free_scsi_task(rc16_task);
			goto err_sds_free;
		}
		block_size = rc16->block_length;
		num_blocks = rc16->returned_lba + 1;
		lbppb = 1 << rc16->lbppbe;
	}

	inq_task = NULL;
	inquiry(sd, &inq_task, 0, 0, 64, EXPECT_STATUS_GOOD);
	if (inq_task == NULL || inq_task->status != SCSI_STATUS_GOOD) {
		printf("Inquiry command failed : %s\n", sd->error_str);
		goto err_sds_free;
	}
	full_size = scsi_datain_getfullsize(inq_task);
	if (full_size > inq_task->datain.size) {
		scsi_free_scsi_task(inq_task);

		/* we need more data for the full list */
		inq_task = NULL;
		inquiry(sd, &inq_task, 0, 0, full_size, EXPECT_STATUS_GOOD);
		if (inq_task == NULL) {
			printf("Inquiry command failed : %s\n", sd->error_str);
			goto err_sds_free;
		}
	}
	inq = scsi_datain_unmarshall(inq_task);
	if (inq == NULL) {
		printf("failed to unmarshall inquiry datain blob\n");
		scsi_free_scsi_task(inq_task);
		goto err_sds_free;
	}

	sbc3_support = 0;
	for (i = 0; i < 8; i++) {
		if (inq->version_descriptor[i] == 0x04C0) {
			sbc3_support = 1;
		}
	}

	/* try reading block limits vpd */
	inq_bl_task = NULL;
	inquiry(sd, &inq_bl_task, 1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, 64, EXPECT_STATUS_GOOD);
	if (inq_bl_task && inq_bl_task->status != SCSI_STATUS_GOOD) {
		scsi_free_scsi_task(inq_bl_task);
		inq_bl_task = NULL;
	}
	if (inq_bl_task) {
		full_size = scsi_datain_getfullsize(inq_bl_task);
		if (full_size > inq_bl_task->datain.size) {
			scsi_free_scsi_task(inq_bl_task);

			inq_bl_task = NULL;
			inquiry(sd, &inq_bl_task, 1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, full_size,
				EXPECT_STATUS_GOOD);
			if (inq_bl_task == NULL) {
				printf("Inquiry command failed : %s\n", sd->error_str);
				goto err_sds_free;
			}
		}

		inq_bl = scsi_datain_unmarshall(inq_bl_task);
		if (inq_bl == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			goto err_sds_free;
		}
	}

	/* try reading block device characteristics vpd */
	inquiry(sd, &inq_bdc_task, 1, SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS, 255,
		EXPECT_STATUS_GOOD);
	if (inq_bdc_task == NULL || inq_bdc_task->status != SCSI_STATUS_GOOD) {
		printf("Failed to read Block Device Characteristics page\n");
	} else {
		inq_bdc = scsi_datain_unmarshall(inq_bdc_task);
		if (inq_bdc == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			goto err_sds_free;
		}
	}

	/* if thin provisioned we also need to read the VPD page for it */
	if (rc16 && rc16->lbpme != 0){
		inq_lbp_task = NULL;
		inquiry(sd, &inq_lbp_task, 1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, 64,
			EXPECT_STATUS_GOOD);
		if (inq_lbp_task == NULL || inq_lbp_task->status != SCSI_STATUS_GOOD) {
			printf("Inquiry command failed : %s\n", sd->error_str);
			goto err_sds_free;
		}
		full_size = scsi_datain_getfullsize(inq_lbp_task);
		if (full_size > inq_lbp_task->datain.size) {
			scsi_free_scsi_task(inq_lbp_task);

			/* we need more data for the full list */
			inq_lbp_task = NULL;
			inquiry(sd, &inq_lbp_task, 1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
				full_size, EXPECT_STATUS_GOOD);
			if (inq_lbp_task == NULL) {
				printf("Inquiry command failed : %s\n", sd->error_str);
				goto err_sds_free;
			}
		}

		inq_lbp = scsi_datain_unmarshall(inq_lbp_task);
		if (inq_lbp == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			goto err_sds_free;
		}
	}

	rsop_task = NULL;
	report_supported_opcodes(sd, &rsop_task, 1, SCSI_REPORT_SUPPORTING_OPS_ALL, 0, 0, 65535,
				 EXPECT_STATUS_GOOD);
	if (rsop_task == NULL) {
		printf("Failed to send REPORT_SUPPORTED_OPCODES command: %s\n", sd->error_str);
		goto err_sds_free;
	}
	if (rsop_task->status == SCSI_STATUS_GOOD) {
		rsop = scsi_datain_unmarshall(rsop_task);
		if (rsop == NULL) {
			printf("failed to unmarshall REPORT_SUPPORTED_OPCODES data.\n");
			scsi_free_scsi_task(rsop_task);
			rsop_task = NULL;
		}
	}

	/* check if the device is write protected or not */
	task = NULL;
	modesense6(sd, &task, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
		   EXPECT_STATUS_GOOD);
	if (task == NULL) {
		printf("Failed to send MODE_SENSE6 command: %s\n", sd->error_str);
		goto err_sds_free;
	}
	if (task->status == SCSI_STATUS_GOOD) {
		struct scsi_mode_sense *ms;

		ms = scsi_datain_unmarshall(task);
		if (ms == NULL) {
			printf("failed to unmarshall mode sense datain blob\n");
			scsi_free_scsi_task(task);
			goto err_sds_free;
		}
		readonly = !!(ms->device_specific_parameter & 0x80);
	}
	scsi_free_scsi_task(task);

	if (maxsectbytes) {
		maximum_transfer_length = maxsectbytes / block_size;
		printf("Bus transfer size is limited to %d bytes. Clamping "
		       "max transfers accordingly.\n", maxsectbytes);
	}

	if (CU_initialize_registry() != 0) {
		fprintf(stderr, "error: unable to initialize test registry\n");
		goto err_sds_free;
	}
	if (CU_is_test_running()) {
		fprintf(stderr, "error: test suite(s) already running!?\n");
		exit(1);
	}

	parse_and_add_tests(testname_re);
	if (testname_re)
		free(testname_re);

	CU_basic_set_mode(mode);
	CU_set_error_action(error_action);
	printf("\n");

	/*
	 * this actually runs the tests ...
	 */

	if (xml_mode) {
	  CU_list_tests_to_file();
	  CU_automated_run_tests();
	} else {
	  res = CU_basic_run_tests();
	  printf("Tests completed with return value: %d\n", res);
	}

	CU_cleanup_registry();

	if (inq_task != NULL) {
		scsi_free_scsi_task(inq_task);
	}
	if (inq_bl_task != NULL) {
		scsi_free_scsi_task(inq_bl_task);
	}
	if (inq_lbp_task != NULL) {
		scsi_free_scsi_task(inq_lbp_task);
	}
	if (inq_bdc_task != NULL) {
		scsi_free_scsi_task(inq_bdc_task);
	}
	if (rc16_task != NULL) {
		scsi_free_scsi_task(rc16_task);
	}
	if (rsop_task != NULL) {
		scsi_free_scsi_task(rsop_task);
	}
	for (i = 0; i < mp_num_sds; i++) {
		free_scsi_device(mp_sds[i]);
	}

	return 0;

err_sds_free:
	for (i = 0; i < mp_num_sds; i++) {
		free_scsi_device(mp_sds[i]);
	}
	return -1;
}
Пример #14
0
int T0103_read10_rdprotect(const char *initiator, const char *url, int data_loss _U_, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	int full_size;
	struct scsi_inquiry_standard *inq;
	int ret, i, lun;

	printf("0103_read10_rdprotect:\n");
	printf("======================\n");
	if (show_info) {
		printf("Test how READ10 handles the rdprotect bits\n");
		printf("1, Any non-zero valued for rdprotect should fail.\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	/* See how big this inquiry data is */
	task = iscsi_inquiry_sync(iscsi, lun, 0, 0, 64);
	if (task == NULL || task->status != SCSI_STATUS_GOOD) {
		printf("Inquiry command failed : %s\n", iscsi_get_error(iscsi));
		return -1;
	}
	full_size = scsi_datain_getfullsize(task);
	if (full_size > task->datain.size) {
		scsi_free_scsi_task(task);

		/* we need more data for the full list */
		if ((task = iscsi_inquiry_sync(iscsi, lun, 0, 0, full_size)) == NULL) {
			printf("Inquiry command failed : %s\n", iscsi_get_error(iscsi));
			return -1;
		}
	}

	inq = scsi_datain_unmarshall(task);
	if (inq == NULL) {
		printf("failed to unmarshall inquiry datain blob\n");
		scsi_free_scsi_task(task);
		return -1;
	}

	if (inq->periperal_device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
		printf("LUN is not SBC device. Skipping test\n");
		scsi_free_scsi_task(task);
		return -1;
	}

	if (inq->protect) {
		printf("LUN is formatted with protection information. Skipping test\n");
		scsi_free_scsi_task(task);
		return -1;
	}

	scsi_free_scsi_task(task);


	ret = 0;

	/* Try out Different non-zero values for RDPROTECT. They should all fail */
	printf("Read10 with non-zero RDPROTECT ... ");
	for (i = 1; i < 8; i++) {

		task = malloc(sizeof(struct scsi_task));

		if (task == NULL) {
			printf("Failed to allocate task structure\n");
			ret = -1;
			goto finished;
		}

		memset(task, 0, sizeof(struct scsi_task));
		task->cdb[0] = SCSI_OPCODE_READ10;
		task->cdb[1] = (i<<5)&0xe0;
		task->cdb[8] = 1;
		task->cdb_size = 10;
		task->xfer_dir = SCSI_XFER_READ;
		task->expxferlen = 512;

		if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		if (task->status        != SCSI_STATUS_CHECK_CONDITION
		    || task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
		    || task->sense.ascq != SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB) {
		        printf("[FAILED]\n");
			printf("Read10 with rdprotect should fail with ILLEGAL REQUEST/INVALID OPCODE\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");


finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}