afs: Use common cleanup code for lockctl EINVAL
[openafs.git] / src / afs / VNOPS / afs_vnop_flock.c
index 6d1ded9..37e58ed 100644 (file)
@@ -15,8 +15,6 @@
 #include <afsconfig.h>
 #include "afs/param.h"
 
-RCSID
-    ("$Header$");
 
 #include "afs/sysincludes.h"   /* Standard vendor system headers */
 #include "afsincludes.h"       /* Afs-based standard headers */
@@ -26,116 +24,136 @@ RCSID
 #include "afs/afs_osidnlc.h"
 #include "afs/unified_afs.h"
 
+
+
+
+
 /* Static prototypes */
-static int HandleGetLock(register struct vcache *avc,
-                        register struct AFS_FLOCK *af,
-                        register struct vrequest *areq, int clid);
+static int HandleGetLock(struct vcache *avc,
+                        struct AFS_FLOCK *af,
+                        struct vrequest *areq, int clid);
 static int GetFlockCount(struct vcache *avc, struct vrequest *areq);
 static int lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
-                     register struct SimpleLocks *alp, int onlymine,
+                     struct SimpleLocks *alp, int onlymine,
                      int clid);
-static void DoLockWarning(void);
+static void DoLockWarning(afs_ucred_t * acred);
 
 /* int clid;  * non-zero on SGI, OSF, SunOS, Darwin, xBSD ** XXX ptr type */
+
+#if defined(AFS_SUN5_ENV)
 void
 lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
 {
-#if    defined(AFS_SUN5_ENV)
-    register proc_t *procp = ttoproc(curthread);
-#else
-#if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
-#ifdef AFS_SGI_ENV
-    struct proc *procp = OSI_GET_CURRENT_PROCP();
-#else
-    struct proc *procp = u.u_procp;
-#endif /* AFS_SGI_ENV */
-#endif
-#endif
-#if defined(AFS_SGI65_ENV)
+    proc_t *procp = ttoproc(curthread);
+
+    if (slp) {
+       slp->sysid = 0;
+       slp->pid = procp->p_pid;
+    } else {
+       flock->l_sysid = 0;
+       flock->l_pid = procp->p_pid;
+    }
+}
+#elif defined(AFS_SGI_ENV)
+void
+lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
+{
+# if defined(AFS_SGI65_ENV)
     flid_t flid;
     get_current_flid(&flid);
-#endif
+# else
+    afs_proc_t *procp = OSI_GET_CURRENT_PROCP();
+# endif
 
     if (slp) {
-#ifdef AFS_AIX32_ENV
-#ifdef AFS_AIX41_ENV
+# ifdef AFS_SGI65_ENV
+       slp->sysid = flid.fl_sysid;
+# else
+       slp->sysid = OSI_GET_CURRENT_SYSID();
+# endif
+       slp->pid = clid;
+    } else {
+# ifdef AFS_SGI65_ENV
+       flock->l_sysid = flid.fl_sysid;
+# else
+       flock->l_sysid = OSI_GET_CURRENT_SYSID();
+# endif
+       flock->l_pid = clid;
+    }
+}
+#elif defined(AFS_AIX_ENV)
+void
+lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
+{
+# if !defined(AFS_AIX32_ENV)
+    afs_proc_t *procp = u.u_procp;
+# endif
+
+    if (slp) {
+# if defined(AFS_AIX41_ENV)
        slp->sysid = 0;
        slp->pid = getpid();
-#else
+# elif defined(AFS_AIX32_ENV)
        slp->sysid = u.u_sysid;
        slp->pid = u.u_epid;
-#endif
-#else
-#if    defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
-#ifdef AFS_SUN53_ENV
-       slp->sysid = 0;
-       slp->pid = procp->p_pid;
-#else
+# else
        slp->sysid = procp->p_sysid;
-       slp->pid = procp->p_epid;
-#endif
-#else
-#if defined(AFS_SGI_ENV)
-#ifdef AFS_SGI65_ENV
-       slp->sysid = flid.fl_sysid;
-#else
-       slp->sysid = OSI_GET_CURRENT_SYSID();
-#endif
-       slp->pid = clid;
-#else
-#if    defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-       slp->pid = clid;
-#else
-#if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
-       slp->pid = getpid();
-#else
-       slp->pid = u.u_procp->p_pid;
-#endif
-#endif
-#endif /* AFS_AIX_ENV */
-#endif /* AFS_AIX32_ENV */
-#endif
+       slp->pid = prcop->p_epid;
+# endif
     } else {
-#if    defined(AFS_AIX32_ENV)
-#ifdef AFS_AIX41_ENV
+# if defined(AFS_AIX41_ENV)
        flock->l_sysid = 0;
        flock->l_pid = getpid();
-#else
+# elif defined(AFS_AIX32_ENV)
        flock->l_sysid = u.u_sysid;
        flock->l_pid = u.u_epid;
-#endif
-#else
-#if    defined(AFS_AIX_ENV)  || defined(AFS_SUN5_ENV)
-#ifdef AFS_SUN53_ENV
-       flock->l_sysid = 0;
-       flock->l_pid = procp->p_pid;
-#else
+# else
        flock->l_sysid = procp->p_sysid;
        flock->l_pid = procp->p_epid;
-#endif
-#else
-#if defined(AFS_SGI_ENV)
-#ifdef AFS_SGI65_ENV
-       flock->l_sysid = flid.fl_sysid;
-#else
-       flock->l_sysid = OSI_GET_CURRENT_SYSID();
-#endif
-       flock->l_pid = clid;
-#else
-#if    defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+# endif
+    }
+}
+#elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+void
+lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
+{
+    if (slp) {
+       slp->pid = clid;
+    } else {
        flock->l_pid = clid;
-#else
-#if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
+    }
+}
+#elif defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
+void
+lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
+{
+    if (slp) {
+       slp->pid = getpid();
+    } else {
        flock->l_pid = getpid();
+    }
+}
+#elif defined(UKERNEL)
+void
+lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
+{
+    if (slp) {
+       slp->pid = get_user_struct()->u_procp->p_pid;
+    } else {
+       flock->l_pid = get_user_struct()->u_procp->p_pid;
+    }
+}
 #else
+void
+lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
+{
+    if (slp) {
+       slp->pid = u.u_procp->p_pid;
+    } else {
        flock->l_pid = u.u_procp->p_pid;
-#endif
-#endif
-#endif
-#endif /* AFS_AIX_ENV */
-#endif /* AFS_AIX32_ENV */
     }
 }
+#endif
 
 /* return 1 (true) if specified flock does not match alp (if 
  * specified), or any of the slp structs (if alp == 0) 
@@ -150,17 +168,19 @@ lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
 
 static int
 lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
-          register struct SimpleLocks *alp, int onlymine, int clid)
+          struct SimpleLocks *alp, int onlymine, int clid)
 {
-    register struct SimpleLocks *slp;
+    struct SimpleLocks *slp;
 #if    defined(AFS_SUN5_ENV)
-    register proc_t *procp = ttoproc(curthread);
+    proc_t *procp = ttoproc(curthread);
 #else
 #if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
 #ifdef AFS_SGI64_ENV
-    struct proc *procp = curprocp;
-#else /* AFS_SGI64_ENV */
-    struct proc *procp = u.u_procp;
+    afs_proc_t *procp = curprocp;
+#elif defined(UKERNEL)
+    afs_proc_t *procp = get_user_struct()->u_procp;
+#else
+    afs_proc_t *procp = u.u_procp;
 #endif /* AFS_SGI64_ENV */
 #endif
 #endif
@@ -215,13 +235,16 @@ lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
     94.04.13 add "force" parameter.  If a child explicitly unlocks a
     file, I guess we'll permit it.  however, we don't want simple,
     innocent closes by children to unlock files in the parent process.
+
+    If called when disconnected support is unabled, the discon_lock must
+    be held
 */
 /* clid - nonzero on sgi sunos osf1 only */
 int
-HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
+HandleFlock(struct vcache *avc, int acom, struct vrequest *areq,
            pid_t clid, int onlymine)
 {
-    struct conn *tc;
+    struct afs_conn *tc;
     struct SimpleLocks *slp, *tlp, **slpp;
     afs_int32 code;
     struct AFSVolSync tsync;
@@ -238,6 +261,8 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
 #endif
     ObtainWriteLock(&avc->lock, 118);
     if (acom & LOCK_UN) {
+       int stored_segments = 0;
+     retry_unlock:
 
 /* defect 3083 */
 
@@ -284,27 +309,40 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
                }
            }
        } else if (avc->flockCount == -1) {
-           afs_StoreAllSegments(avc, areq, AFS_ASYNC); /* fsync file early */
+           if (!stored_segments) {
+               afs_StoreAllSegments(avc, areq, AFS_SYNC | AFS_VMSYNC); /* fsync file early */
+               /* afs_StoreAllSegments can drop and reacquire the write lock
+                * on avc and GLOCK, so the flocks may be completely different
+                * now. Go back and perform all checks again. */
+                stored_segments = 1;
+                goto retry_unlock;
+           }
            avc->flockCount = 0;
            /* And remove the (only) exclusive lock entry from the list... */
            osi_FreeSmallSpace(avc->slocks);
            avc->slocks = 0;
        }
        if (avc->flockCount == 0) {
-           do {
-               tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
-               if (tc) {
-                   XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
-                   RX_AFS_GUNLOCK();
-                   code = RXAFS_ReleaseLock(tc->id, (struct AFSFid *)
-                                            &avc->fid.Fid, &tsync);
-                   RX_AFS_GLOCK();
-                   XSTATS_END_TIME;
-               } else
+           if (!AFS_IS_DISCONNECTED) {
+               struct rx_connection *rxconn;
+               do {
+                   tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK, &rxconn);
+                   if (tc) {
+                       XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
+                       RX_AFS_GUNLOCK();
+                       code = RXAFS_ReleaseLock(rxconn, (struct AFSFid *)
+                                                &avc->f.fid.Fid, &tsync);
+                       RX_AFS_GLOCK();
+                       XSTATS_END_TIME;
+                   } else
                    code = -1;
-           } while (afs_Analyze
-                    (tc, code, &avc->fid, areq,
-                     AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK, NULL));
+               } while (afs_Analyze
+                        (tc, rxconn, code, &avc->f.fid, areq,
+                         AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK, NULL));
+           } else {
+               /*printf("Network is dooooooowwwwwwwnnnnnnn\n");*/
+              code = ENETDOWN;
+           }
        }
     } else {
        while (1) {             /* set a new lock */
@@ -344,30 +382,39 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
                    }
                }
                if (!code && avc->flockCount == 0) {
-                   do {
-                       tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
-                       if (tc) {
-                           XSTATS_START_TIME
-                               (AFS_STATS_FS_RPCIDX_RELEASELOCK);
-                           RX_AFS_GUNLOCK();
-                           code =
-                               RXAFS_ReleaseLock(tc->id,
-                                                 (struct AFSFid *)&avc->fid.
-                                                 Fid, &tsync);
-                           RX_AFS_GLOCK();
-                           XSTATS_END_TIME;
-                       } else
-                           code = -1;
-                   } while (afs_Analyze
-                            (tc, code, &avc->fid, areq,
-                             AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK,
-                             NULL));
+                   if (!AFS_IS_DISCONNECTED) {
+                       struct rx_connection *rxconn;
+                       do {
+                           tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK, &rxconn);
+                           if (tc) {
+                               XSTATS_START_TIME
+                                   (AFS_STATS_FS_RPCIDX_RELEASELOCK);
+                               RX_AFS_GUNLOCK();
+                               code =
+                                   RXAFS_ReleaseLock(rxconn,
+                                                     (struct AFSFid *)&avc->
+                                                     f.fid.Fid, &tsync);
+                               RX_AFS_GLOCK();
+                              XSTATS_END_TIME;
+                           } else
+                               code = -1;
+                       } while (afs_Analyze
+                                (tc, rxconn, code, &avc->f.fid, areq,
+                                 AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK,
+                                 NULL));
+                   }
                }
            } else if (avc->flockCount == -1 && (acom & LOCK_EX)) {
                if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
                    code = EWOULDBLOCK;
-               } else
+               } else {
                    code = 0;
+                   /* We've just re-grabbed an exclusive lock, so we don't
+                    * need to contact the fileserver, and we don't need to
+                    * add the lock to avc->slocks (since we already have a
+                    * lock there). So, we are done. */
+                   break;
+               }
            }
            if (code == 0) {
                /* compatible here, decide if needs to go to file server.  If
@@ -375,24 +422,33 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
                 * we've already checked for compatibility), we shouldn't send
                 * the call through to the server again */
                if (avc->flockCount == 0) {
+                   struct rx_connection *rxconn;
                    /* we're the first on our block, send the call through */
                    lockType = ((acom & LOCK_EX) ? LockWrite : LockRead);
-                   do {
-                       tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
-                       if (tc) {
-                           XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
-                           RX_AFS_GUNLOCK();
-                           code = RXAFS_SetLock(tc->id, (struct AFSFid *)
-                                                &avc->fid.Fid, lockType,
-                                                &tsync);
-                           RX_AFS_GLOCK();
-                           XSTATS_END_TIME;
-                       } else
-                           code = -1;
-                   } while (afs_Analyze
-                            (tc, code, &avc->fid, areq,
-                             AFS_STATS_FS_RPCIDX_SETLOCK, SHARED_LOCK,
-                             NULL));
+                   if (!AFS_IS_DISCONNECTED) {
+                       do {
+                           tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK, &rxconn);
+                           if (tc) {
+                               XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
+                               RX_AFS_GUNLOCK();
+                               code = RXAFS_SetLock(rxconn, (struct AFSFid *)
+                                                    &avc->f.fid.Fid, lockType,
+                                                    &tsync);
+                               RX_AFS_GLOCK();
+                               XSTATS_END_TIME;
+                           } else
+                               code = -1;
+                       } while (afs_Analyze
+                                (tc, rxconn, code, &avc->f.fid, areq,
+                                 AFS_STATS_FS_RPCIDX_SETLOCK, SHARED_LOCK,
+                                 NULL));
+                       if ((lockType == LockWrite) && (code == VREADONLY))
+                           code = EBADF; /* per POSIX; VREADONLY == EROFS */
+                   } else
+                       /* XXX - Should probably try and log this when we're
+                        * XXX - running with logging enabled. But it's horrid
+                        */
+                       code = 0; /* pretend we worked - ick!!! */
                } else
                    code = 0;   /* otherwise, pretend things worked */
            }
@@ -452,107 +508,95 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
 
 /* warn a user that a lock has been ignored */
 afs_int32 lastWarnTime = 0;    /* this is used elsewhere */
+static afs_int32 lastWarnPid = 0;
 static void
-DoLockWarning(void)
+DoLockWarning(afs_ucred_t * acred)
 {
-    register afs_int32 now;
+    afs_int32 now;
+    pid_t pid = MyPidxx2Pid(MyPidxx);
+    char *procname;
+
     now = osi_Time();
 
     AFS_STATCNT(DoLockWarning);
-    /* check if we've already warned someone recently */
-    if (now < lastWarnTime + 120)
-       return;
-
-    /* otherwise, it is time to nag the user */
-    lastWarnTime = now;
-    afs_warn
-       ("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
+    /* check if we've already warned this user recently */
+    if (!((now < lastWarnTime + 120) && (lastWarnPid == pid))) {
+       procname = afs_osi_Alloc(256);
+
+       if (!procname)
+           return;
+
+       /* Copies process name to allocated procname, see osi_machdeps for details of macro */
+       osi_procname(procname, 256);
+       procname[255] = '\0';
+
+       /* otherwise, it is time to nag the user */
+       lastWarnTime = now;
+       lastWarnPid = pid;
+#ifdef AFS_LINUX26_ENV
+       afs_warnuser
+           ("afs: byte-range locks only enforced for processes on this machine (pid %d (%s), user %ld).\n", pid, procname, (long)afs_cr_uid(acred));
+#else
+       afs_warnuser
+           ("afs: byte-range lock/unlock ignored; make sure no one else is running this program (pid %d (%s), user %ld).\n", pid, procname, afs_cr_uid(acred));
+#endif
+       afs_osi_Free(procname, 256);
+    }
+    return;
 }
 
 
-#ifdef AFS_OSF_ENV
-int afs_lockctl(struct vcache * avc, struct eflock * af, int flag,
-               struct AFS_UCRED * acred, pid_t clid, off_t offset)
-#elif defined(AFS_SGI_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#if defined(AFS_SGI_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
 int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
-               struct AFS_UCRED * acred, pid_t clid)
+               afs_ucred_t * acred, pid_t clid)
 #else
 u_int clid = 0;
 int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
-               struct AFS_UCRED * acred)
+               afs_ucred_t * acred)
 #endif
 {
     struct vrequest treq;
     afs_int32 code;
-#ifdef AFS_OSF_ENV
-    int acmd = 0;
-#endif
     struct afs_fakestat_state fakestate;
 
     AFS_STATCNT(afs_lockctl);
     if ((code = afs_InitReq(&treq, acred)))
        return code;
     afs_InitFakeStat(&fakestate);
+
+    AFS_DISCON_LOCK();
+
     code = afs_EvalFakeStat(&avc, &fakestate, &treq);
     if (code) {
-       afs_PutFakeStat(&fakestate);
-       return code;
-    }
-#ifdef AFS_OSF_ENV
-    if (flag & VNOFLCK) {
-       afs_PutFakeStat(&fakestate);
-       return 0;
-    }
-    if (flag & CLNFLCK) {
-       acmd = LOCK_UN;
-    } else if ((flag & GETFLCK) || (flag & RGETFLCK)) {
-       acmd = F_GETLK;
-    } else if ((flag & SETFLCK) || (flag & RSETFLCK)) {
-       acmd = F_SETLK;
+       goto done;
     }
-#endif
-#if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
+#if defined(AFS_SGI_ENV)
     if ((acmd == F_GETLK) || (acmd == F_RGETLK)) {
 #else
     if (acmd == F_GETLK) {
 #endif
        if (af->l_type == F_UNLCK) {
-           afs_PutFakeStat(&fakestate);
-           return 0;
+           code = 0;
+           goto done;
        }
-#ifndef        AFS_OSF_ENV             /* getlock is a no-op for osf (for now) */
        code = HandleGetLock(avc, af, &treq, clid);
-#endif
        code = afs_CheckCode(code, &treq, 2);   /* defeat buggy AIX optimz */
-       afs_PutFakeStat(&fakestate);
-       return code;
+       goto done;
     } else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
-#if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
+#if defined(AFS_SGI_ENV)
               || (acmd == F_RSETLK) || (acmd == F_RSETLKW)) {
 #else
        ) {
 #endif
-    /* this next check is safer when left out, but more applications work
-     * with it in.  However, they fail in race conditions.  The question is
-     * what to do for people who don't have source to their application;
-     * this way at least, they can get work done */
-#ifdef AFS_LINUX24_ENV
-    if (af->l_len == OFFSET_MAX)
-       af->l_len = 0;          /* since some systems indicate it as EOF */
-#else
-    if (af->l_len == 0x7fffffff)
-       af->l_len = 0;          /* since some systems indicate it as EOF */
-#ifdef AFS_LINUX_64BIT_KERNEL
-    if (af->l_len == LONG_MAX)
-       af->l_len = 0;          /* since some systems indicate it as EOF */
-#endif
-#endif
+    /* Java VMs ask for l_len=(long)-1 regardless of OS/CPU */
+    if ((sizeof(af->l_len) == 8) && (af->l_len == 0x7fffffffffffffffLL))
+       af->l_len = 0;
     /* next line makes byte range locks always succeed,
      * even when they should block */
     if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
-       DoLockWarning();
-       afs_PutFakeStat(&fakestate);
-       return 0;
+       DoLockWarning(acred);
+       code = 0;
+       goto done;
     }
     /* otherwise we can turn this into a whole-file flock */
     if (af->l_type == F_RDLCK)
@@ -562,16 +606,16 @@ int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
     else if (af->l_type == F_UNLCK)
        code = LOCK_UN;
     else {
-       afs_PutFakeStat(&fakestate);
-       return EINVAL;          /* unknown lock type */
+       code = EINVAL;          /* unknown lock type */
+       goto done;
     }
     if (((acmd == F_SETLK)
-#if    (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
+#if    defined(AFS_SGI_ENV)
         || (acmd == F_RSETLK)
 #endif
        ) && code != LOCK_UN)
        code |= LOCK_NB;        /* non-blocking, s.v.p. */
-#if    defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
+#if defined(AFS_DARWIN_ENV)
     code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
 #elif defined(AFS_SGI_ENV)
     AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
@@ -581,11 +625,13 @@ int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
     code = HandleFlock(avc, code, &treq, 0, 0 /*!onlymine */ );
 #endif
     code = afs_CheckCode(code, &treq, 3);      /* defeat AIX -O bug */
-    afs_PutFakeStat(&fakestate);
-    return code;
+    goto done;
     }
+    code = EINVAL;
+done:
     afs_PutFakeStat(&fakestate);
-    return EINVAL;
+    AFS_DISCON_UNLOCK();
+    return code;
 }
 
 
@@ -600,12 +646,11 @@ int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
  *    2. Asking for write lock, and only the current
  *       PID has the file read locked.
  */
-#ifndef        AFS_OSF_ENV             /* getlock is a no-op for osf (for now) */
 static int
-HandleGetLock(register struct vcache *avc, register struct AFS_FLOCK *af,
-             register struct vrequest *areq, int clid)
+HandleGetLock(struct vcache *avc, struct AFS_FLOCK *af,
+             struct vrequest *areq, int clid)
 {
-    register afs_int32 code;
+    afs_int32 code;
     struct AFS_FLOCK flock;
 
     lockIdSet(&flock, NULL, clid);
@@ -801,30 +846,35 @@ HandleGetLock(register struct vcache *avc, register struct AFS_FLOCK *af,
 static int
 GetFlockCount(struct vcache *avc, struct vrequest *areq)
 {
-    register struct conn *tc;
-    register afs_int32 code;
+    struct afs_conn *tc;
+    afs_int32 code;
     struct AFSFetchStatus OutStatus;
     struct AFSCallBack CallBack;
     struct AFSVolSync tsync;
+    struct rx_connection *rxconn;
     int temp;
     XSTATS_DECLS;
     temp = areq->flags & O_NONBLOCK;
     areq->flags |= O_NONBLOCK;
 
+    /* If we're disconnected, lie and say that we've got no locks. Ick */
+    if (AFS_IS_DISCONNECTED)
+        return 0;
+        
     do {
-       tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
+       tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK, &rxconn);
        if (tc) {
            XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
            RX_AFS_GUNLOCK();
            code =
-               RXAFS_FetchStatus(tc->id, (struct AFSFid *)&avc->fid.Fid,
+               RXAFS_FetchStatus(rxconn, (struct AFSFid *)&avc->f.fid.Fid,
                                  &OutStatus, &CallBack, &tsync);
            RX_AFS_GLOCK();
            XSTATS_END_TIME;
        } else
            code = -1;
     } while (afs_Analyze
-            (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_FETCHSTATUS,
+            (tc, rxconn, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_FETCHSTATUS,
              SHARED_LOCK, NULL));
 
     if (temp)
@@ -836,119 +886,4 @@ GetFlockCount(struct vcache *avc, struct vrequest *areq)
        return ((int)OutStatus.lockCount);
     }
 }
-#endif
-
-
-#if    !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_SGI_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
-/* Flock not support on System V systems */
-#ifdef AFS_OSF_ENV
-extern struct fileops afs_fileops;
-
-int
-afs_xflock(struct proc *p, void *args, int *retval)
-#else /* AFS_OSF_ENV */
-int
-afs_xflock(void)
-#endif
-{
-    int code = 0;
-    struct a {
-       int fd;
-       int com;
-    } *uap;
-    struct file *fd;
-    struct vrequest treq;
-    struct vcache *tvc;
-    int flockDone;
-    struct afs_fakestat_state fakestate;
-
-    afs_InitFakeStat(&fakestate);
-    AFS_STATCNT(afs_xflock);
-    flockDone = 0;
-#ifdef AFS_OSF_ENV
-    uap = (struct a *)args;
-    getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state);
-#else /* AFS_OSF_ENV */
-    uap = (struct a *)u.u_ap;
-    fd = getf(uap->fd);
-#endif
-    if (!fd) {
-       afs_PutFakeStat(&fakestate);
-       return;
-    }
 
-    if (flockDone = afs_InitReq(&treq, u.u_cred)) {
-       afs_PutFakeStat(&fakestate);
-       return flockDone;
-    }
-    /* first determine whether this is any sort of vnode */
-    if (fd->f_type == DTYPE_VNODE) {
-       /* good, this is a vnode; next see if it is an AFS vnode */
-       tvc = VTOAFS(fd->f_data);       /* valid, given a vnode */
-       if (IsAfsVnode(AFSTOV(tvc))) {
-           /* This is an AFS vnode, so do the work */
-           code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
-           if (code) {
-               afs_PutFakeStat(&fakestate);
-               return code;
-           }
-           if ((fd->f_flag & (FEXLOCK | FSHLOCK)) && !(uap->com & LOCK_UN)) {
-               /* First, if fd already has lock, release it for relock path */
-#if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
-               HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid,
-                           0 /*!onlymine */ );
-#else
-               HandleFlock(tvc, LOCK_UN, &treq, 0, 0 /*!onlymine */ );
-#endif
-               fd->f_flag &= ~(FEXLOCK | FSHLOCK);
-           }
-           /* now try the requested operation */
-
-#if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
-           code =
-               HandleFlock(tvc, uap->com, &treq, u.u_procp->p_pid,
-                           0 /*!onlymine */ );
-#else
-           code = HandleFlock(tvc, uap->com, &treq, 0, 0 /*!onlymine */ );
-#endif
-#ifndef AFS_OSF_ENV
-           u.u_error = code;
-#endif
-
-           if (uap->com & LOCK_UN) {
-               /* gave up lock */
-               fd->f_flag &= ~(FEXLOCK | FSHLOCK);
-           } else {
-#ifdef AFS_OSF_ENV
-               if (!code) {
-#else /* AFS_OSF_ENV */
-               if (!u.u_error) {
-#endif
-                   if (uap->com & LOCK_SH)
-                       fd->f_flag |= FSHLOCK;
-                   else if (uap->com & LOCK_EX)
-                       fd->f_flag |= FEXLOCK;
-               }
-           }
-           flockDone = 1;
-           fd->f_ops = &afs_fileops;
-       }
-    }
-#ifdef AFS_OSF_ENV
-    if (!flockDone)
-       code = flock(p, args, retval);
-#ifdef AFS_OSF30_ENV
-    FP_UNREF_ALWAYS(fd);
-#else
-    FP_UNREF(fd);
-#endif
-    afs_PutFakeStat(&fakestate);
-    return code;
-#else /* AFS_OSF_ENV */
-    if (!flockDone)
-       flock();
-    afs_PutFakeStat(&fakestate);
-    return;
-#endif
-}
-#endif /* !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(UKERNEL)  && !defined(AFS_LINUX20_ENV) */