- Timestamp:
- Aug 20, 2010 10:04:47 AM (14 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/FTM.cpp
r31807 r31809 36 36 #include <iprt/tcp.h> 37 37 #include <iprt/semaphore.h> 38 #include <iprt/asm.h> 39 40 /******************************************************************************* 41 * Structures and Typedefs * 42 *******************************************************************************/ 43 44 /** 45 * TCP stream header. 46 * 47 * This is an extra layer for fixing the problem with figuring out when the SSM 48 * stream ends. 49 */ 50 typedef struct FTMTCPHDR 51 { 52 /** Magic value. */ 53 uint32_t u32Magic; 54 /** The size of the data block following this header. 55 * 0 indicates the end of the stream, while UINT32_MAX indicates 56 * cancelation. */ 57 uint32_t cb; 58 } FTMTCPHDR; 59 /** Magic value for TELEPORTERTCPHDR::u32Magic. (Egberto Gismonti Amin) */ 60 #define FTMTCPHDR_MAGIC UINT32_C(0x19471205) 61 /** The max block size. */ 62 #define FTMTCPHDR_MAX_SIZE UINT32_C(0x00fffff8) 38 63 39 64 /******************************************************************************* … … 232 257 return VERR_INTERNAL_ERROR_3; 233 258 } 259 260 /** 261 * @copydoc SSMSTRMOPS::pfnWrite 262 */ 263 static DECLCALLBACK(int) ftmR3TcpOpWrite(void *pvUser, uint64_t offStream, const void *pvBuf, size_t cbToWrite) 264 { 265 PVM pVM = (PVM)pvUser; 266 267 AssertReturn(cbToWrite > 0, VINF_SUCCESS); 268 AssertReturn(cbToWrite < UINT32_MAX, VERR_OUT_OF_RANGE); 269 AssertReturn(pVM->fFaultTolerantMaster, VERR_INVALID_HANDLE); 270 271 for (;;) 272 { 273 FTMTCPHDR Hdr; 274 Hdr.u32Magic = FTMTCPHDR_MAGIC; 275 Hdr.cb = RT_MIN((uint32_t)cbToWrite, FTMTCPHDR_MAX_SIZE); 276 int rc = RTTcpSgWriteL(pVM->ftm.s.hSocket, 2, &Hdr, sizeof(Hdr), pvBuf, (size_t)Hdr.cb); 277 if (RT_FAILURE(rc)) 278 { 279 LogRel(("FTSync/TCP: Write error: %Rrc (cb=%#x)\n", rc, Hdr.cb)); 280 return rc; 281 } 282 pVM->ftm.s.syncstate.uOffStream += Hdr.cb; 283 if (Hdr.cb == cbToWrite) 284 return VINF_SUCCESS; 285 286 /* advance */ 287 cbToWrite -= Hdr.cb; 288 pvBuf = (uint8_t const *)pvBuf + Hdr.cb; 289 } 290 } 291 292 293 /** 294 * Selects and poll for close condition. 295 * 296 * We can use a relatively high poll timeout here since it's only used to get 297 * us out of error paths. In the normal cause of events, we'll get a 298 * end-of-stream header. 299 * 300 * @returns VBox status code. 301 * 302 * @param pState The teleporter state data. 303 */ 304 static int ftmR3TcpReadSelect(PVM pVM) 305 { 306 int rc; 307 do 308 { 309 rc = RTTcpSelectOne(pVM->ftm.s.hSocket, 1000); 310 if (RT_FAILURE(rc) && rc != VERR_TIMEOUT) 311 { 312 pVM->ftm.s.syncstate.fIOError = true; 313 LogRel(("FTSync/TCP: Header select error: %Rrc\n", rc)); 314 break; 315 } 316 if (pVM->ftm.s.syncstate.fStopReading) 317 { 318 rc = VERR_EOF; 319 break; 320 } 321 } while (rc == VERR_TIMEOUT); 322 return rc; 323 } 324 325 326 /** 327 * @copydoc SSMSTRMOPS::pfnRead 328 */ 329 static DECLCALLBACK(int) ftmR3TcpOpRead(void *pvUser, uint64_t offStream, void *pvBuf, size_t cbToRead, size_t *pcbRead) 330 { 331 PVM pVM = (PVM)pvUser; 332 AssertReturn(!pVM->fFaultTolerantMaster, VERR_INVALID_HANDLE); 333 334 for (;;) 335 { 336 int rc; 337 338 /* 339 * Check for various conditions and may have been signalled. 340 */ 341 if (pVM->ftm.s.syncstate.fEndOfStream) 342 return VERR_EOF; 343 if (pVM->ftm.s.syncstate.fStopReading) 344 return VERR_EOF; 345 if (pVM->ftm.s.syncstate.fIOError) 346 return VERR_IO_GEN_FAILURE; 347 348 /* 349 * If there is no more data in the current block, read the next 350 * block header. 351 */ 352 if (!pVM->ftm.s.syncstate.cbReadBlock) 353 { 354 rc = ftmR3TcpReadSelect(pVM); 355 if (RT_FAILURE(rc)) 356 return rc; 357 FTMTCPHDR Hdr; 358 rc = RTTcpRead(pVM->ftm.s.hSocket, &Hdr, sizeof(Hdr), NULL); 359 if (RT_FAILURE(rc)) 360 { 361 pVM->ftm.s.syncstate.fIOError = true; 362 LogRel(("FTSync/TCP: Header read error: %Rrc\n", rc)); 363 return rc; 364 } 365 366 if (RT_UNLIKELY( Hdr.u32Magic != FTMTCPHDR_MAGIC 367 || Hdr.cb > FTMTCPHDR_MAX_SIZE 368 || Hdr.cb == 0)) 369 { 370 if ( Hdr.u32Magic == FTMTCPHDR_MAGIC 371 && ( Hdr.cb == 0 372 || Hdr.cb == UINT32_MAX) 373 ) 374 { 375 pVM->ftm.s.syncstate.fEndOfStream = true; 376 pVM->ftm.s.syncstate.cbReadBlock = 0; 377 return Hdr.cb ? VERR_SSM_CANCELLED : VERR_EOF; 378 } 379 pVM->ftm.s.syncstate.fIOError = true; 380 LogRel(("FTSync/TCP: Invalid block: u32Magic=%#x cb=%#x\n", Hdr.u32Magic, Hdr.cb)); 381 return VERR_IO_GEN_FAILURE; 382 } 383 384 pVM->ftm.s.syncstate.cbReadBlock = Hdr.cb; 385 if (pVM->ftm.s.syncstate.fStopReading) 386 return VERR_EOF; 387 } 388 389 /* 390 * Read more data. 391 */ 392 rc = ftmR3TcpReadSelect(pVM); 393 if (RT_FAILURE(rc)) 394 return rc; 395 uint32_t cb = (uint32_t)RT_MIN(pVM->ftm.s.syncstate.cbReadBlock, cbToRead); 396 rc = RTTcpRead(pVM->ftm.s.hSocket, pvBuf, cb, pcbRead); 397 if (RT_FAILURE(rc)) 398 { 399 pVM->ftm.s.syncstate.fIOError = true; 400 LogRel(("FTSync/TCP: Data read error: %Rrc (cb=%#x)\n", rc, cb)); 401 return rc; 402 } 403 if (pcbRead) 404 { 405 cb = (uint32_t)*pcbRead; 406 pVM->ftm.s.syncstate.uOffStream += cb; 407 pVM->ftm.s.syncstate.cbReadBlock -= cb; 408 return VINF_SUCCESS; 409 } 410 pVM->ftm.s.syncstate.uOffStream += cb; 411 pVM->ftm.s.syncstate.cbReadBlock -= cb; 412 if (cbToRead == cb) 413 return VINF_SUCCESS; 414 415 /* Advance to the next block. */ 416 cbToRead -= cb; 417 pvBuf = (uint8_t *)pvBuf + cb; 418 } 419 } 420 421 422 /** 423 * @copydoc SSMSTRMOPS::pfnSeek 424 */ 425 static DECLCALLBACK(int) ftmR3TcpOpSeek(void *pvUser, int64_t offSeek, unsigned uMethod, uint64_t *poffActual) 426 { 427 return VERR_NOT_SUPPORTED; 428 } 429 430 431 /** 432 * @copydoc SSMSTRMOPS::pfnTell 433 */ 434 static DECLCALLBACK(uint64_t) ftmR3TcpOpTell(void *pvUser) 435 { 436 PVM pVM = (PVM)pvUser; 437 return pVM->ftm.s.syncstate.uOffStream; 438 } 439 440 441 /** 442 * @copydoc SSMSTRMOPS::pfnSize 443 */ 444 static DECLCALLBACK(int) ftmR3TcpOpSize(void *pvUser, uint64_t *pcb) 445 { 446 return VERR_NOT_SUPPORTED; 447 } 448 449 450 /** 451 * @copydoc SSMSTRMOPS::pfnIsOk 452 */ 453 static DECLCALLBACK(int) ftmR3TcpOpIsOk(void *pvUser) 454 { 455 PVM pVM = (PVM)pvUser; 456 457 if (pVM->fFaultTolerantMaster) 458 { 459 /* Poll for incoming NACKs and errors from the other side */ 460 int rc = RTTcpSelectOne(pVM->ftm.s.hSocket, 0); 461 if (rc != VERR_TIMEOUT) 462 { 463 if (RT_SUCCESS(rc)) 464 { 465 LogRel(("FTSync/TCP: Incoming data detect by IsOk, assuming it is a cancellation NACK.\n")); 466 rc = VERR_SSM_CANCELLED; 467 } 468 else 469 LogRel(("FTSync/TCP: RTTcpSelectOne -> %Rrc (IsOk).\n", rc)); 470 return rc; 471 } 472 } 473 474 return VINF_SUCCESS; 475 } 476 477 478 /** 479 * @copydoc SSMSTRMOPS::pfnClose 480 */ 481 static DECLCALLBACK(int) ftmR3TcpOpClose(void *pvUser, bool fCanceled) 482 { 483 PVM pVM = (PVM)pvUser; 484 485 if (pVM->fFaultTolerantMaster) 486 { 487 FTMTCPHDR EofHdr; 488 EofHdr.u32Magic = FTMTCPHDR_MAGIC; 489 EofHdr.cb = fCanceled ? UINT32_MAX : 0; 490 int rc = RTTcpWrite(pVM->ftm.s.hSocket, &EofHdr, sizeof(EofHdr)); 491 if (RT_FAILURE(rc)) 492 { 493 LogRel(("FTSync/TCP: EOF Header write error: %Rrc\n", rc)); 494 return rc; 495 } 496 } 497 else 498 { 499 ASMAtomicWriteBool(&pVM->ftm.s.syncstate.fStopReading, true); 500 } 501 502 return VINF_SUCCESS; 503 } 504 505 506 /** 507 * Method table for a TCP based stream. 508 */ 509 static SSMSTRMOPS const g_ftmR3TcpOps = 510 { 511 SSMSTRMOPS_VERSION, 512 ftmR3TcpOpWrite, 513 ftmR3TcpOpRead, 514 ftmR3TcpOpSeek, 515 ftmR3TcpOpTell, 516 ftmR3TcpOpSize, 517 ftmR3TcpOpIsOk, 518 ftmR3TcpOpClose, 519 SSMSTRMOPS_VERSION 520 }; 234 521 235 522 /** … … 507 794 AssertMsg(rc == VINF_SUCCESS, ("%Rrc\n", rc)); 508 795 796 /* Reset the sync state. */ 797 pVM->ftm.s.syncstate.uOffStream = 0; 798 pVM->ftm.s.syncstate.cbReadBlock = 0; 799 pVM->ftm.s.syncstate.fStopReading = false; 800 pVM->ftm.s.syncstate.fIOError = false; 801 pVM->ftm.s.syncstate.fEndOfStream = false; 802 803 /** @todo sync state + changed memory. */ 804 509 805 PDMCritSectLeave(&pVM->ftm.s.CritSect); 510 806 pVM->ftm.s.fCheckpointingActive = false; -
trunk/src/VBox/VMM/FTMInternal.h
r31789 r31809 55 55 RTSOCKET hSocket; 56 56 57 /** State sync. */ 58 struct 59 { 60 unsigned uOffStream; 61 unsigned cbReadBlock; 62 bool fStopReading; 63 bool fIOError; 64 bool fEndOfStream; 65 bool fAlignment[5]; 66 } syncstate; 67 57 68 struct 58 69 {
Note:
See TracChangeset
for help on using the changeset viewer.