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