]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Destory the sessions if they are inactive for a long amount of time.
authorVMware, Inc <>
Thu, 22 Dec 2011 00:12:36 +0000 (16:12 -0800)
committerMarcelo Vanzin <mvanzin@vmware.com>
Thu, 22 Dec 2011 00:12:36 +0000 (16:12 -0800)
This changeset is an extension to my earlier changeset #1592340. In
the changeset #1592340, I have implemented the 'InvalidateInactiveSessions'
function in the HGFS server. When this new function is called, it
checks for the inactivity of each session and invalidates the session
if it is inactive for a long amount of time. Also, we should ideally
implement another feature that destroys the session if the session is
inactive for a very long amount of time. Modified the code to destroy
the sessions besides just invalidating the sessions.

Also, implemented the code to limit the number of sessions that can be
created in one transport. HGFS server returns an error if the maximum
number of sessions are already created.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/hgfsServer/hgfsServer.c
open-vm-tools/lib/hgfsServer/hgfsServerInt.h
open-vm-tools/lib/include/hgfsUtil.h

index b236bb9504a5dda5c556548de94e830bfa260d94..7e5059e6ef99946d0bd5cf26658a0bf36d49f8d5 100644 (file)
@@ -228,8 +228,8 @@ typedef struct HgfsSharedFolderProperties {
 static void HgfsServerTransportRemoveSessionFromList(HgfsTransportSessionInfo *transportSession,
                                                      HgfsSessionInfo *sessionInfo);
 
-static void HgfsServerTransportAddSessionToList(HgfsTransportSessionInfo *transportSession,
-                                                HgfsSessionInfo *sessionInfo);
+static HgfsInternalStatus HgfsServerTransportAddSessionToList(HgfsTransportSessionInfo *transportSession,
+                                                              HgfsSessionInfo *sessionInfo);
 /*
  *    Limit payload to 16M + header.
  *    This limit ensures that list of shared pages fits into VMCI datagram.
@@ -3194,6 +3194,7 @@ HgfsServerTransportRemoveSessionFromList(HgfsTransportSessionInfo *transportSess
    ASSERT(session);
 
    DblLnkLst_Unlink1(&session->links);
+   transportSession->numSessions--;
    HgfsServerSessionPut(session);
 }
 
@@ -3203,10 +3204,12 @@ HgfsServerTransportRemoveSessionFromList(HgfsTransportSessionInfo *transportSess
  *
  * HgfsServerTransportAddSessionToList --
  *
- *   Links the specified session info to the list.
+ *    Links the specified session info to the list.
  *
  * Results:
- *    None
+ *    HGFS_ERROR_SUCCESS if the session is successfully added to the list,
+ *    HGFS_ERROR_TOO_MANY_SESSIONS if maximum number of sessions were already
+ *                                 added to the list.
  *
  * Side effects:
  *    None
@@ -3214,17 +3217,29 @@ HgfsServerTransportRemoveSessionFromList(HgfsTransportSessionInfo *transportSess
  *-----------------------------------------------------------------------------
  */
 
-void
+HgfsInternalStatus
 HgfsServerTransportAddSessionToList(HgfsTransportSessionInfo *transportSession,       // IN: transport session info
                                     HgfsSessionInfo *session)                         // IN: session info
 {
+   HgfsInternalStatus status = HGFS_ERROR_TOO_MANY_SESSIONS;
+
    ASSERT(transportSession);
    ASSERT(session);
 
    MXUser_AcquireExclLock(transportSession->sessionArrayLock);
+
+   if (transportSession->numSessions == MAX_SESSION_COUNT) {
+      goto abort;
+   }
+
    DblLnkLst_LinkLast(&transportSession->sessionArray, &session->links);
+   transportSession->numSessions++;
    HgfsServerSessionGet(session);
+   status = HGFS_ERROR_SUCCESS;
+
+abort:
    MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
+   return status;
 }
 
 
@@ -3719,6 +3734,7 @@ HgfsServerSessionConnect(void *transportData,                         // IN: tra
    transportSession->type = HGFS_SESSION_TYPE_REGULAR;
    transportSession->state = HGFS_SESSION_STATE_OPEN;
    transportSession->channelCapabilities = channelCapabilities;
+   transportSession->numSessions = 0;
 
    transportSession->sessionArrayLock =
          MXUser_CreateExclLock("HgfsSessionArrayLock",
@@ -3740,7 +3756,14 @@ HgfsServerSessionConnect(void *transportData,                         // IN: tra
    }
 
    defaultSession->type = HGFS_SESSION_TYPE_INTERNAL;
-   HgfsServerTransportAddSessionToList(transportSession, defaultSession);
+
+   if(HGFS_ERROR_SUCCESS != HgfsServerTransportAddSessionToList(transportSession, defaultSession)) {
+      LOG(4, ("%s: Could not add session to the list.\n", __FUNCTION__));
+      HgfsServerSessionPut(defaultSession);
+      MXUser_DestroyExclLock(transportSession->sessionArrayLock);
+      free(transportSession);
+      return FALSE;
+   }
 
    transportSession->defaultSessionId = defaultSession->sessionId;
 
@@ -3825,6 +3848,7 @@ HgfsServerAllocateSession(HgfsTransportSessionInfo *transportSession, // IN:
    session->activeNotification = FALSE;
    session->isInactive = TRUE;
    session->transportSession = transportSession;
+   session->numInvalidationAttempts = 0;
 
    /*
     * Initialize the node handling components.
@@ -4485,14 +4509,14 @@ HgfsServerSessionInvalidateInactiveSessions(void *clientData)         // IN:
 {
    HgfsTransportSessionInfo *transportSession =
          (HgfsTransportSessionInfo *)clientData;
-   DblLnkLst_Links shares, *curr;
+   DblLnkLst_Links shares, *curr, *next;
 
    ASSERT(transportSession);
    MXUser_AcquireExclLock(transportSession->sessionArrayLock);
 
    DblLnkLst_Init(&shares);
 
-   DblLnkLst_ForEach(curr, &transportSession->sessionArray) {
+   DblLnkLst_ForEachSafe(curr, next,  &transportSession->sessionArray) {
       HgfsSessionInfo *session = DblLnkLst_Container(curr, HgfsSessionInfo, links);
 
       HgfsServerSessionGet(session);
@@ -4502,9 +4526,31 @@ HgfsServerSessionInvalidateInactiveSessions(void *clientData)         // IN:
        * invalidate the session objects.
        */
       if (session->isInactive) {
-         HgfsInvalidateSessionObjects(&shares, session);
+
+         if (session->type == HGFS_SESSION_TYPE_REGULAR) {
+            /*
+             * Each transport session will have one default session. This
+             * default session should exist till the end of the transport
+             * session. So, increase the attempts count only for
+             * non-default sessions.
+             */
+            session->numInvalidationAttempts++;
+         }
+
+         if (session->numInvalidationAttempts == MAX_SESSION_INVALIDATION_ATTEMPTS) {
+            HgfsServerTransportRemoveSessionFromList(transportSession,
+                                                     session);
+            /*
+             * We need to reduce the refcount by 1 since we want to
+             * destroy the session.
+             */
+            HgfsServerSessionPut(session);
+         } else {
+            HgfsInvalidateSessionObjects(&shares, session);
+         }
       } else {
          session->isInactive = TRUE;
+         session->numInvalidationAttempts = 0;
       }
       HgfsServerSessionPut(session);
    }
@@ -8161,7 +8207,13 @@ HgfsServerCreateSession(HgfsInputParam *input)  // IN: Input params
          status = HGFS_ERROR_NOT_ENOUGH_MEMORY;
          goto abort;
       } else {
-         HgfsServerTransportAddSessionToList(input->transportSession, session);
+         status = HgfsServerTransportAddSessionToList(input->transportSession,
+                                                      session);
+         if (HGFS_ERROR_SUCCESS != status) {
+            LOG(4, ("%s: Could not add session to the list.\n", __FUNCTION__));
+            HgfsServerSessionPut(session);
+            goto abort;
+         }
       }
 
       if (info.maxPacketSize < input->session->maxPacketSize) {
index de9e3839eb7ba94561dcc27b9406d8b3933a0924..2f1ccf72e50021ea976d5b886f35ea04fb46208d 100644 (file)
@@ -297,6 +297,9 @@ typedef struct HgfsTransportSessionInfo {
    /* Max packet size that is supported by both client and server. */
    uint32 maxPacketSize;
 
+   /* Total number of sessions present this transport session*/
+   uint32 numSessions;
+
    /* Transport session context. */
    void *transportData;
 
@@ -338,6 +341,8 @@ typedef struct HgfsSessionInfo {
    /* Lock to ensure some fileIO requests are atomic for a handle. */
    MXUserExclLock *fileIOLock;
 
+   int numInvalidationAttempts;
+
    Atomic_uint32 refCount;    /* Reference count for session. */
 
    /*
@@ -393,6 +398,22 @@ typedef struct HgfsSessionInfo {
    Bool activeNotification;
 } HgfsSessionInfo;
 
+/*
+ * This represents the maximum number of HGFS sessions that can be
+ * created in a HGFS transport session. We picked a random value
+ * for this variable. There is no specific reason behind picking
+ * this value.
+ */
+#define MAX_SESSION_COUNT 1024
+
+/*
+ * This represents the maximum number attempts made by the HGFS
+ * invalidator before completely destroying the HGFS session. We
+ * picked a random value and there is no specific reason behind
+ * the value 4 for thie variable.
+ */
+#define MAX_SESSION_INVALIDATION_ATTEMPTS 4
+
 /*
  * These structs represent information about file open requests, file
  * attributes, and directory creation requests.
index 0e1ac4dfd4b0c93cd37b32d4fd32a43e23cf1062..219cd7eecd555acbf3a408ab6bd43deb5acd1b0b 100644 (file)
@@ -104,6 +104,7 @@ struct timespec {
 #define HGFS_ERROR_FILE_EXIST        ERROR_ALREADY_EXISTS
 #define HGFS_ERROR_NOT_SUPPORTED     ERROR_NOT_SUPPORTED
 #define HGFS_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY
+#define HGFS_ERROR_TOO_MANY_SESSIONS ERROR_INTERNAL_ERROR
 #define HGFS_ERROR_INTERNAL          ERROR_INTERNAL_ERROR
 #else
 #define HGFS_ERROR_SUCCESS           0
@@ -119,6 +120,7 @@ struct timespec {
 #define HGFS_ERROR_FILE_EXIST        EEXIST
 #define HGFS_ERROR_NOT_SUPPORTED     EOPNOTSUPP
 #define HGFS_ERROR_NOT_ENOUGH_MEMORY ENOMEM
+#define HGFS_ERROR_TOO_MANY_SESSIONS EINTERNAL
 #define HGFS_ERROR_INTERNAL          EINTERNAL
 #endif // _WIN32