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.
ASSERT(session);
DblLnkLst_Unlink1(&session->links);
+ transportSession->numSessions--;
HgfsServerSessionPut(session);
}
*
* 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
*-----------------------------------------------------------------------------
*/
-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;
}
transportSession->type = HGFS_SESSION_TYPE_REGULAR;
transportSession->state = HGFS_SESSION_STATE_OPEN;
transportSession->channelCapabilities = channelCapabilities;
+ transportSession->numSessions = 0;
transportSession->sessionArrayLock =
MXUser_CreateExclLock("HgfsSessionArrayLock",
}
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;
session->activeNotification = FALSE;
session->isInactive = TRUE;
session->transportSession = transportSession;
+ session->numInvalidationAttempts = 0;
/*
* Initialize the node handling components.
{
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);
* 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);
}
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) {
/* 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;
/* Lock to ensure some fileIO requests are atomic for a handle. */
MXUserExclLock *fileIOLock;
+ int numInvalidationAttempts;
+
Atomic_uint32 refCount; /* Reference count for session. */
/*
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.