afs-checkservers-improve-lock-granularity-20011102

work harder to release afs_xserver and afs_xsrvAddr locks in afs_CheckServers
when not needed
This commit is contained in:
Nickolai Zeldovich 2001-11-02 08:07:58 +00:00 committed by Derrick Brashear
parent 9cbe95a1af
commit ea77b04c29

View File

@ -504,13 +504,15 @@ void afs_CheckServers(adown, acellp)
struct server *ts; struct server *ts;
struct srvAddr *sa; struct srvAddr *sa;
struct conn *tc; struct conn *tc;
afs_int32 i; afs_int32 i, j;
afs_int32 code; afs_int32 code;
afs_int32 start, end, delta; afs_int32 start, end, delta;
osi_timeval_t tv; osi_timeval_t tv;
int setTimer; int setTimer;
struct unixuser *tu; struct unixuser *tu;
char tbuffer[CVBS]; char tbuffer[CVBS];
int srvAddrCount;
struct srvAddr **addrs;
XSTATS_DECLS; XSTATS_DECLS;
AFS_STATCNT(afs_CheckServers); AFS_STATCNT(afs_CheckServers);
@ -518,128 +520,152 @@ void afs_CheckServers(adown, acellp)
ObtainReadLock(&afs_xserver); /* Necessary? */ ObtainReadLock(&afs_xserver); /* Necessary? */
ObtainReadLock(&afs_xsrvAddr); ObtainReadLock(&afs_xsrvAddr);
srvAddrCount = 0;
for (i=0;i<NSERVERS;i++) { for (i=0;i<NSERVERS;i++) {
for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) { for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
ts = sa->server; srvAddrCount++;
if (!ts) }
continue; }
/* See if a cell to check was specified. If it is spec'd and not
* this server's cell, just skip the server.
*/
if (acellp && acellp != ts->cell)
continue;
if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN)) addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
|| (adown && !(sa->sa_flags & SRVADDR_ISDOWN))) j = 0;
continue; for (i=0;i<NSERVERS;i++) {
/* check vlserver with special code */ for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
if (sa->sa_portal == AFS_VLPORT) { if (j >= srvAddrCount) break;
CheckVLServer(sa, &treq); addrs[j++] = sa;
continue; }
} }
if (!ts->cell) /* not really an active server, anyway, it must */ ReleaseReadLock(&afs_xsrvAddr);
continue; /* have just been added by setsprefs */ ReleaseReadLock(&afs_xserver);
/* get a connection, even if host is down; bumps conn ref count */
tu = afs_GetUser(treq.uid, ts->cell, SHARED_LOCK);
tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cell, tu,
1/*force*/, 1/*create*/, SHARED_LOCK);
afs_PutUser(tu, SHARED_LOCK);
if (!tc)
continue;
if ((sa->sa_flags & SRVADDR_ISDOWN) || HaveCallBacksFrom(ts) || for (i=0; i<j; i++) {
(tc->srvr->server == afs_setTimeHost)) { sa = addrs[i];
if (sa->sa_flags & SRVADDR_ISDOWN) { ts = sa->server;
if (!ts)
continue;
/* See if a cell to check was specified. If it is spec'd and not
* this server's cell, just skip the server.
*/
if (acellp && acellp != ts->cell)
continue;
if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN)) ||
(adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
continue;
/* check vlserver with special code */
if (sa->sa_portal == AFS_VLPORT) {
CheckVLServer(sa, &treq);
continue;
}
if (!ts->cell) /* not really an active server, anyway, it must */
continue; /* have just been added by setsprefs */
/* get a connection, even if host is down; bumps conn ref count */
tu = afs_GetUser(treq.uid, ts->cell, SHARED_LOCK);
tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cell, tu,
1/*force*/, 1/*create*/, SHARED_LOCK);
afs_PutUser(tu, SHARED_LOCK);
if (!tc) continue;
if ((sa->sa_flags & SRVADDR_ISDOWN) || HaveCallBacksFrom(ts) ||
(tc->srvr->server == afs_setTimeHost)) {
if (sa->sa_flags & SRVADDR_ISDOWN) {
rx_SetConnDeadTime(tc->id, 3); rx_SetConnDeadTime(tc->id, 3);
setTimer = 1; setTimer = 1;
} else } else {
setTimer = 0; setTimer = 0;
XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETTIME); }
start = osi_Time(); /* time the gettimeofday call */
XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETTIME);
start = osi_Time(); /* time the gettimeofday call */
#ifdef RX_ENABLE_LOCKS #ifdef RX_ENABLE_LOCKS
AFS_GUNLOCK(); AFS_GUNLOCK();
#endif /* RX_ENABLE_LOCKS */ #endif /* RX_ENABLE_LOCKS */
code = RXAFS_GetTime(tc->id, &tv.tv_sec, &tv.tv_usec); code = RXAFS_GetTime(tc->id, &tv.tv_sec, &tv.tv_usec);
#ifdef RX_ENABLE_LOCKS #ifdef RX_ENABLE_LOCKS
AFS_GLOCK(); AFS_GLOCK();
#endif /* RX_ENABLE_LOCKS */ #endif /* RX_ENABLE_LOCKS */
end = osi_Time(); end = osi_Time();
XSTATS_END_TIME; XSTATS_END_TIME;
/* /*
* If we're supposed to set the time, and the call worked * If we're supposed to set the time, and the call worked
* quickly (same second response) and this is the host we * quickly (same second response) and this is the host we
* use for the time and the time is really different, then * use for the time and the time is really different, then
* really set the time * really set the time
*/ */
if (code == 0 && start == end && afs_setTime != 0 && if (code == 0 && start == end && afs_setTime != 0 &&
(tc->srvr->server == afs_setTimeHost || (tc->srvr->server == afs_setTimeHost ||
/* /*
* Sync only to a server in the local cell: cell(id)==1 * Sync only to a server in the local cell: cell(id)==1
* or CPrimary. * or CPrimary.
*/ */
(afs_setTimeHost == (struct server *)0 && (afs_setTimeHost == (struct server *)0 &&
(ts->cell->cell == 1 || (ts->cell->states&CPrimary))))) { (ts->cell->cell == 1 || (ts->cell->states&CPrimary))))) {
char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
/* set the time */ /* set the time */
delta = end - tv.tv_sec; /* how many secs fast we are */ delta = end - tv.tv_sec; /* how many secs fast we are */
/* see if clock has changed enough to make it worthwhile */ /* see if clock has changed enough to make it worthwhile */
if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) { if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
if (delta > AFS_MAXCHANGEBACK) { if (delta > AFS_MAXCHANGEBACK) {
/* setting clock too far back, just do it a little */ /* setting clock too far back, just do it a little */
tv.tv_sec = end - AFS_MAXCHANGEBACK; tv.tv_sec = end - AFS_MAXCHANGEBACK;
} }
afs_osi_SetTime(&tv); afs_osi_SetTime(&tv);
if (delta > 0) { if (delta > 0) {
strcpy(msgbuf, "afs: setting clock back "); strcpy(msgbuf, "afs: setting clock back ");
if (delta > AFS_MAXCHANGEBACK) { if (delta > AFS_MAXCHANGEBACK) {
afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], AFS_MAXCHANGEBACK)); afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], AFS_MAXCHANGEBACK));
afs_strcat(msgbuf, " seconds (of "); afs_strcat(msgbuf, " seconds (of ");
afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], delta - AFS_MAXCHANGEBACK)); afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], delta - AFS_MAXCHANGEBACK));
afs_strcat(msgbuf, ", via "); afs_strcat(msgbuf, ", via ");
print_internet_address(msgbuf, sa, "); clock is still fast.", 0); print_internet_address(msgbuf, sa, "); clock is still fast.", 0);
} else { } else {
afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], delta)); afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], delta));
afs_strcat(msgbuf, " seconds (via "); afs_strcat(msgbuf, " seconds (via ");
print_internet_address(msgbuf, sa, ").", 0); print_internet_address(msgbuf, sa, ").", 0);
} }
} } else {
else { strcpy(msgbuf, "afs: setting clock ahead ");
strcpy(msgbuf, "afs: setting clock ahead "); afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], -delta));
afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], -delta)); afs_strcat(msgbuf, " seconds (via ");
afs_strcat(msgbuf, " seconds (via "); print_internet_address(msgbuf, sa, ").", 0);
print_internet_address(msgbuf, sa, ").", 0); }
}
} }
afs_setTimeHost = tc->srvr->server; afs_setTimeHost = tc->srvr->server;
} }
if (setTimer) if (setTimer)
rx_SetConnDeadTime(tc->id, 50); rx_SetConnDeadTime(tc->id, 50);
if (code >= 0 && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) { if (code >= 0 && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
/* server back up */ /* server back up */
print_internet_address("afs: file server ", sa, " is back up", 2); print_internet_address("afs: file server ", sa, " is back up", 2);
/*
* XXX We should hold a server write lock here XXX
*/
afs_MarkServerUpOrDown(sa, 0);
if (afs_waitForeverCount) {
afs_osi_Wakeup(&afs_waitForever);
}
}
else
if (code < 0) {
/* server crashed */
afs_ServerDown(sa);
ForceNewConnections(sa); /* multi homed clients */
}
}
afs_PutConn(tc, SHARED_LOCK); /* done with it now */ ObtainWriteLock(&afs_xserver, 244);
} /* for each server loop */ ObtainWriteLock(&afs_xsrvAddr, 245);
} /* for each server hash bucket loop */ afs_MarkServerUpOrDown(sa, 0);
ReleaseReadLock(&afs_xsrvAddr); ReleaseWriteLock(&afs_xsrvAddr);
ReleaseReadLock(&afs_xserver); ReleaseWriteLock(&afs_xserver);
if (afs_waitForeverCount) {
afs_osi_Wakeup(&afs_waitForever);
}
} else {
if (code < 0) {
/* server crashed */
afs_ServerDown(sa);
ForceNewConnections(sa); /* multi homed clients */
}
}
}
afs_PutConn(tc, SHARED_LOCK); /* done with it now */
} /* Outer loop over addrs */
afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
} /*afs_CheckServers*/ } /*afs_CheckServers*/