From: Jeffrey Altman Date: Fri, 30 Jul 2004 21:02:57 +0000 (+0000) Subject: server-list-and-volume-updates-20040730 X-Git-Tag: BP-openafs-stable-1_4_x~49 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=6eaeb762448b0887cd3319bbd4cdb242838bc3b2;p=packages%2Fo%2Fopenafs.git server-list-and-volume-updates-20040730 As discovered previously, the cm_serverRef_t objects were not reference counted. This resulted in the objects being freed while they were still in use. This patch adds reference counting to the cm_serverRef_t objects which are locked using the cm_serverLock. Once the reference counting was fixed it became immediately obvious that cm_VolumeUpdates could not succeed in altering the state of a server list from ALLOFFLINE to NOTBUSY. cm_VolumeUpdate calls cm_Analyze without a fid_t object which was required to obtain the server list for the affected volume. Of course, cm_VolumeUpdate has a pointer to the volume so cm_Analyze was updated to take an optional pointer to a cm_serverRef_t which avoids the need for the fid_t object. --- diff --git a/src/WINNT/afsd/cm_callback.c b/src/WINNT/afsd/cm_callback.c index 48be6ff6a..b9bcaef4c 100644 --- a/src/WINNT/afsd/cm_callback.c +++ b/src/WINNT/afsd/cm_callback.c @@ -814,7 +814,7 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp, code = RXAFS_FetchStatus(connp->callp, &tfid, &afsStatus, &callback, &volSync); - } while (cm_Analyze(connp, userp, reqp, &sfid, &volSync, + } while (cm_Analyze(connp, userp, reqp, &sfid, &volSync, NULL, &cbr, code)); code = cm_MapRPCError(code, reqp); osi_Log0(afsd_logp, "CALL FetchStatus DONE"); diff --git a/src/WINNT/afsd/cm_cell.c b/src/WINNT/afsd/cm_cell.c index 8314eef4b..bc7090f65 100644 --- a/src/WINNT/afsd/cm_cell.c +++ b/src/WINNT/afsd/cm_cell.c @@ -45,12 +45,15 @@ long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep) tsp->cellp = cellp; } else - tsp = cm_NewServer(addrp, CM_SERVER_VLDB, cellp); + tsp = cm_NewServer(addrp, CM_SERVER_VLDB, cellp); /* Insert the vlserver into a sorted list, sorted by server rank */ tsrp = cm_NewServerRef(tsp); cm_InsertServerList(&cellp->vlServersp, tsrp); - + /* drop the allocation reference */ + lock_ObtainWrite(&cm_serverLock); + tsrp->refCount--; + lock_ReleaseWrite(&cm_serverLock); return 0; } diff --git a/src/WINNT/afsd/cm_conn.c b/src/WINNT/afsd/cm_conn.c index 856f31d82..ae68422b4 100644 --- a/src/WINNT/afsd/cm_conn.c +++ b/src/WINNT/afsd/cm_conn.c @@ -101,32 +101,23 @@ long cm_GetServerList(struct cm_fid *fidp, struct cm_user *userp, struct cm_req *reqp, cm_serverRef_t **serverspp) { long code; - cm_volume_t *volp = NULL; - cm_serverRef_t *serversp = NULL; - cm_cell_t *cellp = NULL; + cm_volume_t *volp = NULL; + cm_cell_t *cellp = NULL; - if (!fidp) { + if (!fidp) { *serverspp = NULL; return 0; } cellp = cm_FindCellByID(fidp->cell); - if (!cellp) return CM_ERROR_NOSUCHCELL; + if (!cellp) return CM_ERROR_NOSUCHCELL; - code = cm_GetVolumeByID(cellp, fidp->volume, userp, reqp, &volp); - if (code) return code; - - if (fidp->volume == volp->rwID) - serversp = volp->rwServersp; - else if (fidp->volume == volp->roID) - serversp = volp->roServersp; - else if (fidp->volume == volp->bkID) - serversp = volp->bkServersp; - else - serversp = NULL; - - cm_PutVolume(volp); - *serverspp = serversp; + code = cm_GetVolumeByID(cellp, fidp->volume, userp, reqp, &volp); + if (code) return code; + + *serverspp = cm_GetVolServers(volp, fidp->volume); + + cm_PutVolume(volp); return 0; } @@ -148,13 +139,16 @@ long cm_GetServerList(struct cm_fid *fidp, struct cm_user *userp, */ int cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, - struct cm_fid *fidp, - AFSVolSync *volSyncp, cm_callbackRequest_t *cbrp, long errorCode) + struct cm_fid *fidp, + AFSVolSync *volSyncp, + cm_serverRef_t * serversp, + cm_callbackRequest_t *cbrp, long errorCode) { cm_server_t *serverp; - cm_serverRef_t *serversp, *tsrp; + cm_serverRef_t *tsrp; cm_ucell_t *ucellp; - int retry = 0; + int retry = 0; + int free_svr_list = 0; int dead_session; osi_Log2(afsd_logp, "cm_Analyze connp 0x%x, code %d", @@ -167,7 +161,8 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, serverp = connp->serverp; /* Update callback pointer */ - if (cbrp && errorCode == 0) cbrp->serverp = connp->serverp; + if (cbrp && errorCode == 0) + cbrp->serverp = connp->serverp; /* If not allowed to retry, don't */ if (reqp->flags & CM_REQ_NORETRY) @@ -205,7 +200,10 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, * the servers are marked as DOWN. So clear the DOWN * flag and reset the busy state as well. */ - cm_GetServerList(fidp, userp, reqp, &serversp); + if (!serversp) { + cm_GetServerList(fidp, userp, reqp, &serversp); + free_svr_list = 1; + } if (serversp) { lock_ObtainWrite(&cm_serverLock); for (tsrp = serversp; tsrp; tsrp=tsrp->next) { @@ -214,7 +212,8 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, tsrp->status = not_busy; } lock_ReleaseWrite(&cm_serverLock); - + if (free_svr_list) + cm_FreeServerList(&serversp); retry = 1; } @@ -224,20 +223,28 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, /* if all servers are busy, mark them non-busy and start over */ if (errorCode == CM_ERROR_ALLBUSY) { - cm_GetServerList(fidp, userp, reqp, &serversp); + if (!serversp) { + cm_GetServerList(fidp, userp, reqp, &serversp); + free_svr_list = 1; + } lock_ObtainWrite(&cm_serverLock); for (tsrp = serversp; tsrp; tsrp=tsrp->next) { if (tsrp->status == busy) tsrp->status = not_busy; } lock_ReleaseWrite(&cm_serverLock); + if (free_svr_list) + cm_FreeServerList(&serversp); thrd_Sleep(5000); retry = 1; } /* special codes: VBUSY and VRESTARTING */ if (errorCode == VBUSY || errorCode == VRESTARTING) { - cm_GetServerList(fidp, userp, reqp, &serversp); + if (!serversp) { + cm_GetServerList(fidp, userp, reqp, &serversp); + free_svr_list = 1; + } lock_ObtainWrite(&cm_serverLock); for (tsrp = serversp; tsrp; tsrp=tsrp->next) { if (tsrp->server == serverp @@ -247,6 +254,8 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, } } lock_ReleaseWrite(&cm_serverLock); + if (free_svr_list) + cm_FreeServerList(&serversp); retry = 1; } @@ -278,12 +287,16 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, } /* Mark server offline for this volume */ - cm_GetServerList(fidp, userp, reqp, &serversp); - + if (!serversp) { + cm_GetServerList(fidp, userp, reqp, &serversp); + free_svr_list = 1; + } for (tsrp = serversp; tsrp; tsrp=tsrp->next) { if (tsrp->server == serverp) tsrp->status = offline; } + if (free_svr_list) + cm_FreeServerList(&serversp); retry = 1; } @@ -312,10 +325,10 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp, else if (errorCode >= -64 && errorCode < 0) { /* mark server as down */ lock_ObtainMutex(&serverp->mx); - serverp->flags |= CM_SERVERFLAG_DOWN; + serverp->flags |= CM_SERVERFLAG_DOWN; lock_ReleaseMutex(&serverp->mx); - retry = 1; - } + retry = 1; + } if (errorCode == RXKADEXPIRED && !dead_session) { lock_ObtainMutex(&userp->mx); @@ -347,21 +360,21 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp, { long code; cm_serverRef_t *tsrp; - cm_server_t *tsp; - long firstError = 0; + cm_server_t *tsp; + long firstError = 0; int someBusy = 0, someOffline = 0, allBusy = 1, allDown = 1; long timeUsed, timeLeft, hardTimeLeft; #ifdef DJGPP - struct timeval now; + struct timeval now; #endif /* DJGPP */ - *connpp = NULL; + *connpp = NULL; #ifndef DJGPP timeUsed = (GetCurrentTime() - reqp->startTime) / 1000; #else - gettimeofday(&now, NULL); - timeUsed = sub_time(now, reqp->startTime) / 1000; + gettimeofday(&now, NULL); + timeUsed = sub_time(now, reqp->startTime) / 1000; #endif /* leave 5 seconds margin of safety */ @@ -369,8 +382,7 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp, hardTimeLeft = HardDeadtimeout - timeUsed - 5; lock_ObtainWrite(&cm_serverLock); - - for(tsrp = serversp; tsrp; tsrp=tsrp->next) { + for (tsrp = serversp; tsrp; tsrp=tsrp->next) { tsp = tsrp->server; tsp->refCount++; lock_ReleaseWrite(&cm_serverLock); @@ -556,5 +568,6 @@ long cm_Conn(struct cm_fid *fidp, struct cm_user *userp, cm_req_t *reqp, } code = cm_ConnByMServers(serversp, userp, reqp, connpp); - return code; + cm_FreeServerList(&serversp); + return code; } diff --git a/src/WINNT/afsd/cm_conn.h b/src/WINNT/afsd/cm_conn.h index 719d438d3..9404be829 100644 --- a/src/WINNT/afsd/cm_conn.h +++ b/src/WINNT/afsd/cm_conn.h @@ -91,6 +91,7 @@ extern void cm_InitReq(cm_req_t *reqp); extern int cm_Analyze(cm_conn_t *connp, struct cm_user *up, struct cm_req *reqp, struct cm_fid *fidp, struct AFSVolSync *volInfop, + struct cm_serverRef_t * serversp, struct cm_callbackRequest *cbrp, long code); extern long cm_ConnByMServers(struct cm_serverRef *, struct cm_user *, diff --git a/src/WINNT/afsd/cm_dcache.c b/src/WINNT/afsd/cm_dcache.c index 3086fd181..f65e9bb9a 100644 --- a/src/WINNT/afsd/cm_dcache.c +++ b/src/WINNT/afsd/cm_dcache.c @@ -173,7 +173,7 @@ long cm_BufWrite(void *vfidp, osi_hyper_t *offsetp, long length, long flags, code = rx_EndCall(callp, code); osi_Log0(afsd_logp, "CALL StoreData DONE"); - } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, code)); + } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, NULL, code)); code = cm_MapRPCError(code, reqp); /* now, clean up our state */ @@ -266,7 +266,7 @@ long cm_StoreMini(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp) if (code == 0) code = EndRXAFS_StoreData(callp, &outStatus, &volSync); code = rx_EndCall(callp, code); - } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, code)); + } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, NULL, code)); code = cm_MapRPCError(code, reqp); /* now, clean up our state */ @@ -1345,7 +1345,7 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up, osi_Log0(afsd_logp, "CALL EndCall returns RXKADUNKNOWNKEY"); osi_Log0(afsd_logp, "CALL FetchData DONE"); - } while (cm_Analyze(connp, up, reqp, &scp->fid, &volSync, NULL, code)); + } while (cm_Analyze(connp, up, reqp, &scp->fid, &volSync, NULL, NULL, code)); fetchingcompleted: code = cm_MapRPCError(code, reqp); diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index c88dd9064..0104d1a1a 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -419,8 +419,7 @@ long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp) if (code) continue; code = RXAFS_FetchACL(connp->callp, &fid, &acl, &fileStatus, &volSync); - } while (cm_Analyze(connp, userp, &req, &scp->fid, - &volSync, NULL, code)); + } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code)); code = cm_MapRPCError(code, &req); cm_ReleaseSCache(scp); @@ -485,8 +484,7 @@ long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp) if (code) continue; code = RXAFS_StoreACL(connp->callp, &fid, &acl, &fileStatus, &volSync); - } while (cm_Analyze(connp, userp, &req, &scp->fid, - &volSync, NULL, code)); + } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code)); code = cm_MapRPCError(code, &req); /* invalidate cache info, since we just trashed the ACL cache */ @@ -611,7 +609,7 @@ long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) code = RXAFS_SetVolumeStatus(tcp->callp, scp->fid.volume, &storeStat, volName, offLineMsg, motd); - } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, code)); + } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code)); code = cm_MapRPCError(code, &req); /* return on failure */ @@ -669,7 +667,7 @@ long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) code = RXAFS_GetVolumeStatus(tcp->callp, scp->fid.volume, &volStat, &Name, &OfflineMsg, &MOTD); - } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, code)); + } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code)); code = cm_MapRPCError(code, &req); cm_ReleaseSCache(scp); @@ -695,43 +693,43 @@ long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp) { long code; - cm_scache_t *scp; - cm_cell_t *cellp; - cm_volume_t *tvp; - cm_serverRef_t *tsrp; - cm_server_t *tsp; - unsigned long volume; - char *cp; - cm_req_t req; + cm_scache_t *scp; + cm_cell_t *cellp; + cm_volume_t *tvp; + cm_serverRef_t *tsrp, *current; + cm_server_t *tsp; + unsigned long volume; + char *cp; + cm_req_t req; cm_InitReq(&req); - code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp); - if (code) return code; + code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp); + if (code) return code; volume = scp->fid.volume; cellp = cm_FindCellByID(scp->fid.cell); - osi_assert(cellp); + osi_assert(cellp); - cm_ReleaseSCache(scp); + cm_ReleaseSCache(scp); code = cm_GetVolumeByID(cellp, volume, userp, &req, &tvp); - if (code) return code; + if (code) return code; - cp = ioctlp->outDatap; + cp = ioctlp->outDatap; lock_ObtainMutex(&tvp->mx); tsrp = cm_GetVolServers(tvp, volume); lock_ObtainRead(&cm_serverLock); - while(tsrp) { - tsp = tsrp->server; + for (current = tsrp; current; current = current->next) { + tsp = current->server; memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long)); cp += sizeof(long); - tsrp = tsrp->next; } lock_ReleaseRead(&cm_serverLock); - lock_ReleaseMutex(&tvp->mx); + cm_FreeServerList(&tsrp); + lock_ReleaseMutex(&tvp->mx); /* still room for terminating NULL, add it on */ volume = 0; /* reuse vbl */ @@ -1007,14 +1005,14 @@ long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp) long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp) { long whichCell; - long magic = 0; + long magic = 0; cm_cell_t *tcellp; cm_serverRef_t *serverRefp; - cm_server_t *serverp; + cm_server_t *serverp; long i; - char *cp; - char *tp; - char *basep; + char *cp; + char *tp; + char *basep; cm_SkipIoctlPath(ioctlp); @@ -1028,7 +1026,7 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp) memcpy((char *)&magic, tp, sizeof(long)); } - lock_ObtainRead(&cm_cellLock); + lock_ObtainRead(&cm_cellLock); for(tcellp = cm_allCellsp; tcellp; tcellp = tcellp->nextp) { if (whichCell == 0) break; whichCell--; @@ -1044,15 +1042,16 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp) max = 13; } memset(cp, 0, max * sizeof(long)); - basep = cp; + basep = cp; lock_ObtainRead(&cm_serverLock); /* for going down server list */ + /* jaltman - do the reference counts to serverRefp contents need to be increased? */ serverRefp = tcellp->vlServersp; for(i=0; iserver; memcpy(cp, &serverp->addr.sin_addr.s_addr, sizeof(long)); cp += sizeof(long); - serverRefp = serverRefp->next; + serverRefp = serverRefp->next; } lock_ReleaseRead(&cm_serverLock); cp = basep + max * sizeof(afs_int32); @@ -1982,7 +1981,6 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp) { char afspath[MAX_PATH]; char *submountreqp; - int iteration; int nextAutoSubmount; HKEY hkSubmounts; DWORD dwType, dwSize; @@ -2021,7 +2019,6 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp) if (submountreqp && *submountreqp) { char submountPathNormalized[MAX_PATH]; char submountPath[MAX_PATH]; - int submountPathLen; dwSize = sizeof(submountPath); status = RegQueryValueEx( hkSubmounts, submountreqp, 0, diff --git a/src/WINNT/afsd/cm_server.c b/src/WINNT/afsd/cm_server.c index 248050f4d..e5df624a0 100644 --- a/src/WINNT/afsd/cm_server.c +++ b/src/WINNT/afsd/cm_server.c @@ -142,6 +142,11 @@ void cm_PutServer(cm_server_t *serverp) lock_ReleaseWrite(&cm_serverLock); } +void cm_PutServerNoLock(cm_server_t *serverp) +{ + osi_assert(serverp->refCount-- > 0); +} + void cm_SetServerPrefs(cm_server_t * serverp) { unsigned long serverAddr; /* in host byte order */ @@ -243,13 +248,14 @@ cm_serverRef_t *cm_NewServerRef(cm_server_t *serverp) { cm_serverRef_t *tsrp; - lock_ObtainWrite(&cm_serverLock); + lock_ObtainWrite(&cm_serverLock); serverp->refCount++; - lock_ReleaseWrite(&cm_serverLock); + lock_ReleaseWrite(&cm_serverLock); tsrp = malloc(sizeof(*tsrp)); tsrp->server = serverp; tsrp->status = not_busy; tsrp->next = NULL; + tsrp->refCount = 1; return tsrp; } @@ -261,7 +267,6 @@ long cm_ChecksumServerList(cm_serverRef_t *serversp) cm_serverRef_t *tsrp; lock_ObtainWrite(&cm_serverLock); - for (tsrp = serversp; tsrp; tsrp=tsrp->next) { if (first) first = 0; @@ -277,6 +282,8 @@ long cm_ChecksumServerList(cm_serverRef_t *serversp) /* ** Insert a server into the server list keeping the list sorted in ** asending order of ipRank. +** +** The refCount of the cm_serverRef_t is increased */ void cm_InsertServerList(cm_serverRef_t** list, cm_serverRef_t* element) { @@ -284,8 +291,9 @@ void cm_InsertServerList(cm_serverRef_t** list, cm_serverRef_t* element) unsigned short ipRank = element->server->ipRank; lock_ObtainWrite(&cm_serverLock); + element->refCount++; /* increase refCount */ - /* insertion into empty list or at the beginning of the list */ + /* insertion into empty list or at the beginning of the list */ if ( !current || (current->server->ipRank > ipRank) ) { element->next = *list; @@ -338,6 +346,11 @@ long cm_ChangeRankServer(cm_serverRef_t** list, cm_server_t* server) /* re-insert deleted element into the list with modified rank*/ cm_InsertServerList(list, element); + + /* reduce refCount which was increased by cm_InsertServerList */ + lock_ObtainWrite(&cm_serverLock); + element->refCount--; + lock_ReleaseWrite(&cm_serverLock); return 0; } /* @@ -427,8 +440,10 @@ void cm_FreeServerList(cm_serverRef_t** list) while (current) { next = current->next; - cm_FreeServer(current->server); - free(current); + if (--current->refCount == 0) { + cm_FreeServer(current->server); + free(current); + } current = next; } diff --git a/src/WINNT/afsd/cm_server.h b/src/WINNT/afsd/cm_server.h index 114a3782a..cabaf7c16 100644 --- a/src/WINNT/afsd/cm_server.h +++ b/src/WINNT/afsd/cm_server.h @@ -22,22 +22,23 @@ */ typedef struct cm_server { struct cm_server *allNextp; /* locked by cm_serverLock */ - struct sockaddr_in addr; /* by mx */ - int type; /* by mx */ + struct sockaddr_in addr; /* by mx */ + int type; /* by mx */ struct cm_conn *connsp; /* locked by cm_connLock */ - long flags; /* by mx */ - struct cm_cell *cellp; /* cell containing this server */ + long flags; /* by mx */ + struct cm_cell *cellp; /* cell containing this server */ int refCount; /* locked by cm_serverLock */ - osi_mutex_t mx; + osi_mutex_t mx; unsigned short ipRank; /* server priority */ } cm_server_t; enum repstate {not_busy, busy, offline}; typedef struct cm_serverRef { - struct cm_serverRef *next; - struct cm_server *server; - enum repstate status; + struct cm_serverRef *next; /* locked by cm_serverLock */ + struct cm_server *server; /* locked by cm_serverLock */ + enum repstate status; /* locked by cm_serverLock */ + int refCount; /* locked by cm_serverLock */ } cm_serverRef_t; /* types */ @@ -75,6 +76,8 @@ extern long cm_ChecksumServerList(cm_serverRef_t *serversp); extern void cm_PutServer(cm_server_t *); +extern void cm_PutServerNoLock(cm_server_t *); + extern cm_server_t *cm_FindServer(struct sockaddr_in *addrp, int type); extern osi_rwlock_t cm_serverLock; diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 3ffb9fb80..9ef59eb2f 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -1114,8 +1114,7 @@ long cm_Unlink(cm_scache_t *dscp, char *namep, cm_user_t *userp, cm_req_t *reqp) code = RXAFS_RemoveFile(connp->callp, &afsFid, namep, &newDirStatus, &volSync); - } while (cm_Analyze(connp, userp, reqp, - &dscp->fid, &volSync, NULL, code)); + } while (cm_Analyze(connp, userp, reqp, &dscp->fid, &volSync, NULL, NULL, code)); code = cm_MapRPCError(code, reqp); lock_ObtainMutex(&dscp->mx); @@ -1630,7 +1629,7 @@ void cm_TryBulkStat(cm_scache_t *dscp, osi_hyper_t *offsetp, cm_user_t *userp, &statStruct, &callbackStruct, &volSync); } while (cm_Analyze(connp, userp, reqp, &dscp->fid, - &volSync, &cbReq, code)); + &volSync, NULL, &cbReq, code)); code = cm_MapRPCError(code, reqp); osi_Log0(afsd_logp, "CALL BulkStatus DONE"); @@ -1850,7 +1849,7 @@ long cm_SetAttr(cm_scache_t *scp, cm_attr_t *attrp, cm_user_t *userp, &afsInStatus, &afsOutStatus, &volSync); } while (cm_Analyze(connp, userp, reqp, - &scp->fid, &volSync, NULL, code)); + &scp->fid, &volSync, NULL, NULL, code)); code = cm_MapRPCError(code, reqp); osi_Log1(afsd_logp, "CALL StoreStatus DONE, code %d", code); @@ -1923,7 +1922,7 @@ long cm_Create(cm_scache_t *dscp, char *namep, long flags, cm_attr_t *attrp, &updatedDirStatus, &newFileCallback, &volSync); } while (cm_Analyze(connp, userp, reqp, - &dscp->fid, &volSync, &cbReq, code)); + &dscp->fid, &volSync, NULL, &cbReq, code)); code = cm_MapRPCError(code, reqp); lock_ObtainMutex(&dscp->mx); @@ -2039,7 +2038,7 @@ long cm_MakeDir(cm_scache_t *dscp, char *namep, long flags, cm_attr_t *attrp, &updatedDirStatus, &newDirCallback, &volSync); } while (cm_Analyze(connp, userp, reqp, - &dscp->fid, &volSync, &cbReq, code)); + &dscp->fid, &volSync, NULL, &cbReq, code)); code = cm_MapRPCError(code, reqp); lock_ObtainMutex(&dscp->mx); @@ -2121,7 +2120,7 @@ long cm_SymLink(cm_scache_t *dscp, char *namep, char *contentsp, long flags, &inStatus, &newAFSFid, &newLinkStatus, &updatedDirStatus, &volSync); } while (cm_Analyze(connp, userp, reqp, - &dscp->fid, &volSync, NULL, code)); + &dscp->fid, &volSync, NULL, NULL, code)); code = cm_MapRPCError(code, reqp); lock_ObtainMutex(&dscp->mx); @@ -2190,7 +2189,7 @@ long cm_RemoveDir(cm_scache_t *dscp, char *namep, cm_user_t *userp, code = RXAFS_RemoveDir(connp->callp, &dirAFSFid, namep, &updatedDirStatus, &volSync); } while (cm_Analyze(connp, userp, reqp, - &dscp->fid, &volSync, NULL, code)); + &dscp->fid, &volSync, NULL, NULL, code)); code = cm_MapRPCErrorRmdir(code, reqp); lock_ObtainMutex(&dscp->mx); @@ -2330,7 +2329,7 @@ long cm_Rename(cm_scache_t *oldDscp, char *oldNamep, cm_scache_t *newDscp, &updatedOldDirStatus, &updatedNewDirStatus, &volSync); } while (cm_Analyze(connp, userp, reqp, &oldDscp->fid, - &volSync, NULL, code)); + &volSync, NULL, NULL, code)); code = cm_MapRPCError(code, reqp); /* update the individual stat cache entries for the directories */ @@ -2402,7 +2401,7 @@ long cm_Lock(cm_scache_t *scp, unsigned char LockType, code = RXAFS_SetLock(connp->callp, &tfid, Which, &volSync); } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, - NULL, code)); + NULL, NULL, code)); lock_ObtainMutex(&scp->mx); code = cm_MapRPCError(code, reqp); } @@ -2493,7 +2492,7 @@ long cm_Unlock(cm_scache_t *scp, unsigned char LockType, break; code = RXAFS_ReleaseLock(connp->callp, &tfid, &volSync); } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, - NULL, code)); + NULL, NULL, code)); code = cm_MapRPCError(code, reqp); lock_ObtainMutex(&scp->mx); } @@ -2534,7 +2533,7 @@ void cm_CheckLocks() code = RXAFS_ExtendLock(connp->callp, &tfid, &volSync); } while (cm_Analyze(connp, fileLock->userp, &req, - &fileLock->fid, &volSync, NULL, + &fileLock->fid, &volSync, NULL, NULL, code)); code = cm_MapRPCError(code, &req); lock_ObtainWrite(&cm_scacheLock); @@ -2602,7 +2601,7 @@ long cm_RetryLock(cm_file_lock_t *oldFileLock, int vcp_is_dead) &volSync); } while (cm_Analyze(connp, oldFileLock->userp, &req, &oldFileLock->fid, &volSync, - NULL, code)); + NULL, NULL, code)); code = cm_MapRPCError(code, &req); } diff --git a/src/WINNT/afsd/cm_volume.c b/src/WINNT/afsd/cm_volume.c index 7143a520f..aa1ebd43c 100644 --- a/src/WINNT/afsd/cm_volume.c +++ b/src/WINNT/afsd/cm_volume.c @@ -55,21 +55,9 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp, long code; /* clear out old bindings */ - while (tsrp = volp->rwServersp) { - volp->rwServersp = tsrp->next; - cm_PutServer(tsrp->server); - free(tsrp); - } - while (tsrp = volp->roServersp) { - volp->roServersp = tsrp->next; - cm_PutServer(tsrp->server); - free(tsrp); - } - while (tsrp = volp->bkServersp) { - volp->bkServersp = tsrp->next; - cm_PutServer(tsrp->server); - free(tsrp); - } + cm_FreeServerList(&volp->rwServersp); + cm_FreeServerList(&volp->roServersp); + cm_FreeServerList(&volp->bkServersp); /* now we have volume structure locked and held; make RPC to fill it */ do { @@ -79,7 +67,7 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp, osi_Log1(afsd_logp, "CALL VL_GetEntryByNameO name %s", volp->namep); code = VL_GetEntryByNameO(connp->callp, volp->namep, &vldbEntry); - } while (cm_Analyze(connp, userp, reqp, NULL, NULL, NULL, code)); + } while (cm_Analyze(connp, userp, reqp, NULL, NULL, cellp->vlServersp, NULL, code)); code = cm_MapVLRPCError(code, reqp); if (code == 0) { @@ -126,21 +114,28 @@ long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp, if ((tflags & VLSF_RWVOL) && (vldbEntry.flags & VLF_RWEXISTS)) { tsrp = cm_NewServerRef(tsp); - tsrp->next = volp->rwServersp; - volp->rwServersp = tsrp; + cm_InsertServerList(&volp->rwServersp, tsrp); + lock_ObtainWrite(&cm_serverLock); + tsrp->refCount--; /* drop allocation reference */ + lock_ReleaseWrite(&cm_serverLock); } if ((tflags & VLSF_ROVOL) && (vldbEntry.flags & VLF_ROEXISTS)) { tsrp = cm_NewServerRef(tsp); cm_InsertServerList(&volp->roServersp, tsrp); + lock_ObtainWrite(&cm_serverLock); + tsrp->refCount--; /* drop allocation reference */ + lock_ReleaseWrite(&cm_serverLock); ROcount++; } /* We don't use VLSF_BACKVOL !?! */ if ((tflags & VLSF_RWVOL) && (vldbEntry.flags & VLF_BACKEXISTS)) { tsrp = cm_NewServerRef(tsp); - tsrp->next = volp->bkServersp; - volp->bkServersp = tsrp; + cm_InsertServerList(&volp->bkServersp, tsrp); + lock_ObtainWrite(&cm_serverLock); + tsrp->refCount--; /* drop allocation reference */ + lock_ReleaseWrite(&cm_serverLock); } /* Drop the reference obtained by cm_FindServer() */ cm_PutServer(tsp); @@ -311,16 +306,24 @@ void cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp) cm_serverRef_t *cm_GetVolServers(cm_volume_t *volp, unsigned long volume) { cm_serverRef_t *serversp; + cm_serverRef_t *current;; + + lock_ObtainWrite(&cm_serverLock); if (volume == volp->rwID) - serversp = volp->rwServersp; + serversp = volp->rwServersp; else if (volume == volp->roID) - serversp = volp->roServersp; + serversp = volp->roServersp; else if (volume == volp->bkID) - serversp = volp->bkServersp; + serversp = volp->bkServersp; else osi_panic("bad volume ID in cm_GetVolServers", __FILE__, __LINE__); - return serversp; + for (current = serversp; current; current = current->next) + current->refCount++; + + lock_ReleaseWrite(&cm_serverLock); + + return serversp; } void cm_PutVolume(cm_volume_t *volp)