tempHandle = VMCIHandleArray_GetEntry(context->queuePairArray, 0);
while (!VMCI_HANDLE_EQUAL(tempHandle, VMCI_INVALID_HANDLE)) {
- VMCIQPBroker_Lock();
if (VMCIQPBroker_Detach(tempHandle, context) < VMCI_SUCCESS) {
/*
* When VMCIQPBroker_Detach() succeeds it removes the handle from the
*/
VMCIHandleArray_RemoveEntry(context->queuePairArray, tempHandle);
}
- VMCIQPBroker_Unlock();
tempHandle = VMCIHandleArray_GetEntry(context->queuePairArray, 0);
}
}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMCIContext_QueuePairCreate --
+ *
+ * Registers that a new queue pair handle has been allocated by
+ * the context.
+ *
+ * Results:
+ * VMCI_SUCCESS on success, appropriate error code otherewise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+VMCIContext_QueuePairCreate(VMCIContext *context, // IN: Context structure
+ VMCIHandle handle) // IN
+{
+ VMCILockFlags flags;
+ int result;
+
+ if (context == NULL || VMCI_HANDLE_INVALID(handle)) {
+ return VMCI_ERROR_INVALID_ARGS;
+ }
+
+ VMCI_GrabLock(&context->lock, &flags);
+ if (!VMCIHandleArray_HasEntry(context->queuePairArray, handle)) {
+ VMCIHandleArray_AppendEntry(&context->queuePairArray, handle);
+ result = VMCI_SUCCESS;
+ } else {
+ result = VMCI_ERROR_DUPLICATE_ENTRY;
+ }
+ VMCI_ReleaseLock(&context->lock, flags);
+
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMCIContext_QueuePairDestroy --
+ *
+ * Unregisters a queue pair handle that was previously registered
+ * with VMCIContext_QueuePairCreate.
+ *
+ * Results:
+ * VMCI_SUCCESS on success, appropriate error code otherewise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+VMCIContext_QueuePairDestroy(VMCIContext *context, // IN: Context structure
+ VMCIHandle handle) // IN
+{
+ VMCILockFlags flags;
+ VMCIHandle removedHandle;
+
+ if (context == NULL || VMCI_HANDLE_INVALID(handle)) {
+ return VMCI_ERROR_INVALID_ARGS;
+ }
+
+ VMCI_GrabLock(&context->lock, &flags);
+ removedHandle = VMCIHandleArray_RemoveEntry(context->queuePairArray, handle);
+ VMCI_ReleaseLock(&context->lock, flags);
+
+ if (VMCI_HANDLE_INVALID(removedHandle)) {
+ return VMCI_ERROR_NOT_FOUND;
+ } else {
+ return VMCI_SUCCESS;
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMCIContext_QueuePairExists --
+ *
+ * Determines whether a given queue pair handle is registered
+ * with the given context.
+ *
+ * Results:
+ * TRUE, if queue pair is registered with context. FALSE, otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+VMCIContext_QueuePairExists(VMCIContext *context, // IN: Context structure
+ VMCIHandle handle) // IN
+{
+ VMCILockFlags flags;
+ Bool result;
+
+ if (context == NULL || VMCI_HANDLE_INVALID(handle)) {
+ return VMCI_ERROR_INVALID_ARGS;
+ }
+
+ VMCI_GrabLock(&context->lock, &flags);
+ result = VMCIHandleArray_HasEntry(context->queuePairArray, handle);
+ VMCI_ReleaseLock(&context->lock, flags);
+
+ return result;
+}
+
+
/*
*----------------------------------------------------------------------
*
* VMCIContext_RegisterGuestMem --
*
- * Tells the context that guest memory is available for access.
+ * Tells the context that guest memory is available for
+ * access. This should only be used when unquiescing the VMCI
+ * device of a guest.
*
* Results:
* None.
uint32 numQueuePairs;
uint32 cur;
- VMCIQPBroker_Lock();
+ /*
+ * It is safe to access the queue pair array here, since no changes
+ * to the queuePairArray can take place until after the unquiescing
+ * is complete.
+ */
+
numQueuePairs = VMCIHandleArray_GetSize(context->queuePairArray);
for (cur = 0; cur < numQueuePairs; cur++) {
VMCIHandle handle;
}
}
}
- VMCIQPBroker_Unlock();
#endif
}
*
* VMCIContext_ReleaseGuestMem --
*
- * Releases all the contexts references to guest memory.
+ * Releases all the contexts references to guest memory. This
+ * should only be used when qiescing or cleaning up the VMCI
+ * device of a guest.
*
* Results:
* None.
uint32 numQueuePairs;
uint32 cur;
+ /*
+ * It is safe to access the queue pair array here, since no changes
+ * to the queuePairArray can take place when the the quiescing
+ * has been initiated.
+ */
+
numQueuePairs = VMCIHandleArray_GetSize(context->queuePairArray);
for (cur = 0; cur < numQueuePairs; cur++) {
VMCIHandle handle;
if (!VMCI_HANDLE_EQUAL(handle, VMCI_INVALID_HANDLE)) {
int res;
- VMCIQPBroker_Lock();
res = VMCIQPBroker_Unmap(handle, context, gid);
if (res < VMCI_SUCCESS) {
VMCI_WARNING(("Failed to unmap guest memory for queue pair "
"(handle=0x%x:0x%x, res=%d).\n",
handle.context, handle.resource, res));
}
- VMCIQPBroker_Unlock();
}
}
#endif
Bool VMCIContext_Exists(VMCIId cid);
VMCIId VMCIContext_GetId(VMCIContext *context);
-int VMCIContext_AddGroupEntry(VMCIContext *context,
- VMCIHandle entryHandle);
-VMCIHandle VMCIContext_RemoveGroupEntry(VMCIContext *context,
- VMCIHandle entryHandle);
int VMCIContext_AddNotification(VMCIId contextID, VMCIId remoteCID);
int VMCIContext_RemoveNotification(VMCIId contextID, VMCIId remoteCID);
int VMCIContext_GetCheckpointState(VMCIId contextID, uint32 cptType,
void VMCIContext_RegisterGuestMem(VMCIContext *context);
void VMCIContext_ReleaseGuestMem(VMCIContext *context, VMCIGuestMemID gid);
+int VMCIContext_QueuePairCreate(VMCIContext *context, VMCIHandle handle);
+int VMCIContext_QueuePairDestroy(VMCIContext *context, VMCIHandle handle);
+Bool VMCIContext_QueuePairExists(VMCIContext *context, VMCIHandle handle);
+
#ifndef VMX86_SERVER
void VMCIContext_CheckAndSignalNotify(VMCIContext *context);
# ifdef __linux__
static VMCILock hibernateFailedListLock;
#endif
+static void VMCIQPBrokerLock(void);
+static void VMCIQPBrokerUnlock(void);
+
static QueuePairEntry *QueuePairList_FindEntry(QueuePairList *qpList,
VMCIHandle handle);
static void QueuePairList_AddEntry(QueuePairList *qpList,
/*
*-----------------------------------------------------------------------------
*
- * VMCIQPBroker_Lock --
+ * VMCIQPBrokerLock --
*
* Acquires the mutex protecting a VMCI queue pair broker transaction.
*
*-----------------------------------------------------------------------------
*/
-void
-VMCIQPBroker_Lock(void)
+static void
+VMCIQPBrokerLock(void)
{
VMCIMutex_Acquire(&qpBrokerList.mutex);
}
/*
*-----------------------------------------------------------------------------
*
- * VMCIQPBroker_Unlock --
+ * VMCIQPBrokerUnlock --
*
* Releases the mutex protecting a VMCI queue pair broker transaction.
*
*-----------------------------------------------------------------------------
*/
-void
-VMCIQPBroker_Unlock(void)
+static void
+VMCIQPBrokerUnlock(void)
{
VMCIMutex_Release(&qpBrokerList.mutex);
}
{
QPBrokerEntry *entry;
- VMCIQPBroker_Lock();
+ VMCIQPBrokerLock();
while ((entry = (QPBrokerEntry *)QueuePairList_GetHead(&qpBrokerList))) {
QueuePairList_RemoveEntry(&qpBrokerList, &entry->qp);
VMCI_FreeKernelMem(entry, sizeof *entry);
}
- VMCIQPBroker_Unlock();
+ VMCIQPBrokerUnlock();
QueuePairList_Destroy(&qpBrokerList);
}
ASSERT(context);
entry = NULL;
- VMCIQPBroker_Lock();
result = VMCIQPBrokerAllocInt(*handle, peer, flags, privFlags, produceSize,
consumeSize, NULL, context, wakeupCB, clientData,
&entry, &swap);
VMCI_DEBUG_LOG(4, (LGPFX"queue pair broker failed to alloc (result=%d).\n",
result));
}
- VMCIQPBroker_Unlock();
VMCIContext_Release(context);
return result;
}
context = VMCIContext_Get(VMCI_HOST_CONTEXT_ID);
- VMCIQPBroker_Lock();
result = VMCIQPBroker_Detach(handle, context);
- VMCIQPBroker_Unlock();
VMCIContext_Release(context);
return result;
ASSERT(vmkernel || !isLocal);
- if (!isLocal && VMCIHandleArray_HasEntry(context->queuePairArray, handle)) {
+ VMCIQPBrokerLock();
+
+ if (!isLocal && VMCIContext_QueuePairExists(context, handle)) {
VMCI_DEBUG_LOG(4, (LGPFX"Context (ID=0x%x) already attached to queue pair "
"(handle=0x%x:0x%x).\n",
contextId, handle.context, handle.resource));
+ VMCIQPBrokerUnlock();
return VMCI_ERROR_ALREADY_EXISTS;
}
clientData, ent);
}
+ VMCIQPBrokerUnlock();
+
if (swap) {
*swap = (contextId == VMCI_HOST_CONTEXT_ID) && !(create && isLocal);
}
*ent = entry;
}
- ASSERT(!VMCIHandleArray_HasEntry(context->queuePairArray, handle));
- VMCIHandleArray_AppendEntry(&context->queuePairArray, handle);
+ VMCIContext_QueuePairCreate(context, handle);
return VMCI_SUCCESS;
*/
if (!isLocal) {
- VMCIHandleArray_AppendEntry(&context->queuePairArray, entry->qp.handle);
+ VMCIContext_QueuePairCreate(context, entry->qp.handle);
} else {
- ASSERT(VMCIHandleArray_HasEntry(context->queuePairArray,
- entry->qp.handle));
+ ASSERT(VMCIContext_QueuePairExists(context, entry->qp.handle));
}
if (ent != NULL) {
*ent = entry;
return VMCI_ERROR_INVALID_ARGS;
}
- if (!VMCIHandleArray_HasEntry(context->queuePairArray, handle)) {
- VMCI_WARNING((LGPFX"Context (ID=0x%x) not attached to queue pair "
- "(handle=0x%x:0x%x).\n", contextId, handle.context,
- handle.resource));
- result = VMCI_ERROR_NOT_FOUND;
- goto out;
- }
-
/*
* We only support guest to host queue pairs, so the VMX must
* supply UVAs for the mapped page files.
return VMCI_ERROR_INVALID_ARGS;
}
+ VMCIQPBrokerLock();
+
+ if (!VMCIContext_QueuePairExists(context, handle)) {
+ VMCI_WARNING((LGPFX"Context (ID=0x%x) not attached to queue pair "
+ "(handle=0x%x:0x%x).\n", contextId, handle.context,
+ handle.resource));
+ result = VMCI_ERROR_NOT_FOUND;
+ goto out;
+ }
+
entry = (QPBrokerEntry *)QueuePairList_FindEntry(&qpBrokerList, handle);
if (!entry) {
result = VMCI_ERROR_NOT_FOUND;
}
result = VMCI_SUCCESS;
-
out:
+ VMCIQPBrokerUnlock();
return result;
}
const VMCIId contextId = VMCIContext_GetId(context);
VMCIId peerId;
Bool isLocal = FALSE;
+ int result;
if (VMCI_HANDLE_INVALID(handle) || !context || contextId == VMCI_INVALID_ID) {
return VMCI_ERROR_INVALID_ARGS;
}
- if (!VMCIHandleArray_HasEntry(context->queuePairArray, handle)) {
+ VMCIQPBrokerLock();
+
+ if (!VMCIContext_QueuePairExists(context, handle)) {
VMCI_DEBUG_LOG(4, (LGPFX"Context (ID=0x%x) not attached to queue pair "
"(handle=0x%x:0x%x).\n",
contextId, handle.context, handle.resource));
- return VMCI_ERROR_NOT_FOUND;
+ result = VMCI_ERROR_NOT_FOUND;
+ goto out;
}
entry = (QPBrokerEntry *)QueuePairList_FindEntry(&qpBrokerList, handle);
VMCI_DEBUG_LOG(4, (LGPFX"Context (ID=0x%x) reports being attached to queue pair "
"(handle=0x%x:0x%x) that isn't present in broker.\n",
contextId, handle.context, handle.resource));
- return VMCI_ERROR_NOT_FOUND;
+ result = VMCI_ERROR_NOT_FOUND;
+ goto out;
}
if (contextId != entry->createId && contextId != entry->attachId) {
- return VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
+ result = VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
+ goto out;
}
if (contextId == entry->createId) {
VMCIHost_FreeQueue(entry->consumeQ, entry->qp.consumeSize);
VMCI_FreeKernelMem(entry, sizeof *entry);
- VMCIHandleArray_RemoveEntry(context->queuePairArray, handle);
+ VMCIContext_QueuePairDestroy(context, handle);
} else {
ASSERT(peerId != VMCI_INVALID_ID);
QueuePairNotifyPeer(FALSE, handle, contextId, peerId);
entry->state = VMCIQPB_SHUTDOWN_NO_MEM;
}
if (!isLocal) {
- VMCIHandleArray_RemoveEntry(context->queuePairArray, handle);
+ VMCIContext_QueuePairDestroy(context, handle);
}
}
-
- return VMCI_SUCCESS;
+ result = VMCI_SUCCESS;
+out:
+ VMCIQPBrokerUnlock();
+ return result;
}
return VMCI_ERROR_INVALID_ARGS;
}
- if (!VMCIHandleArray_HasEntry(context->queuePairArray, handle)) {
+ VMCIQPBrokerLock();
+
+ if (!VMCIContext_QueuePairExists(context, handle)) {
VMCI_DEBUG_LOG(4, (LGPFX"Context (ID=0x%x) not attached to queue pair "
"(handle=0x%x:0x%x).\n",
contextId, handle.context, handle.resource));
- return VMCI_ERROR_NOT_FOUND;
+ result = VMCI_ERROR_NOT_FOUND;
+ goto out;
}
entry = (QPBrokerEntry *)QueuePairList_FindEntry(&qpBrokerList, handle);
VMCI_DEBUG_LOG(4, (LGPFX"Context (ID=0x%x) reports being attached to queue pair "
"(handle=0x%x:0x%x) that isn't present in broker.\n",
contextId, handle.context, handle.resource));
- return VMCI_ERROR_NOT_FOUND;
+ result = VMCI_ERROR_NOT_FOUND;
+ goto out;
}
if (contextId != entry->createId && contextId != entry->attachId) {
- return VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
+ result = VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
+ goto out;
}
isLocal = entry->qp.flags & VMCI_QPFLAG_LOCAL;
result = VMCI_SUCCESS;
}
+out:
+ VMCIQPBrokerUnlock();
return result;
}
QPBrokerEntry *entry;
const VMCIId contextId = VMCIContext_GetId(context);
Bool isLocal = FALSE;
+ int result;
if (VMCI_HANDLE_INVALID(handle) || !context || contextId == VMCI_INVALID_ID) {
return VMCI_ERROR_INVALID_ARGS;
}
- if (!VMCIHandleArray_HasEntry(context->queuePairArray, handle)) {
+ VMCIQPBrokerLock();
+ if (!VMCIContext_QueuePairExists(context, handle)) {
VMCI_DEBUG_LOG(4, (LGPFX"Context (ID=0x%x) not attached to queue pair "
"(handle=0x%x:0x%x).\n",
contextId, handle.context, handle.resource));
- return VMCI_ERROR_NOT_FOUND;
+ result = VMCI_ERROR_NOT_FOUND;
+ goto out;
}
entry = (QPBrokerEntry *)QueuePairList_FindEntry(&qpBrokerList, handle);
VMCI_DEBUG_LOG(4, (LGPFX"Context (ID=0x%x) reports being attached to queue pair "
"(handle=0x%x:0x%x) that isn't present in broker.\n",
contextId, handle.context, handle.resource));
- return VMCI_ERROR_NOT_FOUND;
+ result = VMCI_ERROR_NOT_FOUND;
+ goto out;
}
if (contextId != entry->createId && contextId != entry->attachId) {
- return VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
+ result = VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
+ goto out;
}
isLocal = entry->qp.flags & VMCI_QPFLAG_LOCAL;
if (contextId != VMCI_HOST_CONTEXT_ID) {
- int result;
-
ASSERT(entry->state != VMCIQPB_CREATED_NO_MEM &&
entry->state != VMCIQPB_SHUTDOWN_NO_MEM &&
entry->state != VMCIQPB_ATTACHED_NO_MEM);
VMCI_ReleaseQueueMutex(entry->produceQ);
}
- return VMCI_SUCCESS;
+ result = VMCI_SUCCESS;
+out:
+ VMCIQPBrokerUnlock();
+ return result;
}
#if !defined(VMKERNEL)
int VMCIQPBroker_Init(void);
void VMCIQPBroker_Exit(void);
-void VMCIQPBroker_Lock(void);
-void VMCIQPBroker_Unlock(void);
int VMCIQPBroker_Alloc(VMCIHandle handle, VMCIId peer, uint32 flags,
VMCIPrivilegeFlags privFlags,
uint64 produceSize, uint64 consumeSize,
cid = VMCIContext_GetId(context);
- VMCIQPBroker_Lock();
result = VMCIQPBroker_Alloc(handle, peer, flags, VMCI_NO_PRIVILEGE_FLAGS,
produceSize, consumeSize, pageStore, context);
if (result == VMCI_SUCCESS && vmToVm) {
result = VMCI_SUCCESS_QUEUEPAIR_CREATE;
}
- Log(LGPFX"IOCTL_VMCI_QUEUEPAIR_ALLOC (cid=%u,result=%d).\n", cid, result);
retval = copy_to_user(resultUVA, &result, sizeof result);
if (retval) {
retval = -EFAULT;
}
}
- VMCIQPBroker_Unlock();
-
return retval;
}
* VMX is passing down a new VA for the queue pair mapping.
*/
- VMCIQPBroker_Lock();
result = VMCIQPBroker_Map(setVAInfo.handle, vmciLinux->context, setVAInfo.va);
- VMCIQPBroker_Unlock();
- Log(LGPFX"IOCTL_VMCI_QUEUEPAIR_SETVA - map (result=%d).\n", result);
} else {
/*
* The queue pair is about to be unmapped by the VMX.
*/
- VMCIQPBroker_Lock();
result = VMCIQPBroker_Unmap(setVAInfo.handle, vmciLinux->context, 0);
- VMCIQPBroker_Unlock();
- Log(LGPFX"IOCTL_VMCI_QUEUEPAIR_SETVA - unmap (result=%d).\n", result);
}
retval = copy_to_user(&info->result, &result, sizeof result);
VMCIQueuePairPageFileInfo pageFileInfo;
VMCIQueuePairPageFileInfo *info = (VMCIQueuePairPageFileInfo *)ioarg;
int32 result;
- VMCIId cid;
if (vmciLinux->userVersion < VMCI_VERSION_HOSTQP ||
vmciLinux->userVersion >= VMCI_VERSION_NOVMVM) {
result = VMCI_SUCCESS;
retval = copy_to_user(&info->result, &result, sizeof result);
if (retval == 0) {
- VMCIQPBroker_Lock();
-
result = VMCIQPBroker_SetPageStore(pageFileInfo.handle,
pageFileInfo.produceVA,
pageFileInfo.consumeVA,
vmciLinux->context);
-
- VMCIQPBroker_Unlock();
- cid = VMCIContext_GetId(vmciLinux->context);
- Log(LGPFX"IOCTL_VMCI_QUEUEPAIR_SETPAGEFILE (cid=%u,result=%d).\n",
- cid, result);
-
if (result < VMCI_SUCCESS) {
retval = copy_to_user(&info->result, &result, sizeof result);
VMCIQueuePairDetachInfo detachInfo;
VMCIQueuePairDetachInfo *info = (VMCIQueuePairDetachInfo *)ioarg;
int32 result;
- VMCIId cid;
if (vmciLinux->ctType != VMCIOBJ_CONTEXT) {
Log(LGPFX"IOCTL_VMCI_QUEUEPAIR_DETACH only valid for contexts.\n");
break;
}
- cid = VMCIContext_GetId(vmciLinux->context);
- VMCIQPBroker_Lock();
result = VMCIQPBroker_Detach(detachInfo.handle, vmciLinux->context);
- Log(LGPFX"IOCTL_VMCI_QUEUEPAIR_DETACH (cid=%u,result=%d).\n",
- cid, result);
- VMCIQPBroker_Unlock();
-
if (result == VMCI_SUCCESS &&
vmciLinux->userVersion < VMCI_VERSION_NOVMVM) {
result = VMCI_SUCCESS_LAST_DETACH;
#ifndef _VMCI_VERSION_H_
#define _VMCI_VERSION_H_
-#define VMCI_DRIVER_VERSION 9.3.12.0
-#define VMCI_DRIVER_VERSION_COMMAS 9,3,12,0
-#define VMCI_DRIVER_VERSION_STRING "9.3.12.0"
+#define VMCI_DRIVER_VERSION 9.3.13.0
+#define VMCI_DRIVER_VERSION_COMMAS 9,3,13,0
+#define VMCI_DRIVER_VERSION_STRING "9.3.13.0"
#endif /* _VMCI_VERSION_H_ */