* On hosted products, uses rename to swap files, so "new" becomes "curr",
* and path to "new" no longer exists on success.
*
- * On ESX on NFS:
- *
- * If renameOnNFS is TRUE, use rename, like on hosted.
- *
- * If renameOnNFS is FALSE, returns -1 rather than trying to use rename,
- * to avoid various bugs in the vmkernel NFSv3 client. Bug 839283,
- * bug 862647, bug 841185, bug 856752.
- *
* On success the caller must call FileIO_IsValid on newFD to verify it
* is still open before using it again.
*
* Results:
- * 1 if successful, 0 on failure, -1 if not supported on this filesystem.
+ * TRUE if successful, FALSE otherwise
* errno is preserved.
*
* Side effects:
*-----------------------------------------------------------------------------
*/
-int
+Bool
FileIO_AtomicUpdate(FileIODescriptor *newFD, // IN/OUT: file IO descriptor
- FileIODescriptor *currFD, // IN/OUT: file IO descriptor
- Bool renameOnNFS) // IN: fall back to rename on NFS
+ FileIODescriptor *currFD) // IN/OUT: file IO descriptor
{
char *currPath;
char *newPath;
uint32 currAccess;
uint32 newAccess;
- int ret = 0;
+ Bool ret = FALSE;
FileIOResult status;
FileIODescriptor tmpFD;
int savedErrno = 0;
ASSERT_BUG_DEBUGONLY(615124, errno != EBUSY);
}
} else {
- ret = 1;
+ ret = TRUE;
}
close(fd);
* Check for both ENOSYS and ENOTTY. PR 957695
*/
if (savedErrno == ENOSYS || savedErrno == ENOTTY) {
- if (renameOnNFS) {
- /*
- * NFS allows renames of locked files, even if both files
- * are locked. The file lock follows the file handle, not
- * the name, so after the rename we can swap the underlying
- * file descriptors instead of closing and reopening the
- * target file.
- *
- * This is different than the hosted path below because
- * ESX uses native file locks and hosted does not.
- *
- * We assume that all ESX file systems that support rename
- * have the same file lock semantics as NFS.
- */
-
- if (File_Rename(newPath, currPath)) {
- Log("%s: rename of '%s' to '%s' failed %d.\n",
- __FUNCTION__, newPath, currPath, errno);
- savedErrno = errno;
- goto swapdone;
- }
- ret = 1;
- fd = newFD->posix;
- newFD->posix = currFD->posix;
- currFD->posix = fd;
- FileIO_Close(newFD);
- } else {
- ret = -1;
+ /*
+ * NFS allows renames of locked files, even if both files
+ * are locked. The file lock follows the file handle, not
+ * the name, so after the rename we can swap the underlying
+ * file descriptors instead of closing and reopening the
+ * target file.
+ *
+ * This is different than the hosted path below because
+ * ESX uses native file locks and hosted does not.
+ *
+ * We assume that all ESX file systems that support rename
+ * have the same file lock semantics as NFS.
+ */
+
+ if (File_Rename(newPath, currPath)) {
+ Log("%s: rename of '%s' to '%s' failed %d.\n",
+ __FUNCTION__, newPath, currPath, errno);
+ savedErrno = errno;
+ goto swapdone;
}
+ ret = TRUE;
+ fd = newFD->posix;
+ newFD->posix = currFD->posix;
+ currFD->posix = fd;
+ FileIO_Close(newFD);
}
swapdone:
Log(LGPFX" %s: could not open %s: %s\n", __func__, UTF8(pathName),
Err_Errno2String(errno));
ret = -1;
+ free(*fsAttrs);
+ *fsAttrs = NULL;
goto bail;
}
if (ret == -1) {
Log(LGPFX" %s: Could not get volume attributes (ret = %d): %s\n",
__func__, ret, Err_Errno2String(errno));
+ free(*fsAttrs);
+ *fsAttrs = NULL;
}
bail:
{
int ret;
int len;
- FS_PartitionListResult *fsAttrs;
+ FS_PartitionListResult *fsAttrs = NULL;
*localMountPoint = File_GetUniqueFileSystemID(pathName);
*remoteIP = NULL;
*remoteMountPoint = NULL;
}
- }
- free(fsAttrs);
+ free(fsAttrs);
+ }
return ret;
}
FileIOResult FileIO_AtomicTempFile(FileIODescriptor *fileFD,
FileIODescriptor *tempFD);
-int FileIO_AtomicUpdate(FileIODescriptor *newFD,
- FileIODescriptor *currFD,
- Bool renameOnNFS);
+Bool FileIO_AtomicUpdate(FileIODescriptor *newFD,
+ FileIODescriptor *currFD);
#if !defined(VMX86_TOOLS) || !defined(__FreeBSD__)
/** \endcond */
};
+/** \cond PRIVATE */
+struct uuid_2_cid {
+ unsigned int u2c_context_id;
+ unsigned int u2c_pad;
+ char u2c_uuid_string[128];
+};
+/** \endcond */
#if defined(_WIN32)
# if !defined(NT_INCLUDED)
# define VMCI_SOCKETS_VERSION 0x81032058
# define VMCI_SOCKETS_GET_AF_VALUE 0x81032068
# define VMCI_SOCKETS_GET_LOCAL_CID 0x8103206c
+# define VMCI_SOCKETS_UUID_2_CID 0x810320a4
static __inline unsigned int __VMCISock_DeviceIoControl(DWORD cmd)
{
{
return __VMCISock_DeviceIoControl(VMCI_SOCKETS_GET_LOCAL_CID);
}
+
+ static __inline unsigned int VMCISock_Uuid2ContextId(const char *uuidString)
+ {
+ struct uuid_2_cid io;
+ HANDLE device = CreateFileW(VMCI_SOCKETS_DEVICE, GENERIC_READ, 0, NULL,
+ OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+ io.u2c_context_id = VMADDR_CID_ANY;
+ if (INVALID_HANDLE_VALUE != device) {
+ DWORD ioReturn;
+ strncpy_s(io.u2c_uuid_string, sizeof io.u2c_uuid_string,
+ uuidString, _TRUNCATE);
+ DeviceIoControl(device, VMCI_SOCKETS_UUID_2_CID, &io, sizeof io,
+ &io, sizeof io, &ioReturn, NULL);
+ CloseHandle(device);
+ device = INVALID_HANDLE_VALUE;
+ }
+ return io.u2c_context_id;
+ }
# endif // !NT_INCLUDED
#else // _WIN32
#if (defined(linux) && !defined(VMKERNEL)) || (defined(__APPLE__))
# elif defined(__APPLE__) && (KERNEL)
/* Nothing to define here. */
# else // __KERNEL__
-# include <sys/types.h>
-# include <sys/stat.h>
# include <fcntl.h>
+# include <stdio.h>
+# include <string.h>
# include <sys/ioctl.h>
+# include <sys/stat.h>
+# include <sys/types.h>
# include <unistd.h>
-# include <stdio.h>
-
/** \cond PRIVATE */
# define VMCI_SOCKETS_DEFAULT_DEVICE "/dev/vsock"
# define VMCI_SOCKETS_CLASSIC_ESX_DEVICE "/vmfs/devices/char/vsock/vsock"
# define VMCI_SOCKETS_VERSION 1972
# define VMCI_SOCKETS_GET_AF_VALUE 1976
# define VMCI_SOCKETS_GET_LOCAL_CID 1977
+# define VMCI_SOCKETS_UUID_2_CID 1991
# elif defined(__APPLE__)
# include <sys/ioccom.h>
-# define VMCI_SOCKETS_VERSION _IOR('V', 21, unsigned)
-# define VMCI_SOCKETS_GET_AF_VALUE _IOR('V', 25 , int)
-# define VMCI_SOCKETS_GET_LOCAL_CID _IOR('V', 26 , unsigned)
+# define VMCI_SOCKETS_VERSION _IOR( 'V', 21, unsigned)
+# define VMCI_SOCKETS_GET_AF_VALUE _IOR( 'V', 25, int)
+# define VMCI_SOCKETS_GET_LOCAL_CID _IOR( 'V', 26, unsigned)
+# define VMCI_SOCKETS_UUID_2_CID _IOWR('V', 40, struct uuid_2_cid)
#endif
/** \endcond */
close(fd);
return contextId;
}
+
+ /*
+ ***********************************************************************
+ * VMCISock_Uuid2ContextId */ /**
+ *
+ * \brief Retrieve the context ID of a running VM, given a VM's UUID.
+ *
+ * Retrieves the context ID of a running virtual machine given that virtual
+ * machines's unique identifier. The identifier is local to the host and
+ * its meaning is platform-specific. On ESX, which is currently the only
+ * supported platform, it is the "bios.uuid" field as specified in the VM's
+ * VMX file.
+ *
+ * \see VMADDR_CID_ANY
+ *
+ * \retval VMADDR_CID_ANY Not available.
+ * \retval other The VM's context ID.
+ *
+ * \note Only available for ESX (userworld) endpoints.
+ *
+ * An example is given below.
+ *
+ * \code
+ * int vmciFd;
+ * int af = VMCISock_GetAFValueFd(&vmciFd);
+ * unsigned int cid = VMCISock_Uuid2ContextId(
+ * "56 4d 07 d8 cc d5 c4 0d-98 44 dc 1e 8f e0 da f3");
+ * VMCISock_ReleaseAFValueFd(vmciFd);
+ * \endcode
+ *
+ ***********************************************************************
+ */
+
+ static inline unsigned int VMCISock_Uuid2ContextId(const char *uuidString)
+ {
+ int fd;
+ struct uuid_2_cid io;
+
+ fd = open(VMCI_SOCKETS_DEFAULT_DEVICE, O_RDWR);
+ if (fd < 0) {
+ fd = open(VMCI_SOCKETS_CLASSIC_ESX_DEVICE, O_RDWR);
+ if (fd < 0) {
+ return VMADDR_CID_ANY;
+ }
+ }
+
+ strncpy(io.u2c_uuid_string, uuidString, sizeof io.u2c_uuid_string);
+ if (ioctl(fd, VMCI_SOCKETS_UUID_2_CID, &io) < 0) {
+ io.u2c_context_id = VMADDR_CID_ANY;
+ }
+
+ close(fd);
+ return io.u2c_context_id;
+ }
# endif // __KERNEL__
#endif // linux && !VMKERNEL
#endif // _WIN32
IOCTLCMD(SOCKETS_SEND_TO),
IOCTLCMD(SOCKETS_SET_SOCK_OPT),
IOCTLCMD(SOCKETS_SHUTDOWN),
- IOCTLCMD(SOCKETS_SOCKET), /* 1990 on Linux. */
+ IOCTLCMD(SOCKETS_SOCKET),
+ IOCTLCMD(SOCKETS_UUID_2_CID), /* 1991 on Linux. */
/* END VMCI SOCKETS */
/*
- * We reserve a range of 4 ioctls for VMCI Sockets to grow. We cannot
+ * We reserve a range of 3 ioctls for VMCI Sockets to grow. We cannot
* reserve many ioctls here since we are close to overlapping with vmmon
* ioctls. Define a meta-ioctl if running out of this binary space.
*/
// Must be last.
- IOCTLCMD(SOCKETS_LAST) = IOCTLCMD(SOCKETS_SOCKET) + 4, /* 1994 on Linux. */
+ IOCTLCMD(SOCKETS_LAST) = IOCTLCMD(SOCKETS_UUID_2_CID) + 3, /* 1994 on Linux. */
/*
* The VSockets ioctls occupy the block above. We define a new range of
* VMCI ioctls to maintain binary compatibility between the user land and
Bool useBH);
#ifdef VMKERNEL
int VMCIHost_ContextToHostVmID(VMCIHost *hostContext, VMCIHostVmID *hostVmID);
+int VMCIHost_ContextHasUuid(VMCIHost *hostContext, const char *uuid);
void VMCIHost_SetActiveHnd(VMCIHost *hostContext, uintptr_t eventHnd);
Bool VMCIHost_RemoveHnd(VMCIHost *hostContext, uintptr_t eventHnd);
Bool VMCIHost_IsActiveHnd(VMCIHost *hostContext, uintptr_t eventHnd);
}
#if defined(VMKERNEL)
-
/*
*----------------------------------------------------------------------
*
}
}
-#endif
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMCI_Uuid2ContextId --
+ *
+ * Given a running VM's UUID, retrieve the VM's VMCI context ID.
+ * The given UUID is local to the host; it is _not_ the UUID
+ * handed out by VC. It comes from the "bios.uuid" field in the
+ * VMX file. We walk the context list and try to match the given
+ * UUID against each context. If we get a match, we return the
+ * contexts's VMCI ID.
+ *
+ * Results:
+ * VMCI_SUCCESS if found and *contextID contains the CID.
+ * VMCI_ERROR_INVALID_ARGS for bad parameters.
+ * VMCI_ERROR_NOT_FOUND if no match.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+VMCI_Uuid2ContextId(const char *uuidString, // IN
+ VMCIId *contextID) // OUT
+{
+ int err;
+ VMCIListItem *next;
+ VMCILockFlags flags;
+
+ if (!uuidString || *uuidString == '\0' || !contextID) {
+ return VMCI_ERROR_INVALID_ARGS;
+ }
+
+ err = VMCI_ERROR_NOT_FOUND;
+
+ VMCI_GrabLock(&contextList.lock, &flags);
+ VMCIList_Scan(next, &contextList.head) {
+ VMCIContext *context = VMCIList_Entry(next, VMCIContext, listItem);
+ if (VMCIHost_ContextHasUuid(&context->hostContext, uuidString) ==
+ VMCI_SUCCESS) {
+ *contextID = context->cid;
+ err = VMCI_SUCCESS;
+ break;
+ }
+ }
+ VMCI_ReleaseLock(&contextList.lock, flags);
+
+ return err;
+}
+#endif // VMKERNEL
#if defined(VMKERNEL)
void VMCIContext_SignalPendingDoorbells(VMCIId contextID);
void VMCIContext_SignalPendingDatagrams(VMCIId contextID);
-
-int VMCIContextID2HostVmID(VMCIId contextID, void *hostVmID, size_t hostVmIDLen);
int VMCIContext_FilterSet(VMCIId cid, VMCIFilterState *filterState);
-#endif
+int VMCI_Uuid2ContextId(const char *uuidString, VMCIId *contextID);
+#endif // VMKERNEL
#endif // _VMCI_CONTEXT_H_