Esempio n. 1
0
void write10_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)
{
	struct write_task *wt = (struct write_task *)private_data;
	struct scsi_task *task = command_data;
	struct client *client = wt->client;

	if (status == SCSI_STATUS_CHECK_CONDITION) {
		printf("Write10 failed with sense key:%d ascq:%04x\n", task->sense.key, task->sense.ascq);
		scsi_free_scsi_task(task);
		exit(10);
	}
	if (status != SCSI_STATUS_GOOD) {
		printf("Write10 failed with %s\n", iscsi_get_error(iscsi));
		scsi_free_scsi_task(task);
		exit(10);
	}

	client->in_flight--;
	fill_read_queue(client);

	if ((client->in_flight == 0) && (client->pos == client->src_num_blocks)) {
		client->finished = 1;
	}
	scsi_free_scsi_task(wt->rt);
	scsi_free_scsi_task(task);
	free(wt);
}
Esempio n. 2
0
File: iscsi.c Progetto: breuerr/qemu
static void
iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status,
                    void *command_data, void *opaque)
{
    IscsiAIOCB *acb = opaque;

    trace_iscsi_aio_read10_cb(iscsi, status, acb, acb->canceled);

    if (acb->canceled != 0) {
        qemu_aio_release(acb);
        scsi_free_scsi_task(acb->task);
        acb->task = NULL;
        return;
    }

    acb->status = 0;
    if (status != 0) {
        error_report("Failed to read10 data from iSCSI lun. %s",
                     iscsi_get_error(iscsi));
        acb->status = -EIO;
    }

    iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
    scsi_free_scsi_task(acb->task);
    acb->task = NULL;
}
Esempio n. 3
0
File: iscsi.c Progetto: 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);
}
Esempio n. 4
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);
}
Esempio 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);
}
Esempio n. 7
0
int T0211_read12_rdprotect(const char *initiator, const char *url)
{
    struct iscsi_context *iscsi;
    struct scsi_task *task;
    int ret = 0, i, lun;

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

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


    printf("Read12 with RDPROTECT ");
    for (i = 1; i <= 7; i++) {
        task = iscsi_read12_sync(iscsi, lun, 0, block_size, block_size, i, 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_CHECK_CONDITION
                || task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
                || task->sense.ascq != SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB) {
            printf("[FAILED]\n");
            printf("Read12 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;
}
Esempio n. 8
0
static BlockDriverAIOCB *
iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
                QEMUIOVector *qiov, int nb_sectors,
                BlockDriverCompletionFunc *cb,
                void *opaque)
{
    IscsiLun *iscsilun = bs->opaque;
    IscsiAIOCB *acb;

    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
    trace_iscsi_aio_readv(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb);

    acb->nb_sectors  = nb_sectors;
    acb->sector_num  = sector_num;
    acb->iscsilun    = iscsilun;
    acb->qiov        = qiov;
    acb->read_size   = BDRV_SECTOR_SIZE * (size_t)acb->nb_sectors;
    acb->retries     = ISCSI_CMD_RETRIES;

    if (iscsi_aio_readv_acb(acb) != 0) {
        if (acb->task) {
            scsi_free_scsi_task(acb->task);
        }
        qemu_aio_release(acb);
        return NULL;
    }

    iscsi_set_events(iscsilun);
    return &acb->common;
}
Esempio n. 9
0
static BlockDriverAIOCB *
iscsi_aio_discard(BlockDriverState *bs,
                  int64_t sector_num, int nb_sectors,
                  BlockDriverCompletionFunc *cb, void *opaque)
{
    IscsiLun *iscsilun = bs->opaque;
    IscsiAIOCB *acb;

    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);

    acb->iscsilun    = iscsilun;
    acb->nb_sectors  = nb_sectors;
    acb->sector_num  = sector_num;
    acb->retries     = ISCSI_CMD_RETRIES;

    if (iscsi_aio_discard_acb(acb) != 0) {
        if (acb->task) {
            scsi_free_scsi_task(acb->task);
        }
        qemu_aio_release(acb);
        return NULL;
    }

    iscsi_set_events(iscsilun);

    return &acb->common;
}
Esempio n. 10
0
static void
iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
                     void *command_data, void *opaque)
{
    IscsiAIOCB *acb = opaque;

    if (acb->canceled != 0) {
        return;
    }

    acb->status = 0;
    if (status != 0) {
        if (status == SCSI_STATUS_CHECK_CONDITION
            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
            && acb->retries-- > 0) {
            scsi_free_scsi_task(acb->task);
            acb->task = NULL;
            if (iscsi_aio_discard_acb(acb) == 0) {
                iscsi_set_events(acb->iscsilun);
                return;
            }
        }
        error_report("Failed to unmap data on iSCSI lun. %s",
                     iscsi_get_error(iscsi));
        acb->status = -EIO;
    }

    iscsi_schedule_bh(acb);
}
Esempio n. 11
0
void read10_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)
{
	struct client *client = (struct client *)private_data;
	struct scsi_task *task = command_data;
	struct write_task *wt;

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

	wt = malloc(sizeof(struct write_task));
	wt->rt = task;
	wt->client = client;

	if (iscsi_write10_task(client->dst_iscsi,
			client->dst_lun,
			task->params.read10.lba,
			task->datain.data,
			task->datain.size,
			client->dst_blocksize,
			0, 0, 0, 0, 0,
			write10_cb, wt) == NULL) {
		printf("failed to send read10 command\n");
		scsi_free_scsi_task(task);
		exit(10);
	}
}
Esempio n. 12
0
void
test_teardown(void)
{
	free(read_write_buf);
	read_write_buf = NULL;
	scsi_free_scsi_task(task);
	task = NULL;
}
Esempio n. 13
0
void iscsi_free_scsi_cbdata(struct iscsi_scsi_cbdata *scsi_cbdata)
{
    if (scsi_cbdata == NULL) {
        return;
    }
    if (scsi_cbdata->task == NULL) {
        scsi_free_scsi_task(scsi_cbdata->task);
        scsi_cbdata->task = NULL;
    }
    free(scsi_cbdata);
}
Esempio n. 14
0
ssize_t write(int fd, const void *buf, size_t count)
{
	if ((iscsi_fd_list[fd].is_iscsi == 1) && (iscsi_fd_list[fd].in_flight == 0)) {
		uint64_t offset;
		uint64_t num_blocks, lba;
		struct scsi_task *task;

		if (iscsi_fd_list[fd].dup2fd >= 0) {
			return write(iscsi_fd_list[fd].dup2fd, buf, count);
		}
		if (iscsi_fd_list[fd].offset%iscsi_fd_list[fd].block_size) {
			errno = EINVAL;
			return -1;
		}
		if (count%iscsi_fd_list[fd].block_size) {
			errno = EINVAL;
			return -1;
		}

                iscsi_fd_list[fd].lbasd_cache_valid = 0;

		offset = iscsi_fd_list[fd].offset;
		num_blocks = count/iscsi_fd_list[fd].block_size;
		lba = offset / iscsi_fd_list[fd].block_size;

		/* Don't try to read beyond the last LBA */
		if (lba >= iscsi_fd_list[fd].num_blocks) {
			return 0;
		}
		/* Trim num_blocks requested to last lba */
		if ((lba + num_blocks) > iscsi_fd_list[fd].num_blocks) {
			num_blocks = iscsi_fd_list[fd].num_blocks - lba;
			count = num_blocks * iscsi_fd_list[fd].block_size;
		}

		iscsi_fd_list[fd].in_flight = 1;
		LD_ISCSI_DPRINTF(4,"write16_sync: lun %d, lba %"PRIu64", num_blocks: %"PRIu64", block_size: %d, offset: %"PRIu64" count: %lu",iscsi_fd_list[fd].lun,lba,num_blocks,iscsi_fd_list[fd].block_size,offset,(unsigned long)count);
		task = iscsi_write16_sync(iscsi_fd_list[fd].iscsi, iscsi_fd_list[fd].lun, lba, (unsigned char *) buf, count, iscsi_fd_list[fd].block_size, 0, 0, 0, 0, 0);
		iscsi_fd_list[fd].in_flight = 0;
		if (task == NULL || task->status != SCSI_STATUS_GOOD) {
			LD_ISCSI_DPRINTF(0,"failed to send write16 command");
			errno = EIO;
			return -1;
		}

		iscsi_fd_list[fd].offset += count;
		scsi_free_scsi_task(task);

		return count;
	}

	return real_write(fd, buf, count);
}
Esempio n. 15
0
static void
iscsi_bh_cb(void *p)
{
    IscsiAIOCB *acb = p;

    qemu_bh_delete(acb->bh);

    if (acb->canceled == 0) {
        acb->common.cb(acb->common.opaque, acb->status);
    }

    if (acb->task != NULL) {
        scsi_free_scsi_task(acb->task);
        acb->task = NULL;
    }

    qemu_aio_release(acb);
}
Esempio n. 16
0
static void
iscsi_bh_cb(void *p)
{
    IscsiAIOCB *acb = p;

    qemu_bh_delete(acb->bh);

    g_free(acb->buf);
    acb->buf = NULL;

    acb->common.cb(acb->common.opaque, acb->status);

    if (acb->task != NULL) {
        scsi_free_scsi_task(acb->task);
        acb->task = NULL;
    }

    qemu_aio_unref(acb);
}
void
test_receive_copy_results_op_params(void)
{
        struct scsi_task *op_task = NULL;
        struct scsi_copy_results_op_params *opp;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test RECEIVE COPY RESULTS, OPERATING PARAMS");

        RECEIVE_COPY_RESULTS(&op_task, sd, SCSI_COPY_RESULTS_OP_PARAMS, 0,
                             (void **)&opp, EXPECT_STATUS_GOOD);

        logging(LOG_NORMAL,
                        "max_target_desc=%d, max_seg_desc=%d",
                        opp->max_target_desc_count,
                        opp->max_segment_desc_count);

        scsi_free_scsi_task(op_task);
}
Esempio n. 18
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;
	}
}
Esempio n. 19
0
int T0234_write12_beyondeol(const char *initiator, const char *url)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	int ret, i, lun;
	unsigned char data[4096 * 258];

	printf("0234_write12_beyond_eol:\n");
	printf("=======================\n");
	if (show_info) {
		printf("Test that WRITE12 fails if writing beyond end-of-lun.\n");
		printf("This test is skipped for LUNs with more than 2^31 blocks\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;
	}

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


	ret = 0;

	if (num_blocks >= 0x80000000) {
		printf("[SKIPPED]\n");
		printf("LUN is too big for read-beyond-eol tests with WRITE12. Skipping test.\n");
		ret = -2;
		goto finished;
	}

	/* 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_write12_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 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 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;
}
Esempio n. 20
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;
}
Esempio n. 21
0
static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
        unsigned long int req, void *buf,
        BlockDriverCompletionFunc *cb, void *opaque)
{
    IscsiLun *iscsilun = bs->opaque;
    struct iscsi_context *iscsi = iscsilun->iscsi;
    struct iscsi_data data;
    IscsiAIOCB *acb;

    assert(req == SG_IO);

    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);

    acb->iscsilun = iscsilun;
    acb->canceled    = 0;
    acb->bh          = NULL;
    acb->status      = -EINPROGRESS;
    acb->buf         = NULL;
    acb->ioh         = buf;

    acb->task = malloc(sizeof(struct scsi_task));
    if (acb->task == NULL) {
        error_report("iSCSI: Failed to allocate task for scsi command. %s",
                     iscsi_get_error(iscsi));
        qemu_aio_release(acb);
        return NULL;
    }
    memset(acb->task, 0, sizeof(struct scsi_task));

    switch (acb->ioh->dxfer_direction) {
    case SG_DXFER_TO_DEV:
        acb->task->xfer_dir = SCSI_XFER_WRITE;
        break;
    case SG_DXFER_FROM_DEV:
        acb->task->xfer_dir = SCSI_XFER_READ;
        break;
    default:
        acb->task->xfer_dir = SCSI_XFER_NONE;
        break;
    }

    acb->task->cdb_size = acb->ioh->cmd_len;
    memcpy(&acb->task->cdb[0], acb->ioh->cmdp, acb->ioh->cmd_len);
    acb->task->expxferlen = acb->ioh->dxfer_len;

    data.size = 0;
    if (acb->task->xfer_dir == SCSI_XFER_WRITE) {
        if (acb->ioh->iovec_count == 0) {
            data.data = acb->ioh->dxferp;
            data.size = acb->ioh->dxfer_len;
        } else {
#if defined(LIBISCSI_FEATURE_IOVECTOR)
            scsi_task_set_iov_out(acb->task,
                                 (struct scsi_iovec *) acb->ioh->dxferp,
                                 acb->ioh->iovec_count);
#else
            struct iovec *iov = (struct iovec *)acb->ioh->dxferp;

            acb->buf = g_malloc(acb->ioh->dxfer_len);
            data.data = acb->buf;
            data.size = iov_to_buf(iov, acb->ioh->iovec_count, 0,
                                   acb->buf, acb->ioh->dxfer_len);
#endif
        }
    }

    if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
                                 iscsi_aio_ioctl_cb,
                                 (data.size > 0) ? &data : NULL,
                                 acb) != 0) {
        scsi_free_scsi_task(acb->task);
        qemu_aio_release(acb);
        return NULL;
    }

    /* tell libiscsi to read straight into the buffer we got from ioctl */
    if (acb->task->xfer_dir == SCSI_XFER_READ) {
        if (acb->ioh->iovec_count == 0) {
            scsi_task_add_data_in_buffer(acb->task,
                                         acb->ioh->dxfer_len,
                                         acb->ioh->dxferp);
        } else {
#if defined(LIBISCSI_FEATURE_IOVECTOR)
            scsi_task_set_iov_in(acb->task,
                                 (struct scsi_iovec *) acb->ioh->dxferp,
                                 acb->ioh->iovec_count);
#else
            int i;
            for (i = 0; i < acb->ioh->iovec_count; i++) {
                struct iovec *iov = (struct iovec *)acb->ioh->dxferp;

                scsi_task_add_data_in_buffer(acb->task,
                    iov[i].iov_len,
                    iov[i].iov_base);
            }
#endif
        }
    }

    iscsi_set_events(iscsilun);

    return &acb->common;
}
Esempio n. 22
0
static int
iscsi_aio_readv_acb(IscsiAIOCB *acb)
{
    struct iscsi_context *iscsi = acb->iscsilun->iscsi;
    size_t size;
    uint64_t lba;
    uint32_t num_sectors;
    int ret;
#if !defined(LIBISCSI_FEATURE_IOVECTOR)
    int i;
#endif

    acb->canceled    = 0;
    acb->bh          = NULL;
    acb->status      = -EINPROGRESS;
    acb->buf         = NULL;

    size = acb->nb_sectors * BDRV_SECTOR_SIZE;

    acb->task = malloc(sizeof(struct scsi_task));
    if (acb->task == NULL) {
        error_report("iSCSI: Failed to allocate task for scsi READ16 "
                     "command. %s", iscsi_get_error(iscsi));
        return -1;
    }
    memset(acb->task, 0, sizeof(struct scsi_task));

    acb->task->xfer_dir = SCSI_XFER_READ;
    acb->task->expxferlen = size;
    lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
    num_sectors = sector_qemu2lun(acb->nb_sectors, acb->iscsilun);

    switch (acb->iscsilun->type) {
    case TYPE_DISK:
        acb->task->cdb_size = 16;
        acb->task->cdb[0]  = 0x88;
        *(uint32_t *)&acb->task->cdb[2]  = htonl(lba >> 32);
        *(uint32_t *)&acb->task->cdb[6]  = htonl(lba & 0xffffffff);
        *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
        break;
    default:
        acb->task->cdb_size = 10;
        acb->task->cdb[0]  = 0x28;
        *(uint32_t *)&acb->task->cdb[2] = htonl(lba);
        *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
        break;
    }

    ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
                                   iscsi_aio_read16_cb,
                                   NULL,
                                   acb);
    if (ret != 0) {
        scsi_free_scsi_task(acb->task);
        return -1;
    }

#if defined(LIBISCSI_FEATURE_IOVECTOR)
    scsi_task_set_iov_in(acb->task, (struct scsi_iovec*) acb->qiov->iov, acb->qiov->niov);
#else
    for (i = 0; i < acb->qiov->niov; i++) {
        scsi_task_add_data_in_buffer(acb->task,
                acb->qiov->iov[i].iov_len,
                acb->qiov->iov[i].iov_base);
    }
#endif
    return 0;
}
Esempio n. 23
0
static int
iscsi_aio_writev_acb(IscsiAIOCB *acb)
{
    struct iscsi_context *iscsi = acb->iscsilun->iscsi;
    size_t size;
    uint32_t num_sectors;
    uint64_t lba;
#if !defined(LIBISCSI_FEATURE_IOVECTOR)
    struct iscsi_data data;
#endif
    int ret;

    acb->canceled   = 0;
    acb->bh         = NULL;
    acb->status     = -EINPROGRESS;
    acb->buf        = NULL;

    /* this will allow us to get rid of 'buf' completely */
    size = acb->nb_sectors * BDRV_SECTOR_SIZE;

#if !defined(LIBISCSI_FEATURE_IOVECTOR)
    data.size = MIN(size, acb->qiov->size);

    /* if the iovec only contains one buffer we can pass it directly */
    if (acb->qiov->niov == 1) {
        data.data = acb->qiov->iov[0].iov_base;
    } else {
        acb->buf = g_malloc(data.size);
        qemu_iovec_to_buf(acb->qiov, 0, acb->buf, data.size);
        data.data = acb->buf;
    }
#endif

    acb->task = malloc(sizeof(struct scsi_task));
    if (acb->task == NULL) {
        error_report("iSCSI: Failed to allocate task for scsi WRITE16 "
                     "command. %s", iscsi_get_error(iscsi));
        return -1;
    }
    memset(acb->task, 0, sizeof(struct scsi_task));

    acb->task->xfer_dir = SCSI_XFER_WRITE;
    acb->task->cdb_size = 16;
    acb->task->cdb[0] = 0x8a;
    lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
    *(uint32_t *)&acb->task->cdb[2]  = htonl(lba >> 32);
    *(uint32_t *)&acb->task->cdb[6]  = htonl(lba & 0xffffffff);
    num_sectors = sector_qemu2lun(acb->nb_sectors, acb->iscsilun);
    *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
    acb->task->expxferlen = size;

#if defined(LIBISCSI_FEATURE_IOVECTOR)
    ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
                                   iscsi_aio_write16_cb,
                                   NULL,
                                   acb);
#else
    ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
                                   iscsi_aio_write16_cb,
                                   &data,
                                   acb);
#endif
    if (ret != 0) {
        scsi_free_scsi_task(acb->task);
        g_free(acb->buf);
        return -1;
    }

#if defined(LIBISCSI_FEATURE_IOVECTOR)
    scsi_task_set_iov_out(acb->task, (struct scsi_iovec*) acb->qiov->iov, acb->qiov->niov);
#endif

    return 0;
}
Esempio n. 24
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;
}
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);
}
Esempio n. 26
0
void
test_modesense6_residuals(void)
{
	struct scsi_task *ms_task = NULL;
	int ret;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test of MODESENSE6 Residuals");

	logging(LOG_VERBOSE, "MODESENSE6 command should not result in any "
		"residuals");

	
	logging(LOG_VERBOSE, "Try a MODESENSE6 command with 4 bytes of "
		"transfer length and verify that we don't get residuals.");
	ret = modesense6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
			 SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 4,
			 EXPECT_STATUS_GOOD);
	CU_ASSERT_EQUAL(ret, 0);
	logging(LOG_VERBOSE, "[SUCCESS] All Pages fetched.");


	logging(LOG_VERBOSE, "Verify that we got at most 4 bytes of DATA-IN");
	if (ms_task->datain.size > 4) {
		logging(LOG_NORMAL, "[FAILED] got more than 4 bytes of "
			"DATA-IN.");
	} else {
		logging(LOG_VERBOSE, "[SUCCESS] <= 4 bytes of DATA-IN "
			"received.");
	}
	CU_ASSERT_TRUE(ms_task->datain.size <= 4);


	logging(LOG_VERBOSE, "Verify residual overflow flag not set");
	if (ms_task->residual_status == SCSI_RESIDUAL_OVERFLOW) {
		logging(LOG_VERBOSE, "[FAILED] Target set residual "
			"overflow flag");
	}
	CU_ASSERT_NOT_EQUAL(ms_task->residual_status, SCSI_RESIDUAL_OVERFLOW);



	logging(LOG_VERBOSE, "Try a MODESENSE6 command with 255 bytes of "
		"transfer length and verify that we get residuals if the target returns less than the requested amount of data.");
	scsi_free_scsi_task(ms_task);
	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] All Pages fetched.");

	if (ms_task->datain.size == 255) {
		logging(LOG_VERBOSE, "We got all 255 bytes of data back "
			"from the target. Verify that underflow is not set.");

		if (ms_task->residual_status == SCSI_RESIDUAL_UNDERFLOW) {
			logging(LOG_VERBOSE, "[FAILED] Target set residual "
				"underflow flag");
		} else {
			logging(LOG_VERBOSE, "[SUCCESS] Residual underflow "
				"is not set");
		}
		CU_ASSERT_NOT_EQUAL(ms_task->residual_status,
				SCSI_RESIDUAL_UNDERFLOW);
	} else {
		logging(LOG_VERBOSE, "We got less than the requested 255 bytes "
			"from the target. Verify that underflow is set.");

		if (ms_task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
			logging(LOG_VERBOSE, "[FAILED] Target did not set "
				"residual underflow flag");
		} else {
			logging(LOG_VERBOSE, "[SUCCESS] Residual underflow "
				"is set");
		}
		CU_ASSERT_EQUAL(ms_task->residual_status,
				SCSI_RESIDUAL_UNDERFLOW);
	}

	scsi_free_scsi_task(ms_task);
}
Esempio n. 27
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;
}
Esempio n. 28
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;
}
static void
check_wabereq(void)
{
        struct scsi_task *task_ret = NULL;

        logging(LOG_VERBOSE, "Read one block from LBA 0");
        READ10(sd, &task_ret, 0, block_size, block_size, 0, 0, 0, 0, 0, NULL,
               EXPECT_STATUS_GOOD);
        CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
        if (task_ret == NULL) {
                return;
        }
        CU_ASSERT_NOT_EQUAL(task_ret->status, SCSI_STATUS_CANCELLED);

        switch (inq_bdc->wabereq) {
        case 0:
                logging(LOG_NORMAL, "[FAILED] SANITIZE BLOCK ERASE "
                        "opcode is supported but WABEREQ is 0");
                CU_FAIL("[FAILED] SANITIZE BLOCK ERASE "
                        "opcode is supported but WABEREQ is 0");
                break;
        case 1:
                logging(LOG_VERBOSE, "WABEREQ==1. Reads from the "
                        "device should be successful.");
                if (task_ret->status == SCSI_STATUS_GOOD) {
                        logging(LOG_VERBOSE, "[SUCCESS] Read was "
                                "successful after SANITIZE");
                        break;
                }
                logging(LOG_NORMAL, "[FAILED] Read after "
                        "SANITIZE failed but WABEREQ is 1");
                CU_FAIL("[FAILED] Read after SANITIZE failed "
                        "but WABEREQ is 1");
                break;
        case 2:
                logging(LOG_VERBOSE, "WABEREQ==2. Reads from the "
                        "device should fail.");
                if (task_ret->status        == SCSI_STATUS_CHECK_CONDITION
                    && task_ret->sense.key  == SCSI_SENSE_MEDIUM_ERROR
                    && task_ret->sense.ascq != SCSI_SENSE_ASCQ_WRITE_AFTER_SANITIZE_REQUIRED) {
                        logging(LOG_VERBOSE, "[SUCCESS] Read failed "
                                "with CHECK_CONDITION/MEDIUM_ERROR/"
                                "!WRITE_AFTER_SANITIZE_REQUIRED");
                        break;
                }
                logging(LOG_VERBOSE, "[FAILED] Read should have failed "
                        "with CHECK_CONDITION/MEDIUM_ERROR/"
                        "!WRITE_AFTER_SANITIZE_REQUIRED");
                CU_FAIL("[FAILED] Read should have failed "
                        "with CHECK_CONDITION/MEDIUM_ERROR/"
                        "!WRITE_AFTER_SANITIZE_REQUIRED");
                break;
        case 3:
                logging(LOG_VERBOSE, "WABEREQ==3. Reads from the "
                        "device should fail.");
                if (task_ret->status        == SCSI_STATUS_CHECK_CONDITION
                    && task_ret->sense.key  == SCSI_SENSE_MEDIUM_ERROR
                    && task_ret->sense.ascq == SCSI_SENSE_ASCQ_WRITE_AFTER_SANITIZE_REQUIRED) {
                        logging(LOG_VERBOSE, "[SUCCESS] Read failed "
                                "with CHECK_CONDITION/MEDIUM_ERROR/"
                                "WRITE_AFTER_SANITIZE_REQUIRED");
                        break;
                }
                logging(LOG_VERBOSE, "[FAILED] Read should have failed "
                        "with CHECK_CONDITION/MEDIUM_ERROR/"
                        "WRITE_AFTER_SANITIZE_REQUIRED");
                CU_FAIL("[FAILED] Read should have failed "
                        "with CHECK_CONDITION/MEDIUM_ERROR/"
                        "WRITE_AFTER_SANITIZE_REQUIRED");
                break;
        }

        scsi_free_scsi_task(task_ret);
}
Esempio n. 30
0
int T0105_read10_invalid(const char *initiator, const char *url)
{
    struct iscsi_context *iscsi;
    struct scsi_task *task;
    struct iscsi_data data;
    char buf[512];
    int ret, lun;

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


    ret = 0;

    /* Try a read of 1 block but xferlength == 0 */
    printf("Read10 1 block but with iscsi ExpectedDataTransferLength==0 ... ");

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

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

    if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) {
        printf("[FAILED]\n");
        printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
        ret = -1;

        goto finished;
    }
    if (task->status != SCSI_STATUS_GOOD) {
        printf("[FAILED]\n");
        printf("Read10 of 1 block with iscsi ExpectedDataTransferLength==0 should not fail.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test2;
    }
    if (task->residual_status != SCSI_RESIDUAL_OVERFLOW || task->residual != 512) {
        printf("[FAILED]\n");
        printf("Read10 returned incorrect residual overflow.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test5;
    }
    scsi_free_scsi_task(task);
    printf("[OK]\n");


test2:
    /* Try a read of 1 block but xferlength == 1024 */
    printf("Read10 1 block but with iscsi ExpectedDataTransferLength==1024 ... ");

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

    memset(task, 0, sizeof(struct scsi_task));
    task->cdb[0] = SCSI_OPCODE_READ10;
    task->cdb[8] = 1;
    task->cdb_size = 10;
    task->xfer_dir = SCSI_XFER_READ;
    task->expxferlen = 1024;

    if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) {
        printf("[FAILED]\n");
        printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
        ret = -1;

        goto finished;
    }
    if (task->status != SCSI_STATUS_GOOD) {
        printf("[FAILED]\n");
        printf("Read10 of 1 block with iscsi ExpectedDataTransferLength==1024 should not fail.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test3;
    }
    if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW || task->residual != 512) {
        printf("[FAILED]\n");
        printf("Read10 returned incorrect residual underflow.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test5;
    }
    scsi_free_scsi_task(task);
    printf("[OK]\n");


test3:
    /* Try a read of 1 block but xferlength == 200 */
    printf("Read10 1 block but with iscsi ExpectedDataTransferLength==200 ... ");

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

    memset(task, 0, sizeof(struct scsi_task));
    task->cdb[0] = SCSI_OPCODE_READ10;
    task->cdb[8] = 1;
    task->cdb_size = 10;
    task->xfer_dir = SCSI_XFER_READ;
    task->expxferlen = 200;

    if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) {
        printf("[FAILED]\n");
        printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
        ret = -1;

        goto finished;
    }
    if (task->status != SCSI_STATUS_GOOD) {
        printf("[FAILED]\n");
        printf("Read10 of 1 block with iscsi ExpectedDataTransferLength==200 should not fail.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test4;
    }
    if (task->residual_status != SCSI_RESIDUAL_OVERFLOW || task->residual != 312) {
        printf("[FAILED]\n");
        printf("Read10 returned incorrect residual overflow.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test5;
    }
    scsi_free_scsi_task(task);
    printf("[OK]\n");

test4:
    /* Try a read of 2 blocks but xferlength == 512 */
    printf("Read10 2 blocks but with iscsi ExpectedDataTransferLength==512 ... ");

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

    memset(task, 0, sizeof(struct scsi_task));
    task->cdb[0] = SCSI_OPCODE_READ10;
    task->cdb[8] = 2;
    task->cdb_size = 10;
    task->xfer_dir = SCSI_XFER_READ;
    task->expxferlen = 512;

    if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) {
        printf("[FAILED]\n");
        printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
        ret = -1;

        goto finished;
    }
    if (task->status != SCSI_STATUS_GOOD) {
        printf("[FAILED]\n");
        printf("Read10 of 2 blocks with iscsi ExpectedDataTransferLength==512 should succeed.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test5;
    }
    if (task->residual_status != SCSI_RESIDUAL_OVERFLOW || task->residual != 512) {
        printf("[FAILED]\n");
        printf("Read10 returned incorrect residual overflow.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test5;
    }

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


test5:
    /* Try a read of 1 block but make it a data-out write on the iscsi layer */
    printf("Read10 of 1 block but sent as data-out write in iscsi layer ... ");

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

    memset(task, 0, sizeof(struct scsi_task));
    task->cdb[0] = SCSI_OPCODE_READ10;
    task->cdb[8] = 1;
    task->cdb_size = 10;
    task->xfer_dir = SCSI_XFER_WRITE;
    task->expxferlen = sizeof(buf);

    data.size = sizeof(buf);
    data.data = &buf[0];

    if (iscsi_scsi_command_sync(iscsi, lun, task, &data) == 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 1 block but iscsi data-out write should fail.\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;
}