Changeset 19562 in vbox for trunk/src/VBox/Runtime/r3/linux
- Timestamp:
- May 10, 2009 9:44:16 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/linux/fileaio-linux.cpp
r19371 r19562 190 190 * the structure! (see notes below) */ 191 191 LNXKAIOIOCB AioCB; 192 /** Current state the request is in. */ 193 RTFILEAIOREQSTATE enmState; 192 194 /** The I/O context this request is associated with. */ 193 195 aio_context_t AioContext; 194 196 /** Return code the request completed with. */ 195 197 int Rc; 196 /** Flag whether the request is in process or not. */197 bool fFinished;198 198 /** Number of bytes actually trasnfered. */ 199 199 size_t cbTransfered; … … 241 241 * Submits an array of I/O requests to the kernel. 242 242 */ 243 DECLINLINE(int) rtFileAsyncIoLinuxSubmit(aio_context_t AioContext, long cReqs, LNXKAIOIOCB **ppIoCB )243 DECLINLINE(int) rtFileAsyncIoLinuxSubmit(aio_context_t AioContext, long cReqs, LNXKAIOIOCB **ppIoCB, int *pcSubmitted) 244 244 { 245 245 int rc = syscall(__NR_io_submit, AioContext, cReqs, ppIoCB); … … 247 247 return RTErrConvertFromErrno(errno); 248 248 249 *pcSubmitted = rc; 250 249 251 return VINF_SUCCESS; 250 252 } … … 276 278 } 277 279 280 RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits) 281 { 282 int rc = VINF_SUCCESS; 283 AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER); 284 285 /* 286 * Check if the API is implemented by creating a 287 * completion port. 288 */ 289 aio_context_t AioContext = 0; 290 rc = rtFileAsyncIoLinuxCreate(1, &AioContext); 291 if (RT_FAILURE(rc)) 292 return rc; 293 294 rc = rtFileAsyncIoLinuxDestroy(AioContext); 295 if (RT_FAILURE(rc)) 296 return rc; 297 298 /* Supported - fill in the limits. The alignment is the only restriction. */ 299 pAioLimits->cReqsOutstandingMax = RTFILEAIO_UNLIMITED_REQS; 300 pAioLimits->cbBufferAlignment = 512; 301 302 return VINF_SUCCESS; 303 } 304 305 278 306 RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq) 279 307 { … … 287 315 return VERR_NO_MEMORY; 288 316 289 pReqInt->fFinished = false;290 317 pReqInt->pCtxInt = NULL; 291 318 pReqInt->u32Magic = RTFILEAIOREQ_MAGIC; 319 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 292 320 293 321 *phReq = (RTFILEAIOREQ)pReqInt; … … 296 324 297 325 298 RTDECL( void) RTFileAioReqDestroy(RTFILEAIOREQ hReq)326 RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq) 299 327 { 300 328 /* … … 302 330 */ 303 331 if (hReq == NIL_RTFILEAIOREQ) 304 return ;332 return VINF_SUCCESS; 305 333 PRTFILEAIOREQINTERNAL pReqInt = hReq; 306 RTFILEAIOREQ_VALID_RETURN_VOID(pReqInt); 334 RTFILEAIOREQ_VALID_RETURN(pReqInt); 335 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 307 336 308 337 /* … … 311 340 ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC); 312 341 RTMemFree(pReqInt); 342 return VINF_SUCCESS; 313 343 } 314 344 … … 327 357 PRTFILEAIOREQINTERNAL pReqInt = hReq; 328 358 RTFILEAIOREQ_VALID_RETURN(pReqInt); 359 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 329 360 Assert(hFile != NIL_RTFILE); 330 361 AssertPtr(pvBuf); … … 342 373 pReqInt->AioCB.pvUser = pvUser; 343 374 344 pReqInt->fFinished = false;345 375 pReqInt->pCtxInt = NULL; 376 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 346 377 347 378 return VINF_SUCCESS; … … 370 401 RTFILEAIOREQ_VALID_RETURN(pReqInt); 371 402 AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE); 403 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 372 404 373 405 /** @todo: Flushing is not neccessary on Linux because O_DIRECT is mandatory … … 397 429 PRTFILEAIOREQINTERNAL pReqInt = hReq; 398 430 RTFILEAIOREQ_VALID_RETURN(pReqInt); 431 RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED); 399 432 400 433 LNXKAIOIOEVENT AioEvent; … … 410 443 411 444 ASMAtomicDecS32(&pReqInt->pCtxInt->cRequests); 445 pReqInt->Rc = VERR_FILE_AIO_CANCELED; 446 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 412 447 return VINF_SUCCESS; 413 448 } … … 423 458 RTFILEAIOREQ_VALID_RETURN(pReqInt); 424 459 AssertPtrNull(pcbTransfered); 425 426 if (!pReqInt->fFinished) 427 return VERR_FILE_AIO_IN_PROGRESS; 460 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 461 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED); 428 462 429 463 if ( pcbTransfered … … 509 543 } 510 544 511 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs, size_t *pcReqs) 512 { 545 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) 546 { 547 int rc = VINF_SUCCESS; 548 513 549 /* 514 550 * Parameter validation. 515 551 */ 516 AssertPtrReturn(pcReqs, VERR_INVALID_POINTER);517 *pcReqs = 0;518 552 PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; 519 553 RTFILEAIOCTX_VALID_RETURN(pCtxInt); … … 521 555 AssertPtrReturn(pahReqs, VERR_INVALID_POINTER); 522 556 uint32_t i = cReqs; 557 PRTFILEAIOREQINTERNAL pReqInt = NULL; 523 558 524 559 /* … … 527 562 while (i-- > 0) 528 563 { 529 PRTFILEAIOREQINTERNAL pReqInt = pahReqs[i]; 530 RTFILEAIOREQ_VALID_RETURN(pReqInt); 564 pReqInt = pahReqs[i]; 565 if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt)) 566 { 567 /* Undo everything and stop submitting. */ 568 size_t iUndo = cReqs; 569 while (iUndo-- > i) 570 { 571 pReqInt = pahReqs[iUndo]; 572 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 573 pReqInt->pCtxInt = NULL; 574 } 575 return VERR_INVALID_HANDLE; 576 } 531 577 532 578 pReqInt->AioContext = pCtxInt->AioContext; 533 579 pReqInt->pCtxInt = pCtxInt; 580 RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); 534 581 } 535 582 536 /* 537 * Add the submitted requests to the counter 538 * to prevent destroying the context while 539 * it is still used. 540 */ 541 ASMAtomicAddS32(&pCtxInt->cRequests, cReqs); 542 543 /* 544 * We cast phReqs to the Linux iocb structure to avoid copying the requests 545 * into a temporary array. This is possible because the iocb structure is 546 * the first element in the request structure (see PRTFILEAIOCTXINTERNAL). 547 */ 548 int rc = rtFileAsyncIoLinuxSubmit(pCtxInt->AioContext, cReqs, (PLNXKAIOIOCB *)pahReqs); 549 if (RT_FAILURE(rc)) 550 ASMAtomicSubS32(&pCtxInt->cRequests, cReqs); 551 else 552 *pcReqs = cReqs; 583 do 584 { 585 /* 586 * We cast pahReqs to the Linux iocb structure to avoid copying the requests 587 * into a temporary array. This is possible because the iocb structure is 588 * the first element in the request structure (see PRTFILEAIOCTXINTERNAL). 589 */ 590 int cReqsSubmitted = 0; 591 rc = rtFileAsyncIoLinuxSubmit(pCtxInt->AioContext, cReqs, 592 (PLNXKAIOIOCB *)pahReqs, 593 &cReqsSubmitted); 594 if (RT_FAILURE(rc)) 595 { 596 /* 597 * We encountered an error. 598 * This means that the first IoCB 599 * is not correctly initialized 600 * (invalid buffer alignment or bad file descriptor). 601 * Revert every request into the prepared state except 602 * the first one which will switch to completed. 603 * Another reason could be insuffidient ressources. 604 */ 605 i = cReqs; 606 while (i-- > 0) 607 { 608 /* Already validated. */ 609 pReqInt = pahReqs[i]; 610 pReqInt->pCtxInt = NULL; 611 pReqInt->AioContext = 0; 612 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 613 } 614 615 if (rc == VERR_TRY_AGAIN) 616 return VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; 617 else 618 { 619 /* The first request failed. */ 620 pReqInt = pahReqs[0]; 621 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 622 pReqInt->Rc = rc; 623 pReqInt->cbTransfered = 0; 624 return rc; 625 } 626 } 627 628 /* Advance. */ 629 cReqs -= cReqsSubmitted; 630 pahReqs += cReqsSubmitted; 631 ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmitted); 632 633 } while (cReqs); 553 634 554 635 return rc; … … 643 724 644 725 /* Mark the request as finished. */ 645 pReqInt->fFinished = true;726 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 646 727 647 728 pahReqs[cRequestsCompleted++] = (RTFILEAIOREQ)pReqInt;
Note:
See TracChangeset
for help on using the changeset viewer.