1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * Copyright (c) 2014, Joyent, Inc. All rights reserved. 28 */ 29 30 #include <sys/types.h> 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/stropts.h> 34 #include <sys/socketvar.h> 35 #include <sys/ksocket.h> 36 #include <io/ksocket/ksocket_impl.h> 37 #include <fs/sockfs/sockcommon.h> 38 #include <fs/sockfs/sodirect.h> 39 #include <fs/sockfs/sockfilter_impl.h> 40 41 /* 42 * There can only be a single thread waiting for data (enforced by 43 * so_lock_read()), whereas for write there might be multiple threads 44 * waiting for transmit buffers. So therefore we use cv_broadcast for 45 * write and cv_signal for read. 46 */ 47 #define SO_WAKEUP_READER(so) { \ 48 if ((so)->so_rcv_wakeup) { \ 49 (so)->so_rcv_wakeup = B_FALSE; \ 50 cv_signal(&(so)->so_rcv_cv); \ 51 } \ 52 } 53 54 #define SO_WAKEUP_WRITER(so) { \ 55 if ((so)->so_snd_wakeup) { \ 56 (so)->so_snd_wakeup = B_FALSE; \ 57 cv_broadcast(&(so)->so_snd_cv); \ 58 } \ 59 } 60 61 static int i_so_notify_last_rx(struct sonode *, int *, int *); 62 static int i_so_notify_last_tx(struct sonode *, int *, int *); 63 64 /* 65 * The notification functions must be called with so_lock held, 66 * and they will all *drop* so_lock before returning. 67 */ 68 69 /* 70 * Wake up anyone waiting for the connection to be established. 71 */ 72 void 73 so_notify_connected(struct sonode *so) 74 { 75 ASSERT(MUTEX_HELD(&so->so_lock)); 76 77 if (IS_KERNEL_SOCKET(so)) { 78 KSOCKET_CALLBACK(so, connected, 0); 79 mutex_exit(&so->so_lock); 80 } else { 81 socket_sendsig(so, SOCKETSIG_WRITE); 82 mutex_exit(&so->so_lock); 83 pollwakeup(&so->so_poll_list, POLLOUT); 84 } 85 sof_sonode_notify_filters(so, SOF_EV_CONNECTED, 0); 86 87 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 88 } 89 90 /* 91 * The socket is disconnecting, so no more data can be sent. Wake up 92 * anyone that is waiting to send data. 93 */ 94 void 95 so_notify_disconnecting(struct sonode *so) 96 { 97 int pollev = 0; 98 int sigev = 0; 99 100 ASSERT(MUTEX_HELD(&so->so_lock)); 101 (void) i_so_notify_last_tx(so, &pollev, &sigev); 102 103 if (IS_KERNEL_SOCKET(so)) { 104 KSOCKET_CALLBACK(so, cantsendmore, 0); 105 mutex_exit(&so->so_lock); 106 } else { 107 if (sigev != 0) 108 socket_sendsig(so, sigev); 109 mutex_exit(&so->so_lock); 110 111 if (pollev != 0) 112 pollwakeup(&so->so_poll_list, pollev); 113 } 114 sof_sonode_notify_filters(so, SOF_EV_CANTSENDMORE, 0); 115 116 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 117 } 118 119 /* 120 * The socket is disconnected, so not more data can be sent or received. 121 * Wake up anyone that is waiting to send or receive data. 122 */ 123 void 124 so_notify_disconnected(struct sonode *so, boolean_t connfailed, int error) 125 { 126 int pollev = 0; 127 int sigev = 0; 128 129 ASSERT(MUTEX_HELD(&so->so_lock)); 130 131 (void) i_so_notify_last_tx(so, &pollev, &sigev); 132 (void) i_so_notify_last_rx(so, &pollev, &sigev); 133 134 if (IS_KERNEL_SOCKET(so)) { 135 if (connfailed) { 136 KSOCKET_CALLBACK(so, disconnected, error); 137 } else { 138 KSOCKET_CALLBACK(so, connectfailed, error); 139 } 140 mutex_exit(&so->so_lock); 141 } else { 142 if (sigev != 0) 143 socket_sendsig(so, sigev); 144 mutex_exit(&so->so_lock); 145 146 /* 147 * If we're here because the socket has become disconnected, 148 * we explicitly set POLLHUP. At the same time, we also clear 149 * POLLOUT, as POLLOUT and POLLHUP are defined to be mutually 150 * exclusive with respect to one another. 151 */ 152 if (!connfailed) 153 pollev = (pollev | POLLHUP) & ~POLLOUT; 154 155 if (pollev != 0) 156 pollwakeup(&so->so_poll_list, pollev); 157 } 158 sof_sonode_notify_filters(so, (connfailed) ? SOF_EV_CONNECTFAILED : 159 SOF_EV_DISCONNECTED, error); 160 161 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 162 } 163 164 /* 165 * The socket is writeable. Wake up anyone waiting to send data. 166 */ 167 void 168 so_notify_writable(struct sonode *so) 169 { 170 ASSERT(MUTEX_HELD(&so->so_lock)); 171 172 SO_WAKEUP_WRITER(so); 173 174 if (IS_KERNEL_SOCKET(so)) { 175 KSOCKET_CALLBACK(so, cansend, 0); 176 mutex_exit(&so->so_lock); 177 } else { 178 socket_sendsig(so, SOCKETSIG_WRITE); 179 mutex_exit(&so->so_lock); 180 pollwakeup(&so->so_poll_list, POLLOUT); 181 } 182 183 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 184 185 /* filters can start injecting data */ 186 if (so->so_filter_active > 0) 187 sof_sonode_notify_filters(so, SOF_EV_INJECT_DATA_OUT_OK, 0); 188 } 189 190 /* 191 * Data is available, so wake up anyone waiting for data. 192 */ 193 void 194 so_notify_data(struct sonode *so, size_t qlen) 195 { 196 ASSERT(MUTEX_HELD(&so->so_lock)); 197 198 SO_WAKEUP_READER(so); 199 200 if (IS_KERNEL_SOCKET(so)) { 201 KSOCKET_CALLBACK(so, newdata, qlen); 202 mutex_exit(&so->so_lock); 203 } else { 204 socket_sendsig(so, SOCKETSIG_READ); 205 if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) { 206 so->so_pollev &= ~SO_POLLEV_IN; 207 mutex_exit(&so->so_lock); 208 pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM); 209 } else { 210 mutex_exit(&so->so_lock); 211 } 212 } 213 214 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 215 } 216 217 /* 218 * Transient error. Wake up anyone waiting to send or receive data. 219 */ 220 void 221 so_notify_error(struct sonode *so) 222 { 223 ASSERT(MUTEX_HELD(&so->so_lock)); 224 225 SO_WAKEUP_WRITER(so); 226 SO_WAKEUP_READER(so); 227 228 if (IS_KERNEL_SOCKET(so)) { 229 KSOCKET_CALLBACK(so, error, 0); 230 mutex_exit(&so->so_lock); 231 } else { 232 socket_sendsig(so, SOCKETSIG_WRITE|SOCKETSIG_READ); 233 so->so_pollev &= ~SO_POLLEV_IN; 234 mutex_exit(&so->so_lock); 235 pollwakeup(&so->so_poll_list, POLLOUT|POLLIN|POLLRDNORM); 236 } 237 238 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 239 } 240 241 /* 242 * Out-of-band data is incoming, notify any interested parties. 243 */ 244 void 245 so_notify_oobsig(struct sonode *so) 246 { 247 socket_sendsig(so, SOCKETSIG_URG); 248 mutex_exit(&so->so_lock); 249 pollwakeup(&so->so_poll_list, POLLRDBAND); 250 } 251 252 /* 253 * Received out-of-band data. If the OOB data is delivered inline, then 254 * in addition of regular OOB notification, anyone waiting for normal 255 * data is also notified. 256 */ 257 void 258 so_notify_oobdata(struct sonode *so, boolean_t oob_inline) 259 { 260 ASSERT(MUTEX_HELD(&so->so_lock)); 261 if (so->so_direct != NULL) 262 SOD_UIOAFINI(so->so_direct); 263 264 SO_WAKEUP_READER(so); 265 266 if (IS_KERNEL_SOCKET(so)) { 267 KSOCKET_CALLBACK(so, oobdata, 0); 268 mutex_exit(&so->so_lock); 269 } else { 270 if (oob_inline) { 271 socket_sendsig(so, SOCKETSIG_READ); 272 so->so_pollev &= ~SO_POLLEV_IN; 273 mutex_exit(&so->so_lock); 274 pollwakeup(&so->so_poll_list, 275 POLLRDBAND|POLLIN|POLLRDNORM); 276 } else { 277 mutex_exit(&so->so_lock); 278 pollwakeup(&so->so_poll_list, POLLRDBAND); 279 } 280 } 281 282 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 283 } 284 285 /* 286 * End-of-file has been reach, so peer will send no new data. Wake up 287 * anyone that is waiting for data. 288 */ 289 void 290 so_notify_eof(struct sonode *so) 291 { 292 int pollev = 0; 293 int sigev = 0; 294 295 ASSERT(MUTEX_HELD(&so->so_lock)); 296 297 (void) i_so_notify_last_rx(so, &pollev, &sigev); 298 299 if (IS_KERNEL_SOCKET(so)) { 300 KSOCKET_CALLBACK(so, cantrecvmore, 0); 301 mutex_exit(&so->so_lock); 302 } else { 303 if (sigev != 0) 304 socket_sendsig(so, sigev); 305 mutex_exit(&so->so_lock); 306 if (pollev != 0) 307 pollwakeup(&so->so_poll_list, pollev); 308 309 } 310 sof_sonode_notify_filters(so, SOF_EV_CANTRECVMORE, 0); 311 312 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 313 } 314 315 /* 316 * Wake up anyone waiting for a new connection. 317 */ 318 void 319 so_notify_newconn(struct sonode *so) 320 { 321 ASSERT(MUTEX_HELD(&so->so_lock)); 322 323 if (IS_KERNEL_SOCKET(so)) { 324 KSOCKET_CALLBACK(so, newconn, 0); 325 mutex_exit(&so->so_lock); 326 } else { 327 socket_sendsig(so, SOCKETSIG_READ); 328 if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) { 329 so->so_pollev &= ~SO_POLLEV_IN; 330 mutex_exit(&so->so_lock); 331 pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM); 332 } else { 333 mutex_exit(&so->so_lock); 334 } 335 } 336 337 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 338 } 339 340 /* 341 * User initated shutdown/close, wake anyone that is trying to do 342 * an operation that is no longer possible. 343 */ 344 void 345 so_notify_shutdown(struct sonode *so) 346 { 347 int pollev = 0; 348 int sigev = 0; 349 350 ASSERT(MUTEX_HELD(&so->so_lock)); 351 ASSERT(so->so_state & (SS_CANTSENDMORE|SS_CANTRCVMORE)); 352 353 if (so->so_state & SS_CANTSENDMORE) 354 (void) i_so_notify_last_tx(so, &pollev, &sigev); 355 if (so->so_state & SS_CANTRCVMORE) 356 (void) i_so_notify_last_rx(so, &pollev, &sigev); 357 358 if (sigev != 0) 359 socket_sendsig(so, sigev); 360 mutex_exit(&so->so_lock); 361 if (pollev != 0) 362 pollwakeup(&so->so_poll_list, pollev); 363 364 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 365 } 366 367 /* 368 * No more data will be coming in, and this will be the last notification 369 * made. 370 */ 371 static int 372 i_so_notify_last_rx(struct sonode *so, int *pollev, int *sigev) 373 { 374 if (!(so->so_state & SS_SENTLASTREADSIG)) { 375 SOCKET_TIMER_CANCEL(so); 376 SO_WAKEUP_READER(so); 377 so->so_state |= SS_SENTLASTREADSIG; 378 so->so_pollev &= ~SO_POLLEV_IN; 379 380 *pollev |= POLLIN|POLLRDNORM; 381 *sigev |= SOCKETSIG_READ; 382 383 return (1); 384 } else { 385 return (0); 386 } 387 } 388 389 /* 390 * The socket is un-writeable. Make one last notification. 391 */ 392 static int 393 i_so_notify_last_tx(struct sonode *so, int *pollev, int *sigev) 394 { 395 if (!(so->so_state & SS_SENTLASTWRITESIG)) { 396 SO_WAKEUP_WRITER(so); 397 so->so_state |= SS_SENTLASTWRITESIG; 398 399 *pollev |= POLLOUT; 400 *sigev |= SOCKETSIG_WRITE; 401 402 return (1); 403 } else { 404 return (0); 405 } 406 } 407