Пример #1
0
static void
iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
                        void *command_data, void *opaque)
{
    struct IscsiTask *iTask = opaque;
    struct scsi_task *task = command_data;

    iTask->complete = 1;
    iTask->status = status;
    iTask->do_retry = 0;
    iTask->task = task;

    if (iTask->retries-- > 0 && status == SCSI_STATUS_CHECK_CONDITION
        && task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
        error_report("iSCSI CheckCondition: %s", iscsi_get_error(iscsi));
        iTask->do_retry = 1;
        goto out;
    }

    if (status != SCSI_STATUS_GOOD) {
        error_report("iSCSI Failure: %s", iscsi_get_error(iscsi));
    }

out:
    if (iTask->co) {
        iTask->bh = qemu_bh_new(iscsi_co_generic_bh_cb, iTask);
        qemu_bh_schedule(iTask->bh);
    }
}
Пример #2
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);
}
Пример #3
0
void iSCSILibWrapper::ServiceISCSIEvents(bool oneShot)
{
    // Event loop to drive the connection through its paces

    while (mClient.finished == 0 && mClient.error == 0 || oneShot)
    {
        int res = 0;

        mPfd.fd = iscsi_get_fd(mIscsi);
        mPfd.events = iscsi_which_events(mIscsi);

        if ((res = poll(&mPfd, 1, mTimeout)) <= 0)
        {
            mError = true;
            if (res)
                mErrorString.Format("%s: poll failed: %s ", 
                                    __func__, 
                                    strerror(errno));
            else
                mErrorString.Format("%s: poll timed out: %d mSec",
                                    __func__,
                                    mTimeout);
            throw CException(mErrorString);
        }

        if (iscsi_service(mIscsi, mPfd.revents) < 0)
        {
            mError = true;
            mErrorString.Format("%s: iscsi_service failed with: %s",
                               __func__,
                              iscsi_get_error(mIscsi));
            throw CException(mErrorString);
        }

        if (oneShot)
        {
            break;
        }
    }

    // Get the iscsi error if there is one at this point
    if (mClient.error != 0)
    {
        mErrorString.Format("%s: %s: %s", __func__,
                            mClient.error_message, 
                            iscsi_get_error(mIscsi));
	throw CException(mErrorString);
    }
}
Пример #4
0
/*
 * Disconnect from the target
 */
void iSCSILibWrapper::iSCSIDisconnect(void)
{
    // Remove us from the background thread
    iSCSIBackGround::GetInstance().RemoveConnection(*this);

    if (!mIscsi)
    {
        mErrorString.Format("%s: Disconnect from target %s not possible without a connection!",
                            __func__,
                            mTarget.c_str());
        mError = true;
        throw CException(mErrorString);
    }

    if (mClient.connected && iscsi_disconnect(mIscsi))
    {
        mErrorString.Format("%s: Failed to disconnect from target %s disconnect: %s",
                           __func__,
                           mAddress.c_str(),
                           iscsi_get_error(mIscsi));
        mError = true;
        throw CException(mErrorString);
    }

    mClient.finished = 0;

    iscsi_destroy_context(mIscsi);
    mIscsi = NULL;
    mClient.connected = 0; // We are no longer connected
    mClient.error = 0;     // There can be no error from here on in
}
Пример #5
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);
}
Пример #6
0
/*
 * Perform actual discovery against the target
 */
void iSCSILibWrapper::iSCSIPerformDiscovery(void)
{
    // Remove us from the background thread
    iSCSIBackGround::GetInstance().RemoveConnection(*this);

    mClient.finished = 0;

    // Clean up those pairs ... from any previous discovery
    if (mDiscoveryPairs.size())
    {
       while (mDiscoveryPairs.size())
           mDiscoveryPairs.erase(mDiscoveryPairs.begin());
    }

    if (iscsi_discovery_async(mIscsi, discovery_cb, this))
    {
	mError = true;
        mErrorString.Format("%s: Failed to send discovery for target %s: %s",
                          __func__,
                          mTarget.c_str(),
                          iscsi_get_error(mIscsi));
        throw CException(mErrorString);
    }

    ServiceISCSIEvents();

    // Add to the background task
    iSCSIBackGround::GetInstance().AddConnection(*this);

}
void
test_reserve6_target_warm_reset(void)
{
	int ret;
	struct scsi_device sd2;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test that RESERVE6 is released on target warm reset");

	if (sd->iscsi_ctx == NULL) {
		const char *err = "[SKIPPED] This RESERVE6 test is only "
			"supported for iSCSI backends";
		logging(LOG_NORMAL, "%s", err);
		CU_PASS(err);
		return;
	}

	logging(LOG_VERBOSE, "Take out a RESERVE6 from the first initiator");
	ret = reserve6(sd);
	if (ret == -2) {
		logging(LOG_VERBOSE, "[SKIPPED] Target does not support RESERVE6. Skipping test");
		CU_PASS("[SKIPPED] Target does not support RESERVE6. Skipping test");
		return;
	}
	CU_ASSERT_EQUAL(ret, 0);


	logging(LOG_VERBOSE, "Send a Warm Reset to the target");
	ret = iscsi_task_mgmt_target_warm_reset_sync(sd->iscsi_ctx);
	if (ret != 0) {
		logging(LOG_NORMAL, "Warm reset failed. %s", iscsi_get_error(sd->iscsi_ctx));
	}
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Sleep for three seconds incase the target is slow to reset");
	sleep(3);


	logging(LOG_VERBOSE, "Create a second connection to the target");
	memset(&sd2, 0, sizeof(sd2));
	sd2.iscsi_url = sd->iscsi_url;
	sd2.iscsi_lun = sd->iscsi_lun;
	sd2.iscsi_ctx = iscsi_context_login(initiatorname2, sd2.iscsi_url, &sd2.iscsi_lun);
	if (sd2.iscsi_ctx == NULL) {
		logging(LOG_VERBOSE, "Failed to login to target");
		return;
	}


	logging(LOG_VERBOSE, "RESERVE6 from the second initiator should work now");
	ret = reserve6(&sd2);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "RELEASE6 from the second initiator");
	ret = release6(&sd2);
	CU_ASSERT_EQUAL(ret, 0);

	iscsi_logout_sync(sd2.iscsi_ctx);
	iscsi_destroy_context(sd2.iscsi_ctx);
}
Пример #8
0
void event_loop(struct iscsi_context *iscsi, struct client_state *state)
{
	struct pollfd pfd;

	while (state->finished == 0) {
		pfd.fd = iscsi_get_fd(iscsi);
		pfd.events = iscsi_which_events(iscsi);
	       
		if (pfd.events == 0) {
			state->got_zero_events = 1;
			printf("iscsi_which_events() returned 0\n");
			sleep(1);
			printf("change portal back to the right portal\n");
			iscsi_full_connect_async(iscsi, state->portal,
						 state->lun, NULL, NULL);
		}
		if (poll(&pfd, 1, -1) < 0) {
			fprintf(stderr, "Poll failed");
			exit(10);
		}
		if (iscsi_service(iscsi, pfd.revents) < 0) {
			fprintf(stderr, "iscsi_service failed with : %s\n",
				iscsi_get_error(iscsi));
			exit(10);
		}
       }
}
Пример #9
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);
}
Пример #10
0
static BlockDriverAIOCB *
iscsi_aio_flush(BlockDriverState *bs,
                BlockDriverCompletionFunc *cb, void *opaque)
{
    IscsiLun *iscsilun = bs->opaque;
    struct iscsi_context *iscsi = iscsilun->iscsi;
    IscsiAIOCB *acb;

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

    acb->iscsilun = iscsilun;
    acb->canceled   = 0;

    acb->task = iscsi_synchronizecache10_task(iscsi, iscsilun->lun,
                                         0, 0, 0, 0,
                                         iscsi_synccache10_cb,
                                         acb);
    if (acb->task == NULL) {
        error_report("iSCSI: Failed to send synchronizecache10 command. %s",
                     iscsi_get_error(iscsi));
        qemu_aio_release(acb);
        return NULL;
    }

    iscsi_set_events(iscsilun);

    return &acb->common;
}
Пример #11
0
static void
event_loop(struct iscsi_context *iscsi, struct iscsi_sync_state *state)
{
	struct pollfd pfd;
	int ret;

	while (state->finished == 0) {
		pfd.fd = iscsi_get_fd(iscsi);
		pfd.events = iscsi_which_events(iscsi);

		if ((ret = poll(&pfd, 1, 1000)) < 0) {
			iscsi_set_error(iscsi, "Poll failed");
			state->status = -1;
			return;
		}
		if (ret == 0) {
			iscsi_timeout_scan(iscsi);
			continue;
		}
		if (iscsi_service(iscsi, pfd.revents) < 0) {
			iscsi_set_error(iscsi,
				"iscsi_service failed with : %s",
				iscsi_get_error(iscsi));
			state->status = -1;
			return;
		}
	}
}
Пример #12
0
static BlockDriverAIOCB *
iscsi_aio_discard(BlockDriverState *bs,
                  int64_t sector_num, int nb_sectors,
                  BlockDriverCompletionFunc *cb, void *opaque)
{
    IscsiLun *iscsilun = bs->opaque;
    struct iscsi_context *iscsi = iscsilun->iscsi;
    IscsiAIOCB *acb;
    struct unmap_list list[1];

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

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

    list[0].lba = sector_qemu2lun(sector_num, iscsilun);
    list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size;

    acb->task = iscsi_unmap_task(iscsi, iscsilun->lun,
                                 0, 0, &list[0], 1,
                                 iscsi_unmap_cb,
                                 acb);
    if (acb->task == NULL) {
        error_report("iSCSI: Failed to send unmap command. %s",
                     iscsi_get_error(iscsi));
        qemu_aio_release(acb);
        return NULL;
    }

    iscsi_set_events(iscsilun);

    return &acb->common;
}
Пример #13
0
/*
 * Discovery callback
 */
static void discovery_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)
{
    iSCSILibWrapper *obj = (iSCSILibWrapper *)private_data;
    struct wrapper_client_state *client = obj->GetClientState();
    struct iscsi_discovery_address *addr;

    if (status)
    {
        EString error;
        error.Format("%s: Failed to perform discovery: %s",
                     __func__,
                     iscsi_get_error(iscsi));
        client->error_message = strdup(error.c_str());
        client->finished = 1;
        client->error = 1;
        return;
    }

    for (addr = (struct iscsi_discovery_address *)command_data; addr; addr = addr->next)
    {
        // Add them to the object that called us
        obj->AddDiscoveryPair(addr->target_name, addr->target_address);
    }

    client->finished = 1;
}
Пример #14
0
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);
}
Пример #15
0
static void
iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
                        void *command_data, void *opaque)
{
    struct IscsiTask *iTask = opaque;
    struct scsi_task *task = command_data;

    iTask->complete = 1;
    iTask->status = status;
    iTask->do_retry = 0;
    iTask->task = task;

    if (iTask->retries-- > 0 && status == SCSI_STATUS_CHECK_CONDITION
        && task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
        iTask->do_retry = 1;
        goto out;
    }

    if (status != SCSI_STATUS_GOOD) {
        error_report("iSCSI: Failure. %s", iscsi_get_error(iscsi));
    }

out:
    if (iTask->co) {
        qemu_coroutine_enter(iTask->co, NULL);
    }
}
Пример #16
0
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;
}
Пример #17
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;
    struct iscsi_context *iscsi = iscsilun->iscsi;
    IscsiAIOCB *acb;
    size_t qemu_read_size, lun_read_size;
    int i;

    qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;

    acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
    trace_iscsi_aio_readv(iscsi, sector_num, nb_sectors, opaque, acb);

    acb->iscsilun = iscsilun;
    acb->qiov     = qiov;

    acb->canceled    = 0;
    acb->read_size   = qemu_read_size;
    acb->buf         = NULL;

    /* If LUN blocksize is bigger than BDRV_BLOCK_SIZE a read from QEMU
     * may be misaligned to the LUN, so we may need to read some extra
     * data.
     */
    acb->read_offset = 0;
    if (iscsilun->block_size > BDRV_SECTOR_SIZE) {
        uint64_t bdrv_offset = BDRV_SECTOR_SIZE * sector_num;

        acb->read_offset  = bdrv_offset % iscsilun->block_size;
    }

    lun_read_size  = (qemu_read_size + iscsilun->block_size
                     + acb->read_offset - 1)
                     / iscsilun->block_size * iscsilun->block_size;
    acb->task = iscsi_read10_task(iscsi, iscsilun->lun,
                             sector_qemu2lun(sector_num, iscsilun),
                             lun_read_size, iscsilun->block_size,
                             0, 0, 0, 0, 0,
                             iscsi_aio_read10_cb, acb);
    if (acb->task == NULL) {
        error_report("iSCSI: Failed to send read10 command. %s",
                     iscsi_get_error(iscsi));
        qemu_aio_release(acb);
        return NULL;
    }

    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);
    }

    iscsi_set_events(iscsilun);

    return &acb->common;
}
Пример #18
0
static void
iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
                        void *command_data, void *opaque)
{
    struct IscsiTask *iTask = opaque;
    struct scsi_task *task = command_data;

    iTask->status = status;
    iTask->do_retry = 0;
    iTask->task = task;

    if (status != SCSI_STATUS_GOOD) {
        if (iTask->retries++ < ISCSI_CMD_RETRIES) {
            if (status == SCSI_STATUS_CHECK_CONDITION
                && task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
                error_report("iSCSI CheckCondition: %s",
                             iscsi_get_error(iscsi));
                iTask->do_retry = 1;
                goto out;
            }
            if (status == SCSI_STATUS_BUSY) {
                unsigned retry_time =
                    exp_random(iscsi_retry_times[iTask->retries - 1]);
                error_report("iSCSI Busy (retry #%u in %u ms): %s",
                             iTask->retries, retry_time,
                             iscsi_get_error(iscsi));
                aio_timer_init(iTask->iscsilun->aio_context,
                               &iTask->retry_timer, QEMU_CLOCK_REALTIME,
                               SCALE_MS, iscsi_retry_timer_expired, iTask);
                timer_mod(&iTask->retry_timer,
                          qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + retry_time);
                iTask->do_retry = 1;
                return;
            }
        }
        error_report("iSCSI Failure: %s", iscsi_get_error(iscsi));
    }

out:
    if (iTask->co) {
        iTask->bh = aio_bh_new(iTask->iscsilun->aio_context,
                               iscsi_co_generic_bh_cb, iTask);
        qemu_bh_schedule(iTask->bh);
    } else {
        iTask->complete = 1;
    }
}
Пример #19
0
void iSCSILibWrapper::iSCSILUNReset(uint32_t lun)
{
    // Remove us from the background thread
    iSCSIBackGround::GetInstance().RemoveConnection(*this);

    if (!mClient.connected || mClient.error)
    {
        if (mClient.error)
            mErrorString.Format("%s: previous error prevents sending LUN reset to target %s: %s",
                               __func__,
                               mTarget.c_str(),
                               iscsi_get_error(mIscsi));
        else
            mErrorString.Format("%s: Sending LUN reset to target %s not possible without a connection!",
                               __func__,
                               mTarget.c_str());
        mError = true;
        throw CException(mErrorString);
    }

    mClient.finished = 0;

    if (iscsi_task_mgmt_async(mIscsi, 
                              lun, 
                              ISCSI_TM_LUN_RESET,
                              0xffffffff,
                              0,
                              lun_reset_cb,
                              this))
    {
        EString estr;
        estr.Format("%s: Error executing SCSI request: %s", __func__,
                    iscsi_get_error(mIscsi));
        mError = true;
        throw CException(mErrorString);
    }

    ServiceISCSIEvents();

    // Add to the background task
    iSCSIBackGround::GetInstance().AddConnection(*this);

}
Пример #20
0
void
test_read6_simple(void)
{
	int i, ret;


	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test READ6 of 1-255 blocks at the start of the LUN");
	for (i = 1; i <= 255; i++) {
		ret = read6(iscsic, tgt_lun, 0, i * block_size,
			    block_size, NULL);
		if (ret == -2) {
			logging(LOG_NORMAL, "[SKIPPED] READ6 is not implemented.");
			CU_PASS("READ6 is not implemented.");
			return;
		}	
		CU_ASSERT_EQUAL(ret, 0);
	}


	logging(LOG_VERBOSE, "Test READ6 of 1-255 blocks at the end of the LUN");
	if (num_blocks > 0x200000) {
		CU_PASS("LUN is too big for read-at-eol tests with READ6. Skipping test.\n");
	} else {
		for (i = 1; i <= 255; i++) {
			ret = read6(iscsic, tgt_lun, num_blocks - i,
				i * block_size, block_size, NULL);
			CU_ASSERT_EQUAL(ret, 0);
		}
	}

	logging(LOG_VERBOSE, "Transfer length == 0 means we want to transfer "
		"256 blocks");

	logging(LOG_VERBOSE, "Test sending a READ6 with transfer length == 0 "
		"(meaning 256 blocks)");
	/* 256 is converted to 0 when the CDB is marshalled by the helper */
	task = iscsi_read6_sync(iscsic, tgt_lun, 0,
				256 * block_size, block_size);
	if (task->status != SCSI_STATUS_GOOD) {
		logging(LOG_NORMAL, "[FAILED] READ6 command: "
			"failed with sense. %s", iscsi_get_error(iscsic));
	}
	CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);

	logging(LOG_VERBOSE, "Verify that we did get 256 blocks of data back");
	if (task->datain.size == (int)(256 * block_size)) {
		logging(LOG_VERBOSE, "[SUCCESS] Target returned 256 blocks of "
			"data");
	} else {
		logging(LOG_NORMAL, "[FAILED] Target did not return 256 "
			"blocks of data");
	}
	CU_ASSERT_EQUAL(task->datain.size, (int)(256 * block_size));
}
Пример #21
0
/*
 * Perform a normal session logout
 */
void iSCSILibWrapper::iSCSINormalLogout(void)
{
    // Remove us from the background thread
    iSCSIBackGround::GetInstance().RemoveConnection(*this);

    if (!mClient.connected || mClient.error)
    {
        if (mClient.error)
            mErrorString.Format("%s: previous error prevents logout from target %s: %s",
                               __func__,
                               mTarget.c_str(),
                               iscsi_get_error(mIscsi));
        else
            mErrorString.Format("%s: Logout from target %s not possible without a connection!",
                               __func__,
                               mTarget.c_str());
        mError = true;
        throw CException(mErrorString);
    }

    mClient.finished = 0;

    if (iscsi_logout_async(mIscsi, discoverylogout_cb, this))
    {
        mErrorString.Format("%s: Logout from target %s failed: %s",
                           __func__,
                           mTarget.c_str(),
                           iscsi_get_error(mIscsi));
        mError = true;
        throw CException(mErrorString);
    }

    ServiceISCSIEvents();

    // Add to the background task
    iSCSIBackGround::GetInstance().AddConnection(*this);

}
Пример #22
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;
}
Пример #23
0
static BlockDriverAIOCB *
iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
                 QEMUIOVector *qiov, int nb_sectors,
                 BlockDriverCompletionFunc *cb,
                 void *opaque)
{
    IscsiLun *iscsilun = bs->opaque;
    struct iscsi_context *iscsi = iscsilun->iscsi;
    IscsiAIOCB *acb;
    size_t size;
    int fua = 0;

    /* set FUA on writes when cache mode is write through */
    if (!(bs->open_flags & BDRV_O_CACHE_WB)) {
        fua = 1;
    }

    acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
    trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);

    acb->iscsilun = iscsilun;
    acb->qiov     = qiov;

    acb->canceled   = 0;

    /* XXX we should pass the iovec to write10 to avoid the extra copy */
    /* this will allow us to get rid of 'buf' completely */
    size = nb_sectors * BDRV_SECTOR_SIZE;
    acb->buf = g_malloc(size);
    qemu_iovec_to_buffer(acb->qiov, acb->buf);
    acb->task = iscsi_write10_task(iscsi, iscsilun->lun,
                              sector_qemu2lun(sector_num, iscsilun),
                              acb->buf, size, iscsilun->block_size,
                              0, 0, fua, 0, 0,
                              iscsi_aio_write10_cb, acb);
    if (acb->task == NULL) {
        error_report("iSCSI: Failed to send write10 command. %s",
                     iscsi_get_error(iscsi));
        g_free(acb->buf);
        qemu_aio_release(acb);
        return NULL;
    }

    iscsi_set_events(iscsilun);

    return &acb->common;
}
void
test_reserve6_target_cold_reset(void)
{
	int ret;


	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test that RESERVE6 is released on target cold reset");


	logging(LOG_VERBOSE, "Take out a RESERVE6 from the first initiator");
	ret = reserve6(iscsic, tgt_lun);
	if (ret == -2) {
		logging(LOG_VERBOSE, "[SKIPPED] Target does not support RESERVE6. Skipping test");
		CU_PASS("[SKIPPED] Target does not support RESERVE6. Skipping test");
		return;
	}
	CU_ASSERT_EQUAL(ret, 0);


	logging(LOG_VERBOSE, "Send a Cold Reset to the target");
	ret = iscsi_task_mgmt_target_cold_reset_sync(iscsic);
	if (ret != 0) {
		logging(LOG_NORMAL, "Cold reset failed. %s", iscsi_get_error(iscsic));
	}
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Sleep for three seconds incase the target is slow to reset");
	sleep(3);

	logging(LOG_VERBOSE, "Create a second connection to the target");
	iscsic2 = iscsi_context_login(initiatorname1, tgt_url, &tgt_lun);
	if (iscsic2 == NULL) {
		logging(LOG_VERBOSE, "Failed to login to target");
		return;
	}

	logging(LOG_VERBOSE, "RESERVE6 from the second initiator should work now");
	ret = reserve6(iscsic2, tgt_lun);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "RELEASE6 from the second initiator");
	ret = release6(iscsic2, tgt_lun);
	CU_ASSERT_EQUAL(ret, 0);
}
void
test_reserve6_target_warm_reset(void)
{
        int ret;
        struct scsi_device *sd2;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test that RESERVE6 is released on target warm reset");

        if (sd->iscsi_ctx == NULL) {
                const char *err = "[SKIPPED] This RESERVE6 test is only "
                        "supported for iSCSI backends";
                logging(LOG_NORMAL, "%s", err);
                CU_PASS(err);
                return;
        }

        logging(LOG_VERBOSE, "Take out a RESERVE6 from the first initiator");
        RESERVE6(sd);

        logging(LOG_VERBOSE, "Send a Warm Reset to the target");
        ret = iscsi_task_mgmt_target_warm_reset_sync(sd->iscsi_ctx);
        if (ret != 0) {
                logging(LOG_NORMAL, "Warm reset failed. %s", iscsi_get_error(sd->iscsi_ctx));
        }
        CU_ASSERT_EQUAL(ret, 0);

        logging(LOG_VERBOSE, "Sleep for three seconds incase the target is slow to reset");
        sleep(3);


        logging(LOG_VERBOSE, "Create a second connection to the target");
        ret = mpath_sd2_get_or_clone(sd, &sd2);
        CU_ASSERT_EQUAL(ret, 0);
        if (ret < 0)
                return;

        logging(LOG_VERBOSE, "RESERVE6 from the second initiator should work now");
        RESERVE6(sd2);

        logging(LOG_VERBOSE, "RELEASE6 from the second initiator");
        RELEASE6(sd2);

        mpath_sd2_put(sd2);
}
Пример #26
0
void event_loop(struct iscsi_context *iscsi, struct client_state *state)
{
       struct pollfd pfd;

       while (state->finished == 0) {
               pfd.fd = iscsi_get_fd(iscsi);
               pfd.events = iscsi_which_events(iscsi);

               if (poll(&pfd, 1, -1) < 0) {
                       fprintf(stderr, "Poll failed");
                       exit(10);
               }
               if (iscsi_service(iscsi, pfd.revents) < 0) {
                       fprintf(stderr, "iscsi_service failed with : %s\n", iscsi_get_error(iscsi));
                       exit(10);
               }
       }
}
Пример #27
0
/*
 * Discovery logout callback 
 */
static void discoverylogout_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)
{
    struct wrapper_client_state *client = 
		((iSCSILibWrapper *)private_data)->GetClientState();

    if (status)
    {
	EString error;
        error.Format("%s: Failed to logout: %s",
                     __func__,
                     iscsi_get_error(iscsi));
        client->error_message = strdup(error.c_str());
        client->finished = 1;
        client->error = 1;
        return;
    }

    client->finished = 1;
}
Пример #28
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) {
        error_report("Failed to unmap data on iSCSI lun. %s",
                     iscsi_get_error(iscsi));
        acb->status = -EIO;
    }

    iscsi_schedule_bh(acb);
}
Пример #29
0
static void
event_loop(struct iscsi_context *iscsi, struct scsi_sync_state *state)
{
	struct pollfd pfd;

	while (state->finished == 0) {
		pfd.fd = iscsi_get_fd(iscsi);
		pfd.events = iscsi_which_events(iscsi);

		if (poll(&pfd, 1, -1) < 0) {
			iscsi_set_error(iscsi, "Poll failed");
			return;
		}
		if (iscsi_service(iscsi, pfd.revents) < 0) {
			iscsi_set_error(iscsi,
					"iscsi_service failed with : %s",
					iscsi_get_error(iscsi));
			return;
		}
	}
}
Пример #30
0
static void
iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
                    void *command_data, void *opaque)
{
    IscsiAIOCB *acb = opaque;

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

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

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

    iscsi_schedule_bh(acb);
}