]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
viced: Keep H_LOCK while locking host in h_Alloc_r
authorAndrew Deason <adeason@sinenomine.net>
Tue, 20 Dec 2011 22:44:42 +0000 (17:44 -0500)
committerDerrick Brashear <shadow@dementix.org>
Thu, 23 Feb 2012 01:45:54 +0000 (17:45 -0800)
Currently in h_Alloc_r, we h_Lock_r the host, so we have it locked on
return. However, h_Lock_r drops the host glock, which is bad in this
situation since we have already added the host to the global hash
table, so other threads may see it. This can mean that by the time
h_Alloc_r returns, the returned host may have HOSTDELETED set, and/or
the addresses associated with the host may be completely different.

h_Alloc_r's caller, h_GetHost_r, seems to assume that the host is
still associated with the address of the passed-in connection. When
this is not true, this can result in the host structure getting into a
strange state, such as the primary addr/port may not be hashed. The
host may also have HOSTDELETED set, in which case we're not supposed
to be dealing with it at all.

To avoid these problems, lock host->lock directly in h_Alloc_r,
without going through h_Lock_r and dropping H_LOCK. Also do it as one
of the first things we do to initialize the host, just to make sure
that if anybody else happens to see the host, it is locked by us when
they do.

Reviewed-on: http://gerrit.openafs.org/6389
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
(cherry picked from commit d6f977830c164ee079c68101595c28ff1847f88f)

Change-Id: Ib0916f3a92c4a34555ee3fa2880dec10041bf047
Reviewed-on: http://gerrit.openafs.org/6754
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
src/viced/host.c

index 8f6dd48740026f4d7a69b27ff1635256f0a0b5a9..51c49b0fd1d7f6902de2942829d6abbf36f5dbe7 100644 (file)
@@ -698,6 +698,12 @@ h_Alloc_r(struct rx_connection *r_con)
     if (!host)
        return NULL;
 
+    h_Hold_r(host);
+    /* acquire the host lock withot dropping H_LOCK. we can do this here
+     * because we know we will not block; we just created this host and
+     * nobody else knows about it. */
+    ObtainWriteLock(&host->lock);
+
     host->host = rxr_HostOf(r_con);
     host->port = rxr_PortOf(r_con);
 
@@ -729,8 +735,6 @@ h_Alloc_r(struct rx_connection *r_con)
     h_gethostcps(host);                /* do this under host hold/lock */
 #endif
     host->FirstClient = NULL;
-    h_Hold_r(host);
-    h_Lock_r(host);
     h_InsertList_r(host);      /* update global host List */
 #if FS_STATS_DETAILED
     /*