afs: Avoid memory leak on recursive write flock
[openafs.git] / src / afs / VNOPS / afs_vnop_flock.c
index 97fb461..931a72c 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);
+static void DoLockWarning(afs_ucred_t * acred);
 
 /* int clid;  * non-zero on SGI, OSF, SunOS, Darwin, xBSD ** XXX ptr type */
 
@@ -178,11 +178,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 +251,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;
@@ -317,7 +317,7 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
                }
            }
        } else if (avc->flockCount == -1) {
-           afs_StoreAllSegments(avc, areq, AFS_ASYNC); /* fsync file early */
+           afs_StoreAllSegments(avc, areq, AFS_SYNC | AFS_VMSYNC);     /* fsync file early */
            avc->flockCount = 0;
            /* And remove the (only) exclusive lock entry from the list... */
            osi_FreeSmallSpace(avc->slocks);
@@ -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
@@ -434,6 +440,8 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
                                 (tc, 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
@@ -498,26 +506,41 @@ 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;
+    /* check if we've already warned this user recently */
+    if (!((now < lastWarnTime + 120) && (lastWarnPid == pid))) {
+       procname = afs_osi_Alloc(256);
 
-    /* otherwise, it is time to nag the user */
-    lastWarnTime = now;
+       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");
+       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_warn
-       ("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
+       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;
 }
 
 
@@ -569,7 +592,7 @@ int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
     /* 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(acred);
        code = 0;
        goto done;
     }
@@ -622,10 +645,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,8 +844,8 @@ 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;