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