security-class-object-leak-20040301
[openafs.git] / src / WINNT / afsd / cm_conn.c
index 6ebdf65..94f19de 100644 (file)
@@ -29,6 +29,9 @@ osi_rwlock_t cm_connLock;
 
 long RDRtimeout = CM_CONN_DEFAULTRDRTIMEOUT;
 
+#define LANMAN_WKS_PARAM_KEY "SYSTEM\\CurrentControlSet\\Services\\lanmanworkstation\\parameters"
+#define LANMAN_WKS_SESSION_TIMEOUT "SessTimeout"
+
 afs_int32 cryptall = 0;
 
 void cm_PutConn(cm_conn_t *connp)
@@ -41,11 +44,37 @@ void cm_PutConn(cm_conn_t *connp)
 void cm_InitConn(void)
 {
        static osi_once_t once;
+       long code;
+       DWORD sessTimeout;
+       HKEY parmKey;
         
-        if (osi_Once(&once)) {
+    if (osi_Once(&once)) {
                lock_InitializeRWLock(&cm_connLock, "connection global lock");
-               osi_EndOnce(&once);
+
+        /* keisa - read timeout value for lanmanworkstation  service.
+         * It is used as hardtimeout for connections. 
+         * Default value is 45 
+         */
+               code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, LANMAN_WKS_PARAM_KEY,
+                            0, KEY_QUERY_VALUE, &parmKey);
+               if (code == ERROR_SUCCESS)
+        {
+                   DWORD dummyLen = sizeof(sessTimeout);
+                   code = RegQueryValueEx(parmKey, LANMAN_WKS_SESSION_TIMEOUT, NULL, NULL, 
+                                   (BYTE *) &sessTimeout, &dummyLen);
+                   if (code == ERROR_SUCCESS)
+            {
+                afsi_log("lanmanworkstation : SessTimeout %d", sessTimeout);
+                RDRtimeout = sessTimeout;
+            }
+                   else
+            {
+                RDRtimeout = CM_CONN_DEFAULTRDRTIMEOUT;
+            }
         }
+               
+        osi_EndOnce(&once);
+    }
 }
 
 void cm_InitReq(cm_req_t *reqp)
@@ -108,6 +137,7 @@ long cm_GetServerList(struct cm_fid *fidp, struct cm_user *userp,
  *
  * volSyncp and/or cbrp may also be NULL.
  */
+int
 cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
        struct cm_fid *fidp,
        AFSVolSync *volSyncp, cm_callbackRequest_t *cbrp, long errorCode)
@@ -134,7 +164,30 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
        if (reqp->flags & CM_REQ_NORETRY)
                goto out;
 
-       /* if all servers are offline, mark them non-busy and start over */
+       /* if timeout - check that is did not exceed the SMB timeout
+          and retry */
+       if (errorCode == CM_ERROR_TIMEDOUT)
+    {
+           long timeUsed, timeLeft;
+           /* timeleft - get if from reqp the same way as cmXonnByMServers does */
+#ifndef DJGPP
+           timeUsed = (GetCurrentTime() - reqp->startTime) / 1000;
+#else
+           gettimeofday(&now, NULL);
+           timeUsed = sub_time(now, reqp->startTime) / 1000;
+#endif
+           
+           /* leave 5 seconds margin for sleep */
+           timeLeft = RDRtimeout - timeUsed;
+           if (timeLeft > 5)
+        {
+            thrd_Sleep(3000);
+            cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
+            retry = 1;
+        } 
+    }
+
+    /* if all servers are offline, mark them non-busy and start over */
        if (errorCode == CM_ERROR_ALLOFFLINE) {
            osi_Log0(afsd_logp, "cm_Analyze passed CM_ERROR_ALLOFFLINE.");
            thrd_Sleep(5000);
@@ -170,12 +223,8 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
        /* special codes:  missing volumes */
        if (errorCode == VNOVOL || errorCode == VMOVED || errorCode == VOFFLINE
            || errorCode == VSALVAGE || errorCode == VNOSERVICE) {
-               long oldSum, newSum;
-               int same;
-
                /* Log server being offline for this volume */
-               osi_Log4(afsd_logp, "cm_Analyze found server %d.%d.%d.%d
-marked offline for a volume",
+               osi_Log4(afsd_logp, "cm_Analyze found server %d.%d.%d.%d marked offline for a volume",
                         ((serverp->addr.sin_addr.s_addr & 0xff)),
                         ((serverp->addr.sin_addr.s_addr & 0xff00)>> 8),
                         ((serverp->addr.sin_addr.s_addr & 0xff0000)>> 16),
@@ -270,7 +319,7 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp,
        cm_serverRef_t *tsrp;
         cm_server_t *tsp;
         long firstError = 0;
-       int someBusy = 0, someOffline = 0;
+       int someBusy = 0, someOffline = 0, allDown = 1;
        long timeUsed, timeLeft, hardTimeLeft;
 #ifdef DJGPP
         struct timeval now;
@@ -296,53 +345,59 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp,
 
        lock_ObtainWrite(&cm_serverLock);
 
-        for(tsrp = serversp; tsrp; tsrp=tsrp->next) {
-               tsp = tsrp->server;
-               tsp->refCount++;
-                lock_ReleaseWrite(&cm_serverLock);
-               if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
-                       if (tsrp->status == busy)
-                               someBusy = 1;
-                       else if (tsrp->status == offline)
-                               someOffline = 1;
-                       else {
-                               code = cm_ConnByServer(tsp, usersp, connpp);
-                               if (code == 0) {
-                                       cm_PutServer(tsp);
-                                       /* Set RPC timeout */
-                                       if (timeLeft > CM_CONN_CONNDEADTIME)
-                                               timeLeft = CM_CONN_CONNDEADTIME;
-
-                                       if (hardTimeLeft > CM_CONN_HARDDEADTIME) 
-                                               hardTimeLeft = CM_CONN_HARDDEADTIME;
-
-                                       lock_ObtainMutex(&(*connpp)->mx);
-                                       rx_SetConnDeadTime((*connpp)->callp,
-                                                          timeLeft);
-                                       rx_SetConnHardDeadTime((*connpp)->callp, 
-                                                              (u_short) hardTimeLeft);
-                                       lock_ReleaseMutex(&(*connpp)->mx);
-
-                                       return 0;
-                               }
-                               if (firstError == 0) firstError = code;
-                       }
+    for(tsrp = serversp; tsrp; tsrp=tsrp->next) {
+        tsp = tsrp->server;
+        tsp->refCount++;
+        lock_ReleaseWrite(&cm_serverLock);
+        if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
+            allDown = 0;
+            if (tsrp->status == busy)
+                someBusy = 1;
+            else if (tsrp->status == offline)
+                someOffline = 1;
+            else {
+                code = cm_ConnByServer(tsp, usersp, connpp);
+                if (code == 0) {
+                    cm_PutServer(tsp);
+                    /* Set RPC timeout */
+                    if (timeLeft > CM_CONN_CONNDEADTIME)
+                        timeLeft = CM_CONN_CONNDEADTIME;
+
+                    if (hardTimeLeft > CM_CONN_HARDDEADTIME) 
+                        hardTimeLeft = CM_CONN_HARDDEADTIME;
+
+                    lock_ObtainMutex(&(*connpp)->mx);
+                    rx_SetConnDeadTime((*connpp)->callp,
+                                        timeLeft);
+                    rx_SetConnHardDeadTime((*connpp)->callp, 
+                                            (u_short) hardTimeLeft);
+                    lock_ReleaseMutex(&(*connpp)->mx);
+
+                    return 0;
                 }
-                lock_ObtainWrite(&cm_serverLock);
-                osi_assert(tsp->refCount-- > 0);
-        }
+                if (firstError == 0) 
+                    firstError = code;
+            }
+               } 
+        lock_ObtainWrite(&cm_serverLock);
+        osi_assert(tsp->refCount-- > 0);
+    }   
 
        lock_ReleaseWrite(&cm_serverLock);
        if (firstError == 0) {
-               if (someBusy) firstError = CM_ERROR_ALLBUSY;
-               else if (someOffline) firstError = CM_ERROR_ALLOFFLINE;
-               else if (serversp) firstError = CM_ERROR_TIMEDOUT;
+               if (someBusy) 
+                       firstError = CM_ERROR_ALLBUSY;
+               else if (someOffline) 
+                       firstError = CM_ERROR_ALLOFFLINE;
+               else if (!allDown && serversp) 
+                       firstError = CM_ERROR_TIMEDOUT;
                /* Only return CM_ERROR_NOSUCHVOLUME if there are no
                   servers for this volume */
-               else firstError = CM_ERROR_NOSUCHVOLUME;
+               else 
+                       firstError = CM_ERROR_NOSUCHVOLUME;
        }
        osi_Log1(afsd_logp, "cm_ConnByMServers returning %x", firstError);
-        return firstError;
+    return firstError;
 }
 
 /* called with a held server to GC all bad connections hanging off of the server */
@@ -416,6 +471,8 @@ static void cm_NewRXConnection(cm_conn_t *tcp, cm_ucell_t *ucellp,
        rx_SetConnDeadTime(tcp->callp, CM_CONN_CONNDEADTIME);
        rx_SetConnHardDeadTime(tcp->callp, CM_CONN_HARDDEADTIME);
        tcp->ucgen = ucellp->gen;
+    if (secObjp)
+        rxs_Release(secObjp);   /* Decrement the initial refCount */
 }
 
 long cm_ConnByServer(cm_server_t *serverp, cm_user_t *userp, cm_conn_t **connpp)