Changeset 31098 in vbox
- Timestamp:
- Jul 26, 2010 9:06:52 AM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 64050
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/VBoxHDD.h
r30863 r31098 1005 1005 } 1006 1006 1007 /** Forward declaration of a VD socket. */ 1008 typedef struct VDSOCKETINT *VDSOCKET; 1009 /** Pointer to a VD socket. */ 1010 typedef VDSOCKET *PVDSOCKET; 1011 /** Nil socket handle. */ 1012 #define NIL_VDSOCKET ((VDSOCKET)0) 1013 1014 /** Connect flag to indicate that the backend wants to use the extended 1015 * socket I/O multiplexing call. This might not be supported on all configurations 1016 * (internal networking and iSCSI) 1017 * and the backend needs to take appropriate action. 1018 */ 1019 #define VD_INTERFACETCPNET_CONNECT_EXTENDED_SELECT RT_BIT_32(0) 1020 1021 /** @name Select events 1022 * @{ */ 1023 /** Readable without blocking. */ 1024 #define VD_INTERFACETCPNET_EVT_READ RT_BIT_32(0) 1025 /** Writable without blocking. */ 1026 #define VD_INTERFACETCPNET_EVT_WRITE RT_BIT_32(1) 1027 /** Error condition, hangup, exception or similar. */ 1028 #define VD_INTERFACETCPNET_EVT_ERROR RT_BIT_32(2) 1029 /** Mask of the valid bits. */ 1030 #define VD_INTERFACETCPNET_EVT_VALID_MASK UINT32_C(0x00000007) 1031 /** @} */ 1007 1032 1008 1033 /** … … 1024 1049 1025 1050 /** 1051 * Creates a socket. The socket is not connected if this succeeds. 1052 * 1053 * @return iprt status code. 1054 * @retval VERR_NOT_SUPPORTED if the combination of flags is not supported. 1055 * @param fFlags Combination of the VD_INTERFACETCPNET_CONNECT_* #defines. 1056 * @param pSock Where to store the handle. 1057 */ 1058 DECLR3CALLBACKMEMBER(int, pfnSocketCreate, (uint32_t fFlags, PVDSOCKET pSock)); 1059 1060 /** 1061 * Destroys the socket. 1062 * 1063 * @return iprt status code. 1064 * @param Sock Socket descriptor. 1065 */ 1066 DECLR3CALLBACKMEMBER(int, pfnSocketDestroy, (VDSOCKET Sock)); 1067 1068 /** 1026 1069 * Connect as a client to a TCP port. 1027 1070 * 1028 1071 * @return iprt status code. 1072 * @param Sock Socket descriptor. 1029 1073 * @param pszAddress The address to connect to. 1030 1074 * @param uPort The port to connect to. 1031 * @param pSock Where to store the handle to the established connection. 1032 */ 1033 DECLR3CALLBACKMEMBER(int, pfnClientConnect, (const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)); 1075 */ 1076 DECLR3CALLBACKMEMBER(int, pfnClientConnect, (VDSOCKET Sock, const char *pszAddress, uint32_t uPort)); 1034 1077 1035 1078 /** … … 1039 1082 * @param Sock Socket descriptor. 1040 1083 */ 1041 DECLR3CALLBACKMEMBER(int, pfnClientClose, (RTSOCKET Sock)); 1084 DECLR3CALLBACKMEMBER(int, pfnClientClose, (VDSOCKET Sock)); 1085 1086 /** 1087 * Returns whether the socket is currently connected to the client. 1088 * 1089 * @returns true if the socket is connected. 1090 * false otherwise. 1091 * @param Sock Socket descriptor. 1092 */ 1093 DECLR3CALLBACKMEMBER(bool, pfnIsClientConnected, (VDSOCKET Sock)); 1042 1094 1043 1095 /** … … 1050 1102 * Use RT_INDEFINITE_WAIT to wait for ever. 1051 1103 */ 1052 DECLR3CALLBACKMEMBER(int, pfnSelectOne, ( RTSOCKET Sock, RTMSINTERVAL cMillies));1104 DECLR3CALLBACKMEMBER(int, pfnSelectOne, (VDSOCKET Sock, RTMSINTERVAL cMillies)); 1053 1105 1054 1106 /** … … 1063 1115 * If not NULL a partial read can be done successfully. 1064 1116 */ 1065 DECLR3CALLBACKMEMBER(int, pfnRead, ( RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead));1117 DECLR3CALLBACKMEMBER(int, pfnRead, (VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)); 1066 1118 1067 1119 /** … … 1073 1125 * @param cbBuffer How much to write. 1074 1126 */ 1075 DECLR3CALLBACKMEMBER(int, pfnWrite, ( RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer));1127 DECLR3CALLBACKMEMBER(int, pfnWrite, (VDSOCKET Sock, const void *pvBuffer, size_t cbBuffer)); 1076 1128 1077 1129 /** … … 1082 1134 * @param pSgBuf Scatter/gather buffer to write data to socket. 1083 1135 */ 1084 DECLR3CALLBACKMEMBER(int, pfnSgWrite, ( RTSOCKET Sock, PCRTSGBUF pSgBuf));1136 DECLR3CALLBACKMEMBER(int, pfnSgWrite, (VDSOCKET Sock, PCRTSGBUF pSgBuf)); 1085 1137 1086 1138 /** … … 1090 1142 * @param Sock Socket descriptor. 1091 1143 */ 1092 DECLR3CALLBACKMEMBER(int, pfnFlush, ( RTSOCKET Sock));1144 DECLR3CALLBACKMEMBER(int, pfnFlush, (VDSOCKET Sock)); 1093 1145 1094 1146 /** … … 1099 1151 * @param fEnable When set to true enables coalescing. 1100 1152 */ 1101 DECLR3CALLBACKMEMBER(int, pfnSetSendCoalescing, ( RTSOCKET Sock, bool fEnable));1153 DECLR3CALLBACKMEMBER(int, pfnSetSendCoalescing, (VDSOCKET Sock, bool fEnable)); 1102 1154 1103 1155 /** … … 1108 1160 * @param pAddr Where to store the local address on success. 1109 1161 */ 1110 DECLR3CALLBACKMEMBER(int, pfnGetLocalAddress, ( RTSOCKET Sock, PRTNETADDR pAddr));1162 DECLR3CALLBACKMEMBER(int, pfnGetLocalAddress, (VDSOCKET Sock, PRTNETADDR pAddr)); 1111 1163 1112 1164 /** … … 1117 1169 * @param pAddr Where to store the peer address on success. 1118 1170 */ 1119 DECLR3CALLBACKMEMBER(int, pfnGetPeerAddress, (RTSOCKET Sock, PRTNETADDR pAddr)); 1171 DECLR3CALLBACKMEMBER(int, pfnGetPeerAddress, (VDSOCKET Sock, PRTNETADDR pAddr)); 1172 1173 /** 1174 * Socket I/O multiplexing - extended version which can be woken up. 1175 * Checks if the socket is ready for reading or writing. 1176 * 1177 * @return iprt status code. 1178 * @retval VERR_INTERRUPTED if the thread was woken up by a pfnPoke call. 1179 * @param Sock Socket descriptor. 1180 * @param pfEvents Where to store the received events. 1181 * @param cMillies Number of milliseconds to wait for the socket. 1182 * Use RT_INDEFINITE_WAIT to wait for ever. 1183 */ 1184 DECLR3CALLBACKMEMBER(int, pfnSelectOneEx, (VDSOCKET Sock, uint32_t *pfEvents, RTMSINTERVAL cMillies)); 1185 1186 /** 1187 * Wakes up the thread waiting in pfnSelectOneEx. 1188 * 1189 * @return iprt status code. 1190 * @param Sock Socket descriptor. 1191 */ 1192 DECLR3CALLBACKMEMBER(int, pfnPoke, (VDSOCKET Sock)); 1120 1193 1121 1194 } VDINTERFACETCPNET, *PVDINTERFACETCPNET; -
trunk/src/VBox/Devices/Storage/DrvVD.cpp
r30468 r31098 33 33 #include <iprt/semaphore.h> 34 34 #include <iprt/sg.h> 35 #include <iprt/poll.h> 36 #include <iprt/pipe.h> 35 37 36 38 #ifdef VBOX_WITH_INIP … … 289 291 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pvTemplateUser; 290 292 293 LogFlowFunc(("pDrvIns=%#p pvTemplateUser=%#p pvUser=%#p rcReq\n", 294 pDrvIns, pvTemplateUser, pvUser, rcReq)); 295 291 296 if (pStorageBackend->fSyncIoPending) 292 297 { 298 Assert(!pvUser); 293 299 pStorageBackend->rcReqLast = rcReq; 294 300 pStorageBackend->fSyncIoPending = false; … … 298 304 { 299 305 int rc; 306 307 AssertPtr(pvUser); 300 308 301 309 AssertPtr(pStorageBackend->pfnCompleted); … … 440 448 PPDMASYNCCOMPLETIONTASK pTask; 441 449 450 LogFlowFunc(("pvUser=%#p pStorage=%#p\n", pvUser, pStorage)); 451 442 452 Assert(!pStorageBackend->fSyncIoPending); 443 453 ASMAtomicXchgBool(&pStorageBackend->fSyncIoPending, true); … … 450 460 { 451 461 /* Wait */ 462 LogFlowFunc(("Waiting for flush to complete\n")); 452 463 rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT); 453 464 AssertRC(rc); … … 592 603 } INIPSOCKADDRUNION; 593 604 594 static DECLCALLBACK(int) drvvdINIPFlush(RTSOCKET Sock); 605 typedef struct INIPSOCKET 606 { 607 int hSock; 608 } INIPSOCKET, *PINIPSOCKET; 609 610 static DECLCALLBACK(int) drvvdINIPFlush(VDSOCKET Sock); 611 612 /** @copydoc VDINTERFACETCPNET::pfnSocketCreate */ 613 static DECLCALLBACK(int) drvvdINIPSocketCreate(uint32_t fFlags, PVDSOCKET pSock) 614 { 615 PINIPSOCKET pSocketInt = NULL; 616 617 /* 618 * The extended select method is not supported because it is impossible to wakeup 619 * the thread. 620 */ 621 if (fFlags & VD_INTERFACETCPNET_CONNECT_EXTENDED_SELECT) 622 return VERR_NOT_SUPPORTED; 623 624 pSocketInt = (PINIPSOCKET)RTMemAllocZ(sizeof(INIPSOCKET)); 625 if (pSocketInt) 626 { 627 pSocketInt->hSock = INT32_MAX; 628 *pSock = (VDSOCKET)pSocketInt; 629 return VINF_SUCCESS; 630 } 631 632 return VERR_NO_MEMORY; 633 } 634 635 /** @copydoc VDINTERFACETCPNET::pfnSocketCreate */ 636 static DECLCALLBACK(int) drvvdINIPSocketDestroy(VDSOCKET Sock) 637 { 638 PINIPSOCKET pSocketInt = (PINIPSOCKET)Sock; 639 640 RTMemFree(pSocketInt); 641 return VINF_SUCCESS; 642 } 595 643 596 644 /** @copydoc VDINTERFACETCPNET::pfnClientConnect */ 597 static DECLCALLBACK(int) drvvdINIPClientConnect( const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)645 static DECLCALLBACK(int) drvvdINIPClientConnect(VDSOCKET Sock, const char *pszAddress, uint32_t uPort) 598 646 { 599 647 int rc = VINF_SUCCESS; 600 /* First check whether lwIP is set up in this VM instance. */ 648 PINIPSOCKET pSocketInt = (PINIPSOCKET)Sock; 649 650 /* Check whether lwIP is set up in this VM instance. */ 601 651 if (!DevINIPConfigured()) 602 652 { … … 613 663 } 614 664 /* Create socket and connect. */ 615 int Sock = lwip_socket(PF_INET, SOCK_STREAM, 0);616 if ( Sock != -1)665 int iSock = lwip_socket(PF_INET, SOCK_STREAM, 0); 666 if (iSock != -1) 617 667 { 618 668 struct sockaddr_in InAddr = {0}; … … 620 670 InAddr.sin_port = htons(uPort); 621 671 InAddr.sin_addr = ip; 622 if (!lwip_connect( Sock, (struct sockaddr *)&InAddr, sizeof(InAddr)))623 { 624 *pSock = (RTSOCKET)Sock;672 if (!lwip_connect(iSock, (struct sockaddr *)&InAddr, sizeof(InAddr))) 673 { 674 pSocketInt->hSock = iSock; 625 675 return VINF_SUCCESS; 626 676 } 627 677 rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */ 628 lwip_close( Sock);678 lwip_close(iSock); 629 679 } 630 680 else … … 634 684 635 685 /** @copydoc VDINTERFACETCPNET::pfnClientClose */ 636 static DECLCALLBACK(int) drvvdINIPClientClose(RTSOCKET Sock) 637 { 638 lwip_close((uintptr_t)Sock); 686 static DECLCALLBACK(int) drvvdINIPClientClose(VDSOCKET Sock) 687 { 688 PINIPSOCKET pSocketInt = (PINIPSOCKET)Sock; 689 690 lwip_close(pSocketInt->hSock); 691 pSocketInt->hSock = INT32_MAX; 639 692 return VINF_SUCCESS; /** @todo real solution needed */ 640 693 } 641 694 695 /** @copydoc VDINTERFACETCPNET::pfnIsClientConnected */ 696 static DECLCALLBACK(bool) drvvdINIPIsClientConnected(VDSOCKET Sock) 697 { 698 PINIPSOCKET pSocketInt = (PINIPSOCKET)Sock; 699 700 return pSocketInt->hSock != INT32_MAX; 701 } 702 642 703 /** @copydoc VDINTERFACETCPNET::pfnSelectOne */ 643 static DECLCALLBACK(int) drvvdINIPSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies) 644 { 704 static DECLCALLBACK(int) drvvdINIPSelectOne(VDSOCKET Sock, RTMSINTERVAL cMillies) 705 { 706 PINIPSOCKET pSocketInt = (PINIPSOCKET)Sock; 645 707 fd_set fdsetR; 646 708 FD_ZERO(&fdsetR); … … 650 712 int rc; 651 713 if (cMillies == RT_INDEFINITE_WAIT) 652 rc = lwip_select( (uintptr_t)Sock + 1, &fdsetR, NULL, &fdsetE, NULL);714 rc = lwip_select(pSocketInt->hSock + 1, &fdsetR, NULL, &fdsetE, NULL); 653 715 else 654 716 { … … 656 718 timeout.tv_sec = cMillies / 1000; 657 719 timeout.tv_usec = (cMillies % 1000) * 1000; 658 rc = lwip_select( (uintptr_t)Sock + 1, &fdsetR, NULL, &fdsetE, &timeout);720 rc = lwip_select(pSocketInt->hSock + 1, &fdsetR, NULL, &fdsetE, &timeout); 659 721 } 660 722 if (rc > 0) … … 666 728 667 729 /** @copydoc VDINTERFACETCPNET::pfnRead */ 668 static DECLCALLBACK(int) drvvdINIPRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 669 { 730 static DECLCALLBACK(int) drvvdINIPRead(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 731 { 732 PINIPSOCKET pSocketInt = (PINIPSOCKET)Sock; 733 670 734 /* Do params checking */ 671 735 if (!pvBuffer || !cbBuffer) … … 686 750 * needed it, so I added it here, too). Didn't investigate if this 687 751 * really has issues. Better be safe than sorry. */ 688 ssize_t cbBytesRead = lwip_recv( (uintptr_t)Sock, (char *)pvBuffer + cbRead,752 ssize_t cbBytesRead = lwip_recv(pSocketInt->hSock, (char *)pvBuffer + cbRead, 689 753 RT_MIN(cbToRead, 32768), 0); 690 754 if (cbBytesRead < 0) … … 712 776 713 777 /** @copydoc VDINTERFACETCPNET::pfnWrite */ 714 static DECLCALLBACK(int) drvvdINIPWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer) 715 { 778 static DECLCALLBACK(int) drvvdINIPWrite(VDSOCKET Sock, const void *pvBuffer, size_t cbBuffer) 779 { 780 PINIPSOCKET pSocketInt = (PINIPSOCKET)Sock; 781 716 782 do 717 783 { … … 720 786 * don't get any wraparounds. This should be moved to DevINIP 721 787 * stack interface once that's implemented. */ 722 ssize_t cbWritten = lwip_send( (uintptr_t)Sock, (void *)pvBuffer,788 ssize_t cbWritten = lwip_send(pSocketInt->hSock, (void *)pvBuffer, 723 789 RT_MIN(cbBuffer, 32768), 0); 724 790 if (cbWritten < 0) … … 734 800 735 801 /** @copydoc VDINTERFACETCPNET::pfnSgWrite */ 736 static DECLCALLBACK(int) drvvdINIPSgWrite( RTSOCKET Sock, PCRTSGBUF pSgBuf)802 static DECLCALLBACK(int) drvvdINIPSgWrite(VDSOCKET Sock, PCRTSGBUF pSgBuf) 737 803 { 738 804 int rc = VINF_SUCCESS; … … 754 820 755 821 /** @copydoc VDINTERFACETCPNET::pfnFlush */ 756 static DECLCALLBACK(int) drvvdINIPFlush(RTSOCKET Sock) 757 { 822 static DECLCALLBACK(int) drvvdINIPFlush(VDSOCKET Sock) 823 { 824 PINIPSOCKET pSocketInt = (PINIPSOCKET)Sock; 825 758 826 int fFlag = 1; 759 lwip_setsockopt( (uintptr_t)Sock, IPPROTO_TCP, TCP_NODELAY,827 lwip_setsockopt(pSocketInt->hSock, IPPROTO_TCP, TCP_NODELAY, 760 828 (const char *)&fFlag, sizeof(fFlag)); 761 829 fFlag = 0; 762 lwip_setsockopt( (uintptr_t)Sock, IPPROTO_TCP, TCP_NODELAY,830 lwip_setsockopt(pSocketInt->hSock, IPPROTO_TCP, TCP_NODELAY, 763 831 (const char *)&fFlag, sizeof(fFlag)); 764 832 return VINF_SUCCESS; … … 766 834 767 835 /** @copydoc VDINTERFACETCPNET::pfnSetSendCoalescing */ 768 static DECLCALLBACK(int) drvvdINIPSetSendCoalescing(RTSOCKET Sock, bool fEnable) 769 { 836 static DECLCALLBACK(int) drvvdINIPSetSendCoalescing(VDSOCKET Sock, bool fEnable) 837 { 838 PINIPSOCKET pSocketInt = (PINIPSOCKET)Sock; 839 770 840 int fFlag = fEnable ? 0 : 1; 771 lwip_setsockopt( (uintptr_t)Sock, IPPROTO_TCP, TCP_NODELAY,841 lwip_setsockopt(pSocketInt->hSock, IPPROTO_TCP, TCP_NODELAY, 772 842 (const char *)&fFlag, sizeof(fFlag)); 773 843 return VINF_SUCCESS; … … 775 845 776 846 /** @copydoc VDINTERFACETCPNET::pfnGetLocalAddress */ 777 static DECLCALLBACK(int) drvvdINIPGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr) 778 { 847 static DECLCALLBACK(int) drvvdINIPGetLocalAddress(VDSOCKET Sock, PRTNETADDR pAddr) 848 { 849 PINIPSOCKET pSocketInt = (PINIPSOCKET)Sock; 779 850 INIPSOCKADDRUNION u; 780 851 socklen_t cbAddr = sizeof(u); 781 852 RT_ZERO(u); 782 if (!lwip_getsockname( (uintptr_t)Sock, &u.Addr, &cbAddr))853 if (!lwip_getsockname(pSocketInt->hSock, &u.Addr, &cbAddr)) 783 854 { 784 855 /* … … 801 872 802 873 /** @copydoc VDINTERFACETCPNET::pfnGetPeerAddress */ 803 static DECLCALLBACK(int) drvvdINIPGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr) 804 { 874 static DECLCALLBACK(int) drvvdINIPGetPeerAddress(VDSOCKET Sock, PRTNETADDR pAddr) 875 { 876 PINIPSOCKET pSocketInt = (PINIPSOCKET)Sock; 805 877 INIPSOCKADDRUNION u; 806 878 socklen_t cbAddr = sizeof(u); 807 879 RT_ZERO(u); 808 if (!lwip_getpeername( (uintptr_t)Sock, &u.Addr, &cbAddr))880 if (!lwip_getpeername(pSocketInt->hSock, &u.Addr, &cbAddr)) 809 881 { 810 882 /* … … 825 897 return VERR_NET_OPERATION_NOT_SUPPORTED; 826 898 } 899 900 /** @copydoc VDINTERFACETCPNET::pfnSelectOneEx */ 901 static DECLCALLBACK(int) drvvdINIPSelectOneEx(VDSOCKET Sock, uint32_t *pfEvents, RTMSINTERVAL cMillies) 902 { 903 AssertMsgFailed(("Not supported!\n")); 904 return VERR_NOT_SUPPORTED; 905 } 906 907 /** @copydoc VDINTERFACETCPNET::pfnPoke */ 908 static DECLCALLBACK(int) drvvdINIPPoke(VDSOCKET Sock) 909 { 910 AssertMsgFailed(("Not supported!\n")); 911 return VERR_NOT_SUPPORTED; 912 } 913 827 914 #endif /* VBOX_WITH_INIP */ 915 916 917 /******************************************************************************* 918 * VD TCP network stack interface implementation - Host TCP case * 919 *******************************************************************************/ 920 921 /** 922 * Socket data. 923 */ 924 typedef struct VDSOCKETINT 925 { 926 /** IPRT socket handle. */ 927 RTSOCKET hSocket; 928 /** Pollset with the wakeup pipe and socket. */ 929 RTPOLLSET hPollSet; 930 /** Pipe endpoint - read (in the pollset). */ 931 RTPIPE hPipeR; 932 /** Pipe endpoint - write. */ 933 RTPIPE hPipeW; 934 /** Flag whether the thread was woken up. */ 935 volatile bool fWokenUp; 936 /** Flag whether the thread is waiting in the select call. */ 937 volatile bool fWaiting; 938 } VDSOCKETINT, *PVDSOCKETINT; 939 940 /** Pollset id of the socket. */ 941 #define VDSOCKET_POLL_ID_SOCKET 0 942 /** Pollset id of the pipe. */ 943 #define VDSOCKET_POLL_ID_PIPE 1 944 945 /** @copydoc VDINTERFACETCPNET::pfnSocketCreate */ 946 static DECLCALLBACK(int) drvvdTcpSocketCreate(uint32_t fFlags, PVDSOCKET pSock) 947 { 948 int rc = VINF_SUCCESS; 949 int rc2 = VINF_SUCCESS; 950 PVDSOCKETINT pSockInt = NULL; 951 952 pSockInt = (PVDSOCKETINT)RTMemAllocZ(sizeof(VDSOCKETINT)); 953 if (!pSockInt) 954 return VERR_NO_MEMORY; 955 956 pSockInt->hSocket = NIL_RTSOCKET; 957 pSockInt->hPollSet = NIL_RTPOLLSET; 958 pSockInt->hPipeR = NIL_RTPIPE; 959 pSockInt->hPipeW = NIL_RTPIPE; 960 pSockInt->fWokenUp = false; 961 pSockInt->fWaiting = false; 962 963 if (fFlags & VD_INTERFACETCPNET_CONNECT_EXTENDED_SELECT) 964 { 965 /* Init pipe and pollset. */ 966 rc = RTPipeCreate(&pSockInt->hPipeR, &pSockInt->hPipeW, 0); 967 if (RT_SUCCESS(rc)) 968 { 969 rc = RTPollSetCreate(&pSockInt->hPollSet); 970 if (RT_SUCCESS(rc)) 971 { 972 rc = RTPollSetAddPipe(pSockInt->hPollSet, pSockInt->hPipeR, 973 RTPOLL_EVT_READ, VDSOCKET_POLL_ID_PIPE); 974 if (RT_SUCCESS(rc)) 975 { 976 *pSock = pSockInt; 977 return VINF_SUCCESS; 978 } 979 980 RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_PIPE); 981 rc2 = RTPollSetDestroy(pSockInt->hPollSet); 982 AssertRC(rc2); 983 } 984 985 rc2 = RTPipeClose(pSockInt->hPipeR); 986 AssertRC(rc2); 987 rc2 = RTPipeClose(pSockInt->hPipeW); 988 AssertRC(rc2); 989 } 990 } 991 992 RTMemFree(pSockInt); 993 994 return rc; 995 } 996 997 /** @copydoc VDINTERFACETCPNET::pfnSocketDestroy */ 998 static DECLCALLBACK(int) drvvdTcpSocketDestroy(VDSOCKET Sock) 999 { 1000 int rc = VINF_SUCCESS; 1001 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1002 1003 /* Destroy the pipe and pollset if necessary. */ 1004 if (pSockInt->hPollSet != NIL_RTPOLLSET) 1005 { 1006 if (pSockInt->hSocket != NIL_RTSOCKET) 1007 { 1008 rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_SOCKET); 1009 AssertRC(rc); 1010 } 1011 rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_PIPE); 1012 AssertRC(rc); 1013 rc = RTPollSetDestroy(pSockInt->hPollSet); 1014 AssertRC(rc); 1015 rc = RTPipeClose(pSockInt->hPipeR); 1016 AssertRC(rc); 1017 rc = RTPipeClose(pSockInt->hPipeW); 1018 AssertRC(rc); 1019 } 1020 1021 if (pSockInt->hSocket != NIL_RTSOCKET) 1022 rc = RTTcpClientClose(pSockInt->hSocket); 1023 1024 RTMemFree(pSockInt); 1025 1026 return rc; 1027 } 1028 1029 /** @copydoc VDINTERFACETCPNET::pfnClientConnect */ 1030 static DECLCALLBACK(int) drvvdTcpClientConnect(VDSOCKET Sock, const char *pszAddress, uint32_t uPort) 1031 { 1032 int rc = VINF_SUCCESS; 1033 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1034 1035 rc = RTTcpClientConnect(pszAddress, uPort, &pSockInt->hSocket); 1036 if (RT_SUCCESS(rc)) 1037 { 1038 /* Add to the pollset if required. */ 1039 if (pSockInt->hPollSet != NIL_RTPOLLSET) 1040 { 1041 rc = RTPollSetAddSocket(pSockInt->hPollSet, pSockInt->hSocket, 1042 RTPOLL_EVT_READ | /*RTPOLL_EVT_WRITE |*/ RTPOLL_EVT_ERROR, 1043 VDSOCKET_POLL_ID_SOCKET); 1044 1045 if (RT_SUCCESS(rc)) 1046 return VINF_SUCCESS; 1047 } 1048 1049 rc = RTTcpClientClose(pSockInt->hSocket); 1050 } 1051 1052 return rc; 1053 } 1054 1055 /** @copydoc VDINTERFACETCPNET::pfnClientClose */ 1056 static DECLCALLBACK(int) drvvdTcpClientClose(VDSOCKET Sock) 1057 { 1058 int rc = VINF_SUCCESS; 1059 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1060 1061 if (pSockInt->hPollSet != NIL_RTPOLLSET) 1062 { 1063 rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_SOCKET); 1064 AssertRC(rc); 1065 } 1066 1067 rc = RTTcpClientClose(pSockInt->hSocket); 1068 pSockInt->hSocket = NIL_RTSOCKET; 1069 1070 return rc; 1071 } 1072 1073 /** @copydoc VDINTERFACETCPNET::pfnIsClientConnected */ 1074 static DECLCALLBACK(bool) drvvdTcpIsClientConnected(VDSOCKET Sock) 1075 { 1076 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1077 1078 return pSockInt->hSocket != NIL_RTSOCKET; 1079 } 1080 1081 /** @copydoc VDINTERFACETCPNET::pfnSelectOne */ 1082 static DECLCALLBACK(int) drvvdTcpSelectOne(VDSOCKET Sock, RTMSINTERVAL cMillies) 1083 { 1084 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1085 1086 return RTTcpSelectOne(pSockInt->hSocket, cMillies); 1087 } 1088 1089 /** @copydoc VDINTERFACETCPNET::pfnRead */ 1090 static DECLCALLBACK(int) drvvdTcpRead(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 1091 { 1092 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1093 1094 return RTTcpRead(pSockInt->hSocket, pvBuffer, cbBuffer, pcbRead); 1095 } 1096 1097 /** @copydoc VDINTERFACETCPNET::pfnWrite */ 1098 static DECLCALLBACK(int) drvvdTcpWrite(VDSOCKET Sock, const void *pvBuffer, size_t cbBuffer) 1099 { 1100 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1101 1102 return RTTcpWrite(pSockInt->hSocket, pvBuffer, cbBuffer); 1103 } 1104 1105 /** @copydoc VDINTERFACETCPNET::pfnSgWrite */ 1106 static DECLCALLBACK(int) drvvdTcpSgWrite(VDSOCKET Sock, PCRTSGBUF pSgBuf) 1107 { 1108 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1109 1110 return RTTcpSgWrite(pSockInt->hSocket, pSgBuf); 1111 } 1112 1113 /** @copydoc VDINTERFACETCPNET::pfnFlush */ 1114 static DECLCALLBACK(int) drvvdTcpFlush(VDSOCKET Sock) 1115 { 1116 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1117 1118 return RTTcpFlush(pSockInt->hSocket); 1119 } 1120 1121 /** @copydoc VDINTERFACETCPNET::pfnSetSendCoalescing */ 1122 static DECLCALLBACK(int) drvvdTcpSetSendCoalescing(VDSOCKET Sock, bool fEnable) 1123 { 1124 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1125 1126 return RTTcpSetSendCoalescing(pSockInt->hSocket, fEnable); 1127 } 1128 1129 /** @copydoc VDINTERFACETCPNET::pfnGetLocalAddress */ 1130 static DECLCALLBACK(int) drvvdTcpGetLocalAddress(VDSOCKET Sock, PRTNETADDR pAddr) 1131 { 1132 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1133 1134 return RTTcpGetLocalAddress(pSockInt->hSocket, pAddr); 1135 } 1136 1137 /** @copydoc VDINTERFACETCPNET::pfnGetPeerAddress */ 1138 static DECLCALLBACK(int) drvvdTcpGetPeerAddress(VDSOCKET Sock, PRTNETADDR pAddr) 1139 { 1140 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1141 1142 return RTTcpGetPeerAddress(pSockInt->hSocket, pAddr); 1143 } 1144 1145 /** @copydoc VDINTERFACETCPNET::pfnSelectOneEx */ 1146 static DECLCALLBACK(int) drvvdTcpSelectOneEx(VDSOCKET Sock, uint32_t *pfEvents, RTMSINTERVAL cMillies) 1147 { 1148 int rc = VINF_SUCCESS; 1149 uint32_t id = 0; 1150 uint32_t fEvents = 0; 1151 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1152 1153 *pfEvents = 0; 1154 1155 ASMAtomicXchgBool(&pSockInt->fWaiting, true); 1156 if (ASMAtomicXchgBool(&pSockInt->fWokenUp, false)) 1157 { 1158 ASMAtomicXchgBool(&pSockInt->fWaiting, false); 1159 return VERR_INTERRUPTED; 1160 } 1161 1162 rc = RTPoll(pSockInt->hPollSet, cMillies, &fEvents, &id); 1163 Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT); 1164 1165 ASMAtomicXchgBool(&pSockInt->fWaiting, false); 1166 1167 if (RT_SUCCESS(rc)) 1168 { 1169 if (id == VDSOCKET_POLL_ID_SOCKET) 1170 { 1171 fEvents &= RTPOLL_EVT_VALID_MASK; 1172 1173 if (fEvents & RTPOLL_EVT_READ) 1174 *pfEvents |= VD_INTERFACETCPNET_EVT_READ; 1175 if (fEvents & RTPOLL_EVT_WRITE) 1176 *pfEvents |= VD_INTERFACETCPNET_EVT_WRITE; 1177 if (fEvents & RTPOLL_EVT_ERROR) 1178 *pfEvents |= VD_INTERFACETCPNET_EVT_ERROR; 1179 } 1180 else 1181 { 1182 size_t cbRead = 0; 1183 uint8_t abBuf[10]; 1184 Assert(id == VDSOCKET_POLL_ID_PIPE); 1185 Assert((fEvents & RTPOLL_EVT_VALID_MASK) == RTPOLL_EVT_READ); 1186 1187 /* We got interrupted, drain the pipe. */ 1188 rc = RTPipeRead(pSockInt->hPipeR, abBuf, sizeof(abBuf), &cbRead); 1189 AssertRC(rc); 1190 1191 ASMAtomicXchgBool(&pSockInt->fWokenUp, false); 1192 1193 rc = VERR_INTERRUPTED; 1194 } 1195 } 1196 1197 return rc; 1198 } 1199 1200 /** @copydoc VDINTERFACETCPNET::pfnPoke */ 1201 static DECLCALLBACK(int) drvvdTcpPoke(VDSOCKET Sock) 1202 { 1203 int rc = VINF_SUCCESS; 1204 size_t cbWritten = 0; 1205 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1206 1207 ASMAtomicXchgBool(&pSockInt->fWokenUp, true); 1208 1209 if (ASMAtomicReadBool(&pSockInt->fWaiting)) 1210 { 1211 rc = RTPipeWrite(pSockInt->hPipeW, "", 1, &cbWritten); 1212 Assert(RT_SUCCESS(rc) || cbWritten == 0); 1213 } 1214 1215 return VINF_SUCCESS; 1216 } 828 1217 829 1218 … … 1410 1799 pThis->VDITcpNetCallbacks.cbSize = sizeof(VDINTERFACETCPNET); 1411 1800 pThis->VDITcpNetCallbacks.enmInterface = VDINTERFACETYPE_TCPNET; 1412 pThis->VDITcpNetCallbacks.pfnClientConnect = RTTcpClientConnect; 1413 pThis->VDITcpNetCallbacks.pfnClientClose = RTTcpClientClose; 1414 pThis->VDITcpNetCallbacks.pfnSelectOne = RTTcpSelectOne; 1415 pThis->VDITcpNetCallbacks.pfnRead = RTTcpRead; 1416 pThis->VDITcpNetCallbacks.pfnWrite = RTTcpWrite; 1417 pThis->VDITcpNetCallbacks.pfnSgWrite = RTTcpSgWrite; 1418 pThis->VDITcpNetCallbacks.pfnFlush = RTTcpFlush; 1419 pThis->VDITcpNetCallbacks.pfnSetSendCoalescing = RTTcpSetSendCoalescing; 1420 pThis->VDITcpNetCallbacks.pfnGetLocalAddress = RTTcpGetLocalAddress; 1421 pThis->VDITcpNetCallbacks.pfnGetPeerAddress = RTTcpGetPeerAddress; 1801 pThis->VDITcpNetCallbacks.pfnSocketCreate = drvvdTcpSocketCreate; 1802 pThis->VDITcpNetCallbacks.pfnSocketDestroy = drvvdTcpSocketDestroy; 1803 pThis->VDITcpNetCallbacks.pfnClientConnect = drvvdTcpClientConnect; 1804 pThis->VDITcpNetCallbacks.pfnIsClientConnected = drvvdTcpIsClientConnected; 1805 pThis->VDITcpNetCallbacks.pfnClientClose = drvvdTcpClientClose; 1806 pThis->VDITcpNetCallbacks.pfnSelectOne = drvvdTcpSelectOne; 1807 pThis->VDITcpNetCallbacks.pfnRead = drvvdTcpRead; 1808 pThis->VDITcpNetCallbacks.pfnWrite = drvvdTcpWrite; 1809 pThis->VDITcpNetCallbacks.pfnSgWrite = drvvdTcpSgWrite; 1810 pThis->VDITcpNetCallbacks.pfnFlush = drvvdTcpFlush; 1811 pThis->VDITcpNetCallbacks.pfnSetSendCoalescing = drvvdTcpSetSendCoalescing; 1812 pThis->VDITcpNetCallbacks.pfnGetLocalAddress = drvvdTcpGetLocalAddress; 1813 pThis->VDITcpNetCallbacks.pfnGetPeerAddress = drvvdTcpGetPeerAddress; 1814 pThis->VDITcpNetCallbacks.pfnSelectOneEx = drvvdTcpSelectOneEx; 1815 pThis->VDITcpNetCallbacks.pfnPoke = drvvdTcpPoke; 1422 1816 } 1423 1817 else … … 1429 1823 pThis->VDITcpNetCallbacks.cbSize = sizeof(VDINTERFACETCPNET); 1430 1824 pThis->VDITcpNetCallbacks.enmInterface = VDINTERFACETYPE_TCPNET; 1825 pThis->VDITcpNetCallbacks.pfnSocketCreate = drvvdINIPSocketCreate; 1826 pThis->VDITcpNetCallbacks.pfnSocketDestroy = drvvdINIPSocketDestroy; 1431 1827 pThis->VDITcpNetCallbacks.pfnClientConnect = drvvdINIPClientConnect; 1432 1828 pThis->VDITcpNetCallbacks.pfnClientClose = drvvdINIPClientClose; 1829 pThis->VDITcpNetCallbacks.pfnIsClientConnected = drvvdINIPIsClientConnected; 1433 1830 pThis->VDITcpNetCallbacks.pfnSelectOne = drvvdINIPSelectOne; 1434 1831 pThis->VDITcpNetCallbacks.pfnRead = drvvdINIPRead; … … 1439 1836 pThis->VDITcpNetCallbacks.pfnGetLocalAddress = drvvdINIPGetLocalAddress; 1440 1837 pThis->VDITcpNetCallbacks.pfnGetPeerAddress = drvvdINIPGetPeerAddress; 1838 pThis->VDITcpNetCallbacks.pfnSelectOneEx = drvvdINIPSelectOneEx; 1839 pThis->VDITcpNetCallbacks.pfnPoke = drvvdINIPPoke; 1441 1840 #endif /* VBOX_WITH_INIP */ 1442 1841 } -
trunk/src/VBox/Devices/Storage/ISCSIHDDCore.cpp
r30941 r31098 266 266 * Structures and Typedefs * 267 267 *******************************************************************************/ 268 269 /** 270 * iSCSI login negotiation parameter 271 */ 272 typedef struct ISCSIPARAMETER 273 { 274 /** Name of the parameter. */ 275 const char *pszParamName; 276 /** Value of the parameter. */ 277 const char *pszParamValue; 278 /** Length of the binary parameter. 0=zero-terminated string. */ 279 size_t cbParamValue; 280 } ISCSIPARAMETER; 281 282 283 /** 284 * iSCSI Response PDU buffer (scatter). 285 */ 286 typedef struct ISCSIRES 287 { 288 /** Length of PDU segment. */ 289 size_t cbSeg; 290 /** Pointer to PDU segment. */ 291 void *pvSeg; 292 } ISCSIRES; 293 /** Pointer to an iSCSI Response PDU buffer. */ 294 typedef ISCSIRES *PISCSIRES; 295 /** Pointer to a const iSCSI Response PDU buffer. */ 296 typedef ISCSIRES const *PCISCSIRES; 297 298 268 299 /** 269 300 * iSCSI Request PDU buffer (gather). … … 281 312 typedef ISCSIREQ const *PCISCSIREQ; 282 313 314 315 /** 316 * SCSI transfer directions. 317 */ 318 typedef enum SCSIXFER 319 { 320 SCSIXFER_NONE = 0, 321 SCSIXFER_TO_TARGET, 322 SCSIXFER_FROM_TARGET, 323 SCSIXFER_TO_FROM_TARGET 324 } SCSIXFER, *PSCSIXFER; 325 326 327 /** 328 * SCSI request structure. 329 */ 330 typedef struct SCSIREQ 331 { 332 /** Transfer direction. */ 333 SCSIXFER enmXfer; 334 /** Length of command block. */ 335 size_t cbCmd; 336 /** Length of Initiator2Target data buffer. */ 337 size_t cbI2TData; 338 /** Length of Target2Initiator data buffer. */ 339 size_t cbT2IData; 340 /** Length of sense buffer. */ 341 size_t cbSense; 342 /** Completion status of the command. */ 343 uint8_t status; 344 /** Pointer to command block. */ 345 void *pvCmd; 346 /** Pointer to Initiator2Target data buffer. */ 347 const void *pcvI2TData; 348 /** Pointer to Target2Initiator data buffer. */ 349 void *pvT2IData; 350 /** Pointer to sense buffer. */ 351 void *pvSense; 352 } SCSIREQ, *PSCSIREQ; 353 354 355 typedef enum ISCSICMDTYPE 356 { 357 /** Process a SCSI request. */ 358 ISCSICMDTYPE_REQ = 0, 359 /** Call a function in the I/O thread. */ 360 ISCSICMDTYPE_EXEC, 361 /** Usual 32bit hack. */ 362 ISCSICMDTYPE_32BIT_HACK = 0x7fffffff 363 } ISCSICMDTYPE; 364 365 366 /** The command completion function. */ 367 typedef DECLCALLBACK(void) FNISCSICMDCOMPLETED(void *pvUser); 368 /** Pointer to a command completion function. */ 369 typedef FNISCSICMDCOMPLETED *PFNISCSICMDCOMPLETED; 370 371 /** The command execution function. */ 372 typedef DECLCALLBACK(int) FNISCSIEXEC(void *pvUser); 373 /** Pointer to a command execution function. */ 374 typedef FNISCSIEXEC *PFNISCSIEXEC; 375 376 /** 377 * iSCSI command. 378 * Used to forward requests to the I/O thread 379 * if existing. 380 */ 381 typedef struct ISCSICMD 382 { 383 /** Next one in the list. */ 384 struct ISCSICMD *pNext; 385 /** Command to execute. */ 386 ISCSICMDTYPE enmCmdType; 387 /** Flag whether this is a synchronous request. */ 388 bool fSync; 389 /** Type dependent data - based on fSync. */ 390 union 391 { 392 /** Synchronous request. */ 393 struct 394 { 395 /** Event semaphore to signal if this is a synchronous request. */ 396 RTSEMEVENT EventSem; 397 /** Completion status code. */ 398 int rcCmd; 399 } Sync; 400 /** Asynchronous request. */ 401 struct 402 { 403 /** Completion callback. */ 404 PFNISCSICMDCOMPLETED pfnComplete; 405 /** Opaque user data. */ 406 void *pvUser; 407 } Async; 408 } Type; 409 /** Command type dependent data. */ 410 union 411 { 412 /** Process a SCSI request. */ 413 struct 414 { 415 /** The SCSI request to process. */ 416 PSCSIREQ pScsiReq; 417 } ScsiReq; 418 /** Call a function in the I/O thread. */ 419 struct 420 { 421 /** The method to execute. */ 422 PFNISCSIEXEC pfnExec; 423 /** User data. */ 424 void *pvUser; 425 } Exec; 426 } CmdType; 427 } ISCSICMD, *PISCSICMD; 283 428 284 429 /** … … 377 522 uint32_t uPort; 378 523 /** Socket handle of the TCP connection. */ 379 RTSOCKET Socket;524 VDSOCKET Socket; 380 525 /** Timeout for read operations on the TCP connection (in milliseconds). */ 381 526 uint32_t uReadTimeout; … … 384 529 /** Flag whether to use the host IP stack or DevINIP. */ 385 530 bool fHostIP; 531 532 /** Head of request queue */ 533 PISCSICMD pScsiReqQueue; 534 /** Mutex protecting the request queue from concurrent access. */ 535 RTSEMMUTEX MutexReqQueue; 536 /** I/O thread. */ 537 RTTHREAD hThreadIo; 538 /** Flag whether the thread should be still running. */ 539 volatile bool fRunning; 540 /** Flag whether extended select is supported. */ 541 bool fExtendedSelectSupported; 386 542 } ISCSIIMAGE, *PISCSIIMAGE; 387 388 389 /**390 * SCSI transfer directions.391 */392 typedef enum SCSIXFER393 {394 SCSIXFER_NONE = 0,395 SCSIXFER_TO_TARGET,396 SCSIXFER_FROM_TARGET,397 SCSIXFER_TO_FROM_TARGET398 } SCSIXFER, *PSCSIXFER;399 400 401 /**402 * SCSI request structure.403 */404 typedef struct SCSIREQ405 {406 /** Transfer direction. */407 SCSIXFER enmXfer;408 /** Length of command block. */409 size_t cbCmd;410 /** Length of Initiator2Target data buffer. */411 size_t cbI2TData;412 /** Length of Target2Initiator data buffer. */413 size_t cbT2IData;414 /** Length of sense buffer. */415 size_t cbSense;416 /** Completion status of the command. */417 uint8_t status;418 /** Pointer to command block. */419 void *pvCmd;420 /** Pointer to Initiator2Target data buffer. */421 const void *pcvI2TData;422 /** Pointer to Target2Initiator data buffer. */423 void *pvT2IData;424 /** Pointer to sense buffer. */425 void *pvSense;426 } SCSIREQ, *PSCSIREQ;427 428 429 /**430 * iSCSI login negotiation parameter431 */432 typedef struct ISCSIPARAMETER433 {434 /** Name of the parameter. */435 const char *pszParamName;436 /** Value of the parameter. */437 const char *pszParamValue;438 /** Length of the binary parameter. 0=zero-terminated string. */439 size_t cbParamValue;440 } ISCSIPARAMETER;441 442 443 /**444 * iSCSI Response PDU buffer (scatter).445 */446 typedef struct ISCSIRES447 {448 /** Length of PDU segment. */449 size_t cbSeg;450 /** Pointer to PDU segment. */451 void *pvSeg;452 } ISCSIRES;453 /** Pointer to an iSCSI Response PDU buffer. */454 typedef ISCSIRES *PISCSIRES;455 /** Pointer to a const iSCSI Response PDU buffer. */456 typedef ISCSIRES const *PCISCSIRES;457 543 458 544 … … 501 587 static uint32_t iscsiNewITT(PISCSIIMAGE pImage); 502 588 static int iscsiSendPDU(PISCSIIMAGE pImage, PISCSIREQ paReq, uint32_t cnReq, uint32_t uFlags); 503 static int iscsiRecvPDU(PISCSIIMAGE pImage, uint32_t itt, PISCSIRES paRes, uint32_t cnRes );589 static int iscsiRecvPDU(PISCSIIMAGE pImage, uint32_t itt, PISCSIRES paRes, uint32_t cnRes, bool fSelect); 504 590 static int drvISCSIValidatePDU(PISCSIRES paRes, uint32_t cnRes); 505 591 static int iscsiTextAddKeyValue(uint8_t *pbBuf, size_t cbBuf, size_t *pcbBufCurr, const char *pcszKey, const char *pcszValue, size_t cbValue); … … 540 626 } 541 627 628 DECLINLINE(bool) iscsiIsClientConnected(PISCSIIMAGE pImage) 629 { 630 return pImage->Socket != NIL_VDSOCKET 631 && pImage->pInterfaceNetCallbacks->pfnIsClientConnected(pImage->Socket); 632 } 542 633 543 634 static int iscsiTransportConnect(PISCSIIMAGE pImage) … … 547 638 return VERR_NET_DEST_ADDRESS_REQUIRED; 548 639 549 rc = pImage->pInterfaceNetCallbacks->pfnClientConnect(pImage-> pszHostname, pImage->uPort, &pImage->Socket);640 rc = pImage->pInterfaceNetCallbacks->pfnClientConnect(pImage->Socket, pImage->pszHostname, pImage->uPort); 550 641 if (RT_FAILURE(rc)) 551 642 { … … 591 682 592 683 593 static int iscsiTransportRead(PISCSIIMAGE pImage, PISCSIRES paResponse, unsigned int cnResponse )684 static int iscsiTransportRead(PISCSIIMAGE pImage, PISCSIRES paResponse, unsigned int cnResponse, bool fSelect) 594 685 { 595 686 int rc = VINF_SUCCESS; … … 599 690 600 691 LogFlowFunc(("cnResponse=%d (%s:%d)\n", cnResponse, pImage->pszHostname, pImage->uPort)); 601 if ( pImage->Socket == NIL_RTSOCKET)692 if (!iscsiIsClientConnected(pImage)) 602 693 { 603 694 /* Reconnecting makes no sense in this case, as there will be nothing … … 622 713 } 623 714 Assert(cMilliesRemaining < 1000000); 624 rc = pImage->pInterfaceNetCallbacks->pfnSelectOne(pImage->Socket, 625 cMilliesRemaining); 626 if (RT_FAILURE(rc)) 627 break; 715 if (fSelect) 716 { 717 rc = pImage->pInterfaceNetCallbacks->pfnSelectOne(pImage->Socket, 718 cMilliesRemaining); 719 if (RT_FAILURE(rc)) 720 break; 721 } 628 722 rc = pImage->pInterfaceNetCallbacks->pfnRead(pImage->Socket, 629 723 pDst, residual, … … 635 729 /* The other end has closed the connection. */ 636 730 pImage->pInterfaceNetCallbacks->pfnClientClose(pImage->Socket); 637 pImage->Socket = NIL_RTSOCKET;638 731 pImage->state = ISCSISTATE_FREE; 639 732 rc = VERR_NET_CONNECTION_RESET; … … 686 779 cbSegActual = residual; 687 780 } 781 LogFlowFunc(("cbToRead=%u residual=%u cbSegActual=%u cbActuallRead=%u\n", 782 cbToRead, residual, cbSegActual, cbActuallyRead)); 688 783 } while (true); 689 784 } … … 723 818 724 819 LogFlowFunc(("cnRequest=%d (%s:%d)\n", cnRequest, pImage->pszHostname, pImage->uPort)); 725 if ( pImage->Socket == NIL_RTSOCKET)820 if (!iscsiIsClientConnected(pImage)) 726 821 { 727 822 /* Attempt to reconnect if the connection was previously broken. */ … … 791 886 792 887 /* Clean up previous connection data. */ 793 if ( pImage->Socket != NIL_RTSOCKET)888 if (iscsiIsClientConnected(pImage)) 794 889 { 795 890 pImage->pInterfaceNetCallbacks->pfnClientClose(pImage->Socket); 796 pImage->Socket = NIL_RTSOCKET;797 891 } 798 892 if (pImage->pszHostname) … … 870 964 if (RT_SUCCESS(rc)) 871 965 { 872 if ( pImage->Socket == NIL_RTSOCKET)966 if (!iscsiIsClientConnected(pImage)) 873 967 rc = iscsiTransportConnect(pImage); 874 968 } … … 893 987 894 988 LogFlowFunc(("(%s:%d)\n", pImage->pszHostname, pImage->uPort)); 895 if ( pImage->Socket != NIL_RTSOCKET)989 if (iscsiIsClientConnected(pImage)) 896 990 { 897 991 rc = pImage->pInterfaceNetCallbacks->pfnClientClose(pImage->Socket); 898 pImage->Socket = NIL_RTSOCKET;899 992 } 900 993 else … … 912 1005 * @param pImage The iSCSI connection state to be used. 913 1006 */ 914 static int iscsiAttach( PISCSIIMAGE pImage)1007 static int iscsiAttach(void *pvUser) 915 1008 { 916 1009 int rc; … … 932 1025 uint32_t aResBHS[12]; 933 1026 char *pszNext; 1027 PISCSIIMAGE pImage = (PISCSIIMAGE)pvUser; 934 1028 935 1029 bool fParameterNeg = true;; … … 966 1060 967 1061 restart: 968 if ( pImage->Socket == NIL_RTSOCKET)1062 if (!iscsiIsClientConnected(pImage)) 969 1063 { 970 1064 rc = iscsiTransportOpen(pImage); … … 1110 1204 cnISCSIRes++; 1111 1205 1112 rc = iscsiRecvPDU(pImage, itt, aISCSIRes, cnISCSIRes );1206 rc = iscsiRecvPDU(pImage, itt, aISCSIRes, cnISCSIRes, true); 1113 1207 if (RT_FAILURE(rc)) 1114 1208 break; … … 1351 1445 * @param pImage The iSCSI connection state to be used. 1352 1446 */ 1353 static int iscsiDetach( PISCSIIMAGE pImage)1447 static int iscsiDetach(void *pvUser) 1354 1448 { 1355 1449 int rc; … … 1358 1452 ISCSIREQ aISCSIReq[4]; 1359 1453 uint32_t aReqBHS[12]; 1454 PISCSIIMAGE pImage = (PISCSIIMAGE)pvUser; 1455 1360 1456 LogFlowFunc(("entering\n")); 1361 1457 … … 1399 1495 aISCSIRes.pvSeg = aResBHS; 1400 1496 aISCSIRes.cbSeg = sizeof(aResBHS); 1401 rc = iscsiRecvPDU(pImage, itt, &aISCSIRes, 1 );1497 rc = iscsiRecvPDU(pImage, itt, &aISCSIRes, 1, true); 1402 1498 if (RT_SUCCESS(rc)) 1403 1499 { … … 1557 1653 cnISCSIRes++; 1558 1654 1559 rc = iscsiRecvPDU(pImage, itt, aISCSIRes, cnISCSIRes );1655 rc = iscsiRecvPDU(pImage, itt, aISCSIRes, cnISCSIRes, true); 1560 1656 if (RT_FAILURE(rc)) 1561 1657 break; … … 1736 1832 * @param cnRes Number of valid iSCSI response sections in the array. 1737 1833 */ 1738 static int iscsiRecvPDU(PISCSIIMAGE pImage, uint32_t itt, PISCSIRES paRes, uint32_t cnRes )1834 static int iscsiRecvPDU(PISCSIIMAGE pImage, uint32_t itt, PISCSIRES paRes, uint32_t cnRes, bool fSelect) 1739 1835 { 1740 1836 int rc = VINF_SUCCESS; … … 1745 1841 aResBuf.pvSeg = pImage->pvRecvPDUBuf; 1746 1842 aResBuf.cbSeg = pImage->cbRecvPDUBuf; 1747 rc = iscsiTransportRead(pImage, &aResBuf, 1 );1843 rc = iscsiTransportRead(pImage, &aResBuf, 1, fSelect); 1748 1844 if (RT_FAILURE(rc)) 1749 1845 { … … 1828 1924 } 1829 1925 /* Finally check whether the received PDU matches what the caller wants. */ 1830 if (itt == pcvResSeg[4]) 1926 if ( itt == pcvResSeg[4] 1927 && itt != ISCSI_TASK_TAG_RSVD) 1831 1928 { 1832 1929 /* Copy received PDU (one segment) to caller-provided buffers. */ … … 1888 1985 1889 1986 iscsiSendPDU(pImage, aISCSIReq, cnISCSIReq, ISCSIPDU_NO_REATTACH); 1987 /* Break if the caller wanted to process the NOP-in only. */ 1988 if (itt == ISCSI_TASK_TAG_RSVD) 1989 break; 1890 1990 } 1891 1991 } … … 2271 2371 2272 2372 /** 2373 * Internal. - Wrapper around the extended select callback of the net interface. 2374 */ 2375 DECLINLINE(int) iscsiIoThreadWait(PISCSIIMAGE pImage, RTMSINTERVAL cMillies, uint32_t *pfEvents) 2376 { 2377 return pImage->pInterfaceNetCallbacks->pfnSelectOneEx(pImage->Socket, pfEvents, cMillies); 2378 } 2379 2380 /** 2381 * Internal. - Pokes a thread waiting for I/O. 2382 */ 2383 DECLINLINE(int) iscsiIoThreadPoke(PISCSIIMAGE pImage) 2384 { 2385 return pImage->pInterfaceNetCallbacks->pfnPoke(pImage->Socket); 2386 } 2387 2388 /** 2389 * Internal. - Get the next request from the queue. 2390 */ 2391 DECLINLINE(PISCSICMD) iscsiCmdGet(PISCSIIMAGE pImage) 2392 { 2393 int rc; 2394 PISCSICMD pIScsiCmd = NULL; 2395 2396 rc = RTSemMutexRequest(pImage->MutexReqQueue, RT_INDEFINITE_WAIT); 2397 AssertRC(rc); 2398 2399 pIScsiCmd = pImage->pScsiReqQueue; 2400 if (pIScsiCmd) 2401 { 2402 pImage->pScsiReqQueue = pIScsiCmd->pNext; 2403 pIScsiCmd->pNext = NULL; 2404 } 2405 2406 rc = RTSemMutexRelease(pImage->MutexReqQueue); 2407 AssertRC(rc); 2408 2409 return pIScsiCmd; 2410 } 2411 2412 2413 /** 2414 * Internal. - Adds the given command to the queue. 2415 */ 2416 DECLINLINE(int) iscsiCmdPut(PISCSIIMAGE pImage, PISCSICMD pIScsiCmd) 2417 { 2418 int rc = RTSemMutexRequest(pImage->MutexReqQueue, RT_INDEFINITE_WAIT); 2419 AssertRC(rc); 2420 2421 pIScsiCmd->pNext = pImage->pScsiReqQueue; 2422 pImage->pScsiReqQueue = pIScsiCmd; 2423 2424 rc = RTSemMutexRelease(pImage->MutexReqQueue); 2425 AssertRC(rc); 2426 2427 iscsiIoThreadPoke(pImage); 2428 2429 /* Wait if the request is synchronous. */ 2430 if (pIScsiCmd->fSync) 2431 { 2432 rc = RTSemEventWait(pIScsiCmd->Type.Sync.EventSem, RT_INDEFINITE_WAIT); 2433 AssertRC(rc); 2434 rc = pIScsiCmd->Type.Sync.rcCmd; 2435 } 2436 else 2437 rc = VINF_SUCCESS; 2438 2439 return rc; 2440 } 2441 2442 /** 2443 * Internal. - Completes the request with the appropriate action. 2444 * Synchronous requests are completed with waking up the thread 2445 * and asynchronous ones by continuing the associated I/O context. 2446 */ 2447 static void iscsiCmdComplete(PISCSICMD pIScsiCmd, int rcCmd) 2448 { 2449 if (pIScsiCmd->fSync) 2450 { 2451 int rc; 2452 2453 /* Store completion code */ 2454 pIScsiCmd->Type.Sync.rcCmd = rcCmd; 2455 2456 /* 2457 * Wakeup the waiting thread. We are NOT allowed to touch the request 2458 * beyond this call. 2459 */ 2460 rc = RTSemEventSignal(pIScsiCmd->Type.Sync.EventSem); 2461 AssertRC(rc); 2462 } 2463 else 2464 AssertMsgFailed(("Not implemented yet\n")); 2465 } 2466 2467 /** 2468 * Internal. Main iSCSI I/O worker. 2469 */ 2470 static DECLCALLBACK(int) iscsiIoThreadWorker(RTTHREAD ThreadSelf, void *pvUser) 2471 { 2472 PISCSIIMAGE pImage = (PISCSIIMAGE)pvUser; 2473 2474 while (pImage->fRunning) 2475 { 2476 uint32_t fEvents = 0; 2477 int rc; 2478 2479 /* Wait for work or for data from the target. */ 2480 rc = iscsiIoThreadWait(pImage, RT_INDEFINITE_WAIT, &fEvents); 2481 if (rc == VERR_INTERRUPTED) 2482 { 2483 /* Check the queue. */ 2484 PISCSICMD pIScsiCmd = iscsiCmdGet(pImage); 2485 2486 while (pIScsiCmd) 2487 { 2488 switch (pIScsiCmd->enmCmdType) 2489 { 2490 case ISCSICMDTYPE_REQ: 2491 { 2492 rc = iscsiCommand(pImage, pIScsiCmd->CmdType.ScsiReq.pScsiReq); 2493 break; 2494 } 2495 case ISCSICMDTYPE_EXEC: 2496 { 2497 rc = pIScsiCmd->CmdType.Exec.pfnExec(pIScsiCmd->CmdType.Exec.pvUser); 2498 break; 2499 } 2500 default: 2501 AssertMsgFailed(("Invalid command type %d\n", pIScsiCmd->enmCmdType)); 2502 } 2503 2504 iscsiCmdComplete(pIScsiCmd, rc); 2505 pIScsiCmd = iscsiCmdGet(pImage); 2506 } 2507 } 2508 else if (RT_SUCCESS(rc)) 2509 { 2510 /* 2511 * There is data on the socket. 2512 * 2513 * @todo: This will only handle NOP-IN requests. Check other requests. 2514 */ 2515 if (fEvents & VD_INTERFACETCPNET_EVT_READ) 2516 { 2517 rc = iscsiRecvPDU(pImage, ISCSI_TASK_TAG_RSVD, NULL, 0, false); 2518 if (RT_FAILURE(rc)) 2519 LogRel(("iSCSI: Handling incoming request failed %Rrc\n", rc)); 2520 } 2521 else 2522 LogRel(("iSCSI: Received unexpected event %#x\n", fEvents)); 2523 } 2524 else 2525 { 2526 LogRel(("iSCSI: Waiting for I/O failed rc=%Rrc\n", rc)); 2527 } 2528 } 2529 2530 return VINF_SUCCESS; 2531 } 2532 2533 /** 2534 * Internal. - Enqueues a request in a synchronous fashion 2535 * i.e. returns when the request completed. 2536 */ 2537 static int iscsiCommandSync(PISCSIIMAGE pImage, PSCSIREQ pScsiReq, bool fRetry, int rcSense) 2538 { 2539 int rc; 2540 2541 if (pImage->fExtendedSelectSupported) 2542 { 2543 ISCSICMD IScsiCmd; 2544 2545 /* Init the command structure. */ 2546 IScsiCmd.pNext = NULL; 2547 IScsiCmd.enmCmdType = ISCSICMDTYPE_REQ; 2548 IScsiCmd.fSync = true; 2549 IScsiCmd.Type.Sync.rcCmd = VINF_SUCCESS; 2550 IScsiCmd.CmdType.ScsiReq.pScsiReq = pScsiReq; 2551 2552 /* Create event semaphore. */ 2553 rc = RTSemEventCreate(&IScsiCmd.Type.Sync.EventSem); 2554 if (RT_FAILURE(rc)) 2555 return rc; 2556 2557 if (fRetry) 2558 { 2559 for (unsigned i = 0; i < 10; i++) 2560 { 2561 rc = iscsiCmdPut(pImage, &IScsiCmd); 2562 if ( (RT_SUCCESS(rc) && !pScsiReq->cbSense) 2563 || RT_FAILURE(rc)) 2564 break; 2565 rc = rcSense; 2566 } 2567 } 2568 else 2569 { 2570 rc = iscsiCmdPut(pImage, &IScsiCmd); 2571 if (RT_SUCCESS(rc) && pScsiReq->cbSense > 0) 2572 rc = rcSense; 2573 } 2574 2575 RTSemEventDestroy(IScsiCmd.Type.Sync.EventSem); 2576 } 2577 else 2578 { 2579 if (fRetry) 2580 { 2581 for (unsigned i = 0; i < 10; i++) 2582 { 2583 rc = iscsiCommand(pImage, pScsiReq); 2584 if ( (RT_SUCCESS(rc) && !pScsiReq->cbSense) 2585 || RT_FAILURE(rc)) 2586 break; 2587 rc = rcSense; 2588 } 2589 } 2590 else 2591 { 2592 rc = iscsiCommand(pImage, pScsiReq); 2593 if (RT_SUCCESS(rc) && pScsiReq->cbSense > 0) 2594 rc = rcSense; 2595 } 2596 } 2597 2598 return rc; 2599 } 2600 2601 /** 2602 * Internal. - Executes a given function in a synchronous fashion 2603 * on the I/O thread if available. 2604 */ 2605 static int iscsiExecSync(PISCSIIMAGE pImage, PFNISCSIEXEC pfnExec, void *pvUser) 2606 { 2607 int rc; 2608 2609 if (pImage->fExtendedSelectSupported) 2610 { 2611 ISCSICMD IScsiCmd; 2612 2613 /* Init the command structure. */ 2614 IScsiCmd.pNext = NULL; 2615 IScsiCmd.enmCmdType = ISCSICMDTYPE_EXEC; 2616 IScsiCmd.fSync = true; 2617 IScsiCmd.Type.Sync.rcCmd = VINF_SUCCESS; 2618 IScsiCmd.CmdType.Exec.pfnExec = pfnExec; 2619 IScsiCmd.CmdType.Exec.pvUser = pvUser; 2620 2621 /* Create event semaphore. */ 2622 rc = RTSemEventCreate(&IScsiCmd.Type.Sync.EventSem); 2623 if (RT_FAILURE(rc)) 2624 return rc; 2625 2626 rc = iscsiCmdPut(pImage, &IScsiCmd); 2627 RTSemEventDestroy(IScsiCmd.Type.Sync.EventSem); 2628 } 2629 else 2630 { 2631 /* No I/O thread, execute in the current thread. */ 2632 rc = pfnExec(pvUser); 2633 } 2634 2635 return rc; 2636 } 2637 2638 /** 2273 2639 * Internal. Free all allocated space for representing an image, and optionally 2274 2640 * delete the image from disk. … … 2283 2649 /* Detaching only makes sense when the mutex is there. Otherwise the 2284 2650 * failure happened long before we could attach to the target. */ 2285 iscsi Detach(pImage);2651 iscsiExecSync(pImage, iscsiDetach, pImage); 2286 2652 RTSemMutexDestroy(pImage->Mutex); 2287 2653 pImage->Mutex = NIL_RTSEMMUTEX; 2654 } 2655 if (pImage->hThreadIo != NIL_RTTHREAD) 2656 { 2657 int rc; 2658 2659 ASMAtomicXchgBool(&pImage->fRunning, false); 2660 rc = iscsiIoThreadPoke(pImage); 2661 AssertRC(rc); 2662 2663 /* Wait for the thread to terminate. */ 2664 rc = RTThreadWait(pImage->hThreadIo, RT_INDEFINITE_WAIT, NULL); 2665 AssertRC(rc); 2666 } 2667 /* Destroy the socket. */ 2668 if (pImage->Socket != NIL_VDSOCKET) 2669 { 2670 pImage->pInterfaceNetCallbacks->pfnSocketDestroy(pImage->Socket); 2671 } 2672 if (pImage->MutexReqQueue != NIL_RTSEMMUTEX) 2673 { 2674 RTSemMutexDestroy(pImage->MutexReqQueue); 2675 pImage->MutexReqQueue = NIL_RTSEMMUTEX; 2288 2676 } 2289 2677 if (pImage->pszTargetName) … … 2391 2779 } 2392 2780 pImage->Mutex = NIL_RTSEMMUTEX; 2781 pImage->MutexReqQueue = NIL_RTSEMMUTEX; 2393 2782 rc = RTSemMutexCreate(&pImage->Mutex); 2783 if (RT_FAILURE(rc)) 2784 goto out; 2785 2786 rc = RTSemMutexCreate(&pImage->MutexReqQueue); 2394 2787 if (RT_FAILURE(rc)) 2395 2788 goto out; … … 2534 2927 pImage->pszHostname = NULL; 2535 2928 pImage->uPort = 0; 2536 pImage->Socket = NIL_ RTSOCKET;2929 pImage->Socket = NIL_VDSOCKET; 2537 2930 /* Query the iSCSI lower level configuration. */ 2538 2931 rc = VDCFGQueryU32Def(pImage->pInterfaceConfigCallbacks, … … 2565 2958 } 2566 2959 2960 /* Create the socket structure. */ 2961 rc = pImage->pInterfaceNetCallbacks->pfnSocketCreate(VD_INTERFACETCPNET_CONNECT_EXTENDED_SELECT, 2962 &pImage->Socket); 2963 if (RT_SUCCESS(rc)) 2964 { 2965 pImage->fExtendedSelectSupported = true; 2966 pImage->fRunning = true; 2967 rc = RTThreadCreate(&pImage->hThreadIo, iscsiIoThreadWorker, pImage, 0, 2968 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "iSCSI-Io"); 2969 if (RT_FAILURE(rc)) 2970 { 2971 LogFunc(("Creating iSCSI I/O thread failed rc=%Rrc\n", rc)); 2972 goto out; 2973 } 2974 } 2975 else if (rc == VERR_NOT_SUPPORTED) 2976 { 2977 /* Async I/O is not supported without extended select. */ 2978 if ((uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)) 2979 { 2980 LogFunc(("Extended select is not supported by the interface but async I/O is requested -> %Rrc\n", rc)); 2981 goto out; 2982 } 2983 else 2984 { 2985 pImage->fExtendedSelectSupported = false; 2986 rc = pImage->pInterfaceNetCallbacks->pfnSocketCreate(0, &pImage->Socket); 2987 if (RT_FAILURE(rc)) 2988 { 2989 LogFunc(("Creating socket failed -> %Rrc\n", rc)); 2990 goto out; 2991 } 2992 } 2993 } 2994 else 2995 { 2996 LogFunc(("Creating socket failed -> %Rrc\n", rc)); 2997 goto out; 2998 } 2999 2567 3000 /* 2568 3001 * Attach to the iSCSI target. This implicitly establishes the iSCSI 2569 3002 * transport connection. 2570 3003 */ 2571 rc = iscsiAttach(pImage); 2572 3004 rc = iscsiExecSync(pImage, iscsiAttach, pImage); 2573 3005 if (RT_FAILURE(rc)) 2574 3006 { … … 2611 3043 sr.pvSense = sense; 2612 3044 2613 rc = iscsiCommand (pImage, &sr);3045 rc = iscsiCommandSync(pImage, &sr, false, VERR_INVALID_STATE); 2614 3046 if (RT_FAILURE(rc)) 2615 3047 { … … 2639 3071 sr.pvSense = sense; 2640 3072 2641 for (unsigned i = 0; i < 10; i++) 2642 { 2643 rc = iscsiCommand(pImage, &sr); 2644 if ( (RT_SUCCESS(rc) && !sr.cbSense) 2645 || RT_FAILURE(rc)) 2646 break; 2647 rc = VERR_INVALID_STATE; 2648 } 3073 rc = iscsiCommandSync(pImage, &sr, true /* fRetry */, VERR_INVALID_STATE); 2649 3074 if (RT_SUCCESS(rc)) 2650 3075 { … … 2690 3115 sr.pvSense = sense; 2691 3116 2692 for (unsigned i = 0; i < 10; i++) 2693 { 2694 rc = iscsiCommand(pImage, &sr); 2695 if ( (RT_SUCCESS(rc) && !sr.cbSense) 2696 || RT_FAILURE(rc)) 2697 break; 2698 rc = VERR_INVALID_STATE; 2699 } 3117 rc = iscsiCommandSync(pImage, &sr, true /* fRetry */, VERR_INVALID_STATE); 2700 3118 if (RT_SUCCESS(rc)) 2701 3119 { … … 2705 3123 goto out; 2706 3124 } 2707 }3125 } 2708 3126 else 2709 3127 { … … 2733 3151 sr.pvSense = sense; 2734 3152 2735 rc = iscsiCommand (pImage, &sr);3153 rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS); 2736 3154 if ( RT_SUCCESS(rc) 2737 3155 && sr.status == SCSI_STATUS_OK) … … 2775 3193 sr.pvSense = sense; 2776 3194 2777 rc = iscsiCommand (pImage, &sr);3195 rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS); 2778 3196 if (RT_SUCCESS(rc)) 2779 3197 { … … 2823 3241 sr.cbSense = sizeof(sense); 2824 3242 sr.pvSense = sense; 2825 rc = iscsiCommand (pImage, &sr);3243 rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS); 2826 3244 if ( RT_SUCCESS(rc) 2827 3245 && (sr.status == SCSI_STATUS_OK) … … 2863 3281 sr.pvSense = sense; 2864 3282 sr.status = 0; 2865 rc = iscsiCommand (pImage, &sr);3283 rc = iscsiCommandSync(pImage, &sr, false /* fRetry */, VINF_SUCCESS); 2866 3284 if ( RT_SUCCESS(rc) 2867 3285 && (sr.status == SCSI_STATUS_OK)) … … 2887 3305 } 2888 3306 2889 2890 3307 out: 2891 3308 if (RT_FAILURE(rc)) … … 3074 3491 sr.pvSense = sense; 3075 3492 3076 for (unsigned i = 0; i < 10; i++) 3077 { 3078 rc = iscsiCommand(pImage, &sr); 3079 if ( (RT_SUCCESS(rc) && !sr.cbSense) 3080 || RT_FAILURE(rc)) 3081 break; 3082 rc = VERR_READ_ERROR; 3083 } 3493 rc = iscsiCommandSync(pImage, &sr, true, VERR_READ_ERROR); 3084 3494 if (RT_FAILURE(rc)) 3085 3495 { … … 3155 3565 sr.pvSense = sense; 3156 3566 3157 for (unsigned i = 0; i < 10; i++) 3158 { 3159 rc = iscsiCommand(pImage, &sr); 3160 if ( (RT_SUCCESS(rc) && !sr.cbSense) 3161 || RT_FAILURE(rc)) 3162 break; 3163 rc = VERR_WRITE_ERROR; 3164 } 3567 rc = iscsiCommandSync(pImage, &sr, true, VERR_WRITE_ERROR); 3165 3568 if (RT_FAILURE(rc)) 3166 3569 { … … 3211 3614 sr.pvSense = sense; 3212 3615 3213 rc = iscsiCommand (pImage, &sr);3616 rc = iscsiCommandSync(pImage, &sr, false, VINF_SUCCESS); 3214 3617 if (RT_FAILURE(rc)) 3215 3618 AssertMsgFailed(("iscsiCommand(%s) -> %Rrc\n", pImage->pszTargetName, rc)); -
trunk/src/VBox/Main/MediumImpl.cpp
r31068 r31098 169 169 }; 170 170 171 typedef struct VDSOCKETINT 172 { 173 /** Socket handle. */ 174 RTSOCKET hSocket; 175 } VDSOCKETINT, *PVDSOCKETINT; 176 171 177 //////////////////////////////////////////////////////////////////////////////// 172 178 // … … 672 678 m->vdIfCallsTcpNet.cbSize = sizeof(VDINTERFACETCPNET); 673 679 m->vdIfCallsTcpNet.enmInterface = VDINTERFACETYPE_TCPNET; 674 m->vdIfCallsTcpNet.pfnClientConnect = RTTcpClientConnect; 675 m->vdIfCallsTcpNet.pfnClientClose = RTTcpClientClose; 676 m->vdIfCallsTcpNet.pfnSelectOne = RTTcpSelectOne; 677 m->vdIfCallsTcpNet.pfnRead = RTTcpRead; 678 m->vdIfCallsTcpNet.pfnWrite = RTTcpWrite; 679 m->vdIfCallsTcpNet.pfnSgWrite = RTTcpSgWrite; 680 m->vdIfCallsTcpNet.pfnFlush = RTTcpFlush; 681 m->vdIfCallsTcpNet.pfnSetSendCoalescing = RTTcpSetSendCoalescing; 682 m->vdIfCallsTcpNet.pfnGetLocalAddress = RTTcpGetLocalAddress; 683 m->vdIfCallsTcpNet.pfnGetPeerAddress = RTTcpGetPeerAddress; 680 m->vdIfCallsTcpNet.pfnSocketCreate = vdTcpSocketCreate; 681 m->vdIfCallsTcpNet.pfnSocketDestroy = vdTcpSocketDestroy; 682 m->vdIfCallsTcpNet.pfnClientConnect = vdTcpClientConnect; 683 m->vdIfCallsTcpNet.pfnClientClose = vdTcpClientClose; 684 m->vdIfCallsTcpNet.pfnIsClientConnected = vdTcpIsClientConnected; 685 m->vdIfCallsTcpNet.pfnSelectOne = vdTcpSelectOne; 686 m->vdIfCallsTcpNet.pfnRead = vdTcpRead; 687 m->vdIfCallsTcpNet.pfnWrite = vdTcpWrite; 688 m->vdIfCallsTcpNet.pfnSgWrite = vdTcpSgWrite; 689 m->vdIfCallsTcpNet.pfnFlush = vdTcpFlush; 690 m->vdIfCallsTcpNet.pfnSetSendCoalescing = vdTcpSetSendCoalescing; 691 m->vdIfCallsTcpNet.pfnGetLocalAddress = vdTcpGetLocalAddress; 692 m->vdIfCallsTcpNet.pfnGetPeerAddress = vdTcpGetPeerAddress; 693 m->vdIfCallsTcpNet.pfnSelectOneEx = NULL; 694 m->vdIfCallsTcpNet.pfnPoke = NULL; 684 695 685 696 /* Initialize the per-disk interface chain */ … … 5051 5062 } 5052 5063 5064 DECLCALLBACK(int) Medium::vdTcpSocketCreate(uint32_t fFlags, PVDSOCKET pSock) 5065 { 5066 PVDSOCKETINT pSocketInt = NULL; 5067 5068 if ((fFlags & VD_INTERFACETCPNET_CONNECT_EXTENDED_SELECT) != 0) 5069 return VERR_NOT_SUPPORTED; 5070 5071 pSocketInt = (PVDSOCKETINT)RTMemAllocZ(sizeof(VDSOCKETINT)); 5072 if (!pSocketInt) 5073 return VERR_NO_MEMORY; 5074 5075 pSocketInt->hSocket = NIL_RTSOCKET; 5076 *pSock = pSocketInt; 5077 return VINF_SUCCESS; 5078 } 5079 5080 DECLCALLBACK(int) Medium::vdTcpSocketDestroy(VDSOCKET Sock) 5081 { 5082 PVDSOCKETINT pSocketInt = (PVDSOCKETINT)Sock; 5083 5084 if (pSocketInt->hSocket != NIL_RTSOCKET) 5085 RTTcpClientClose(pSocketInt->hSocket); 5086 5087 RTMemFree(pSocketInt); 5088 5089 return VINF_SUCCESS; 5090 } 5091 5092 DECLCALLBACK(int) Medium::vdTcpClientConnect(VDSOCKET Sock, const char *pszAddress, uint32_t uPort) 5093 { 5094 PVDSOCKETINT pSocketInt = (PVDSOCKETINT)Sock; 5095 5096 return RTTcpClientConnect(pszAddress, uPort, &pSocketInt->hSocket); 5097 } 5098 5099 DECLCALLBACK(int) Medium::vdTcpClientClose(VDSOCKET Sock) 5100 { 5101 int rc = VINF_SUCCESS; 5102 PVDSOCKETINT pSocketInt = (PVDSOCKETINT)Sock; 5103 5104 rc = RTTcpClientClose(pSocketInt->hSocket); 5105 pSocketInt->hSocket = NIL_RTSOCKET; 5106 return rc; 5107 } 5108 5109 DECLCALLBACK(bool) Medium::vdTcpIsClientConnected(VDSOCKET Sock) 5110 { 5111 PVDSOCKETINT pSocketInt = (PVDSOCKETINT)Sock; 5112 return pSocketInt->hSocket != NIL_RTSOCKET; 5113 } 5114 5115 DECLCALLBACK(int) Medium::vdTcpSelectOne(VDSOCKET Sock, RTMSINTERVAL cMillies) 5116 { 5117 PVDSOCKETINT pSocketInt = (PVDSOCKETINT)Sock; 5118 return RTTcpSelectOne(pSocketInt->hSocket, cMillies); 5119 } 5120 5121 DECLCALLBACK(int) Medium::vdTcpRead(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 5122 { 5123 PVDSOCKETINT pSocketInt = (PVDSOCKETINT)Sock; 5124 return RTTcpRead(pSocketInt->hSocket, pvBuffer, cbBuffer, pcbRead); 5125 } 5126 5127 DECLCALLBACK(int) Medium::vdTcpWrite(VDSOCKET Sock, const void *pvBuffer, size_t cbBuffer) 5128 { 5129 PVDSOCKETINT pSocketInt = (PVDSOCKETINT)Sock; 5130 return RTTcpWrite(pSocketInt->hSocket, pvBuffer, cbBuffer); 5131 } 5132 5133 DECLCALLBACK(int) Medium::vdTcpSgWrite(VDSOCKET Sock, PCRTSGBUF pSgBuf) 5134 { 5135 PVDSOCKETINT pSocketInt = (PVDSOCKETINT)Sock; 5136 return RTTcpSgWrite(pSocketInt->hSocket, pSgBuf); 5137 } 5138 5139 DECLCALLBACK(int) Medium::vdTcpFlush(VDSOCKET Sock) 5140 { 5141 PVDSOCKETINT pSocketInt = (PVDSOCKETINT)Sock; 5142 return RTTcpFlush(pSocketInt->hSocket); 5143 } 5144 5145 DECLCALLBACK(int) Medium::vdTcpSetSendCoalescing(VDSOCKET Sock, bool fEnable) 5146 { 5147 PVDSOCKETINT pSocketInt = (PVDSOCKETINT)Sock; 5148 return RTTcpSetSendCoalescing(pSocketInt->hSocket, fEnable); 5149 } 5150 5151 DECLCALLBACK(int) Medium::vdTcpGetLocalAddress(VDSOCKET Sock, PRTNETADDR pAddr) 5152 { 5153 PVDSOCKETINT pSocketInt = (PVDSOCKETINT)Sock; 5154 return RTTcpGetLocalAddress(pSocketInt->hSocket, pAddr); 5155 } 5156 5157 DECLCALLBACK(int) Medium::vdTcpGetPeerAddress(VDSOCKET Sock, PRTNETADDR pAddr) 5158 { 5159 PVDSOCKETINT pSocketInt = (PVDSOCKETINT)Sock; 5160 return RTTcpGetPeerAddress(pSocketInt->hSocket, pAddr); 5161 } 5162 5163 5053 5164 /** 5054 5165 * Starts a new thread driven by the appropriate Medium::Task::handler() method. -
trunk/src/VBox/Main/include/MediumImpl.h
r31063 r31098 20 20 #ifndef ____H_MEDIUMIMPL 21 21 #define ____H_MEDIUMIMPL 22 23 #include <VBox/VBoxHDD.h> 22 24 23 25 #include "VirtualBoxBase.h" … … 255 257 char *pszValue, size_t cchValue); 256 258 259 static DECLCALLBACK(int) vdTcpSocketCreate(uint32_t fFlags, PVDSOCKET pSock); 260 static DECLCALLBACK(int) vdTcpSocketDestroy(VDSOCKET Sock); 261 static DECLCALLBACK(int) vdTcpClientConnect(VDSOCKET Sock, const char *pszAddress, uint32_t uPort); 262 static DECLCALLBACK(int) vdTcpClientClose(VDSOCKET Sock); 263 static DECLCALLBACK(bool) vdTcpIsClientConnected(VDSOCKET Sock); 264 static DECLCALLBACK(int) vdTcpSelectOne(VDSOCKET Sock, RTMSINTERVAL cMillies); 265 static DECLCALLBACK(int) vdTcpRead(VDSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead); 266 static DECLCALLBACK(int) vdTcpWrite(VDSOCKET Sock, const void *pvBuffer, size_t cbBuffer); 267 static DECLCALLBACK(int) vdTcpSgWrite(VDSOCKET Sock, PCRTSGBUF pSgBuf); 268 static DECLCALLBACK(int) vdTcpFlush(VDSOCKET Sock); 269 static DECLCALLBACK(int) vdTcpSetSendCoalescing(VDSOCKET Sock, bool fEnable); 270 static DECLCALLBACK(int) vdTcpGetLocalAddress(VDSOCKET Sock, PRTNETADDR pAddr); 271 static DECLCALLBACK(int) vdTcpGetPeerAddress(VDSOCKET Sock, PRTNETADDR pAddr); 272 257 273 class Task; 258 274 class CreateBaseTask;
Note:
See TracChangeset
for help on using the changeset viewer.