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>
HEADERS += os.h
HEADERS += vfsopscommon.h
HEADERS += transport.h
+HEADERS += channel.h
COMMON_SRCS := cpName.c
COMMON_SRCS += cpNameLinux.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
MODULE_SRCS := vnops.c
MODULE_SRCS += vfsops.c
MODULE_SRCS += os.c
+MODULE_SRCS += vmci.c
MODULE_SRCS += hgfsUtil.c
MODULE_SRCS += kernelStubsBSD.c
--- /dev/null
+/*********************************************************
+ * 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;
+}
+
--- /dev/null
+/*********************************************************
+ * 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_
((type & VM_DEBUG_LEV) ? \
(kprintf("%s:%u: " fmt, \
__func__, __LINE__, ##__VA_ARGS__)) \
- : 0)
+ : (void)0)
# endif
#else
# define DEBUG(type, ...)
#include "vm_basic_types.h"
#include "os.h"
#include "debug.h"
+#include "channel.h"
#include "compat_freebsd.h"
/*
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;
}
void
os_zone_free(OS_ZONE_T *zone, // IN
- void *mem) // IN
+ void *mem) // IN
{
ASSERT(zone);
ASSERT(zone->umaZone);
#include "hgfs_kernel.h"
#include "requestInt.h"
+#include "channel.h"
/*
* Macros
* 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)
* 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
*----------------------------------------------------------------------------
*/
-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;
}
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.
/* 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;
}
/* 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;
}
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);
#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,
// 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 ".
* 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;
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 */
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);
uint32 repSize;
int ret;
- req = HgfsKReq_AllocateRequest(sip->reqs);
+ req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
if (!req) {
- return ENOMEM;
+ return ret;
}
/*
uint32 repSize;
int ret;
- req = HgfsKReq_AllocateRequest(sip->reqs);
+ req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
if (!req) {
- return ENOMEM;
+ return ret;
}
/*
}
/* 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);
--- /dev/null
+/*********************************************************
+ * 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;
+}
+
return EXDEV;
}
- req = HgfsKReq_AllocateRequest(sip->reqs);
+ req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
if (!req) {
- return ENOMEM;
+ return ret;
}
requestHeader = (HgfsRequest *)HgfsKReq_GetPayload(req);
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);
}
fullNameLen = ret;
- req = HgfsKReq_AllocateRequest(sip->reqs);
+ req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
if (!req) {
- ret = ENOMEM;
goto out;
}
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);
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);
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. */
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;
}
/*
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);
goto out;
}
- req = HgfsKReq_AllocateRequest(sip->reqs);
+ req = HgfsKReq_AllocateRequest(sip->reqs, &ret);
if (!req) {
- ret = ENOMEM;
goto out;
}
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);
#include "request.h"
#include "requestInt.h"
#include "os.h"
-
-#include "hgfsBd.h"
+#include "channel.h"
/*
* 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;
+}
+
/*
*-----------------------------------------------------------------------------
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
os_mutex_lock(hgfsKReqWorkItemLock);
while (!ws->exit && !DblLnkLst_IsLinked(&hgfsKReqWorkItemList)) {
- os_cv_wait(&hgfsKReqWorkItemCv, hgfsKReqWorkItemLock);
+ os_cv_wait(&hgfsKReqWorkItemCv, hgfsKReqWorkItemLock);
}
if (ws->exit) {
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;
*/
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) {
/*
* 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:
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);
}