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