From: VMware, Inc <> Date: Thu, 22 Dec 2011 00:12:36 +0000 (-0800) Subject: Destory the sessions if they are inactive for a long amount of time. X-Git-Tag: 2011.12.20-562307~53 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=49e86e07ca7ad2db104a6111ba7ea1ddddb3a277;p=thirdparty%2Fopen-vm-tools.git Destory the sessions if they are inactive for a long amount of time. 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 --- diff --git a/open-vm-tools/lib/hgfsServer/hgfsServer.c b/open-vm-tools/lib/hgfsServer/hgfsServer.c index b236bb950..7e5059e6e 100644 --- a/open-vm-tools/lib/hgfsServer/hgfsServer.c +++ b/open-vm-tools/lib/hgfsServer/hgfsServer.c @@ -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) { diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerInt.h b/open-vm-tools/lib/hgfsServer/hgfsServerInt.h index de9e3839e..2f1ccf72e 100644 --- a/open-vm-tools/lib/hgfsServer/hgfsServerInt.h +++ b/open-vm-tools/lib/hgfsServer/hgfsServerInt.h @@ -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. diff --git a/open-vm-tools/lib/include/hgfsUtil.h b/open-vm-tools/lib/include/hgfsUtil.h index 0e1ac4dfd..219cd7eec 100644 --- a/open-vm-tools/lib/include/hgfsUtil.h +++ b/open-vm-tools/lib/include/hgfsUtil.h @@ -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