refactor afs_CheckServers
authorDerrick Brashear <shadow@dementia.org>
Wed, 1 Dec 2010 20:22:30 +0000 (15:22 -0500)
committerDerrick Brashear <shadow@dementia.org>
Mon, 13 Dec 2010 19:25:32 +0000 (11:25 -0800)
basically, we need the ability to reuse this function, so, let's make it work
differently so we can.

Change-Id: I41a7e1dc62feeb137f1a7f5c939f54cb59cc6c13
Reviewed-on: http://gerrit.openafs.org/3403
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

src/afs/afs.h
src/afs/afs_prototypes.h
src/afs/afs_server.c

index 13c68ca..6969831 100644 (file)
@@ -1330,6 +1330,11 @@ extern struct brequest afs_brs[NBRS];    /* request structures */
 #define IS_WLOCK 8
 #define FIND_CDEAD 16
 
+/* values for adown value of afs_LoopServers */
+#define AFS_LS_UP 0
+#define AFS_LS_DOWN 1
+#define AFS_LS_ALL 2
+
 /* values for flag param of afs_CheckVolumeNames */
 #define AFS_VOLCHECK_EXPIRED   0x1     /* volumes whose callbacks have expired */
 #define AFS_VOLCHECK_BUSY      0x2     /* volumes which were marked busy */
index 1327298..acf1d32 100644 (file)
@@ -844,6 +844,15 @@ extern void afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown);
 extern afs_int32 afs_ServerDown(struct srvAddr *sa);
 extern void afs_CountServers(void);
 extern void afs_CheckServers(int adown, struct cell *acellp);
+extern void afs_LoopServers(int adown, struct cell *acellp, int vlalso,
+                           void (*func1) (struct rx_connection **rxconns,
+                                          int nconns, int nservers,
+                                          struct afs_conn **conns,
+                                          struct srvAddr **addrs),
+                           void (*func2) (struct rx_connection **rxconns,
+                                          int nconns, int nservers,
+                                          struct afs_conn **conns,
+                                          struct srvAddr **addrs));
 extern unsigned int afs_random(void);
 extern int afs_randomMod15(void);
 extern int afs_randomMod127(void);
index 49dc24e..39925f9 100644 (file)
@@ -523,27 +523,254 @@ ForceAllNewConnections(void)
     }
 }
 
+static void
+CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
+{
+    struct srvAddr *sa;
+    struct afs_conn *tc;
+    afs_int32 i;
+
+    for(i = 0; i < nconns; i++){
+       tc = conns[i];
+       sa = tc->parent->srvr;
+
+       if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) &&
+           (tc->parent->srvr == sa)) {
+           /* server back up */
+           print_internet_address("afs: file server ", sa, " is back up", 2);
+
+           ObtainWriteLock(&afs_xserver, 244);
+           ObtainWriteLock(&afs_xsrvAddr, 245);
+           afs_MarkServerUpOrDown(sa, 0);
+           ReleaseWriteLock(&afs_xsrvAddr);
+           ReleaseWriteLock(&afs_xserver);
+
+           if (afs_waitForeverCount) {
+               afs_osi_Wakeup(&afs_waitForever);
+           }
+       } else {
+           if (results[i] < 0) {
+               /* server crashed */
+               afs_ServerDown(sa);
+               ForceNewConnections(sa);  /* multi homed clients */
+           }
+       }
+    }
+}
+
+void
+CkSrv_SetTime(struct rx_connection **rxconns, int nconns, int nservers,
+             struct afs_conn **conns, struct srvAddr **addrs)
+{
+    struct afs_conn *tc;
+    afs_int32 start, end = 0, delta;
+    osi_timeval_t tv;
+    struct srvAddr *sa;
+    afs_int32 *conntimer, *results, *deltas;
+    afs_int32 i = 0;
+    char tbuffer[CVBS];
+
+    conntimer = afs_osi_Alloc(nservers * sizeof (afs_int32));
+    osi_Assert(conntimer != NULL);
+    results = afs_osi_Alloc(nservers * sizeof (afs_int32));
+    osi_Assert(results != NULL);
+    deltas = afs_osi_Alloc(nservers * sizeof (afs_int32));
+    osi_Assert(deltas != NULL);
+
+    /* make sure we're starting from zero */
+    memset(&deltas, 0, sizeof(deltas));
+
+    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->parent->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 < nservers ; i++ ) {
+           if ( conns[i] == NULL || conns[i]->parent->srvr == NULL )
+               continue;
+           if ( conns[i]->parent->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();
+
+    if ( afs_setTimeHost == NULL )
+       CkSrv_MarkUpDown(conns, nconns, results);
+    else /* We lack info for other than this host */
+       CkSrv_MarkUpDown(&conns[i], 1, &results[i]);
+
+    /*
+     * If we're supposed to set the time, and the call worked
+     * quickly (same second response) and this is the host we
+     * use for the time and the time is really different, then
+     * really set the time
+     */
+    if (afs_setTime != 0) {
+       for (i=0; i<nconns; i++) {
+           delta = deltas[i];
+           tc = conns[i];
+           sa = tc->parent->srvr;
+
+           if ((tc->parent->srvr->server == afs_setTimeHost ||
+                /* Sync only to a server in the local cell */
+                (afs_setTimeHost == (struct server *)0 &&
+                 afs_IsPrimaryCell(sa->server->cell)))) {
+               /* set the time */
+               char msgbuf[90];  /* strlen("afs: setting clock...") + slop */
+               delta = end - tv.tv_sec;   /* how many secs fast we are */
+
+               afs_setTimeHost = tc->parent->srvr->server;
+               /* see if clock has changed enough to make it worthwhile */
+               if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
+                   end = osi_Time();
+                   if (delta > AFS_MAXCHANGEBACK) {
+                       /* setting clock too far back, just do it a little */
+                       tv.tv_sec = end - AFS_MAXCHANGEBACK;
+                   } else {
+                       tv.tv_sec = end - delta;
+                   }
+                   afs_osi_SetTime(&tv);
+                   if (delta > 0) {
+                       strcpy(msgbuf, "afs: setting clock back ");
+                       if (delta > AFS_MAXCHANGEBACK) {
+                           afs_strcat(msgbuf,
+                                      afs_cv2string(&tbuffer[CVBS],
+                                                    AFS_MAXCHANGEBACK));
+                           afs_strcat(msgbuf, " seconds (of ");
+                           afs_strcat(msgbuf,
+                                      afs_cv2string(&tbuffer[CVBS],
+                                                    delta -
+                                                    AFS_MAXCHANGEBACK));
+                           afs_strcat(msgbuf, ", via ");
+                           print_internet_address(msgbuf, sa,
+                                                  "); clock is still fast.",
+                                                  0);
+                       } else {
+                           afs_strcat(msgbuf,
+                                      afs_cv2string(&tbuffer[CVBS], delta));
+                           afs_strcat(msgbuf, " seconds (via ");
+                           print_internet_address(msgbuf, sa, ").", 0);
+                       }
+                   } else {
+                       strcpy(msgbuf, "afs: setting clock ahead ");
+                       afs_strcat(msgbuf,
+                                  afs_cv2string(&tbuffer[CVBS], -delta));
+                       afs_strcat(msgbuf, " seconds (via ");
+                       print_internet_address(msgbuf, sa, ").", 0);
+                   }
+                    /* We're only going to set it once; why bother looping? */
+                   break;
+               }
+           }
+       }
+    }
+    afs_osi_Free(conntimer, nservers * sizeof(afs_int32));
+    afs_osi_Free(deltas, nservers * sizeof(afs_int32));
+    afs_osi_Free(results, nservers * sizeof(afs_int32));
+}
+
+void
+CkSrv_GetCaps(struct rx_connection **rxconns, int nconns, int nservers,
+             struct afs_conn **conns, struct srvAddr **addrs)
+{
+    Capabilities *caps;
+    afs_int32 *results;
+    afs_int32 i;
+    struct server *ts;
+
+    caps = afs_osi_Alloc(nservers * sizeof (Capabilities));
+    osi_Assert(caps != NULL);
+    memset(caps, 0, nservers * sizeof(Capabilities));
+
+    results = afs_osi_Alloc(nservers * sizeof (afs_int32));
+    osi_Assert(results != NULL);
+
+    AFS_GUNLOCK();
+    multi_Rx(rxconns,nconns)
+      {
+       multi_RXAFS_GetCapabilities(&caps[multi_i]);
+       results[multi_i] = multi_error;
+      } multi_End;
+    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;
+           }
+    }
+    CkSrv_MarkUpDown(conns, nconns, results);
+
+    afs_osi_Free(caps, nservers * sizeof(Capabilities));
+    afs_osi_Free(results, nservers * sizeof(afs_int32));
+}
+
 /* check down servers (if adown), or running servers (if !adown) */
 void
 afs_CheckServers(int adown, struct cell *acellp)
 {
+    afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps,
+                   afs_setTime?CkSrv_SetTime:NULL);
+}
+
+/* adown: 0 - check only down. 1 - check only up. 2 - check all */
+void
+afs_LoopServers(int adown, struct cell *acellp, int vlalso,
+               void (*func1) (struct rx_connection **rxconns, int nconns,
+                              int nservers, struct afs_conn **conns,
+                              struct srvAddr **addrs),
+               void (*func2) (struct rx_connection **rxconns, int nconns,
+                              int nservers, struct afs_conn **conns,
+                              struct srvAddr **addrs))
+{
     struct vrequest treq;
     struct server *ts;
     struct srvAddr *sa;
-    struct afs_conn *tc;
+    struct afs_conn *tc = NULL;
     afs_int32 i, j;
     afs_int32 code;
-    afs_int32 start, end = 0, delta;
-    osi_timeval_t tv;
     struct unixuser *tu;
-    char tbuffer[CVBS];
     int srvAddrCount;
     struct srvAddr **addrs;
     struct afs_conn **conns;
     int nconns;
     struct rx_connection **rxconns;
-    afs_int32 *conntimer, *deltas, *results;
-    Capabilities *caps = NULL;
+    afs_int32 *conntimer, *results;
 
     AFS_STATCNT(afs_CheckServers);
 
@@ -591,17 +818,10 @@ afs_CheckServers(int adown, struct cell *acellp)
     osi_Assert(rxconns != NULL);
     conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
     osi_Assert(conntimer != NULL);
-    deltas = afs_osi_Alloc(j * sizeof (afs_int32));
-    osi_Assert(deltas != NULL);
     results = afs_osi_Alloc(j * sizeof (afs_int32));
     osi_Assert(results != NULL);
 
-    caps = afs_osi_Alloc(j * sizeof (Capabilities));
-    osi_Assert(caps != NULL);
-    memset(caps, 0, j * sizeof(Capabilities));
-
     for (i = 0; i < j; i++) {
-       deltas[i] = 0;
        sa = addrs[i];
        ts = sa->server;
        if (!ts)
@@ -613,13 +833,14 @@ afs_CheckServers(int adown, struct cell *acellp)
        if (acellp && acellp != ts->cell)
            continue;
 
-       if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
-           || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
+       if (((adown==AFS_LS_DOWN) && (sa->sa_flags & SRVADDR_ISDOWN))
+           || ((adown==AFS_LS_UP) && !(sa->sa_flags & SRVADDR_ISDOWN)))
            continue;
 
        /* check vlserver with special code */
        if (sa->sa_portal == AFS_VLPORT) {
-           CheckVLServer(sa, &treq);
+           if (vlalso)
+               CheckVLServer(sa, &treq);
            continue;
        }
 
@@ -648,164 +869,15 @@ afs_CheckServers(int adown, struct cell *acellp)
        }
     } /* Outer loop over addrs */
 
-    AFS_GUNLOCK();
-    multi_Rx(rxconns,nconns)
-      {
-       multi_RXAFS_GetCapabilities(&caps[multi_i]);
-       results[multi_i] = multi_error;
-      } multi_End;
-    AFS_GLOCK();
+    (*func1)(rxconns, nconns, j, conns, addrs);
 
-    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->parent->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]->parent->srvr == NULL )
-                   continue;
-               if ( conns[i]->parent->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];
-       sa = tc->parent->srvr;
-
-       if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->parent->srvr == sa)) {
-           /* server back up */
-           print_internet_address("afs: file server ", sa, " is back up", 2);
-
-           ObtainWriteLock(&afs_xserver, 244);
-           ObtainWriteLock(&afs_xsrvAddr, 245);
-           afs_MarkServerUpOrDown(sa, 0);
-           ReleaseWriteLock(&afs_xsrvAddr);
-           ReleaseWriteLock(&afs_xserver);
-
-           if (afs_waitForeverCount) {
-               afs_osi_Wakeup(&afs_waitForever);
-           }
-       } else {
-           if ((results[i] < 0) && (results[i] != RXGEN_OPCODE)) {
-               /* server crashed */
-               afs_ServerDown(sa);
-               ForceNewConnections(sa);  /* multi homed clients */
-           }
-       }
+    if (func2) {
+       (*func2)(rxconns, nconns, j, conns, addrs);
     }
 
-    /*
-     * If we're supposed to set the time, and the call worked
-     * quickly (same second response) and this is the host we
-     * use for the time and the time is really different, then
-     * really set the time
-     */
-    if (afs_setTime != 0) {
-       for (i=0; i<nconns; i++) {
-           delta = deltas[i];
-           tc = conns[i];
-           sa = tc->parent->srvr;
-
-           if ((tc->parent->srvr->server == afs_setTimeHost ||
-                /* Sync only to a server in the local cell */
-                (afs_setTimeHost == (struct server *)0 &&
-                 afs_IsPrimaryCell(sa->server->cell)))) {
-               /* set the time */
-               char msgbuf[90];  /* strlen("afs: setting clock...") + slop */
-               delta = end - tv.tv_sec;   /* how many secs fast we are */
-
-               afs_setTimeHost = tc->parent->srvr->server;
-               /* see if clock has changed enough to make it worthwhile */
-               if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
-                   end = osi_Time();
-                   if (delta > AFS_MAXCHANGEBACK) {
-                       /* setting clock too far back, just do it a little */
-                       tv.tv_sec = end - AFS_MAXCHANGEBACK;
-                   } else {
-                       tv.tv_sec = end - delta;
-                   }
-                   afs_osi_SetTime(&tv);
-                   if (delta > 0) {
-                       strcpy(msgbuf, "afs: setting clock back ");
-                       if (delta > AFS_MAXCHANGEBACK) {
-                           afs_strcat(msgbuf,
-                                      afs_cv2string(&tbuffer[CVBS],
-                                                    AFS_MAXCHANGEBACK));
-                           afs_strcat(msgbuf, " seconds (of ");
-                           afs_strcat(msgbuf,
-                                      afs_cv2string(&tbuffer[CVBS],
-                                                    delta -
-                                                    AFS_MAXCHANGEBACK));
-                           afs_strcat(msgbuf, ", via ");
-                           print_internet_address(msgbuf, sa,
-                                                  "); clock is still fast.",
-                                                  0);
-                       } else {
-                           afs_strcat(msgbuf,
-                                      afs_cv2string(&tbuffer[CVBS], delta));
-                           afs_strcat(msgbuf, " seconds (via ");
-                           print_internet_address(msgbuf, sa, ").", 0);
-                       }
-                   } else {
-                       strcpy(msgbuf, "afs: setting clock ahead ");
-                       afs_strcat(msgbuf,
-                                  afs_cv2string(&tbuffer[CVBS], -delta));
-                       afs_strcat(msgbuf, " seconds (via ");
-                       print_internet_address(msgbuf, sa, ").", 0);
-                   }
-                    /* We're only going to set it once; why bother looping? */
-                   break;
-               }
-           }
-       }
-    }
     for (i = 0; i < nconns; i++) {
+       if (conntimer[i] == 1)
+           rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
        afs_PutConn(conns[i], SHARED_LOCK);     /* done with it now */
     }
 
@@ -813,9 +885,7 @@ afs_CheckServers(int adown, struct cell *acellp)
     afs_osi_Free(conns, j * sizeof(struct afs_conn *));
     afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
     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*/