[OpenAFS-devel] Proposal for capabilities support in Unix client 1.4.x

Felix Frank Felix.Frank@Desy.de
Thu, 18 Jun 2009 16:06:11 +0200


This is a multi-part message in MIME format.
--------------060702040007040103060108
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

> Note that all servers are GetTime'd now in the case of a NULL 
> setTimeHost. Also, server pruning should be correct now (but if GetTime 
> ends up being completely replaced with GetCapabilities in the setTime == 
> 0 case, the pruning won't be necessary anyway - only three cases will 
> remain:
>  - setTime == 0 -> no GetTime whatsoever
>  - setTime == 1 && setTimeHost == NULL -> GetTime from all
>  - else GetTime for setTimeHost only)

There were no further objections, so that's what it now does.

Of course, the code could be restructured now to pick the setTimeHost 
earliert, but that's out of scope for this change imo.

Also, please note that RXGEN_OPCODE is (hopefully) handled correctly now.

Cheers
  - Felix

--------------060702040007040103060108
Content-Type: text/x-patch;
 name="unix-cm-fs-caps.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="unix-cm-fs-caps.patch"

diff --git a/src/afs/afs.h b/src/afs/afs.h
index 4cefbc4..4e21df7 100644
--- a/src/afs/afs.h
+++ b/src/afs/afs.h
@@ -376,6 +376,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)
@@ -407,6 +411,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 dd003f8..40c2d32 100644
--- a/src/afs/afs_callback.c
+++ b/src/afs/afs_callback.c
@@ -768,10 +768,11 @@ SRXAFSCB_InitCallBackState(struct rx_call *a_call)
 			ReleaseWriteLock(&afs_xcbhash);
 		    }
 		}
-	}
-
-
 
+	    /* capabilities need be requested again */
+	    ts->flags &= ~SCAPS_KNOWN;
+	}
+	
 	/* find any volumes residing on this server and flush their state */
 	{
 	    register struct volume *tv;
diff --git a/src/afs/afs_prototypes.h b/src/afs/afs_prototypes.h
index 0f8ceff..f6c17a1 100644
--- a/src/afs/afs_prototypes.h
+++ b/src/afs/afs_prototypes.h
@@ -698,6 +698,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 3e683c3..dda7f89 100644
--- a/src/afs/afs_server.c
+++ b/src/afs/afs_server.c
@@ -544,6 +544,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);
 
@@ -582,7 +583,10 @@ afs_CheckServers(int adown, struct cell *acellp)
     conntimer = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
     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];
@@ -631,24 +635,70 @@ 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(&tv.tv_sec, &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 )
+	    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(caps[i].Capabilities_val,
+			caps[i].Capabilities_len * sizeof(afs_int32));
+		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(&tv.tv_sec, &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 known setTimeHost */
+	    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], &tv.tv_sec, &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];
       sa = tc->srvr;
@@ -672,7 +722,6 @@ afs_CheckServers(int adown, struct cell *acellp)
 	  afs_ServerDown(sa);
 	  ForceNewConnections(sa);  /* multi homed clients */
 	}
-      }
     }
 
     /*
@@ -750,6 +799,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*/
 
@@ -1616,6 +1666,48 @@ void 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 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(caps.Capabilities_val, 
+			caps.Capabilities_len * sizeof(afs_int32));
+	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.
@@ -1625,7 +1717,8 @@ void afs_RemoveSrvAddr(struct srvAddr *sap) {
 struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
 			     afs_int32 acell, u_short aport,
 			     afs_int32 locktype, afsUUID * uuidp,
-			     afs_int32 addr_uniquifier) {
+			     afs_int32 addr_uniquifier)
+{
     struct server *oldts = 0, *ts, *newts, *orphts = 0;
     struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
     u_short fsport;
@@ -1819,6 +1912,9 @@ struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
 	    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);
diff --git a/src/libafsrpc/afsrpc.def b/src/libafsrpc/afsrpc.def
index cd75567..3c0f173 100644
--- a/src/libafsrpc/afsrpc.def
+++ b/src/libafsrpc/afsrpc.def
@@ -217,5 +217,6 @@ EXPORTS
 	rxkad_stats_key				@222 DATA
 	rx_InitHost				@224
 	rx_NewServiceHost			@225
+	xdr_free                                @252
         
 
diff --git a/src/rx/xdr.c b/src/rx/xdr.c
index 1a01bab..3de1467 100644
--- a/src/rx/xdr.c
+++ b/src/rx/xdr.c
@@ -583,4 +583,10 @@ xdr_wrapstring(register XDR * xdrs, char **cpp)
     return (FALSE);
 }
 #endif
+
+void 
+xdr_free(void *x, afs_int32 size)
+{
+    osi_free(x, size);
+}
 #endif /* NeXT */
diff --git a/src/rx/xdr_prototypes.h b/src/rx/xdr_prototypes.h
index 5c1898e..e36ddd4 100644
--- a/src/rx/xdr_prototypes.h
+++ b/src/rx/xdr_prototypes.h
@@ -58,6 +58,7 @@ extern bool_t xdr_union(register XDR * xdrs, enum_t * dscmp, caddr_t unp,
 			struct xdr_discrim *choices, xdrproc_t dfault);
 extern bool_t xdr_string(register XDR * xdrs, char **cpp, u_int maxsize);
 extern bool_t xdr_wrapstring(register XDR * xdrs, char **cpp);
+extern void   xdr_free(void *x, afs_int32 size);
 
 
 /* xdr_float.c */

--------------060702040007040103060108--