#include <winsock2.h>
#include <nb30.h>
#include <string.h>
+#include <strsafe.h>
#include <malloc.h>
#include "afsd.h"
#include <osi.h>
cm_VolumeStatusNotification(volp, volp->vol[volType].ID, volp->vol[volType].state, vl_alldown);
}
volp->cbExpiresRO = 0;
+ volp->cbIssuedRO = 0;
volp->cbServerpRO = NULL;
lock_FinalizeRWLock(&volp->rw);
}
lock_InitializeRWLock(&volp->rw, "cm_volume_t rwlock", LOCK_HIERARCHY_VOLUME);
_InterlockedOr(&volp->flags, CM_VOLUMEFLAG_RESET);
_InterlockedAnd(&volp->flags, ~CM_VOLUMEFLAG_UPDATING_VL);
+ volp->lastUpdateTime = 0;
for (volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
volp->vol[volType].state = vl_unknown;
volp->vol[volType].serversp = NULL;
cm_VolumeStatusNotification(volp, volp->vol[volType].ID, vl_unknown, volp->vol[volType].state);
}
volp->cbExpiresRO = 0;
+ volp->cbIssuedRO = 0;
volp->cbServerpRO = NULL;
}
}
* first, and fall back to successively older versions if you get
* RXGEN_OPCODE.
*/
-#define MULTIHOMED 1
+static long
+cm_GetEntryByName( struct cm_cell *cellp, const char *name,
+ struct vldbentry *vldbEntryp,
+ struct nvldbentry *nvldbEntryp,
+ struct uvldbentry *uvldbEntryp,
+ int *methodp,
+ cm_user_t *userp,
+ cm_req_t *reqp
+ )
+{
+ long code;
+ cm_conn_t *connp;
+ struct rx_connection * rxconnp;
+
+ osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s",
+ osi_LogSaveString(afsd_logp,cellp->name),
+ osi_LogSaveString(afsd_logp,name));
+ do {
+
+ code = cm_ConnByMServers(cellp->vlServersp, FALSE, userp, reqp, &connp);
+ if (code)
+ continue;
+
+ rxconnp = cm_GetRxConn(connp);
+ code = VL_GetEntryByNameU(rxconnp, name, uvldbEntryp);
+ *methodp = 2;
+ if ( code == RXGEN_OPCODE )
+ {
+ code = VL_GetEntryByNameN(rxconnp, name, nvldbEntryp);
+ *methodp = 1;
+ }
+ if ( code == RXGEN_OPCODE ) {
+ code = VL_GetEntryByNameO(rxconnp, name, vldbEntryp);
+ *methodp = 0;
+ }
+ rx_PutConnection(rxconnp);
+ } while (cm_Analyze(connp, userp, reqp, NULL, 0, NULL, cellp->vlServersp, NULL, code));
+ code = cm_MapVLRPCError(code, reqp);
+ if ( code )
+ osi_Log3(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s FAILURE, code 0x%x",
+ osi_LogSaveString(afsd_logp,cellp->name),
+ osi_LogSaveString(afsd_logp,name), code);
+ else
+ osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s SUCCESS",
+ osi_LogSaveString(afsd_logp,cellp->name),
+ osi_LogSaveString(afsd_logp,name));
+ return code;
+}
+
+static long
+cm_GetEntryByID( struct cm_cell *cellp, afs_uint32 id,
+ struct vldbentry *vldbEntryp,
+ struct nvldbentry *nvldbEntryp,
+ struct uvldbentry *uvldbEntryp,
+ int *methodp,
+ cm_user_t *userp,
+ cm_req_t *reqp
+ )
+{
+ char name[64];
+
+ StringCbPrintf(name, sizeof(name), "%u", id);
+
+ return cm_GetEntryByName(cellp, name, vldbEntryp, nvldbEntryp, uvldbEntryp, methodp, userp, reqp);
+}
+
long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
cm_volume_t *volp)
{
+ struct rx_connection *rxconnp;
cm_conn_t *connp;
int i;
afs_uint32 j, k;
u_long tempAddr;
struct vldbentry vldbEntry;
struct nvldbentry nvldbEntry;
-#ifdef MULTIHOMED
struct uvldbentry uvldbEntry;
-#endif
int method = -1;
int ROcount = 0;
long code;
#endif
afs_uint32 volType;
time_t now;
+ int replicated = 0;
lock_AssertWrite(&volp->rw);
osi_Wakeup((LONG_PTR) &volp->flags);
return 0;
}
+ now = time(NULL);
+ }
+
+ /* Do not query again if the last update attempt failed in the last 60 seconds */
+ if ((volp->flags & CM_VOLUMEFLAG_RESET) && (volp->lastUpdateTime > now - 60))
+ {
+ osi_Log3(afsd_logp, "cm_UpdateVolumeLocation unsuccessful update in last 60 seconds -- name %s:%s flags 0x%x",
+ volp->cellp->name, volp->namep, volp->flags);
+ return(CM_ERROR_ALLDOWN);
}
_InterlockedOr(&volp->flags, CM_VOLUMEFLAG_UPDATING_VL);
lock_ReleaseWrite(&volp->rw);
if (cellp->flags & CM_CELLFLAG_VLSERVER_INVALID)
- cm_UpdateCell(cellp, 0);
+ cm_UpdateCell(cellp, 0);
/* now we have volume structure locked and held; make RPC to fill it */
- osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s",
- osi_LogSaveString(afsd_logp,volp->cellp->name),
- osi_LogSaveString(afsd_logp,volp->namep));
- do {
- struct rx_connection * rxconnp;
-
- code = cm_ConnByMServers(cellp->vlServersp, userp, reqp, &connp);
- if (code)
- continue;
-
- rxconnp = cm_GetRxConn(connp);
-#ifdef MULTIHOMED
- code = VL_GetEntryByNameU(rxconnp, volp->namep, &uvldbEntry);
- method = 2;
- if ( code == RXGEN_OPCODE )
-#endif
- {
- code = VL_GetEntryByNameN(rxconnp, volp->namep, &nvldbEntry);
- method = 1;
- }
- if ( code == RXGEN_OPCODE ) {
- code = VL_GetEntryByNameO(rxconnp, volp->namep, &vldbEntry);
- method = 0;
- }
- rx_PutConnection(rxconnp);
- } while (cm_Analyze(connp, userp, reqp, NULL, NULL, cellp->vlServersp, NULL, code));
- code = cm_MapVLRPCError(code, reqp);
- if ( code )
- osi_Log3(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s FAILURE, code 0x%x",
- osi_LogSaveString(afsd_logp,volp->cellp->name),
- osi_LogSaveString(afsd_logp,volp->namep), code);
- else
- osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s SUCCESS",
- osi_LogSaveString(afsd_logp,volp->cellp->name),
- osi_LogSaveString(afsd_logp,volp->namep));
+ code = cm_GetEntryByName(cellp, volp->namep, &vldbEntry, &nvldbEntry,
+ &uvldbEntry,
+ &method, userp, reqp);
}
/* We can end up here with code == CM_ERROR_NOSUCHVOLUME if the base volume name
snprintf(name, VL_MAXNAMELEN, "%s.readonly", volp->namep);
/* now we have volume structure locked and held; make RPC to fill it */
- osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s",
- osi_LogSaveString(afsd_logp,volp->cellp->name),
- osi_LogSaveString(afsd_logp,name));
- do {
- struct rx_connection * rxconnp;
-
- code = cm_ConnByMServers(cellp->vlServersp, userp, reqp, &connp);
- if (code)
- continue;
+ code = cm_GetEntryByName(cellp, name, &vldbEntry, &nvldbEntry,
+ &uvldbEntry,
+ &method, userp, reqp);
+ }
- rxconnp = cm_GetRxConn(connp);
-#ifdef MULTIHOMED
- code = VL_GetEntryByNameU(connp->rxconnp, name, &uvldbEntry);
- method = 2;
- if ( code == RXGEN_OPCODE )
-#endif
- {
- code = VL_GetEntryByNameN(connp->rxconnp, name, &nvldbEntry);
- method = 1;
- }
- if ( code == RXGEN_OPCODE ) {
- code = VL_GetEntryByNameO(connp->rxconnp, name, &vldbEntry);
- method = 0;
- }
- rx_PutConnection(rxconnp);
- } while (cm_Analyze(connp, userp, reqp, NULL, NULL, cellp->vlServersp, NULL, code));
- code = cm_MapVLRPCError(code, reqp);
- if ( code )
- osi_Log3(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s FAILURE, code 0x%x",
- osi_LogSaveString(afsd_logp,volp->cellp->name),
- osi_LogSaveString(afsd_logp,name), code);
- else
- osi_Log2(afsd_logp, "CALL VL_GetEntryByName{UNO} name %s:%s SUCCESS",
- osi_LogSaveString(afsd_logp,volp->cellp->name),
- osi_LogSaveString(afsd_logp,name));
+ /*
+ * What if there was a volume rename? The volume name no longer exists but the
+ * volume id might. Try to refresh the volume location information based one
+ * of the readwrite or readonly volume id.
+ */
+ if (code == CM_ERROR_NOSUCHVOLUME) {
+ if (volp->vol[RWVOL].ID != 0) {
+ code = cm_GetEntryByID(cellp, volp->vol[RWVOL].ID, &vldbEntry, &nvldbEntry,
+ &uvldbEntry,
+ &method, userp, reqp);
+ } else if (volp->vol[ROVOL].ID != 0) {
+ code = cm_GetEntryByID(cellp, volp->vol[ROVOL].ID, &vldbEntry, &nvldbEntry,
+ &uvldbEntry,
+ &method, userp, reqp);
+ }
}
lock_ObtainWrite(&volp->rw);
case 0:
flags = vldbEntry.flags;
nServers = vldbEntry.nServers;
+ replicated = (nServers > 0);
rwID = vldbEntry.volumeId[0];
roID = vldbEntry.volumeId[1];
bkID = vldbEntry.volumeId[2];
case 1:
flags = nvldbEntry.flags;
nServers = nvldbEntry.nServers;
+ replicated = (nServers > 0);
rwID = nvldbEntry.volumeId[0];
roID = nvldbEntry.volumeId[1];
bkID = nvldbEntry.volumeId[2];
strncpy(name, nvldbEntry.name, VL_MAXNAMELEN);
name[VL_MAXNAMELEN - 1] = '\0';
break;
-#ifdef MULTIHOMED
case 2:
flags = uvldbEntry.flags;
nServers = uvldbEntry.nServers;
+ replicated = (nServers > 0);
rwID = uvldbEntry.volumeId[0];
roID = uvldbEntry.volumeId[1];
bkID = uvldbEntry.volumeId[2];
for ( i=0, j=0; code == 0 && i<nServers && j<NMAXNSERVERS; i++ ) {
- if ( !(uvldbEntry.serverFlags[i] & VLSERVER_FLAG_UUID) ) {
+ if ( !(uvldbEntry.serverFlags[i] & VLSF_UUID) ) {
serverFlags[j] = uvldbEntry.serverFlags[i];
serverNumber[j] = uvldbEntry.serverNumber[i].time_low;
j++;
memset(&addrs, 0, sizeof(addrs));
do {
- struct rx_connection *rxconnp;
-
- code = cm_ConnByMServers(cellp->vlServersp, userp, reqp, &connp);
+ code = cm_ConnByMServers(cellp->vlServersp, FALSE, userp, reqp, &connp);
if (code)
continue;
rxconnp = cm_GetRxConn(connp);
code = VL_GetAddrsU(rxconnp, &attrs, &uuid, &unique, &nentries, &addrs);
rx_PutConnection(rxconnp);
- } while (cm_Analyze(connp, userp, reqp, NULL, NULL, cellp->vlServersp, NULL, code));
+ } while (cm_Analyze(connp, userp, reqp, NULL, 0, NULL, cellp->vlServersp, NULL, code));
if ( code ) {
code = cm_MapVLRPCError(code, reqp);
strncpy(name, uvldbEntry.name, VL_MAXNAMELEN);
name[VL_MAXNAMELEN - 1] = '\0';
break;
-#endif
}
/* decode the response */
lock_ObtainWrite(&cm_volumeLock);
- if (cm_VolNameIsID(volp->namep)) {
+ if (!cm_VolNameIsID(volp->namep)) {
size_t len;
len = strlen(name);
volp->vol[ROVOL].ID = roID;
cm_AddVolumeToIDHashTable(volp, ROVOL);
}
+ if (replicated)
+ _InterlockedOr(&volp->vol[ROVOL].flags, CM_VOL_STATE_FLAG_REPLICATED);
+ else
+ _InterlockedAnd(&volp->vol[ROVOL].flags, ~CM_VOL_STATE_FLAG_REPLICATED);
} else {
if (volp->vol[ROVOL].qflags & CM_VOLUME_QFLAG_IN_HASH)
cm_RemoveVolumeFromIDHashTable(volp, ROVOL);
tsockAddr.sin_family = AF_INET;
tempAddr = htonl(serverNumber[i]);
tsockAddr.sin_addr.s_addr = tempAddr;
- tsp = cm_FindServer(&tsockAddr, CM_SERVER_FILE);
+ tsp = cm_FindServer(&tsockAddr, CM_SERVER_FILE, FALSE);
if (tsp && (method == 2) && (tsp->flags & CM_SERVERFLAG_UUID)) {
/*
* Check to see if the uuid of the server we know at this address
if ( (method == 2) && !(tsp->flags & CM_SERVERFLAG_UUID) &&
!afs_uuid_is_nil(&serverUUID[i])) {
tsp->uuid = serverUUID[i];
- tsp->flags |= CM_SERVERFLAG_UUID;
+ _InterlockedOr(&tsp->flags, CM_SERVERFLAG_UUID);
}
/* and add it to the list(s). */
if ((tflags & VLSF_RWVOL) && (flags & VLF_RWEXISTS)) {
tsrp = cm_NewServerRef(tsp, rwID);
cm_InsertServerList(&volp->vol[RWVOL].serversp, tsrp);
-
- lock_ObtainWrite(&cm_serverLock);
- tsrp->refCount--; /* drop allocation reference */
- lock_ReleaseWrite(&cm_serverLock);
-
if (!(tsp->flags & CM_SERVERFLAG_DOWN))
rwServers_alldown = 0;
}
if ((tflags & VLSF_ROVOL) && (flags & VLF_ROEXISTS)) {
tsrp = cm_NewServerRef(tsp, roID);
cm_InsertServerList(&volp->vol[ROVOL].serversp, tsrp);
- lock_ObtainWrite(&cm_serverLock);
- tsrp->refCount--; /* drop allocation reference */
- lock_ReleaseWrite(&cm_serverLock);
ROcount++;
if (!(tsp->flags & CM_SERVERFLAG_DOWN))
if ((tflags & VLSF_RWVOL) && (flags & VLF_BACKEXISTS)) {
tsrp = cm_NewServerRef(tsp, bkID);
cm_InsertServerList(&volp->vol[BACKVOL].serversp, tsrp);
- lock_ObtainWrite(&cm_serverLock);
- tsrp->refCount--; /* drop allocation reference */
- lock_ReleaseWrite(&cm_serverLock);
if (!(tsp->flags & CM_SERVERFLAG_DOWN))
bkServers_alldown = 0;
strncpy(volp->namep, name, VL_MAXNAMELEN);
volp->namep[VL_MAXNAMELEN-1] = '\0';
volp->flags = CM_VOLUMEFLAG_RESET;
+ volp->lastUpdateTime = 0;
for ( volType = RWVOL; volType < NUM_VOL_TYPES; volType++) {
volp->vol[volType].state = vl_unknown;
volp->vol[volType].flags = 0;
}
volp->cbExpiresRO = 0;
+ volp->cbIssuedRO = 0;
volp->cbServerpRO = NULL;
volp->creationDateRO = 0;
cm_AddVolumeToNameHashTable(volp);
cm_data.mountRootGen = time(NULL);
lock_ObtainWrite(&volp->rw);
_InterlockedOr(&volp->flags, CM_VOLUMEFLAG_RESET);
+ volp->lastUpdateTime = 0;
code = cm_UpdateVolumeLocation(cellp, userp, reqp, volp);
lock_ReleaseWrite(&volp->rw);
firstTry = 0;
lock_ObtainWrite(&volp->rw);
_InterlockedOr(&volp->flags, CM_VOLUMEFLAG_RESET);
+ volp->lastUpdateTime = 0;
code = cm_UpdateVolumeLocation(volp->cellp, userp, reqp, volp);
lock_ReleaseWrite(&volp->rw);
if (code == 0)
* They will be freed by cm_FreeServerList when they get to zero
*/
for (current = *serverspp; current; current = current->next)
- current->refCount++;
+ cm_GetServerRef(current, TRUE);
lock_ReleaseWrite(&cm_serverLock);
if (!(volp->flags & CM_VOLUMEFLAG_RESET)) {
lock_ObtainWrite(&volp->rw);
- if (volp->lastUpdateTime + lifetime <= now)
+ if (volp->lastUpdateTime + lifetime <= now) {
_InterlockedOr(&volp->flags, CM_VOLUMEFLAG_RESET);
+ volp->lastUpdateTime = 0;
+ }
lock_ReleaseWrite(&volp->rw);
}
*volumeUpdatedp = 1;
}
+ lock_ObtainRead(&cm_serverLock);
if (statep->serversp) {
alldown = 1;
alldeleted = 1;
continue;
alldeleted = 0;
- *onlinep = 1;
- alldown = 0;
+
+ if (!(serversp->server->flags & CM_SERVERFLAG_DOWN))
+ alldown = 0;
if (serversp->status == srv_busy || serversp->status == srv_offline)
serversp->status = srv_not_busy;
}
+ lock_ReleaseRead(&cm_serverLock);
if (alldeleted && !(*volumeUpdatedp)) {
cm_InitReq(&req);
code = RXAFS_GetVolumeStatus(rxconnp, statep->ID,
&volStat, &Name, &OfflineMsg, &MOTD);
rx_PutConnection(rxconnp);
- } while (cm_Analyze(connp, cm_rootUserp, &req, &fid, NULL, NULL, NULL, code));
+ } while (cm_Analyze(connp, cm_rootUserp, &req, &fid, 0, NULL, NULL, NULL, code));
code = cm_MapRPCError(code, &req);
lock_ObtainWrite(&volp->rw);
cm_VolumeStatusNotification(volp, statep->ID, statep->state, vl_alldown);
statep->state = vl_alldown;
}
- } else if (statep->state != vl_alldown) {
- cm_VolumeStatusNotification(volp, statep->ID, statep->state, vl_alldown);
- statep->state = vl_alldown;
+ } else {
+ lock_ReleaseRead(&cm_serverLock);
+ if (statep->state != vl_alldown) {
+ cm_VolumeStatusNotification(volp, statep->ID, statep->state, vl_alldown);
+ statep->state = vl_alldown;
+ }
}
}
}
cm_InitReq(&req);
lock_ReleaseRead(&cm_volumeLock);
- if (cm_GetSCache(&fid, &scp, cm_rootUserp, &req) == 0) {
+ if (cm_GetSCache(&fid, NULL, &scp, cm_rootUserp, &req) == 0) {
lock_ObtainWrite(&scp->rw);
cm_GetCallback(scp, cm_rootUserp, &req, 1);
lock_ReleaseWrite(&scp->rw);