]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
afs: Fix some afs_conn overcounts
authorAndrew Deason <adeason@sinenomine.net>
Sun, 14 Sep 2014 19:10:11 +0000 (14:10 -0500)
committerStephan Wiesand <stephan.wiesand@desy.de>
Fri, 23 Jan 2015 07:37:58 +0000 (02:37 -0500)
The usual pattern of using afs_Conn looks like this:

  do {
      tc = afs_Conn(...);
      if (tc) {
          code = /* ... */
      } else {
          code = -1;
      }
  } while (afs_Analyze(...));

The afs_Analyze call, amongst other things, puts back the reference to
the connection obtained from afs_Conn. If anything inside the do/while
block exits that block without calling afs_Analyze or afs_PutConn, we
will leak a reference to the conn.

A few places currently do this, by jumping out of the loop with
'goto's. Specifically, in afs_dcache.c and afs_bypasscache.c. These
locations currently leak references to our connection object (and to
the underlying Rx connection object), which can cause problems over
time. Specifically, this can cause a panic when the refcount overflows
and becomes negative, causing a panic message that looks like:

  afs_PutConn: refcount imbalance 0xd34db33f -32768

To avoid this, make sure we afs_PutConn in these cases where we 'goto'
out of the afs_Conn/afs_Analyze loop. Perhaps ideally we should cause
afs_Analyze itself to be called in these situations, but for now just
fix the problem with the least amount of impact possible.

FIXES 131885

Reviewed-on: http://gerrit.openafs.org/11464
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Daria Brashear <shadow@your-file-system.com>
Tested-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
(cherry picked from commit 54c0ee608f4afd2b178c9b60eabfc3564293d996)

Change-Id: Ic02ede4f8177863e8079b4a92c9bad492d6dc97b
Reviewed-on: http://gerrit.openafs.org/11645
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Daria Brashear <shadow@your-file-system.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
src/afs/afs_bypasscache.c
src/afs/afs_dcache.c

index 744feb2b2c8b94de04828fd3b35e78a4ff569f82..8fc60096913f2018365749b56104522191fb750b 100644 (file)
@@ -637,6 +637,7 @@ afs_PrefetchNoCache(struct vcache *avc,
            } else {
                afs_warn("BYPASS: StartRXAFS_FetchData failed: %d\n", code);
                unlock_and_release_pages(auio);
+               afs_PutConn(tc, rxconn, SHARED_LOCK);
                goto done;
            }
            if (code == 0) {
index dc1e039c168c9c838e9060300db9301a4b66e2f2..a156e22ed4599db449057252cf3f8b8d6bb64df5 100644 (file)
@@ -2399,6 +2399,13 @@ afs_GetDCache(struct vcache *avc, afs_size_t abyte,
                        afs_PutDCache(tdc);
                        tdc = 0;
                        ReleaseReadLock(&avc->lock);
+
+                       if (tc) {
+                           /* If we have a connection, we must put it back,
+                            * since afs_Analyze will not be called here. */
+                           afs_PutConn(tc, rxconn, SHARED_LOCK);
+                       }
+
                        slowPass = 1;
                        goto RetryGetDCache;
                    }