initialize-variables-to-avoid-logic-issues-20081027
[openafs.git] / src / afs / afs_analyze.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Implements:
12  */
13 #include <afsconfig.h>
14 #include "afs/param.h"
15
16 RCSID
17     ("$Header$");
18
19 #include "afs/stds.h"
20 #include "afs/sysincludes.h"    /* Standard vendor system headers */
21
22 #ifndef UKERNEL
23 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD_ENV)
24 #include <net/if.h>
25 #include <netinet/in.h>
26 #endif
27
28 #ifdef AFS_SGI62_ENV
29 #include "h/hashing.h"
30 #endif
31 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD_ENV) && !defined(AFS_DARWIN60_ENV)
32 #include <netinet/in_var.h>
33 #endif
34 #endif /* !UKERNEL */
35
36 #include "afsincludes.h"        /* Afs-based standard headers */
37 #include "afs/afs_stats.h"      /* afs statistics */
38 #include "afs/afs_util.h"
39 #include "afs/unified_afs.h"
40
41 #if     defined(AFS_SUN56_ENV)
42 #include <inet/led.h>
43 #include <inet/common.h>
44 #if     defined(AFS_SUN58_ENV)
45 #include <netinet/ip6.h>
46 #endif
47 #include <inet/ip.h>
48 #endif
49
50
51 /* shouldn't do it this way, but for now will do */
52 #ifndef ERROR_TABLE_BASE_U
53 #define ERROR_TABLE_BASE_U      (5376L)
54 #endif /* ubik error base define */
55
56 /* shouldn't do it this way, but for now will do */
57 #ifndef ERROR_TABLE_BASE_uae
58 #define ERROR_TABLE_BASE_uae    (49733376L)
59 #endif /* unified afs error base define */
60
61 /* same hack for vlserver error base as for ubik error base */
62 #ifndef ERROR_TABLE_BASE_VL
63 #define ERROR_TABLE_BASE_VL     (363520L)
64 #define VL_NOENT                (363524L)
65 #endif /* vlserver error base define */
66
67
68 int afs_BusyWaitPeriod = 15;    /* poll every 15 seconds */
69
70 afs_int32 hm_retry_RO = 0;      /* don't wait */
71 afs_int32 hm_retry_RW = 0;      /* don't wait */
72 afs_int32 hm_retry_int = 0;     /* don't wait */
73
74 #define VSleep(at)      afs_osi_Wait((at)*1000, 0, 0)
75
76
77 int lastcode;
78 /* returns:
79  * 0   if the vldb record for a specific volume is different from what
80  *     we have cached -- perhaps the volume has moved.
81  * 1   if the vldb record is the same
82  * 2   if we can't tell if it's the same or not. 
83  *
84  * If 0, the caller will probably start over at the beginning of our
85  * list of servers for this volume and try to find one that is up.  If
86  * not 0, we will probably just keep plugging with what we have
87  * cached.   If we fail to contact the VL server, we  should just keep
88  * trying with the information we have, rather than failing. */
89 #define DIFFERENT 0
90 #define SAME 1
91 #define DUNNO 2
92 static int
93 VLDB_Same(struct VenusFid *afid, struct vrequest *areq)
94 {
95     struct vrequest treq;
96     struct conn *tconn;
97     int i, type = 0;
98     union {
99         struct vldbentry tve;
100         struct nvldbentry ntve;
101         struct uvldbentry utve;
102     } *v;
103     struct volume *tvp;
104     struct cell *tcell;
105     char *bp, tbuf[CVBS];       /* biggest volume id is 2^32, ~ 4*10^9 */
106     unsigned int changed;
107     struct server *(oldhosts[NMAXNSERVERS]);
108
109     AFS_STATCNT(CheckVLDB);
110     afs_FinalizeReq(areq);
111
112     if ((i = afs_InitReq(&treq, afs_osi_credp)))
113         return DUNNO;
114     v = afs_osi_Alloc(sizeof(*v));
115     tcell = afs_GetCell(afid->Cell, READ_LOCK);
116     bp = afs_cv2string(&tbuf[CVBS], afid->Fid.Volume);
117     do {
118         VSleep(2);              /* Better safe than sorry. */
119         tconn =
120             afs_ConnByMHosts(tcell->cellHosts, tcell->vlport, tcell->cellNum,
121                              &treq, SHARED_LOCK);
122         if (tconn) {
123             if (tconn->srvr->server->flags & SNO_LHOSTS) {
124                 type = 0;
125                 RX_AFS_GUNLOCK();
126                 i = VL_GetEntryByNameO(tconn->id, bp, &v->tve);
127                 RX_AFS_GLOCK();
128             } else if (tconn->srvr->server->flags & SYES_LHOSTS) {
129                 type = 1;
130                 RX_AFS_GUNLOCK();
131                 i = VL_GetEntryByNameN(tconn->id, bp, &v->ntve);
132                 RX_AFS_GLOCK();
133             } else {
134                 type = 2;
135                 RX_AFS_GUNLOCK();
136                 i = VL_GetEntryByNameU(tconn->id, bp, &v->utve);
137                 RX_AFS_GLOCK();
138                 if (!(tconn->srvr->server->flags & SVLSRV_UUID)) {
139                     if (i == RXGEN_OPCODE) {
140                         type = 1;
141                         RX_AFS_GUNLOCK();
142                         i = VL_GetEntryByNameN(tconn->id, bp, &v->ntve);
143                         RX_AFS_GLOCK();
144                         if (i == RXGEN_OPCODE) {
145                             type = 0;
146                             tconn->srvr->server->flags |= SNO_LHOSTS;
147                             RX_AFS_GUNLOCK();
148                             i = VL_GetEntryByNameO(tconn->id, bp, &v->tve);
149                             RX_AFS_GLOCK();
150                         } else if (!i)
151                             tconn->srvr->server->flags |= SYES_LHOSTS;
152                     } else if (!i)
153                         tconn->srvr->server->flags |= SVLSRV_UUID;
154                 }
155                 lastcode = i;
156             }
157         } else
158             i = -1;
159     } while (afs_Analyze(tconn, i, NULL, &treq, -1,     /* no op code for this */
160                          SHARED_LOCK, tcell));
161
162     afs_PutCell(tcell, READ_LOCK);
163     afs_Trace2(afs_iclSetp, CM_TRACE_CHECKVLDB, ICL_TYPE_FID, &afid,
164                ICL_TYPE_INT32, i);
165
166     if (i) {
167         afs_osi_Free(v, sizeof(*v));
168         return DUNNO;
169     }
170     /* have info, copy into serverHost array */
171     changed = 0;
172     tvp = afs_FindVolume(afid, WRITE_LOCK);
173     if (tvp) {
174         ObtainWriteLock(&tvp->lock, 107);
175         for (i = 0; i < NMAXNSERVERS && tvp->serverHost[i]; i++) {
176             oldhosts[i] = tvp->serverHost[i];
177         }
178
179         if (type == 2) {
180             InstallUVolumeEntry(tvp, &v->utve, afid->Cell, tcell, &treq);
181         } else if (type == 1) {
182             InstallNVolumeEntry(tvp, &v->ntve, afid->Cell);
183         } else {
184             InstallVolumeEntry(tvp, &v->tve, afid->Cell);
185         }
186
187         if (i < NMAXNSERVERS && tvp->serverHost[i]) {
188             changed = 1;
189         }
190         for (--i; !changed && i >= 0; i--) {
191             if (tvp->serverHost[i] != oldhosts[i]) {
192                 changed = 1;    /* also happens if prefs change.  big deal. */
193             }
194         }
195
196         ReleaseWriteLock(&tvp->lock);
197         afs_PutVolume(tvp, WRITE_LOCK);
198     } else {                    /* can't find volume */
199         tvp = afs_GetVolume(afid, &treq, WRITE_LOCK);
200         if (tvp) {
201             afs_PutVolume(tvp, WRITE_LOCK);
202             afs_osi_Free(v, sizeof(*v));
203             return DIFFERENT;
204         } else {
205             afs_osi_Free(v, sizeof(*v));
206             return DUNNO;
207         }
208     }
209
210     afs_osi_Free(v, sizeof(*v));
211     return (changed ? DIFFERENT : SAME);
212 }                               /*VLDB_Same */
213
214 /*------------------------------------------------------------------------
215  * afs_BlackListOnce
216  *
217  * Description:
218  *      Mark a server as invalid for further attempts of this request only.
219  *
220  * Arguments:
221  *      areq  : The request record associated with this operation.
222  *      afid  : The FID of the file involved in the action.  This argument
223  *              may be null if none was involved.
224  *      tsp   : pointer to a server struct for the server we wish to 
225  *              blacklist. 
226  *
227  * Returns:
228  *      Non-zero value if further servers are available to try,
229  *      zero otherwise.
230  *
231  * Environment:
232  *      This routine is typically called in situations where we believe
233  *      one server out of a pool may have an error condition.
234  *
235  * Side Effects:
236  *      As advertised.
237  *
238  * NOTE:
239  *      The afs_Conn* routines use the list of invalidated servers to 
240  *      avoid reusing a server marked as invalid for this request.
241  *------------------------------------------------------------------------*/
242 static afs_int32 
243 afs_BlackListOnce(struct vrequest *areq, struct VenusFid *afid, 
244                   struct server *tsp)
245 {
246     struct volume *tvp;
247     afs_int32 i;
248     afs_int32 serversleft = 0;
249
250     if (afid) {
251         tvp = afs_FindVolume(afid, READ_LOCK);
252         if (tvp) {
253             for (i = 0; i < MAXHOSTS; i++) {
254                 if (tvp->serverHost[i] == tsp) {
255                     areq->skipserver[i] = 1;
256                 }
257                 if (tvp->serverHost[i] &&
258                     (tvp->serverHost[i]->addr->sa_flags & 
259                       SRVR_ISDOWN)) {
260                     areq->skipserver[i] = 1;
261                 }
262             }
263             afs_PutVolume(tvp, READ_LOCK);
264             for (i = 0; i < MAXHOSTS; i++) {
265                 if (tvp->serverHost[i] && areq->skipserver[i] == 0) {
266                     serversleft = 1;
267                     break;
268                 }
269             }
270             return serversleft;
271         }
272     }
273     return 1;
274 }
275
276
277 /*------------------------------------------------------------------------
278  * EXPORTED afs_Analyze
279  *
280  * Description:
281  *      Analyze the outcome of an RPC operation, taking whatever support
282  *      actions are necessary.
283  *
284  * Arguments:
285  *      aconn : Ptr to the relevant connection on which the call was made.
286  *      acode : The return code experienced by the RPC.
287  *      afid  : The FID of the file involved in the action.  This argument
288  *              may be null if none was involved.
289  *      areq  : The request record associated with this operation.
290  *      op    : which RPC we are analyzing.
291  *      cellp : pointer to a cell struct.  Must provide either fid or cell.
292  *
293  * Returns:
294  *      Non-zero value if the related RPC operation should be retried,
295  *      zero otherwise.
296  *
297  * Environment:
298  *      This routine is typically called in a do-while loop, causing the
299  *      embedded RPC operation to be called repeatedly if appropriate
300  *      until whatever error condition (if any) is intolerable.
301  *
302  * Side Effects:
303  *      As advertised.
304  *
305  * NOTE:
306  *      The retry return value is used by afs_StoreAllSegments to determine
307  *      if this is a temporary or permanent error.
308  *------------------------------------------------------------------------*/
309 int
310 afs_Analyze(register struct conn *aconn, afs_int32 acode,
311             struct VenusFid *afid, register struct vrequest *areq, int op,
312             afs_int32 locktype, struct cell *cellp)
313 {
314     afs_int32 i;
315     struct srvAddr *sa;
316     struct server *tsp;
317     struct volume *tvp;
318     afs_int32 shouldRetry = 0;
319     afs_int32 serversleft = 1;
320     struct afs_stats_RPCErrors *aerrP;
321     afs_int32 markeddown;
322
323  
324  
325     if (AFS_IS_DISCONNECTED && !AFS_IN_SYNC) {
326         /* On reconnection, act as connected. XXX: for now.... */
327         /* SXW - This may get very tired after a while. We should try and
328          *       intercept all RPCs before they get here ... */
329         /*printf("afs_Analyze: disconnected\n");*/
330         afs_FinalizeReq(areq);
331         if (aconn) {
332             /* SXW - I suspect that this will _never_ happen - we shouldn't
333              *       get a connection because we're disconnected !!!*/
334             afs_PutConn(aconn, locktype);
335         }
336         return 0;
337     }
338     
339     AFS_STATCNT(afs_Analyze);
340     afs_Trace4(afs_iclSetp, CM_TRACE_ANALYZE, ICL_TYPE_INT32, op,
341                ICL_TYPE_POINTER, aconn, ICL_TYPE_INT32, acode, ICL_TYPE_LONG,
342                areq->uid);
343
344     aerrP = (struct afs_stats_RPCErrors *)0;
345
346     if ((op >= 0) && (op < AFS_STATS_NUM_FS_RPC_OPS))
347         aerrP = &(afs_stats_cmfullperf.rpc.fsRPCErrors[op]);
348
349     afs_FinalizeReq(areq);
350     if (!aconn && areq->busyCount) {    /* one RPC or more got VBUSY/VRESTARTING */
351
352         tvp = afs_FindVolume(afid, READ_LOCK);
353         if (tvp) {
354             afs_warnuser("afs: Waiting for busy volume %u (%s) in cell %s\n",
355                          (afid ? afid->Fid.Volume : 0),
356                          (tvp->name ? tvp->name : ""),
357                          ((tvp->serverHost[0]
358                            && tvp->serverHost[0]->cell) ? tvp->serverHost[0]->
359                           cell->cellName : ""));
360
361             for (i = 0; i < MAXHOSTS; i++) {
362                 if (tvp->status[i] != not_busy && tvp->status[i] != offline) {
363                     tvp->status[i] = not_busy;
364                 }
365                 if (tvp->status[i] == not_busy)
366                     shouldRetry = 1;
367             }
368             afs_PutVolume(tvp, READ_LOCK);
369         } else {
370             afs_warnuser("afs: Waiting for busy volume %u\n",
371                          (afid ? afid->Fid.Volume : 0));
372         }
373
374         if (areq->busyCount > 100) {
375             if (aerrP)
376                 (aerrP->err_Volume)++;
377             areq->volumeError = VOLBUSY;
378             shouldRetry = 0;
379         } else {
380             VSleep(afs_BusyWaitPeriod); /* poll periodically */
381         }
382         if (shouldRetry != 0)
383             areq->busyCount++;
384
385         return shouldRetry;     /* should retry */
386     }
387
388     if (!aconn || !aconn->srvr) {
389         if (!areq->volumeError) {
390             if (aerrP)
391                 (aerrP->err_Network)++;
392             if (hm_retry_int && !(areq->flags & O_NONBLOCK) &&  /* "hard" mount */
393                 ((afid && afs_IsPrimaryCellNum(afid->Cell))
394                  || (cellp && afs_IsPrimaryCell(cellp)))) {
395                 if (!afid) {
396                     afs_warnuser
397                         ("afs: hard-mount waiting for a vlserver to return to service\n");
398                     VSleep(hm_retry_int);
399                     afs_CheckServers(1, cellp);
400                     shouldRetry = 1;
401                 } else {
402                     tvp = afs_FindVolume(afid, READ_LOCK);
403                     if (!tvp || (tvp->states & VRO)) {
404                         shouldRetry = hm_retry_RO;
405                     } else {
406                         shouldRetry = hm_retry_RW;
407                     }
408                     if (tvp)
409                         afs_PutVolume(tvp, READ_LOCK);
410                     if (shouldRetry) {
411                         afs_warnuser
412                             ("afs: hard-mount waiting for volume %u\n",
413                              afid->Fid.Volume);
414                         VSleep(hm_retry_int);
415                         afs_CheckServers(1, cellp);
416                     }
417                 }
418             } /* if (hm_retry_int ... */
419             else {
420                 areq->networkError = 1;
421             }
422         }
423         return shouldRetry;
424     }
425
426     /* Find server associated with this connection. */
427     sa = aconn->srvr;
428     tsp = sa->server;
429
430     /* Before we do anything with acode, make sure we translate it back to
431      * a system error */
432     if ((acode & ~0xff) == ERROR_TABLE_BASE_uae)
433         acode = et_to_sys_error(acode);
434
435     if (acode == 0) {
436         /* If we previously took an error, mark this volume not busy */
437         if (areq->volumeError) {
438             tvp = afs_FindVolume(afid, READ_LOCK);
439             if (tvp) {
440                 for (i = 0; i < MAXHOSTS; i++) {
441                     if (tvp->serverHost[i] == tsp) {
442                         tvp->status[i] = not_busy;
443                     }
444                 }
445                 afs_PutVolume(tvp, READ_LOCK);
446             }
447         }
448
449         afs_PutConn(aconn, locktype);
450         return 0;
451     }
452
453     /* If network troubles, mark server as having bogued out again. */
454     /* VRESTARTING is < 0 because of backward compatibility issues 
455      * with 3.4 file servers and older cache managers */
456 #ifdef AFS_64BIT_CLIENT
457     if (acode == -455)
458         acode = 455;
459 #endif /* AFS_64BIT_CLIENT */
460     if ((acode < 0) && (acode != VRESTARTING)) {
461         if (acode == RX_CALL_TIMEOUT) {
462             serversleft = afs_BlackListOnce(areq, afid, tsp);
463             areq->idleError++;
464             if (serversleft) {
465                 shouldRetry = 1;
466             } else {
467                 shouldRetry = 0;
468             }
469             /* By doing this, we avoid ever marking a server down
470              * in an idle timeout case. That's because the server is 
471              * still responding and may only be letting a single vnode
472              * time out. We otherwise risk having the server continually
473              * be marked down, then up, then down again... 
474              */
475             goto out;
476         } 
477         markeddown = afs_ServerDown(sa);
478         ForceNewConnections(sa); /**multi homed clients lock:afs_xsrvAddr? */
479         if (aerrP)
480             (aerrP->err_Server)++;
481 #if 0
482         /* retry *once* when the server is timed out in case of NAT */
483         if (markeddown && acode == RX_CALL_DEAD) {
484             aconn->forceConnectFS = 1;
485             shouldRetry = 1;
486         }
487 #endif
488     }
489
490     if (acode == VBUSY || acode == VRESTARTING) {
491         if (acode == VBUSY) {
492             areq->busyCount++;
493             if (aerrP)
494                 (aerrP->err_VolumeBusies)++;
495         } else
496             areq->busyCount = 1;
497
498         tvp = afs_FindVolume(afid, READ_LOCK);
499         if (tvp) {
500             for (i = 0; i < MAXHOSTS; i++) {
501                 if (tvp->serverHost[i] == tsp) {
502                     tvp->status[i] = rdwr_busy; /* can't tell which yet */
503                     /* to tell which, have to look at the op code. */
504                 }
505             }
506             afs_PutVolume(tvp, READ_LOCK);
507         } else {
508             afs_warnuser("afs: Waiting for busy volume %u in cell %s\n",
509                          (afid ? afid->Fid.Volume : 0), tsp->cell->cellName);
510             VSleep(afs_BusyWaitPeriod); /* poll periodically */
511         }
512         shouldRetry = 1;
513         acode = 0;
514     } else if (acode == VICETOKENDEAD
515                || (acode & ~0xff) == ERROR_TABLE_BASE_RXK) {
516         /* any rxkad error is treated as token expiration */
517         struct unixuser *tu;
518         /*
519          * I'm calling these errors protection errors, since they involve
520          * faulty authentication.
521          */
522         if (aerrP)
523             (aerrP->err_Protection)++;
524
525         tu = afs_FindUser(areq->uid, tsp->cell->cellNum, READ_LOCK);
526         if (tu) {
527             if (acode == VICETOKENDEAD) {
528                 aconn->forceConnectFS = 1;
529             } else if (acode == RXKADEXPIRED) {
530                 aconn->forceConnectFS = 0;      /* don't check until new tokens set */
531                 aconn->user->states |= UTokensBad;
532                 afs_warnuser
533                     ("afs: Tokens for user of AFS id %d for cell %s have expired\n",
534                      tu->vid, aconn->srvr->server->cell->cellName);
535             } else {
536                 serversleft = afs_BlackListOnce(areq, afid, tsp);
537                 areq->tokenError++;
538
539                 if (serversleft) {
540                     afs_warnuser
541                         ("afs: Tokens for user of AFS id %d for cell %s: rxkad error=%d\n",
542                          tu->vid, aconn->srvr->server->cell->cellName, acode);
543                     shouldRetry = 1;
544                 } else {
545                     areq->tokenError = 0;
546                     aconn->forceConnectFS = 0;  /* don't check until new tokens set */
547                     aconn->user->states |= UTokensBad;
548                     afs_warnuser
549                         ("afs: Tokens for user of AFS id %d for cell %s are discarded (rxkad error=%d)\n",
550                          tu->vid, aconn->srvr->server->cell->cellName, acode);
551                 }
552             }
553             afs_PutUser(tu, READ_LOCK);
554         } else {
555             /* The else case shouldn't be possible and should probably be replaced by a panic? */
556             if (acode == VICETOKENDEAD) {
557                 aconn->forceConnectFS = 1;
558             } else if (acode == RXKADEXPIRED) {
559                 aconn->forceConnectFS = 0;      /* don't check until new tokens set */
560                 aconn->user->states |= UTokensBad;
561                 afs_warnuser
562                     ("afs: Tokens for user %d for cell %s have expired\n",
563                      areq->uid, aconn->srvr->server->cell->cellName);
564             } else {
565                 aconn->forceConnectFS = 0;      /* don't check until new tokens set */
566                 aconn->user->states |= UTokensBad;
567                 afs_warnuser
568                     ("afs: Tokens for user %d for cell %s are discarded (rxkad error = %d)\n",
569                      areq->uid, aconn->srvr->server->cell->cellName, acode);
570             }
571         }
572         shouldRetry = 1;        /* Try again (as root). */
573     }
574     /* Check for access violation. */
575     else if (acode == EACCES) {
576         /* should mark access error in non-existent per-user global structure */
577         if (aerrP)
578             (aerrP->err_Protection)++;
579         areq->accessError = 1;
580         if (op == AFS_STATS_FS_RPCIDX_STOREDATA)
581             areq->permWriteError = 1;
582         shouldRetry = 0;
583     }
584     /* check for ubik errors; treat them like crashed servers */
585     else if (acode >= ERROR_TABLE_BASE_U && acode < ERROR_TABLE_BASE_U + 255) {
586         afs_ServerDown(sa);
587         if (aerrP)
588             (aerrP->err_Server)++;
589         shouldRetry = 1;        /* retryable (maybe one is working) */
590         VSleep(1);              /* just in case */
591     }
592     /* Check for bad volume data base / missing volume. */
593     else if (acode == VSALVAGE || acode == VOFFLINE || acode == VNOVOL
594              || acode == VNOSERVICE || acode == VMOVED) {
595         struct cell *tcell;
596         int same;
597
598         shouldRetry = 1;
599         areq->volumeError = VOLMISSING;
600         if (aerrP)
601             (aerrP->err_Volume)++;
602         if (afid && (tcell = afs_GetCell(afid->Cell, 0))) {
603             same = VLDB_Same(afid, areq);
604             tvp = afs_FindVolume(afid, READ_LOCK);
605             if (tvp) {
606                 for (i = 0; i < MAXHOSTS && tvp->serverHost[i]; i++) {
607                     if (tvp->serverHost[i] == tsp) {
608                         if (tvp->status[i] == end_not_busy)
609                             tvp->status[i] = offline;
610                         else
611                             tvp->status[i]++;
612                     } else if (!same) {
613                         tvp->status[i] = not_busy;      /* reset the others */
614                     }
615                 }
616                 afs_PutVolume(tvp, READ_LOCK);
617             }
618         }
619     } else if (acode >= ERROR_TABLE_BASE_VL && acode <= ERROR_TABLE_BASE_VL + 255) {    /* vlserver errors */
620         shouldRetry = 0;
621         areq->volumeError = VOLMISSING;
622     } else if (acode >= 0) {
623         if (aerrP)
624             (aerrP->err_Other)++;
625         if (op == AFS_STATS_FS_RPCIDX_STOREDATA)
626             areq->permWriteError = 1;
627         shouldRetry = 0;        /* Other random Vice error. */
628     } else if (acode == RX_MSGSIZE) {   /* same meaning as EMSGSIZE... */
629         VSleep(1);              /* Just a hack for desperate times. */
630         if (aerrP)
631             (aerrP->err_Other)++;
632         shouldRetry = 1;        /* packet was too big, please retry call */
633     }
634
635     if (acode < 0 && acode != RX_MSGSIZE && acode != VRESTARTING) {
636         /* If we get here, code < 0 and we have network/Server troubles.
637          * areq->networkError is not set here, since we always
638          * retry in case there is another server.  However, if we find
639          * no connection (aconn == 0) we set the networkError flag.
640          */
641         afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
642         if (aerrP)
643             (aerrP->err_Server)++;
644         VSleep(1);              /* Just a hack for desperate times. */
645         shouldRetry = 1;
646     }
647 out:
648     /* now unlock the connection and return */
649     afs_PutConn(aconn, locktype);
650     return (shouldRetry);
651 }                               /*afs_Analyze */