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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 /* 31 * Portions of this source code were derived from Berkeley 32 * 4.3 BSD under license from the Regents of the University of 33 * California. 34 */ 35 36 #pragma ident "%Z%%M% %I% %E% SMI" 37 38 /* 39 * This is the rpc server side idle loop 40 * Wait for input, call server program. 41 */ 42 #include "mt.h" 43 #include "rpc_mt.h" 44 #include <stdlib.h> 45 #include <unistd.h> 46 #include <signal.h> 47 #include <rpc/rpc.h> 48 #include <errno.h> 49 #include <sys/poll.h> 50 #include <sys/types.h> 51 #include <syslog.h> 52 #include <thread.h> 53 #include <assert.h> 54 #include <libintl.h> 55 #include <values.h> 56 57 extern const char __nsl_dom[]; 58 59 extern int __rpc_compress_pollfd(int, pollfd_t *, pollfd_t *); 60 extern bool_t __is_a_userfd(int P_fd); 61 extern void __destroy_userfd(); 62 extern void clear_pollfd(int); 63 extern void set_pollfd(int /* fd */, short /* events */); 64 extern void svc_getreq_poll(); 65 extern void (*__proc_cleanup_cb)(); 66 67 static void start_threads(); 68 static void create_pipe(); 69 static void clear_pipe(); 70 static int select_next_pollfd(); 71 static SVCXPRT *make_xprt_copy(); 72 static void _svc_run_mt(); 73 static void _svc_run(); 74 75 int _svc_prog_dispatch(); 76 static void _svc_done_private(); 77 78 extern rwlock_t svc_fd_lock; 79 extern mutex_t svc_door_mutex; 80 extern cond_t svc_door_waitcv; 81 extern int svc_ndoorfds; 82 extern void __svc_cleanup_door_xprts(); 83 extern void __svc_free_xprtlist(); 84 extern void __svc_getreq_user(struct pollfd *); 85 86 /* 87 * Maximum fragment size allowed for connection oriented connections. 88 * Zero means that no maximum size limit has been requested. 89 */ 90 int __rpc_connmaxrec = 0; 91 92 /* Inter-Record Timeout in secs for non-blocked connection RPC */ 93 int __rpc_irtimeout = 35; 94 95 /* 96 * Request exclusive access to tcp and udp non-priv ports bound with a 97 * wildcard addr. 98 */ 99 bool_t __rpc_tp_exclbind = FALSE; 100 101 /* 102 * XXX - eventually, all mutexes and their initializations static 103 */ 104 105 /* 106 * Variables used for MT 107 */ 108 int svc_mt_mode; /* multi-threading mode */ 109 110 int svc_pipe[2]; /* pipe for breaking out of poll: read(0), write(1) */ 111 112 /* BEGIN PROTECTED BY svc_mutex */ 113 114 static int svc_thr_max = 16; /* default maximum number of threads allowed */ 115 116 static int svc_thr_total; /* current number of threads */ 117 118 static int svc_thr_active; /* current number of threads active */ 119 120 /* circular array of file descriptors with pending data */ 121 122 #define CIRCULAR_BUFSIZE 1024 123 124 static int svc_pending_fds[CIRCULAR_BUFSIZE+1]; /* fds with pending data */ 125 126 static int svc_next_pending; /* next one to be processed */ 127 128 static int svc_last_pending; /* last one in list */ 129 130 static int svc_total_pending; /* total in list */ 131 132 static int svc_thr_total_creates; /* total created - stats */ 133 134 static int svc_thr_total_create_errors; /* total create errors - stats */ 135 136 static int svc_waiters; /* number of waiting threads */ 137 138 /* END PROTECTED BY svc_mutex */ 139 140 /* BEGIN PROTECTED BY svc_fd_lock: */ 141 142 int svc_nfds; /* total number of active file descriptors */ 143 144 int svc_nfds_set; /* total number of fd bits set in svc_fdset */ 145 146 int svc_max_fd = 0; /* largest active file descriptor */ 147 148 int svc_npollfds; /* total number of active pollfds */ 149 150 int svc_npollfds_set; /* total number of pollfd set in svc_pollfd */ 151 152 int svc_max_pollfd; /* largest active pollfd so far */ 153 154 int svc_pollfd_allocd; /* number of pollfd structures allocated */ 155 156 /* END PROTECTED BY svc_fd_lock: */ 157 158 /* BEGIN PROTECTED BY svc_thr_mutex */ 159 160 #define POLLSET_EXTEND 256 161 static int svc_pollset_allocd; 162 static struct pollfd *svc_pollset; 163 /* 164 * array of file descriptors currently active 165 */ 166 static int svc_polled; /* no of fds polled in last poll() - input */ 167 168 static int svc_pollfds; /* no of active fds in last poll() - output */ 169 170 static int svc_next_pollfd; /* next fd to processin svc_pollset */ 171 172 bool_t svc_polling; /* true if a thread is polling */ 173 174 /* END PROTECTED BY svc_thr_mutex */ 175 176 /* BEGIN PROTECTED BY svc_exit_mutex */ 177 178 static bool_t svc_exit_done = TRUE; 179 180 /* END PROTECTED BY svc_exit_mutex */ 181 182 /* 183 * Warlock section 184 */ 185 186 /* VARIABLES PROTECTED BY svc_mutex: 187 svc_thr_total, svc_thr_active, svc_pending_fds, svc_next_pending, 188 svc_last_pending, svc_total_pending, svc_thr_total_creates, 189 svc_thr_total_create_errors, 190 svcxprt_list_t::next, svcxprt_ext_t::my_xlist, 191 svc_thr_max, svc_waiters 192 */ 193 194 /* VARIABLES PROTECTED BY svc_fd_lock: 195 svc_xports, svc_fdset, svc_nfds, svc_nfds_set, svc_max_fd, 196 svc_pollfd, svc_npollfds, svc_npollfds_set, svc_max_pollfd 197 */ 198 199 /* VARIABLES PROTECTED BY svc_thr_mutex: 200 svc_pollset, svc_pollfds, svc_next_pollfd, svc_polling 201 svc_pollset_allocd, svc_polled 202 */ 203 204 /* VARIABLES PROTECTED BY svc_exit_mutex: 205 svc_exit_done 206 */ 207 208 /* VARIABLES READABLE WITHOUT LOCK: 209 svc_thr_total, svc_thr_active, svc_thr_total_creates, 210 svc_thr_total_create_errors, 211 svc_xports, svc_nfds, svc_nfds_set, svc_max_fd, 212 svc_npollfds, svc_npollfds_set, svc_max_pollfd, 213 svc_pollfds, svc_next_pollfd, svc_exit_done, svc_polling, 214 svc_thr_max, svc_waiters 215 */ 216 217 /* VARIABLES PROTECTED BY "program_logic": 218 rpc_msg::, svc_req::, svcxprt_ext_t::flags, svc_mt_mode, 219 svcxprt_ext_t::parent 220 */ 221 222 /* LOCK ORDER: 223 svc_exit_mutex, svc_thr_mutex, svc_mutex, svc_fd_lock 224 */ 225 226 227 void 228 svc_run(void) 229 { 230 /* NO OTHER THREADS ARE RUNNING */ 231 232 svc_exit_done = FALSE; 233 234 while ((svc_npollfds > 0 || svc_ndoorfds > 0) && !svc_exit_done) { 235 if (svc_npollfds > 0) { 236 switch (svc_mt_mode) { 237 case RPC_SVC_MT_NONE: 238 _svc_run(); 239 break; 240 default: 241 _svc_run_mt(); 242 break; 243 } 244 continue; 245 } 246 247 (void) mutex_lock(&svc_door_mutex); 248 if (svc_ndoorfds > 0) 249 (void) cond_wait(&svc_door_waitcv, &svc_door_mutex); 250 (void) mutex_unlock(&svc_door_mutex); 251 } 252 } 253 254 255 /* 256 * This function causes svc_run() to exit by destroying all 257 * service handles. 258 */ 259 void 260 svc_exit(void) 261 { 262 SVCXPRT *xprt; 263 int fd; 264 char dummy; 265 266 /* NO LOCKS HELD */ 267 268 (void) mutex_lock(&svc_exit_mutex); 269 if (svc_exit_done) { 270 (void) mutex_unlock(&svc_exit_mutex); 271 return; 272 } 273 svc_exit_done = TRUE; 274 for (fd = 0; fd < svc_max_pollfd; fd++) { 275 xprt = svc_xports[fd]; 276 if (xprt) { 277 SVC_DESTROY(xprt); 278 } 279 } 280 __svc_free_xprtlist(); 281 __svc_cleanup_door_xprts(); 282 (void) mutex_unlock(&svc_exit_mutex); 283 284 if (svc_mt_mode != RPC_SVC_MT_NONE) { 285 (void) mutex_lock(&svc_mutex); 286 (void) cond_broadcast(&svc_thr_fdwait); 287 (void) mutex_unlock(&svc_mutex); 288 289 (void) write(svc_pipe[1], &dummy, sizeof (dummy)); 290 } 291 292 (void) mutex_lock(&svc_door_mutex); 293 (void) cond_signal(&svc_door_waitcv); /* wake up door dispatching */ 294 (void) mutex_unlock(&svc_door_mutex); 295 296 /* destroy reactor information if any */ 297 __destroy_userfd(); 298 } 299 300 301 /* 302 * this funtion is called with svc_fd_lock and svc_thr_mutex 303 */ 304 305 static int 306 alloc_pollset(int npollfds) 307 { 308 if (npollfds > svc_pollset_allocd) { 309 pollfd_t *tmp; 310 do { 311 svc_pollset_allocd += POLLSET_EXTEND; 312 } while (npollfds > svc_pollset_allocd); 313 tmp = realloc(svc_pollset, 314 sizeof (pollfd_t) * svc_pollset_allocd); 315 if (tmp == NULL) { 316 syslog(LOG_ERR, "alloc_pollset: out of memory"); 317 return (-1); 318 } 319 svc_pollset = tmp; 320 } 321 return (0); 322 } 323 324 static void 325 _svc_run(void) 326 { 327 sigset_t set, oldset; 328 int npollfds; 329 int i; 330 331 /* 332 * Block SIGALRM while doing work. Unblock it while doing poll(). 333 * This is so that services like rpc.rstatd can cause the poll() 334 * to be interrupted due to alarm() but that we don't end up in 335 * an MT-unsafe signal handler at an inopportune time. 336 */ 337 (void) sigemptyset(&set); 338 (void) sigaddset(&set, SIGALRM); 339 (void) sigprocmask(SIG_BLOCK, &set, &oldset); 340 while (!svc_exit_done) { 341 /* 342 * Check whether there is any server fd on which we may want 343 * to wait. 344 */ 345 (void) rw_rdlock(&svc_fd_lock); 346 if (alloc_pollset(svc_npollfds) == -1) 347 break; 348 npollfds = __rpc_compress_pollfd(svc_max_pollfd, 349 svc_pollfd, svc_pollset); 350 (void) rw_unlock(&svc_fd_lock); 351 if (npollfds == 0) 352 break; /* None waiting, hence return */ 353 354 (void) sigprocmask(SIG_SETMASK, &oldset, NULL); 355 i = poll(svc_pollset, npollfds, -1); 356 (void) sigprocmask(SIG_BLOCK, &set, &oldset); 357 switch (i) { 358 case -1: 359 /* 360 * We ignore all errors, continuing with the assumption 361 * that it was set by the signal handlers (or any 362 * other outside event) and not caused by poll(). 363 */ 364 case 0: 365 continue; 366 default: 367 svc_getreq_poll(svc_pollset, i); 368 } 369 } 370 (void) sigprocmask(SIG_SETMASK, &oldset, NULL); 371 } 372 373 /* 374 * In _svc_run_mt, myfd is linked with mypollfd 375 * svc_pollset[mypollfd].fd == myfd 376 * However, in some cases, the link can not be made, thus we define the 377 * following values for these special cases 378 */ 379 enum { 380 INVALID_POLLFD = -200, 381 FD_FROM_PENDING 382 }; 383 384 static void 385 _svc_run_mt(void) 386 { 387 int npollfds; 388 int n_polled, dispatch; 389 390 static bool_t first_time = TRUE; 391 bool_t main_thread = FALSE; 392 int n_new; 393 int myfd, mypollfd; 394 SVCXPRT *parent_xprt, *xprt; 395 396 /* 397 * Server is multi-threaded. Do "first time" initializations. 398 * Since only one thread exists in the beginning, there's no 399 * need for mutex protection for first time initializations. 400 */ 401 if (first_time) { 402 first_time = FALSE; 403 main_thread = TRUE; 404 svc_thr_total = 1; /* this thread */ 405 svc_next_pending = svc_last_pending = 0; 406 407 /* 408 * Create a pipe for waking up the poll, if new 409 * descriptors have been added to svc_fdset. 410 */ 411 create_pipe(); 412 } 413 414 /* OTHER THREADS ARE RUNNING */ 415 416 if (svc_exit_done) 417 return; 418 419 for (;;) { 420 /* 421 * svc_thr_mutex prevents more than one thread from 422 * trying to select a descriptor to process further. 423 * svc_thr_mutex is unlocked after a thread selects 424 * a descriptor on which to receive data. If there are 425 * no such descriptors, the thread will poll with 426 * svc_thr_mutex locked, after unlocking all other 427 * locks. This prevents more than one thread from 428 * trying to poll at the same time. 429 */ 430 (void) mutex_lock(&svc_thr_mutex); 431 (void) mutex_lock(&svc_mutex); 432 continue_with_locks: 433 myfd = -1; 434 mypollfd = INVALID_POLLFD; 435 436 /* 437 * Check if there are any descriptors with data pending. 438 */ 439 if (svc_total_pending > 0) { 440 myfd = svc_pending_fds[svc_next_pending++]; 441 mypollfd = FD_FROM_PENDING; 442 if (svc_next_pending > CIRCULAR_BUFSIZE) 443 svc_next_pending = 0; 444 svc_total_pending--; 445 } 446 447 /* 448 * Get the next active file descriptor to process. 449 */ 450 if (myfd == -1 && svc_pollfds == 0) { 451 /* 452 * svc_pollset is empty; do polling 453 */ 454 svc_polling = TRUE; 455 456 /* 457 * if there are no file descriptors, return 458 */ 459 (void) rw_rdlock(&svc_fd_lock); 460 if (svc_npollfds == 0 || 461 alloc_pollset(svc_npollfds + 1) == -1) { 462 (void) rw_unlock(&svc_fd_lock); 463 svc_polling = FALSE; 464 svc_thr_total--; 465 (void) mutex_unlock(&svc_mutex); 466 (void) mutex_unlock(&svc_thr_mutex); 467 if (!main_thread) { 468 thr_exit(NULL); 469 /* NOTREACHED */ 470 } 471 break; 472 } 473 474 npollfds = __rpc_compress_pollfd(svc_max_pollfd, 475 svc_pollfd, svc_pollset); 476 (void) rw_unlock(&svc_fd_lock); 477 478 if (npollfds == 0) { 479 /* 480 * There are file descriptors, but none of them 481 * are available for polling. If this is the 482 * main thread, or if no thread is waiting, 483 * wait on condition variable, otherwise exit. 484 */ 485 svc_polling = FALSE; 486 (void) mutex_unlock(&svc_thr_mutex); 487 if ((!main_thread) && svc_waiters > 0) { 488 svc_thr_total--; 489 (void) mutex_unlock(&svc_mutex); 490 thr_exit(NULL); 491 /* NOTREACHED */ 492 } 493 494 while (svc_npollfds_set == 0 && 495 svc_pollfds == 0 && 496 svc_total_pending == 0 && 497 !svc_exit_done) { 498 svc_waiters++; 499 (void) cond_wait(&svc_thr_fdwait, 500 &svc_mutex); 501 svc_waiters--; 502 } 503 504 /* 505 * Check exit flag. If this is not the main 506 * thread, exit. 507 */ 508 if (svc_exit_done) { 509 svc_thr_total--; 510 (void) mutex_unlock(&svc_mutex); 511 if (!main_thread) 512 thr_exit(NULL); 513 break; 514 } 515 516 (void) mutex_unlock(&svc_mutex); 517 continue; 518 } 519 520 /* 521 * We're ready to poll. Always set svc_pipe[0] 522 * as the last one, since the poll will occasionally 523 * need to be interrupted. Release svc_mutex for 524 * the duration of the poll, but hold on to 525 * svc_thr_mutex, as we don't want any other thread 526 * to do the same. 527 */ 528 svc_pollset[npollfds].fd = svc_pipe[0]; 529 svc_pollset[npollfds].events = MASKVAL; 530 531 do { 532 int i, j; 533 534 (void) mutex_unlock(&svc_mutex); 535 n_polled = poll(svc_pollset, npollfds + 1, -1); 536 (void) mutex_lock(&svc_mutex); 537 if (n_polled <= 0) 538 continue; 539 540 /* 541 * Check if information returned indicates one 542 * or more closed fd's; find and remove any such 543 * information 544 */ 545 for (i = 0; i <= npollfds; i++) { 546 if (svc_pollset[i].revents & POLLNVAL) { 547 /* Overwrite svc_pollset[i] */ 548 for (j = i; j < npollfds; j++) 549 svc_pollset[j] = 550 svc_pollset[j + 1]; 551 (void) memset(&svc_pollset[j], 552 0, sizeof (struct pollfd)); 553 npollfds--; 554 n_polled--; 555 i--; 556 } 557 } 558 } while (n_polled <= 0); 559 svc_polling = FALSE; 560 561 /* 562 * If there's data in the pipe, clear it. 563 */ 564 if (svc_pollset[npollfds].revents) { 565 clear_pipe(); 566 n_polled--; 567 svc_pollset[npollfds].revents = 0; 568 } 569 svc_polled = npollfds; 570 svc_pollfds = n_polled; 571 svc_next_pollfd = 0; 572 573 /* 574 * Check exit flag. 575 */ 576 if (svc_exit_done) { 577 svc_thr_total--; 578 (void) mutex_unlock(&svc_mutex); 579 (void) mutex_unlock(&svc_thr_mutex); 580 if (!main_thread) { 581 thr_exit(NULL); 582 /* NOTREACHED */ 583 } 584 break; 585 } 586 587 /* 588 * If no descriptor is active, continue. 589 */ 590 if (svc_pollfds == 0) 591 goto continue_with_locks; 592 } 593 594 /* 595 * If a file descriptor has already not been selected, 596 * choose a file descriptor. 597 * svc_pollfds and svc_next_pollfd are updated. 598 */ 599 if (myfd == -1) { 600 if (select_next_pollfd(&myfd, &mypollfd) == -1) 601 goto continue_with_locks; 602 } 603 604 /* 605 * Check to see if new threads need to be started. 606 * Count of threads that could be gainfully employed is 607 * obtained as follows: 608 * - count 1 for poller 609 * - count 1 for this request 610 * - count active file descriptors (svc_pollfds) 611 * - count pending file descriptors 612 * 613 * (svc_thr_total - svc_thr_active) are already available. 614 * This thread is one of the available threads. 615 * 616 * Number of new threads should not exceed 617 * (svc_thr_max - svc_thr_total). 618 */ 619 if (svc_thr_total < svc_thr_max && 620 svc_mt_mode == RPC_SVC_MT_AUTO && !svc_exit_done) { 621 n_new = 1 + 1 + svc_pollfds + svc_total_pending - 622 (svc_thr_total - svc_thr_active); 623 if (n_new > (svc_thr_max - svc_thr_total)) 624 n_new = svc_thr_max - svc_thr_total; 625 if (n_new > 0) 626 start_threads(n_new); 627 } 628 629 /* 630 * Get parent xprt. It is possible for the parent service 631 * handle to be destroyed by now, due to a race condition. 632 * Check for this, and if so, log a warning and go on. 633 */ 634 parent_xprt = svc_xports[myfd]; 635 if (parent_xprt == NULL) { 636 /* Check if it is not a user FD */ 637 if (__is_a_userfd(myfd) == TRUE) 638 __svc_getreq_user(&(svc_pollset[mypollfd])); 639 goto continue_with_locks; 640 } 641 /* LINTED pointer alignment */ 642 if (svc_defunct(parent_xprt) || svc_failed(parent_xprt)) 643 goto continue_with_locks; 644 645 /* 646 * Make a copy of parent xprt, update svc_fdset. 647 */ 648 if ((xprt = make_xprt_copy(parent_xprt)) == NULL) 649 goto continue_with_locks; 650 651 /* 652 * Keep track of active threads in automatic mode. 653 */ 654 if (svc_mt_mode == RPC_SVC_MT_AUTO) 655 svc_thr_active++; 656 657 /* 658 * Release mutexes so other threads can get going. 659 */ 660 (void) mutex_unlock(&svc_mutex); 661 (void) mutex_unlock(&svc_thr_mutex); 662 663 /* 664 * Process request. 665 */ 666 { 667 struct rpc_msg *msg; 668 struct svc_req *r; 669 char *cred_area; 670 671 /* LINTED pointer alignment */ 672 msg = SVCEXT(xprt)->msg; 673 /* LINTED pointer alignment */ 674 r = SVCEXT(xprt)->req; 675 /* LINTED pointer alignment */ 676 cred_area = SVCEXT(xprt)->cred_area; 677 678 679 msg->rm_call.cb_cred.oa_base = cred_area; 680 msg->rm_call.cb_verf.oa_base = 681 &(cred_area[MAX_AUTH_BYTES]); 682 r->rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]); 683 684 /* 685 * receive RPC message 686 */ 687 if ((dispatch = SVC_RECV(xprt, msg))) { 688 if (svc_mt_mode != RPC_SVC_MT_NONE) 689 /* LINTED pointer alignment */ 690 svc_flags(xprt) |= SVC_ARGS_CHECK; 691 dispatch = _svc_prog_dispatch(xprt, msg, r); 692 693 /* 694 * Call cleanup procedure if set. 695 */ 696 if (__proc_cleanup_cb != NULL) 697 (*__proc_cleanup_cb)(xprt); 698 } else 699 svc_args_done(xprt); 700 701 /* 702 * Finish up, if automatic mode, or not dispatched. 703 */ 704 if (svc_mt_mode == RPC_SVC_MT_AUTO || !dispatch) { 705 /* LINTED pointer alignment */ 706 if (svc_flags(xprt) & SVC_ARGS_CHECK) 707 svc_args_done(xprt); 708 (void) mutex_lock(&svc_mutex); 709 _svc_done_private(xprt); 710 if (svc_mt_mode == RPC_SVC_MT_AUTO) { 711 /* 712 * not active any more 713 */ 714 svc_thr_active--; 715 716 /* 717 * If not main thread, exit unless 718 * there's some immediate work. 719 */ 720 if (!main_thread && 721 svc_pollfds <= 0 && 722 svc_total_pending <= 0 && 723 (svc_polling || 724 svc_waiters > 0)) { 725 svc_thr_total--; 726 if (svc_thr_total == 727 svc_waiters) { 728 (void) cond_broadcast( 729 &svc_thr_fdwait); 730 } 731 (void) mutex_unlock(&svc_mutex); 732 thr_exit(NULL); 733 /* NOTREACHED */ 734 } 735 } 736 (void) mutex_unlock(&svc_mutex); 737 } 738 } 739 740 } 741 } 742 743 744 /* 745 * start_threads() - Start specified number of threads. 746 */ 747 static void 748 start_threads(int num_threads) 749 { 750 int i; 751 752 assert(MUTEX_HELD(&svc_mutex)); 753 754 for (i = 0; i < num_threads; i++) { 755 if (thr_create(NULL, 0, (void *(*)(void *))_svc_run_mt, NULL, 756 THR_DETACHED, NULL) == 0) { 757 svc_thr_total++; 758 svc_thr_total_creates++; 759 } else { 760 svc_thr_total_create_errors++; 761 } 762 } 763 } 764 765 766 /* 767 * create_pipe() - create pipe for breaking out of poll. 768 */ 769 static void 770 create_pipe(void) 771 { 772 if (pipe(svc_pipe) == -1) { 773 syslog(LOG_ERR, dgettext(__nsl_dom, 774 "RPC: svc could not create pipe - exiting")); 775 exit(1); 776 } 777 if (fcntl(svc_pipe[0], F_SETFL, O_NONBLOCK) == -1) { 778 syslog(LOG_ERR, dgettext(__nsl_dom, 779 "RPC: svc pipe error - exiting")); 780 exit(1); 781 } 782 if (fcntl(svc_pipe[1], F_SETFL, O_NONBLOCK) == -1) { 783 syslog(LOG_ERR, dgettext(__nsl_dom, 784 "RPC: svc pipe error - exiting")); 785 exit(1); 786 } 787 } 788 789 790 /* 791 * clear_pipe() - Empty data in pipe. 792 */ 793 static void 794 clear_pipe(void) 795 { 796 char buf[16]; 797 int i; 798 799 do { 800 i = read(svc_pipe[0], buf, sizeof (buf)); 801 } while (i == sizeof (buf)); 802 } 803 804 805 /* 806 * select_next_pollfd() - Select the next active fd in svc_pollset. 807 */ 808 static int 809 select_next_pollfd(int *fd, int *pollfdIndex) 810 { 811 int i; 812 813 assert(MUTEX_HELD(&svc_thr_mutex)); 814 assert(MUTEX_HELD(&svc_mutex)); 815 816 for (i = svc_next_pollfd; svc_pollfds > 0 && i < svc_polled; 817 i++) { 818 if (svc_pollset[i].revents) { 819 svc_pollfds--; 820 /* 821 * No more special case for POLLNVAL, because it may 822 * be linked with a user file descriptot callback 823 */ 824 svc_next_pollfd = i + 1; 825 826 *fd = svc_pollset[i].fd; 827 *pollfdIndex = i; 828 829 return (0); 830 } 831 } 832 svc_next_pollfd = svc_pollfds = 0; 833 *fd = -1; 834 *pollfdIndex = INVALID_POLLFD; 835 return (-1); 836 } 837 838 839 /* 840 * make_xprt_copy() - make a copy of the parent xprt. 841 * Clear fd bit in svc_fdset. 842 */ 843 static SVCXPRT * 844 make_xprt_copy(SVCXPRT *parent) 845 { 846 /* LINTED pointer alignment */ 847 SVCXPRT_LIST *xlist = SVCEXT(parent)->my_xlist; 848 SVCXPRT_LIST *xret; 849 SVCXPRT *xprt; 850 int fd = parent->xp_fd; 851 852 assert(MUTEX_HELD(&svc_mutex)); 853 854 xret = xlist->next; 855 if (xret) { 856 xlist->next = xret->next; 857 xret->next = NULL; 858 xprt = xret->xprt; 859 /* LINTED pointer alignment */ 860 svc_flags(xprt) = svc_flags(parent); 861 } else 862 xprt = svc_copy(parent); 863 864 if (xprt) { 865 /* LINTED pointer alignment */ 866 SVCEXT(parent)->refcnt++; 867 (void) rw_wrlock(&svc_fd_lock); 868 clear_pollfd(fd); 869 (void) rw_unlock(&svc_fd_lock); 870 } 871 return (xprt); 872 } 873 874 /* 875 * _svc_done_private() - return copies to library. 876 */ 877 static void 878 _svc_done_private(SVCXPRT *xprt) 879 { 880 SVCXPRT *parent; 881 SVCXPRT_LIST *xhead, *xlist; 882 883 assert(MUTEX_HELD(&svc_mutex)); 884 885 /* LINTED pointer alignment */ 886 if ((parent = SVCEXT(xprt)->parent) == NULL) 887 return; 888 889 /* LINTED pointer alignment */ 890 xhead = SVCEXT(parent)->my_xlist; 891 /* LINTED pointer alignment */ 892 xlist = SVCEXT(xprt)->my_xlist; 893 xlist->next = xhead->next; 894 xhead->next = xlist; 895 896 /* LINTED pointer alignment */ 897 SVCEXT(parent)->refcnt--; 898 899 /* 900 * Propagate any error flags. This is done in both directions to 901 * ensure that if one child gets an error, everyone will see it 902 * (even if there are multiple outstanding children) and the 903 * transport will get closed. 904 */ 905 /* LINTED pointer alignment */ 906 svc_flags(xprt) |= svc_flags(parent); 907 /* LINTED pointer alignment */ 908 if (svc_failed(xprt) || svc_defunct(xprt)) { 909 /* LINTED pointer alignment */ 910 svc_flags(parent) |= (svc_flags(xprt) & 911 (SVC_FAILED | SVC_DEFUNCT)); 912 /* LINTED pointer alignment */ 913 if (SVCEXT(parent)->refcnt == 0) 914 _svc_destroy_private(xprt); 915 } 916 } 917 918 void 919 svc_done(SVCXPRT *xprt) 920 { 921 if (svc_mt_mode != RPC_SVC_MT_USER) 922 return; 923 924 /* 925 * Make sure file descriptor is released in user mode. 926 * If the xprt is a door, do nothing: this work is performed by 927 * svc_door.c's return_xprt_copy() routine, which is basically a 928 * door-specific copy of _svc_done_private(). 929 */ 930 /* LINTED pointer alignment */ 931 if (svc_type(xprt) == SVC_DOOR) 932 return; 933 934 /* LINTED pointer alignment */ 935 if (svc_flags(xprt) & SVC_ARGS_CHECK) 936 svc_args_done(xprt); 937 938 (void) mutex_lock(&svc_mutex); 939 _svc_done_private(xprt); 940 (void) mutex_unlock(&svc_mutex); 941 } 942 943 944 /* 945 * Mark argument completion. Release file descriptor. 946 */ 947 void 948 svc_args_done(SVCXPRT *xprt) 949 { 950 char dummy; 951 /* LINTED pointer alignment */ 952 SVCXPRT *parent = SVCEXT(xprt)->parent; 953 bool_t wake_up_poller; 954 enum xprt_stat stat; 955 956 /* LINTED pointer alignment */ 957 svc_flags(xprt) |= svc_flags(parent); 958 /* LINTED pointer alignment */ 959 svc_flags(xprt) &= ~SVC_ARGS_CHECK; 960 /* LINTED pointer alignment */ 961 if (svc_failed(xprt) || svc_defunct(parent)) 962 return; 963 964 /* LINTED pointer alignment */ 965 if (svc_type(xprt) == SVC_CONNECTION && 966 (stat = SVC_STAT(xprt)) != XPRT_IDLE) { 967 if (stat == XPRT_MOREREQS) { 968 (void) mutex_lock(&svc_mutex); 969 svc_pending_fds[svc_last_pending++] = xprt->xp_fd; 970 if (svc_last_pending > CIRCULAR_BUFSIZE) 971 svc_last_pending = 0; 972 svc_total_pending++; 973 (void) mutex_unlock(&svc_mutex); 974 wake_up_poller = FALSE; 975 } else { 976 /* 977 * connection failed 978 */ 979 return; 980 } 981 } else { 982 (void) rw_wrlock(&svc_fd_lock); 983 set_pollfd(xprt->xp_fd, MASKVAL); 984 (void) rw_unlock(&svc_fd_lock); 985 wake_up_poller = TRUE; 986 } 987 988 if (!wake_up_poller || !svc_polling) { 989 /* 990 * Wake up any waiting threads. 991 */ 992 (void) mutex_lock(&svc_mutex); 993 if (svc_waiters > 0) { 994 (void) cond_broadcast(&svc_thr_fdwait); 995 (void) mutex_unlock(&svc_mutex); 996 return; 997 } 998 (void) mutex_unlock(&svc_mutex); 999 } 1000 1001 /* 1002 * Wake up any polling thread. 1003 */ 1004 if (svc_polling) 1005 (void) write(svc_pipe[1], &dummy, sizeof (dummy)); 1006 } 1007 1008 1009 int 1010 __rpc_legal_connmaxrec(int suggested) { 1011 if (suggested == -1) { 1012 /* Supply default */ 1013 return (RPC_MAXDATASIZE + 2*sizeof (uint32_t)); 1014 } else if (suggested < 0) { 1015 return (-1); 1016 } else if (suggested > 0) { 1017 /* Round down to multiple of BYTES_PER_XDR_UNIT */ 1018 suggested -= suggested % BYTES_PER_XDR_UNIT; 1019 /* If possible, allow for two fragment headers */ 1020 if (suggested < MAXINT-(2*sizeof (uint32_t))) { 1021 /* Allow for two fragment headers */ 1022 suggested += 2 * sizeof (uint32_t); 1023 } else { 1024 suggested = MAXINT; 1025 } 1026 if (suggested < sizeof (struct rpc_msg)) { 1027 return (-1); 1028 } 1029 } 1030 return (suggested); 1031 } 1032 1033 1034 bool_t 1035 rpc_control(int op, void *info) 1036 { 1037 int tmp; 1038 extern int __rpc_minfd; 1039 1040 switch (op) { 1041 case RPC_SVC_MTMODE_SET: 1042 tmp = *((int *)info); 1043 if (tmp != RPC_SVC_MT_NONE && tmp != RPC_SVC_MT_AUTO && 1044 tmp != RPC_SVC_MT_USER) 1045 return (FALSE); 1046 if (svc_mt_mode != RPC_SVC_MT_NONE && svc_mt_mode != tmp) 1047 return (FALSE); 1048 svc_mt_mode = tmp; 1049 return (TRUE); 1050 case RPC_SVC_MTMODE_GET: 1051 *((int *)info) = svc_mt_mode; 1052 return (TRUE); 1053 case RPC_SVC_THRMAX_SET: 1054 if ((tmp = *((int *)info)) < 1) 1055 return (FALSE); 1056 (void) mutex_lock(&svc_mutex); 1057 svc_thr_max = tmp; 1058 (void) mutex_unlock(&svc_mutex); 1059 return (TRUE); 1060 case RPC_SVC_THRMAX_GET: 1061 *((int *)info) = svc_thr_max; 1062 return (TRUE); 1063 case RPC_SVC_THRTOTAL_GET: 1064 *((int *)info) = svc_thr_total; 1065 return (TRUE); 1066 case RPC_SVC_THRCREATES_GET: 1067 *((int *)info) = svc_thr_total_creates; 1068 return (TRUE); 1069 case RPC_SVC_THRERRORS_GET: 1070 *((int *)info) = svc_thr_total_create_errors; 1071 return (TRUE); 1072 case RPC_SVC_USE_POLLFD: 1073 if (*((int *)info) && !__rpc_use_pollfd_done) { 1074 __rpc_use_pollfd_done = 1; 1075 return (TRUE); 1076 } 1077 return (FALSE); 1078 case __RPC_CLNT_MINFD_SET: 1079 tmp = *((int *)info); 1080 if (tmp < 0) 1081 return (FALSE); 1082 __rpc_minfd = tmp; 1083 return (TRUE); 1084 case __RPC_CLNT_MINFD_GET: 1085 *((int *)info) = __rpc_minfd; 1086 return (TRUE); 1087 case RPC_SVC_CONNMAXREC_SET: 1088 tmp = __rpc_legal_connmaxrec(*(int *)info); 1089 if (tmp >= 0) { 1090 __rpc_connmaxrec = tmp; 1091 return (TRUE); 1092 } else { 1093 return (FALSE); 1094 } 1095 case RPC_SVC_CONNMAXREC_GET: 1096 *((int *)info) = __rpc_connmaxrec; 1097 return (TRUE); 1098 case RPC_SVC_IRTIMEOUT_SET: 1099 tmp = *((int *)info); 1100 if (tmp >= 0) { 1101 __rpc_irtimeout = tmp; 1102 return (TRUE); 1103 } else { 1104 return (FALSE); 1105 } 1106 /* 1107 * No mutex necessary as _EXCLBIND_SET will/should only 1108 * be used before an RPC daemon goes mt-hot. 1109 */ 1110 case __RPC_SVC_EXCLBIND_SET: 1111 if (info) { 1112 __rpc_tp_exclbind = *((bool_t *)info); 1113 return (TRUE); 1114 } 1115 return (FALSE); 1116 case __RPC_SVC_EXCLBIND_GET: 1117 if (info) { 1118 *((bool_t *)info) = __rpc_tp_exclbind; 1119 return (TRUE); 1120 } 1121 return (FALSE); 1122 1123 default: 1124 return (FALSE); 1125 } 1126 } 1127