| 1058 | #endif |
| 1059 | |
| 1060 | static int |
| 1061 | pipe_write(struct file *fp, struct uio *uio, struct ucred *active_cred, |
| 1062 | int flags, struct thread *td) |
| 1063 | { |
| 1064 | struct pipe *wpipe, *rpipe; |
| 1065 | ssize_t orig_resid; |
| 1066 | int desiredsize, error; |
| 1067 | |
| 1068 | rpipe = fp->f_data; |
| 1069 | wpipe = PIPE_PEER(rpipe); |
| 1070 | PIPE_LOCK(rpipe); |
| 1071 | error = pipelock(wpipe, 1); |
| 1072 | if (error) { |
| 1073 | PIPE_UNLOCK(rpipe); |
| 1074 | return (error); |
| 1075 | } |
| 1076 | /* |
| 1077 | * detect loss of pipe read side, issue SIGPIPE if lost. |
| 1078 | */ |
| 1079 | if (wpipe->pipe_present != PIPE_ACTIVE || |
| 1080 | (wpipe->pipe_state & PIPE_EOF)) { |
| 1081 | pipeunlock(wpipe); |
| 1082 | PIPE_UNLOCK(rpipe); |
| 1083 | return (EPIPE); |
| 1084 | } |
| 1085 | #ifdef MAC |
| 1086 | error = mac_pipe_check_write(active_cred, wpipe->pipe_pair); |
| 1087 | if (error) { |
| 1088 | pipeunlock(wpipe); |
| 1089 | PIPE_UNLOCK(rpipe); |
| 1090 | return (error); |
| 1091 | } |
| 1092 | #endif |
| 1093 | ++wpipe->pipe_busy; |
| 1094 | |
| 1095 | /* Choose a larger size if it's advantageous */ |
| 1096 | desiredsize = max(SMALL_PIPE_SIZE, wpipe->pipe_buffer.size); |
| 1097 | while (desiredsize < wpipe->pipe_buffer.cnt + uio->uio_resid) { |
| 1098 | if (piperesizeallowed != 1) |
| 1099 | break; |
| 1100 | if (amountpipekva > maxpipekva / 2) |
| 1101 | break; |
| 1102 | if (desiredsize == BIG_PIPE_SIZE) |
| 1103 | break; |
| 1104 | desiredsize = desiredsize * 2; |
| 1105 | } |
| 1106 | |
| 1107 | /* Choose a smaller size if we're in a OOM situation */ |
| 1108 | if (amountpipekva > (3 * maxpipekva) / 4 && |
| 1109 | wpipe->pipe_buffer.size > SMALL_PIPE_SIZE && |
| 1110 | wpipe->pipe_buffer.cnt <= SMALL_PIPE_SIZE && |
| 1111 | piperesizeallowed == 1) |
| 1112 | desiredsize = SMALL_PIPE_SIZE; |
| 1113 | |
| 1114 | /* Resize if the above determined that a new size was necessary */ |
| 1115 | if (desiredsize != wpipe->pipe_buffer.size && |
| 1116 | (wpipe->pipe_state & PIPE_DIRECTW) == 0) { |
| 1117 | PIPE_UNLOCK(wpipe); |
nothing calls this directly
no test coverage detected