]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Hgfs Over VMCI - Mac OSX. Synchronous.
authorVMware, Inc <>
Thu, 18 Nov 2010 21:22:40 +0000 (13:22 -0800)
committerMarcelo Vanzin <mvanzin@vmware.com>
Thu, 18 Nov 2010 21:22:40 +0000 (13:22 -0800)
This is resubmission of change that was backed out.
I have changed mostly channel switching logic that was broken. Now
we store the channel in every request so that we call free/allocate/send
of the same channel when global hgfs channel resets to some different
channel.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
13 files changed:
open-vm-tools/modules/freebsd/vmhgfs/Makefile
open-vm-tools/modules/freebsd/vmhgfs/bdhandler.c [new file with mode: 0644]
open-vm-tools/modules/freebsd/vmhgfs/channel.h [new file with mode: 0644]
open-vm-tools/modules/freebsd/vmhgfs/debug.h
open-vm-tools/modules/freebsd/vmhgfs/os.c
open-vm-tools/modules/freebsd/vmhgfs/request.c
open-vm-tools/modules/freebsd/vmhgfs/request.h
open-vm-tools/modules/freebsd/vmhgfs/requestInt.h
open-vm-tools/modules/freebsd/vmhgfs/transport.c
open-vm-tools/modules/freebsd/vmhgfs/vfsopscommon.c
open-vm-tools/modules/freebsd/vmhgfs/vmci.c [new file with mode: 0644]
open-vm-tools/modules/freebsd/vmhgfs/vnopscommon.c
open-vm-tools/modules/freebsd/vmhgfs/worker.c

index 06b24a051dd68eea7ebaed5d4b5051867cd0d23d..9f065f188fba2aab767c74cd6f5332ab67b0cfe6 100644 (file)
@@ -29,6 +29,7 @@ HEADERS += vnopscommon.h
 HEADERS += os.h
 HEADERS += vfsopscommon.h
 HEADERS += transport.h
+HEADERS += channel.h
 
 COMMON_SRCS := cpName.c
 COMMON_SRCS += cpNameLinux.c
@@ -46,6 +47,7 @@ COMMON_SRCS += backdoorGcc32.c
 .endif
 
 COMMON_HGFS_SRCS := debug.c
+COMMON_HGFS_SRCS := bdhandler.c
 COMMON_HGFS_SRCS += request.c
 COMMON_HGFS_SRCS += worker.c
 COMMON_HGFS_SRCS += fsutil.c
@@ -57,6 +59,7 @@ COMMON_HGFS_SRCS += transport.c
 MODULE_SRCS := vnops.c
 MODULE_SRCS += vfsops.c
 MODULE_SRCS += os.c
+MODULE_SRCS += vmci.c
 MODULE_SRCS += hgfsUtil.c
 MODULE_SRCS += kernelStubsBSD.c
 
diff --git a/open-vm-tools/modules/freebsd/vmhgfs/bdhandler.c b/open-vm-tools/modules/freebsd/vmhgfs/bdhandler.c
new file mode 100644 (file)
index 0000000..3c92343
--- /dev/null
@@ -0,0 +1,236 @@
+/*********************************************************
+ * Copyright (C) 2010 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * bdhandler.c --
+ *
+ */
+
+#include "hgfsBd.h"
+#include "rpcout.h"
+#include "channel.h"
+
+static Bool HgfsBdChannelOpen(HgfsTransportChannel *channel);
+static void HgfsBdChannelClose(HgfsTransportChannel *channel);
+static HgfsKReqObject * HgfsBdChannelAllocate(size_t payloadSize, int flags);
+void HgfsBdChannelFree(HgfsKReqObject *req, size_t payloadSize);
+static int HgfsBdChannelSend(HgfsTransportChannel *channel, HgfsKReqObject *req);
+
+static HgfsTransportChannel gBdChannel = {
+   .name = "backdoor",
+   .ops.open = HgfsBdChannelOpen,
+   .ops.close = HgfsBdChannelClose,
+   .ops.allocate = HgfsBdChannelAllocate,
+   .ops.free = HgfsBdChannelFree,
+   .ops.send = HgfsBdChannelSend,
+   .priv = NULL,
+   .status = HGFS_CHANNEL_NOTCONNECTED
+};
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsBdChannelOpen --
+ *
+ *      Open the backdoor in an idempotent way.
+ *
+ * Results:
+ *      TRUE on success, FALSE on failure.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsBdChannelOpen(HgfsTransportChannel *channel) // IN: Channel
+{
+   Bool ret;
+
+   if ((ret = HgfsBd_OpenBackdoor((RpcOut **)&channel->priv))) {
+      DEBUG(VM_DEBUG_INFO, "VMware hgfs: %s: backdoor opened.\n", __func__);
+      ASSERT(channel->priv != NULL);
+      channel->status = HGFS_CHANNEL_CONNECTED;
+   }
+
+   return ret;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsBdChannelClose --
+ *
+ *      Close the backdoor in an idempotent way.
+ *
+ * Results:
+ *      None
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsBdChannelClose(HgfsTransportChannel *channel) // IN: Channel
+{
+   int ret;
+
+   if (channel->priv == NULL) {
+      return;
+   }
+
+   ret = HgfsBd_CloseBackdoor((RpcOut **)&channel->priv);
+   if (!ret) {
+      DEBUG(VM_DEBUG_FAIL, "VMware hgfs: %s: Failed to close backdoor.\n", __func__);
+   } else {
+      DEBUG(VM_DEBUG_INFO, "VMware hgfs: %s: backdoor closed.\n", __func__);
+   }
+   channel->status = HGFS_CHANNEL_NOTCONNECTED;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsBdChannelAllocate --
+ *
+ *      Allocate request in a way that is suitable for sending through
+ *      backdoor.
+ *
+ * Results:
+ *      NULL on failure; otherwise address of the new request.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static HgfsKReqObject *
+HgfsBdChannelAllocate(size_t payloadSize,   // IN: Size of allocation
+                      int flags)            // IN:
+{
+   return os_malloc(payloadSize, flags);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsBdChannelFree --
+ *
+ *     Free previously allocated request.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HgfsBdChannelFree(HgfsKReqObject *req,    // IN:
+                  size_t payloadSize)     // IN:
+{
+   ASSERT(req);
+   os_free(req, payloadSize);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsBdChannelSend --
+ *
+ *     Send a request via backdoor.
+ *
+ * Results:
+ *     0 on success, negative error on failure.
+ *
+ * Side effects:
+ *     None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HgfsBdChannelSend(HgfsTransportChannel *channel, // IN: Channel
+                  HgfsKReqObject *req)           // IN: request to send
+{
+   char const *replyPacket = NULL;
+   int ret;
+
+   ASSERT(req);
+
+   DEBUG(VM_DEBUG_INFO, "VMware hgfs: %s: backdoor sending.\n", __func__);
+
+   bcopy(HGFS_SYNC_REQREP_CLIENT_CMD, req->__rpc_packet._command,
+         HGFS_SYNC_REQREP_CLIENT_CMD_LEN);
+
+   ret = HgfsBd_Dispatch(channel->priv, req->payload, &req->payloadSize,
+                         &replyPacket);
+   os_mutex_lock(req->stateLock);
+
+   /*
+    * We have a response.  (Maybe.)  Re-lock the request, update its state,
+    * etc.
+    */
+   if ((ret == 0) && (req->state == HGFS_REQ_SUBMITTED)) {
+      DEBUG(VM_DEBUG_INFO, "VMware hgfs: %s: Success in backdoor.\n", __func__);
+      bcopy(replyPacket, req->payload, req->payloadSize);
+      req->state = HGFS_REQ_COMPLETED;
+   } else {
+      DEBUG(VM_DEBUG_INFO, "hgfs: %s: Error in backdoor.\n", __func__);
+      req->state = HGFS_REQ_ERROR;
+   }
+
+   os_cv_signal(&req->stateCv);
+   os_mutex_unlock(req->stateLock);
+   return ret;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsGetBdChannel --
+ *
+ *     Get backdoor channel.
+ *
+ * Results:
+ *     Always return pointer to back door channel.
+ *
+ * Side effects:
+ *     None
+ *
+ *----------------------------------------------------------------------
+ */
+
+HgfsTransportChannel*
+HgfsGetBdChannel(void)
+{
+   return &gBdChannel;
+}
+
diff --git a/open-vm-tools/modules/freebsd/vmhgfs/channel.h b/open-vm-tools/modules/freebsd/vmhgfs/channel.h
new file mode 100644 (file)
index 0000000..0fcae72
--- /dev/null
@@ -0,0 +1,60 @@
+/*********************************************************
+ * Copyright (C) 2010 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * channel.h --
+ */
+
+#ifndef _HGFS_CHANNEL_H_
+#define _HGFS_CHANNEL__H_
+
+#include "hgfs_kernel.h"
+#include "requestInt.h"
+
+/*
+ * There are the operations a channel should implement.
+ */
+struct HgfsTransportChannel;
+typedef struct HgfsTransportChannelOps {
+   Bool (*open)(struct HgfsTransportChannel *);
+   void (*close)(struct HgfsTransportChannel *);
+   HgfsKReqObject* (*allocate)(size_t payloadSize, int flags);
+   int (*send)(struct HgfsTransportChannel *, HgfsKReqObject *);
+   void (*free)(HgfsKReqObject *, size_t payloadSize);
+} HgfsTransportChannelOps;
+
+typedef enum {
+   HGFS_CHANNEL_UNINITIALIZED,
+   HGFS_CHANNEL_NOTCONNECTED,
+   HGFS_CHANNEL_CONNECTED,
+   HGFS_CHANNEL_DEAD,   /* Error has been detected, need to shut it down. */
+} HgfsChannelStatus;
+
+typedef struct HgfsTransportChannel {
+   const char *name;               /* Channel name. */
+   HgfsTransportChannelOps ops;    /* Channel ops. */
+   HgfsChannelStatus status;       /* Connection status. */
+   void *priv;                     /* Channel private data. */
+} HgfsTransportChannel;
+
+HgfsTransportChannel *HgfsGetBdChannel(void);
+HgfsTransportChannel *HgfsGetVmciChannel(void);
+Bool HgfsSetupNewChannel(void);
+extern HgfsTransportChannel *gHgfsChannel;
+
+#endif // _HGFS_CHANNEL_H_
index e2968157a59c52d48c8a86a2a5c85ff9878f4afb..3baede77f6d9f1fd600b0ebc54610f40651dce61 100644 (file)
@@ -88,7 +88,7 @@
                  ((type & VM_DEBUG_LEV) ?                     \
                   (kprintf("%s:%u: " fmt,                     \
                        __func__, __LINE__, ##__VA_ARGS__))    \
-                  : 0)
+                  : (void)0)
 #  endif
 #else
 #  define DEBUG(type, ...)
index 0ac3af2ee88039da762a4c62ab85b93ef0ee7e85..2bfae4d09b94d8804eb36eedccfbfa18fae68fbb 100644 (file)
@@ -40,6 +40,7 @@
 #include "vm_basic_types.h"
 #include "os.h"
 #include "debug.h"
+#include "channel.h"
 #include "compat_freebsd.h"
 
 /*
@@ -187,12 +188,20 @@ os_zone_destroy(OS_ZONE_T *zone) // IN
 
 void *
 os_zone_alloc(OS_ZONE_T *zone, // IN
-             int flags)       // IN
+              int flags)       // IN
 {
+   void *mem;
+   HgfsTransportChannel *channel = gHgfsChannel;
+   HgfsKReqObject *req;
    ASSERT(zone);
    ASSERT(zone->umaZone);
 
-   return uma_zalloc(zone->umaZone, flags);
+   mem = uma_zalloc(zone->umaZone, flags | M_ZERO);
+   if (mem) {
+      req = (HgfsKReqObject *)mem;
+      req->channel = channel;
+   }
+   return mem;
 }
 
 
@@ -215,7 +224,7 @@ os_zone_alloc(OS_ZONE_T *zone, // IN
 
 void
 os_zone_free(OS_ZONE_T *zone, // IN
-            void *mem)       // IN
+             void *mem)       // IN
 {
    ASSERT(zone);
    ASSERT(zone->umaZone);
index 5d3eea68efbaecc591399ca017e3941c951f97f9..f9828c50b1142241d21f3240ac52d0cb1f03cc75 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "hgfs_kernel.h"
 #include "requestInt.h"
+#include "channel.h"
 
 /*
  * Macros
@@ -62,10 +63,10 @@ OS_CV_T hgfsKReqWorkItemCv;
  * Local functions (prototypes)
  */
 
-   static int   HgfsKReqZCtor(void *mem, int size, void *arg, int flags);
-   static void  HgfsKReqZDtor(void *mem, int size, void *arg);
-   static int   HgfsKReqZInit(void *mem, int size, int flags);
-   static void  HgfsKReqZFini(void *mem, int size);
+static int   HgfsKReqZCtor(void *mem, int size, void *arg, int flags);
+static void  HgfsKReqZDtor(void *mem, int size, void *arg);
+static int   HgfsKReqZInit(void *mem, int size, int flags);
+static void  HgfsKReqZFini(void *mem, int size);
 
 /*
  * Global functions (definitions)
@@ -370,7 +371,7 @@ HgfsKReq_ContainerIsEmpty(HgfsKReqContainerHandle container)       // IN:
  *      interrupted by a signal.
  *
  * Results:
- *      Pointer to fresh HgfsKReqObject or NULL on failure.
+ *      0 on success, error code on failure.
  *
  * Side effects:
  *      Request inserted into caller's requests container.  This routine may
@@ -379,15 +380,32 @@ HgfsKReq_ContainerIsEmpty(HgfsKReqContainerHandle container)       // IN:
  *----------------------------------------------------------------------------
  */
 
-HgfsKReqObject *
-HgfsKReq_AllocateRequest(HgfsKReqContainerHandle container)        // IN
+HgfsKReqHandle
+HgfsKReq_AllocateRequest(HgfsKReqContainerHandle container,  // IN:
+                         int *errorRet)                      // OUT:
 {
    HgfsKReqObject *req;
 
+   ASSERT(errorRet);
    ASSERT(container);
 
+   *errorRet = 0;
+
+   if (!gHgfsChannel) {
+      *errorRet = EIO;
+      return NULL;
+   }
+
+   if (gHgfsChannel->status != HGFS_CHANNEL_CONNECTED) {
+      if (!HgfsSetupNewChannel()) {
+         *errorRet = EIO;
+         return NULL;
+      }
+   }
+
    req = os_zone_alloc(hgfsKReqZone, M_WAITOK);
    if (!req) {
+      *errorRet = ENOMEM;
       return NULL;
    }
 
@@ -719,12 +737,6 @@ HgfsKReqZInit(void *mem,     // IN: Pointer to the allocated object
    HgfsKReqObject *req = (HgfsKReqObject *)mem;
    ASSERT(size == sizeof *req);
 
-   /*
-    * Zero out the object.  (Do NOT pass UMA_ZEROINIT to uma_zcreate, as
-    * that will override this routine and zero everything -after- us.)
-    */
-   bzero(req, sizeof *req);
-
    /*
     * Request IDs are a 32-bit unsigned integer.  Conveniently enough for us,
     * our memory addresses provide (at least) 32 bits.
@@ -746,8 +758,6 @@ HgfsKReqZInit(void *mem,     // IN: Pointer to the allocated object
 
    /* Clear packet of request before allocating to clients. */
    bzero(&req->__rpc_packet, sizeof req->__rpc_packet);
-   bcopy(HGFS_SYNC_REQREP_CLIENT_CMD, req->__rpc_packet._command,
-         HGFS_SYNC_REQREP_CLIENT_CMD_LEN);
 
    return 0;
 }
@@ -817,9 +827,6 @@ HgfsKReqZCtor(void *mem,     // IN: Pointer to memory allocated to user
    /* Initialize state & reference count. */
    req->state = HGFS_REQ_ALLOCATED;
    req->refcnt = 1;
-
-   ASSERT(!strncmp(req->__rpc_packet._command, HGFS_SYNC_REQREP_CLIENT_CMD, HGFS_SYNC_REQREP_CLIENT_CMD_LEN));
-
    return 0;
 }
 
index ad8cbb238a8e9bae3c0c4afb0201116ef05c0958..d68e9c21409a38640231ff5ae5f2f1518e90c7e6 100644 (file)
@@ -69,7 +69,7 @@ extern void                    HgfsKReq_FreeContainer(HgfsKReqContainerHandle ha
 extern void                    HgfsKReq_CancelRequests(HgfsKReqContainerHandle handle);
 extern Bool                    HgfsKReq_ContainerIsEmpty(HgfsKReqContainerHandle handle);
 
-extern HgfsKReqHandle          HgfsKReq_AllocateRequest(HgfsKReqContainerHandle handle);
+extern HgfsKReqHandle          HgfsKReq_AllocateRequest(HgfsKReqContainerHandle handle, int *ret);
 extern void                    HgfsKReq_ReleaseRequest(HgfsKReqContainerHandle container,
                                                        HgfsKReqHandle oldRequest);
 extern int                     HgfsKReq_SubmitRequest(HgfsKReqHandle req);
index 877836a3e2bc730ae70d8480a2f8f764489a7ab8..296bb9a5630d5ecd10591d221324a1d93162d64a 100644 (file)
 #include "request.h"
 #include "debug.h"
 
+#if defined __APPLE__
+ #include "hgfsTransport.h"
+ #define HGFS_REQUEST_PREFIX_LENGTH MAX(HGFS_CLIENT_CMD_LEN, sizeof (HgfsVmciTransportStatus))
+#else
+ #define HGFS_REQUEST_PREFIX_LENGTH HGFS_CLIENT_CMD_LEN
+#endif
+
 
 /*
  * Data types
  */
+struct HgfsTransportChannel;
+
 
 /*
  * In-kernel representation of an Hgfs request.  These objects are kept on zero,
@@ -98,6 +107,8 @@ typedef struct HgfsKReqObject {
                                 // Typically set to the address of the HgfsKReq
                                 // object.
    size_t payloadSize;          // Total size of payload
+   void *ioBuf;
+   struct HgfsTransportChannel *channel;
    /*
     * The file system is concerned only with the payload portion of an Hgfs
     * request packet, but the RPC message opens with the command string "f ".
@@ -111,7 +122,7 @@ typedef struct HgfsKReqObject {
     * muck with _payload.
     */
    struct {
-      char      _command[HGFS_CLIENT_CMD_LEN];  // Typically "f ".
+      char      _command[HGFS_REQUEST_PREFIX_LENGTH];  // Typically "f ".
       char      _payload[HGFS_PACKET_MAX];      // Contains both the request and
                                                 // its reply.
    } __rpc_packet;
index 4ea26674f7a7e1aa57f8b0e9a2faeb44d808bc2d..5eb86b4eef00c1eba987fb8e905eb87bff2b9fd7 100644 (file)
@@ -73,9 +73,9 @@ HgfsSendOpenDirRequest(HgfsSuperInfo *sip,   // IN: Superinfo pointer
    uint32 reqBufferSize;
    int ret;
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      return ENOMEM;
+      return ret;
    }
 
    /* Set the correct header values */
@@ -174,10 +174,10 @@ HgfsSendOpenRequest(HgfsSuperInfo *sip,   // IN: Superinfo pointer
    uint32 reqBufferSize;
 
    DEBUG(VM_DEBUG_LOG, "Trace enter.\n");
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
       DEBUG(VM_DEBUG_FAIL, "HgfsKReq_AllocateRequest failed.\n");
-      return ENOMEM;
+      return ret;
    }
 
    requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req);
@@ -276,9 +276,9 @@ HgfsCloseServerDirHandle(HgfsSuperInfo *sip,         // IN: Superinfo pointer
    uint32 repSize;
    int ret;
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      return ENOMEM;
+      return ret;
    }
 
    /*
@@ -347,9 +347,9 @@ HgfsCloseServerFileHandle(HgfsSuperInfo *sip,         // IN: Superinfo pointer
    uint32 repSize;
    int ret;
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      return ENOMEM;
+      return ret;
    }
 
    /*
index 06064083e4d1d0861719b1cd3c1f6d9c4ba33d1a..5ab39057c27fcf3548b93484ddec319b094ab322 100644 (file)
@@ -74,9 +74,9 @@ HgfsStatfsInt(struct vnode *vp,          // IN: vnode
    }
 
    /* Prepare the request */
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      return ENOMEM;
+      return ret;
    }
 
    requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req);
diff --git a/open-vm-tools/modules/freebsd/vmhgfs/vmci.c b/open-vm-tools/modules/freebsd/vmhgfs/vmci.c
new file mode 100644 (file)
index 0000000..b5fd216
--- /dev/null
@@ -0,0 +1,48 @@
+/*********************************************************
+ * Copyright (C) 2010 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * vmci.c --
+ *
+ * VMCI transport channel for the HGFS client is not currently implemented.
+ */
+#include "channel.h"
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsGetVmciChannel --
+ *
+ *     Get Vmci channel.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+HgfsTransportChannel*
+HgfsGetVmciChannel(void) // IN:
+{
+   return NULL;
+}
+
index 79ede776428d331c3576862bdbf0046e5ba43666..91b4f0643f3f9147e9dd0a8d3e1bb93e8c398358 100644 (file)
@@ -110,9 +110,9 @@ HgfsRenameInt(struct vnode *fvp,          // IN: "from" file
       return EXDEV;
    }
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      return ENOMEM;
+      return ret;
    }
 
    requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req);
@@ -528,9 +528,9 @@ HgfsSetattrInt(struct vnode *vp,     // IN : vnode of the file
    ASSERT(vp);
    ASSERT(vap);
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      return ENOMEM;
+      return ret;
    }
 
    requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req);
@@ -1407,9 +1407,8 @@ HgfsMkdirInt(struct vnode *dvp,         // IN : directory vnode
    }
    fullNameLen = ret;
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      ret = ENOMEM;
       goto out;
    }
 
@@ -1911,9 +1910,9 @@ HgfsDoRead(HgfsSuperInfo *sip,  // IN: Superinfo pointer
 
    DEBUG(VM_DEBUG_ENTRY, "entry.\n");
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      return -ENOMEM;
+      return -ret;
    }
 
    requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req);
@@ -2043,9 +2042,9 @@ HgfsDoWrite(HgfsSuperInfo *sip, // IN: Superinfo pointer
    ASSERT(uiop);
    ASSERT(size <= HGFS_IO_MAX); // HgfsWrite() guarantees this
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      return -ENOMEM;
+      return -ret;
    }
 
    requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req);
@@ -2162,9 +2161,9 @@ HgfsDelete(HgfsSuperInfo *sip,          // IN: Superinfo
 
    DEBUG(VM_DEBUG_ENTRY, "HgfsDelete().\n");
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      return ENOMEM;
+      return ret;
    }
 
    /* Initialize the request's contents. */
@@ -2275,10 +2274,10 @@ HgfsGetNextDirEntry(HgfsSuperInfo *sip,         // IN: Superinfo pointer
    ASSERT(nameOut);
    ASSERT(done);
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
       DEBUG(VM_DEBUG_FAIL, "couldn't get req.\n");
-      return ENOMEM;
+      return ret;
    }
 
    /*
@@ -2394,9 +2393,9 @@ HgfsReadlinkInt(struct vnode *vp,   // IN : File vnode
       return EINVAL;
    }
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      return ENOMEM;
+      return ret;
    }
 
    ret = HgfsQueryAttrInt(HGFS_VP_TO_FILENAME(vp), 0, sip, req);
@@ -2490,9 +2489,8 @@ HgfsSymlinkInt(struct vnode *dvp,         // IN : directory vnode
       goto out;
    }
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      ret = ENOMEM;
       goto out;
    }
 
@@ -2716,9 +2714,9 @@ HgfsDoGetattrInt(const char *path,       // IN : Path to get attributes for
    DEBUG(VM_DEBUG_LOG, "Trace enter, %s.\n", path);
    ASSERT(hgfsAttrV2);
 
-   req = HgfsKReq_AllocateRequest(sip->reqs);
+   req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
    if (!req) {
-      return ENOMEM;
+      return ret;
    }
 
    ret = HgfsQueryAttrInt(path, handle, sip, req);
index 48b26231e930e85c8acde9acf89bd896180bbf88..43ce44a3133cb9ec5dca6cef878f0b6151b37893 100644 (file)
@@ -30,8 +30,7 @@
 #include "request.h"
 #include "requestInt.h"
 #include "os.h"
-
-#include "hgfsBd.h"
+#include "channel.h"
 
 
 /*
@@ -47,12 +46,66 @@ OS_THREAD_T hgfsKReqWorkerThread;
  * See requestInt.h.
  */
 HgfsKReqWState hgfsKReqWorkerState;
+HgfsTransportChannel *gHgfsChannel = NULL;
+OS_MUTEX_T *gHgfsChannelLock = NULL;
 
 
 /*
  * Global (module) functions
  */
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * HgfsTransportSetupNewChannel --
+ *
+ *     Find a new workable channel.
+ *
+ * Results:
+ *     TRUE on success, otherwise FALSE.
+ *
+ * Side effects:
+ *     None
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+HgfsSetupNewChannel(void)
+{
+   Bool ret;
+
+   os_mutex_lock(gHgfsChannelLock);
+
+   if (gHgfsChannel && gHgfsChannel->status == HGFS_CHANNEL_CONNECTED) {
+      ret = TRUE;
+      goto exit;
+   }
+
+   gHgfsChannel = HgfsGetVmciChannel();
+   if (gHgfsChannel) {
+      if ((ret = gHgfsChannel->ops.open(gHgfsChannel))) {
+         goto exit;
+      }
+   }
+
+   /* Every client using this code is expected to have backdoor enabled. */
+   gHgfsChannel = HgfsGetBdChannel();
+   ret = gHgfsChannel->ops.open(gHgfsChannel);
+
+exit:
+   if (ret) {
+      gHgfsChannel->status = HGFS_CHANNEL_CONNECTED;
+      DEBUG(VM_DEBUG_ALWAYS, "Channel: %s\n", gHgfsChannel->name);
+   } else {
+      gHgfsChannel->status = HGFS_CHANNEL_NOTCONNECTED;
+   }
+
+   os_mutex_unlock(gHgfsChannelLock);
+
+   return ret;
+}
+
 
 /*
  *-----------------------------------------------------------------------------
@@ -77,12 +130,21 @@ HgfsKReqWorker(void *arg)
    DblLnkLst_Links *currNode, *nextNode;
    HgfsKReqWState *ws = (HgfsKReqWState *)arg;
    HgfsKReqObject *req;
-   RpcOut *hgfsRpcOut = NULL;
-   char const *replyPacket;
    int ret = 0;
+   HgfsTransportChannel *channel;
 
    ws->running = TRUE;
 
+   gHgfsChannelLock = os_mutex_alloc_init(HGFS_FS_NAME "_channellck");
+   if (!gHgfsChannelLock) {
+      goto exit;
+   }
+
+   ret = HgfsSetupNewChannel();
+   if (!ret) {
+      DEBUG(VM_DEBUG_INFO, "VMware hgfs: %s: ohoh no channel yet.\n", __func__);
+   }
+
    for (;;) {
       /*
        * This loop spends most of its time sleeping until signalled by another
@@ -93,7 +155,7 @@ HgfsKReqWorker(void *arg)
       os_mutex_lock(hgfsKReqWorkItemLock);
 
       while (!ws->exit && !DblLnkLst_IsLinked(&hgfsKReqWorkItemList)) {
-        os_cv_wait(&hgfsKReqWorkItemCv, hgfsKReqWorkItemLock);
+         os_cv_wait(&hgfsKReqWorkItemCv, hgfsKReqWorkItemLock);
       }
 
       if (ws->exit) {
@@ -124,13 +186,15 @@ HgfsKReqWorker(void *arg)
       req = DblLnkLst_Container(currNode, HgfsKReqObject, pendingNode);
 
       os_mutex_lock(req->stateLock);
+
+      channel = req->channel;
       switch (req->state) {
       case HGFS_REQ_SUBMITTED:
-         if (!HgfsBd_OpenBackdoor(&hgfsRpcOut)) {
+         if (channel->status != HGFS_CHANNEL_CONNECTED) {
             req->state = HGFS_REQ_ERROR;
             os_cv_signal(&req->stateCv);
             os_mutex_unlock(req->stateLock);
-           os_mutex_unlock(hgfsKReqWorkItemLock);
+            os_mutex_unlock(hgfsKReqWorkItemLock);
             goto done;
          }
          break;
@@ -150,25 +214,7 @@ HgfsKReqWorker(void *arg)
        */
       os_mutex_unlock(hgfsKReqWorkItemLock);
 
-      ret = HgfsBd_Dispatch(hgfsRpcOut, req->payload, &req->payloadSize,
-                            &replyPacket);
-
-      /*
-       * We have a response.  (Maybe.)  Re-lock the request, update its state,
-       * etc.
-       */
-
-      os_mutex_lock(req->stateLock);
-
-      if ((ret == 0) && (req->state == HGFS_REQ_SUBMITTED)) {
-         bcopy(replyPacket, req->payload, req->payloadSize);
-         req->state = HGFS_REQ_COMPLETED;
-      } else {
-         req->state = HGFS_REQ_ERROR;
-      }
-
-      os_cv_signal(&req->stateCv);
-      os_mutex_unlock(req->stateLock);
+      ret = channel->ops.send(gHgfsChannel, req);
 
       if (ret != 0) {
          /*
@@ -176,7 +222,9 @@ HgfsKReqWorker(void *arg)
           * now. We do this because subsequent requests deserve a chance to
           * reopen it.
           */
-         HgfsBd_CloseBackdoor(&hgfsRpcOut);
+         os_mutex_lock(gHgfsChannelLock);
+         gHgfsChannel->ops.close(gHgfsChannel);
+         os_mutex_unlock(gHgfsChannelLock);
       }
 
 done:
@@ -213,9 +261,13 @@ done:
 
    ws->running = FALSE;
 
-   if (hgfsRpcOut != NULL ) {
-      HgfsBd_CloseBackdoor(&hgfsRpcOut);
+   if (gHgfsChannel && gHgfsChannel->status == HGFS_CHANNEL_CONNECTED) {
+      gHgfsChannel->ops.close(gHgfsChannel);
    }
 
+   if (gHgfsChannelLock) {
+      os_mutex_free(gHgfsChannelLock);
+   }
+exit:
    os_thread_exit(0);
 }