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