void RegThread::run() { DBG("registrar client started.\n"); sleep(2); // wait for sems to completely start up while (true) { for (vector<RegInfo>::iterator it = registrations.begin(); it != registrations.end(); it++) { if (!check_registration(*it)) { DBG("Registration %d does not exist or timeout. Creating registration.\n", (int)(it - registrations.begin())); create_registration(*it); } } sleep(10); // 10 seconds } }
void pr_reserve_out(pr_context_t *context, lun_t lun, const unsigned char *cdb, int session_id, scsi_command_status_t *scsi_status) { pr_info_t *pr_info = &context->pr_info[lun]; EXA_ASSERT(session_id < MAX_GLOBAL_SESSION); if (cdb[0] == RESERVE_6) { if (persistent_spc2_reserve_lun(context, session_id, lun, scsi_status)) SCSI_STATUS_OK(scsi_status, 0); else SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_RESERVATION_CONFLICT, 0, 0); return; } if (cdb[0] == RELEASE_6) { if (persistent_spc2_release_lun(context, session_id, lun, scsi_status)) SCSI_STATUS_OK(scsi_status, 0); else SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_RESERVATION_CONFLICT, 0, 0); return; } if (cdb[0] == PERSISTENT_RESERVE_OUT) { /* int len = get_bigendian32(cdb + 5); // FIXME: TODO: must be checked for all service action */ int pr_scope = cdb[2] >> 4; int pr_type = cdb[2] & 0xf; const unsigned char *param = cdb + SCSI_CDB_MAX_FIXED_LENGTH; pr_key_t reservation_key = get_bigendian64(param); pr_key_t service_action_key = get_bigendian64(param + 8); unsigned char flags = param[20]; unsigned char spec_i_pt = (flags >> 3) & 1; /* unsigned char all_tg_pt = (flags >>2) & 1 ; */ int service_action = cdb[1] & 0x1f; /* spc3r23 table 116 "allowed scope" */ if (pr_scope != PR_LU_SCOPE && service_action != PR_OUT_REGISTER && service_action != PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY && service_action != PR_OUT_CLEAR) { exalog_error("iSCSI PR failed: " "reserve operation (%i) from session %i on LUN %" PRIlun " is not allowed in this scope", service_action, session_id, lun); SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_ASC_INVALID_FIELD_IN_CDB); return; } if (check_registration(context, session_id, lun, reservation_key, service_action) != SCSI_STATUS_GOOD) { SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_RESERVATION_CONFLICT, 0, 0); return; } switch (service_action) { case PR_OUT_REGISTER: if (spec_i_pt == 0) { persistent_register_lun(context, session_id, lun, service_action_key, scsi_status); break; } /* spec_i_pt == 1 ! */ if (reservation_key != 0) /* spec_i_pt == 1 and we are on a registered nexus */ { exalog_warning("iSCSI PR conflict: " "reserve operation (%i) from session %i on LUN %" PRIlun " is not allowed, already registered nexus %" PRIu64, service_action, session_id, lun, reservation_key); SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_ASC_INVALID_FIELD_IN_CDB); break; ; } persistent_register_lun(context, session_id, lun, service_action_key, scsi_status); break; case PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY: if (service_action_key == 0 && !pr_info_is_registered(pr_info, session_id)) { /* FIXME: is this a "nothing to do" case ? */ exalog_debug("iSCSI PR: register and ignore existing keys" " from session %i on LUN %" PRIlun " (ntd)", session_id, lun); SCSI_STATUS_OK(scsi_status, 0); break; } if (spec_i_pt == 1) { exalog_warning("iSCSI PR failed: " "reserve operation (%i) from session %i on LUN %" PRIlun " is not allowed", service_action, session_id, lun); SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_ASC_INVALID_FIELD_IN_CDB); break; } persistent_register_lun(context, session_id, lun, service_action_key, scsi_status); break; case PR_OUT_RESERVE: if (persistent_reserve_lun(context, session_id, lun, reservation_key, pr_type)) SCSI_STATUS_OK(scsi_status, 0); else SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_RESERVATION_CONFLICT, 0, 0); break; case PR_OUT_RELEASE: persistent_release_lun(context, session_id, lun, reservation_key, pr_type, scsi_status); break; case PR_OUT_CLEAR: persistent_clear_lun(context, session_id, lun, scsi_status); break; case PR_OUT_PREEMPT: persistent_preempt_lun(context, session_id, lun, reservation_key, service_action_key, pr_type, scsi_status); break; case PR_OUT_PREEMPT_AND_ABORT: persistent_preempt_lun(context, session_id, lun, reservation_key, service_action_key, pr_type, scsi_status); break; /* FIXME : we must add abort task set and it's not done spc3 - 5.6.10.5 */ case PR_OUT_REGISTER_AND_MOVE: /* FIXME : not implemented ,not needed for windows */ exalog_error("iSCSI PR failed: " "reserve operation 'register_and_move' not supported" " (from session %i on LUN %" PRIlun ")", session_id, lun); SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, 0); break; default: exalog_error("iSCSI PR failed: " "reserve operation (%i) not expected" " (from session %i on LUN %" PRIlun ")", service_action, session_id, lun); SCSI_STATUS_ERROR(scsi_status, SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, 0); break; } /* PR generation sp3r23 6.11.2 */ if (scsi_status->status == SCSI_STATUS_GOOD && service_action != PR_OUT_RESERVE && service_action != PR_OUT_RELEASE) { pr_info->pr_generation++; } }