Ejemplo n.º 1
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);
}
Ejemplo n.º 2
0
Archivo: iscsi.c Proyecto: breuerr/qemu
static void
iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
                        void *command_data, void *opaque)
{
    struct IscsiTask *itask = opaque;
    struct scsi_readcapacity10 *rc10;
    struct scsi_task *task = command_data;

    if (status != 0) {
        error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
                     iscsi_get_error(iscsi));
        itask->status   = 1;
        itask->complete = 1;
        scsi_free_scsi_task(task);
        return;
    }

    rc10 = scsi_datain_unmarshall(task);
    if (rc10 == NULL) {
        error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
        itask->status   = 1;
        itask->complete = 1;
        scsi_free_scsi_task(task);
        return;
    }

    itask->iscsilun->block_size = rc10->block_size;
    itask->iscsilun->num_blocks = rc10->lba;
    itask->bs->total_sectors = (uint64_t)rc10->lba *
                               rc10->block_size / BDRV_SECTOR_SIZE ;

    itask->status   = 0;
    itask->complete = 1;
    scsi_free_scsi_task(task);
}
Ejemplo n.º 3
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);
	}
}
Ejemplo n.º 4
0
void inquiry_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_inquiry_standard *inq;

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

	printf("INQUIRY successful for standard data.\n");
	inq = scsi_datain_unmarshall(task);
	if (inq == NULL) {
		printf("failed to unmarshall inquiry datain blob\n");
		exit(10);
	}

	printf("Device Type is %d. VendorId:%s ProductId:%s\n", inq->periperal_device_type, inq->vendor_identification, inq->product_identification);
	printf("Send MODESENSE6\n");
	if (iscsi_modesense6_async(iscsi, clnt->lun, modesense6_cb, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES, 0, 4, private_data) != 0) {
		printf("failed to send modesense6 command\n");
		exit(10);
	}

}
Ejemplo n.º 5
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);
}
void
test_report_supported_opcodes_servactv(void)
{
	int i, ret;
	struct scsi_task *rso_task;
	struct scsi_report_supported_op_codes *rsoc;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test READ_SUPPORTED_OPCODES SERVACTV flag");


	ret = report_supported_opcodes(
		sd, &rso_task,
		0, SCSI_REPORT_SUPPORTING_OPS_ALL, 0, 0,
		65535,
		EXPECT_STATUS_GOOD);
	if (ret == -2) {
		logging(LOG_NORMAL, "[SKIPPED] READ_SUPPORTED_OPCODES is not "
			"implemented.");
		CU_PASS("READ_SUPPORTED_OPCODES is not implemented.");
		scsi_free_scsi_task(rso_task);
		return;
	}
	CU_ASSERT_EQUAL(ret, 0);
	if (ret != 0) {
		scsi_free_scsi_task(rso_task);
		return;
	}
	
	logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
	rsoc = scsi_datain_unmarshall(rso_task);
	CU_ASSERT_NOT_EQUAL(rsoc, NULL);
	if (!rsoc) {
		logging(LOG_NORMAL, "[FAILED] Target did not return any data "
			"for ReportSupportedOpcodes\n");
		CU_FAIL("Target did not return any data for "
			"ReportSupportedOpcodes");
		return;
	}


	logging(LOG_VERBOSE, "Verify that when SERVACTV is clear then "
		"ServiceAction must be zero.");
	for (i = 0; i < rsoc->num_descriptors; i++) {
		if (!rsoc->descriptors[i].servactv && rsoc->descriptors[i].sa) {
			logging(LOG_NORMAL, "[FAILED] ServiceAction is "
				"non-zero but SERVACTV is clear");
			CU_FAIL("[FAILED] ServiceAction is "
				"non-zero but SERVACTV is clear");
		}
	}

	scsi_free_scsi_task(rso_task);
}
Ejemplo n.º 7
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);
	}
}
Ejemplo n.º 8
0
void
test_inquiry_supported_vpd(void)
{
	int ret, i;
	struct scsi_inquiry_supported_pages *sup_inq;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test INQUIRY supported VPD pages");

	logging(LOG_VERBOSE, "Verify we can read the SUPPORTED VPD page");
	ret = inquiry(sd, &task,
		      1, SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES, 255,
		      EXPECT_STATUS_GOOD);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Verify we got at least 4 bytes of data");
	CU_ASSERT(task->datain.size >= 4);

	logging(LOG_VERBOSE, "Verify we can unmarshall the DATA-IN buffer");
	sup_inq = scsi_datain_unmarshall(task);
	CU_ASSERT_NOT_EQUAL(sup_inq, NULL);
	if (sup_inq == NULL) {
		logging(LOG_NORMAL, "[FAILED] Failed to unmarshall DATA-IN "
			"buffer");
		return;
	}

	logging(LOG_VERBOSE, "Verify we read all the supported pages");
	for (i = 0; i < sup_inq->num_pages; i++) {
		logging(LOG_VERBOSE, "Verify we can read page 0x%02x",
			sup_inq->pages[i]);

		ret = inquiry(sd, NULL, 1, sup_inq->pages[i], 255,
			      EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);
	}

	if (task != NULL) {
		scsi_free_scsi_task(task);
		task = NULL;
	}
}
Ejemplo n.º 9
0
int T0102_read10_0blocks(const char *initiator, const char *url)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity10 *rc10;
	int ret, i, lun;
	uint32_t block_size, num_blocks;

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

	/* find the size of the LUN */
	task = iscsi_readcapacity10_sync(iscsi, lun, 0, 0);
	if (task == NULL) {
		printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc10 = scsi_datain_unmarshall(task);
	if (rc10 == NULL) {
		printf("failed to unmarshall readcapacity10 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	block_size = rc10->block_size;
	num_blocks = rc10->lba;
	scsi_free_scsi_task(task);



	ret = 0;

	/* read10 0 blocks one block at lba 0 */
	printf("Reading 0 blocks at lba:0 ... ");
	task = iscsi_read10_sync(iscsi, lun, 0, 0, block_size);
	if (task == NULL) {
 	        printf("[FAILED]\n");
		printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
 	        printf("[FAILED]\n");
		printf("Read10 of 0 at lba:0 failed with sense.\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	/* read10 0 blocks one block beyond the eol */
	printf("Reading 0 blocks at one block beyond end ... ");
	task = iscsi_read10_sync(iscsi, lun, num_blocks + 1, 0, block_size);
	if (task == NULL) {
 	        printf("[FAILED]\n");
		printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
 	        printf("[FAILED]\n");
		printf("Read10 of 0 one block beyond end-of-lun failed with sense.\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* read10 0 blocks two blocks beyond the eol */
	printf("Reading 0 blocks at two blocks beyond end ... ");
	task = iscsi_read10_sync(iscsi, lun, num_blocks + 1, 0, block_size);
	if (task == NULL) {
 	        printf("[FAILED]\n");
		printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
 	        printf("[FAILED]\n");
		printf("Read10 of 0 two blocks beyond end-of-lun failed with sense.\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* read10 0 at lba -1 */
	printf("Reading 0 blocks at lba:-1 ... ");
	task = iscsi_read10_sync(iscsi, lun, 0xffffff, 0, block_size);
	if (task == NULL) {
 	        printf("[FAILED]\n");
		printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
 	        printf("[FAILED]\n");
		printf("Read10 of 0 at lba:-1 failed with sense.\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;
}
Ejemplo n.º 10
0
/*
 * We support iscsi url's on the form
 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
 */
static int iscsi_open(BlockDriverState *bs, QDict *options, int flags)
{
    IscsiLun *iscsilun = bs->opaque;
    struct iscsi_context *iscsi = NULL;
    struct iscsi_url *iscsi_url = NULL;
    struct scsi_task *task = NULL;
    struct scsi_inquiry_standard *inq = NULL;
    char *initiator_name = NULL;
    QemuOpts *opts;
    Error *local_err = NULL;
    const char *filename;
    int ret;

    if ((BDRV_SECTOR_SIZE % 512) != 0) {
        error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. "
                     "BDRV_SECTOR_SIZE(%lld) is not a multiple "
                     "of 512", BDRV_SECTOR_SIZE);
        return -EINVAL;
    }

    opts = qemu_opts_create_nofail(&runtime_opts);
    qemu_opts_absorb_qdict(opts, options, &local_err);
    if (error_is_set(&local_err)) {
        qerror_report_err(local_err);
        error_free(local_err);
        ret = -EINVAL;
        goto out;
    }

    filename = qemu_opt_get(opts, "filename");


    iscsi_url = iscsi_parse_full_url(iscsi, filename);
    if (iscsi_url == NULL) {
        error_report("Failed to parse URL : %s", filename);
        ret = -EINVAL;
        goto out;
    }

    memset(iscsilun, 0, sizeof(IscsiLun));

    initiator_name = parse_initiator_name(iscsi_url->target);

    iscsi = iscsi_create_context(initiator_name);
    if (iscsi == NULL) {
        error_report("iSCSI: Failed to create iSCSI context.");
        ret = -ENOMEM;
        goto out;
    }

    if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
        error_report("iSCSI: Failed to set target name.");
        ret = -EINVAL;
        goto out;
    }

    if (iscsi_url->user != NULL) {
        ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
                                              iscsi_url->passwd);
        if (ret != 0) {
            error_report("Failed to set initiator username and password");
            ret = -EINVAL;
            goto out;
        }
    }

    /* check if we got CHAP username/password via the options */
    if (parse_chap(iscsi, iscsi_url->target) != 0) {
        error_report("iSCSI: Failed to set CHAP user/password");
        ret = -EINVAL;
        goto out;
    }

    if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
        error_report("iSCSI: Failed to set session type to normal.");
        ret = -EINVAL;
        goto out;
    }

    iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);

    /* check if we got HEADER_DIGEST via the options */
    parse_header_digest(iscsi, iscsi_url->target);

    if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
        error_report("iSCSI: Failed to connect to LUN : %s",
            iscsi_get_error(iscsi));
        ret = -EINVAL;
        goto out;
    }

    iscsilun->iscsi = iscsi;
    iscsilun->lun   = iscsi_url->lun;

    task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36);

    if (task == NULL || task->status != SCSI_STATUS_GOOD) {
        error_report("iSCSI: failed to send inquiry command.");
        ret = -EINVAL;
        goto out;
    }

    inq = scsi_datain_unmarshall(task);
    if (inq == NULL) {
        error_report("iSCSI: Failed to unmarshall inquiry data.");
        ret = -EINVAL;
        goto out;
    }

    iscsilun->type = inq->periperal_device_type;

    if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
        goto out;
    }
    bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);

    /* Medium changer or tape. We dont have any emulation for this so this must
     * be sg ioctl compatible. We force it to be sg, otherwise qemu will try
     * to read from the device to guess the image format.
     */
    if (iscsilun->type == TYPE_MEDIUM_CHANGER ||
        iscsilun->type == TYPE_TAPE) {
        bs->sg = 1;
    }

#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
    /* Set up a timer for sending out iSCSI NOPs */
    iscsilun->nop_timer = qemu_new_timer_ms(rt_clock, iscsi_nop_timed_event, iscsilun);
    qemu_mod_timer(iscsilun->nop_timer, qemu_get_clock_ms(rt_clock) + NOP_INTERVAL);
#endif

out:
    qemu_opts_del(opts);
    if (initiator_name != NULL) {
        g_free(initiator_name);
    }
    if (iscsi_url != NULL) {
        iscsi_destroy_url(iscsi_url);
    }
    if (task != NULL) {
        scsi_free_scsi_task(task);
    }

    if (ret) {
        if (iscsi != NULL) {
            iscsi_destroy_context(iscsi);
        }
        memset(iscsilun, 0, sizeof(IscsiLun));
    }
    return ret;
}
Ejemplo n.º 11
0
int T0293_write10_0blocks(const char *initiator, const char *url, int data_loss, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret = 0, lun;
	uint32_t block_size;
	uint32_t num_blocks;

	printf("0293_write10_0blocks:\n");
	printf("====================\n");
	if (show_info) {
		printf("Test that WRITE10 works correctly when writing 0 number of blocks.\n");
		printf("1, Read at LBA:0 should work.\n");
		printf("2, Read at LBA:end-of-lun should work.\n");
		printf("3, Read at LBA:end-of-lun+1 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;
	}

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY16 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall READCAPACITY16 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	block_size = rc16->block_length;
	num_blocks = rc16->returned_lba;
	scsi_free_scsi_task(task);

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


	printf("Write10 0blocks at LBA:0 ");
	task = iscsi_write10_sync(iscsi, lun, 0, NULL, 0, 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: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	printf("Write10 0blocks at LBA:<end-of-disk> ");
	task = iscsi_write10_sync(iscsi, lun, num_blocks, NULL, 0, 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: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	printf("Write10 0blocks at LBA:<beyond end-of-disk> ");
	task = iscsi_write10_sync(iscsi, lun, num_blocks + 1, NULL, 0, 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 0blocks beyond end\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Ejemplo n.º 12
0
void
test_read12_dpofua(void)
{ 
	int ret, dpofua, usage_data_dpofua;
	struct scsi_task *ms_task = NULL;
	struct scsi_mode_sense *ms;
	struct scsi_task *rso_task = NULL;
	struct scsi_report_supported_op_codes_one_command *rsoc;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test READ12 DPO/FUA flags");

	CHECK_FOR_SBC;

	logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data");
	ret = modesense6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
			 SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
			 EXPECT_STATUS_GOOD);
	CU_ASSERT_EQUAL(ret, 0);
	logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD");
	ms = scsi_datain_unmarshall(ms_task);
	dpofua = ms && (ms->device_specific_parameter & 0x10);
	scsi_free_scsi_task(ms_task);

	if (dpofua) {
		logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow "
			"DPO/FUA flags in CDBs");
	} else {
		logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail "
			"CDBs with DPO/FUA set");
	}

	logging(LOG_VERBOSE, "Test READ12 with DPO==1");
	if (dpofua) {
		ret = read12(sd, 0,
			     block_size, block_size, 0, 1, 0, 0, 0, NULL,
			     EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);
	} else {
		ret = read12(sd, 0,
			     block_size, block_size, 0, 1, 0, 0, 0, NULL,
			     EXPECT_INVALID_FIELD_IN_CDB);
		CU_ASSERT_EQUAL(ret, 0);
	}

	logging(LOG_VERBOSE, "Test READ12 with FUA==1");
	if (dpofua) {
		ret = read12(sd, 0,
			     block_size, block_size, 0, 0, 1, 0, 0, NULL,
			     EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);
	} else {
		ret = read12(sd, 0,
			     block_size, block_size, 0, 0, 1, 0, 0, NULL,
			     EXPECT_INVALID_FIELD_IN_CDB);
		CU_ASSERT_EQUAL(ret, 0);
	}

	logging(LOG_VERBOSE, "Test READ12 with DPO==1 FUA==1");
	if (dpofua) {
		ret = read12(sd, 0,
			     block_size, block_size, 0, 1, 1, 0, 0, NULL,
			     EXPECT_STATUS_GOOD);
		CU_ASSERT_EQUAL(ret, 0);
	} else {
		ret = read12(sd, 0,
			     block_size, block_size, 0, 1, 1, 0, 0, NULL,
			     EXPECT_INVALID_FIELD_IN_CDB);
		CU_ASSERT_EQUAL(ret, 0);
	}

	logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
		"for READ12");
	ret = report_supported_opcodes(sd, &rso_task,
				       0, SCSI_REPORT_SUPPORTING_OPCODE,
				       SCSI_OPCODE_READ12,
				       0,
				       65535,
				       EXPECT_STATUS_GOOD);
	if (ret == -2) {
		logging(LOG_NORMAL, "REPORT_SUPPORTED_OPCODES not implemented. "
			"Skipping this part of the test");
		return;
	}
	logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
	rsoc = scsi_datain_unmarshall(rso_task);
	CU_ASSERT_NOT_EQUAL(rsoc, NULL);
	usage_data_dpofua = rsoc ? rsoc->cdb_usage_data[1] & 0x18 : -1;
	if (dpofua) {
		logging(LOG_VERBOSE, "DPOFUA is set. Verify the DPO/FUA flags "
			"are set in the CDB_USAGE_DATA");
		CU_ASSERT_EQUAL(usage_data_dpofua, 0x18);
	} else {
		logging(LOG_VERBOSE, "DPOFUA is clear. Verify the DPO/FUA "
			"flags are clear in the CDB_USAGE_DATA");
		CU_ASSERT_EQUAL(usage_data_dpofua, 0x00);
	}
	scsi_free_scsi_task(rso_task);
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 15
0
int T0292_write10_flags(const char *initiator, const char *url, int data_loss, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret = 0, lun;
	uint32_t block_size;
	unsigned char data[256 * 512];

	printf("0292_write10_flags:\n");
	printf("===================\n");
	if (show_info) {
		printf("Test how WRITE10 handles the flags\n");
		printf("1, Write with DPU should work.\n");
		printf("2, Write with FUA should work.\n");
		printf("3, Write with FUA_NV should work.\n");
		printf("4, Write with FUA+FUA_NV should work.\n");
		printf("\n");
		return 0;
	}

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

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY16 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall READCAPACITY16 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	block_size = rc16->block_length;
	scsi_free_scsi_task(task);


	printf("Write10 with DPO ");
	task = iscsi_write10_sync(iscsi, lun, 0, data, block_size, block_size, 0, 1, 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: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

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


	printf("Write10 with FUA ");
	task = iscsi_write10_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 1, 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: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");


	printf("Write10 with FUA_NV ");
	task = iscsi_write10_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 1, 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: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	printf("Write10 with FUA+FUA_NV ");
	task = iscsi_write10_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 1, 1, 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: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Ejemplo n.º 16
0
int T0231_write12_wrprotect(const char *initiator, const char *url, int data_loss, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret = 0, i, lun;
	uint32_t block_size;
	unsigned char data[4096];

	printf("0231_write12_wrprotect:\n");
	printf("======================\n");
	if (show_info) {
		printf("Test how WRITE12 handles the wrprotect bits\n");
		printf("1, Any non-zero valued for wrprotect 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;
	}

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY16 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall READCAPACITY16 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	block_size = rc16->block_length;

	if(rc16->prot_en != 0) {
		printf("device is formatted with protection information, skipping test\n");
		scsi_free_scsi_task(task);
		ret = -2;
		goto finished;
	}
	scsi_free_scsi_task(task);

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

	printf("Write12 with RDPROTECT ");
	for (i = 1; i <= 7; i++) {
		task = iscsi_write12_sync(iscsi, lun, 0, data, block_size, block_size, i, 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_CHECK_CONDITION
		    || task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
		    || task->sense.ascq != SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB) {
		        printf("[FAILED]\n");
			printf("Write12 with RDPROTECT!=0 should have failed with CHECK_CONDITION/ILLEGAL_REQUEST/INVALID_FIELD_IN_CDB\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;
}
Ejemplo n.º 17
0
int T0294_write10_beyondeol(const char *initiator, const char *url, int data_loss, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret, i, lun;
	uint32_t block_size;
	uint32_t num_blocks;
	unsigned char data[258 * 512];

	printf("0294_write10_beyond_eol:\n");
	printf("=======================\n");
	if (show_info) {
		printf("Test that WRITE10 fails if writing beyond end-of-lun.\n");
		printf("1, Writing 1-256 blocks beyond end-of-lun 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;
	}

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY16 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall READCAPACITY10 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	block_size = rc16->block_length;
	num_blocks = rc16->returned_lba;
	scsi_free_scsi_task(task);

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


	ret = 0;

	/* read 1 - 256 blocks beyond the end of the device */
	printf("Writing 1-256 blocks beyond end-of-device ... ");
	for (i = 2; i <= 257; i++) {
		task = iscsi_write10_sync(iscsi, lun, num_blocks, data, i * 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 beyond end of device\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;
}
int T0264_get_lba_status_beyondeol(const char *initiator, const char *url, int data_loss _U_, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret, lun;
	uint32_t block_size;
	uint64_t num_blocks;

	printf("0264_get_lba_status_beyondeol:\n");
	printf("==============================\n");
	if (show_info) {
		printf("Test GET_LBA_STATUS functionality for beyond end-of-lun requests\n");
		printf("1, Reading a descriptor beyond the end of the lun 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;
	}

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send readcapacity16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall readcapacity16 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	if (rc16->lbpme == 0){
		printf("Logical unit is fully provisioned. Skipping test\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	block_size = rc16->block_length;
	num_blocks = rc16->returned_lba;

	scsi_free_scsi_task(task);

	ret = 0;

	/* try reading one descriptor beyond end-of-device */
	printf("Read one descriptor beyond end-of-device ... ");
	task = iscsi_get_lba_status_sync(iscsi, lun, num_blocks + 1, 8 + 16);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send GET_LBA_STATUS command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("GET_LBA_STATUS beyond eol should fail with ILLEGAL_REQUEST/LBA_OUT_OF_RANGE\n");
		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_LBA_OUT_OF_RANGE) {
	        printf("[FAILED]\n");
		printf("GET_LBA_STATUS failed but with the wrong sense code. It should have failed with ILLEGAL_REQUEST/LBA_OUT_OF_RANGE.\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;
}
Ejemplo n.º 19
0
int T0213_read12_0blocks(const char *initiator, const char *url, int data_loss _U_, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret = 0, lun;
	uint32_t block_size;
	uint64_t num_blocks;

	printf("0213_read12_0blocks:\n");
	printf("====================\n");
	if (show_info) {
		printf("Test that READ12 works correctly when reading 0 number of blocks.\n");
		printf("1, Read at 0 should work.\n");
		printf("2, Read at end-of-lun should work.\n");
		printf("3, Read beyond end-of-lun should fail.\n");
		printf("4, Read at LBA:-1 should fail. (only test this if the device is < 2TB)\n");
		printf("\n");
		return 0;
	}

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

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY16 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall READCAPACITY16 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	block_size = rc16->block_length;
	num_blocks = rc16->returned_lba;
	scsi_free_scsi_task(task);


	printf("Read12 0blocks at LBA:0 ");
	task = iscsi_read12_sync(iscsi, lun, 0, 0, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Read12 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	printf("Read12 0blocks at LBA:<end-of-disk> ");
	task = iscsi_read12_sync(iscsi, lun, num_blocks, 0, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Read12 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	printf("Read12 0blocks at LBA:<beyond end-of-disk> ");
	task = iscsi_read12_sync(iscsi, lun, num_blocks + 1, 0, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Read12 command: Should fail when reading 0blocks beyond end\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	/* read12 0 at lba -1, only do this if the device is < 2TB */
	if (num_blocks == 0xffffffff) {
		goto finished;
	}
	printf("Reading 0 blocks at lba:-1 ... ");
	task = iscsi_read12_sync(iscsi, lun, -1, 0, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Read12 command: Should fail when reading 0blocks at -1\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Ejemplo n.º 20
0
int main(int argc, const char *argv[])
{
	poptContext pc;
	const char **extra_argv;
	char *src_url = NULL;
	char *dst_url = NULL;
	struct iscsi_url *iscsi_url;
	struct scsi_task *task;
	struct scsi_readcapacity10 *rc10;
	int extra_argc = 0;
	int res;
	struct pollfd pfd[2];
	struct client client;

	struct poptOption popt_options[] = {
		POPT_AUTOHELP
		{ "initiator-name", 'i', POPT_ARG_STRING, &initiator, 0, "Initiatorname to use", "iqn-name" },
		{ "src", 0, POPT_ARG_STRING, &src_url, 0, "SRC lun", "iscsi url" },
		{ "dst", 0, POPT_ARG_STRING, &dst_url, 0, "DST lun", "iscsi url" },
		POPT_TABLEEND
	};

	pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_POSIXMEHARDER);
	if ((res = poptGetNextOpt(pc)) < -1) {
		fprintf(stderr, "Failed to parse option : %s %s\n",
			poptBadOption(pc, 0), poptStrerror(res));
		exit(10);
	}
	extra_argv = poptGetArgs(pc);
	poptFreeContext(pc);

	if (src_url == NULL) {
		fprintf(stderr, "You must specify source url\n");
		fprintf(stderr, "  --src iscsi://<host>[:<port>]/<target-iqn>/<lun>\n", argv[0]);
		exit(10);
	}
	if (dst_url == NULL) {
		fprintf(stderr, "You must specify destination url\n");
		fprintf(stderr, "  --dst iscsi://<host>[:<port>]/<target-iqn>/<lun>\n", argv[0]);
		exit(10);
	}


	memset(&client, 0, sizeof(client));


	client.src_iscsi = iscsi_create_context(initiator);
	if (client.src_iscsi == NULL) {
		fprintf(stderr, "Failed to create context\n");
		exit(10);
	}
	iscsi_url = iscsi_parse_full_url(client.src_iscsi, src_url);
	if (iscsi_url == NULL) {
		fprintf(stderr, "Failed to parse URL: %s\n", 
			iscsi_get_error(client.src_iscsi));
		exit(10);
	}
	iscsi_set_targetname(client.src_iscsi, iscsi_url->target);
	iscsi_set_session_type(client.src_iscsi, ISCSI_SESSION_NORMAL);
	iscsi_set_header_digest(client.src_iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
	if (iscsi_url->user != NULL) {
		if (iscsi_set_initiator_username_pwd(client.src_iscsi, iscsi_url->user, iscsi_url->passwd) != 0) {
			fprintf(stderr, "Failed to set initiator username and password\n");
			exit(10);
		}
	}
	if (iscsi_full_connect_sync(client.src_iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
		fprintf(stderr, "Login Failed. %s\n", iscsi_get_error(client.src_iscsi));
		iscsi_destroy_url(iscsi_url);
		iscsi_destroy_context(client.src_iscsi);
		exit(10);
	}
	client.src_lun = iscsi_url->lun;
	iscsi_destroy_url(iscsi_url);

	task = iscsi_readcapacity10_sync(client.src_iscsi, client.src_lun, 0, 0);
	if (task == NULL || task->status != SCSI_STATUS_GOOD) {
		fprintf(stderr, "failed to send readcapacity command\n");
		exit(10);
	}
	rc10 = scsi_datain_unmarshall(task);
	if (rc10 == NULL) {
		fprintf(stderr, "failed to unmarshall readcapacity10 data\n");
		exit(10);
	}
	client.src_blocksize  = rc10->block_size;
	client.src_num_blocks  = rc10->lba;
	scsi_free_scsi_task(task);





	client.dst_iscsi = iscsi_create_context(initiator);
	if (client.dst_iscsi == NULL) {
		fprintf(stderr, "Failed to create context\n");
		exit(10);
	}
	iscsi_url = iscsi_parse_full_url(client.dst_iscsi, dst_url);
	if (iscsi_url == NULL) {
		fprintf(stderr, "Failed to parse URL: %s\n", 
			iscsi_get_error(client.dst_iscsi));
		exit(10);
	}
	iscsi_set_targetname(client.dst_iscsi, iscsi_url->target);
	iscsi_set_session_type(client.dst_iscsi, ISCSI_SESSION_NORMAL);
	iscsi_set_header_digest(client.dst_iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
	if (iscsi_url->user != NULL) {
		if (iscsi_set_initiator_username_pwd(client.dst_iscsi, iscsi_url->user, iscsi_url->passwd) != 0) {
			fprintf(stderr, "Failed to set initiator username and password\n");
			exit(10);
		}
	}
	if (iscsi_full_connect_sync(client.dst_iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
		fprintf(stderr, "Login Failed. %s\n", iscsi_get_error(client.dst_iscsi));
		iscsi_destroy_url(iscsi_url);
		iscsi_destroy_context(client.dst_iscsi);
		exit(10);
	}
	client.dst_lun = iscsi_url->lun;
	iscsi_destroy_url(iscsi_url);

	task = iscsi_readcapacity10_sync(client.dst_iscsi, client.dst_lun, 0, 0);
	if (task == NULL || task->status != SCSI_STATUS_GOOD) {
		fprintf(stderr, "failed to send readcapacity command\n");
		exit(10);
	}
	rc10 = scsi_datain_unmarshall(task);
	if (rc10 == NULL) {
		fprintf(stderr, "failed to unmarshall readcapacity10 data\n");
		exit(10);
	}
	client.dst_blocksize  = rc10->block_size;
	client.dst_num_blocks  = rc10->lba;
	scsi_free_scsi_task(task);

	fill_read_queue(&client);

	while (client.finished == 0) {
		pfd[0].fd = iscsi_get_fd(client.src_iscsi);
		pfd[0].events = iscsi_which_events(client.src_iscsi);
		pfd[1].fd = iscsi_get_fd(client.dst_iscsi);
		pfd[1].events = iscsi_which_events(client.dst_iscsi);

		if (poll(&pfd[0], 2, -1) < 0) {
			printf("Poll failed");
			exit(10);
		}
		if (iscsi_service(client.src_iscsi, pfd[0].revents) < 0) {
			printf("iscsi_service failed with : %s\n", iscsi_get_error(client.src_iscsi));
			break;
		}
		if (iscsi_service(client.dst_iscsi, pfd[1].revents) < 0) {
			printf("iscsi_service failed with : %s\n", iscsi_get_error(client.dst_iscsi));
			break;
		}
	}

	iscsi_logout_sync(client.src_iscsi);
	iscsi_destroy_context(client.src_iscsi);
	iscsi_logout_sync(client.dst_iscsi);
	iscsi_destroy_context(client.dst_iscsi);

	return 0;
}
Ejemplo n.º 21
0
void
test_writeatomic16_vpd(void)
{
	int ret;
	struct scsi_inquiry_block_limits *bl;
	struct scsi_task *bl_task = NULL;
	int gran;
	unsigned char *buf;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test WRITEATOMIC16 VPD data");

	CHECK_FOR_SBC;
	CHECK_FOR_DATALOSS;


	logging(LOG_VERBOSE, "Block device. Verify that we can read Block "
		"Limits VPD");
	ret = inquiry(sd, &bl_task,
		      1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, 255,
		      EXPECT_STATUS_GOOD);
	CU_ASSERT_EQUAL(ret, 0);
	if (ret != 0) {
		logging(LOG_NORMAL, "[FAILURE] failed to read Block Limits VDP");
		CU_FAIL("[FAILURE] failed to read Block Limits VDP");
		goto finished;
	}
	bl = scsi_datain_unmarshall(bl_task);
	if (bl == NULL) {
		logging(LOG_NORMAL, "[FAILURE] failed to unmarshall Block Limits VDP");
		CU_FAIL("[FAILURE] failed to unmarshall Block Limits VDP");
		goto finished;
	}


	logging(LOG_VERBOSE, "Check if WRITEATOMIC16 is supported");
	gran = inq_bl->atomic_gran ? inq_bl->atomic_gran : 1;
	buf = alloca(block_size * gran);
	memset(buf, 0x00, block_size * gran);
	ret = writeatomic16(sd, 0, block_size * gran,
			    block_size, 0, 0, 0, 0, buf,
			    EXPECT_STATUS_GOOD);
	if (ret == -2) {
		logging(LOG_VERBOSE, "WRITEATOMIC16 is NOT supported by the target.");

		logging(LOG_VERBOSE, "Verify that MAXIMUM_ATOMIC_TRANSFER_LENGTH is zero");
		if (bl->max_atomic_xfer_len) {
			logging(LOG_VERBOSE, "MAXIMUM_ATOMIC_TRANSFER_LENGTH is non-zero but target does not support ATOMICWRITE16");
			CU_FAIL("MAXIMUM_ATOMIC_TRANSFER_LENGTH is non-zero but target does not support ATOMICWRITE16");
		}

		logging(LOG_VERBOSE, "Verify that ATOMIC_ALIGNMENT is zero");
		if (bl->atomic_align) {
			logging(LOG_VERBOSE, "ATOMIC_ALIGNMENT is non-zero but target does not support ATOMICWRITE16");
			CU_FAIL("ATOMIC_ALIGNMENT is non-zero but target does not support ATOMICWRITE16");
		}

		logging(LOG_VERBOSE, "Verify that ATOMIC_GRANULARITY is zero");
		if (bl->atomic_gran) {
			logging(LOG_VERBOSE, "ATOMIC_GRANULARITY is non-zero but target does not support ATOMICWRITE16");
			CU_FAIL("ATOMIC_GRANULARITY is non-zero but target does not support ATOMICWRITE16");
		}
		goto finished;
	}

	logging(LOG_VERBOSE, "WRITEATOMIC16 IS supported by the target.");
	logging(LOG_VERBOSE, "Verify that MAXIMUM_ATOMIC_TRANSFER_LENGTH is non-zero");
	if (!bl->max_atomic_xfer_len) {
		logging(LOG_VERBOSE, "[WARNING] MAXIMUM_ATOMIC_TRANSFER_LENGTH is zero but target supports ATOMICWRITE16");
		CU_FAIL("[WARNING] MAXIMUM_ATOMIC_TRANSFER_LENGTH is zero but target supports ATOMICWRITE16");
	}

	logging(LOG_VERBOSE, "Verify that MAXIMUM_ATOMIC_TRANSFER_LENGTH is less than or equal to MAXIMUM_TRANSFER_LENGTH");
	if (bl->max_atomic_xfer_len > bl->max_xfer_len) {
		logging(LOG_VERBOSE, "[FAILED] MAXIMUM_ATOMIC_TRANSFER_LENGTH is greater than MAXIMUM_TRANSFER_LENGTH");
		CU_FAIL("[FAILED] MAXIMUM_ATOMIC_TRANSFER_LENGTH is greater than MAXIMUM_TRANSFER_LENGTH");
	}

	logging(LOG_VERBOSE, "Check handling on misaligned writes");
	if (bl->atomic_align < 2) {
		logging(LOG_VERBOSE, "[SKIPPED] No alignment restrictions on this LUN");
	} else {
		logging(LOG_VERBOSE, "Atomic Write at LBA 1 should fail due to misalignment");
		ret = writeatomic16(sd, 1, block_size * gran,
				    block_size, 0, 0, 0, 0, buf,
				    EXPECT_INVALID_FIELD_IN_CDB);
		if (ret) {
			logging(LOG_VERBOSE, "[FAILED] Misaligned write did NOT fail with INVALID_FIELD_IN_CDB");
		CU_FAIL("[FAILED] Misaligned write did NOT fail with INVALID_FIELD_IN_CDB");
		}
	}

	logging(LOG_VERBOSE, "Check handling on invalid granularity");
	if (bl->atomic_gran < 2) {
		logging(LOG_VERBOSE, "[SKIPPED] No granularity restrictions on this LUN");
	} else {
		logging(LOG_VERBOSE, "Atomic Write of 1 block should fail due to invalid granularity");
		ret = writeatomic16(sd, 0, block_size,
				    block_size, 0, 0, 0, 0, buf,
				    EXPECT_INVALID_FIELD_IN_CDB);
		if (ret) {
			logging(LOG_VERBOSE, "[FAILED] Misgranularity write did NOT fail with INVALID_FIELD_IN_CDB");
		CU_FAIL("[FAILED] Misgranularity write did NOT fail with INVALID_FIELD_IN_CDB");
		}
	}


finished:
	scsi_free_scsi_task(bl_task);
}
Ejemplo n.º 22
0
int T0170_unmap_simple(const char *initiator, const char *url, int data_loss, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret, i, lun;
	uint32_t block_size, num_blocks;

	printf("0170_unmap_simple:\n");
	printf("==================\n");
	if (show_info) {
		printf("Test basic UNMAP functionality.\n");
		printf("1, Test UNMAP the first 1-256 blocks of the LUN.\n");
		printf("2, Test UNMAP the last 1-256 blocks of the LUN.\n");
		printf("\n");
		return 0;
	}

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

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send readcapacity16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall readcapacity16 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	if (rc16->lbpme == 0){
		printf("Logical unit is fully provisioned. Skipping test\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	block_size = rc16->block_length;
	num_blocks = rc16->returned_lba;

	scsi_free_scsi_task(task);

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

	/* unmap the first 1 - 256 blocks at the start of the LUN */
	printf("Unmapping first 1-256 blocks ... ");
	for (i=1; i<=256; i++) {
		struct unmap_list list[1];

		list[0].lba = 0;
		list[0].num = i;
		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: failed with sense. %s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			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 ... ");
	for (i=1; i<=256; i++) {
		struct unmap_list list[1];

		list[0].lba = num_blocks + 1 - i;
		list[0].num = i;
		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: failed with sense. %s\n", iscsi_get_error(iscsi));
			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;
}
Ejemplo n.º 23
0
int main(int argc, char *argv[])
{
	struct iscsi_context *iscsi;
	const char *url = NULL;
	struct iscsi_url *iscsi_url = NULL;
	int show_help = 0, show_usage = 0, debug = 0;
	int c;
	int ret = 0;
	int swp = 0;
	struct scsi_task *sense_task = NULL;
	struct scsi_task *select_task = NULL;
	struct scsi_mode_sense *ms;
	struct scsi_mode_page *mp;

	static struct option long_options[] = {
		{"help",           no_argument,          NULL,        'h'},
		{"usage",          no_argument,          NULL,        'u'},
		{"debug",          no_argument,          NULL,        'd'},
		{"initiator-name", required_argument,    NULL,        'i'},
		{"swp",            required_argument,    NULL,        's'},
		{0, 0, 0, 0}
	};
	int option_index;

	while ((c = getopt_long(argc, argv, "h?udi:s:", long_options,
			&option_index)) != -1) {
		switch (c) {
		case 'h':
		case '?':
			show_help = 1;
			break;
		case 'u':
			show_usage = 1;
			break;
		case 'd':
			debug = 1;
			break;
		case 'i':
			initiator = optarg;
			break;
		case 's':
			if (!strcmp(optarg, "on") || !strcmp(optarg, "ON")) {
				swp = 1;
			}
			if (!strcmp(optarg, "off") || !strcmp(optarg, "OFF")) {
				swp = 2;
			}
			break;
		default:
			fprintf(stderr, "Unrecognized option '%c'\n\n", c);
			print_help();
			exit(0);
		}
	}

	if (show_help != 0) {
		print_help();
		exit(0);
	}

	if (show_usage != 0) {
		print_usage();
		exit(0);
	}

	iscsi = iscsi_create_context(initiator);
	if (iscsi == NULL) {
		fprintf(stderr, "Failed to create context\n");
		exit(10);
	}

	if (debug > 0) {
		iscsi_set_log_level(iscsi, debug);
		iscsi_set_log_fn(iscsi, iscsi_log_to_stderr);
	}

	if (argv[optind] != NULL) {
		url = strdup(argv[optind]);
	}
	if (url == NULL) {
		fprintf(stderr, "You must specify the URL\n");
		print_usage();
		ret = 10;
		goto finished;
	}
	iscsi_url = iscsi_parse_full_url(iscsi, url);
	
	free(discard_const(url));

	if (iscsi_url == NULL) {
		fprintf(stderr, "Failed to parse URL: %s\n", 
			iscsi_get_error(iscsi));
		ret = 10;
		goto finished;
	}

	iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL);
	iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);

	if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
		fprintf(stderr, "Login Failed. %s\n", iscsi_get_error(iscsi));
		ret = 10;
		goto finished;
	}


	sense_task = iscsi_modesense10_sync(iscsi, iscsi_url->lun,
		0, 1, SCSI_MODESENSE_PC_CURRENT,
		SCSI_MODEPAGE_CONTROL,
		0, 255);
	if (sense_task == NULL) {
		printf("Failed to send MODE_SENSE10 command: %s\n",
			iscsi_get_error(iscsi));
		ret = 10;
		goto finished;
	}
	if (sense_task->status != SCSI_STATUS_GOOD) {
		printf("MODE_SENSE10 failed: %s\n",
			iscsi_get_error(iscsi));
		ret = 10;
		goto finished;
	}
	ms = scsi_datain_unmarshall(sense_task);
	if (ms == NULL) {
		printf("failed to unmarshall mode sense datain blob\n");
		ret = 10;
		goto finished;
	}
	mp = scsi_modesense_get_page(ms, SCSI_MODEPAGE_CONTROL, 0);
	if (mp == NULL) {
		printf("failed to read control mode page\n");
		ret = 10;
		goto finished;
	}

	/* For MODE SELECT PS is reserved and hence must be cleared */
	mp->ps = 0;

	printf("SWP:%d\n", mp->control.swp);

	switch (swp) {
	case 1:
		mp->control.swp = 1;
		break;
	case 2:
		mp->control.swp = 0;
		break;
	default:
		goto finished;
	}

	printf("Turning SWP %s\n", (swp == 1) ? "ON" : "OFF"); 
	select_task = iscsi_modeselect10_sync(iscsi, iscsi_url->lun,
		    1, 0, mp);
	if (select_task == NULL) {
		printf("Failed to send MODE_SELECT10 command: %s\n",
			iscsi_get_error(iscsi));
		ret = 10;
		goto finished;
	}
	if (select_task->status != SCSI_STATUS_GOOD) {
		printf("MODE_SELECT10 failed: %s\n",
			iscsi_get_error(iscsi));
		ret = 10;
		goto finished;
	}


finished:
	if (sense_task != NULL) {
		scsi_free_scsi_task(sense_task);
	}
	if (select_task != NULL) {
		scsi_free_scsi_task(select_task);
	}
	if (iscsi_url != NULL) {
		iscsi_destroy_url(iscsi_url);
	}
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Ejemplo n.º 24
0
int T0252_prefetch16_beyondeol(const char *initiator, const char *url, int data_loss _U_, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret, i, lun;
	uint64_t num_blocks;

	printf("0252_prefetch16_beyondeol:\n");
	printf("===================\n");
	if (show_info) {
		printf("Test PREFETCH16 for blocks beyond the EOL.\n");
		printf("1, Prefetch 1-256 blocks one block beyond end-of-lun.\n");
		printf("2, Prefetch 1-256 blocks at LBA 2^63 should fail.\n");
		printf("3, Prefetch 1-256 blocks at LBA -1 should fail.\n");
		printf("4, Prefetch 1-256 blocks all but one block beyond eol\n");
		printf("\n");
		return 0;
	}

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

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY16 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall READCAPACITY16 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	num_blocks = rc16->returned_lba;
	scsi_free_scsi_task(task);

	ret = 0;



	/* prefetch 1-256 blocks, one block beyond the end-of-lun */
	printf("Prefetch last 1-256 blocks one block beyond eol ... ");
	for (i = 1; i <= 256; i++) {
		task = iscsi_prefetch16_sync(iscsi, lun, num_blocks + 2 - i, i, 0, 0);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send prefetch16 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto test2;
		}
		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 (task->status        != SCSI_STATUS_CHECK_CONDITION
			|| task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
			|| task->sense.ascq != SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE) {
			printf("[FAILED]\n");
			printf("PREFETCH16 failed but with the wrong sense code. It should have failed with ILLEGAL_REQUEST/LBA_OUT_OF_RANGE. Sense:%s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			goto test2;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");

test2:
	/* Prefetch 1 - 256 blocks at LBA 2^63 */
	printf("Prefetch 1-256 blocks at LBA 2^63 ... ");
	for (i = 1; i <= 256; i++) {
		task = iscsi_prefetch16_sync(iscsi, lun, 0x8000000000000000, i, 0, 0);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send PREFETCH16 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto test3;
		}
		if (task->status == SCSI_STATUS_GOOD) {
		        printf("[FAILED]\n");
			printf("PREFETCH16 command should fail for LBA 2^31\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto test3;
		}
		if (task->status        != SCSI_STATUS_CHECK_CONDITION
			|| task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
			|| task->sense.ascq != SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE) {
			printf("[FAILED]\n");
			printf("PREFETCH16 failed but with the wrong sense code. It should have failed with ILLEGAL_REQUEST/LBA_OUT_OF_RANGE. Sense:%s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			goto test3;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");


test3:
	/* prefetch 1 - 256 blocks at LBA -1 */
	for (i = 1; i <= 256; i++) {
		task = iscsi_prefetch16_sync(iscsi, lun, -1, i, 0, 0);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send PREFETCH16 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto test4;
		}
		if (task->status == SCSI_STATUS_GOOD) {
		        printf("[FAILED]\n");
			printf("PREFETCH16 command should fail for LBA -1\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto test4;
		}
		if (task->status        != SCSI_STATUS_CHECK_CONDITION
			|| task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
			|| task->sense.ascq != SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE) {
			printf("[FAILED]\n");
			printf("PREFETCH16 failed but with the wrong sense code. It should have failed with ILLEGAL_REQUEST/LBA_OUT_OF_RANGE. Sense:%s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			goto test4;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");


 test4:
	/* prefetch 2-256 blocks, all but one block beyond the eol */
	printf("Prefetch 1-255 blocks beyond eol starting at last block ... ");
	for (i=2; i<=256; i++) {
		task = iscsi_prefetch16_sync(iscsi, lun, num_blocks, i, 0, 0);
		if (task == NULL) {
			printf("[FAILED]\n");
			printf("Failed to send PREFETCH16 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto test5;
		}
		if (task->status == SCSI_STATUS_GOOD) {
			printf("[FAILED]\n");
			printf("PREFETCH16 beyond end-of-lun did not return sense.\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto test5;
		}
		if (task->status        != SCSI_STATUS_CHECK_CONDITION
		    || task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
		    || task->sense.ascq != SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE) {
		        printf("[FAILED]\n");
			printf("PREFETCH16 failed but ascq was wrong. Should have failed with ILLEGAL_REQUEST/LBA_OUT_OF_RANGE. Sense:%s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			goto test5;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");


test5:

finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Ejemplo n.º 25
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;
}
Ejemplo n.º 26
0
void
test_inquiry_standard(void)
{
        int ret, i;
        struct scsi_inquiry_standard *std_inq;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test of the standard INQUIRY page");

        logging(LOG_VERBOSE, "Verify we can read standard INQUIRY page");
        /* 260 bytes is the maximum possible size of the standard vpd */
        ret = inquiry(sd, &task, 0, 0, 260,
                      EXPECT_STATUS_GOOD);
        CU_ASSERT_EQUAL(ret, 0);

        logging(LOG_VERBOSE, "Verify we got at least 36 bytes of data");
        CU_ASSERT(task->datain.size >= 36);

        logging(LOG_VERBOSE, "Verify we can unmarshall the DATA-IN buffer");
        std_inq = scsi_datain_unmarshall(task);
        CU_ASSERT_NOT_EQUAL(std_inq, NULL);
        if (std_inq == NULL) {
                logging(LOG_NORMAL, "[FAILED] Failed to unmarshall DATA-IN "
                        "buffer");
                return;
        }

        logging(LOG_VERBOSE, "Verify peripheral-qualifier is 0");
        CU_ASSERT_EQUAL(std_inq->qualifier, 0);

        logging(LOG_VERBOSE, "Verify version field is either 0x4, 0x5 or 0x6");
        switch (std_inq->version) {
        case 0x0:
                logging(LOG_NORMAL, "[WARNING] Standard INQUIRY data claims "
                        "conformance to no standard. Version==0. "
                        "Bad sport.");

                break;
        case 0x4:
        case 0x5:
        case 0x6:
                break;
        default:
                logging(LOG_NORMAL, "[FAILED] Invalid version in standard "
                        "INQUIRY data. Version %d found but only versions "
                        "0x4,0x4,0x6 are valid.", std_inq->version);
                CU_FAIL("Invalid version in INQUIRY data");
        }

        logging(LOG_VERBOSE, "Verify response-data-format is 2 "
                "(SPC-2 or later)");
        if (std_inq->response_data_format != 2) {
                logging(LOG_NORMAL, "[FAILED] Response data format is "
                        "invalid. Must be 2 but device returned %d",
                        std_inq->response_data_format);
        }
        CU_ASSERT_EQUAL(std_inq->response_data_format, 2);

        logging(LOG_VERBOSE, "Verify additional-length is correct");
        if (std_inq->additional_length > task->datain.size - 5) {
                logging(LOG_NORMAL, "[FAILED] Bad additional length "
                        "returned. Should be %d but device returned %d.",
                        task->datain.size - 5,
                        std_inq->additional_length);
                logging(LOG_NORMAL, "[FAILED] Additional length points "
                        "beyond end of data");
                CU_FAIL("Additional length points beyond end of data");
        }
        if (std_inq->additional_length < task->datain.size - 5) {
                logging(LOG_NORMAL, "[WARNING] Bad additional length "
                        "returned. Should be %d but device returned %d. ",
                        task->datain.size - 5,
                        std_inq->additional_length);
                logging(LOG_VERBOSE, "Verify that all padding data is 0");
                for (i = std_inq->additional_length + 6; i < task->datain.size; i++) {
                        if (!task->datain.data[i])
                                continue;
                        logging(LOG_NORMAL, "[FAILED] Padding data is not zero."
                                           " Are we leaking data?");
                        CU_FAIL("Padding data is not zero. Leaking data?");
                }
        }

        logging(LOG_VERBOSE, "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;
                }

                logging(LOG_NORMAL, "[FAILED] VENDOR_IDENTIFICATION contains "
                        "non-ASCII characters");
                CU_FAIL("Invalid characters in VENDOR_IDENTIFICATION");
                break;
        }

        logging(LOG_VERBOSE, "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;
                }

                logging(LOG_NORMAL, "[FAILED] PRODUCT_IDENTIFICATION contains "
                        "non-ASCII characters");
                CU_FAIL("Invalid characters in PRODUCT_IDENTIFICATION");
                break;
        }

        logging(LOG_VERBOSE, "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;
                }

                logging(LOG_NORMAL, "[FAILED] PRODUCT_REVISON_LEVEL contains "
                        "non-ASCII characters");
                CU_FAIL("Invalid characters in PRODUCT_REVISON_LEVEL");
                break;
        }

        logging(LOG_VERBOSE, "Verify AERC is clear in SPC-3 and later");
        if (task->datain.data[3] & 0x80 && std_inq->version >= 5) {
                logging(LOG_NORMAL, "[FAILED] AERC is set but this device "
                        "reports SPC-3 or later.");
                CU_FAIL("AERC is set but SPC-3+ is claimed");
        }

        logging(LOG_VERBOSE, "Verify TRMTSK is clear in SPC-2 and later");
        if (task->datain.data[3] & 0x40 && std_inq->version >= 4) {
                logging(LOG_NORMAL, "[FAILED] TRMTSK is set but this device "
                        "reports SPC-2 or later.");
                CU_FAIL("TRMTSK is set but SPC-2+ is claimed");
        }

        if (task != NULL) {
                scsi_free_scsi_task(task);
                task = NULL;
        }
}
Ejemplo n.º 27
0
static int iscsi_readcapacity_sync(IscsiLun *iscsilun)
{
    struct scsi_task *task = NULL;
    struct scsi_readcapacity10 *rc10 = NULL;
    struct scsi_readcapacity16 *rc16 = NULL;
    int ret = 0;
    int retries = ISCSI_CMD_RETRIES; 

    do {
        if (task != NULL) {
            scsi_free_scsi_task(task);
            task = NULL;
        }

        switch (iscsilun->type) {
        case TYPE_DISK:
            task = iscsi_readcapacity16_sync(iscsilun->iscsi, iscsilun->lun);
            if (task != NULL && task->status == SCSI_STATUS_GOOD) {
                rc16 = scsi_datain_unmarshall(task);
                if (rc16 == NULL) {
                    error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
                    ret = -EINVAL;
                } else {
                    iscsilun->block_size = rc16->block_length;
                    iscsilun->num_blocks = rc16->returned_lba + 1;
                }
            }
            break;
        case TYPE_ROM:
            task = iscsi_readcapacity10_sync(iscsilun->iscsi, iscsilun->lun, 0, 0);
            if (task != NULL && task->status == SCSI_STATUS_GOOD) {
                rc10 = scsi_datain_unmarshall(task);
                if (rc10 == NULL) {
                    error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
                    ret = -EINVAL;
                } else {
                    iscsilun->block_size = rc10->block_size;
                    if (rc10->lba == 0) {
                        /* blank disk loaded */
                        iscsilun->num_blocks = 0;
                    } else {
                        iscsilun->num_blocks = rc10->lba + 1;
                    }
                }
            }
            break;
        default:
            return 0;
        }
    } while (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
             && task->sense.key == SCSI_SENSE_UNIT_ATTENTION
             && retries-- > 0);

    if (task == NULL || task->status != SCSI_STATUS_GOOD) {
        error_report("iSCSI: failed to send readcapacity10 command.");
        ret = -EINVAL;
    }
    if (task) {
        scsi_free_scsi_task(task);
    }
    return ret;
}
Ejemplo n.º 28
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;
}
Ejemplo n.º 29
0
static void
check_unmap(void)
{
        int i;
        struct scsi_task *task_ret = NULL;
        struct scsi_get_lba_status *lbas;
        uint64_t lba;

        logging(LOG_VERBOSE, "Read LBA mapping from the target");
        GETLBASTATUS(sd, &task_ret, 0, 256,
                     EXPECT_STATUS_GOOD);
        if (task_ret == NULL) {
                logging(LOG_VERBOSE, "[FAILED] Failed to read LBA mapping "
                        "from the target.");
                CU_FAIL("[FAILED] Failed to read LBA mapping "
                        "from the target.");
                return;
        }
        if (task_ret->status != SCSI_STATUS_GOOD) {
                logging(LOG_VERBOSE, "[FAILED] Failed to read LBA mapping "
                        "from the target. Sense: %s",
                        sd->error_str);
                CU_FAIL("[FAILED] Failed to read LBA mapping "
                        "from the target.");
                scsi_free_scsi_task(task_ret);
                return;
        }

        logging(LOG_VERBOSE, "Unmarshall LBA mapping datain buffer");
        lbas = scsi_datain_unmarshall(task_ret);
        if (lbas == NULL) {
                logging(LOG_VERBOSE, "[FAILED] Failed to unmarshall LBA "
                        "mapping");
                CU_FAIL("[FAILED] Failed to read unmarshall LBA mapping");
                scsi_free_scsi_task(task_ret);
                return;
        }

        logging(LOG_VERBOSE, "Verify we got at least one status descriptor "
                "from the target");
        if (lbas->num_descriptors < 1) {
                logging(LOG_VERBOSE, "[FAILED] Wrong number of LBA status "
                        "descriptors. Expected >=1 but got %d descriptors",
                        lbas->num_descriptors);
                CU_FAIL("[FAILED] Wrong number of LBA status descriptors.");
                scsi_free_scsi_task(task_ret);
                return;
        }

        logging(LOG_VERBOSE, "Verify that all descriptors are either "
                "DEALLOCATED or ANCHORED.");
        for (i = 0; i < (int)lbas->num_descriptors; i++) {
                logging(LOG_VERBOSE, "Check descriptor %d LBA:%" PRIu64 "-%"
                        PRIu64 " that it is not MAPPED",
                        i,
                        lbas->descriptors[i].lba,
                        lbas->descriptors[i].lba + lbas->descriptors[i].num_blocks);
                if (lbas->descriptors[i].provisioning == SCSI_PROVISIONING_TYPE_MAPPED) {
                          logging(LOG_VERBOSE, "[FAILED] Descriptor %d is MAPPED."
                                "All descriptors shoudl be either DEALLOCATED "
                                "or ANCHORED after SANITIZE", i);
                          CU_FAIL("[FAILED] LBA status descriptor is MAPPED.");
                }
        }

        logging(LOG_VERBOSE, "Verify that the descriptors cover the whole LUN");
        lba = 0;
        for (i = 0; i < (int)lbas->num_descriptors; i++) {
                logging(LOG_VERBOSE, "Check descriptor %d LBA:%" PRIu64 "-%"
                        PRIu64 " that it is in order",
                        i,
                        lbas->descriptors[i].lba,
                        lbas->descriptors[i].lba + lbas->descriptors[i].num_blocks);
                if (lba != lbas->descriptors[i].lba) {
                          logging(LOG_VERBOSE, "[FAILED] LBA status descriptors "
                                "are not in order.");
                          CU_FAIL("[FAILED] LBA status descriptors not in order");
                }
                lba += lbas->descriptors[i].num_blocks;
        }
        if (lba != num_blocks) {
                  logging(LOG_VERBOSE, "[FAILED] The LUN is not fully"
                        "DEALLOCATED/ANCHORED");
                  CU_FAIL("[FAILED] The LUN is not fully"
                        "DEALLOCATED/ANCHORED");
        }

        scsi_free_scsi_task(task_ret);
}
Ejemplo n.º 30
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;
}