From 523d39f020f551e59b0f369c8480fa13b90db277 Mon Sep 17 00:00:00 2001 From: Felix Frank Date: Wed, 3 Mar 2010 22:41:15 -0500 Subject: [PATCH] Fileserver capabilities support for the UNIX client The attached patch has the client perform a GetCapabilities RPC on fileservers it encounters. It uses an additional server flag bit to keep track of the servers that have been queried already. In the case of afs_CeckServers(), GetTime RPCs are largely replaced by GetCapabilities. GetTime is performed on a server if and only if afs_setTime is nonzero and either (a) no setTimeHost has yet been determined or (b) the server in question has been designated as setTimeHost The GetServers() function could thus be simplified even further wrt. the setTime mechanism, but doing so would imply more rewriting (violating the KISS principle; a followup patch should deal with that). When a client is asked to reset callback states, it also resets the "capabilites known" bit. Thanks go to Simon Wilkinson, Jeffrey Altman and Jeffrey Hutzelman for input regarding logic and implementation details. FIXES 124972 Change-Id: I4e22db3c5ca71f00e8c77f337e38daa0fa5b9124 Reviewed-on: http://gerrit.openafs.org/1640 Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear --- src/afs/afs.h | 5 ++ src/afs/afs_callback.c | 5 ++ src/afs/afs_prototypes.h | 1 + src/afs/afs_server.c | 127 ++++++++++++++++++++++++++++++++++----- 4 files changed, 124 insertions(+), 14 deletions(-) diff --git a/src/afs/afs.h b/src/afs/afs.h index 1b2ab15f5..d4da4f812 100644 --- a/src/afs/afs.h +++ b/src/afs/afs.h @@ -406,6 +406,10 @@ struct srvAddr { #define SRVR_ISGONE 0x80 #define SNO_INLINEBULK 0x100 #define SNO_64BIT 0x200 +#define SCAPS_KNOWN 0x400 + +#define SRV_CAPABILITIES(ts) \ +{ if ( !(ts->flags & SCAPS_KNOWN)) afs_GetCapabilities(ts); ts->capabilities; } #define afs_serverSetNo64Bit(s) ((s)->srvr->server->flags |= SNO_64BIT) #define afs_serverHasNo64Bit(s) ((s)->srvr->server->flags & SNO_64BIT) @@ -437,6 +441,7 @@ struct server { afs_int32 sumOfDowntimes; /* Total downtime experienced, in seconds */ struct srvAddr *addr; afs_uint32 flags; /* Misc flags */ + afs_int32 capabilities; }; #define afs_PutServer(servp, locktype) diff --git a/src/afs/afs_callback.c b/src/afs/afs_callback.c index b8373bb55..674bb867a 100644 --- a/src/afs/afs_callback.c +++ b/src/afs/afs_callback.c @@ -771,6 +771,11 @@ SRXAFSCB_InitCallBackState(struct rx_call *a_call) ReleaseWriteLock(&afs_xcbhash); } } + + /* capabilities need be requested again */ + ObtainWriteLock(&afs_xserver, 877); + ts->flags &= ~SCAPS_KNOWN; + ReleaseWriteLock(&afs_xserver); } diff --git a/src/afs/afs_prototypes.h b/src/afs/afs_prototypes.h index d4dc7fcfe..cbaef5b43 100644 --- a/src/afs/afs_prototypes.h +++ b/src/afs/afs_prototypes.h @@ -833,6 +833,7 @@ extern struct server *afs_GetServer(afs_uint32 * aserver, afs_int32 nservers, afs_int32 acell, u_short aport, afs_int32 locktype, afsUUID * uuidp, afs_int32 addr_uniquifier); +extern void afs_GetCapabilities(struct server *ts); extern void ForceAllNewConnections(void); extern void afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown); extern afs_int32 afs_ServerDown(struct srvAddr *sa); diff --git a/src/afs/afs_server.c b/src/afs/afs_server.c index 8dfd2f12c..01e81a4af 100644 --- a/src/afs/afs_server.c +++ b/src/afs/afs_server.c @@ -542,6 +542,7 @@ afs_CheckServers(int adown, struct cell *acellp) int nconns; struct rx_connection **rxconns; afs_int32 *conntimer, *deltas, *results; + Capabilities *caps = NULL; AFS_STATCNT(afs_CheckServers); @@ -588,6 +589,9 @@ afs_CheckServers(int adown, struct cell *acellp) deltas = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32)); results = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32)); + caps = (Capabilities *)afs_osi_Alloc(j * sizeof (Capabilities)); + memset(caps, 0, j * sizeof(Capabilities)); + for (i = 0; i < j; i++) { deltas[i] = 0; sa = addrs[i]; @@ -636,23 +640,72 @@ afs_CheckServers(int adown, struct cell *acellp) } } /* Outer loop over addrs */ - start = osi_Time(); /* time the gettimeofday call */ - AFS_GUNLOCK(); + AFS_GUNLOCK(); multi_Rx(rxconns,nconns) { - tv.tv_sec = tv.tv_usec = 0; - multi_RXAFS_GetTime((afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec); - tc = conns[multi_i]; - sa = tc->srvr; - if (conntimer[multi_i] == 1) - rx_SetConnDeadTime(tc->id, afs_rx_deadtime); - end = osi_Time(); - results[multi_i]=multi_error; - if ((start == end) && !multi_error) - deltas[multi_i] = end - tv.tv_sec; - + multi_RXAFS_GetCapabilities(&caps[multi_i]); + results[multi_i] = multi_error; } multi_End; - AFS_GLOCK(); + AFS_GLOCK(); + + for ( i = 0 ; i < nconns ; i++ ) { + ts = addrs[i]->server; + if ( !ts ) + continue; + ts->capabilities = 0; + ts->flags |= SCAPS_KNOWN; + if ( results[i] == RXGEN_OPCODE ) { + /* Mark server as up - it responded */ + results[i] = 0; + continue; + } + if ( results[i] >= 0 ) + /* we currently handle 32-bits of capabilities */ + if (caps[i].Capabilities_len > 0) { + ts->capabilities = caps[i].Capabilities_val[0]; + xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]); + caps[i].Capabilities_val = NULL; + caps[i].Capabilities_len = 0; + } + } + + if ( afs_setTime != 0 ) { + start = osi_Time(); /* time the gettimeofday call */ + AFS_GUNLOCK(); + if ( afs_setTimeHost == NULL ) { + multi_Rx(rxconns,nconns) + { + tv.tv_sec = tv.tv_usec = 0; + multi_RXAFS_GetTime( + (afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec); + tc = conns[multi_i]; + sa = tc->srvr; + if (conntimer[multi_i] == 1) + rx_SetConnDeadTime(tc->id, afs_rx_deadtime); + end = osi_Time(); + results[multi_i]=multi_error; + if ((start == end) && !multi_error) + deltas[multi_i] = end - tv.tv_sec; + + } multi_End; + } + else { /* find and query setTimeHost only */ + for ( i = 0 ; i < j ; i++ ) { + if ( conns[i] == NULL || conns[i]->srvr == NULL ) + continue; + if ( conns[i]->srvr->server == afs_setTimeHost ) { + tv.tv_sec = tv.tv_usec = 0; + results[i] = RXAFS_GetTime(rxconns[i], + (afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec); + end = osi_Time(); + if ((start == end) && !results[i]) + deltas[i] = end - tv.tv_sec; + break; + } + } + } + AFS_GLOCK(); + } for(i=0;icell->cellNum, SHARED_LOCK); + if ( !tu ) + return; + tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1, + SHARED_LOCK); + if ( !tc ) + return; + code = RXAFS_GetCapabilities(tc->id, &caps); + if ( code && code != RXGEN_OPCODE ) + afs_warn("RXAFS_GetCapabilities failed with code %d\n", code); + else + ts->flags |= SCAPS_KNOWN; + afs_PutConn(tc, SHARED_LOCK); + + if ( caps.Capabilities_len > 0 ) { + ts->capabilities = caps.Capabilities_val[0]; + xdr_free((xdrproc_t)xdr_Capabilities, &caps); + caps.Capabilities_len = 0; + caps.Capabilities_val = NULL; + } + +} + /* afs_GetServer() * Return an updated and properly initialized server structure * corresponding to the server ID, cell, and port specified. @@ -1823,6 +1919,9 @@ afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers, afs_int32 acell, afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords; } + if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN)) + afs_GetCapabilities(newts); + ReleaseWriteLock(&afs_xsrvAddr); ReleaseWriteLock(&afs_xserver); return (newts); -- 2.39.5