]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Fileserver capabilities support for the UNIX client
authorFelix Frank <Felix.Frank@Desy.de>
Thu, 4 Mar 2010 03:41:15 +0000 (22:41 -0500)
committerDerrick Brashear <shadow@dementia.org>
Tue, 13 Apr 2010 11:30:25 +0000 (04:30 -0700)
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 <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
src/afs/afs.h
src/afs/afs_callback.c
src/afs/afs_prototypes.h
src/afs/afs_server.c

index 1b2ab15f55558e0dee8d04eca5c7becbf8f131d1..d4da4f8125f8abf1b66937c9dc54a56af9c8829a 100644 (file)
@@ -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)
index b8373bb55b4ac0c22af4475d212d762df8f91b7d..674bb867a51896b5c2cfb1f746779857031f8d3f 100644 (file)
@@ -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);
        }
 
 
index d4dc7fcfe4a0893ee22a78edd52e334f208b62b0..cbaef5b43b8d02e9da4a3004ee4e5d6ef5601d86 100644 (file)
@@ -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);
index 8dfd2f12cb6ee2b537ffec02ce0e932461b1dc31..01e81a4af1cedcce7fce55395dba24acfabe61e0 100644 (file)
@@ -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;i<nconns;i++){
       tc = conns[i];
@@ -755,6 +808,7 @@ afs_CheckServers(int adown, struct cell *acellp)
     afs_osi_Free(conntimer, j * sizeof(afs_int32));
     afs_osi_Free(deltas, j * sizeof(afs_int32));
     afs_osi_Free(results, j * sizeof(afs_int32));
+    afs_osi_Free(caps, j * sizeof(Capabilities));
     
 } /*afs_CheckServers*/
 
@@ -1623,6 +1677,48 @@ afs_RemoveSrvAddr(struct srvAddr *sap)
     }
 }
 
+/* afs_GetCapabilities
+ * Try and retrieve capabilities of a given file server. Carps on actual
+ * failure. Servers are not expected to support this RPC. */
+void
+afs_GetCapabilities(struct server *ts)
+{
+    Capabilities caps = {0, NULL};
+    struct vrequest treq;
+    struct afs_conn *tc;
+    struct unixuser *tu;
+    afs_int32 code;
+
+    if ( !ts )
+       return;
+    if ( !afs_osi_credp )
+       return;
+
+    if ((code = afs_InitReq(&treq, afs_osi_credp)))
+       return;
+    tu = afs_GetUser(treq.uid, ts->cell->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);