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 *
lockd_type(cfglockd_t type)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 *
lockd_state(int state)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 *
lockd_msg(int message)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
getmyaddrs(struct ifconf * ifc)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
cmp_addr(daemonaddr_t * a,daemonaddr_t * b)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
addr_is_holder(int32_t order)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
islocalhost(daemonaddr_t * host)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
send_lockmsg(int cmd,pid_t pid,daemonaddr_t * dp,uint8_t seq)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
send_aliveall()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 *
find_lockdaemon(daemonaddr_t * d)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
daemon_alive(daemonaddr_t * daemon,int32_t order)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
delete_queue_entry(struct lock_req * req)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
take_lock(int ackmessage)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
check_for_write_lock()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
lock_granted(daemonaddr_t * da)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
try_lock()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
process_queue()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
lock_sort(const void * a,const void * b)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
queue_lock(cfglockd_t type,struct lock_msg * msg,daemonaddr_t * addr)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
lock_stat()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
is_duplicate(cfglockd_t type,pid_t pid,uint8_t seq)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
local_lock(cfglockd_t type,struct lock_msg * msg,daemonaddr_t * client)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
remote_lock(struct sockaddr_in * remote,struct lock_msg * msg)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
unqueue_lock(daemonaddr_t * d,pid_t pid)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
xxunlock()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
local_unlock(pid_t pid,uint8_t seq,int method)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
remote_unlock(int32_t order,daemonaddr_t * d)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
lockedby(daemonaddr_t * d,uint8_t seq)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
keepalive(int signo)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
dispatch(struct lock_msg * mp,daemonaddr_t * host)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
purge_pid(pid_t pid)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
check_for_dead()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
build_daemon_list(char * cf_file,int exe)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
usage()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
unexpected(int sig)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
term(int sig)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
init(int argc,char * argv[])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
lintmain(int argc,char * argv[])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