linux-byte-range-locks-sensibility-20090526
[openafs.git] / src / afs / VNOPS / afs_vnop_flock.c
index 5e4b0e6..0e6e6d8 100644 (file)
@@ -219,13 +219,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,
            pid_t clid, int onlymine)
 {
-    struct conn *tc;
+    struct afs_conn *tc;
     struct SimpleLocks *slp, *tlp, **slpp;
     afs_int32 code;
     struct AFSVolSync tsync;
@@ -295,20 +298,25 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
            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) {
+               do {
+                   tc = afs_Conn(&avc->f.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->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, 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 */
@@ -348,24 +356,26 @@ 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) {
+                       do {
+                           tc = afs_Conn(&avc->f.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->
+                                                     f.fid.Fid, &tsync);
+                               RX_AFS_GLOCK();
+                              XSTATS_END_TIME;
+                           } else
+                               code = -1;
+                       } while (afs_Analyze
+                                (tc, 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)) {
@@ -381,22 +391,28 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
                if (avc->flockCount == 0) {
                    /* 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);
+                           if (tc) {
+                               XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
+                               RX_AFS_GUNLOCK();
+                               code = RXAFS_SetLock(tc->id, (struct AFSFid *)
+                                                    &avc->f.fid.Fid, lockType,
+                                                    &tsync);
+                               RX_AFS_GLOCK();
+                               XSTATS_END_TIME;
+                           } else
+                               code = -1;
+                       } while (afs_Analyze
+                                (tc, code, &avc->f.fid, areq,
+                                 AFS_STATS_FS_RPCIDX_SETLOCK, SHARED_LOCK,
+                                 NULL));
+                   } 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 */
            }
@@ -469,8 +485,13 @@ DoLockWarning(void)
 
     /* otherwise, it is time to nag the user */
     lastWarnTime = now;
+#ifdef AFS_LINUX26_ENV
+    afs_warn
+       ("afs: byte-range locks only enforced for processes on this machine.\n");
+#else
     afs_warn
        ("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
+#endif
 }
 
 
@@ -497,15 +518,17 @@ int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
     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;
+       goto done;
     }
 #ifdef AFS_OSF_ENV
     if (flag & VNOFLCK) {
-       afs_PutFakeStat(&fakestate);
-       return 0;
+       code = 0;
+       goto done;
     }
     if (flag & CLNFLCK) {
        acmd = LOCK_UN;
@@ -521,15 +544,14 @@ int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
     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)
               || (acmd == F_RSETLK) || (acmd == F_RSETLKW)) {
@@ -553,14 +575,14 @@ int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
 #endif
     /* Java VMs ask for l_len=(long)-1 regardless of OS/CPU; bottom 32 bits
      * sometimes get masked off by OS */
-    if ((sizeof(af->l_len) == 8) && (af->l_len == 0x7ffffffffffffffe))
+    if ((sizeof(af->l_len) == 8) && (af->l_len == 0x7ffffffffffffffeLL))
        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;
+       code = 0;
+       goto done;
     }
     /* otherwise we can turn this into a whole-file flock */
     if (af->l_type == F_RDLCK)
@@ -589,11 +611,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;
 }
 
 
@@ -809,7 +833,7 @@ HandleGetLock(register struct vcache *avc, register struct AFS_FLOCK *af,
 static int
 GetFlockCount(struct vcache *avc, struct vrequest *areq)
 {
-    register struct conn *tc;
+    register struct afs_conn *tc;
     register afs_int32 code;
     struct AFSFetchStatus OutStatus;
     struct AFSCallBack CallBack;
@@ -819,20 +843,24 @@ GetFlockCount(struct vcache *avc, struct vrequest *areq)
     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);
        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(tc->id, (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, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_FETCHSTATUS,
              SHARED_LOCK, NULL));
 
     if (temp)
@@ -889,6 +917,9 @@ afs_xflock(void)
        afs_PutFakeStat(&fakestate);
        return flockDone;
     }
+
+    AFS_DISCON_LOCK();
+    
     /* 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 */
@@ -897,6 +928,7 @@ afs_xflock(void)
            /* This is an AFS vnode, so do the work */
            code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
            if (code) {
+               AFS_DISCON_UNLOCK();
                afs_PutFakeStat(&fakestate);
                return code;
            }
@@ -950,11 +982,13 @@ afs_xflock(void)
 #else
     FP_UNREF(fd);
 #endif
+    AFS_DISCON_UNLOCK();
     afs_PutFakeStat(&fakestate);
     return code;
 #else /* AFS_OSF_ENV */
     if (!flockDone)
        flock();
+    AFS_DISCON_UNLOCK();
     afs_PutFakeStat(&fakestate);
     return;
 #endif