Changeset 63829 in vbox
- Timestamp:
- Sep 14, 2016 10:49:28 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/ISCSI.cpp
r63827 r63829 3909 3909 3910 3910 /** 3911 * Internal: Open an image, constructing all necessary data structures. 3911 * Inits the basic iSCSI image state, allocating vital resources. 3912 * 3913 * @returns VBox status code. 3914 * @param pImage The iSCSI image instance. 3912 3915 */ 3913 static int iscsiOpenImage(PISCSIIMAGE pImage, unsigned uOpenFlags) 3914 { 3915 int rc; 3916 static int iscsiOpenImageInit(PISCSIIMAGE pImage) 3917 { 3918 int rc = VINF_SUCCESS; 3919 3920 /* Get error signalling interface. */ 3921 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk); 3922 3923 /* Get TCP network stack interface. */ 3924 pImage->pIfNet = VDIfTcpNetGet(pImage->pVDIfsImage); 3925 if (pImage->pIfNet) 3926 { 3927 /* Get configuration interface. */ 3928 pImage->pIfConfig = VDIfConfigGet(pImage->pVDIfsImage); 3929 if (pImage->pIfConfig) 3930 { 3931 /* Get I/O interface. */ 3932 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage); 3933 if (pImage->pIfIo) 3934 { 3935 /* This ISID will be adjusted later to make it unique on this host. */ 3936 pImage->pszHostname = NULL; 3937 pImage->uPort = 0; 3938 pImage->Socket = NIL_VDSOCKET; 3939 pImage->ISID = 0x800000000000ULL | 0x001234560000ULL; 3940 pImage->cISCSIRetries = 10; 3941 pImage->state = ISCSISTATE_FREE; 3942 pImage->cLoginsSinceIo = 0; 3943 pImage->Mutex = NIL_RTSEMMUTEX; 3944 pImage->MutexReqQueue = NIL_RTSEMMUTEX; 3945 pImage->pszInitiatorUsername = NULL; 3946 pImage->pbInitiatorSecret = NULL; 3947 pImage->cbInitiatorSecret = 0; 3948 pImage->pszTargetUsername = NULL; 3949 pImage->pbTargetSecret = NULL; 3950 pImage->cbTargetSecret = 0; 3951 3952 memset(pImage->aCmdsWaiting, 0, sizeof(pImage->aCmdsWaiting)); 3953 pImage->cbRecvPDUResidual = 0; 3954 3955 pImage->pvRecvPDUBuf = RTMemAlloc(ISCSI_RECV_PDU_BUFFER_SIZE); 3956 pImage->cbRecvPDUBuf = ISCSI_RECV_PDU_BUFFER_SIZE; 3957 if (!pImage->pvRecvPDUBuf) 3958 rc = VERR_NO_MEMORY; 3959 3960 if (RT_SUCCESS(rc)) 3961 rc = RTSemMutexCreate(&pImage->Mutex); 3962 if (RT_SUCCESS(rc)) 3963 rc = RTSemMutexCreate(&pImage->MutexReqQueue); 3964 } 3965 else 3966 rc = vdIfError(pImage->pIfError, VERR_VD_UNKNOWN_INTERFACE, 3967 RT_SRC_POS, N_("iSCSI: I/O interface missing")); 3968 } 3969 else 3970 rc = vdIfError(pImage->pIfError, VERR_VD_UNKNOWN_INTERFACE, 3971 RT_SRC_POS, N_("iSCSI: configuration interface missing")); 3972 } 3973 else 3974 rc = vdIfError(pImage->pIfError, VERR_VD_UNKNOWN_INTERFACE, 3975 RT_SRC_POS, N_("iSCSI: TCP network stack interface missing")); 3976 3977 return rc; 3978 } 3979 3980 /** 3981 * Parses the user supplied config before opening the connection to the target. 3982 * 3983 * @returns VBox status code. 3984 * @param pImage The iSCSI image instance. 3985 */ 3986 static int iscsiOpenImageParseCfg(PISCSIIMAGE pImage) 3987 { 3916 3988 char *pszLUN = NULL, *pszLUNInitial = NULL; 3917 3989 bool fLunEncoded = false; … … 3921 3993 bool fHostIPDef = false; 3922 3994 bool fDumpMalformedPacketsDef = false; 3923 rc = RTStrToUInt32Full(s_iscsiConfigDefaultWriteSplit, 0, &uWriteSplitDef); 3995 3996 int rc = RTStrToUInt32Full(s_iscsiConfigDefaultWriteSplit, 0, &uWriteSplitDef); 3924 3997 AssertRC(rc); 3925 3998 rc = RTStrToUInt32Full(s_iscsiConfigDefaultTimeout, 0, &uTimeoutDef); … … 3928 4001 AssertRC(rc); 3929 4002 fHostIPDef = RT_BOOL(uCfgTmp); 3930 3931 4003 rc = RTStrToUInt64Full(s_iscsiConfigDefaultDumpMalformedPackets, 0, &uCfgTmp); 3932 4004 AssertRC(rc); 3933 4005 fDumpMalformedPacketsDef = RT_BOOL(uCfgTmp); 3934 3935 pImage->uOpenFlags = uOpenFlags;3936 3937 /* Get error signalling interface. */3938 pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk);3939 3940 /* Get TCP network stack interface. */3941 pImage->pIfNet = VDIfTcpNetGet(pImage->pVDIfsImage);3942 if (!pImage->pIfNet)3943 {3944 rc = vdIfError(pImage->pIfError, VERR_VD_UNKNOWN_INTERFACE,3945 RT_SRC_POS, N_("iSCSI: TCP network stack interface missing"));3946 goto out;3947 }3948 3949 /* Get configuration interface. */3950 pImage->pIfConfig = VDIfConfigGet(pImage->pVDIfsImage);3951 if (!pImage->pIfConfig)3952 {3953 rc = vdIfError(pImage->pIfError, VERR_VD_UNKNOWN_INTERFACE,3954 RT_SRC_POS, N_("iSCSI: configuration interface missing"));3955 goto out;3956 }3957 3958 /* Get I/O interface. */3959 pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage);3960 if (!pImage->pIfIo)3961 {3962 rc = vdIfError(pImage->pIfError, VERR_VD_UNKNOWN_INTERFACE,3963 RT_SRC_POS, N_("iSCSI: I/O interface missing"));3964 goto out;3965 }3966 3967 /* This ISID will be adjusted later to make it unique on this host. */3968 pImage->ISID = 0x800000000000ULL | 0x001234560000ULL;3969 pImage->cISCSIRetries = 10;3970 pImage->state = ISCSISTATE_FREE;3971 pImage->cLoginsSinceIo = 0;3972 pImage->pvRecvPDUBuf = RTMemAlloc(ISCSI_RECV_PDU_BUFFER_SIZE);3973 pImage->cbRecvPDUBuf = ISCSI_RECV_PDU_BUFFER_SIZE;3974 if (pImage->pvRecvPDUBuf == NULL)3975 {3976 rc = VERR_NO_MEMORY;3977 goto out;3978 }3979 pImage->Mutex = NIL_RTSEMMUTEX;3980 pImage->MutexReqQueue = NIL_RTSEMMUTEX;3981 rc = RTSemMutexCreate(&pImage->Mutex);3982 if (RT_FAILURE(rc))3983 goto out;3984 3985 rc = RTSemMutexCreate(&pImage->MutexReqQueue);3986 if (RT_FAILURE(rc))3987 goto out;3988 4006 3989 4007 /* Validate configuration, detect unknown keys. */ … … 4002 4020 "HostIPStack\0" 4003 4021 "DumpMalformedPackets\0")) 4004 { 4005 rc = vdIfError(pImage->pIfError, VERR_VD_UNKNOWN_CFG_VALUES, RT_SRC_POS, N_("iSCSI: configuration error: unknown configuration keys present")); 4006 goto out; 4007 } 4022 return vdIfError(pImage->pIfError, VERR_VD_UNKNOWN_CFG_VALUES, RT_SRC_POS, N_("iSCSI: configuration error: unknown configuration keys present")); 4008 4023 4009 4024 /* Query the iSCSI upper level configuration. */ 4010 rc = VDCFGQueryStringAlloc(pImage->pIfConfig, 4011 "TargetName", &pImage->pszTargetName); 4025 rc = VDCFGQueryStringAlloc(pImage->pIfConfig, "TargetName", &pImage->pszTargetName); 4012 4026 if (RT_FAILURE(rc)) 4013 { 4014 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read TargetName as string")); 4015 goto out; 4016 } 4017 rc = VDCFGQueryStringAlloc(pImage->pIfConfig, 4018 "InitiatorName", &pImage->pszInitiatorName); 4027 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read TargetName as string")); 4028 4029 rc = VDCFGQueryStringAlloc(pImage->pIfConfig, "InitiatorName", &pImage->pszInitiatorName); 4019 4030 if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT) 4020 {4021 4031 pImage->fAutomaticInitiatorName = true; 4022 rc = VINF_SUCCESS; 4023 } 4032 else if (RT_FAILURE(rc)) 4033 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read InitiatorName as string")); 4034 4035 rc = VDCFGQueryStringAllocDef(pImage->pIfConfig, "LUN", &pszLUN, s_iscsiConfigDefaultLUN); 4024 4036 if (RT_FAILURE(rc)) 4025 { 4026 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read InitiatorName as string")); 4027 goto out; 4028 } 4029 rc = VDCFGQueryStringAllocDef(pImage->pIfConfig, 4030 "LUN", &pszLUN, s_iscsiConfigDefaultLUN); 4031 if (RT_FAILURE(rc)) 4032 { 4033 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read LUN as string")); 4034 goto out; 4035 } 4037 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read LUN as string")); 4038 4036 4039 pszLUNInitial = pszLUN; 4037 4040 if (!strncmp(pszLUN, "enc", 3)) … … 4042 4045 rc = RTStrToUInt64Full(pszLUN, 0, &pImage->LUN); 4043 4046 if (RT_FAILURE(rc)) 4044 {4045 4047 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to convert LUN to integer")); 4046 goto out; 4047 }4048 if ( !fLunEncoded)4048 4049 RTMemFree(pszLUNInitial); 4050 if (RT_SUCCESS(rc) && !fLunEncoded) 4049 4051 { 4050 4052 if (pImage->LUN <= 255) 4051 {4052 4053 pImage->LUN = pImage->LUN << 48; /* uses peripheral device addressing method */ 4053 }4054 4054 else if (pImage->LUN <= 16383) 4055 {4056 4055 pImage->LUN = (pImage->LUN << 48) | RT_BIT_64(62); /* uses flat space addressing method */ 4057 }4058 4056 else 4059 { 4060 rc = VERR_OUT_OF_RANGE; 4061 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: LUN number out of range (0-16383)")); 4062 goto out; 4063 } 4064 } 4065 rc = VDCFGQueryStringAlloc(pImage->pIfConfig, 4066 "TargetAddress", &pImage->pszTargetAddress); 4057 rc = vdIfError(pImage->pIfError, VERR_OUT_OF_RANGE, RT_SRC_POS, N_("iSCSI: configuration error: LUN number out of range (0-16383)")); 4058 } 4059 4067 4060 if (RT_FAILURE(rc)) 4068 { 4069 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read TargetAddress as string")); 4070 goto out; 4071 } 4072 pImage->pszInitiatorUsername = NULL; 4073 rc = VDCFGQueryStringAlloc(pImage->pIfConfig, 4074 "InitiatorUsername", 4075 &pImage->pszInitiatorUsername); 4076 if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT) 4077 rc = VINF_SUCCESS; 4061 return rc; 4062 4063 rc = VDCFGQueryStringAlloc(pImage->pIfConfig, "TargetAddress", &pImage->pszTargetAddress); 4078 4064 if (RT_FAILURE(rc)) 4079 { 4080 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read InitiatorUsername as string")); 4081 goto out; 4082 } 4083 pImage->pbInitiatorSecret = NULL; 4084 pImage->cbInitiatorSecret = 0; 4085 rc = VDCFGQueryBytesAlloc(pImage->pIfConfig, 4086 "InitiatorSecret", 4087 (void **)&pImage->pbInitiatorSecret, 4088 &pImage->cbInitiatorSecret); 4089 if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT) 4090 rc = VINF_SUCCESS; 4091 if (RT_FAILURE(rc)) 4092 { 4093 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read InitiatorSecret as byte string")); 4094 goto out; 4095 } 4065 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read TargetAddress as string")); 4066 4067 rc = VDCFGQueryStringAlloc(pImage->pIfConfig, "InitiatorUsername", &pImage->pszInitiatorUsername); 4068 if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND && rc != VERR_CFGM_NO_PARENT) 4069 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read InitiatorUsername as string")); 4070 4071 rc = VDCFGQueryBytesAlloc(pImage->pIfConfig, "InitiatorSecret", 4072 (void **)&pImage->pbInitiatorSecret, &pImage->cbInitiatorSecret); 4073 if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND && rc != VERR_CFGM_NO_PARENT) 4074 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read InitiatorSecret as byte string")); 4075 4096 4076 void *pvInitiatorSecretEncrypted; 4097 4077 size_t cbInitiatorSecretEncrypted; 4098 rc = VDCFGQueryBytesAlloc(pImage->pIfConfig, 4099 "InitiatorSecretEncrypted", 4100 &pvInitiatorSecretEncrypted, 4101 &cbInitiatorSecretEncrypted); 4078 rc = VDCFGQueryBytesAlloc(pImage->pIfConfig, "InitiatorSecretEncrypted", 4079 &pvInitiatorSecretEncrypted, &cbInitiatorSecretEncrypted); 4102 4080 if (RT_SUCCESS(rc)) 4103 4081 { … … 4106 4084 { 4107 4085 /* we have an encrypted initiator secret but not an unencrypted one */ 4108 rc = vdIfError(pImage->pIfError, VERR_VD_ISCSI_SECRET_ENCRYPTED, RT_SRC_POS, N_("iSCSI: initiator secret not decrypted")); 4109 goto out; 4110 } 4111 } 4112 pImage->pszTargetUsername = NULL; 4113 rc = VDCFGQueryStringAlloc(pImage->pIfConfig, 4114 "TargetUsername", 4115 &pImage->pszTargetUsername); 4116 if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT) 4117 rc = VINF_SUCCESS; 4086 return vdIfError(pImage->pIfError, VERR_VD_ISCSI_SECRET_ENCRYPTED, RT_SRC_POS, N_("iSCSI: initiator secret not decrypted")); 4087 } 4088 } 4089 4090 rc = VDCFGQueryStringAlloc(pImage->pIfConfig, "TargetUsername", &pImage->pszTargetUsername); 4091 if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND && rc != VERR_CFGM_NO_PARENT) 4092 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read TargetUsername as string")); 4093 4094 rc = VDCFGQueryBytesAlloc(pImage->pIfConfig, "TargetSecret", 4095 (void **)&pImage->pbTargetSecret, &pImage->cbTargetSecret); 4096 if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND && rc != VERR_CFGM_NO_PARENT) 4097 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read TargetSecret as byte string")); 4098 4099 rc = VDCFGQueryU32Def(pImage->pIfConfig, "WriteSplit", &pImage->cbWriteSplit, uWriteSplitDef); 4118 4100 if (RT_FAILURE(rc)) 4119 { 4120 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read TargetUsername as string")); 4121 goto out; 4122 } 4123 pImage->pbTargetSecret = NULL; 4124 pImage->cbTargetSecret = 0; 4125 rc = VDCFGQueryBytesAlloc(pImage->pIfConfig, 4126 "TargetSecret", (void **)&pImage->pbTargetSecret, 4127 &pImage->cbTargetSecret); 4128 if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT) 4129 rc = VINF_SUCCESS; 4101 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read WriteSplit as U32")); 4102 4103 /* Query the iSCSI lower level configuration. */ 4104 rc = VDCFGQueryU32Def(pImage->pIfConfig, "Timeout", &pImage->uReadTimeout, uTimeoutDef); 4130 4105 if (RT_FAILURE(rc)) 4131 { 4132 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read TargetSecret as byte string")); 4133 goto out; 4134 } 4135 rc = VDCFGQueryU32Def(pImage->pIfConfig, 4136 "WriteSplit", &pImage->cbWriteSplit, 4137 uWriteSplitDef); 4106 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read Timeout as U32")); 4107 4108 rc = VDCFGQueryBoolDef(pImage->pIfConfig, "HostIPStack", &pImage->fHostIP, fHostIPDef); 4138 4109 if (RT_FAILURE(rc)) 4139 { 4140 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read WriteSplit as U32")); 4141 goto out; 4142 } 4143 4144 pImage->pszHostname = NULL; 4145 pImage->uPort = 0; 4146 pImage->Socket = NIL_VDSOCKET; 4147 /* Query the iSCSI lower level configuration. */ 4148 rc = VDCFGQueryU32Def(pImage->pIfConfig, 4149 "Timeout", &pImage->uReadTimeout, 4150 uTimeoutDef); 4110 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read HostIPStack as boolean")); 4111 4112 rc = VDCFGQueryBoolDef(pImage->pIfConfig, "DumpMalformedPackets", 4113 &pImage->fDumpMalformedPackets, fDumpMalformedPacketsDef); 4151 4114 if (RT_FAILURE(rc)) 4152 { 4153 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read Timeout as U32")); 4154 goto out; 4155 } 4156 rc = VDCFGQueryBoolDef(pImage->pIfConfig, 4157 "HostIPStack", &pImage->fHostIP, 4158 fHostIPDef); 4159 if (RT_FAILURE(rc)) 4160 { 4161 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read HostIPStack as boolean")); 4162 goto out; 4163 } 4164 4165 rc = VDCFGQueryBoolDef(pImage->pIfConfig, 4166 "DumpMalformedPackets", &pImage->fDumpMalformedPackets, 4167 fDumpMalformedPacketsDef); 4168 if (RT_FAILURE(rc)) 4169 { 4170 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read DumpMalformedPackets as boolean")); 4171 goto out; 4172 } 4173 4174 /* Don't actually establish iSCSI transport connection if this is just an 4175 * open to query the image information and the host IP stack isn't used. 4176 * Even trying is rather useless, as in this context the InTnet IP stack 4177 * isn't present. Returning dummies is the best possible result anyway. */ 4178 if ((uOpenFlags & VD_OPEN_FLAGS_INFO) && !pImage->fHostIP) 4179 { 4180 LogFunc(("Not opening the transport connection as IntNet IP stack is not available. Will return dummies\n")); 4181 goto out; 4182 } 4183 4184 memset(pImage->aCmdsWaiting, 0, sizeof(pImage->aCmdsWaiting)); 4185 pImage->cbRecvPDUResidual = 0; 4186 4115 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("iSCSI: configuration error: failed to read DumpMalformedPackets as boolean")); 4116 4117 return VINF_SUCCESS; 4118 } 4119 4120 /** 4121 * Creates the necessary socket structure. 4122 * 4123 * @returns VBox status code. 4124 * @param pImage The iSCSI image instance. 4125 */ 4126 static int iscsiOpenImageSocketCreate(PISCSIIMAGE pImage) 4127 { 4187 4128 /* Create the socket structure. */ 4188 rc = pImage->pIfNet->pfnSocketCreate(VD_INTERFACETCPNET_CONNECT_EXTENDED_SELECT,4189 &pImage->Socket);4129 int rc = pImage->pIfNet->pfnSocketCreate(VD_INTERFACETCPNET_CONNECT_EXTENDED_SELECT, 4130 &pImage->Socket); 4190 4131 if (RT_SUCCESS(rc)) 4191 4132 { … … 4195 4136 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "iSCSI-Io"); 4196 4137 if (RT_FAILURE(rc)) 4197 {4198 4138 LogFunc(("Creating iSCSI I/O thread failed rc=%Rrc\n", rc)); 4199 goto out;4200 }4201 4139 } 4202 4140 else if (rc == VERR_NOT_SUPPORTED) 4203 4141 { 4204 4142 /* Async I/O is not supported without extended select. */ 4205 if ((uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)) 4206 { 4143 if ((pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)) 4207 4144 LogFunc(("Extended select is not supported by the interface but async I/O is requested -> %Rrc\n", rc)); 4208 goto out;4209 }4210 4145 else 4211 4146 { 4212 4147 pImage->fExtendedSelectSupported = false; 4213 4148 rc = pImage->pIfNet->pfnSocketCreate(0, &pImage->Socket); 4214 if (RT_FAILURE(rc)) 4215 { 4216 LogFunc(("Creating socket failed -> %Rrc\n", rc)); 4217 goto out; 4218 } 4219 } 4220 } 4221 else 4222 { 4149 } 4150 } 4151 4152 if (RT_FAILURE(rc)) 4223 4153 LogFunc(("Creating socket failed -> %Rrc\n", rc)); 4224 goto out; 4225 } 4226 4227 /* 4228 * Attach to the iSCSI target. This implicitly establishes the iSCSI 4229 * transport connection. 4230 */ 4231 rc = iscsiExecSync(pImage, iscsiAttach, pImage); 4232 if (RT_FAILURE(rc)) 4233 { 4234 LogRel(("iSCSI: could not open target %s, rc=%Rrc\n", pImage->pszTargetName, rc)); 4235 goto out; 4236 } 4237 LogFlowFunc(("target '%s' opened successfully\n", pImage->pszTargetName)); 4238 4154 4155 return rc; 4156 } 4157 4158 /** 4159 * Issues a REPORT LUNS to the target. 4160 * 4161 * @returns VBox status code. 4162 * @param pImage The iSCSI image instance. 4163 */ 4164 static int iscsiOpenImageReportLuns(PISCSIIMAGE pImage) 4165 { 4239 4166 SCSIREQ sr; 4240 4167 RTSGSEG DataSeg; 4241 uint8_t data8[8]; 4242 uint8_t data12[12]; 4168 uint8_t rlundata[16]; 4243 4169 4244 4170 /* 4245 4171 * Inquire available LUNs - purely dummy request. 4246 4172 */ 4247 uint8_t rlundata[16];4248 4173 RT_ZERO(sr.abCDB); 4249 4174 sr.abCDB[0] = SCSI_REPORT_LUNS; … … 4272 4197 sr.cT2ISegs = 1; 4273 4198 sr.cbSense = sizeof(sr.abSense); 4274 rc = iscsiCommandSync(pImage, &sr, false, VERR_INVALID_STATE);4199 int rc = iscsiCommandSync(pImage, &sr, false, VERR_INVALID_STATE); 4275 4200 if (RT_FAILURE(rc)) 4276 {4277 4201 LogRel(("iSCSI: Could not get LUN info for target %s, rc=%Rrc\n", pImage->pszTargetName, rc)); 4278 goto out; 4279 } 4202 4203 return rc; 4204 } 4205 4206 /** 4207 * Issues the INQUIRY command to the target and checks for the correct device type. 4208 * 4209 * @returns VBox status code. 4210 * @param pImage The iSCSI image instance. 4211 */ 4212 static int iscsiOpenImageInquiry(PISCSIIMAGE pImage) 4213 { 4214 SCSIREQ sr; 4215 RTSGSEG DataSeg; 4216 uint8_t data8[8]; 4280 4217 4281 4218 /* … … 4302 4239 sr.cT2ISegs = 1; 4303 4240 sr.cbSense = sizeof(sr.abSense); 4304 rc = iscsiCommandSync(pImage, &sr, true /* fRetry */, VERR_INVALID_STATE);4241 int rc = iscsiCommandSync(pImage, &sr, true /* fRetry */, VERR_INVALID_STATE); 4305 4242 if (RT_SUCCESS(rc)) 4306 4243 { 4307 4244 uint8_t devType = (sr.cbT2IData > 0) ? data8[0] & SCSI_DEVTYPE_MASK : 255; 4308 if (devType != SCSI_DEVTYPE_DISK) 4245 if (devType == SCSI_DEVTYPE_DISK) 4246 { 4247 uint8_t uCmdQueue = (sr.cbT2IData >= 8) ? data8[7] & SCSI_INQUIRY_CMDQUE_MASK : 0; 4248 if (uCmdQueue > 0) 4249 pImage->fCmdQueuingSupported = true; 4250 else if (pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) 4251 rc = VERR_NOT_SUPPORTED; 4252 else 4253 LogRel(("iSCSI: target address %s, target name %s, %s command queuing\n", 4254 pImage->pszTargetAddress, pImage->pszTargetName, 4255 pImage->fCmdQueuingSupported ? "supports" : "doesn't support")); 4256 } 4257 else 4309 4258 { 4310 4259 rc = vdIfError(pImage->pIfError, VERR_VD_ISCSI_INVALID_TYPE, … … 4313 4262 pImage->LUN, devType); 4314 4263 LogRel(("iSCSI: Unsupported SCSI peripheral device type %d for target %s\n", devType & SCSI_DEVTYPE_MASK, pImage->pszTargetName)); 4315 goto out; 4316 } 4317 uint8_t uCmdQueue = (sr.cbT2IData >= 8) ? data8[7] & SCSI_INQUIRY_CMDQUE_MASK : 0; 4318 if (uCmdQueue > 0) 4319 pImage->fCmdQueuingSupported = true; 4320 else if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) 4321 { 4322 rc = VERR_NOT_SUPPORTED; 4323 goto out; 4324 } 4325 4326 LogRel(("iSCSI: target address %s, target name %s, %s command queuing\n", 4327 pImage->pszTargetAddress, pImage->pszTargetName, 4328 pImage->fCmdQueuingSupported ? "supports" : "doesn't support")); 4264 } 4329 4265 } 4330 4266 else 4331 {4332 4267 LogRel(("iSCSI: Could not get INQUIRY info for target %s, rc=%Rrc\n", pImage->pszTargetName, rc)); 4333 goto out; 4334 } 4268 4269 return rc; 4270 } 4271 4272 /** 4273 * Checks that the target allows write access if the caller requested it. 4274 * 4275 * @returns VBox status code. 4276 * @param pImage The iSCSI image instance. 4277 */ 4278 static int iscsiOpenImageCheckWriteAccess(PISCSIIMAGE pImage) 4279 { 4280 SCSIREQ sr; 4281 RTSGSEG DataSeg; 4282 uint8_t data4[4]; 4335 4283 4336 4284 /* … … 4338 4286 * mode parameter header. Refuse read/write opening of read only disks. 4339 4287 */ 4340 uint8_t data4[4];4341 4288 RT_ZERO(sr.abCDB); 4342 4289 sr.abCDB[0] = SCSI_MODE_SENSE_6; … … 4359 4306 sr.cT2ISegs = 1; 4360 4307 sr.cbSense = sizeof(sr.abSense); 4361 rc = iscsiCommandSync(pImage, &sr, true /* fRetry */, VERR_INVALID_STATE);4308 int rc = iscsiCommandSync(pImage, &sr, true /* fRetry */, VERR_INVALID_STATE); 4362 4309 if (RT_SUCCESS(rc)) 4363 4310 { 4364 4311 pImage->fTargetReadOnly = !!(data4[2] & 0x80); 4365 if (!(uOpenFlags & VD_OPEN_FLAGS_READONLY) && pImage->fTargetReadOnly) 4366 { 4312 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) && pImage->fTargetReadOnly) 4367 4313 rc = VERR_VD_IMAGE_READ_ONLY; 4368 goto out;4369 }4370 4314 } 4371 4315 else 4372 {4373 4316 LogRel(("iSCSI: Could not get MODE SENSE info for target %s, rc=%Rrc\n", pImage->pszTargetName, rc)); 4374 goto out; 4375 } 4317 4318 return rc; 4319 } 4320 4321 /** 4322 * Queries the media and sector size of the target. 4323 * 4324 * @returns VBox status code. 4325 * @param pImage The iSCSI image instance. 4326 */ 4327 static int iscsiOpenImageQueryTargetSizes(PISCSIIMAGE pImage) 4328 { 4329 SCSIREQ sr; 4330 RTSGSEG DataSeg; 4331 uint8_t data12[12]; 4376 4332 4377 4333 /* … … 4397 4353 sr.cbSense = sizeof(sr.abSense); 4398 4354 4399 rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);4355 int rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS); 4400 4356 if (RT_SUCCESS(rc)) 4401 4357 { … … 4429 4385 && sr.abSense[13] == SCSI_ASCQ_POWER_ON_RESET_BUS_DEVICE_RESET_OCCURRED) 4430 4386 { 4431 /** @todo for future: prepare and send command "REQUEST SENSE" which will 4432 return the status of target and will clear any unit attention condition that it reports */ 4387 /** @todo for future: prepare and send command "REQUEST SENSE" which will 4388 * return the status of target and will clear any unit attention 4389 * condition that it reports */ 4433 4390 rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS); 4434 4391 if (RT_FAILURE(rc)) … … 4436 4393 cMaxRetries--; 4437 4394 break; 4438 4439 4395 } 4440 4396 } … … 4456 4412 else 4457 4413 { 4414 uint8_t data8[8]; 4415 4458 4416 RT_ZERO(data8); 4459 4417 sr.abCDB[0] = SCSI_READ_CAPACITY; … … 4513 4471 && sr.abSense[13] == SCSI_ASCQ_POWER_ON_RESET_BUS_DEVICE_RESET_OCCURRED) 4514 4472 { 4515 /** @todo for future: prepare and send command "REQUEST SENSE" which will 4516 return the status of target and will clear any unit attention condition that it reports */ 4473 /** @todo for future: prepare and send command "REQUEST SENSE" which will 4474 * return the status of target and will clear any unit attention 4475 * condition that it reports */ 4517 4476 rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS); 4518 4477 if (RT_FAILURE(rc)) … … 4539 4498 } 4540 4499 else 4541 {4542 4500 LogRel(("iSCSI: Could not determine capacity of target %s, rc=%Rrc\n", pImage->pszTargetName, rc)); 4543 goto out; 4544 } 4545 } 4546 4501 } 4502 4503 return rc; 4504 } 4505 4506 /** 4507 * Queries the state of the read/write caches and tries to enable them if disabled. 4508 * 4509 * @returns VBox status code. 4510 * @param pImage The iSCSI image instance. 4511 */ 4512 static int iscsiOpenImageEnableReadWriteCache(PISCSIIMAGE pImage) 4513 { 4547 4514 /* 4548 4515 * Check the read and write cache bits. … … 4552 4519 * to do it again. 4553 4520 */ 4521 SCSIREQ sr; 4522 RTSGSEG DataSeg; 4554 4523 uint8_t aCachingModePage[32]; 4555 4524 … … 4574 4543 sr.cT2ISegs = 1; 4575 4544 sr.cbSense = sizeof(sr.abSense); 4576 rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);4545 int rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS); 4577 4546 if ( RT_SUCCESS(rc) 4578 4547 && (sr.status == SCSI_STATUS_OK) … … 4620 4589 if ( RT_SUCCESS(rc) 4621 4590 && (sr.status == SCSI_STATUS_OK)) 4622 {4623 4591 LogRel(("iSCSI: Enabled read and write cache of target %s\n", pImage->pszTargetName)); 4624 }4625 4592 else 4626 4593 { … … 4641 4608 } 4642 4609 4643 out: 4644 if (pszLUNInitial) 4645 RTMemFree(pszLUNInitial); 4610 return rc; 4611 } 4612 4613 /** 4614 * Internal: Open an image, constructing all necessary data structures. 4615 */ 4616 static int iscsiOpenImage(PISCSIIMAGE pImage, unsigned uOpenFlags) 4617 { 4618 pImage->uOpenFlags = uOpenFlags; 4619 4620 int rc = iscsiOpenImageInit(pImage); 4621 if (RT_SUCCESS(rc)) 4622 rc = iscsiOpenImageParseCfg(pImage); 4623 4624 if (RT_SUCCESS(rc)) 4625 { 4626 /* Don't actually establish iSCSI transport connection if this is just an 4627 * open to query the image information and the host IP stack isn't used. 4628 * Even trying is rather useless, as in this context the InTnet IP stack 4629 * isn't present. Returning dummies is the best possible result anyway. */ 4630 if ((uOpenFlags & VD_OPEN_FLAGS_INFO) && !pImage->fHostIP) 4631 LogFunc(("Not opening the transport connection as IntNet IP stack is not available. Will return dummies\n")); 4632 else 4633 { 4634 rc = iscsiOpenImageSocketCreate(pImage); 4635 if (RT_SUCCESS(rc)) 4636 { 4637 /* 4638 * Attach to the iSCSI target. This implicitly establishes the iSCSI 4639 * transport connection. 4640 */ 4641 rc = iscsiExecSync(pImage, iscsiAttach, pImage); 4642 if (RT_SUCCESS(rc)) 4643 { 4644 LogFlowFunc(("target '%s' opened successfully\n", pImage->pszTargetName)); 4645 4646 rc = iscsiOpenImageReportLuns(pImage); 4647 if (RT_SUCCESS(rc)) 4648 rc = iscsiOpenImageInquiry(pImage); 4649 if (RT_SUCCESS(rc)) 4650 rc = iscsiOpenImageCheckWriteAccess(pImage); 4651 if (RT_SUCCESS(rc)) 4652 rc = iscsiOpenImageQueryTargetSizes(pImage); 4653 if (RT_SUCCESS(rc)) 4654 rc = iscsiOpenImageEnableReadWriteCache(pImage); 4655 } 4656 else 4657 LogRel(("iSCSI: could not open target %s, rc=%Rrc\n", pImage->pszTargetName, rc)); 4658 } 4659 } 4660 } 4661 4646 4662 if (RT_FAILURE(rc)) 4647 4663 iscsiFreeImage(pImage, false);
Note:
See TracChangeset
for help on using the changeset viewer.