Remove support for Solaris pre-8
[openafs.git] / src / afs / afs_analyze.c
index 076c2e1..220311e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
@@ -26,7 +26,7 @@
 #ifdef AFS_SGI62_ENV
 #include "h/hashing.h"
 #endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD_ENV) && !defined(AFS_DARWIN60_ENV)
+#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD_ENV) && !defined(AFS_DARWIN_ENV)
 #include <netinet/in_var.h>
 #endif
 #endif /* !UKERNEL */
 #include "afs/afs_util.h"
 #include "afs/unified_afs.h"
 
-#if    defined(AFS_SUN56_ENV)
+#if    defined(AFS_SUN5_ENV)
 #include <inet/led.h>
 #include <inet/common.h>
-#if     defined(AFS_SUN58_ENV)
 #include <netinet/ip6.h>
-#endif
 #include <inet/ip.h>
 #endif
 
-
 /* shouldn't do it this way, but for now will do */
 #ifndef ERROR_TABLE_BASE_U
 #define ERROR_TABLE_BASE_U     (5376L)
@@ -77,7 +74,7 @@ int lastcode;
  * 0   if the vldb record for a specific volume is different from what
  *     we have cached -- perhaps the volume has moved.
  * 1   if the vldb record is the same
- * 2   if we can't tell if it's the same or not. 
+ * 2   if we can't tell if it's the same or not.
  *
  * If 0, the caller will probably start over at the beginning of our
  * list of servers for this volume and try to find one that is up.  If
@@ -103,6 +100,7 @@ VLDB_Same(struct VenusFid *afid, struct vrequest *areq)
     char *bp, tbuf[CVBS];      /* biggest volume id is 2^32, ~ 4*10^9 */
     unsigned int changed;
     struct server *(oldhosts[NMAXNSERVERS]);
+    struct rx_connection *rxconn;
 
     AFS_STATCNT(CheckVLDB);
     afs_FinalizeReq(areq);
@@ -110,51 +108,52 @@ VLDB_Same(struct VenusFid *afid, struct vrequest *areq)
     if ((i = afs_InitReq(&treq, afs_osi_credp)))
        return DUNNO;
     v = afs_osi_Alloc(sizeof(*v));
+    osi_Assert(v != NULL);
     tcell = afs_GetCell(afid->Cell, READ_LOCK);
     bp = afs_cv2string(&tbuf[CVBS], afid->Fid.Volume);
     do {
        VSleep(2);              /* Better safe than sorry. */
        tconn =
            afs_ConnByMHosts(tcell->cellHosts, tcell->vlport, tcell->cellNum,
-                            &treq, SHARED_LOCK);
+                            &treq, SHARED_LOCK, &rxconn);
        if (tconn) {
-           if (tconn->srvr->server->flags & SNO_LHOSTS) {
+           if ( tconn->parent->srvr->server->flags & SNO_LHOSTS) {
                type = 0;
                RX_AFS_GUNLOCK();
-               i = VL_GetEntryByNameO(tconn->id, bp, &v->tve);
+               i = VL_GetEntryByNameO(rxconn, bp, &v->tve);
                RX_AFS_GLOCK();
-           } else if (tconn->srvr->server->flags & SYES_LHOSTS) {
+           } else if (tconn->parent->srvr->server->flags & SYES_LHOSTS) {
                type = 1;
                RX_AFS_GUNLOCK();
-               i = VL_GetEntryByNameN(tconn->id, bp, &v->ntve);
+               i = VL_GetEntryByNameN(rxconn, bp, &v->ntve);
                RX_AFS_GLOCK();
            } else {
                type = 2;
                RX_AFS_GUNLOCK();
-               i = VL_GetEntryByNameU(tconn->id, bp, &v->utve);
+               i = VL_GetEntryByNameU(rxconn, bp, &v->utve);
                RX_AFS_GLOCK();
-               if (!(tconn->srvr->server->flags & SVLSRV_UUID)) {
+               if (!(tconn->parent->srvr->server->flags & SVLSRV_UUID)) {
                    if (i == RXGEN_OPCODE) {
                        type = 1;
                        RX_AFS_GUNLOCK();
-                       i = VL_GetEntryByNameN(tconn->id, bp, &v->ntve);
+                       i = VL_GetEntryByNameN(rxconn, bp, &v->ntve);
                        RX_AFS_GLOCK();
                        if (i == RXGEN_OPCODE) {
                            type = 0;
-                           tconn->srvr->server->flags |= SNO_LHOSTS;
+                           tconn->parent->srvr->server->flags |= SNO_LHOSTS;
                            RX_AFS_GUNLOCK();
-                           i = VL_GetEntryByNameO(tconn->id, bp, &v->tve);
+                           i = VL_GetEntryByNameO(rxconn, bp, &v->tve);
                            RX_AFS_GLOCK();
                        } else if (!i)
-                           tconn->srvr->server->flags |= SYES_LHOSTS;
+                           tconn->parent->srvr->server->flags |= SYES_LHOSTS;
                    } else if (!i)
-                       tconn->srvr->server->flags |= SVLSRV_UUID;
+                       tconn->parent->srvr->server->flags |= SVLSRV_UUID;
                }
                lastcode = i;
            }
        } else
            i = -1;
-    } while (afs_Analyze(tconn, i, NULL, &treq, -1,    /* no op code for this */
+    } while (afs_Analyze(tconn, rxconn, i, NULL, &treq, -1,    /* no op code for this */
                         SHARED_LOCK, tcell));
 
     afs_PutCell(tcell, READ_LOCK);
@@ -219,8 +218,8 @@ VLDB_Same(struct VenusFid *afid, struct vrequest *areq)
  *     areq  : The request record associated with this operation.
  *     afid  : The FID of the file involved in the action.  This argument
  *             may be null if none was involved.
- *      tsp   : pointer to a server struct for the server we wish to 
- *              blacklist. 
+ *      tsp   : pointer to a server struct for the server we wish to
+ *              blacklist.
  *
  * Returns:
  *     Non-zero value if further servers are available to try,
@@ -234,11 +233,11 @@ VLDB_Same(struct VenusFid *afid, struct vrequest *areq)
  *     As advertised.
  *
  * NOTE:
- *     The afs_Conn* routines use the list of invalidated servers to 
+ *     The afs_Conn* routines use the list of invalidated servers to
  *      avoid reusing a server marked as invalid for this request.
  *------------------------------------------------------------------------*/
-static afs_int32 
-afs_BlackListOnce(struct vrequest *areq, struct VenusFid *afid, 
+static afs_int32
+afs_BlackListOnce(struct vrequest *areq, struct VenusFid *afid,
                  struct server *tsp)
 {
     struct volume *tvp;
@@ -253,7 +252,7 @@ afs_BlackListOnce(struct vrequest *areq, struct VenusFid *afid,
                    areq->skipserver[i] = 1;
                }
                if (tvp->serverHost[i] &&
-                   (tvp->serverHost[i]->addr->sa_flags & 
+                   (tvp->serverHost[i]->addr->sa_flags &
                      SRVR_ISDOWN)) {
                    areq->skipserver[i] = 1;
                }
@@ -268,7 +267,7 @@ afs_BlackListOnce(struct vrequest *areq, struct VenusFid *afid,
            return serversleft;
        }
     }
-    return 1;
+    return serversleft;
 }
 
 
@@ -305,21 +304,20 @@ afs_BlackListOnce(struct vrequest *areq, struct VenusFid *afid,
  *     if this is a temporary or permanent error.
  *------------------------------------------------------------------------*/
 int
-afs_Analyze(register struct afs_conn *aconn, afs_int32 acode,
-           struct VenusFid *afid, register struct vrequest *areq, int op,
-           afs_int32 locktype, struct cell *cellp)
+afs_Analyze(struct afs_conn *aconn, struct rx_connection *rxconn,
+            afs_int32 acode, struct VenusFid *afid, struct vrequest *areq,
+            int op, afs_int32 locktype, struct cell *cellp)
 {
     afs_int32 i;
     struct srvAddr *sa;
     struct server *tsp;
-    struct volume *tvp;
+    struct volume *tvp = NULL;
     afs_int32 shouldRetry = 0;
     afs_int32 serversleft = 1;
     struct afs_stats_RPCErrors *aerrP;
     afs_int32 markeddown;
+    afs_uint32 address;
 
     if (AFS_IS_DISCONNECTED && !AFS_IN_SYNC) {
        /* On reconnection, act as connected. XXX: for now.... */
         /* SXW - This may get very tired after a while. We should try and
@@ -329,11 +327,11 @@ afs_Analyze(register struct afs_conn *aconn, afs_int32 acode,
        if (aconn) {
            /* SXW - I suspect that this will _never_ happen - we shouldn't
             *       get a connection because we're disconnected !!!*/
-           afs_PutConn(aconn, locktype);
+           afs_PutConn(aconn, rxconn, locktype);
        }
        return 0;
     }
-    
+
     AFS_STATCNT(afs_Analyze);
     afs_Trace4(afs_iclSetp, CM_TRACE_ANALYZE, ICL_TYPE_INT32, op,
               ICL_TYPE_POINTER, aconn, ICL_TYPE_INT32, acode, ICL_TYPE_LONG,
@@ -383,7 +381,7 @@ afs_Analyze(register struct afs_conn *aconn, afs_int32 acode,
        return shouldRetry;     /* should retry */
     }
 
-    if (!aconn || !aconn->srvr) {
+    if (!aconn || !aconn->parent->srvr) {
        if (!areq->volumeError) {
            if (aerrP)
                (aerrP->err_Network)++;
@@ -415,15 +413,19 @@ afs_Analyze(register struct afs_conn *aconn, afs_int32 acode,
                }
            } /* if (hm_retry_int ... */
            else {
-               areq->networkError = 1;
+               if (acode == RX_MSGSIZE)
+                   shouldRetry = 1;
+               else
+                   areq->networkError = 1;
            }
        }
        return shouldRetry;
     }
 
     /* Find server associated with this connection. */
-    sa = aconn->srvr;
+    sa = aconn->parent->srvr;
     tsp = sa->server;
+    address = ntohl(sa->sa_ip);
 
     /* Before we do anything with acode, make sure we translate it back to
      * a system error */
@@ -444,34 +446,44 @@ afs_Analyze(register struct afs_conn *aconn, afs_int32 acode,
            }
        }
 
-       afs_PutConn(aconn, locktype);
+       afs_PutConn(aconn, rxconn, locktype);
        return 0;
     }
 
     /* If network troubles, mark server as having bogued out again. */
-    /* VRESTARTING is < 0 because of backward compatibility issues 
+    /* VRESTARTING is < 0 because of backward compatibility issues
      * with 3.4 file servers and older cache managers */
 #ifdef AFS_64BIT_CLIENT
     if (acode == -455)
        acode = 455;
 #endif /* AFS_64BIT_CLIENT */
     if ((acode < 0) && (acode != VRESTARTING)) {
+       if (acode == RX_MSGSIZE) {
+           shouldRetry = 1;
+           goto out;
+       }
        if (acode == RX_CALL_TIMEOUT) {
            serversleft = afs_BlackListOnce(areq, afid, tsp);
-           areq->idleError++;
-           if (serversleft) {
-               shouldRetry = 1;
-           } else {
+           if (afid)
+               tvp = afs_FindVolume(afid, READ_LOCK);
+           if (!afid || !tvp || (tvp->states & VRO))
+               areq->idleError++;
+           if ((serversleft == 0) && tvp &&
+               ((tvp->states & VRO) || (tvp->states & VBackup))) {
                shouldRetry = 0;
+           } else {
+               shouldRetry = 1;
            }
+           if (tvp)
+               afs_PutVolume(tvp, READ_LOCK);
            /* By doing this, we avoid ever marking a server down
-            * in an idle timeout case. That's because the server is 
+            * in an idle timeout case. That's because the server is
             * still responding and may only be letting a single vnode
             * time out. We otherwise risk having the server continually
-            * be marked down, then up, then down again... 
+            * be marked down, then up, then down again...
             */
            goto out;
-       } 
+       }
        markeddown = afs_ServerDown(sa);
        ForceNewConnections(sa); /**multi homed clients lock:afs_xsrvAddr? */
        if (aerrP)
@@ -503,8 +515,10 @@ afs_Analyze(register struct afs_conn *aconn, afs_int32 acode,
            }
            afs_PutVolume(tvp, READ_LOCK);
        } else {
-           afs_warnuser("afs: Waiting for busy volume %u in cell %s\n",
-                        (afid ? afid->Fid.Volume : 0), tsp->cell->cellName);
+           afs_warnuser("afs: Waiting for busy volume %u in cell %s (server %d.%d.%d.%d)\n",
+                        (afid ? afid->Fid.Volume : 0), tsp->cell->cellName,
+                        (address >> 24), (address >> 16) & 0xff,
+                        (address >> 8) & 0xff, (address) & 0xff);
            VSleep(afs_BusyWaitPeriod); /* poll periodically */
        }
        shouldRetry = 1;
@@ -526,26 +540,34 @@ afs_Analyze(register struct afs_conn *aconn, afs_int32 acode,
                aconn->forceConnectFS = 1;
            } else if (acode == RXKADEXPIRED) {
                aconn->forceConnectFS = 0;      /* don't check until new tokens set */
-               aconn->user->states |= UTokensBad;
+               aconn->parent->user->states |= UTokensBad;
+               afs_NotifyUser(tu, UTokensDropped);
                afs_warnuser
-                   ("afs: Tokens for user of AFS id %d for cell %s have expired\n",
-                    tu->vid, aconn->srvr->server->cell->cellName);
+                   ("afs: Tokens for user of AFS id %d for cell %s have expired (server %d.%d.%d.%d)\n",
+                    tu->viceId, aconn->parent->srvr->server->cell->cellName,
+                    (address >> 24), (address >> 16) & 0xff,
+                    (address >> 8) & 0xff, (address) & 0xff);
            } else {
                serversleft = afs_BlackListOnce(areq, afid, tsp);
                areq->tokenError++;
 
                if (serversleft) {
                    afs_warnuser
-                       ("afs: Tokens for user of AFS id %d for cell %s: rxkad error=%d\n",
-                        tu->vid, aconn->srvr->server->cell->cellName, acode);
+                       ("afs: Tokens for user of AFS id %d for cell %s: rxkad error=%d (server %d.%d.%d.%d)\n",
+                        tu->viceId, aconn->parent->srvr->server->cell->cellName, acode,
+                        (address >> 24), (address >> 16) & 0xff,
+                        (address >> 8) & 0xff, (address) & 0xff);
                    shouldRetry = 1;
                } else {
                    areq->tokenError = 0;
                    aconn->forceConnectFS = 0;  /* don't check until new tokens set */
-                   aconn->user->states |= UTokensBad;
+                   aconn->parent->user->states |= UTokensBad;
+                   afs_NotifyUser(tu, UTokensDropped);
                    afs_warnuser
-                       ("afs: Tokens for user of AFS id %d for cell %s are discarded (rxkad error=%d)\n",
-                        tu->vid, aconn->srvr->server->cell->cellName, acode);
+                       ("afs: Tokens for user of AFS id %d for cell %s are discarded (rxkad error=%d, server %d.%d.%d.%d)\n",
+                        tu->viceId, aconn->parent->srvr->server->cell->cellName, acode,
+                        (address >> 24), (address >> 16) & 0xff,
+                        (address >> 8) & 0xff, (address) & 0xff);
                }
            }
            afs_PutUser(tu, READ_LOCK);
@@ -555,16 +577,24 @@ afs_Analyze(register struct afs_conn *aconn, afs_int32 acode,
                aconn->forceConnectFS = 1;
            } else if (acode == RXKADEXPIRED) {
                aconn->forceConnectFS = 0;      /* don't check until new tokens set */
-               aconn->user->states |= UTokensBad;
+               aconn->parent->user->states |= UTokensBad;
+               afs_NotifyUser(tu, UTokensDropped);
                afs_warnuser
-                   ("afs: Tokens for user %d for cell %s have expired\n",
-                    areq->uid, aconn->srvr->server->cell->cellName);
+                   ("afs: Tokens for user %d for cell %s have expired (server %d.%d.%d.%d)\n",
+                    areq->uid, aconn->parent->srvr->server->cell->cellName,
+                    (address >> 24), (address >> 16) & 0xff,
+                    (address >> 8) & 0xff, (address) & 0xff);
            } else {
                aconn->forceConnectFS = 0;      /* don't check until new tokens set */
-               aconn->user->states |= UTokensBad;
+               aconn->parent->user->states |= UTokensBad;
+               afs_NotifyUser(tu, UTokensDropped);
                afs_warnuser
-                   ("afs: Tokens for user %d for cell %s are discarded (rxkad error = %d)\n",
-                    areq->uid, aconn->srvr->server->cell->cellName, acode);
+                   ("afs: Tokens for user %d for cell %s are discarded (rxkad error = %d, server %d.%d.%d.%d)\n",
+                    areq->uid, aconn->parent->srvr->server->cell->cellName,
+                     acode,
+                    (address >> 24), (address >> 16) & 0xff,
+                    (address >> 8) & 0xff, (address) & 0xff);
+
            }
        }
        shouldRetry = 1;        /* Try again (as root). */
@@ -624,6 +654,11 @@ afs_Analyze(register struct afs_conn *aconn, afs_int32 acode,
            areq->permWriteError = 1;
        shouldRetry = 0;        /* Other random Vice error. */
     } else if (acode == RX_MSGSIZE) {  /* same meaning as EMSGSIZE... */
+       afs_warnuser
+           ("afs: Path MTU may have been exceeded, retrying (server %d.%d.%d.%d)\n",
+            (address >> 24), (address >> 16) & 0xff,
+            (address >> 8) & 0xff, (address) & 0xff);
+
        VSleep(1);              /* Just a hack for desperate times. */
        if (aerrP)
            (aerrP->err_Other)++;
@@ -644,6 +679,6 @@ afs_Analyze(register struct afs_conn *aconn, afs_int32 acode,
     }
 out:
     /* now unlock the connection and return */
-    afs_PutConn(aconn, locktype);
+    afs_PutConn(aconn, rxconn, locktype);
     return (shouldRetry);
 }                              /*afs_Analyze */