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 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <signal.h> 27 #include <sys/types.h> 28 #include <sys/time.h> 29 #include <sys/socket.h> 30 #include <netinet/in.h> 31 #include <netinet/tcp.h> 32 #include <arpa/inet.h> 33 #include <netdb.h> 34 #include <fcntl.h> 35 #include <string.h> 36 #include <memory.h> 37 #include <sys/param.h> 38 #include <sys/pathconf.h> 39 #include <netdir.h> 40 #include <netconfig.h> 41 #include <sys/sockio.h> 42 #include <net/if.h> 43 #include <sys/resource.h> 44 #include <stdio.h> 45 #include <errno.h> 46 #include <assert.h> 47 #include <locale.h> 48 #include <unistd.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <strings.h> 52 #include <sys/unistat/spcs_s.h> 53 #include <sys/unistat/spcs_s_u.h> 54 #include <sys/unistat/spcs_errors.h> 55 56 #include <sys/nsctl/cfg.h> 57 #include <sys/nsctl/cfg_lockd.h> 58 59 #ifdef DEBUG 60 #define DPF(m) if (debug) (void) fprintf m 61 #else 62 #define DPF(m) 63 #endif 64 65 #ifdef TTY_MESSAGES 66 #define CLOSE_FD 3 67 #else 68 #define CLOSE_FD 0 69 #endif 70 71 #define MAX_LOCKQ 1024 72 #define MAX_DAEMONS 1024 73 #define MAX_LOCAL 1024 74 #define MAX_UNLOCK 32 75 #define MAX_TIMEOUTS 3 76 #define TIMEOUT_SECS 5 77 78 static char program[] = "dscfglockd"; 79 static int debug; 80 static int lstate; 81 static int msgtrace; 82 static FILE *debugfile = NULL; 83 84 struct lock_req { 85 cfglockd_t type; /* read or write */ 86 pid_t pid; /* pid of read locker or local writer */ 87 daemonaddr_t remote; /* remote machine requesting write lock */ 88 int state; /* for write locks */ 89 int32_t order; /* who gets priority? */ 90 } lock_queue[MAX_LOCKQ]; 91 92 struct unlock_s { 93 pid_t pid; /* pid of locker */ 94 uint8_t seq; /* seq number of last lock request */ 95 } unlock_buf[MAX_UNLOCK]; 96 97 int next_req; 98 int32_t order; 99 100 #define lock_wanted lock_queue[0] 101 long ticker = 1l; 102 103 #define ALIVE 0x10 104 #define READ_LOCK 0x11 105 #define WRITE_LOCK 0x12 106 #define UNLOCK 0x13 107 #define GRANTED 0x14 108 109 int next_q; 110 111 struct { 112 cfglockd_t type; 113 int nholders; 114 int state; 115 daemonaddr_t holder; 116 struct lockdaemon *remote_daemon; 117 pid_t holding_pid[MAX_LOCAL]; 118 } the_lock; 119 120 daemonaddr_t thishost; 121 daemonaddr_t localhost; 122 123 #define STATE_CLEAR 0 124 #define STATE_ASKED 1 125 #define STATE_OKAYED 2 126 #define STATE_WANTS 3 127 #define lockdaemon_dead(ldp) ((ticker - (ldp)->timeout) > MAX_TIMEOUTS) 128 #define CRIT_BEGIN() (void) sighold(SIGALRM) 129 #define CRIT_END() (void) sigrelse(SIGALRM) 130 131 #define NORMAL_UNLOCK 0 132 #define FORCE_UNLOCK 1 133 134 struct lockdaemon { 135 daemonaddr_t host; 136 int up; 137 long timeout; 138 int inuse; 139 int state; 140 int32_t order; 141 } daemon_list[MAX_DAEMONS]; 142 143 unsigned short lock_port = CFG_SERVER_PORT; 144 int lock_soc = 0; 145 int pf_inet = PF_INET; 146 #define dp_addr(p) inet_ntoa(((struct sockaddr_in *)p)->sin_addr) 147 148 #define MAXIFS 32 149 150 static char * 151 lockd_type(cfglockd_t type) 152 { 153 switch (type) { 154 case LOCK_NOTLOCKED: return "NotLocked"; 155 case LOCK_READ: return "Read"; 156 case LOCK_WRITE: return "Write"; 157 case LOCK_LOCKED: return "Locked"; 158 case LOCK_LOCKEDBY: return "LockedBy"; 159 case LOCK_STAT: return "Stat"; 160 case LOCK_ACK: return "Ack"; 161 default: return "*unknown*"; 162 } 163 } 164 165 static char * 166 lockd_state(int state) 167 { 168 switch (state) { 169 case STATE_CLEAR: return "Clear"; 170 case STATE_ASKED: return "Asked"; 171 case STATE_OKAYED: return "Okayed"; 172 case STATE_WANTS: return "Wants"; 173 default: return "*unknown*"; 174 } 175 } 176 177 static char * 178 lockd_msg(int message) 179 { 180 switch (message) { 181 case ALIVE: return "Alive"; 182 case READ_LOCK: return "ReadLock"; 183 case WRITE_LOCK: return "WriteLock"; 184 case UNLOCK: return "Unlock"; 185 case GRANTED: return "Granted"; 186 default: return lockd_type((cfglockd_t)message); 187 } 188 } 189 190 /* 191 * The following is stolen from autod_nfs.c 192 */ 193 static void 194 getmyaddrs(struct ifconf *ifc) 195 { 196 int sock; 197 int numifs; 198 char *buf; 199 int family; 200 201 ifc->ifc_buf = NULL; 202 ifc->ifc_len = 0; 203 204 #ifdef AF_INET6 205 family = AF_INET6; 206 #else 207 family = AF_INET; 208 #endif 209 if ((sock = socket(family, SOCK_DGRAM, 0)) < 0) { 210 #ifdef DEBUG 211 perror("getmyaddrs(): socket"); 212 #endif 213 return; 214 } 215 216 if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) { 217 #ifdef DEBUG 218 perror("getmyaddrs(): SIOCGIFNUM"); 219 #endif 220 numifs = MAXIFS; 221 } 222 223 buf = (char *)malloc(numifs * sizeof (struct ifreq)); 224 if (buf == NULL) { 225 #ifdef DEBUG 226 (void) fprintf(stderr, "getmyaddrs(): malloc failed\n"); 227 #endif 228 (void) close(sock); 229 return; 230 } 231 232 ifc->ifc_buf = buf; 233 ifc->ifc_len = numifs * sizeof (struct ifreq); 234 235 if (ioctl(sock, SIOCGIFCONF, (char *)ifc) < 0) { 236 #ifdef DEBUG 237 perror("getmyaddrs(): SIOCGIFCONF"); 238 #endif 239 } 240 241 (void) close(sock); 242 } 243 244 struct ifconf *ifc; 245 246 static int 247 cmp_addr(daemonaddr_t *a, daemonaddr_t *b) 248 { 249 int rc; 250 rc = memcmp(&(a->sin_addr), &(b->sin_addr), sizeof (a->sin_addr)); 251 DPF((stderr, "compare %s %hu with", dp_addr(a), a->sin_port)); 252 DPF((stderr, " %s %hu = %d\n", dp_addr(b), b->sin_port, rc)); 253 return (rc); 254 } 255 256 static int 257 addr_is_holder(int32_t order) 258 { 259 return ((the_lock.nholders > 0) && the_lock.remote_daemon != NULL && 260 (order == the_lock.remote_daemon->order)); 261 } 262 263 static int 264 islocalhost(daemonaddr_t *host) 265 { 266 int n; 267 struct sockaddr_in *s1, *s2; 268 struct ifreq *ifr; 269 int retval = 0; 270 271 ifr = ifc->ifc_req; 272 n = ifc->ifc_len / sizeof (struct ifreq); 273 s1 = host; 274 s2 = NULL; 275 for (; n > 0; n--, ifr++) { 276 if (ifr->ifr_addr.sa_family != AF_INET) 277 continue; 278 279 /* LINTED pointer alignment */ 280 s2 = (struct sockaddr_in *)&ifr->ifr_addr; 281 282 if (memcmp((char *)&s2->sin_addr, 283 (char *)&s1->sin_addr, sizeof (s1->sin_addr)) == 0) { 284 retval = 1; 285 /* it's me */ 286 break; 287 } 288 } 289 return (retval); 290 } 291 292 static void 293 send_lockmsg(int cmd, pid_t pid, daemonaddr_t *dp, uint8_t seq) 294 { 295 struct lock_msg message_buf; 296 int rc; 297 298 if (msgtrace && debugfile) { 299 time_t t = time(0); 300 (void) fprintf(debugfile, "%19.19s send %-9.9s to %s\n", 301 ctime(&t), lockd_msg(cmd), dp_addr(dp)); 302 } 303 DPF((stderr, "send %d to %s port %hu\n", cmd, 304 dp_addr(dp), dp->sin_port)); 305 message_buf.message = cmd; 306 message_buf.pid = pid; 307 message_buf.order = order; 308 message_buf.seq = seq; 309 do { 310 rc = sendto(lock_soc, &message_buf, sizeof (message_buf), 0, 311 (struct sockaddr *)dp, sizeof (struct sockaddr)); 312 } while (rc == -1 && errno == EINTR); 313 if (rc == -1) 314 spcs_log("cfglockd", NULL, "sendto rc -1 errno %d", errno); 315 } 316 317 /* 318 * send an alive message to all configured daemons so that they can tell 319 * us if they are holding a write lock. 320 */ 321 322 static void 323 send_aliveall() 324 { 325 struct lockdaemon *ldp; 326 int i; 327 for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) { 328 if (ldp->inuse == 0) 329 break; 330 send_lockmsg(ALIVE, (pid_t)0, &(ldp->host), 0); 331 } 332 } 333 334 /* find the lock daemon structure for a give daemon address */ 335 336 static struct lockdaemon * 337 find_lockdaemon(daemonaddr_t *d) 338 { 339 struct lockdaemon *ldp; 340 int i; 341 for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) { 342 if (ldp->inuse == 0) 343 break; 344 if (cmp_addr(&(ldp->host), d) == 0) 345 return (ldp); 346 } 347 return (NULL); 348 } 349 350 /* 351 * a messge has been received from daemon, note this and if the daemon 352 * was previously dead and we have the write lock tell it that we do. 353 */ 354 355 static void 356 daemon_alive(daemonaddr_t *daemon, int32_t order) 357 { 358 struct lockdaemon *ldp; 359 int i; 360 361 for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) { 362 if (ldp->inuse == 0) 363 break; 364 if (cmp_addr(&(ldp->host), daemon) == 0) { 365 ldp->order = order; 366 ldp->timeout = ticker; 367 if (ldp->up == 0) { 368 spcs_log("cfglockd", NULL, 369 "daemon restarted on %s\n", 370 dp_addr(daemon)); 371 DPF((stderr, "daemon restarted on %s\n", 372 dp_addr(daemon))); 373 ldp->up = 1; 374 goto come_up; 375 } 376 return; 377 } 378 } 379 /* new daemon has announced itself */ 380 if (i < MAX_DAEMONS) { 381 DPF((stderr, "new daemon on %s\n", dp_addr(daemon))); 382 spcs_log("cfglockd", NULL, 383 "new daemon on %s\n", dp_addr(daemon)); 384 ldp->host = *daemon; 385 ldp->inuse = 1; 386 ldp->timeout = ticker; 387 ldp->order = order; 388 } else { 389 /* problem, more daemons than expected */ 390 i++; 391 } 392 come_up: 393 if (the_lock.type == LOCK_WRITE && the_lock.remote_daemon == NULL) 394 send_lockmsg(WRITE_LOCK, (pid_t)0, daemon, 0); 395 } 396 397 static void 398 delete_queue_entry(struct lock_req *req) 399 { 400 int i; 401 402 for (i = (req - lock_queue); i++ < next_req; req++) 403 *req = *(req+1); 404 next_req--; 405 } 406 407 static void 408 take_lock(int ackmessage) 409 { 410 send_lockmsg(ackmessage, (pid_t)0, &lock_wanted.remote, 0); 411 delete_queue_entry(lock_queue); 412 } 413 414 static void 415 check_for_write_lock() 416 { 417 struct lockdaemon *ldp; 418 int i; 419 int wait = 0; 420 421 DPF((stderr, "check for lock\n")); 422 if (lock_wanted.state != STATE_ASKED) 423 return; 424 for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) { 425 if (ldp->inuse == 0) 426 break; 427 if (ldp->up && ldp->state != STATE_OKAYED) { 428 wait = 1; 429 break; 430 } 431 } 432 if (wait == 0 && lock_wanted.type == LOCK_WRITE) { 433 the_lock.type = LOCK_WRITE; 434 the_lock.holding_pid[0] = lock_wanted.pid; 435 the_lock.nholders = 1; 436 the_lock.state = STATE_CLEAR; 437 take_lock(LOCK_LOCKED); 438 } 439 } 440 441 static void 442 lock_granted(daemonaddr_t *da) 443 { 444 struct lockdaemon *ldp; 445 446 if ((ldp = find_lockdaemon(da)) != NULL) { 447 /* if we already own the lock, throw the msg away */ 448 if (the_lock.remote_daemon == NULL && 449 the_lock.type == LOCK_WRITE) { 450 return; 451 } 452 453 /* 454 * If the current lock isn't a write lock and we're not 455 * asking for one 456 * -OR- 457 * The current lock is a write lock and it's not owned by us 458 * -THEN- 459 * send back an unlocked message. 460 */ 461 if ((the_lock.type != LOCK_WRITE && 462 the_lock.state != STATE_ASKED) || 463 (the_lock.type == LOCK_WRITE && 464 the_lock.remote_daemon != NULL)) { 465 send_lockmsg(UNLOCK, (pid_t)0, &(ldp->host), 0); 466 return; 467 } 468 ldp->state = STATE_OKAYED; 469 } 470 check_for_write_lock(); 471 } 472 473 static int 474 try_lock() 475 { 476 struct lockdaemon *ldp; 477 int i; 478 479 switch (the_lock.type) { 480 case LOCK_READ: 481 if (lock_wanted.type == LOCK_READ) { 482 i = the_lock.nholders++; 483 the_lock.holding_pid[i] = lock_wanted.pid; 484 the_lock.state = STATE_CLEAR; 485 DPF((stderr, "increment read lockers to %d\n", 486 the_lock.nholders)); 487 take_lock(LOCK_LOCKED); 488 break; 489 } 490 /* write lock has to wait */ 491 break; 492 case LOCK_WRITE: 493 /* lock has to wait until write lock is cleared */ 494 break; 495 case LOCK_NOTLOCKED: 496 if (lock_wanted.type == LOCK_READ) { 497 DPF((stderr, "local locker, 1 lock holder\n")); 498 the_lock.holding_pid[0] = lock_wanted.pid; 499 the_lock.nholders = 1; 500 the_lock.type = LOCK_READ; 501 the_lock.state = STATE_CLEAR; 502 the_lock.remote_daemon = NULL; 503 take_lock(LOCK_LOCKED); 504 return (1); 505 } 506 if (islocalhost(&lock_wanted.remote)) { 507 DPF((stderr, "local locker, take write lock\n")); 508 /* tell everyone I'm locking */ 509 if (lock_wanted.state != STATE_ASKED) { 510 for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; 511 i++, ldp++) { 512 if (ldp->inuse == 0) 513 break; 514 ldp->state = STATE_ASKED; 515 send_lockmsg(WRITE_LOCK, (pid_t)0, 516 &(ldp->host), 0); 517 } 518 } 519 lock_wanted.state = STATE_ASKED; 520 check_for_write_lock(); 521 the_lock.remote_daemon = NULL; 522 the_lock.state = STATE_ASKED; 523 return (0); 524 } else { 525 DPF((stderr, "remote locker, take write lock\n")); 526 the_lock.type = LOCK_WRITE; 527 the_lock.holder = lock_wanted.remote; 528 the_lock.nholders = 1; 529 the_lock.remote_daemon = 530 find_lockdaemon(&the_lock.holder); 531 the_lock.state = STATE_CLEAR; 532 /* okay to remote */ 533 take_lock(GRANTED); 534 } 535 break; 536 default: 537 DPF((stderr, "weird lock type held - %d\n", the_lock.type)); 538 the_lock.type = LOCK_NOTLOCKED; 539 break; 540 } 541 return (0); 542 } 543 544 static void 545 process_queue() 546 { 547 if (next_req < 1) 548 return; /* no locks queued */ 549 while (try_lock()) 550 ; 551 } 552 553 static int 554 lock_sort(const void *a, const void *b) 555 { 556 struct lock_req *left = (struct lock_req *)a; 557 struct lock_req *right = (struct lock_req *)b; 558 559 return (left->order - right->order); 560 } 561 562 static void 563 queue_lock(cfglockd_t type, struct lock_msg *msg, daemonaddr_t *addr) 564 { 565 int i; 566 struct lock_req *lrp; 567 struct lockdaemon *ldp; 568 569 /* first check if new lock matches current lock */ 570 if (the_lock.type == type && addr_is_holder(msg->order)) { 571 /* remote daemon missed locked message */ 572 send_lockmsg(GRANTED, (pid_t)0, addr, msg->seq); 573 return; 574 } 575 576 /* next search queue to check for duplicate */ 577 for (i = 0, lrp = lock_queue; i++ < next_req; lrp++) { 578 if (lrp->type == type && lrp->pid == msg->pid && 579 cmp_addr(addr, &(lrp->remote)) == 0) 580 return; 581 582 } 583 584 /* 585 * It's a new lock request. Are we in the middle of 586 * obtaining one for ourselves? 587 */ 588 589 if (the_lock.type == LOCK_NOTLOCKED && the_lock.state == STATE_ASKED) { 590 /* did a higher priority request just come in? */ 591 if (msg->order < order) { 592 /* requeue our request */ 593 the_lock.state = STATE_CLEAR; 594 lock_wanted.state = STATE_CLEAR; 595 596 /* let the other lockds know */ 597 for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; 598 i++, ldp++) { 599 if (ldp->inuse == 0) 600 break; 601 if (ldp->up && ldp->state == STATE_OKAYED) { 602 send_lockmsg(UNLOCK, (pid_t)0, 603 &(ldp->host), 0); 604 } 605 } 606 } 607 } 608 609 610 lrp = lock_queue; 611 lrp += (next_req++); 612 lrp->type = type; 613 lrp->pid = msg->pid; 614 lrp->state = STATE_CLEAR; 615 lrp->order = msg->order; 616 if (addr) { 617 lrp->remote = *addr; 618 } 619 620 if (next_req > 1) 621 qsort(lock_queue, next_req, sizeof (lock_queue[0]), lock_sort); 622 623 if (the_lock.type != LOCK_WRITE) 624 process_queue(); 625 } 626 627 static void 628 lock_stat() 629 { 630 char *lt = "Unknown"; 631 struct lockdaemon *ldp; 632 int i; 633 634 spcs_log("cfglockd", NULL, 635 "%s, Lock daemon built %s **********", program, __DATE__); 636 switch (the_lock.type) { 637 case LOCK_NOTLOCKED: 638 lt = "not locked"; 639 break; 640 case LOCK_READ: 641 lt = "read locked"; 642 break; 643 case LOCK_WRITE: 644 lt = "write locked"; 645 break; 646 } 647 spcs_log("cfglockd", NULL, "Lock is %s (%d)", lt, the_lock.type); 648 spcs_log("cfglockd", NULL, "There are %d holders of the lock", 649 the_lock.nholders); 650 if (the_lock.nholders > 0) { 651 for (i = 0; i < the_lock.nholders; i++) 652 spcs_log("cfglockd", NULL, "holding_pid[%d] = %6d", i, 653 the_lock.holding_pid[i]); 654 } 655 spcs_log("cfglockd", NULL, "holder daemon was %s port %hu, remote %x", 656 dp_addr(&the_lock.holder), the_lock.holder.sin_port, 657 the_lock.remote_daemon); 658 spcs_log("cfglockd", NULL, "Lock queue, %d requests", next_req); 659 for (i = 0; i < next_req; i++) { 660 spcs_log("cfglockd", NULL, "request %d type %d order %d", i, 661 lock_queue[i].type, lock_queue[i].order); 662 spcs_log("cfglockd", NULL, " client %s port %hu, pid %d", 663 dp_addr(&lock_queue[i].remote), 664 lock_queue[i].remote.sin_port, lock_queue[i].pid); 665 } 666 spcs_log("cfglockd", NULL, "Daemon list"); 667 668 for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) { 669 if (ldp->inuse == 0) 670 break; 671 spcs_log("cfglockd", NULL, "daemon %d, %s port %hu", i, 672 dp_addr(&ldp->host), ldp->host.sin_port); 673 spcs_log("cfglockd", NULL, 674 " up %d timeout %ld missed %d state %d\n", ldp->up, 675 ldp->timeout, ticker - ldp->timeout, ldp->state); 676 } 677 } 678 679 static int 680 is_duplicate(cfglockd_t type, pid_t pid, uint8_t seq) 681 { 682 struct unlock_s *bufp; 683 int i; 684 685 if (!pid) { 686 return (0); 687 } 688 689 for (i = 0, bufp = unlock_buf; bufp->pid && i < MAX_UNLOCK; 690 i++, bufp++) { 691 if (bufp->pid == pid && bufp->seq == seq) { 692 /* throw message away */ 693 #ifdef DEBUG 694 spcs_log("cfglockd", NULL, 695 "duplicate '%d' request received from %d", 696 type, pid); 697 #endif 698 return (1); 699 } 700 } 701 702 /* add it to the list */ 703 bcopy(unlock_buf, &unlock_buf[ 1 ], 704 sizeof (unlock_buf) - sizeof (struct unlock_s)); 705 (*unlock_buf).pid = pid; 706 (*unlock_buf).seq = seq; 707 708 return (0); 709 } 710 711 static void 712 local_lock(cfglockd_t type, struct lock_msg *msg, daemonaddr_t *client) 713 { 714 if (is_duplicate(type, msg->pid, msg->seq)) { 715 if (the_lock.remote_daemon == NULL && 716 (the_lock.type == LOCK_WRITE || 717 the_lock.type == LOCK_READ) && 718 the_lock.holding_pid[0] == msg->pid) { 719 send_lockmsg(LOCK_LOCKED, (pid_t)0, client, msg->seq); 720 } 721 } else { 722 queue_lock(type, msg, client); 723 } 724 } 725 726 static void 727 remote_lock(struct sockaddr_in *remote, struct lock_msg *msg) 728 { 729 /* make sure remote knows we are alive */ 730 send_lockmsg(ALIVE, (pid_t)0, remote, 0); 731 732 /* clear out pid as it is meaningless on this node */ 733 msg->pid = (pid_t)0; 734 735 queue_lock(LOCK_WRITE, msg, (daemonaddr_t *)remote); 736 } 737 738 static void 739 unqueue_lock(daemonaddr_t *d, pid_t pid) 740 { 741 int i; 742 struct lock_req *lrp, *xrp; 743 int diff; 744 745 /* search queue to delete ungranted locks */ 746 for (i = 0, xrp = lrp = lock_queue; i++ < next_req; lrp++) { 747 *xrp = *lrp; 748 diff = 0; 749 if (pid != (pid_t)0 && lrp->pid != pid) 750 diff = 1; 751 if (d != NULL && cmp_addr(d, &(lrp->remote)) != 0) 752 diff = 1; 753 if (!diff) 754 continue; 755 756 xrp++; 757 } 758 next_req = xrp - lock_queue; 759 } 760 761 static void 762 xxunlock() 763 { 764 DPF((stderr, "** UNLOCK **\n")); 765 the_lock.remote_daemon = NULL; 766 the_lock.type = LOCK_NOTLOCKED; 767 the_lock.nholders = 0; 768 the_lock.state = STATE_CLEAR; 769 process_queue(); 770 } 771 772 773 static void 774 local_unlock(pid_t pid, uint8_t seq, int method) 775 { 776 struct lockdaemon *ldp; 777 int i; 778 779 if (method == NORMAL_UNLOCK && is_duplicate(LOCK_NOTLOCKED, pid, seq)) { 780 return; 781 } 782 783 if (the_lock.type == LOCK_READ) { 784 /* delete reference to pid of reading process */ 785 for (i = 0; i < the_lock.nholders; i++) { 786 if (the_lock.holding_pid[i] == pid) { 787 DPF((stderr, "decrement lockers from %d\n", 788 the_lock.nholders)); 789 --the_lock.nholders; 790 break; 791 } 792 } 793 for (; i < the_lock.nholders; i++) { 794 the_lock.holding_pid[i] = the_lock.holding_pid[i+1]; 795 } 796 if (the_lock.nholders > 0) 797 return; 798 } else { 799 /* LOCK_WRITE */ 800 if (pid != the_lock.holding_pid[0]) 801 return; 802 the_lock.holding_pid[0] = (pid_t)0; 803 for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) { 804 if (ldp->inuse == 0) 805 break; 806 if (ldp->up) 807 send_lockmsg(UNLOCK, (pid_t)0, &(ldp->host), 0); 808 } 809 } 810 xxunlock(); 811 } 812 813 static void 814 remote_unlock(int32_t order, daemonaddr_t *d) 815 { 816 int i; 817 struct lock_req *lrp; 818 819 DPF((stderr, "remote unlock from %s ", dp_addr(d))); 820 DPF((stderr, "when %s holds lock\n", dp_addr(&the_lock.holder))); 821 822 /* search queue to check for ungranted lock */ 823 for (i = 0, lrp = lock_queue; i++ < next_req; lrp++) { 824 if (lrp->type == LOCK_WRITE && 825 cmp_addr(d, &(lrp->remote)) == 0) { 826 delete_queue_entry(lrp); 827 return; 828 } 829 830 } 831 if (addr_is_holder(order)) { 832 xxunlock(); 833 } 834 } 835 836 static void 837 lockedby(daemonaddr_t *d, uint8_t seq) 838 { 839 DPF((stderr, "lockby enquiry from %s ", dp_addr(d))); 840 switch (the_lock.type) { 841 case LOCK_NOTLOCKED: 842 send_lockmsg(LOCK_NOTLOCKED, (pid_t)0, d, seq); 843 break; 844 case LOCK_READ: 845 send_lockmsg(LOCK_READ, the_lock.holding_pid[0], d, seq); 846 break; 847 case LOCK_WRITE: 848 send_lockmsg(LOCK_WRITE, the_lock.holding_pid[0], d, seq); 849 break; 850 } 851 } 852 853 /* ARGSUSED */ 854 static void 855 keepalive(int signo) 856 { 857 int i; 858 struct lock_req *locker; 859 struct lockdaemon *ldp; 860 861 DPF((stderr, "keepalive...\n")); 862 ticker++; 863 864 /* 865 * tell any other daemon that has a lock request in our queue that 866 * this daemon is still alive. 867 */ 868 869 for (i = 0, locker = lock_queue; i < next_req; i++, locker++) { 870 if (locker->pid == 0) /* remote lock request */ 871 send_lockmsg(ALIVE, (pid_t)0, &(locker->remote), 0); 872 } 873 874 /* 875 * if a remote daemon holds the lock, check it is still alive and 876 * if the remote daemon is sent it a grant message in case the 877 * remote daemon missed our original grant. 878 */ 879 880 if (the_lock.remote_daemon) { 881 if (lockdaemon_dead(the_lock.remote_daemon)) { 882 DPF((stderr, "lock owner died\n")); 883 the_lock.remote_daemon->up = 0; 884 xxunlock(); 885 } else { 886 send_lockmsg(GRANTED, (pid_t)0, &the_lock.holder, 0); 887 } 888 } 889 890 /* 891 * check for response from daemons preventing this daemon 892 * from taking a write lock by not sending a grant message. 893 * if the remote daemon is alive send another lock request, 894 * otherwise mark it as dead. 895 * send alive message to any live remote daemons if this 896 * daemon has the write lock. 897 */ 898 if (lstate) { 899 (void) printf("\nlock: %s\n", lockd_type(the_lock.type)); 900 (void) printf(" no. holders: %d\n", the_lock.nholders); 901 (void) printf(" hold addr : %s\n", the_lock.remote_daemon? 902 dp_addr(the_lock.remote_daemon): "0.0.0.0"); 903 (void) printf(" holding pid:"); 904 for (i = 0; i < the_lock.nholders; i++) { 905 (void) printf(" %ld", the_lock.holding_pid[ i ]); 906 } 907 (void) printf("\n"); 908 } 909 for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) { 910 if (ldp->inuse == 0) 911 break; 912 913 if (lstate) { 914 (void) printf("%-15.15s ", dp_addr(&ldp->host)); 915 (void) printf("%-4.4s ", ldp->up? "up" : "down"); 916 (void) printf("%5ld ", ldp->timeout); 917 (void) printf("%-10.10s ", lockd_state(ldp->state)); 918 (void) printf("%6d\n", ldp->order); 919 } 920 921 if (ldp->state == STATE_ASKED) { 922 if (lockdaemon_dead(ldp)) { 923 ldp->up = 0; 924 ldp->state = STATE_CLEAR; 925 continue; 926 } 927 send_lockmsg(WRITE_LOCK, (pid_t)0, &(ldp->host), 0); 928 continue; 929 } 930 if (the_lock.type == LOCK_WRITE && 931 the_lock.remote_daemon == NULL) 932 send_lockmsg(ALIVE, (pid_t)0, &(ldp->host), 0); 933 } 934 } 935 936 static void 937 dispatch(struct lock_msg *mp, daemonaddr_t *host) 938 { 939 int message = mp->message; 940 int localhost; 941 942 localhost = islocalhost(host); 943 if (msgtrace && debugfile) { 944 time_t t = time(0); 945 if (localhost) { 946 (void) fprintf(debugfile, 947 "%19.19s recv %-9.9s from %s (%ld)\n", ctime(&t), 948 lockd_msg(message), dp_addr(host), mp->pid); 949 } else { 950 (void) fprintf(debugfile, 951 "%19.19s recv %-9.9s from %s order %d (%ld)\n", 952 ctime(&t), lockd_msg(message), dp_addr(host), 953 mp->order, mp->pid); 954 } 955 } 956 DPF((stderr, "received message %d\n", message)); 957 DPF((stderr, "from %s port %hu\n", dp_addr(host), host->sin_port)); 958 if (!localhost) 959 daemon_alive(host, mp->order); 960 else 961 mp->order = order; 962 switch (message) { 963 case ALIVE: 964 DPF((stderr, "received ALIVE %s\n", dp_addr(host))); 965 /* do nothing, general "not localhost" code above does this */ 966 break; 967 case UNLOCK: 968 DPF((stderr, "received UNLOCK\n")); 969 remote_unlock(mp->order, host); 970 break; 971 case GRANTED: 972 DPF((stderr, "received GRANTED\n")); 973 lock_granted(host); 974 break; 975 case WRITE_LOCK: 976 DPF((stderr, "received WRITE_LOCK\n")); 977 assert(!localhost); 978 remote_lock(host, mp); 979 break; 980 case READ_LOCK: 981 case LOCK_READ: 982 DPF((stderr, "received READ_LOCK\n")); 983 assert(localhost); 984 local_lock(LOCK_READ, mp, host); 985 break; 986 case LOCK_WRITE: 987 DPF((stderr, "received LOCK_WRITE\n")); 988 assert(localhost); 989 local_lock(LOCK_WRITE, mp, host); 990 break; 991 case LOCK_NOTLOCKED: 992 DPF((stderr, "received LOCK_NOTLOCKED\n")); 993 send_lockmsg(LOCK_ACK, (pid_t)0, host, mp->seq); 994 if (the_lock.type != LOCK_NOTLOCKED) { 995 local_unlock(mp->pid, mp->seq, NORMAL_UNLOCK); 996 } 997 break; 998 case LOCK_LOCKEDBY: 999 lockedby(host, mp->seq); 1000 break; 1001 case LOCK_STAT: 1002 lock_stat(); 1003 break; 1004 case LOCK_ACK: 1005 /* throw message away -- this is an error to receive */ 1006 break; 1007 } 1008 } 1009 1010 /* 1011 * unqueue any locks asked for by pid and unlock any locks held by pid. 1012 */ 1013 1014 static void 1015 purge_pid(pid_t pid) 1016 { 1017 DPF((stderr, "purge locks for %ld\n", pid)); 1018 unqueue_lock(NULL, pid); 1019 if (the_lock.type != LOCK_NOTLOCKED) 1020 local_unlock(pid, 0, FORCE_UNLOCK); 1021 } 1022 1023 /* 1024 * Check for exit or exec of client processes. 1025 * The lock protecting the processes pid in the lockfile will 1026 * be removed by the kernel when a client exits or execs. 1027 */ 1028 1029 static void 1030 check_for_dead() 1031 { 1032 int i, x; 1033 pid_t pid; 1034 1035 for (i = 0; (x = cfg_filelock(i, 0)) != CFG_LF_EOF; i++) { 1036 if (x == CFG_LF_AGAIN) 1037 continue; /* can't take lock, must be still alive */ 1038 cfg_readpid(i, &pid); 1039 cfg_writepid(i, (pid_t)0); 1040 (void) cfg_fileunlock(i); 1041 if (pid != (pid_t)0) 1042 purge_pid(pid); 1043 } 1044 } 1045 1046 static void 1047 build_daemon_list(char *cf_file, int exe) 1048 { 1049 FILE *fp; 1050 char host[1024]; 1051 int port; 1052 int i; 1053 struct hostent *hp; 1054 struct lockdaemon *ldp; 1055 1056 if ((hp = gethostbyname("localhost")) == NULL) { 1057 (void) fprintf(stderr, "%s: Can't find hostent for %s\n", 1058 program, "localhost"); 1059 spcs_log("cfglockd", NULL, "couldn't find localhost"); 1060 exit(1); 1061 } 1062 1063 (void) memcpy(&(localhost.sin_addr.s_addr), *(hp->h_addr_list), 1064 sizeof (localhost.sin_addr)); 1065 if (cf_file == NULL) { 1066 (void) endhostent(); 1067 return; 1068 } 1069 if (exe) { 1070 if ((fp = popen(cf_file, "r")) == NULL) { 1071 perror(cf_file); 1072 (void) fprintf(stderr, 1073 "%s: Can't open config program\n", program); 1074 spcs_log("cfglockd", NULL, "couldn't read config"); 1075 exit(1); 1076 } 1077 } else { 1078 if ((fp = fopen(cf_file, "r")) == NULL) { 1079 perror(cf_file); 1080 (void) fprintf(stderr, "%s: Can't open config file\n", 1081 program); 1082 spcs_log("cfglockd", NULL, "couldn't read config"); 1083 exit(1); 1084 } 1085 } 1086 ldp = daemon_list; 1087 while ((i = fscanf(fp, "%s %d\n", host, &port)) != EOF) { 1088 if (host[0] == '#') /* line starting with # are comments */ 1089 continue; 1090 if (i == 1) { 1091 port = lock_port; 1092 } else { 1093 if (strcmp(host, "localhost") == 0) { 1094 lock_port = port; 1095 continue; 1096 } 1097 } 1098 1099 if ((hp = gethostbyname(host)) == NULL) { 1100 (void) fprintf(stderr, 1101 "%s: Can't find hostent for %s\n", program, host); 1102 continue; 1103 } 1104 1105 (void) memcpy(&(ldp->host.sin_addr.s_addr), *(hp->h_addr_list), 1106 sizeof (ldp->host.sin_addr)); 1107 DPF((stderr, "daemon: %s\t%s\n", 1108 inet_ntoa(ldp->host.sin_addr), hp->h_name)); 1109 if (islocalhost(&(ldp->host))) { 1110 DPF((stderr, "is an alias for this host, skipping\n")); 1111 continue; 1112 } 1113 ldp->host.sin_port = htons((short)port); 1114 ldp->host.sin_family = hp->h_addrtype; 1115 ldp->inuse = 1; 1116 ldp->up = 1; 1117 ldp++; 1118 } 1119 if (exe) 1120 (void) pclose(fp); 1121 else 1122 (void) fclose(fp); 1123 (void) endhostent(); 1124 } 1125 1126 static void 1127 usage() 1128 { 1129 (void) fprintf(stderr, 1130 gettext("usage: %s [-d] [-f file]|[-e program]\n"), program); 1131 exit(1); 1132 } 1133 1134 static void 1135 unexpected(int sig) 1136 { 1137 spcs_log("cfglockd", NULL, "pid %d unexpected signal %d, ignoring", 1138 getpid(), sig); 1139 } 1140 1141 static void 1142 term(int sig) 1143 { 1144 (void) unlink(CFG_PIDFILE); 1145 spcs_log("cfglockd", NULL, "pid %d terminate on signal %d", getpid(), 1146 sig); 1147 exit(0); 1148 } 1149 1150 static void 1151 init(int argc, char *argv[]) 1152 { 1153 #if defined(_SunOS_5_6) || defined(_SunOS_5_7) || defined(_SunOS_5_8) 1154 struct rlimit rl; 1155 #endif 1156 int c, i, x; 1157 int rc; 1158 char *cp = NULL; 1159 struct itimerval tv; 1160 struct timeval tp; 1161 socklen_t len = sizeof (thishost); 1162 int exe = 0; 1163 pid_t pid; 1164 FILE *fp; 1165 1166 lstate = (getenv("LOCKD_STATE") != NULL); 1167 msgtrace = (getenv("LOCKD_MSG") != NULL); 1168 1169 /* 1170 * Fork off a child that becomes the daemon. 1171 */ 1172 1173 #ifndef TTY_MESSAGES 1174 if ((rc = fork()) > 0) 1175 exit(0); 1176 else if (rc < 0) { 1177 spcs_log("cfglockd", NULL, "can't fork %d", errno); 1178 (void) fprintf(stderr, gettext("dscfglockd: cannot fork: %s\n"), 1179 strerror(errno)); 1180 exit(1); 1181 } 1182 #endif 1183 1184 /* 1185 * In child - become daemon. 1186 */ 1187 1188 #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8) 1189 /* use closefrom(3C) from PSARC/2000/193 when possible */ 1190 closefrom(CLOSE_FD); 1191 #else 1192 (void) getrlimit(RLIMIT_NOFILE, &rl); 1193 for (i = CLOSE_FD; i < rl.rlim_max; i++) 1194 (void) close(i); 1195 #endif 1196 1197 #ifdef DEBUG 1198 #ifndef TTY_MESSAGES 1199 (void) open("/dev/console", O_WRONLY|O_APPEND); 1200 (void) dup(0); 1201 (void) dup(0); 1202 #endif 1203 #endif 1204 (void) close(0); 1205 1206 if (msgtrace || lstate) { 1207 debugfile = fopen("/var/tmp/dscfglockd.out", "a"); 1208 if (debugfile) { 1209 time_t t = time(0); 1210 setbuf(debugfile, (char *)0); 1211 (void) fprintf(debugfile, "%19.19s dscfglockd start\n", 1212 ctime(&t)); 1213 } 1214 } 1215 1216 (void) setpgrp(); 1217 spcs_log("cfglockd", NULL, "new lock daemon, pid %d", getpid()); 1218 1219 /* 1220 * Catch as unexpected all signals apart from SIGTERM. 1221 */ 1222 1223 for (i = 1; i < _sys_nsig; i++) 1224 (void) sigset(i, unexpected); 1225 (void) sigset(SIGTERM, term); 1226 1227 for (i = 0; (c = getopt(argc, argv, "df:e:")) != EOF; i++) { 1228 switch (c) { 1229 case 'd': 1230 debug = 1; 1231 break; 1232 case 'e': 1233 exe = 1; 1234 if (cp) { 1235 usage(); 1236 } 1237 cp = optarg; 1238 break; 1239 case 'f': 1240 if (cp) { 1241 usage(); 1242 } 1243 cp = optarg; 1244 break; 1245 default: 1246 usage(); 1247 break; 1248 } 1249 } 1250 1251 ifc = (struct ifconf *)malloc(sizeof (struct ifconf)); 1252 if (ifc == NULL) { 1253 perror(CFG_PIDFILE); 1254 DPF((stderr, "Can't open pid file\n")); 1255 exit(1); 1256 } 1257 (void) memset((char *)ifc, 0, sizeof (struct ifconf)); 1258 getmyaddrs(ifc); 1259 1260 /* 1261 * if (lockdaemonalive()) { 1262 * (void) fprintf(stderr, "%s: %s\n", program, 1263 * gettext("There is already a live lockdaemon")); 1264 * exit(1); 1265 * } 1266 */ 1267 if ((fp = fopen(CFG_PIDFILE, "w")) == NULL) { 1268 perror(CFG_PIDFILE); 1269 DPF((stderr, "Can't open pid file\n")); 1270 exit(1); 1271 } 1272 (void) fprintf(fp, "%ld\n", getpid()); 1273 (void) fclose(fp); 1274 1275 /* order should be set to node number within cluster */ 1276 order = cfg_iscluster(); 1277 cfg_lfinit(); 1278 1279 if (!order) { 1280 (void) gettimeofday(&tp, NULL); 1281 srand48(tp.tv_usec); 1282 order = lrand48(); 1283 if (debugfile) { 1284 (void) fprintf(debugfile, "WARNING: order number " 1285 "is 0 -- changing randomly to %d\n", order); 1286 } 1287 } 1288 c = 0; 1289 for (i = 0; (x = cfg_filelock(i, 0)) != CFG_LF_EOF; i++) { 1290 if (x == CFG_LF_AGAIN) { 1291 cfg_readpid(i, &pid); 1292 if (c++ == 0) 1293 spcs_log("cfglockd", NULL, 1294 "init .dscfg.lck slot %d pid %d locked", 1295 i, pid); 1296 DPF((stderr, "client process %ld still alive\n", pid)); 1297 continue; /* can't take lock, must be still alive */ 1298 } 1299 cfg_writepid(i, 0); 1300 (void) cfg_fileunlock(i); 1301 } 1302 1303 tv.it_interval.tv_sec = TIMEOUT_SECS; 1304 tv.it_interval.tv_usec = 0; 1305 tv.it_value = tv.it_interval; 1306 1307 bzero(unlock_buf, sizeof (unlock_buf)); 1308 next_q = 0; 1309 build_daemon_list(cp, exe); 1310 if ((lock_soc = socket(pf_inet, SOCK_DGRAM, 0)) < 0) { 1311 (void) fprintf(stderr, "%s: %s\n", program, 1312 gettext("failed to create socket")); 1313 perror("socket"); 1314 spcs_log("cfglockd", NULL, "couldn't create socket"); 1315 exit(1); 1316 } 1317 thishost.sin_family = AF_INET; 1318 thishost.sin_addr.s_addr = INADDR_ANY; 1319 thishost.sin_port = htons(lock_port); 1320 rc = bind(lock_soc, (struct sockaddr *)&thishost, sizeof (thishost)); 1321 if (rc < 0) { 1322 perror("bind"); 1323 spcs_log("cfglockd", NULL, "couldn't bind"); 1324 exit(1); 1325 } 1326 if (getsockname(lock_soc, (struct sockaddr *)&thishost, &len) < 0) 1327 perror("getsockname"); 1328 send_aliveall(); 1329 (void) sigset(SIGALRM, keepalive); 1330 (void) setitimer(ITIMER_REAL, &tv, NULL); 1331 /* 1332 * wait 2 time outs before allowing a lock to find if someone else 1333 * currently has the lock. 1334 */ 1335 } 1336 1337 #ifdef lint 1338 int 1339 lintmain(int argc, char *argv[]) 1340 #else 1341 int 1342 main(int argc, char *argv[]) 1343 #endif 1344 { 1345 struct lock_msg message_buf; 1346 daemonaddr_t from; 1347 int addrlen; 1348 int rc; 1349 int x = 1; /* kludge to stop warnings from compiler */ 1350 1351 init(argc, argv); 1352 CRIT_BEGIN(); 1353 while (x) { 1354 CRIT_END(); 1355 addrlen = sizeof (from); 1356 DPF((stderr, "begin recvfrom\n")); 1357 rc = recvfrom(lock_soc, &message_buf, sizeof (message_buf), 1358 0, (struct sockaddr *)&from, &addrlen); 1359 DPF((stderr, "end recvfrom rc = %d\n", rc)); 1360 CRIT_BEGIN(); 1361 if (rc == sizeof (message_buf)) 1362 dispatch(&message_buf, &from); 1363 else 1364 check_for_write_lock(); 1365 1366 /* if we own the lock, check to see if the process died */ 1367 if (the_lock.type != LOCK_NOTLOCKED && 1368 the_lock.remote_daemon == NULL) 1369 check_for_dead(); 1370 } 1371 CRIT_END(); 1372 return (0); 1373 } 1374