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