xref: /freebsd/usr.sbin/rpc.lockd/lockd_lock.c (revision 7e589b0b6e414d5618e6bcd0ad8225194c4ec999)
14945c132SAlfred Perlstein /*	$NetBSD: lockd_lock.c,v 1.5 2000/11/21 03:47:41 enami Exp $	*/
24945c132SAlfred Perlstein /*	$FreeBSD$ */
34945c132SAlfred Perlstein 
44945c132SAlfred Perlstein /*
54945c132SAlfred Perlstein  * Copyright (c) 2001 Andrew P. Lentvorski, Jr.
64945c132SAlfred Perlstein  * Copyright (c) 2000 Manuel Bouyer.
74945c132SAlfred Perlstein  *
84945c132SAlfred Perlstein  * Redistribution and use in source and binary forms, with or without
94945c132SAlfred Perlstein  * modification, are permitted provided that the following conditions
104945c132SAlfred Perlstein  * are met:
114945c132SAlfred Perlstein  * 1. Redistributions of source code must retain the above copyright
124945c132SAlfred Perlstein  *    notice, this list of conditions and the following disclaimer.
134945c132SAlfred Perlstein  * 2. Redistributions in binary form must reproduce the above copyright
144945c132SAlfred Perlstein  *    notice, this list of conditions and the following disclaimer in the
154945c132SAlfred Perlstein  *    documentation and/or other materials provided with the distribution.
164945c132SAlfred Perlstein  * 3. All advertising materials mentioning features or use of this software
174945c132SAlfred Perlstein  *    must display the following acknowledgement:
184945c132SAlfred Perlstein  *	This product includes software developed by the University of
194945c132SAlfred Perlstein  *	California, Berkeley and its contributors.
204945c132SAlfred Perlstein  * 4. Neither the name of the University nor the names of its contributors
214945c132SAlfred Perlstein  *    may be used to endorse or promote products derived from this software
224945c132SAlfred Perlstein  *    without specific prior written permission.
234945c132SAlfred Perlstein  *
244945c132SAlfred Perlstein  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
254945c132SAlfred Perlstein  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
264945c132SAlfred Perlstein  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
274945c132SAlfred Perlstein  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
284945c132SAlfred Perlstein  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
294945c132SAlfred Perlstein  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
304945c132SAlfred Perlstein  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
314945c132SAlfred Perlstein  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
324945c132SAlfred Perlstein  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
334945c132SAlfred Perlstein  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
344945c132SAlfred Perlstein  * SUCH DAMAGE.
354945c132SAlfred Perlstein  *
364945c132SAlfred Perlstein  */
374945c132SAlfred Perlstein 
387e589b0bSAlfred Perlstein #define DEBUG 1
394945c132SAlfred Perlstein 
404945c132SAlfred Perlstein #include <stdio.h>
417e589b0bSAlfred Perlstein #ifdef DEBUG
424945c132SAlfred Perlstein #include <stdarg.h>
434945c132SAlfred Perlstein #endif
444945c132SAlfred Perlstein #include <stdlib.h>
454945c132SAlfred Perlstein #include <unistd.h>
464945c132SAlfred Perlstein #include <fcntl.h>
474945c132SAlfred Perlstein #include <syslog.h>
484945c132SAlfred Perlstein #include <errno.h>
494945c132SAlfred Perlstein #include <string.h>
504945c132SAlfred Perlstein #include <signal.h>
514945c132SAlfred Perlstein #include <rpc/rpc.h>
524945c132SAlfred Perlstein #include <sys/types.h>
534945c132SAlfred Perlstein #include <sys/stat.h>
544945c132SAlfred Perlstein #include <sys/socket.h>
554945c132SAlfred Perlstein #include <sys/param.h>
564945c132SAlfred Perlstein #include <sys/mount.h>
574945c132SAlfred Perlstein #include <sys/wait.h>
584945c132SAlfred Perlstein #include <rpcsvc/sm_inter.h>
594945c132SAlfred Perlstein #include <rpcsvc/nlm_prot.h>
604945c132SAlfred Perlstein #include "lockd_lock.h"
614945c132SAlfred Perlstein #include "lockd.h"
624945c132SAlfred Perlstein 
634945c132SAlfred Perlstein #define MAXOBJECTSIZE 64
644945c132SAlfred Perlstein #define MAXBUFFERSIZE 1024
654945c132SAlfred Perlstein 
664945c132SAlfred Perlstein /*
674945c132SAlfred Perlstein  * SM_MAXSTRLEN is usually 1024.  This means that lock requests and
684945c132SAlfred Perlstein  * host name monitoring entries are *MUCH* larger than they should be
694945c132SAlfred Perlstein  */
704945c132SAlfred Perlstein 
714945c132SAlfred Perlstein /*
724945c132SAlfred Perlstein  * A set of utilities for managing file locking
734945c132SAlfred Perlstein  *
744945c132SAlfred Perlstein  * XXX: All locks are in a linked list, a better structure should be used
754945c132SAlfred Perlstein  * to improve search/access effeciency.
764945c132SAlfred Perlstein  */
774945c132SAlfred Perlstein 
784945c132SAlfred Perlstein /* struct describing a lock */
794945c132SAlfred Perlstein struct file_lock {
804945c132SAlfred Perlstein 	LIST_ENTRY(file_lock) nfslocklist;
814945c132SAlfred Perlstein 	fhandle_t filehandle; /* NFS filehandle */
824945c132SAlfred Perlstein 	struct sockaddr *addr;
834945c132SAlfred Perlstein 	struct nlm4_holder client; /* lock holder */
844945c132SAlfred Perlstein 	netobj client_cookie; /* cookie sent by the client */
854945c132SAlfred Perlstein 	char client_name[SM_MAXSTRLEN];
864945c132SAlfred Perlstein 	int nsm_status; /* status from the remote lock manager */
874945c132SAlfred Perlstein 	int status; /* lock status, see below */
884945c132SAlfred Perlstein 	int flags; /* lock flags, see lockd_lock.h */
897e589b0bSAlfred Perlstein 	int blocking; /* blocking lock or not */
904945c132SAlfred Perlstein 	pid_t locker; /* pid of the child process trying to get the lock */
914945c132SAlfred Perlstein 	int fd;	/* file descriptor for this lock */
924945c132SAlfred Perlstein };
934945c132SAlfred Perlstein 
947e589b0bSAlfred Perlstein LIST_HEAD(nfslocklist_head, file_lock);
957e589b0bSAlfred Perlstein struct nfslocklist_head nfslocklist_head = LIST_HEAD_INITIALIZER(nfslocklist_head);
967e589b0bSAlfred Perlstein 
977e589b0bSAlfred Perlstein LIST_HEAD(blockedlocklist_head, file_lock);
987e589b0bSAlfred Perlstein struct blockedlocklist_head blockedlocklist_head = LIST_HEAD_INITIALIZER(blockedlocklist_head);
997e589b0bSAlfred Perlstein 
1004945c132SAlfred Perlstein /* lock status */
1014945c132SAlfred Perlstein #define LKST_LOCKED	1 /* lock is locked */
1024945c132SAlfred Perlstein /* XXX: Is this flag file specific or lock specific? */
1034945c132SAlfred Perlstein #define LKST_WAITING	2 /* file is already locked by another host */
1044945c132SAlfred Perlstein #define LKST_PROCESSING	3 /* child is trying to aquire the lock */
1054945c132SAlfred Perlstein #define LKST_DYING	4 /* must dies when we get news from the child */
1064945c132SAlfred Perlstein 
1077e589b0bSAlfred Perlstein /* struct describing a monitored host */
1084945c132SAlfred Perlstein struct host {
1094945c132SAlfred Perlstein 	LIST_ENTRY(host) hostlst;
1104945c132SAlfred Perlstein 	char name[SM_MAXSTRLEN];
1114945c132SAlfred Perlstein 	int refcnt;
1124945c132SAlfred Perlstein };
1137e589b0bSAlfred Perlstein /* list of hosts we monitor */
1147e589b0bSAlfred Perlstein LIST_HEAD(hostlst_head, host);
1157e589b0bSAlfred Perlstein struct hostlst_head hostlst_head = LIST_HEAD_INITIALIZER(hostlst_head);
1167e589b0bSAlfred Perlstein 
1177e589b0bSAlfred Perlstein /*
1187e589b0bSAlfred Perlstein  * File monitoring handlers
1197e589b0bSAlfred Perlstein  * XXX: These might be able to be removed when kevent support
1207e589b0bSAlfred Perlstein  * is placed into the hardware lock/unlock routines.  (ie.
1217e589b0bSAlfred Perlstein  * let the kernel do all the file monitoring)
1227e589b0bSAlfred Perlstein  */
1237e589b0bSAlfred Perlstein 
1247e589b0bSAlfred Perlstein /* Struct describing a monitored file */
1257e589b0bSAlfred Perlstein struct monfile {
1267e589b0bSAlfred Perlstein 	LIST_ENTRY(monfile) monfilelist;
1277e589b0bSAlfred Perlstein 	fhandle_t filehandle; /* Local access filehandle */
1287e589b0bSAlfred Perlstein 	int fd; /* file descriptor: remains open until unlock! */
1297e589b0bSAlfred Perlstein 	int refcount;
1307e589b0bSAlfred Perlstein 	int exclusive;
1317e589b0bSAlfred Perlstein };
1327e589b0bSAlfred Perlstein 
1337e589b0bSAlfred Perlstein /* List of files we monitor */
1347e589b0bSAlfred Perlstein LIST_HEAD(monfilelist_head, monfile);
1357e589b0bSAlfred Perlstein struct monfilelist_head monfilelist_head = LIST_HEAD_INITIALIZER(monfilelist_head);
1364945c132SAlfred Perlstein 
1374945c132SAlfred Perlstein static int debugdelay = 0;
1384945c132SAlfred Perlstein 
1397e589b0bSAlfred Perlstein enum nfslock_status { NFS_GRANTED = 0, NFS_GRANTED_DUPLICATE,
1407e589b0bSAlfred Perlstein 		      NFS_DENIED, NFS_DENIED_NOLOCK,
1417e589b0bSAlfred Perlstein 		      NFS_RESERR };
1427e589b0bSAlfred Perlstein 
1437e589b0bSAlfred Perlstein enum hwlock_status { HW_GRANTED = 0, HW_GRANTED_DUPLICATE,
1447e589b0bSAlfred Perlstein 		     HW_DENIED, HW_DENIED_NOLOCK,
1457e589b0bSAlfred Perlstein 		     HW_STALEFH, HW_READONLY, HW_RESERR };
1464945c132SAlfred Perlstein 
1474945c132SAlfred Perlstein enum partialfilelock_status { PFL_GRANTED=0, PFL_GRANTED_DUPLICATE, PFL_DENIED,
1487e589b0bSAlfred Perlstein 			      PFL_NFSDENIED, PFL_NFSBLOCKED, PFL_NFSDENIED_NOLOCK, PFL_NFSRESERR,
1497e589b0bSAlfred Perlstein 			      PFL_HWDENIED,  PFL_HWBLOCKED,  PFL_HWDENIED_NOLOCK, PFL_HWRESERR};
1504945c132SAlfred Perlstein 
1517e589b0bSAlfred Perlstein enum partialfilelock_status lock_partialfilelock(struct file_lock *fl);
1527e589b0bSAlfred Perlstein 
1537e589b0bSAlfred Perlstein void send_granted(struct file_lock *fl, int opcode);
1544945c132SAlfred Perlstein void siglock(void);
1554945c132SAlfred Perlstein void sigunlock(void);
1564945c132SAlfred Perlstein 
1574945c132SAlfred Perlstein void
1584945c132SAlfred Perlstein debuglog(char const *fmt, ...)
1594945c132SAlfred Perlstein {
1604945c132SAlfred Perlstein 	va_list ap;
1614945c132SAlfred Perlstein 
1627e589b0bSAlfred Perlstein 	if (debug_level < 1) {
1634945c132SAlfred Perlstein 		return;
1647e589b0bSAlfred Perlstein 	}
1654945c132SAlfred Perlstein 
1664945c132SAlfred Perlstein 	sleep(debugdelay);
1674945c132SAlfred Perlstein 
1684945c132SAlfred Perlstein 	va_start(ap, fmt);
1694945c132SAlfred Perlstein 	vsyslog(LOG_DEBUG, fmt, ap);
1704945c132SAlfred Perlstein 	va_end(ap);
1714945c132SAlfred Perlstein }
1724945c132SAlfred Perlstein 
1737e589b0bSAlfred Perlstein void dump_static_object(const unsigned char* object, const int sizeof_object,
1747e589b0bSAlfred Perlstein 			unsigned char* hbuff, const int sizeof_hbuff,
1757e589b0bSAlfred Perlstein 			unsigned char* cbuff, const int sizeof_cbuff)
1764945c132SAlfred Perlstein {
1774945c132SAlfred Perlstein 	int i,objectsize;
1784945c132SAlfred Perlstein 
1797e589b0bSAlfred Perlstein 	if (debug_level < 2) {
1804945c132SAlfred Perlstein 		return;
1814945c132SAlfred Perlstein 	}
1824945c132SAlfred Perlstein 
1837e589b0bSAlfred Perlstein 	objectsize = sizeof_object;
1847e589b0bSAlfred Perlstein 
1857e589b0bSAlfred Perlstein 	if (objectsize == 0) {
1867e589b0bSAlfred Perlstein 		debuglog("object is size 0\n");
1877e589b0bSAlfred Perlstein 	} else {
1884945c132SAlfred Perlstein 		if (objectsize > MAXOBJECTSIZE) {
1894945c132SAlfred Perlstein 			debuglog("Object of size %d being clamped"
1904945c132SAlfred Perlstein 			    "to size %d\n", objectsize, MAXOBJECTSIZE);
1914945c132SAlfred Perlstein 			objectsize = MAXOBJECTSIZE;
1924945c132SAlfred Perlstein 		}
1934945c132SAlfred Perlstein 
1944945c132SAlfred Perlstein 		if (hbuff != NULL) {
1957e589b0bSAlfred Perlstein 			if (sizeof_hbuff < objectsize*2+1) {
1967e589b0bSAlfred Perlstein 				debuglog("Hbuff not large enough."
1977e589b0bSAlfred Perlstein 				    "  Increase size\n");
1984945c132SAlfred Perlstein 			} else {
1994945c132SAlfred Perlstein 				for(i=0;i<objectsize;i++) {
2004945c132SAlfred Perlstein 					sprintf(hbuff+i*2,"%02x",*(object+i));
2014945c132SAlfred Perlstein 				}
2024945c132SAlfred Perlstein 				*(hbuff+i*2) = '\0';
2034945c132SAlfred Perlstein 			}
2044945c132SAlfred Perlstein 		}
2054945c132SAlfred Perlstein 
2064945c132SAlfred Perlstein 		if (cbuff != NULL) {
2077e589b0bSAlfred Perlstein 			if (sizeof_cbuff < objectsize+1) {
2084945c132SAlfred Perlstein 				debuglog("Cbuff not large enough."
2094945c132SAlfred Perlstein 				    "  Increase Size\n");
2104945c132SAlfred Perlstein 			}
2114945c132SAlfred Perlstein 
2124945c132SAlfred Perlstein 			for(i=0;i<objectsize;i++) {
2134945c132SAlfred Perlstein 				if (*(object+i) >= 32 && *(object+i) <= 127) {
2144945c132SAlfred Perlstein 					*(cbuff+i) = *(object+i);
2154945c132SAlfred Perlstein 				} else {
2164945c132SAlfred Perlstein 					*(cbuff+i) = '.';
2174945c132SAlfred Perlstein 				}
2184945c132SAlfred Perlstein 			}
2194945c132SAlfred Perlstein 			*(cbuff+i) = '\0';
2204945c132SAlfred Perlstein 		}
2214945c132SAlfred Perlstein 	}
2227e589b0bSAlfred Perlstein }
2234945c132SAlfred Perlstein 
2247e589b0bSAlfred Perlstein void dump_netobj(const struct netobj *nobj)
2254945c132SAlfred Perlstein {
2264945c132SAlfred Perlstein 	char hbuff[MAXBUFFERSIZE*2];
2274945c132SAlfred Perlstein 	char cbuff[MAXBUFFERSIZE];
2284945c132SAlfred Perlstein 
2297e589b0bSAlfred Perlstein 	if (debug_level < 2) {
2304945c132SAlfred Perlstein 		return;
2317e589b0bSAlfred Perlstein 	}
2324945c132SAlfred Perlstein 
2334945c132SAlfred Perlstein 	if (nobj == NULL) {
2344945c132SAlfred Perlstein 		debuglog("Null netobj pointer\n");
2357e589b0bSAlfred Perlstein 	}
2367e589b0bSAlfred Perlstein 	else if (nobj->n_len == 0) {
2374945c132SAlfred Perlstein 		debuglog("Size zero netobj\n");
2384945c132SAlfred Perlstein 	} else {
2394945c132SAlfred Perlstein 		dump_static_object(nobj->n_bytes,nobj->n_len,
2404945c132SAlfred Perlstein 		    hbuff,sizeof(hbuff),cbuff,sizeof(cbuff));
2414945c132SAlfred Perlstein 		debuglog("netobj: len: %d  data: %s :::  %s\n",
2424945c132SAlfred Perlstein 		    nobj->n_len,hbuff,cbuff);
2434945c132SAlfred Perlstein 	}
2444945c132SAlfred Perlstein }
2454945c132SAlfred Perlstein 
2467e589b0bSAlfred Perlstein void dump_filelock(const struct file_lock *fl)
2474945c132SAlfred Perlstein {
2484945c132SAlfred Perlstein 	char hbuff[MAXBUFFERSIZE*2];
2494945c132SAlfred Perlstein 	char cbuff[MAXBUFFERSIZE];
2504945c132SAlfred Perlstein 
2517e589b0bSAlfred Perlstein 	if (debug_level < 2) {
2524945c132SAlfred Perlstein 		return;
2534945c132SAlfred Perlstein 	}
2544945c132SAlfred Perlstein 
2557e589b0bSAlfred Perlstein 	if (fl != NULL) {
2564945c132SAlfred Perlstein 		debuglog("Dumping file lock structure\n");
2574945c132SAlfred Perlstein 
2584945c132SAlfred Perlstein 		dump_static_object((unsigned char *)&fl->filehandle,
2594945c132SAlfred Perlstein 		    sizeof(fl->filehandle), hbuff, sizeof(hbuff),
2604945c132SAlfred Perlstein 		    cbuff, sizeof(cbuff));
2614945c132SAlfred Perlstein 		debuglog("Filehandle: %8s  :::  %8s\n", hbuff, cbuff);
2624945c132SAlfred Perlstein 
2634945c132SAlfred Perlstein 		debuglog("Dumping nlm4_holder:\n");
2644945c132SAlfred Perlstein 		debuglog("exc: %x  svid: %x  offset:len %llx:%llx\n",
2654945c132SAlfred Perlstein 		    fl->client.exclusive, fl->client.svid,
2664945c132SAlfred Perlstein 		    fl->client.l_offset, fl->client.l_len);
2674945c132SAlfred Perlstein 
2684945c132SAlfred Perlstein 		debuglog("Dumping client identity:\n");
2694945c132SAlfred Perlstein 		dump_netobj(&fl->client.oh);
2704945c132SAlfred Perlstein 
2714945c132SAlfred Perlstein 		debuglog("Dumping client cookie:\n");
2724945c132SAlfred Perlstein 		dump_netobj(&fl->client_cookie);
2734945c132SAlfred Perlstein 
2744945c132SAlfred Perlstein 		debuglog("nsm: %d  status: %d  flags: %d  locker: %d"
2754945c132SAlfred Perlstein 		    "  fd:  %d\n", fl->nsm_status, fl->status,
2764945c132SAlfred Perlstein 		    fl->flags, fl->locker, fl->fd);
2777e589b0bSAlfred Perlstein 	} else {
2787e589b0bSAlfred Perlstein 		debuglog("NULL file lock structure\n");
2797e589b0bSAlfred Perlstein 	}
2807e589b0bSAlfred Perlstein }
2817e589b0bSAlfred Perlstein 
2827e589b0bSAlfred Perlstein struct file_lock *
2837e589b0bSAlfred Perlstein malloccopy_filelock(struct file_lock *fl)
2847e589b0bSAlfred Perlstein {
2854945c132SAlfred Perlstein }
2864945c132SAlfred Perlstein 
2874945c132SAlfred Perlstein void
2887e589b0bSAlfred Perlstein copy_nlm4_lock_to_nlm4_holder(const struct nlm4_lock *src,
2897e589b0bSAlfred Perlstein     const bool_t exclusive, struct nlm4_holder *dest)
2904945c132SAlfred Perlstein {
2914945c132SAlfred Perlstein 	dest->exclusive = exclusive;
2924945c132SAlfred Perlstein 	dest->oh.n_len = src->oh.n_len;
2934945c132SAlfred Perlstein 	dest->oh.n_bytes = src->oh.n_bytes;
2944945c132SAlfred Perlstein 	dest->svid = src->svid;
2954945c132SAlfred Perlstein 	dest->l_offset = src->l_offset;
2964945c132SAlfred Perlstein 	dest->l_len = src->l_len;
2974945c132SAlfred Perlstein }
2984945c132SAlfred Perlstein 
2994945c132SAlfred Perlstein /*
3004945c132SAlfred Perlstein  * deallocate_file_lock: Free all storage associated with a file lock
3014945c132SAlfred Perlstein  */
3024945c132SAlfred Perlstein 
3034945c132SAlfred Perlstein void
3044945c132SAlfred Perlstein deallocate_file_lock(struct file_lock *fl)
3054945c132SAlfred Perlstein {
3064945c132SAlfred Perlstein   /* XXX: Check to see if this gets *all* the dynamic structures */
3074945c132SAlfred Perlstein   /* XXX: It should be placed closer to the file_lock definition */
3084945c132SAlfred Perlstein 
3094945c132SAlfred Perlstein 	free(fl->client.oh.n_bytes);
3104945c132SAlfred Perlstein 	free(fl->client_cookie.n_bytes);
3114945c132SAlfred Perlstein 	free(fl);
3124945c132SAlfred Perlstein }
3134945c132SAlfred Perlstein 
3144945c132SAlfred Perlstein /*
3154945c132SAlfred Perlstein  * regions_overlap(): This function examines the two provided regions for
3164945c132SAlfred Perlstein  * overlap.  It is non-trivial because start+len *CAN* overflow a 64-bit
3174945c132SAlfred Perlstein  * unsigned integer and NFS semantics are unspecified on this account.
3184945c132SAlfred Perlstein  */
3194945c132SAlfred Perlstein int
3207e589b0bSAlfred Perlstein regions_overlap(const u_int64_t start1, const u_int64_t len1,
3217e589b0bSAlfred Perlstein 		const u_int64_t start2, const u_int64_t len2)
3224945c132SAlfred Perlstein {
3234945c132SAlfred Perlstein   /* XXX: Check to make sure I got *ALL* the cases */
3244945c132SAlfred Perlstein   /* XXX: This DESPERATELY needs a regression test */
3257e589b0bSAlfred Perlstein 	int result;
3267e589b0bSAlfred Perlstein 
3274945c132SAlfred Perlstein 	debuglog("Entering region overlap with vals: %llu:%llu--%llu:%llu\n",
3284945c132SAlfred Perlstein 		 start1, len1, start2, len2);
3294945c132SAlfred Perlstein 
3304945c132SAlfred Perlstein 	/* XXX: Look for a way to collapse the region checks */
3314945c132SAlfred Perlstein 
3324945c132SAlfred Perlstein 	/* XXX: Need to adjust checks to account for integer overflow */
3337e589b0bSAlfred Perlstein 	if (len1 == 0 && len2 == 0) {
3347e589b0bSAlfred Perlstein 		/* Regions *must* overlap if they both extend to the end */
3357e589b0bSAlfred Perlstein 		result = 1;
3367e589b0bSAlfred Perlstein 	} else if (len1 == 0) {
3377e589b0bSAlfred Perlstein 		if (start2+len2 <= start1) {
3384945c132SAlfred Perlstein 			/* Region 2 is completely left of region 1 */
3397e589b0bSAlfred Perlstein 			result = 0;
3404945c132SAlfred Perlstein 		} else {
3417e589b0bSAlfred Perlstein 			result = 1;
3427e589b0bSAlfred Perlstein 		}
3437e589b0bSAlfred Perlstein 	} else if (len2 == 0) {
3447e589b0bSAlfred Perlstein 		if (start1+len1 <= start2) {
3457e589b0bSAlfred Perlstein 			/* Region 1 is completely left of region 2 */
3467e589b0bSAlfred Perlstein 			result = 0;
3477e589b0bSAlfred Perlstein 		} else {
3487e589b0bSAlfred Perlstein 			result = 1;
3497e589b0bSAlfred Perlstein 		}
3507e589b0bSAlfred Perlstein 	} else {
3517e589b0bSAlfred Perlstein 		if (start1+len1 <= start2 || start2+len2 <= start1) {
3524945c132SAlfred Perlstein 			/*
3534945c132SAlfred Perlstein 			 * 1 is completely left of 2 or
3544945c132SAlfred Perlstein 			 * 2 is completely left of 1
3554945c132SAlfred Perlstein 			 */
3567e589b0bSAlfred Perlstein 			result = 0;
3577e589b0bSAlfred Perlstein 		} else {
3587e589b0bSAlfred Perlstein 			result = 1;
3594945c132SAlfred Perlstein 		}
3604945c132SAlfred Perlstein 	}
3614945c132SAlfred Perlstein 
3627e589b0bSAlfred Perlstein 	debuglog("Exiting region overlap with val: %d\n",result);
3637e589b0bSAlfred Perlstein 
3647e589b0bSAlfred Perlstein 	return (result);
3657e589b0bSAlfred Perlstein }
3667e589b0bSAlfred Perlstein 
3674945c132SAlfred Perlstein /*
3684945c132SAlfred Perlstein  * same_netobj: Compares the apprpriate bits of a netobj for identity
3694945c132SAlfred Perlstein  */
3704945c132SAlfred Perlstein int
3714945c132SAlfred Perlstein same_netobj(const netobj *n0, const netobj *n1)
3724945c132SAlfred Perlstein {
3734945c132SAlfred Perlstein 	int retval;
3744945c132SAlfred Perlstein 
3754945c132SAlfred Perlstein 	retval=0;
3764945c132SAlfred Perlstein 
3774945c132SAlfred Perlstein 	debuglog("Entering netobj identity check\n");
3784945c132SAlfred Perlstein 
3794945c132SAlfred Perlstein 	if (n0->n_len == n1->n_len) {
3804945c132SAlfred Perlstein 		debuglog("Preliminary length check passed\n");
3814945c132SAlfred Perlstein 
3824945c132SAlfred Perlstein 		if (!bcmp(n0->n_bytes,n1->n_bytes,n0->n_len)) {
3834945c132SAlfred Perlstein 			retval = 1;
3844945c132SAlfred Perlstein 			debuglog("netobj match\n");
3854945c132SAlfred Perlstein 		} else {
3864945c132SAlfred Perlstein 			debuglog("netobj mismatch\n");
3874945c132SAlfred Perlstein 		}
3884945c132SAlfred Perlstein 	}
3894945c132SAlfred Perlstein 
3904945c132SAlfred Perlstein 	return retval;
3914945c132SAlfred Perlstein }
3924945c132SAlfred Perlstein 
3934945c132SAlfred Perlstein /*
3944945c132SAlfred Perlstein  * same_filelock_identity: Compares the appropriate bits of a file_lock
3954945c132SAlfred Perlstein  */
3964945c132SAlfred Perlstein int
3974945c132SAlfred Perlstein same_filelock_identity(const struct file_lock *fl0,
3984945c132SAlfred Perlstein     const struct file_lock *fl1)
3994945c132SAlfred Perlstein {
4004945c132SAlfred Perlstein 	int retval;
4014945c132SAlfred Perlstein 
4024945c132SAlfred Perlstein 	retval = 0;
4034945c132SAlfred Perlstein 
4044945c132SAlfred Perlstein 	debuglog("Checking filelock identity\n");
4054945c132SAlfred Perlstein 
4064945c132SAlfred Perlstein 	if (fl0->client.svid == fl1->client.svid) {
4074945c132SAlfred Perlstein 		/* Process ids match now check host information */
4084945c132SAlfred Perlstein 		retval = same_netobj(&(fl0->client.oh),&(fl1->client.oh));
4094945c132SAlfred Perlstein 	}
4104945c132SAlfred Perlstein 
4114945c132SAlfred Perlstein 	debuglog("Exiting checking filelock identity: retval: %d\n",retval);
4124945c132SAlfred Perlstein 
4134945c132SAlfred Perlstein 	return retval;
4144945c132SAlfred Perlstein }
4154945c132SAlfred Perlstein 
4164945c132SAlfred Perlstein /*
4174945c132SAlfred Perlstein  * Below here are routines associated with manipulating the NFS
4184945c132SAlfred Perlstein  * lock list.
4194945c132SAlfred Perlstein  */
4204945c132SAlfred Perlstein 
4214945c132SAlfred Perlstein /*
4224945c132SAlfred Perlstein  * get_lock_matching_unlock: Return a lock which matches the given unlock lock
4234945c132SAlfred Perlstein  *                           or NULL otehrwise
4244945c132SAlfred Perlstein  */
4254945c132SAlfred Perlstein struct file_lock*
4264945c132SAlfred Perlstein get_lock_matching_unlock (const struct file_lock *fl)
4274945c132SAlfred Perlstein {
4287e589b0bSAlfred Perlstein 	/* XXX: It is annoying that this duplicates so much code from test_nfslock */
4297e589b0bSAlfred Perlstein 
4304945c132SAlfred Perlstein 	struct file_lock *ifl; /* Iterator */
4314945c132SAlfred Perlstein 	struct file_lock *retval;
4324945c132SAlfred Perlstein 
4334945c132SAlfred Perlstein 	debuglog("Entering lock_matching_unlock\n");
4344945c132SAlfred Perlstein 	debuglog("********Dump of fl*****************\n");
4354945c132SAlfred Perlstein 	dump_filelock(fl);
4364945c132SAlfred Perlstein 
4374945c132SAlfred Perlstein 	retval = NULL;
4384945c132SAlfred Perlstein 
4394945c132SAlfred Perlstein 	for (ifl = LIST_FIRST(&nfslocklist_head);
4404945c132SAlfred Perlstein 	     ifl != NULL && retval == NULL;
4414945c132SAlfred Perlstein 	     ifl = LIST_NEXT(ifl, nfslocklist)) {
4424945c132SAlfred Perlstein 		debuglog("Pointer to file lock: %p\n",ifl);
4434945c132SAlfred Perlstein 
4444945c132SAlfred Perlstein 		debuglog("****Dump of ifl****\n");
4454945c132SAlfred Perlstein 		dump_filelock(ifl);
4464945c132SAlfred Perlstein 		debuglog("*******************\n");
4474945c132SAlfred Perlstein 
4484945c132SAlfred Perlstein 		/*
4494945c132SAlfred Perlstein 		 * XXX: It is conceivable that someone could use the NLM RPC
4504945c132SAlfred Perlstein 		 * system to directly access filehandles.  This may be a
4514945c132SAlfred Perlstein 		 * security hazard as the filehandle code may bypass normal
4524945c132SAlfred Perlstein 		 * file access controls
4534945c132SAlfred Perlstein 		 */
4544945c132SAlfred Perlstein 		if (!bcmp(&fl->filehandle, &ifl->filehandle,
4554945c132SAlfred Perlstein 			sizeof(fhandle_t))) {
4564945c132SAlfred Perlstein 			debuglog("matching_unlock: Filehandles match."
4574945c132SAlfred Perlstein 			    "  Checking regions\n");
4584945c132SAlfred Perlstein 
4594945c132SAlfred Perlstein 			/* Filehandles match, check for region overlap */
4604945c132SAlfred Perlstein 			if (regions_overlap(fl->client.l_offset, fl->client.l_len,
4614945c132SAlfred Perlstein 				ifl->client.l_offset, ifl->client.l_len)) {
4624945c132SAlfred Perlstein 				debuglog("matching_unlock: Region overlap"
4634945c132SAlfred Perlstein 				    " found %llu : %llu -- %llu : %llu\n",
4644945c132SAlfred Perlstein 				    fl->client.l_offset,fl->client.l_len,
4654945c132SAlfred Perlstein 				    ifl->client.l_offset,ifl->client.l_len);
4664945c132SAlfred Perlstein 
4674945c132SAlfred Perlstein 				/* Regions overlap, check the identity */
4684945c132SAlfred Perlstein 				if (same_filelock_identity(fl,ifl)) {
4694945c132SAlfred Perlstein 					debuglog("matching_unlock: Duplicate"
4704945c132SAlfred Perlstein 					    " lock id.  Granting\n");
4714945c132SAlfred Perlstein 					retval = ifl;
4724945c132SAlfred Perlstein 				}
4734945c132SAlfred Perlstein 			}
4744945c132SAlfred Perlstein 		}
4754945c132SAlfred Perlstein 	}
4764945c132SAlfred Perlstein 
4774945c132SAlfred Perlstein 	debuglog("Exiting lock_matching_unlock\n");
4784945c132SAlfred Perlstein 
4797e589b0bSAlfred Perlstein 	return retval;
4804945c132SAlfred Perlstein }
4814945c132SAlfred Perlstein 
4824945c132SAlfred Perlstein /*
4834945c132SAlfred Perlstein  * test_nfslock: check for NFS lock in lock list
4844945c132SAlfred Perlstein  *
4854945c132SAlfred Perlstein  * This routine makes the following assumptions:
4864945c132SAlfred Perlstein  *    1) Nothing will adjust the lock list during a lookup
4874945c132SAlfred Perlstein  *
4884945c132SAlfred Perlstein  * This routine has an intersting quirk which bit me hard.
4894945c132SAlfred Perlstein  * The conflicting_fl is the pointer to the conflicting lock.
4904945c132SAlfred Perlstein  * However, to modify the "*pointer* to the conflicting lock" rather
4914945c132SAlfred Perlstein  * that the "conflicting lock itself" one must pass in a "pointer to
4924945c132SAlfred Perlstein  * the pointer of the conflicting lock".  Gross.
4934945c132SAlfred Perlstein  */
4944945c132SAlfred Perlstein 
4954945c132SAlfred Perlstein enum nfslock_status
4964945c132SAlfred Perlstein test_nfslock(const struct file_lock *fl, struct file_lock **conflicting_fl)
4974945c132SAlfred Perlstein {
4984945c132SAlfred Perlstein 	struct file_lock *ifl; /* Iterator */
4994945c132SAlfred Perlstein 	enum nfslock_status retval;
5004945c132SAlfred Perlstein 
5017e589b0bSAlfred Perlstein 	debuglog("Entering test_nfslock\n");
5024945c132SAlfred Perlstein 
5034945c132SAlfred Perlstein 	retval = NFS_GRANTED;
5044945c132SAlfred Perlstein 	(*conflicting_fl) = NULL;
5054945c132SAlfred Perlstein 
5064945c132SAlfred Perlstein 	debuglog("Entering lock search loop\n");
5074945c132SAlfred Perlstein 
5084945c132SAlfred Perlstein 	debuglog("***********************************\n");
5094945c132SAlfred Perlstein 	debuglog("Dumping match filelock\n");
5104945c132SAlfred Perlstein 	debuglog("***********************************\n");
5114945c132SAlfred Perlstein 	dump_filelock(fl);
5124945c132SAlfred Perlstein 	debuglog("***********************************\n");
5134945c132SAlfred Perlstein 
5144945c132SAlfred Perlstein 	for (ifl = LIST_FIRST(&nfslocklist_head);
5154945c132SAlfred Perlstein 	     ifl != NULL && retval != NFS_DENIED;
5164945c132SAlfred Perlstein 	     ifl = LIST_NEXT(ifl, nfslocklist)) {
5174945c132SAlfred Perlstein 		debuglog("Top of lock loop\n");
5184945c132SAlfred Perlstein 		debuglog("Pointer to file lock: %p\n",ifl);
5194945c132SAlfred Perlstein 
5204945c132SAlfred Perlstein 		debuglog("***********************************\n");
5214945c132SAlfred Perlstein 		debuglog("Dumping test filelock\n");
5224945c132SAlfred Perlstein 		debuglog("***********************************\n");
5234945c132SAlfred Perlstein 		dump_filelock(ifl);
5244945c132SAlfred Perlstein 		debuglog("***********************************\n");
5254945c132SAlfred Perlstein 
5264945c132SAlfred Perlstein 		/*
5274945c132SAlfred Perlstein 		 * XXX: It is conceivable that someone could use the NLM RPC
5284945c132SAlfred Perlstein 		 * system to directly access filehandles.  This may be a
5294945c132SAlfred Perlstein 		 * security hazard as the filehandle code may bypass normal
5304945c132SAlfred Perlstein 		 * file access controls
5314945c132SAlfred Perlstein 		 */
5324945c132SAlfred Perlstein 		if (!bcmp(&fl->filehandle, &ifl->filehandle,
5334945c132SAlfred Perlstein 			sizeof(fhandle_t))) {
5344945c132SAlfred Perlstein 			debuglog("test_nfslock: filehandle match found\n");
5354945c132SAlfred Perlstein 
5364945c132SAlfred Perlstein 			/* Filehandles match, check for region overlap */
5374945c132SAlfred Perlstein 			if (regions_overlap(fl->client.l_offset, fl->client.l_len,
5384945c132SAlfred Perlstein 				ifl->client.l_offset, ifl->client.l_len)) {
5394945c132SAlfred Perlstein 				debuglog("test_nfslock: Region overlap found"
5404945c132SAlfred Perlstein 				    " %llu : %llu -- %llu : %llu\n",
5414945c132SAlfred Perlstein 				    fl->client.l_offset,fl->client.l_len,
5424945c132SAlfred Perlstein 				    ifl->client.l_offset,ifl->client.l_len);
5434945c132SAlfred Perlstein 
5444945c132SAlfred Perlstein 				/* Regions overlap, check the exclusivity */
5454945c132SAlfred Perlstein 				if (fl->client.exclusive ||
5464945c132SAlfred Perlstein 				    ifl->client.exclusive) {
5474945c132SAlfred Perlstein 					debuglog("test_nfslock: "
5484945c132SAlfred Perlstein 					    "Exclusivity failure: %d %d\n",
5494945c132SAlfred Perlstein 					    fl->client.exclusive,
5504945c132SAlfred Perlstein 					    ifl->client.exclusive);
5514945c132SAlfred Perlstein 
5524945c132SAlfred Perlstein 					if (same_filelock_identity(fl,ifl)) {
5534945c132SAlfred Perlstein 						debuglog("test_nfslock: "
5544945c132SAlfred Perlstein 						    "Duplicate lock id.  "
5554945c132SAlfred Perlstein 						    "Granting\n");
5564945c132SAlfred Perlstein 						(*conflicting_fl) = ifl;
5574945c132SAlfred Perlstein 						retval = NFS_GRANTED_DUPLICATE;
5584945c132SAlfred Perlstein 					} else {
5594945c132SAlfred Perlstein 						/* locking attempt fails */
5604945c132SAlfred Perlstein 						debuglog("test_nfslock: "
5614945c132SAlfred Perlstein 						    "Lock attempt failed\n");
5624945c132SAlfred Perlstein 						debuglog("Desired lock\n");
5634945c132SAlfred Perlstein 						dump_filelock(fl);
5644945c132SAlfred Perlstein 						debuglog("Conflicting lock\n");
5654945c132SAlfred Perlstein 						dump_filelock(ifl);
5664945c132SAlfred Perlstein 						(*conflicting_fl) = ifl;
5674945c132SAlfred Perlstein 						retval = NFS_DENIED;
5684945c132SAlfred Perlstein 					}
5694945c132SAlfred Perlstein 				}
5704945c132SAlfred Perlstein 			}
5714945c132SAlfred Perlstein 		}
5724945c132SAlfred Perlstein 	}
5734945c132SAlfred Perlstein 
5744945c132SAlfred Perlstein 	debuglog("Dumping file locks\n");
5754945c132SAlfred Perlstein 	debuglog("Exiting test_nfslock\n");
5764945c132SAlfred Perlstein 
5774945c132SAlfred Perlstein 	return retval;
5784945c132SAlfred Perlstein }
5794945c132SAlfred Perlstein 
5804945c132SAlfred Perlstein /*
5814945c132SAlfred Perlstein  * lock_nfslock: attempt to create a lock in the NFS lock list
5824945c132SAlfred Perlstein  *
5834945c132SAlfred Perlstein  * This routine tests whether the lock will be granted and then adds
5844945c132SAlfred Perlstein  * the entry to the lock list if so.
5854945c132SAlfred Perlstein  *
5864945c132SAlfred Perlstein  * Argument fl gets modified as its list housekeeping entries get modified
5874945c132SAlfred Perlstein  * upon insertion into the NFS lock list
5884945c132SAlfred Perlstein  *
5894945c132SAlfred Perlstein  * This routine makes several assumptions:
5904945c132SAlfred Perlstein  *    1) It is perfectly happy to grant a duplicate lock from the same pid.
5914945c132SAlfred Perlstein  *       While this seems to be intuitively wrong, it is required for proper
5924945c132SAlfred Perlstein  *       Posix semantics during unlock.  It is absolutely imperative to not
5934945c132SAlfred Perlstein  *       unlock the main lock before the two child locks are established. Thus,
5944945c132SAlfred Perlstein  *       one has be be able to create duplicate locks over an existing lock
5954945c132SAlfred Perlstein  *    2) It currently accepts duplicate locks from the same id,pid
5964945c132SAlfred Perlstein  */
5974945c132SAlfred Perlstein 
5984945c132SAlfred Perlstein enum nfslock_status
5994945c132SAlfred Perlstein lock_nfslock(struct file_lock *fl)
6004945c132SAlfred Perlstein {
6014945c132SAlfred Perlstein 	enum nfslock_status retval;
6024945c132SAlfred Perlstein 	struct file_lock *dummy_fl;
6034945c132SAlfred Perlstein 
6044945c132SAlfred Perlstein 	dummy_fl = NULL;
6054945c132SAlfred Perlstein 
6064945c132SAlfred Perlstein 	debuglog("Entering lock_nfslock...\n");
6074945c132SAlfred Perlstein 
6084945c132SAlfred Perlstein 	retval = test_nfslock(fl,&dummy_fl);
6094945c132SAlfred Perlstein 
6104945c132SAlfred Perlstein 	if (retval == NFS_GRANTED || retval == NFS_GRANTED_DUPLICATE) {
6114945c132SAlfred Perlstein 		debuglog("Inserting lock...\n");
6124945c132SAlfred Perlstein 		dump_filelock(fl);
6134945c132SAlfred Perlstein 		LIST_INSERT_HEAD(&nfslocklist_head, fl, nfslocklist);
6144945c132SAlfred Perlstein 	}
6154945c132SAlfred Perlstein 
6164945c132SAlfred Perlstein 	debuglog("Exiting lock_nfslock...\n");
6174945c132SAlfred Perlstein 
6187e589b0bSAlfred Perlstein 	return retval;
6194945c132SAlfred Perlstein }
6204945c132SAlfred Perlstein 
6214945c132SAlfred Perlstein /*
6224945c132SAlfred Perlstein  * delete_nfslock: delete an NFS lock list entry
6234945c132SAlfred Perlstein  *
6244945c132SAlfred Perlstein  * This routine is used to delete a lock out of the NFS lock list
6254945c132SAlfred Perlstein  * without regard to status, underlying locks, regions or anything else
6264945c132SAlfred Perlstein  *
6277e589b0bSAlfred Perlstein  * Note that this routine *does not deallocate memory* of the lock.
6287e589b0bSAlfred Perlstein  * It just disconnects it from the list.  The lock can then be used
6297e589b0bSAlfred Perlstein  * by other routines without fear of trashing the list.
6304945c132SAlfred Perlstein  */
6314945c132SAlfred Perlstein 
6324945c132SAlfred Perlstein enum nfslock_status
6337e589b0bSAlfred Perlstein delete_nfslock(struct file_lock *fl)
6344945c132SAlfred Perlstein {
6357e589b0bSAlfred Perlstein 	LIST_REMOVE(fl, nfslocklist);
6367e589b0bSAlfred Perlstein 
6377e589b0bSAlfred Perlstein 	return NFS_GRANTED;
6384945c132SAlfred Perlstein }
6394945c132SAlfred Perlstein 
6404945c132SAlfred Perlstein 
6414945c132SAlfred Perlstein enum split_status {SPL_DISJOINT, SPL_LOCK_CONTAINED, SPL_LOCK_LEFT,
6424945c132SAlfred Perlstein 		   SPL_LOCK_RIGHT, SPL_UNLOCK_CONTAINED};
6434945c132SAlfred Perlstein 
6444945c132SAlfred Perlstein enum split_status
6454945c132SAlfred Perlstein split_nfslock(const struct file_lock *exist_lock,
6464945c132SAlfred Perlstein     const struct file_lock *unlock_lock,
6474945c132SAlfred Perlstein     const struct file_lock *left_lock, const struct file_lock *right_lock)
6484945c132SAlfred Perlstein {
6494945c132SAlfred Perlstein }
6504945c132SAlfred Perlstein 
6514945c132SAlfred Perlstein enum nfslock_status
6527e589b0bSAlfred Perlstein unlock_nfslock(const struct file_lock *fl, struct file_lock **released_lock,
6537e589b0bSAlfred Perlstein     struct file_lock *left_lock, struct file_lock *right_lock)
6544945c132SAlfred Perlstein {
6554945c132SAlfred Perlstein 	struct file_lock *mfl; /* Matching file lock */
6564945c132SAlfred Perlstein 	enum nfslock_status retval;
6574945c132SAlfred Perlstein 
6584945c132SAlfred Perlstein 	debuglog("Entering unlock_nfslock\n");
6594945c132SAlfred Perlstein 
6607e589b0bSAlfred Perlstein 	*released_lock = NULL;
6617e589b0bSAlfred Perlstein 	left_lock = NULL;
6627e589b0bSAlfred Perlstein 	right_lock = NULL;
6637e589b0bSAlfred Perlstein 
6644945c132SAlfred Perlstein 	retval = NFS_DENIED_NOLOCK;
6654945c132SAlfred Perlstein 
6664945c132SAlfred Perlstein 	printf("Attempting to match lock...\n");
6674945c132SAlfred Perlstein 	mfl = get_lock_matching_unlock(fl);
6684945c132SAlfred Perlstein 
6697e589b0bSAlfred Perlstein 	if (mfl != NULL) {
6704945c132SAlfred Perlstein 		debuglog("Unlock matched\n");
6717e589b0bSAlfred Perlstein 		/* Unlock the lock since it matches identity */
6724945c132SAlfred Perlstein 		LIST_REMOVE(mfl, nfslocklist);
6737e589b0bSAlfred Perlstein 		*released_lock = mfl;
6744945c132SAlfred Perlstein 		retval = NFS_GRANTED;
6754945c132SAlfred Perlstein 	}
6764945c132SAlfred Perlstein 
6777e589b0bSAlfred Perlstein /* 	  split_status = split_nfslock(mfl,fl,lfl,rfl); */
6787e589b0bSAlfred Perlstein 
6797e589b0bSAlfred Perlstein /* 	  if (split_status == SPL_DISJOINT) */
6807e589b0bSAlfred Perlstein /* 	    { */
6817e589b0bSAlfred Perlstein /* 	      /* Shouldn't happen, throw error */
6827e589b0bSAlfred Perlstein /* 	    } */
6837e589b0bSAlfred Perlstein /* 	  else if (split_status == SPL_LOCK_CONTAINED) */
6847e589b0bSAlfred Perlstein /* 	    { */
6857e589b0bSAlfred Perlstein /* 	      /* Delete entire lock */
6867e589b0bSAlfred Perlstein /* 	    } */
6877e589b0bSAlfred Perlstein /* 	  else if (split_status == SPL_LOCK_LEFT) */
6887e589b0bSAlfred Perlstein /* 	    { */
6897e589b0bSAlfred Perlstein /* 	      /* Create new lock for left lock and delete old one */
6907e589b0bSAlfred Perlstein /* 	    } */
6917e589b0bSAlfred Perlstein /* 	  else if (split_status == SPL_LOCK_RIGHT) */
6927e589b0bSAlfred Perlstein /* 	    { */
6937e589b0bSAlfred Perlstein /* 	      /* Create new lock for right lock and delete old one */
6947e589b0bSAlfred Perlstein /* 	    } */
6957e589b0bSAlfred Perlstein /* 	  else if (split_status == SPL_UNLOCK_CONTAINED) */
6967e589b0bSAlfred Perlstein /* 	    { */
6977e589b0bSAlfred Perlstein /* 	      /* Create new locks for both and then delete old one */
6987e589b0bSAlfred Perlstein /* 	    } */
6994945c132SAlfred Perlstein 
7004945c132SAlfred Perlstein 	debuglog("Exiting unlock_nfslock\n");
7014945c132SAlfred Perlstein 
7024945c132SAlfred Perlstein 	return retval;
7034945c132SAlfred Perlstein }
7044945c132SAlfred Perlstein 
7057e589b0bSAlfred Perlstein /*
7067e589b0bSAlfred Perlstein  * Below here are the routines for manipulating the file lock directly
7077e589b0bSAlfred Perlstein  * on the disk hardware itself
7087e589b0bSAlfred Perlstein  */
7097e589b0bSAlfred Perlstein enum hwlock_status
7107e589b0bSAlfred Perlstein lock_hwlock(struct file_lock *fl)
7117e589b0bSAlfred Perlstein {
7127e589b0bSAlfred Perlstein 	struct monfile *imf,*nmf;
7137e589b0bSAlfred Perlstein 	enum hwlock_status retval;
7147e589b0bSAlfred Perlstein 	int lflags, flerror;
7157e589b0bSAlfred Perlstein 
7167e589b0bSAlfred Perlstein 	/* Scan to see if filehandle already present */
7177e589b0bSAlfred Perlstein 	LIST_FOREACH(imf, &monfilelist_head, monfilelist) {
7187e589b0bSAlfred Perlstein 		if (bcmp(&fl->filehandle, &imf->filehandle,
7197e589b0bSAlfred Perlstein 			sizeof(fl->filehandle)) == 0) {
7207e589b0bSAlfred Perlstein 			/* imf is the correct filehandle */
7217e589b0bSAlfred Perlstein 			break;
7227e589b0bSAlfred Perlstein 		}
7237e589b0bSAlfred Perlstein 	}
7247e589b0bSAlfred Perlstein 
7257e589b0bSAlfred Perlstein 	if (imf == NULL) {
7267e589b0bSAlfred Perlstein 		/* No filehandle found, create and go */
7277e589b0bSAlfred Perlstein 		nmf = malloc(sizeof(struct monfile));
7287e589b0bSAlfred Perlstein 		if (nmf == NULL) {
7297e589b0bSAlfred Perlstein 			debuglog("hwlock resource allocation failure\n");
7307e589b0bSAlfred Perlstein 			retval = HW_RESERR;
7317e589b0bSAlfred Perlstein 			return retval;
7327e589b0bSAlfred Perlstein 		}
7337e589b0bSAlfred Perlstein 
7347e589b0bSAlfred Perlstein 		/* XXX: Is O_RDWR always the correct mode? */
7357e589b0bSAlfred Perlstein 		nmf->fd = fhopen(&fl->filehandle, O_RDWR);
7367e589b0bSAlfred Perlstein 		if (nmf->fd < 0) {
7377e589b0bSAlfred Perlstein 			switch (errno) {
7387e589b0bSAlfred Perlstein 			case ESTALE:
7397e589b0bSAlfred Perlstein 				retval = HW_STALEFH;
7407e589b0bSAlfred Perlstein 				break;
7417e589b0bSAlfred Perlstein 			case EROFS:
7427e589b0bSAlfred Perlstein 				retval = HW_READONLY;
7437e589b0bSAlfred Perlstein 				break;
7447e589b0bSAlfred Perlstein 			default:
7457e589b0bSAlfred Perlstein 				retval = HW_RESERR;
7467e589b0bSAlfred Perlstein 				break;
7477e589b0bSAlfred Perlstein 			}
7487e589b0bSAlfred Perlstein 			debuglog("fhopen failed (from %16s): %32s\n",
7497e589b0bSAlfred Perlstein 			    fl->client_name, strerror(errno));
7507e589b0bSAlfred Perlstein 			free(nmf);
7517e589b0bSAlfred Perlstein 		} else {
7527e589b0bSAlfred Perlstein 			/* File opened correctly, fill the monitor struct */
7537e589b0bSAlfred Perlstein 			bcopy(&fl->filehandle, &nmf->filehandle, sizeof(fl->filehandle));
7547e589b0bSAlfred Perlstein 			nmf->refcount = 1;
7557e589b0bSAlfred Perlstein 			nmf->exclusive = fl->client.exclusive;
7567e589b0bSAlfred Perlstein 
7577e589b0bSAlfred Perlstein 			lflags = (nmf->exclusive == 1) ?
7587e589b0bSAlfred Perlstein 			    (LOCK_EX | LOCK_NB) : (LOCK_SH | LOCK_NB);
7597e589b0bSAlfred Perlstein 
7607e589b0bSAlfred Perlstein 			flerror = flock(nmf->fd, lflags);
7617e589b0bSAlfred Perlstein 
7627e589b0bSAlfred Perlstein 			if (flerror != 0) {
7637e589b0bSAlfred Perlstein 				switch (errno) {
7647e589b0bSAlfred Perlstein 				case EAGAIN:
7657e589b0bSAlfred Perlstein 					retval = HW_DENIED;
7667e589b0bSAlfred Perlstein 					break;
7677e589b0bSAlfred Perlstein 				case ESTALE:
7687e589b0bSAlfred Perlstein 					retval = HW_STALEFH;
7697e589b0bSAlfred Perlstein 					break;
7707e589b0bSAlfred Perlstein 				case EROFS:
7717e589b0bSAlfred Perlstein 					retval = HW_READONLY;
7727e589b0bSAlfred Perlstein 					break;
7737e589b0bSAlfred Perlstein 				default:
7747e589b0bSAlfred Perlstein 					retval = HW_RESERR;
7757e589b0bSAlfred Perlstein 					break;
7767e589b0bSAlfred Perlstein 				}
7777e589b0bSAlfred Perlstein 
7787e589b0bSAlfred Perlstein 				debuglog("flock failed (from %16s): %32s\n",
7797e589b0bSAlfred Perlstein 				    fl->client_name, strerror(errno));
7807e589b0bSAlfred Perlstein 
7817e589b0bSAlfred Perlstein 				close(nmf->fd);
7827e589b0bSAlfred Perlstein 				free(nmf);
7837e589b0bSAlfred Perlstein 			} else {
7847e589b0bSAlfred Perlstein 				/* File opened and locked */
7857e589b0bSAlfred Perlstein 				LIST_INSERT_HEAD(&monfilelist_head, nmf, monfilelist);
7867e589b0bSAlfred Perlstein 				retval = HW_GRANTED;
7877e589b0bSAlfred Perlstein 
7887e589b0bSAlfred Perlstein 				debuglog("flock succeeded (from %16s)\n",
7897e589b0bSAlfred Perlstein 				    fl->client_name);
7907e589b0bSAlfred Perlstein 			}
7917e589b0bSAlfred Perlstein 		}
7927e589b0bSAlfred Perlstein 	} else {
7937e589b0bSAlfred Perlstein 		/*
7947e589b0bSAlfred Perlstein 		 * Filehandle already exists (we control the file)
7957e589b0bSAlfred Perlstein 		 * *AND* NFS has already cleared the lock for availability
7967e589b0bSAlfred Perlstein 		 * Grant it and bump the refcount.
7977e589b0bSAlfred Perlstein 		 */
7987e589b0bSAlfred Perlstein 		++(imf->refcount);
7997e589b0bSAlfred Perlstein 		retval = HW_GRANTED;
8007e589b0bSAlfred Perlstein 	}
8017e589b0bSAlfred Perlstein 
8027e589b0bSAlfred Perlstein 	return retval;
8037e589b0bSAlfred Perlstein }
8047e589b0bSAlfred Perlstein 
8057e589b0bSAlfred Perlstein enum hwlock_status
8067e589b0bSAlfred Perlstein unlock_hwlock(const struct file_lock *fl)
8077e589b0bSAlfred Perlstein {
8087e589b0bSAlfred Perlstein 	struct monfile *imf;
8097e589b0bSAlfred Perlstein 	enum hwlock_status retval;
8107e589b0bSAlfred Perlstein 
8117e589b0bSAlfred Perlstein 	debuglog("Entering unlock_hwlock\n");
8127e589b0bSAlfred Perlstein 	debuglog("Entering loop interation\n");
8137e589b0bSAlfred Perlstein 
8147e589b0bSAlfred Perlstein 
8157e589b0bSAlfred Perlstein 	/* Scan to see if filehandle already present */
8167e589b0bSAlfred Perlstein 	LIST_FOREACH(imf, &monfilelist_head, monfilelist) {
8177e589b0bSAlfred Perlstein 		if (bcmp(&fl->filehandle, &imf->filehandle,
8187e589b0bSAlfred Perlstein 			sizeof(fl->filehandle)) == 0) {
8197e589b0bSAlfred Perlstein 			/* imf is the correct filehandle */
8207e589b0bSAlfred Perlstein 			break;
8217e589b0bSAlfred Perlstein 		}
8227e589b0bSAlfred Perlstein 	}
8237e589b0bSAlfred Perlstein 
8247e589b0bSAlfred Perlstein 	debuglog("Completed iteration.  Proceeding\n");
8257e589b0bSAlfred Perlstein 
8267e589b0bSAlfred Perlstein 	if (imf == NULL) {
8277e589b0bSAlfred Perlstein 		/* No lock found */
8287e589b0bSAlfred Perlstein 		debuglog("No hardware lock found.\n");
8297e589b0bSAlfred Perlstein 		retval = HW_DENIED_NOLOCK;
8307e589b0bSAlfred Perlstein 	} else {
8317e589b0bSAlfred Perlstein 		/* Lock found */
8327e589b0bSAlfred Perlstein 		--imf->refcount;
8337e589b0bSAlfred Perlstein 
8347e589b0bSAlfred Perlstein 		if (imf->refcount < 0) {
8357e589b0bSAlfred Perlstein 			debuglog("Negative hardware reference count\n");
8367e589b0bSAlfred Perlstein 		}
8377e589b0bSAlfred Perlstein 
8387e589b0bSAlfred Perlstein 		if (imf->refcount <= 0) {
8397e589b0bSAlfred Perlstein 			close(imf->fd);
8407e589b0bSAlfred Perlstein 			LIST_REMOVE(imf, monfilelist);
8417e589b0bSAlfred Perlstein 			free(imf);
8427e589b0bSAlfred Perlstein 		}
8437e589b0bSAlfred Perlstein 		retval = HW_GRANTED;
8447e589b0bSAlfred Perlstein 	}
8457e589b0bSAlfred Perlstein 
8467e589b0bSAlfred Perlstein 	debuglog("Exiting unlock_hwlock\n");
8477e589b0bSAlfred Perlstein 
8487e589b0bSAlfred Perlstein 	return retval;
8497e589b0bSAlfred Perlstein }
8507e589b0bSAlfred Perlstein 
8517e589b0bSAlfred Perlstein enum hwlock_status
8527e589b0bSAlfred Perlstein test_hwlock(const struct file_lock *fl, struct file_lock **conflicting_fl)
8537e589b0bSAlfred Perlstein {
8547e589b0bSAlfred Perlstein 	/*
8557e589b0bSAlfred Perlstein 	 * XXX: lock tests on hardware are not required until
8567e589b0bSAlfred Perlstein 	 * true partial file testing is done on the underlying file
8577e589b0bSAlfred Perlstein 	 */
8587e589b0bSAlfred Perlstein 	return HW_RESERR;
8597e589b0bSAlfred Perlstein }
8607e589b0bSAlfred Perlstein 
8617e589b0bSAlfred Perlstein 
8627e589b0bSAlfred Perlstein 
8637e589b0bSAlfred Perlstein /*
8647e589b0bSAlfred Perlstein  * Below here are routines for manipulating blocked lock requests
8657e589b0bSAlfred Perlstein  * They should only be called from the XXX_partialfilelock routines
8667e589b0bSAlfred Perlstein  * if at all possible
8677e589b0bSAlfred Perlstein  */
8687e589b0bSAlfred Perlstein 
8697e589b0bSAlfred Perlstein void
8707e589b0bSAlfred Perlstein add_blockingfilelock(struct file_lock *fl)
8717e589b0bSAlfred Perlstein {
8727e589b0bSAlfred Perlstein 	debuglog("Entering add_blockingfilelock\n");
8737e589b0bSAlfred Perlstein 
8747e589b0bSAlfred Perlstein 	/*
8757e589b0bSAlfred Perlstein 	 * Clear the blocking flag so that it can be reused without
8767e589b0bSAlfred Perlstein 	 * adding it to the blocking queue a second time
8777e589b0bSAlfred Perlstein 	 */
8787e589b0bSAlfred Perlstein 
8797e589b0bSAlfred Perlstein 	fl->blocking = 0;
8807e589b0bSAlfred Perlstein 	LIST_INSERT_HEAD(&blockedlocklist_head, fl, nfslocklist);
8817e589b0bSAlfred Perlstein 
8827e589b0bSAlfred Perlstein 	debuglog("Exiting add_blockingfilelock\n");
8837e589b0bSAlfred Perlstein }
8847e589b0bSAlfred Perlstein 
8857e589b0bSAlfred Perlstein void
8867e589b0bSAlfred Perlstein remove_blockingfilelock(struct file_lock *fl)
8877e589b0bSAlfred Perlstein {
8887e589b0bSAlfred Perlstein 	debuglog("Entering remove_blockingfilelock\n");
8897e589b0bSAlfred Perlstein 
8907e589b0bSAlfred Perlstein 	LIST_REMOVE(fl, nfslocklist);
8917e589b0bSAlfred Perlstein 
8927e589b0bSAlfred Perlstein 	debuglog("Exiting remove_blockingfilelock\n");
8937e589b0bSAlfred Perlstein }
8947e589b0bSAlfred Perlstein 
8957e589b0bSAlfred Perlstein void
8967e589b0bSAlfred Perlstein retry_blockingfilelocklist(void)
8977e589b0bSAlfred Perlstein {
8987e589b0bSAlfred Perlstein 	/* Retry all locks in the blocked list */
8997e589b0bSAlfred Perlstein 	struct file_lock *ifl, *nfl; /* Iterator */
9007e589b0bSAlfred Perlstein 	enum partialfilelock_status pflstatus;
9017e589b0bSAlfred Perlstein 
9027e589b0bSAlfred Perlstein 	debuglog("Entering retry_blockingfilelocklist\n");
9037e589b0bSAlfred Perlstein 
9047e589b0bSAlfred Perlstein 	ifl = LIST_FIRST(&blockedlocklist_head);
9057e589b0bSAlfred Perlstein 	debuglog("Iterator choice %p\n",ifl);
9067e589b0bSAlfred Perlstein 
9077e589b0bSAlfred Perlstein 	while (ifl != NULL) {
9087e589b0bSAlfred Perlstein 		/*
9097e589b0bSAlfred Perlstein 		 * SUBTLE BUG: The next element must be worked out before the
9107e589b0bSAlfred Perlstein 		 * current element has been moved
9117e589b0bSAlfred Perlstein 		 */
9127e589b0bSAlfred Perlstein 		nfl = LIST_NEXT(ifl, nfslocklist);
9137e589b0bSAlfred Perlstein 		debuglog("Iterator choice %p\n",ifl);
9147e589b0bSAlfred Perlstein 		debuglog("Next iterator choice %p\n",nfl);
9157e589b0bSAlfred Perlstein 
9167e589b0bSAlfred Perlstein 		/*
9177e589b0bSAlfred Perlstein 		 * SUBTLE BUG: The file_lock must be removed from the
9187e589b0bSAlfred Perlstein 		 * old list so that it's list pointers get disconnected
9197e589b0bSAlfred Perlstein 		 * before being allowed to participate in the new list
9207e589b0bSAlfred Perlstein 		 * which will automatically add it in if necessary.
9217e589b0bSAlfred Perlstein 		 */
9227e589b0bSAlfred Perlstein 
9237e589b0bSAlfred Perlstein 		LIST_REMOVE(ifl, nfslocklist);
9247e589b0bSAlfred Perlstein 		pflstatus = lock_partialfilelock(ifl);
9257e589b0bSAlfred Perlstein 
9267e589b0bSAlfred Perlstein 		if (pflstatus == PFL_GRANTED || pflstatus == PFL_GRANTED_DUPLICATE) {
9277e589b0bSAlfred Perlstein 			debuglog("Granted blocked lock\n");
9287e589b0bSAlfred Perlstein 			/* lock granted and is now being used */
9297e589b0bSAlfred Perlstein 			send_granted(ifl,0);
9307e589b0bSAlfred Perlstein 		} else {
9317e589b0bSAlfred Perlstein 			/* Reinsert lock back into same place in blocked list */
9327e589b0bSAlfred Perlstein 			debuglog("Replacing blocked lock\n");
9337e589b0bSAlfred Perlstein 			LIST_INSERT_BEFORE(nfl, ifl, nfslocklist);
9347e589b0bSAlfred Perlstein 		}
9357e589b0bSAlfred Perlstein 
9367e589b0bSAlfred Perlstein 		/* Valid increment behavior regardless of state of ifl */
9377e589b0bSAlfred Perlstein 		ifl = nfl;
9387e589b0bSAlfred Perlstein 	}
9397e589b0bSAlfred Perlstein 
9407e589b0bSAlfred Perlstein 	debuglog("Exiting retry_blockingfilelocklist\n");
9417e589b0bSAlfred Perlstein }
9424945c132SAlfred Perlstein 
9434945c132SAlfred Perlstein /*
9444945c132SAlfred Perlstein  * Below here are routines associated with manipulating all
9454945c132SAlfred Perlstein  * aspects of the partial file locking system (list, hardware, etc.)
9464945c132SAlfred Perlstein  */
9474945c132SAlfred Perlstein 
9484945c132SAlfred Perlstein /*
9494945c132SAlfred Perlstein  * lock_partialfilelock:
9504945c132SAlfred Perlstein  *
9514945c132SAlfred Perlstein  * Argument fl gets modified as its list housekeeping entries get modified
9524945c132SAlfred Perlstein  * upon insertion into the NFS lock list
9534945c132SAlfred Perlstein  *
9544945c132SAlfred Perlstein  * This routine makes several assumptions:
9554945c132SAlfred Perlstein  *    1) It (will) pass locks through to fcntl to lock the underlying file
9564945c132SAlfred Perlstein  *           fcntl has some absolutely brain damaged unlocking semantics which
9574945c132SAlfred Perlstein  *               may cause trouble with NFS subsystem.  The primary problem
9584945c132SAlfred Perlstein  *               is that fcntl drops *ALL* locks held by a process when it
9594945c132SAlfred Perlstein  *               executes a close.  This means that NFS may indicate a range as
9604945c132SAlfred Perlstein  *               locked but the underlying file on hardware may not have that
9614945c132SAlfred Perlstein  *               lock anymore.
9624945c132SAlfred Perlstein  *           The safe solution may be for any NFS locks to cause an flock
9634945c132SAlfred Perlstein  *               of the entire underlying file by the lockd, parcel out
9644945c132SAlfred Perlstein  *               the partitions manually, and then to only
9654945c132SAlfred Perlstein  *               release the underlying file when all NFS locks are finished.
9664945c132SAlfred Perlstein  *    2) Nothing modifies the lock lists between testing and granting
9674945c132SAlfred Perlstein  *           I have no idea whether this is a useful guarantee of not
9684945c132SAlfred Perlstein  *
9694945c132SAlfred Perlstein  */
9704945c132SAlfred Perlstein 
9714945c132SAlfred Perlstein enum partialfilelock_status
9724945c132SAlfred Perlstein lock_partialfilelock(struct file_lock *fl)
9734945c132SAlfred Perlstein {
9744945c132SAlfred Perlstein 	enum partialfilelock_status retval;
9754945c132SAlfred Perlstein 	enum nfslock_status lnlstatus;
9767e589b0bSAlfred Perlstein 	enum hwlock_status hwstatus;
9774945c132SAlfred Perlstein 
9784945c132SAlfred Perlstein 	debuglog("Entering lock_partialfilelock\n");
9794945c132SAlfred Perlstein 
9804945c132SAlfred Perlstein 	retval = PFL_DENIED;
9814945c132SAlfred Perlstein 
9824945c132SAlfred Perlstein 	/*
9834945c132SAlfred Perlstein 	 * Execute the NFS lock first, if possible, as it is significantly
9844945c132SAlfred Perlstein 	 * easier and less expensive to undo than the filesystem lock
9854945c132SAlfred Perlstein 	 */
9864945c132SAlfred Perlstein 
9874945c132SAlfred Perlstein 	lnlstatus = lock_nfslock(fl);
9884945c132SAlfred Perlstein 
9897e589b0bSAlfred Perlstein 	switch (lnlstatus) {
9907e589b0bSAlfred Perlstein 	case NFS_GRANTED:
9917e589b0bSAlfred Perlstein 	case NFS_GRANTED_DUPLICATE:
9927e589b0bSAlfred Perlstein 		/*
9937e589b0bSAlfred Perlstein 		 * At this point, the NFS lock is allocated and active.
9947e589b0bSAlfred Perlstein 		 * Remember to clean it up if the hardware lock fails
9957e589b0bSAlfred Perlstein 		 */
9967e589b0bSAlfred Perlstein 		hwstatus = lock_hwlock(fl);
9977e589b0bSAlfred Perlstein 
9987e589b0bSAlfred Perlstein 		switch (hwstatus) {
9997e589b0bSAlfred Perlstein 		case HW_GRANTED:
10007e589b0bSAlfred Perlstein 		case HW_GRANTED_DUPLICATE:
10017e589b0bSAlfred Perlstein 			debuglog("HW GRANTED\n");
10027e589b0bSAlfred Perlstein 			/*
10037e589b0bSAlfred Perlstein 			 * XXX: Fixme: Check hwstatus for duplicate when
10047e589b0bSAlfred Perlstein 			 * true partial file locking and accounting is
10057e589b0bSAlfred Perlstein 			 * done on the hardware
10067e589b0bSAlfred Perlstein 			 */
10077e589b0bSAlfred Perlstein 			if (lnlstatus == NFS_GRANTED_DUPLICATE) {
10087e589b0bSAlfred Perlstein 				retval = PFL_GRANTED_DUPLICATE;
10094945c132SAlfred Perlstein 			} else {
10107e589b0bSAlfred Perlstein 				retval = PFL_GRANTED;
10114945c132SAlfred Perlstein 			}
10127e589b0bSAlfred Perlstein 			break;
10137e589b0bSAlfred Perlstein 		case HW_RESERR:
10147e589b0bSAlfred Perlstein 			debuglog("HW RESERR\n");
10157e589b0bSAlfred Perlstein 			retval = PFL_HWRESERR;
10167e589b0bSAlfred Perlstein 			break;
10177e589b0bSAlfred Perlstein 		case HW_DENIED:
10187e589b0bSAlfred Perlstein 			debuglog("HW DENIED\n");
10197e589b0bSAlfred Perlstein 			retval = PFL_HWDENIED;
10207e589b0bSAlfred Perlstein 			break;
10217e589b0bSAlfred Perlstein 		default:
10227e589b0bSAlfred Perlstein 			debuglog("Unmatched hwstatus %d\n",hwstatus);
10237e589b0bSAlfred Perlstein 			break;
10247e589b0bSAlfred Perlstein 		}
10257e589b0bSAlfred Perlstein 
10267e589b0bSAlfred Perlstein 		if (retval != PFL_GRANTED &&
10277e589b0bSAlfred Perlstein 		    retval != PFL_GRANTED_DUPLICATE) {
10287e589b0bSAlfred Perlstein 			/* Clean up the NFS lock */
10297e589b0bSAlfred Perlstein 			debuglog("Deleting trial NFS lock\n");
10307e589b0bSAlfred Perlstein 			delete_nfslock(fl);
10317e589b0bSAlfred Perlstein 		}
10327e589b0bSAlfred Perlstein 		break;
10337e589b0bSAlfred Perlstein 	case NFS_DENIED:
10344945c132SAlfred Perlstein 		retval = PFL_NFSDENIED;
10357e589b0bSAlfred Perlstein 		break;
10367e589b0bSAlfred Perlstein 	case NFS_RESERR:
10377e589b0bSAlfred Perlstein 		retval = PFL_NFSRESERR;
10387e589b0bSAlfred Perlstein 	default:
10397e589b0bSAlfred Perlstein 		debuglog("Unmatched lnlstatus %d\n");
10407e589b0bSAlfred Perlstein 		retval = PFL_NFSDENIED_NOLOCK;
10417e589b0bSAlfred Perlstein 		break;
10427e589b0bSAlfred Perlstein 	}
10437e589b0bSAlfred Perlstein 
10447e589b0bSAlfred Perlstein 	/*
10457e589b0bSAlfred Perlstein 	 * By the time fl reaches here, it is completely free again on
10467e589b0bSAlfred Perlstein 	 * failure.  The NFS lock done before attempting the
10477e589b0bSAlfred Perlstein 	 * hardware lock has been backed out
10487e589b0bSAlfred Perlstein 	 */
10497e589b0bSAlfred Perlstein 
10507e589b0bSAlfred Perlstein 	if (retval == PFL_NFSDENIED || retval == PFL_HWDENIED) {
10517e589b0bSAlfred Perlstein 		/* Once last chance to check the lock */
10527e589b0bSAlfred Perlstein 		if (fl->blocking == 1) {
10537e589b0bSAlfred Perlstein 			/* Queue the lock */
10547e589b0bSAlfred Perlstein 			debuglog("BLOCKING LOCK RECEIVED\n");
10557e589b0bSAlfred Perlstein 			retval = (retval == PFL_NFSDENIED ?
10567e589b0bSAlfred Perlstein 			    PFL_NFSBLOCKED : PFL_HWBLOCKED);
10577e589b0bSAlfred Perlstein 			add_blockingfilelock(fl);
10584945c132SAlfred Perlstein 			dump_filelock(fl);
10597e589b0bSAlfred Perlstein 		} else {
10607e589b0bSAlfred Perlstein 			/* Leave retval alone, it's already correct */
10617e589b0bSAlfred Perlstein 			debuglog("Lock denied.  Non-blocking failure\n");
10627e589b0bSAlfred Perlstein 			dump_filelock(fl);
10637e589b0bSAlfred Perlstein 		}
10644945c132SAlfred Perlstein 	}
10654945c132SAlfred Perlstein 
10664945c132SAlfred Perlstein 	debuglog("Exiting lock_partialfilelock\n");
10674945c132SAlfred Perlstein 
10684945c132SAlfred Perlstein 	return retval;
10694945c132SAlfred Perlstein }
10704945c132SAlfred Perlstein 
10714945c132SAlfred Perlstein /*
10724945c132SAlfred Perlstein  * unlock_partialfilelock:
10734945c132SAlfred Perlstein  */
10744945c132SAlfred Perlstein 
10754945c132SAlfred Perlstein enum partialfilelock_status
10764945c132SAlfred Perlstein unlock_partialfilelock(const struct file_lock *fl)
10774945c132SAlfred Perlstein {
10787e589b0bSAlfred Perlstein 	struct file_lock *lfl,*rfl,*releasedfl,*mfl;
10794945c132SAlfred Perlstein 	enum partialfilelock_status retval;
10807e589b0bSAlfred Perlstein 	enum nfslock_status unlstatus;
10817e589b0bSAlfred Perlstein 	enum hwlock_status unlhwstatus;
10824945c132SAlfred Perlstein 
10834945c132SAlfred Perlstein 	debuglog("Entering unlock_partialfilelock\n");
10844945c132SAlfred Perlstein 
10857e589b0bSAlfred Perlstein 	releasedfl = NULL;
10864945c132SAlfred Perlstein 	retval = PFL_DENIED;
10874945c132SAlfred Perlstein 
10887e589b0bSAlfred Perlstein 	/*
10897e589b0bSAlfred Perlstein 	 * Loop is required since multiple little locks
10907e589b0bSAlfred Perlstein 	 * can be allocated and then deallocated with one
10917e589b0bSAlfred Perlstein 	 * big unlock.
10927e589b0bSAlfred Perlstein 	 *
10937e589b0bSAlfred Perlstein 	 * The loop is required to be here so that the nfs &
10947e589b0bSAlfred Perlstein 	 * hw subsystems do not need to communicate with one
10957e589b0bSAlfred Perlstein 	 * one another
10967e589b0bSAlfred Perlstein 	 */
10974945c132SAlfred Perlstein 
10987e589b0bSAlfred Perlstein 	do {
10997e589b0bSAlfred Perlstein 		debuglog("Value of releasedfl: %p\n",releasedfl);
11007e589b0bSAlfred Perlstein 		unlstatus = unlock_nfslock(fl, &releasedfl, lfl, rfl);
11017e589b0bSAlfred Perlstein 		debuglog("Value of releasedfl: %p\n",releasedfl);
11027e589b0bSAlfred Perlstein 
11037e589b0bSAlfred Perlstein 		switch (unlstatus) {
11047e589b0bSAlfred Perlstein 		case NFS_GRANTED:
11057e589b0bSAlfred Perlstein 			/* Attempt to unlock on the hardware */
11067e589b0bSAlfred Perlstein 			debuglog("NFS unlock granted.  Attempting hardware unlock\n");
11077e589b0bSAlfred Perlstein 
11087e589b0bSAlfred Perlstein 			unlhwstatus = unlock_hwlock(fl);
11097e589b0bSAlfred Perlstein 			debuglog("HW unlock returned with code %d\n",unlhwstatus);
11107e589b0bSAlfred Perlstein 
11117e589b0bSAlfred Perlstein 			switch (unlhwstatus) {
11127e589b0bSAlfred Perlstein 			case HW_GRANTED:
11137e589b0bSAlfred Perlstein 				debuglog("HW unlock granted\n");
11144945c132SAlfred Perlstein 				retval = PFL_GRANTED;
11157e589b0bSAlfred Perlstein 				break;
11167e589b0bSAlfred Perlstein 			case HW_DENIED_NOLOCK:
11177e589b0bSAlfred Perlstein 				/* Huh?!?!  This shouldn't happen */
11187e589b0bSAlfred Perlstein 				debuglog("HW unlock denied no lock\n");
11197e589b0bSAlfred Perlstein 				retval = PFL_HWRESERR;
11207e589b0bSAlfred Perlstein 				/* Break out of do-while */
11217e589b0bSAlfred Perlstein 				unlstatus = NFS_RESERR;
11227e589b0bSAlfred Perlstein 				break;
11237e589b0bSAlfred Perlstein 			default:
11247e589b0bSAlfred Perlstein 				debuglog("HW unlock failed\n");
11257e589b0bSAlfred Perlstein 				retval = PFL_HWRESERR;
11267e589b0bSAlfred Perlstein 				/* Break out of do-while */
11277e589b0bSAlfred Perlstein 				unlstatus = NFS_RESERR;
11287e589b0bSAlfred Perlstein 				break;
11294945c132SAlfred Perlstein 			}
11304945c132SAlfred Perlstein 
11317e589b0bSAlfred Perlstein 			debuglog("Exiting with status retval: %d\n",retval);
11327e589b0bSAlfred Perlstein 
11337e589b0bSAlfred Perlstein 			/*
11347e589b0bSAlfred Perlstein 			 * XXX: this deallocation *still* needs to migrate closer
11357e589b0bSAlfred Perlstein 			 * to the allocation code way up in get_lock or the allocation
11367e589b0bSAlfred Perlstein 			 * code needs to migrate down (violation of "When you write
11377e589b0bSAlfred Perlstein 			 * malloc you must write free")
11387e589b0bSAlfred Perlstein 			 */
11397e589b0bSAlfred Perlstein 
11407e589b0bSAlfred Perlstein 			if (releasedfl != NULL) {
11417e589b0bSAlfred Perlstein 				deallocate_file_lock(releasedfl);
11427e589b0bSAlfred Perlstein 			}
11437e589b0bSAlfred Perlstein 
11447e589b0bSAlfred Perlstein 			retry_blockingfilelocklist();
11457e589b0bSAlfred Perlstein 			break;
11467e589b0bSAlfred Perlstein 		case NFS_DENIED_NOLOCK:
11477e589b0bSAlfred Perlstein 			retval = PFL_GRANTED;
11487e589b0bSAlfred Perlstein 			debuglog("All locks cleaned out\n");
11497e589b0bSAlfred Perlstein 			break;
11507e589b0bSAlfred Perlstein 		default:
11517e589b0bSAlfred Perlstein 			retval = PFL_NFSRESERR;
11527e589b0bSAlfred Perlstein 			debuglog("NFS unlock failure\n");
11537e589b0bSAlfred Perlstein 			dump_filelock(fl);
11547e589b0bSAlfred Perlstein 			break;
11557e589b0bSAlfred Perlstein 		}
11567e589b0bSAlfred Perlstein 	} while (unlstatus == NFS_GRANTED);
11577e589b0bSAlfred Perlstein 
11584945c132SAlfred Perlstein 	debuglog("Exiting unlock_partialfilelock\n");
11594945c132SAlfred Perlstein 
11604945c132SAlfred Perlstein 	return retval;
11614945c132SAlfred Perlstein }
11624945c132SAlfred Perlstein 
11634945c132SAlfred Perlstein /*
11644945c132SAlfred Perlstein  * test_partialfilelock:
11654945c132SAlfred Perlstein  */
11664945c132SAlfred Perlstein enum partialfilelock_status
11674945c132SAlfred Perlstein test_partialfilelock(const struct file_lock *fl,
11684945c132SAlfred Perlstein     struct file_lock **conflicting_fl)
11694945c132SAlfred Perlstein {
11704945c132SAlfred Perlstein 	enum partialfilelock_status retval;
11714945c132SAlfred Perlstein 	enum nfslock_status teststatus;
11724945c132SAlfred Perlstein 
11734945c132SAlfred Perlstein 	debuglog("Entering testpartialfilelock...\n");
11744945c132SAlfred Perlstein 
11754945c132SAlfred Perlstein 	retval = PFL_DENIED;
11764945c132SAlfred Perlstein 
11774945c132SAlfred Perlstein 	teststatus = test_nfslock(fl, conflicting_fl);
11784945c132SAlfred Perlstein 	debuglog("test_partialfilelock: teststatus %d\n",teststatus);
11794945c132SAlfred Perlstein 
11804945c132SAlfred Perlstein 	if (teststatus == NFS_GRANTED || teststatus == NFS_GRANTED_DUPLICATE) {
11814945c132SAlfred Perlstein 		/* XXX: Add the underlying filesystem locking code */
11824945c132SAlfred Perlstein 		retval = (teststatus == NFS_GRANTED) ?
11834945c132SAlfred Perlstein 		    PFL_GRANTED : PFL_GRANTED_DUPLICATE;
11844945c132SAlfred Perlstein 		debuglog("Dumping locks...\n");
11854945c132SAlfred Perlstein 		dump_filelock(fl);
11864945c132SAlfred Perlstein 		dump_filelock(*conflicting_fl);
11874945c132SAlfred Perlstein 		debuglog("Done dumping locks...\n");
11884945c132SAlfred Perlstein 	} else {
11894945c132SAlfred Perlstein 		retval = PFL_NFSDENIED;
11904945c132SAlfred Perlstein 		debuglog("NFS test denied.\n");
11914945c132SAlfred Perlstein 		dump_filelock(fl);
11924945c132SAlfred Perlstein 		debuglog("Conflicting.\n");
11934945c132SAlfred Perlstein 		dump_filelock(*conflicting_fl);
11944945c132SAlfred Perlstein 	}
11954945c132SAlfred Perlstein 
11964945c132SAlfred Perlstein 	debuglog("Exiting testpartialfilelock...\n");
11974945c132SAlfred Perlstein 
11984945c132SAlfred Perlstein 	return retval;
11994945c132SAlfred Perlstein }
12004945c132SAlfred Perlstein 
12014945c132SAlfred Perlstein 
12024945c132SAlfred Perlstein /*
12034945c132SAlfred Perlstein  * Below here are routines associated with translating the partial file locking
12044945c132SAlfred Perlstein  * codes into useful codes to send back to the NFS RPC messaging system
12054945c132SAlfred Perlstein  */
12064945c132SAlfred Perlstein 
12077e589b0bSAlfred Perlstein /*
12087e589b0bSAlfred Perlstein  * These routines translate the (relatively) useful return codes back onto
12097e589b0bSAlfred Perlstein  * the few return codes which the nlm subsystems wishes to trasmit
12107e589b0bSAlfred Perlstein  */
12117e589b0bSAlfred Perlstein 
12124945c132SAlfred Perlstein enum nlm_stats
12134945c132SAlfred Perlstein do_test(struct file_lock *fl, struct file_lock **conflicting_fl)
12144945c132SAlfred Perlstein {
12154945c132SAlfred Perlstein 	enum partialfilelock_status pfsret;
12164945c132SAlfred Perlstein 	enum nlm_stats retval;
12174945c132SAlfred Perlstein 
12184945c132SAlfred Perlstein 	debuglog("Entering do_test...\n");
12194945c132SAlfred Perlstein 
12204945c132SAlfred Perlstein 	pfsret = test_partialfilelock(fl,conflicting_fl);
12214945c132SAlfred Perlstein 
12227e589b0bSAlfred Perlstein 	switch (pfsret) {
12237e589b0bSAlfred Perlstein 	case PFL_GRANTED:
12247e589b0bSAlfred Perlstein 		debuglog("PFL test lock granted\n");
12254945c132SAlfred Perlstein 		dump_filelock(fl);
12264945c132SAlfred Perlstein 		dump_filelock(*conflicting_fl);
12274945c132SAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_granted : nlm_granted;
12287e589b0bSAlfred Perlstein 		break;
12297e589b0bSAlfred Perlstein 	case PFL_GRANTED_DUPLICATE:
12307e589b0bSAlfred Perlstein 		debuglog("PFL test lock granted--duplicate id detected\n");
12314945c132SAlfred Perlstein 		dump_filelock(fl);
12324945c132SAlfred Perlstein 		dump_filelock(*conflicting_fl);
12334945c132SAlfred Perlstein 		debuglog("Clearing conflicting_fl for call semantics\n");
12344945c132SAlfred Perlstein 		*conflicting_fl = NULL;
12354945c132SAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_granted : nlm_granted;
12367e589b0bSAlfred Perlstein 		break;
12377e589b0bSAlfred Perlstein 	case PFL_NFSDENIED:
12387e589b0bSAlfred Perlstein 	case PFL_HWDENIED:
12397e589b0bSAlfred Perlstein 		debuglog("PFL test lock denied\n");
12404945c132SAlfred Perlstein 		dump_filelock(fl);
12414945c132SAlfred Perlstein 		dump_filelock(*conflicting_fl);
12424945c132SAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_denied : nlm_denied;
12437e589b0bSAlfred Perlstein 		break;
12447e589b0bSAlfred Perlstein 	case PFL_NFSRESERR:
12457e589b0bSAlfred Perlstein 	case PFL_HWRESERR:
12467e589b0bSAlfred Perlstein 		debuglog("PFL test lock resource fail\n");
12477e589b0bSAlfred Perlstein 		dump_filelock(fl);
12487e589b0bSAlfred Perlstein 		dump_filelock(*conflicting_fl);
12497e589b0bSAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_denied_nolocks : nlm_denied_nolocks;
12507e589b0bSAlfred Perlstein 		break;
12517e589b0bSAlfred Perlstein 	default:
12527e589b0bSAlfred Perlstein 		debuglog("PFL test lock *FAILED*\n");
12534945c132SAlfred Perlstein 		dump_filelock(fl);
12544945c132SAlfred Perlstein 		dump_filelock(*conflicting_fl);
12554945c132SAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_failed : nlm_denied;
12567e589b0bSAlfred Perlstein 		break;
12574945c132SAlfred Perlstein 	}
12584945c132SAlfred Perlstein 
12594945c132SAlfred Perlstein 	debuglog("Exiting do_test...\n");
12604945c132SAlfred Perlstein 
12614945c132SAlfred Perlstein 	return retval;
12624945c132SAlfred Perlstein }
12634945c132SAlfred Perlstein 
12644945c132SAlfred Perlstein /*
12654945c132SAlfred Perlstein  * do_lock: Try to acquire a lock
12664945c132SAlfred Perlstein  *
12674945c132SAlfred Perlstein  * This routine makes a distinction between NLM versions.  I am pretty
12684945c132SAlfred Perlstein  * convinced that this should be abstracted out and bounced up a level
12694945c132SAlfred Perlstein  */
12704945c132SAlfred Perlstein 
12714945c132SAlfred Perlstein enum nlm_stats
12724945c132SAlfred Perlstein do_lock(struct file_lock *fl)
12734945c132SAlfred Perlstein {
12744945c132SAlfred Perlstein 	enum partialfilelock_status pfsret;
12754945c132SAlfred Perlstein 	enum nlm_stats retval;
12764945c132SAlfred Perlstein 
12774945c132SAlfred Perlstein 	debuglog("Entering do_lock...\n");
12784945c132SAlfred Perlstein 
12794945c132SAlfred Perlstein 	pfsret = lock_partialfilelock(fl);
12804945c132SAlfred Perlstein 
12817e589b0bSAlfred Perlstein 	switch (pfsret) {
12827e589b0bSAlfred Perlstein 	case PFL_GRANTED:
12834945c132SAlfred Perlstein 		debuglog("PFL lock granted");
12844945c132SAlfred Perlstein 		dump_filelock(fl);
12854945c132SAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_granted : nlm_granted;
12867e589b0bSAlfred Perlstein 		break;
12877e589b0bSAlfred Perlstein 	case PFL_GRANTED_DUPLICATE:
12884945c132SAlfred Perlstein 		debuglog("PFL lock granted--duplicate id detected");
12894945c132SAlfred Perlstein 		dump_filelock(fl);
12904945c132SAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_granted : nlm_granted;
12917e589b0bSAlfred Perlstein 		break;
12927e589b0bSAlfred Perlstein 	case PFL_NFSDENIED:
12937e589b0bSAlfred Perlstein 	case PFL_HWDENIED:
12944945c132SAlfred Perlstein 		debuglog("PFL_NFS lock denied");
12954945c132SAlfred Perlstein 		dump_filelock(fl);
12964945c132SAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_denied : nlm_denied;
12977e589b0bSAlfred Perlstein 		break;
12987e589b0bSAlfred Perlstein 	case PFL_NFSBLOCKED:
12997e589b0bSAlfred Perlstein 	case PFL_HWBLOCKED:
13007e589b0bSAlfred Perlstein 		debuglog("PFL_NFS blocking lock denied.  Queued.\n");
13017e589b0bSAlfred Perlstein 		dump_filelock(fl);
13027e589b0bSAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_blocked : nlm_blocked;
13037e589b0bSAlfred Perlstein 		break;
13047e589b0bSAlfred Perlstein 	case PFL_NFSRESERR:
13057e589b0bSAlfred Perlstein 	case PFL_HWRESERR:
13067e589b0bSAlfred Perlstein 		debuglog("PFL lock resource alocation fail\n");
13077e589b0bSAlfred Perlstein 		dump_filelock(fl);
13087e589b0bSAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_denied_nolocks : nlm_denied_nolocks;
13097e589b0bSAlfred Perlstein 		break;
13107e589b0bSAlfred Perlstein 	default:
13114945c132SAlfred Perlstein 		debuglog("PFL lock *FAILED*");
13124945c132SAlfred Perlstein 		dump_filelock(fl);
13134945c132SAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_failed : nlm_denied;
13147e589b0bSAlfred Perlstein 		break;
13154945c132SAlfred Perlstein 	}
13164945c132SAlfred Perlstein 
13174945c132SAlfred Perlstein 	debuglog("Exiting do_lock...\n");
13184945c132SAlfred Perlstein 
13194945c132SAlfred Perlstein 	return retval;
13204945c132SAlfred Perlstein }
13214945c132SAlfred Perlstein 
13224945c132SAlfred Perlstein enum nlm_stats
13234945c132SAlfred Perlstein do_unlock(struct file_lock *fl)
13244945c132SAlfred Perlstein {
13254945c132SAlfred Perlstein 	enum partialfilelock_status pfsret;
13264945c132SAlfred Perlstein 	enum nlm_stats retval;
13274945c132SAlfred Perlstein 
13284945c132SAlfred Perlstein 	debuglog("Entering do_unlock...\n");
13294945c132SAlfred Perlstein 	pfsret = unlock_partialfilelock(fl);
13304945c132SAlfred Perlstein 
13317e589b0bSAlfred Perlstein 	switch (pfsret) {
13327e589b0bSAlfred Perlstein 	case PFL_GRANTED:
13334945c132SAlfred Perlstein 		debuglog("PFL unlock granted");
13344945c132SAlfred Perlstein 		dump_filelock(fl);
13354945c132SAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_granted : nlm_granted;
13367e589b0bSAlfred Perlstein 		break;
13377e589b0bSAlfred Perlstein 	case PFL_NFSDENIED:
13387e589b0bSAlfred Perlstein 	case PFL_HWDENIED:
13394945c132SAlfred Perlstein 		debuglog("PFL_NFS unlock denied");
13404945c132SAlfred Perlstein 		dump_filelock(fl);
13414945c132SAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_denied : nlm_denied;
13427e589b0bSAlfred Perlstein 		break;
13437e589b0bSAlfred Perlstein 	case PFL_NFSDENIED_NOLOCK:
13447e589b0bSAlfred Perlstein 	case PFL_HWDENIED_NOLOCK:
13454945c132SAlfred Perlstein 		debuglog("PFL_NFS no lock found\n");
13464945c132SAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_granted : nlm_granted;
13477e589b0bSAlfred Perlstein 		break;
13487e589b0bSAlfred Perlstein 	case PFL_NFSRESERR:
13497e589b0bSAlfred Perlstein 	case PFL_HWRESERR:
13507e589b0bSAlfred Perlstein 		debuglog("PFL unlock resource failure");
13517e589b0bSAlfred Perlstein 		dump_filelock(fl);
13527e589b0bSAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_denied_nolocks : nlm_denied_nolocks;
13537e589b0bSAlfred Perlstein 		break;
13547e589b0bSAlfred Perlstein 	default:
13554945c132SAlfred Perlstein 		debuglog("PFL unlock *FAILED*");
13564945c132SAlfred Perlstein 		dump_filelock(fl);
13574945c132SAlfred Perlstein 		retval = (fl->flags & LOCK_V4) ? nlm4_failed : nlm_denied;
13587e589b0bSAlfred Perlstein 		break;
13594945c132SAlfred Perlstein 	}
13604945c132SAlfred Perlstein 
13614945c132SAlfred Perlstein 	debuglog("Exiting do_unlock...\n");
13624945c132SAlfred Perlstein 
13634945c132SAlfred Perlstein 	return retval;
13644945c132SAlfred Perlstein }
13654945c132SAlfred Perlstein 
13664945c132SAlfred Perlstein /*
13674945c132SAlfred Perlstein  * The following routines are all called from the code which the
13684945c132SAlfred Perlstein  * RPC layer invokes
13694945c132SAlfred Perlstein  */
13704945c132SAlfred Perlstein 
13714945c132SAlfred Perlstein /*
13724945c132SAlfred Perlstein  * testlock(): inform the caller if the requested lock would be granted
13734945c132SAlfred Perlstein  *
13744945c132SAlfred Perlstein  * returns NULL if lock would granted
13754945c132SAlfred Perlstein  * returns pointer to a conflicting nlm4_holder if not
13764945c132SAlfred Perlstein  */
13774945c132SAlfred Perlstein 
13784945c132SAlfred Perlstein struct nlm4_holder *
13794945c132SAlfred Perlstein testlock(struct nlm4_lock *lock, bool_t exclusive, int flags)
13804945c132SAlfred Perlstein {
13814945c132SAlfred Perlstein 	struct file_lock test_fl, *conflicting_fl;
13824945c132SAlfred Perlstein 
13834945c132SAlfred Perlstein 	bzero(&test_fl, sizeof(test_fl));
13844945c132SAlfred Perlstein 
13854945c132SAlfred Perlstein 	bcopy(lock->fh.n_bytes, &(test_fl.filehandle), sizeof(fhandle_t));
13864945c132SAlfred Perlstein 	copy_nlm4_lock_to_nlm4_holder(lock, exclusive, &test_fl.client);
13874945c132SAlfred Perlstein 
13884945c132SAlfred Perlstein 	siglock();
13894945c132SAlfred Perlstein 	do_test(&test_fl, &conflicting_fl);
13904945c132SAlfred Perlstein 
13914945c132SAlfred Perlstein 	if (conflicting_fl == NULL) {
13924945c132SAlfred Perlstein 		debuglog("No conflicting lock found\n");
13934945c132SAlfred Perlstein 		sigunlock();
13944945c132SAlfred Perlstein 		return NULL;
13954945c132SAlfred Perlstein 	} else {
13964945c132SAlfred Perlstein 		debuglog("Found conflicting lock\n");
13974945c132SAlfred Perlstein 		dump_filelock(conflicting_fl);
13984945c132SAlfred Perlstein 		sigunlock();
13994945c132SAlfred Perlstein 		return (&conflicting_fl->client);
14004945c132SAlfred Perlstein 	}
14014945c132SAlfred Perlstein }
14024945c132SAlfred Perlstein 
14034945c132SAlfred Perlstein /*
14044945c132SAlfred Perlstein  * getlock: try to aquire the lock.
14054945c132SAlfred Perlstein  * If file is already locked and we can sleep, put the lock in the list with
14064945c132SAlfred Perlstein  * status LKST_WAITING; it'll be processed later.
14074945c132SAlfred Perlstein  * Otherwise try to lock. If we're allowed to block, fork a child which
14084945c132SAlfred Perlstein  * will do the blocking lock.
14094945c132SAlfred Perlstein  */
14104945c132SAlfred Perlstein enum nlm_stats
14114945c132SAlfred Perlstein getlock(nlm4_lockargs *lckarg, struct svc_req *rqstp, const int flags)
14124945c132SAlfred Perlstein {
14134945c132SAlfred Perlstein 	struct file_lock *newfl;
14144945c132SAlfred Perlstein 	enum nlm_stats retval;
14154945c132SAlfred Perlstein 
14164945c132SAlfred Perlstein 	debuglog("Entering getlock...\n");
14174945c132SAlfred Perlstein 
14184945c132SAlfred Perlstein 	if (grace_expired == 0 && lckarg->reclaim == 0)
14194945c132SAlfred Perlstein 		return (flags & LOCK_V4) ?
14204945c132SAlfred Perlstein 		    nlm4_denied_grace_period : nlm_denied_grace_period;
14214945c132SAlfred Perlstein 
14224945c132SAlfred Perlstein 	/* allocate new file_lock for this request */
14234945c132SAlfred Perlstein 	newfl = malloc(sizeof(struct file_lock));
14244945c132SAlfred Perlstein 	if (newfl == NULL) {
14254945c132SAlfred Perlstein 		syslog(LOG_NOTICE, "malloc failed: %s", strerror(errno));
14264945c132SAlfred Perlstein 		/* failed */
14274945c132SAlfred Perlstein 		return (flags & LOCK_V4) ?
14284945c132SAlfred Perlstein 		    nlm4_denied_nolocks : nlm_denied_nolocks;
14294945c132SAlfred Perlstein 	}
14304945c132SAlfred Perlstein 
14314945c132SAlfred Perlstein 	if (lckarg->alock.fh.n_len != sizeof(fhandle_t)) {
14324945c132SAlfred Perlstein 		debuglog("recieved fhandle size %d, local size %d",
14334945c132SAlfred Perlstein 		    lckarg->alock.fh.n_len, (int)sizeof(fhandle_t));
14344945c132SAlfred Perlstein 	}
14354945c132SAlfred Perlstein 
14364945c132SAlfred Perlstein 	bcopy(lckarg->alock.fh.n_bytes,&newfl->filehandle, sizeof(fhandle_t));
14374945c132SAlfred Perlstein 	newfl->addr = (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf;
14384945c132SAlfred Perlstein 	newfl->client.exclusive = lckarg->exclusive;
14394945c132SAlfred Perlstein 	newfl->client.svid = lckarg->alock.svid;
14404945c132SAlfred Perlstein 	newfl->client.oh.n_bytes = malloc(lckarg->alock.oh.n_len);
14414945c132SAlfred Perlstein 	if (newfl->client.oh.n_bytes == NULL) {
14424945c132SAlfred Perlstein 		syslog(LOG_NOTICE, "malloc failed: %s", strerror(errno));
14434945c132SAlfred Perlstein 		free(newfl);
14444945c132SAlfred Perlstein 		return (flags & LOCK_V4) ?
14454945c132SAlfred Perlstein 		    nlm4_denied_nolocks : nlm_denied_nolocks;
14464945c132SAlfred Perlstein 	}
14474945c132SAlfred Perlstein 
14484945c132SAlfred Perlstein 	newfl->client.oh.n_len = lckarg->alock.oh.n_len;
14494945c132SAlfred Perlstein 	bcopy(lckarg->alock.oh.n_bytes, newfl->client.oh.n_bytes,
14504945c132SAlfred Perlstein 	    lckarg->alock.oh.n_len);
14514945c132SAlfred Perlstein 	newfl->client.l_offset = lckarg->alock.l_offset;
14524945c132SAlfred Perlstein 	newfl->client.l_len = lckarg->alock.l_len;
14534945c132SAlfred Perlstein 	newfl->client_cookie.n_len = lckarg->cookie.n_len;
14544945c132SAlfred Perlstein 	newfl->client_cookie.n_bytes = malloc(lckarg->cookie.n_len);
14554945c132SAlfred Perlstein 	if (newfl->client_cookie.n_bytes == NULL) {
14564945c132SAlfred Perlstein 		syslog(LOG_NOTICE, "malloc failed: %s", strerror(errno));
14574945c132SAlfred Perlstein 		free(newfl->client.oh.n_bytes);
14584945c132SAlfred Perlstein 		free(newfl);
14594945c132SAlfred Perlstein 		return (flags & LOCK_V4) ?
14604945c132SAlfred Perlstein 		    nlm4_denied_nolocks : nlm_denied_nolocks;
14614945c132SAlfred Perlstein 	}
14624945c132SAlfred Perlstein 
14634945c132SAlfred Perlstein 	bcopy(lckarg->cookie.n_bytes, newfl->client_cookie.n_bytes,
14644945c132SAlfred Perlstein 	    lckarg->cookie.n_len);
14654945c132SAlfred Perlstein 	strncpy(newfl->client_name, lckarg->alock.caller_name, SM_MAXSTRLEN);
14664945c132SAlfred Perlstein 	newfl->nsm_status = lckarg->state;
14674945c132SAlfred Perlstein 	newfl->status = 0;
14684945c132SAlfred Perlstein 	newfl->flags = flags;
14697e589b0bSAlfred Perlstein 	newfl->blocking = lckarg->block;
14704945c132SAlfred Perlstein 
14714945c132SAlfred Perlstein 	/*
14724945c132SAlfred Perlstein 	 * newfl is now fully constructed and deallocate_file_lock
14734945c132SAlfred Perlstein 	 * can now be used to delete it
14744945c132SAlfred Perlstein 	 * The *only* place which should deallocate a file_lock is
14754945c132SAlfred Perlstein 	 * either here (error condition) or the unlock code.
14764945c132SAlfred Perlstein 	 */
14774945c132SAlfred Perlstein 
14784945c132SAlfred Perlstein 	siglock();
14794945c132SAlfred Perlstein 	debuglog("Pointer to new lock is %p\n",newfl);
14807e589b0bSAlfred Perlstein 
14814945c132SAlfred Perlstein 	retval = do_lock(newfl);
14827e589b0bSAlfred Perlstein 
14834945c132SAlfred Perlstein 	debuglog("Pointer to new lock is %p\n",newfl);
14844945c132SAlfred Perlstein 	sigunlock();
14854945c132SAlfred Perlstein 
14864945c132SAlfred Perlstein 	switch (retval)
14874945c132SAlfred Perlstein 		{
14884945c132SAlfred Perlstein 		case nlm4_granted:
14894945c132SAlfred Perlstein 			/* case nlm_granted: is the same as nlm4_granted */
14904945c132SAlfred Perlstein 			/* do_mon(lckarg->alock.caller_name); */
14914945c132SAlfred Perlstein 			break;
14924945c132SAlfred Perlstein 		case nlm4_blocked:
14934945c132SAlfred Perlstein 			/* case nlm_blocked: is the same as nlm4_blocked */
14944945c132SAlfred Perlstein 			/* do_mon(lckarg->alock.caller_name); */
14954945c132SAlfred Perlstein 			break;
14964945c132SAlfred Perlstein 		default:
14974945c132SAlfred Perlstein 			deallocate_file_lock(newfl);
14984945c132SAlfred Perlstein 			break;
14994945c132SAlfred Perlstein 		}
15004945c132SAlfred Perlstein 
15014945c132SAlfred Perlstein 	debuglog("Exiting getlock...\n");
15024945c132SAlfred Perlstein 
15037e589b0bSAlfred Perlstein 	return retval;
15044945c132SAlfred Perlstein }
15054945c132SAlfred Perlstein 
15064945c132SAlfred Perlstein 
15074945c132SAlfred Perlstein /* unlock a filehandle */
15084945c132SAlfred Perlstein enum nlm_stats
15094945c132SAlfred Perlstein unlock(nlm4_lock *lock, const int flags)
15104945c132SAlfred Perlstein {
15114945c132SAlfred Perlstein 	struct file_lock fl;
15124945c132SAlfred Perlstein 	enum nlm_stats err;
15134945c132SAlfred Perlstein 
15144945c132SAlfred Perlstein 	siglock();
15154945c132SAlfred Perlstein 
15164945c132SAlfred Perlstein 	debuglog("Entering unlock...\n");
15174945c132SAlfred Perlstein 
15184945c132SAlfred Perlstein 	bzero(&fl,sizeof(struct file_lock));
15194945c132SAlfred Perlstein 	bcopy(lock->fh.n_bytes, &fl.filehandle, sizeof(fhandle_t));
15204945c132SAlfred Perlstein 
15214945c132SAlfred Perlstein 	copy_nlm4_lock_to_nlm4_holder(lock, 0, &fl.client);
15224945c132SAlfred Perlstein 
15234945c132SAlfred Perlstein 	err = do_unlock(&fl);
15244945c132SAlfred Perlstein 
15254945c132SAlfred Perlstein 	sigunlock();
15264945c132SAlfred Perlstein 
15274945c132SAlfred Perlstein 	debuglog("Exiting unlock...\n");
15284945c132SAlfred Perlstein 
15294945c132SAlfred Perlstein 	return err;
15304945c132SAlfred Perlstein }
15314945c132SAlfred Perlstein 
15324945c132SAlfred Perlstein /*
15334945c132SAlfred Perlstein  * XXX: The following monitor/unmonitor routines
15344945c132SAlfred Perlstein  * HAVE NOT BEEN TESTED!!!  THEY ARE GUARANTEED TO
15354945c132SAlfred Perlstein  * BE WRONG!!! At the very least, there are pointers
15364945c132SAlfred Perlstein  * to characters being thrown around when they should be
15374945c132SAlfred Perlstein  * strings in the statd structures.  Consequently, the
15384945c132SAlfred Perlstein  * statd calling code has been commented out. Please note
15394945c132SAlfred Perlstein  * that this problem was also in the original do_mon routine
15404945c132SAlfred Perlstein  * which this pair replaced (and there was no do_unmon either)
15414945c132SAlfred Perlstein  */
15424945c132SAlfred Perlstein 
15434945c132SAlfred Perlstein /*
15444945c132SAlfred Perlstein  * monitor_lock_host: monitor lock hosts locally with a ref count and
15454945c132SAlfred Perlstein  * inform statd
15464945c132SAlfred Perlstein  *
15474945c132SAlfred Perlstein  * XXX: Are the strnXXX functions the correct choices?
15484945c132SAlfred Perlstein  */
15494945c132SAlfred Perlstein void
15504945c132SAlfred Perlstein monitor_lock_host(const char *hostname)
15514945c132SAlfred Perlstein {
15524945c132SAlfred Perlstein 	struct host *ihp, *nhp;
15534945c132SAlfred Perlstein 	struct mon smon;
15544945c132SAlfred Perlstein 	struct sm_stat_res sres;
15554945c132SAlfred Perlstein 	int rpcret, statflag;
15564945c132SAlfred Perlstein 
15574945c132SAlfred Perlstein 	rpcret = 0;
15584945c132SAlfred Perlstein 	statflag = 0;
15594945c132SAlfred Perlstein 
15607e589b0bSAlfred Perlstein 	for( ihp=LIST_FIRST(&hostlst_head); ihp != NULL;
15617e589b0bSAlfred Perlstein 	     ihp=LIST_NEXT(ihp, hostlst)) {
15624945c132SAlfred Perlstein 		if (strncmp(hostname, ihp->name, SM_MAXSTRLEN) == 0) {
15634945c132SAlfred Perlstein 			/* Host is already monitored, bump refcount */
15644945c132SAlfred Perlstein 			++ihp->refcnt;
15654945c132SAlfred Perlstein 			/* Host should only be in the monitor list once */
15664945c132SAlfred Perlstein 			break;
15674945c132SAlfred Perlstein 		}
15684945c132SAlfred Perlstein 	}
15694945c132SAlfred Perlstein 
15707e589b0bSAlfred Perlstein 	if (ihp == NULL) {
15714945c132SAlfred Perlstein 		/* Host is not yet monitored, add it */
15724945c132SAlfred Perlstein 		nhp = malloc(sizeof(struct host));
15734945c132SAlfred Perlstein 
15744945c132SAlfred Perlstein 		if (nhp == NULL) {
15754945c132SAlfred Perlstein 			debuglog("Unable to allocate entry for statd mon\n");
15767e589b0bSAlfred Perlstein 		} else {
15774945c132SAlfred Perlstein 			/* Allocated new host entry, now fill the fields */
15784945c132SAlfred Perlstein 			strncpy(nhp->name, hostname, SM_MAXSTRLEN);
15794945c132SAlfred Perlstein 			nhp->refcnt = 1;
15804945c132SAlfred Perlstein 			debuglog("Locally Monitoring host %16s\n",hostname);
15817e589b0bSAlfred Perlstein 
15824945c132SAlfred Perlstein 			debuglog("Attempting to tell statd\n");
15837e589b0bSAlfred Perlstein 
15844945c132SAlfred Perlstein 			bzero(&smon,sizeof(struct mon));
15857e589b0bSAlfred Perlstein 
15867e589b0bSAlfred Perlstein 			/*
15874945c132SAlfred Perlstein 			  smon.mon_id.mon_name = nhp->name;
15884945c132SAlfred Perlstein 			  smon.mon_id.my_id.my_name = "localhost";
15894945c132SAlfred Perlstein 			  smon.mon_id.my_id.my_prog = NLM_PROG;
15904945c132SAlfred Perlstein 			  smon.mon_id.my_id.my_vers = NLM_SM;
15914945c132SAlfred Perlstein 			  smon.mon_id.my_id.my_proc = NLM_SM_NOTIFY;
15924945c132SAlfred Perlstein 
15937e589b0bSAlfred Perlstein 			  rpcret = callrpc("localhost", SM_PROG, SM_VERS, SM_MON, xdr_mon,
15947e589b0bSAlfred Perlstein 			  &smon, xdr_sm_stat_res, &sres);
15954945c132SAlfred Perlstein 
15967e589b0bSAlfred Perlstein 			  if (rpcret == 0)
15977e589b0bSAlfred Perlstein 			  {
15984945c132SAlfred Perlstein 			  if (sres.res_stat == stat_fail) {
15994945c132SAlfred Perlstein 			  debuglog("Statd call failed\n");
16004945c132SAlfred Perlstein 			  statflag = 0;
16014945c132SAlfred Perlstein 			  } else {
16024945c132SAlfred Perlstein 			  statflag = 1;
16034945c132SAlfred Perlstein 			  }
16044945c132SAlfred Perlstein 			  } else {
16057e589b0bSAlfred Perlstein 			  debuglog("Rpc call to statd failed with return value: %d\n",rpcret);
16064945c132SAlfred Perlstein 			  statflag = 0;
16074945c132SAlfred Perlstein 			  }
16087e589b0bSAlfred Perlstein 			*/
16094945c132SAlfred Perlstein 
16104945c132SAlfred Perlstein 			/* XXX: remove this when statd code is fixed */
16114945c132SAlfred Perlstein 			statflag = 1;
16124945c132SAlfred Perlstein 			if (statflag == 1) {
16134945c132SAlfred Perlstein 				LIST_INSERT_HEAD(&hostlst_head, nhp, hostlst);
16144945c132SAlfred Perlstein 			} else {
16154945c132SAlfred Perlstein 				free(nhp);
16164945c132SAlfred Perlstein 			}
16174945c132SAlfred Perlstein 		}
16187e589b0bSAlfred Perlstein 	}
16197e589b0bSAlfred Perlstein }
16204945c132SAlfred Perlstein 
16214945c132SAlfred Perlstein /*
16224945c132SAlfred Perlstein  * unmonitor_lock_host: clear monitor ref counts and inform statd when gone
16234945c132SAlfred Perlstein  */
16244945c132SAlfred Perlstein void
16254945c132SAlfred Perlstein unmonitor_lock_host(const char *hostname)
16264945c132SAlfred Perlstein {
16274945c132SAlfred Perlstein 	struct host *ihp, *nhp;
16284945c132SAlfred Perlstein 	struct mon_id smon_id;
16294945c132SAlfred Perlstein 	struct sm_stat smstat;
16304945c132SAlfred Perlstein 	int rpcret;
16314945c132SAlfred Perlstein 
16324945c132SAlfred Perlstein 	rpcret = 0;
16334945c132SAlfred Perlstein 
16347e589b0bSAlfred Perlstein 	for( ihp=LIST_FIRST(&hostlst_head); ihp != NULL;
16357e589b0bSAlfred Perlstein 	     ihp=LIST_NEXT(ihp, hostlst)) {
16364945c132SAlfred Perlstein 		if (strncmp(hostname, ihp->name, SM_MAXSTRLEN) == 0) {
16374945c132SAlfred Perlstein 			/* Host is monitored, bump refcount */
16384945c132SAlfred Perlstein 			--ihp->refcnt;
16394945c132SAlfred Perlstein 			/* Host should only be in the monitor list once */
16404945c132SAlfred Perlstein 			break;
16414945c132SAlfred Perlstein 		}
16424945c132SAlfred Perlstein 	}
16434945c132SAlfred Perlstein 
16444945c132SAlfred Perlstein 	if (ihp == NULL) {
16454945c132SAlfred Perlstein 		debuglog("Could not find host %16s in mon list\n", hostname);
16467e589b0bSAlfred Perlstein 	} else {
16477e589b0bSAlfred Perlstein 		if (ihp->refcnt <= 0) {
16487e589b0bSAlfred Perlstein 			if (ihp->refcnt < 0) {
16497e589b0bSAlfred Perlstein 				debuglog("Negative refcount!: %d\n",
16507e589b0bSAlfred Perlstein 				    ihp->refcnt);
16514945c132SAlfred Perlstein 			}
16524945c132SAlfred Perlstein 
16537e589b0bSAlfred Perlstein 			debuglog("Attempting to unmonitor host %16s\n",
16547e589b0bSAlfred Perlstein 			    hostname);
16554945c132SAlfred Perlstein 
16564945c132SAlfred Perlstein 			bzero(&smon_id,sizeof(smon_id));
16577e589b0bSAlfred Perlstein 
16587e589b0bSAlfred Perlstein 			/*
16594945c132SAlfred Perlstein 			  smon_id.mon_name = hostname;
16604945c132SAlfred Perlstein 			  smon_id.my_id.my_name = "localhost";
16614945c132SAlfred Perlstein 			  smon_id.my_id.my_prog = NLM_PROG;
16624945c132SAlfred Perlstein 			  smon_id.my_id.my_vers = NLM_SM;
16634945c132SAlfred Perlstein 			  smon_id.my_id.my_proc = NLM_SM_NOTIFY;
16647e589b0bSAlfred Perlstein 
16657e589b0bSAlfred Perlstein 			  rpcret = callrpc("localhost", SM_PROG, SM_VERS, SM_UNMON, xdr_mon,
16667e589b0bSAlfred Perlstein 			  &smon_id, xdr_sm_stat_res, &smstat);
16677e589b0bSAlfred Perlstein 
16684945c132SAlfred Perlstein 			  if (rpcret != 0)
16697e589b0bSAlfred Perlstein 			  {
16707e589b0bSAlfred Perlstein 			  debuglog("Rpc call to unmonitor statd failed with return value: %d\n",rpcret);
16717e589b0bSAlfred Perlstein 			  }
16727e589b0bSAlfred Perlstein 			*/
16737e589b0bSAlfred Perlstein 
16744945c132SAlfred Perlstein 			LIST_REMOVE(ihp, hostlst);
16754945c132SAlfred Perlstein 			free(ihp);
16764945c132SAlfred Perlstein 		}
16777e589b0bSAlfred Perlstein 	}
16787e589b0bSAlfred Perlstein }
16794945c132SAlfred Perlstein 
16804945c132SAlfred Perlstein /*
16814945c132SAlfred Perlstein  * notify: Clear all locks from a host if statd complains
16824945c132SAlfred Perlstein  *
16834945c132SAlfred Perlstein  * CAUTION: This routine has probably not been thoroughly tested even in
16844945c132SAlfred Perlstein  * its original incarnation.  The proof is the fact that it only tests
16854945c132SAlfred Perlstein  * for nlm_granted on do_unlock rather than inlcluding nlm4_granted.
16864945c132SAlfred Perlstein  *
16874945c132SAlfred Perlstein  * Consequently, it has been commented out until it has.
16884945c132SAlfred Perlstein  */
16894945c132SAlfred Perlstein 
16904945c132SAlfred Perlstein void
16914945c132SAlfred Perlstein notify(const char *hostname, const int state)
16924945c132SAlfred Perlstein {
16934945c132SAlfred Perlstein 	struct file_lock *fl, *next_fl;
16944945c132SAlfred Perlstein 	int err;
16954945c132SAlfred Perlstein 	debuglog("notify from %s, new state %d", hostname, state);
16964945c132SAlfred Perlstein 
16974945c132SAlfred Perlstein 	debuglog("****************************\n");
16984945c132SAlfred Perlstein 	debuglog("No action taken in notify!!!\n");
16994945c132SAlfred Perlstein 	debuglog("****************************\n");
17004945c132SAlfred Perlstein 
17014945c132SAlfred Perlstein   /* search all lock for this host; if status changed, release the lock */
17027e589b0bSAlfred Perlstein   /*
17034945c132SAlfred Perlstein 	siglock();
17044945c132SAlfred Perlstein 	for (fl = LIST_FIRST(&nfslocklist_head); fl != NULL; fl = next_fl) {
17054945c132SAlfred Perlstein 		next_fl = LIST_NEXT(fl, nfslocklist);
17064945c132SAlfred Perlstein 		if (strcmp(hostname, fl->client_name) == 0 &&
17074945c132SAlfred Perlstein 		    fl->nsm_status != state) {
17084945c132SAlfred Perlstein 			debuglog("state %d, nsm_state %d, unlocking",
17094945c132SAlfred Perlstein 				 fl->status, fl->nsm_status);
17104945c132SAlfred Perlstein 			switch(fl->status) {
17114945c132SAlfred Perlstein 			case LKST_LOCKED:
17124945c132SAlfred Perlstein 				err = do_unlock(fl);
17134945c132SAlfred Perlstein 				if (err != nlm_granted)
17144945c132SAlfred Perlstein 				  debuglog("notify: unlock failed for %s (%d)",
17154945c132SAlfred Perlstein 					   hostname, err);
17164945c132SAlfred Perlstein 				break;
17174945c132SAlfred Perlstein 			case LKST_WAITING:
17184945c132SAlfred Perlstein 				LIST_REMOVE(fl, nfslocklist);
17194945c132SAlfred Perlstein 				lfree(fl);
17204945c132SAlfred Perlstein 				break;
17214945c132SAlfred Perlstein 			case LKST_PROCESSING:
17224945c132SAlfred Perlstein 				fl->status = LKST_DYING;
17234945c132SAlfred Perlstein 				break;
17244945c132SAlfred Perlstein 			case LKST_DYING:
17254945c132SAlfred Perlstein 				break;
17264945c132SAlfred Perlstein 			default:
17274945c132SAlfred Perlstein 				syslog(LOG_NOTICE, "unknow status %d for %s",
17284945c132SAlfred Perlstein 				    fl->status, fl->client_name);
17294945c132SAlfred Perlstein 			}
17304945c132SAlfred Perlstein 		}
17314945c132SAlfred Perlstein 	}
17324945c132SAlfred Perlstein 	sigunlock();
17337e589b0bSAlfred Perlstein   */
17344945c132SAlfred Perlstein }
17354945c132SAlfred Perlstein 
17364945c132SAlfred Perlstein /*
17374945c132SAlfred Perlstein  * Routines below here have not been modified in the overhaul
17384945c132SAlfred Perlstein  */
17394945c132SAlfred Perlstein void
17404945c132SAlfred Perlstein send_granted(fl, opcode)
17414945c132SAlfred Perlstein 	struct file_lock *fl;
17424945c132SAlfred Perlstein 	int opcode;
17434945c132SAlfred Perlstein {
17444945c132SAlfred Perlstein 	CLIENT *cli;
17454945c132SAlfred Perlstein 	static char dummy;
17464945c132SAlfred Perlstein 	struct timeval timeo;
17474945c132SAlfred Perlstein 	int success;
17484945c132SAlfred Perlstein 	static struct nlm_res retval;
17494945c132SAlfred Perlstein 	static struct nlm4_res retval4;
17504945c132SAlfred Perlstein 
17517e589b0bSAlfred Perlstein 	debuglog("About to send granted on blocked lock\n");
17527e589b0bSAlfred Perlstein 	sleep(1);
17537e589b0bSAlfred Perlstein 	debuglog("Blowing off return send\n");
17547e589b0bSAlfred Perlstein 
17554945c132SAlfred Perlstein 	cli = get_client(fl->addr,
17564945c132SAlfred Perlstein 	    (fl->flags & LOCK_V4) ? NLM_VERS4 : NLM_VERS);
17574945c132SAlfred Perlstein 	if (cli == NULL) {
17584945c132SAlfred Perlstein 		syslog(LOG_NOTICE, "failed to get CLIENT for %s",
17594945c132SAlfred Perlstein 		    fl->client_name);
17604945c132SAlfred Perlstein 		/*
17614945c132SAlfred Perlstein 		 * We fail to notify remote that the lock has been granted.
17624945c132SAlfred Perlstein 		 * The client will timeout and retry, the lock will be
17634945c132SAlfred Perlstein 		 * granted at this time.
17644945c132SAlfred Perlstein 		 */
17654945c132SAlfred Perlstein 		return;
17664945c132SAlfred Perlstein 	}
17674945c132SAlfred Perlstein 	timeo.tv_sec = 0;
17684945c132SAlfred Perlstein 	timeo.tv_usec = (fl->flags & LOCK_ASYNC) ? 0 : 500000; /* 0.5s */
17694945c132SAlfred Perlstein 
17704945c132SAlfred Perlstein 	if (fl->flags & LOCK_V4) {
17714945c132SAlfred Perlstein 		static nlm4_testargs res;
17724945c132SAlfred Perlstein 		res.cookie = fl->client_cookie;
17734945c132SAlfred Perlstein 		res.exclusive = fl->client.exclusive;
17744945c132SAlfred Perlstein 		res.alock.caller_name = fl->client_name;
17754945c132SAlfred Perlstein 		res.alock.fh.n_len = sizeof(fhandle_t);
17764945c132SAlfred Perlstein 		res.alock.fh.n_bytes = (char*)&fl->filehandle;
17774945c132SAlfred Perlstein 		res.alock.oh = fl->client.oh;
17784945c132SAlfred Perlstein 		res.alock.svid = fl->client.svid;
17794945c132SAlfred Perlstein 		res.alock.l_offset = fl->client.l_offset;
17804945c132SAlfred Perlstein 		res.alock.l_len = fl->client.l_len;
17814945c132SAlfred Perlstein 		debuglog("sending v4 reply%s",
17824945c132SAlfred Perlstein 			 (fl->flags & LOCK_ASYNC) ? " (async)":"");
17834945c132SAlfred Perlstein 		if (fl->flags & LOCK_ASYNC) {
17844945c132SAlfred Perlstein 			success = clnt_call(cli, NLM4_GRANTED_MSG,
17854945c132SAlfred Perlstein 			    xdr_nlm4_testargs, &res, xdr_void, &dummy, timeo);
17864945c132SAlfred Perlstein 		} else {
17874945c132SAlfred Perlstein 			success = clnt_call(cli, NLM4_GRANTED,
17884945c132SAlfred Perlstein 			    xdr_nlm4_testargs, &res, xdr_nlm4_res,
17894945c132SAlfred Perlstein 			    &retval4, timeo);
17904945c132SAlfred Perlstein 		}
17914945c132SAlfred Perlstein 	} else {
17924945c132SAlfred Perlstein 		static nlm_testargs res;
17934945c132SAlfred Perlstein 
17944945c132SAlfred Perlstein 		res.cookie = fl->client_cookie;
17954945c132SAlfred Perlstein 		res.exclusive = fl->client.exclusive;
17964945c132SAlfred Perlstein 		res.alock.caller_name = fl->client_name;
17974945c132SAlfred Perlstein 		res.alock.fh.n_len = sizeof(fhandle_t);
17984945c132SAlfred Perlstein 		res.alock.fh.n_bytes = (char*)&fl->filehandle;
17994945c132SAlfred Perlstein 		res.alock.oh = fl->client.oh;
18004945c132SAlfred Perlstein 		res.alock.svid = fl->client.svid;
18014945c132SAlfred Perlstein 		res.alock.l_offset = fl->client.l_offset;
18024945c132SAlfred Perlstein 		res.alock.l_len = fl->client.l_len;
18034945c132SAlfred Perlstein 		debuglog("sending v1 reply%s",
18044945c132SAlfred Perlstein 			 (fl->flags & LOCK_ASYNC) ? " (async)":"");
18054945c132SAlfred Perlstein 		if (fl->flags & LOCK_ASYNC) {
18064945c132SAlfred Perlstein 			success = clnt_call(cli, NLM_GRANTED_MSG,
18074945c132SAlfred Perlstein 			    xdr_nlm_testargs, &res, xdr_void, &dummy, timeo);
18084945c132SAlfred Perlstein 		} else {
18094945c132SAlfred Perlstein 			success = clnt_call(cli, NLM_GRANTED,
18104945c132SAlfred Perlstein 			    xdr_nlm_testargs, &res, xdr_nlm_res,
18114945c132SAlfred Perlstein 			    &retval, timeo);
18124945c132SAlfred Perlstein 		}
18134945c132SAlfred Perlstein 	}
18144945c132SAlfred Perlstein 	if (debug_level > 2)
18157e589b0bSAlfred Perlstein 		debuglog("clnt_call returns %d(%s) for granted",
18164945c132SAlfred Perlstein 			 success, clnt_sperrno(success));
18174945c132SAlfred Perlstein 
18184945c132SAlfred Perlstein }
18194945c132SAlfred Perlstein 
18204945c132SAlfred Perlstein /*
18217e589b0bSAlfred Perlstein  * Are these two routines still required since lockd is not spawning off
18227e589b0bSAlfred Perlstein  * children to service locks anymore?  Presumably they were originally
18237e589b0bSAlfred Perlstein  * put in place to prevent a one child from changing the lock list out
18247e589b0bSAlfred Perlstein  * from under another one.
18254945c132SAlfred Perlstein  */
18267e589b0bSAlfred Perlstein 
18274945c132SAlfred Perlstein void
18284945c132SAlfred Perlstein siglock(void)
18294945c132SAlfred Perlstein {
18304945c132SAlfred Perlstein   sigset_t block;
18314945c132SAlfred Perlstein 
18324945c132SAlfred Perlstein   sigemptyset(&block);
18334945c132SAlfred Perlstein   sigaddset(&block, SIGCHLD);
18344945c132SAlfred Perlstein 
18357e589b0bSAlfred Perlstein   if (sigprocmask(SIG_BLOCK, &block, NULL) < 0) {
18364945c132SAlfred Perlstein     syslog(LOG_WARNING, "siglock failed: %s", strerror(errno));
18374945c132SAlfred Perlstein   }
18384945c132SAlfred Perlstein }
18394945c132SAlfred Perlstein 
18404945c132SAlfred Perlstein void
18414945c132SAlfred Perlstein sigunlock(void)
18424945c132SAlfred Perlstein {
18434945c132SAlfred Perlstein   sigset_t block;
18444945c132SAlfred Perlstein 
18454945c132SAlfred Perlstein   sigemptyset(&block);
18464945c132SAlfred Perlstein   sigaddset(&block, SIGCHLD);
18474945c132SAlfred Perlstein 
18487e589b0bSAlfred Perlstein   if (sigprocmask(SIG_UNBLOCK, &block, NULL) < 0) {
18494945c132SAlfred Perlstein     syslog(LOG_WARNING, "sigunlock failed: %s", strerror(errno));
18504945c132SAlfred Perlstein   }
18514945c132SAlfred Perlstein }
18527e589b0bSAlfred Perlstein 
18537e589b0bSAlfred Perlstein 
1854