From 06b5006517c77767a246df2b6d66a344a44cbea1 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Thu, 14 Aug 2008 03:36:43 +0000 Subject: [PATCH] windows-free-server-deadlock-20080813 LICENSE MIT avoid a deadloc when freeing servers. cm_serverLock must be released around cm_GCConnections() --- src/WINNT/afsd/cm_server.c | 18 +++++++++++++++++- src/WINNT/afsd/cm_server.h | 2 ++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/WINNT/afsd/cm_server.c b/src/WINNT/afsd/cm_server.c index be2b7fd75..0a442fc81 100644 --- a/src/WINNT/afsd/cm_server.c +++ b/src/WINNT/afsd/cm_server.c @@ -1191,16 +1191,32 @@ void cm_RandomizeServer(cm_serverRef_t** list) void cm_FreeServer(cm_server_t* serverp) { cm_server_vols_t * tsrvp, *nextp; + int delserver = 0; cm_PutServerNoLock(serverp); if (serverp->refCount == 0) { - /* we need to check to ensure that all of the connections + /* + * we need to check to ensure that all of the connections * for this server have a 0 refCount; otherwise, they will * not be garbage collected + * + * must drop the cm_serverLock because cm_GCConnections + * obtains the cm_connLock and that comes first in the + * lock hierarchy. */ + lock_ReleaseWrite(&cm_serverLock); cm_GCConnections(serverp); /* connsp */ + lock_ObtainWrite(&cm_serverLock); + } + + /* + * Once we have the cm_serverLock locked check to make + * sure the refCount is still zero before removing the + * server entirely. + */ + if (serverp->refCount == 0) { if (!(serverp->flags & CM_SERVERFLAG_PREF_SET)) { switch (serverp->type) { case CM_SERVER_VLDB: diff --git a/src/WINNT/afsd/cm_server.h b/src/WINNT/afsd/cm_server.h index 143ff4cb2..93001b668 100644 --- a/src/WINNT/afsd/cm_server.h +++ b/src/WINNT/afsd/cm_server.h @@ -128,6 +128,8 @@ extern cm_server_t * cm_FindServerByIP(afs_uint32 addr, int type); extern void cm_SetLanAdapterChangeDetected(void); +extern void cm_RemoveVolumeFromServer(cm_server_t * serverp, afs_uint32 volID); + /* Protected by cm_syscfgLock (rw) */ extern int cm_noIPAddr; /* number of client network interfaces */ extern int cm_IPAddr[CM_MAXINTERFACE_ADDR]; /* client's IP address in host order */ -- 2.39.5