* Allocate kva for pipe circular buffer, the space is pageable * This routine will 'realloc' the size of a pipe safely, if it fails * it will retain the old buffer. * If it fails it will return ENOMEM. */
| 535 | * If it fails it will return ENOMEM. |
| 536 | */ |
| 537 | static int |
| 538 | pipespace_new(struct pipe *cpipe, int size) |
| 539 | { |
| 540 | caddr_t buffer; |
| 541 | int error, cnt, firstseg; |
| 542 | static int curfail = 0; |
| 543 | static struct timeval lastfail; |
| 544 | |
| 545 | KASSERT(!mtx_owned(PIPE_MTX(cpipe)), ("pipespace: pipe mutex locked")); |
| 546 | KASSERT(!(cpipe->pipe_state & PIPE_DIRECTW), |
| 547 | ("pipespace: resize of direct writes not allowed")); |
| 548 | retry: |
| 549 | cnt = cpipe->pipe_buffer.cnt; |
| 550 | if (cnt > size) |
| 551 | size = cnt; |
| 552 | |
| 553 | size = round_page(size); |
| 554 | buffer = (caddr_t) vm_map_min(pipe_map); |
| 555 | |
| 556 | error = vm_map_find(pipe_map, NULL, 0, (vm_offset_t *)&buffer, size, 0, |
| 557 | VMFS_ANY_SPACE, VM_PROT_RW, VM_PROT_RW, 0); |
| 558 | if (error != KERN_SUCCESS) { |
| 559 | if (cpipe->pipe_buffer.buffer == NULL && |
| 560 | size > SMALL_PIPE_SIZE) { |
| 561 | size = SMALL_PIPE_SIZE; |
| 562 | pipefragretry++; |
| 563 | goto retry; |
| 564 | } |
| 565 | if (cpipe->pipe_buffer.buffer == NULL) { |
| 566 | pipeallocfail++; |
| 567 | if (ppsratecheck(&lastfail, &curfail, 1)) |
| 568 | printf("kern.ipc.maxpipekva exceeded; see tuning(7)\n"); |
| 569 | } else { |
| 570 | piperesizefail++; |
| 571 | } |
| 572 | return (ENOMEM); |
| 573 | } |
| 574 | |
| 575 | /* copy data, then free old resources if we're resizing */ |
| 576 | if (cnt > 0) { |
| 577 | if (cpipe->pipe_buffer.in <= cpipe->pipe_buffer.out) { |
| 578 | firstseg = cpipe->pipe_buffer.size - cpipe->pipe_buffer.out; |
| 579 | bcopy(&cpipe->pipe_buffer.buffer[cpipe->pipe_buffer.out], |
| 580 | buffer, firstseg); |
| 581 | if ((cnt - firstseg) > 0) |
| 582 | bcopy(cpipe->pipe_buffer.buffer, &buffer[firstseg], |
| 583 | cpipe->pipe_buffer.in); |
| 584 | } else { |
| 585 | bcopy(&cpipe->pipe_buffer.buffer[cpipe->pipe_buffer.out], |
| 586 | buffer, cnt); |
| 587 | } |
| 588 | } |
| 589 | pipe_free_kmem(cpipe); |
| 590 | cpipe->pipe_buffer.buffer = buffer; |
| 591 | cpipe->pipe_buffer.size = size; |
| 592 | cpipe->pipe_buffer.in = cnt; |
| 593 | cpipe->pipe_buffer.out = 0; |
| 594 | cpipe->pipe_buffer.cnt = cnt; |
no test coverage detected