VirtualBox

Changeset 63829 in vbox


Ignore:
Timestamp:
Sep 14, 2016 10:49:28 AM (8 years ago)
Author:
vboxsync
Message:

Storage/iSCSI: Cleanup (part 2, split up iscsiOpenImage into several smaller parts)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/ISCSI.cpp

    r63827 r63829  
    39093909
    39103910/**
    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.
    39123915 */
    3913 static int iscsiOpenImage(PISCSIIMAGE pImage, unsigned uOpenFlags)
    3914 {
    3915     int rc;
     3916static 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 */
     3986static int iscsiOpenImageParseCfg(PISCSIIMAGE pImage)
     3987{
    39163988    char *pszLUN = NULL, *pszLUNInitial = NULL;
    39173989    bool fLunEncoded = false;
     
    39213993    bool fHostIPDef = false;
    39223994    bool fDumpMalformedPacketsDef = false;
    3923     rc = RTStrToUInt32Full(s_iscsiConfigDefaultWriteSplit, 0, &uWriteSplitDef);
     3995
     3996    int rc = RTStrToUInt32Full(s_iscsiConfigDefaultWriteSplit, 0, &uWriteSplitDef);
    39243997    AssertRC(rc);
    39253998    rc = RTStrToUInt32Full(s_iscsiConfigDefaultTimeout, 0, &uTimeoutDef);
     
    39284001    AssertRC(rc);
    39294002    fHostIPDef = RT_BOOL(uCfgTmp);
    3930 
    39314003    rc = RTStrToUInt64Full(s_iscsiConfigDefaultDumpMalformedPackets, 0, &uCfgTmp);
    39324004    AssertRC(rc);
    39334005    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;
    39884006
    39894007    /* Validate configuration, detect unknown keys. */
     
    40024020                           "HostIPStack\0"
    40034021                           "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"));
    40084023
    40094024    /* Query the iSCSI upper level configuration. */
    4010     rc = VDCFGQueryStringAlloc(pImage->pIfConfig,
    4011                                "TargetName", &pImage->pszTargetName);
     4025    rc = VDCFGQueryStringAlloc(pImage->pIfConfig, "TargetName", &pImage->pszTargetName);
    40124026    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);
    40194030    if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
    4020     {
    40214031        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);
    40244036    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
    40364039    pszLUNInitial = pszLUN;
    40374040    if (!strncmp(pszLUN, "enc", 3))
     
    40424045    rc = RTStrToUInt64Full(pszLUN, 0, &pImage->LUN);
    40434046    if (RT_FAILURE(rc))
    4044     {
    40454047        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)
    40494051    {
    40504052        if (pImage->LUN <= 255)
    4051         {
    40524053            pImage->LUN = pImage->LUN << 48; /* uses peripheral device addressing method */
    4053         }
    40544054        else if (pImage->LUN <= 16383)
    4055         {
    40564055            pImage->LUN = (pImage->LUN << 48) | RT_BIT_64(62); /* uses flat space addressing method */
    4057         }
    40584056        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
    40674060    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);
    40784064    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
    40964076    void *pvInitiatorSecretEncrypted;
    40974077    size_t cbInitiatorSecretEncrypted;
    4098     rc = VDCFGQueryBytesAlloc(pImage->pIfConfig,
    4099                               "InitiatorSecretEncrypted",
    4100                               &pvInitiatorSecretEncrypted,
    4101                               &cbInitiatorSecretEncrypted);
     4078    rc = VDCFGQueryBytesAlloc(pImage->pIfConfig, "InitiatorSecretEncrypted",
     4079                              &pvInitiatorSecretEncrypted, &cbInitiatorSecretEncrypted);
    41024080    if (RT_SUCCESS(rc))
    41034081    {
     
    41064084        {
    41074085            /* 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);
    41184100    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);
    41304105    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);
    41384109    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);
    41514114    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 */
     4126static int iscsiOpenImageSocketCreate(PISCSIIMAGE pImage)
     4127{
    41874128    /* 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);
    41904131    if (RT_SUCCESS(rc))
    41914132    {
     
    41954136                            RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "iSCSI-Io");
    41964137        if (RT_FAILURE(rc))
    4197         {
    41984138            LogFunc(("Creating iSCSI I/O thread failed rc=%Rrc\n", rc));
    4199             goto out;
    4200         }
    42014139    }
    42024140    else if (rc == VERR_NOT_SUPPORTED)
    42034141    {
    42044142        /* 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))
    42074144            LogFunc(("Extended select is not supported by the interface but async I/O is requested -> %Rrc\n", rc));
    4208             goto out;
    4209         }
    42104145        else
    42114146        {
    42124147            pImage->fExtendedSelectSupported = false;
    42134148            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))
    42234153        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 */
     4164static int iscsiOpenImageReportLuns(PISCSIIMAGE pImage)
     4165{
    42394166    SCSIREQ sr;
    42404167    RTSGSEG DataSeg;
    4241     uint8_t data8[8];
    4242     uint8_t data12[12];
     4168    uint8_t rlundata[16];
    42434169
    42444170    /*
    42454171     * Inquire available LUNs - purely dummy request.
    42464172     */
    4247     uint8_t rlundata[16];
    42484173    RT_ZERO(sr.abCDB);
    42494174    sr.abCDB[0] = SCSI_REPORT_LUNS;
     
    42724197    sr.cT2ISegs  = 1;
    42734198    sr.cbSense   = sizeof(sr.abSense);
    4274     rc = iscsiCommandSync(pImage, &sr, false, VERR_INVALID_STATE);
     4199    int rc = iscsiCommandSync(pImage, &sr, false, VERR_INVALID_STATE);
    42754200    if (RT_FAILURE(rc))
    4276     {
    42774201        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 */
     4212static int iscsiOpenImageInquiry(PISCSIIMAGE pImage)
     4213{
     4214    SCSIREQ sr;
     4215    RTSGSEG DataSeg;
     4216    uint8_t data8[8];
    42804217
    42814218    /*
     
    43024239    sr.cT2ISegs  = 1;
    43034240    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);
    43054242    if (RT_SUCCESS(rc))
    43064243    {
    43074244        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
    43094258        {
    43104259            rc = vdIfError(pImage->pIfError, VERR_VD_ISCSI_INVALID_TYPE,
     
    43134262                            pImage->LUN, devType);
    43144263            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        }
    43294265    }
    43304266    else
    4331     {
    43324267        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 */
     4278static int iscsiOpenImageCheckWriteAccess(PISCSIIMAGE pImage)
     4279{
     4280    SCSIREQ sr;
     4281    RTSGSEG DataSeg;
     4282    uint8_t data4[4];
    43354283
    43364284    /*
     
    43384286     * mode parameter header. Refuse read/write opening of read only disks.
    43394287     */
    4340     uint8_t data4[4];
    43414288    RT_ZERO(sr.abCDB);
    43424289    sr.abCDB[0] = SCSI_MODE_SENSE_6;
     
    43594306    sr.cT2ISegs  = 1;
    43604307    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);
    43624309    if (RT_SUCCESS(rc))
    43634310    {
    43644311        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)
    43674313            rc = VERR_VD_IMAGE_READ_ONLY;
    4368             goto out;
    4369         }
    43704314    }
    43714315    else
    4372     {
    43734316        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 */
     4327static int iscsiOpenImageQueryTargetSizes(PISCSIIMAGE pImage)
     4328{
     4329    SCSIREQ sr;
     4330    RTSGSEG DataSeg;
     4331    uint8_t data12[12];
    43764332
    43774333    /*
     
    43974353    sr.cbSense   = sizeof(sr.abSense);
    43984354
    4399     rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
     4355    int rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
    44004356    if (RT_SUCCESS(rc))
    44014357    {
     
    44294385                           && sr.abSense[13] == SCSI_ASCQ_POWER_ON_RESET_BUS_DEVICE_RESET_OCCURRED)
    44304386                        {
    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 */
    44334390                            rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
    44344391                            if (RT_FAILURE(rc))
     
    44364393                            cMaxRetries--;
    44374394                            break;
    4438 
    44394395                        }
    44404396                    }
     
    44564412    else
    44574413    {
     4414        uint8_t data8[8];
     4415
    44584416        RT_ZERO(data8);
    44594417        sr.abCDB[0] = SCSI_READ_CAPACITY;
     
    45134471                               && sr.abSense[13] == SCSI_ASCQ_POWER_ON_RESET_BUS_DEVICE_RESET_OCCURRED)
    45144472                            {
    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 */
    45174476                                rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
    45184477                                if (RT_FAILURE(rc))
     
    45394498        }
    45404499        else
    4541         {
    45424500            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 */
     4512static int iscsiOpenImageEnableReadWriteCache(PISCSIIMAGE pImage)
     4513{
    45474514    /*
    45484515     * Check the read and write cache bits.
     
    45524519     * to do it again.
    45534520     */
     4521    SCSIREQ sr;
     4522    RTSGSEG DataSeg;
    45544523    uint8_t aCachingModePage[32];
    45554524
     
    45744543    sr.cT2ISegs  = 1;
    45754544    sr.cbSense = sizeof(sr.abSense);
    4576     rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
     4545    int rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS);
    45774546    if (   RT_SUCCESS(rc)
    45784547        && (sr.status == SCSI_STATUS_OK)
     
    46204589            if (   RT_SUCCESS(rc)
    46214590                && (sr.status == SCSI_STATUS_OK))
    4622             {
    46234591                LogRel(("iSCSI: Enabled read and write cache of target %s\n", pImage->pszTargetName));
    4624             }
    46254592            else
    46264593            {
     
    46414608    }
    46424609
    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 */
     4616static 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
    46464662    if (RT_FAILURE(rc))
    46474663        iscsiFreeImage(pImage, false);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette