示例#1
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;
}
示例#2
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;
}
示例#3
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;
}
示例#4
0
/*
 * We support iscsi url's on the form
 * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
 */
static int iscsi_open(BlockDriverState *bs, const char *filename, 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;
    struct scsi_readcapacity10 *rc10 = NULL;
    struct scsi_readcapacity16 *rc16 = NULL;
    char *initiator_name = NULL;
    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;
    }

    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;

    scsi_free_scsi_task(task);

    switch (iscsilun->type) {
    case TYPE_DISK:
        task = iscsi_readcapacity16_sync(iscsi, iscsilun->lun);
        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
            error_report("iSCSI: failed to send readcapacity16 command.");
            ret = -EINVAL;
            goto out;
        }
        rc16 = scsi_datain_unmarshall(task);
        if (rc16 == NULL) {
            error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
            ret = -EINVAL;
            goto out;
        }
        iscsilun->block_size = rc16->block_length;
        iscsilun->num_blocks = rc16->returned_lba + 1;
        break;
    case TYPE_ROM:
        task = iscsi_readcapacity10_sync(iscsi, iscsilun->lun, 0, 0);
        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
            error_report("iSCSI: failed to send readcapacity10 command.");
            ret = -EINVAL;
            goto out;
        }
        rc10 = scsi_datain_unmarshall(task);
        if (rc10 == NULL) {
            error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
            ret = -EINVAL;
            goto out;
        }
        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:
        break;
    }

    bs->total_sectors    = iscsilun->num_blocks *
                           iscsilun->block_size / BDRV_SECTOR_SIZE ;

    /* 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;
    }

    ret = 0;

#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:
    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;
}
示例#5
0
int T0200_read16_simple(const char *initiator, const char *url, int data_loss _U_, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity10 *rc10;
	int ret, i, lun;
	uint32_t block_size, num_blocks;

	printf("0200_read16_simple:\n");
	printf("===================\n");
	if (show_info) {
		printf("Test basic READ16 functionality.\n");
		printf("1, Verify we can read the first 1-256 blocks of the LUN.\n");
		printf("2, Verify we can read 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_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;

	/* read the first 1 - 256 blocks at the start of the LUN */
	printf("Reading first 1-256 blocks ... ");
	for (i=1; i<=256; i++) {
		task = iscsi_read16_sync(iscsi, lun, 0, i * block_size, block_size, 0, 0, 0, 0, 0);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send read16 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto finished;
		}
		if (task->status != SCSI_STATUS_GOOD) {
		        printf("[FAILED]\n");
			printf("Read16 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");


	/* read the last 1 - 256 blocks at the end of the LUN */
	printf("Reading last 1-256 blocks ... ");
	for (i=1; i<=256; i++) {
		task = iscsi_read16_sync(iscsi, lun, num_blocks +1 - i, i * block_size, block_size, 0, 0, 0, 0, 0);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send read16 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto finished;
		}
		if (task->status != SCSI_STATUS_GOOD) {
		        printf("[FAILED]\n");
			printf("Read16 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;
}
示例#6
0
int
main(int argc, char *argv[])
{
	char *testname_re = NULL;
	int lun;
	CU_BasicRunMode mode = CU_BRM_VERBOSE;
	CU_ErrorAction error_action = CUEA_IGNORE;
	int res;
	struct scsi_readcapacity10 *rc10;
	struct scsi_task *inq_task = NULL;
	struct scsi_task *inq_lbp_task = NULL;
	struct scsi_task *inq_bdc_task = NULL;
	struct scsi_task *inq_bl_task = NULL;
	struct scsi_task *rc16_task = NULL;
	struct scsi_task *rsop_task = NULL;
	int full_size;
	int is_usb = 0;
	int xml_mode = 0;
	static struct option long_opts[] = {
		{ "help", no_argument, 0, '?' },
		{ "list", no_argument, 0, 'l' },
		{ "initiator-name", required_argument, 0, 'i' },
		{ "initiator-name-2", required_argument, 0, 'I' },
		{ "test", required_argument, 0, 't' },
		{ "dataloss", no_argument, 0, 'd' },
		{ "allow-sanitize", no_argument, 0, 'S' },
		{ "ignore", no_argument, 0, 'g' },
		{ "fail", no_argument, 0, 'f' },
		{ "abort", no_argument, 0, 'A' },
		{ "silent", no_argument, 0, 's' },
		{ "normal", no_argument, 0, 'n' },
		{ "usb", no_argument, 0, 'u' },
		{ "verbose", no_argument, 0, 'v' },
		{ "xml", no_argument, 0, 'x' },
		{ "Verbose-scsi", no_argument, 0, 'V' },
		{ NULL, 0, 0, 0 }
	};
	int i, c;
	int opt_idx = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	iscsi_logout_sync(iscsic);
	iscsi_destroy_context(iscsic);

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

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

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

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

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

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

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

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

	return 0;
}
示例#7
0
void show_lun(struct iscsi_context *iscsi, int lun)
{
	struct scsi_task *task;
	struct scsi_inquiry_standard *inq;
	int type;
	long long size = 0;
	int size_pf = 0;
	static const char sf[] = {' ', 'k', 'M', 'G', 'T' };

	/* check we can talk to the lun */
tur_try_again:
	if ((task = iscsi_testunitready_sync(iscsi, lun)) == NULL) {
		fprintf(stderr, "testunitready failed\n");
		exit(10);
	}
	if (task->status == SCSI_STATUS_CHECK_CONDITION) {
		if (task->sense.key == SCSI_SENSE_UNIT_ATTENTION && task->sense.ascq == SCSI_SENSE_ASCQ_BUS_RESET) {
			scsi_free_scsi_task(task);
			goto tur_try_again;
		}
	}
	if (task->status != SCSI_STATUS_GOOD) {
		fprintf(stderr, "TESTUNITREADY failed with %s\n", iscsi_get_error(iscsi));
		exit(10);
	}
	scsi_free_scsi_task(task);



	/* check what type of lun we have */
	task = iscsi_inquiry_sync(iscsi, lun, 0, 0, 64);
	if (task == NULL || task->status != SCSI_STATUS_GOOD) {
		fprintf(stderr, "failed to send inquiry command : %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);
	}
	type = inq->periperal_device_type;
	scsi_free_scsi_task(task);



	if (type == SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
		struct scsi_readcapacity10 *rc10;

		task = iscsi_readcapacity10_sync(iscsi, 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);
		}

		size  = rc10->block_size;
		size *= rc10->lba;

		for (size_pf=0; size_pf<4 && size > 1024; size_pf++) {
			size /= 1024;
		}

		scsi_free_scsi_task(task);
	}


	printf("Lun:%-4d Type:%s", lun, scsi_devtype_to_str(type));
	if (type == SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
		printf(" (Size:%lld%c)", size, sf[size_pf]);
	}
	printf("\n");
}
示例#8
0
int T0101_read10_beyond_eol(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;

	/* read 1-256 blocks, one block beyond the end-of-lun */
	printf("Reading last 1-256 blocks one block beyond eol ... ");
	for (i=1; i<=256; i++) {
		task = iscsi_read10_sync(iscsi, lun, num_blocks + 2 - i, i * block_size, 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 beyond end-of-lun did not fail with sense.\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		if (task->sense.key != SCSI_SENSE_ILLEGAL_REQUEST) {
			printf("[FAILED]\n");
			printf("Read10 beyond end-of-lun did not return sense key ILLEGAL_REQUEST.\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		if (task->sense.ascq != SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE) {
			printf("[FAILED]\n");
			printf("Read10 beyond end-of-lun did not return sense ascq LBA OUT OF RANGE.\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");


	/* read 2-256 blocks, all but one block beyond the eol */
	printf("Reading 1-255 blocks beyond eol starting at last block ... ");
	for (i=2; i<=256; i++) {
		task = iscsi_read10_sync(iscsi, lun, num_blocks, i * block_size, 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 beyond end-of-lun did not return sense.\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		if (task->sense.key != SCSI_SENSE_ILLEGAL_REQUEST) {
			printf("[FAILED]\n");
			printf("Read10 beyond end-of-lun did not return sense key ILLEGAL_REQUEST.\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		if (task->sense.ascq != SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE) {
			printf("[FAILED]\n");
			printf("Read10 beyond end-of-lun did not return sense ascq 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;
}