]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Internal branch sync. Included in this change:
authorVMware, Inc <>
Wed, 26 Dec 2012 21:20:54 +0000 (13:20 -0800)
committerDmitry Torokhov <dtor@vmware.com>
Thu, 27 Dec 2012 19:15:59 +0000 (11:15 -0800)
. fix crash in File_GetVMFSMountInfo()
. fix crash in File_GetMountInfo with NFS4.1
. lib/file: restore atomic file updates on ESX NFS for descriptor writes
. VMCI/VSOCK: find the context ID of a running VM given a UUID

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/lib/file/fileIO.c
open-vm-tools/lib/file/filePosix.c
open-vm-tools/lib/include/fileIO.h
open-vm-tools/lib/include/vmci_sockets.h
open-vm-tools/modules/linux/shared/vmci_iocontrols.h
open-vm-tools/modules/linux/shared/vmci_kernel_if.h
open-vm-tools/modules/linux/vmci/common/vmciContext.c
open-vm-tools/modules/linux/vmci/common/vmciContext.h

index 8eb605c6c06da8040c224bfab29562dcb07be127..119ce06a99819dac5102344da9113dbb5f5b5bd9 100644 (file)
@@ -797,19 +797,11 @@ bail:
  *      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:
@@ -818,16 +810,15 @@ bail:
  *-----------------------------------------------------------------------------
  */
 
-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;
@@ -894,7 +885,7 @@ FileIO_AtomicUpdate(FileIODescriptor *newFD,   // IN/OUT: file IO descriptor
             ASSERT_BUG_DEBUGONLY(615124, errno != EBUSY);
          }
       } else {
-         ret = 1;
+         ret = TRUE;
       }
 
       close(fd);
@@ -907,35 +898,31 @@ FileIO_AtomicUpdate(FileIODescriptor *newFD,   // IN/OUT: file IO descriptor
        * 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:
index 880219b6a0ec5ed4a027833f69a50979a7675c25..36387b18d0341c679b7ce21b61a879c18905148a 100644 (file)
@@ -1145,6 +1145,8 @@ File_GetVMFSAttributes(ConstUnicode pathName,             // IN: File to test
       Log(LGPFX" %s: could not open %s: %s\n", __func__, UTF8(pathName),
           Err_Errno2String(errno));
       ret = -1;
+      free(*fsAttrs);
+      *fsAttrs = NULL;
       goto bail;
    }
 
@@ -1154,6 +1156,8 @@ File_GetVMFSAttributes(ConstUnicode pathName,             // IN: File to test
    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:
@@ -1286,7 +1290,7 @@ File_GetVMFSMountInfo(ConstUnicode pathName,   // IN:
 {
    int ret;
    int len;
-   FS_PartitionListResult *fsAttrs;
+   FS_PartitionListResult *fsAttrs = NULL;
 
    *localMountPoint = File_GetUniqueFileSystemID(pathName);
 
@@ -1309,9 +1313,9 @@ File_GetVMFSMountInfo(ConstUnicode pathName,   // IN:
          *remoteIP = NULL;
          *remoteMountPoint = NULL;   
       }  
-   }
 
-   free(fsAttrs);
+      free(fsAttrs);
+   }
 
    return ret;
 }
index dd9725f779401fcbdb3cce904bac42561002b0d2..404e4b27012b686c90019f392fe8f644ae6f0c43 100644 (file)
@@ -314,9 +314,8 @@ Unicode FileIO_AtomicTempPath(ConstUnicode path);
 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__)
 
index 0493f99f25bea12f72557043986abd9217e59938..7609250bad64bd8953eeafdf23aaacde34b95319 100644 (file)
@@ -410,6 +410,13 @@ struct sockaddr_vm {
    /** \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)
@@ -418,6 +425,7 @@ struct sockaddr_vm {
 #     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)
       {
@@ -459,6 +467,24 @@ struct sockaddr_vm {
       {
          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__))
@@ -470,14 +496,14 @@ struct sockaddr_vm {
 #  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"
@@ -485,11 +511,13 @@ struct sockaddr_vm {
 #     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 */
 
@@ -729,6 +757,60 @@ struct sockaddr_vm {
       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
index e5aa7cc63e5732a22fa073c6d1c1839186078d9b..e1355ec3fde8cd6060f9981d2416332975a61219 100644 (file)
@@ -288,16 +288,17 @@ enum IOCTLCmd_VMCI {
    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
index 2993c77f486ca57c46ab9a11fe6014b98480669f..4163aabb2cd7c125155586dbc4031a26082c0fe6 100644 (file)
@@ -252,6 +252,7 @@ Bool VMCIHost_WaitForCallLocked(VMCIHost *hostContext,
                                 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);
index 0e05de5e04f69b4ff80d77febfdde69fc9a7821f..207cec98799a2e822f80145bf4c086edc4e244e0 100644 (file)
@@ -2557,7 +2557,6 @@ VMCIContext_ReleaseGuestMem(VMCIContext *context, // IN: Context structure
 }
 
 #if defined(VMKERNEL)
-
 /*
  *----------------------------------------------------------------------
  *
@@ -2637,5 +2636,56 @@ VMCIContextInFilterCleanup(VMCIContext *context)
    }
 }
 
-#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
index 2546097302af9f6042435ce3445c0a80aa6b0c33..93e37a8d2c511907a7935732897515b7fc275dcd 100644 (file)
@@ -114,8 +114,7 @@ void VMCIContext_ReceiveNotificationsRelease(VMCIId contextID,
 #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_