afs: Include FID in DoLockWarning
[openafs.git] / src / afs / VNOPS / afs_vnop_flock.c
index 97fb461..fed0bcc 100644 (file)
 
 
 /* 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);
 
 /* int clid;  * non-zero on SGI, OSF, SunOS, Darwin, xBSD ** XXX ptr type */
 
@@ -47,21 +46,11 @@ lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
     proc_t *procp = ttoproc(curthread);
 
     if (slp) {
-# ifdef AFS_SUN53_ENV
        slp->sysid = 0;
        slp->pid = procp->p_pid;
-# else
-       slp->sysid = procp->p_sysid;
-       slp->pid = procp->p_epid;
-# endif
     } else {
-# ifdef AFS_SUN53_ENV
        flock->l_sysid = 0;
        flock->l_pid = procp->p_pid;
-# else
-       flock->l_sysid = procp->p_sysid;
-       flock->l_pid = procp->p_epid;
-# endif
     }
 }
 #elif defined(AFS_SGI_ENV)
@@ -178,11 +167,11 @@ 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
@@ -251,7 +240,7 @@ lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
 */
 /* 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 afs_conn *tc;
@@ -271,6 +260,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 */
 
@@ -317,7 +308,14 @@ 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);
@@ -325,19 +323,20 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
        }
        if (avc->flockCount == 0) {
            if (!AFS_IS_DISCONNECTED) {
+               struct rx_connection *rxconn;
                do {
-                   tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
+                   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(tc->id, (struct AFSFid *)
+                       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->f.fid, areq,
+                        (tc, rxconn, code, &avc->f.fid, areq,
                          AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK, NULL));
            } else {
                /*printf("Network is dooooooowwwwwwwnnnnnnn\n");*/
@@ -383,14 +382,15 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
                }
                if (!code && avc->flockCount == 0) {
                    if (!AFS_IS_DISCONNECTED) {
+                       struct rx_connection *rxconn;
                        do {
-                           tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
+                           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(tc->id,
+                                   RXAFS_ReleaseLock(rxconn,
                                                      (struct AFSFid *)&avc->
                                                      f.fid.Fid, &tsync);
                                RX_AFS_GLOCK();
@@ -398,7 +398,7 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
                            } else
                                code = -1;
                        } while (afs_Analyze
-                                (tc, code, &avc->f.fid, areq,
+                                (tc, rxconn, code, &avc->f.fid, areq,
                                  AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK,
                                  NULL));
                    }
@@ -406,8 +406,14 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
            } 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
@@ -415,15 +421,16 @@ 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);
                    if (!AFS_IS_DISCONNECTED) {
                        do {
-                           tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
+                           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(tc->id, (struct AFSFid *)
+                               code = RXAFS_SetLock(rxconn, (struct AFSFid *)
                                                     &avc->f.fid.Fid, lockType,
                                                     &tsync);
                                RX_AFS_GLOCK();
@@ -431,9 +438,11 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
                            } else
                                code = -1;
                        } while (afs_Analyze
-                                (tc, code, &avc->f.fid, areq,
+                                (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
@@ -497,27 +506,51 @@ 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 void
-DoLockWarning(void)
+DoLockWarning(struct vcache *avc, afs_ucred_t * acred)
 {
-    register afs_int32 now;
+    static afs_uint32 lastWarnTime;
+    static pid_t lastWarnPid;
+
+    afs_uint32 now;
+    pid_t pid = MyPidxx2Pid(MyPidxx);
+    char *procname;
+    const char *message;
+
     now = osi_Time();
 
     AFS_STATCNT(DoLockWarning);
-    /* check if we've already warned someone recently */
-    if (now < lastWarnTime + 120)
+
+    /* check if we've already warned this user recently */
+    if ((now < lastWarnTime + 120) && (lastWarnPid == pid)) {
        return;
+    }
+
+    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_warn
-       ("afs: byte-range locks only enforced for processes on this machine.\n");
+    message = "byte-range locks only enforced for processes on this machine";
 #else
-    afs_warn
-       ("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
+    message = "byte-range lock/unlock ignored; make sure no one else is running this program";
 #endif
+
+    afs_warnuser("afs: %s (pid %d (%s), user %ld, fid %lu.%lu.%lu).\n",
+                 message, pid, procname, (long)afs_cr_uid(acred),
+                 (unsigned long)avc->f.fid.Fid.Volume,
+                 (unsigned long)avc->f.fid.Fid.Vnode,
+                 (unsigned long)avc->f.fid.Fid.Unique);
+
+    afs_osi_Free(procname, 256);
 }
 
 
@@ -545,7 +578,7 @@ int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
     if (code) {
        goto done;
     }
-#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) {
@@ -558,18 +591,30 @@ int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
        code = afs_CheckCode(code, &treq, 2);   /* defeat buggy AIX optimz */
        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
+
+    if ((avc->f.states & CRO)) {
+       /* for RO volumes, don't do anything for locks; the fileserver doesn't
+        * even track them. A write lock should not be possible, though. */
+       if (af->l_type == F_WRLCK) {
+           code = EBADF;
+       } else {
+           code = 0;
+       }
+       goto done;
+    }
+
     /* 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();
+       DoLockWarning(avc, acred);
        code = 0;
        goto done;
     }
@@ -581,11 +626,11 @@ 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)
@@ -622,10 +667,10 @@ done:
  *       PID has the file read locked.
  */
 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);
@@ -821,11 +866,12 @@ HandleGetLock(register struct vcache *avc, register struct AFS_FLOCK *af,
 static int
 GetFlockCount(struct vcache *avc, struct vrequest *areq)
 {
-    register struct afs_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;
@@ -836,19 +882,19 @@ GetFlockCount(struct vcache *avc, struct vrequest *areq)
         return 0;
         
     do {
-       tc = afs_Conn(&avc->f.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->f.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->f.fid, areq, AFS_STATS_FS_RPCIDX_FETCHSTATUS,
+            (tc, rxconn, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_FETCHSTATUS,
              SHARED_LOCK, NULL));
 
     if (temp)