]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
[HGFS Server] Support oplock inside HGFS server for Windows host
authorJohn Wolfe <jwolfe@vmware.com>
Fri, 7 Aug 2020 19:03:24 +0000 (12:03 -0700)
committerJohn Wolfe <jwolfe@vmware.com>
Fri, 7 Aug 2020 19:03:24 +0000 (12:03 -0700)
The motivation for this change is to cache file/directory related information
in host side, for example the file/directory attributes.  To make the cache
correct, we will use the oplock(Windows)/lease(Linux) to monitor the
file/directory change event.  When the file/directory changes, the item in
cache will be invalidated.

In this change, two new functions are defined:
- HgfsOplockMonitorFileChange
   This function is used to monitor the change event for a file/directory,
   and the callback will be called if file/directory is changed.
- HgfsOplockUnmonitorFileChange
   This function is used to cancel the change event monitoring.

This patch only implements the oplock support for Windows host, the support
for Linux will be delivered in another patch.

open-vm-tools/lib/hgfsServer/Makefile.am
open-vm-tools/lib/hgfsServer/hgfsServer.c
open-vm-tools/lib/hgfsServer/hgfsServerOplockInt.h
open-vm-tools/lib/hgfsServer/hgfsServerOplockMonitor.c [new file with mode: 0644]
open-vm-tools/lib/hgfsServer/hgfsServerOplockMonitor.h [new file with mode: 0644]
open-vm-tools/lib/include/hgfsServer.h

index 9936a56ec0359de81c8e76bad2c089cb8c300f82..d2271156743fea34785f6414e2e00c6762c038aa 100644 (file)
@@ -24,6 +24,7 @@ libHgfsServer_la_SOURCES += hgfsServerPacketUtil.c
 libHgfsServer_la_SOURCES += hgfsDirNotifyStub.c
 libHgfsServer_la_SOURCES += hgfsServerParameters.c
 libHgfsServer_la_SOURCES += hgfsServerOplock.c
+libHgfsServer_la_SOURCES += hgfsServerOplockMonitor.c
 libHgfsServer_la_SOURCES += hgfsServerOplockLinux.c
 libHgfsServer_la_SOURCES += hgfsThreadpoolStub.c
 
index 74c2ff2b92f0fddffdeb270bca46fca0d1159046..2b580e0bbcdf3d9ae1ef42ac25e85bf723aa2a94 100644 (file)
@@ -46,6 +46,7 @@
 #include "hgfsServer.h"
 #include "hgfsServerParameters.h"
 #include "hgfsServerOplock.h"
+#include "hgfsServerOplockMonitor.h"
 #include "hgfsDirNotify.h"
 #include "hgfsThreadpool.h"
 #include "userlock.h"
@@ -3975,9 +3976,13 @@ HgfsServer_InitState(const HgfsServerCallbacks **callbackTable,   // IN/OUT: our
          Log("%s: initialized notification %s.\n", __FUNCTION__,
              (gHgfsDirNotifyActive ? "active" : "inactive"));
       }
-      if (0 != (gHgfsCfgSettings.flags & HGFS_CONFIG_OPLOCK_ENABLED)) {
+      if (   0 != (gHgfsCfgSettings.flags & HGFS_CONFIG_OPLOCK_ENABLED)
+          || 0 != (gHgfsCfgSettings.flags & HGFS_CONFIG_OPLOCK_MONITOR_ENABLED)) {
          if (!HgfsServerOplockInit()) {
+            Log("%s: failed to init oplock module.\n", __FUNCTION__);
+            HgfsServerOplockDestroy();
             gHgfsCfgSettings.flags &= ~HGFS_CONFIG_OPLOCK_ENABLED;
+            gHgfsCfgSettings.flags &= ~HGFS_CONFIG_OPLOCK_MONITOR_ENABLED;
          }
       }
       if (0 != (gHgfsCfgSettings.flags & HGFS_CONFIG_THREADPOOL_ENABLED)) {
@@ -3986,6 +3991,12 @@ HgfsServer_InitState(const HgfsServerCallbacks **callbackTable,   // IN/OUT: our
          Log("%s: initialized threadpool %s.\n", __FUNCTION__,
              (gHgfsThreadpoolActive ? "active" : "inactive"));
       }
+      if (0 != (gHgfsCfgSettings.flags & HGFS_CONFIG_OPLOCK_MONITOR_ENABLED)) {
+         if (!HgfsOplockMonitorInit()) {
+            Log("%s: failed to init oplock monitor module.\n", __FUNCTION__);
+            gHgfsCfgSettings.flags &= ~HGFS_CONFIG_OPLOCK_MONITOR_ENABLED;
+         }
+      }
    } else {
       HgfsServer_ExitState(); // Cleanup partially initialized state
    }
@@ -4017,7 +4028,11 @@ HgfsServer_InitState(const HgfsServerCallbacks **callbackTable,   // IN/OUT: our
 void
 HgfsServer_ExitState(void)
 {
-   if (0 != (gHgfsCfgSettings.flags & HGFS_CONFIG_OPLOCK_ENABLED)) {
+   if (0 != (gHgfsCfgSettings.flags & HGFS_CONFIG_OPLOCK_MONITOR_ENABLED)) {
+      HgfsOplockMonitorDestroy();
+   }
+   if (   0 != (gHgfsCfgSettings.flags & HGFS_CONFIG_OPLOCK_ENABLED)
+       || 0 != (gHgfsCfgSettings.flags & HGFS_CONFIG_OPLOCK_MONITOR_ENABLED)) {
       HgfsServerOplockDestroy();
    }
    if (gHgfsDirNotifyActive) {
index d0b50b31e5535676936763cf117f6b23a1fd1a2d..61521a1d1e1fe27fd4fe166c1d727b675fc74535 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2013-2016 VMware, Inc. All rights reserved.
+ * Copyright (C) 2013-2016,2020 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -26,6 +26,9 @@
 #ifndef _HGFS_SERVER_OPLOCKINT_H_
 #define _HGFS_SERVER_OPLOCKINT_H_
 
+#ifdef _WIN32
+#include <winioctl.h>      // for REQUEST_OPLOCK_OUTPUT_BUFFER
+#endif
 #include "hgfsProto.h"     // for protocol types
 #include "hgfsServerInt.h" // for common server types e.g. HgfsSessionInfo
 
  * XXX describe the data structure
  */
 
+typedef void(*HgfsOplockCallback)(HgfsSessionInfo *session, void *data);
+
 /* Server lock related structure */
 typedef struct {
    fileDesc fileDesc;
-   int32 event;
+   HgfsSessionInfo *session;
    HgfsLockType serverLock;
+   HgfsOplockCallback callback;
+   void *data;
+#ifdef _WIN32
+   REQUEST_OPLOCK_OUTPUT_BUFFER oplockInfo;
+   OVERLAPPED overlapped;
+#endif
 } ServerLockData;
 
 
@@ -55,12 +66,32 @@ typedef struct {
  * Global variables
  */
 
+/*
+ * The maximum count of oplocks that the server supports.
+ * This value can be adjusted as necessary, but must be a power of 2.
+ */
+#define HGFS_OPLOCK_MAX_COUNT 512
 
 
 /*
  * Global functions
  */
 
+Bool
+HgfsServerOplockIsInited(void);
+Bool
+HgfsPlatformOplockInit(void);
+void
+HgfsPlatformOplockDestroy(void);
+Bool
+HgfsAcquireAIOServerLock(fileDesc fileDesc,
+                         HgfsSessionInfo *session,
+                         HgfsLockType *serverLock,
+                         HgfsOplockCallback callback,
+                         void *data);
+void
+HgfsRemoveAIOServerLock(fileDesc fileDesc);
+
 #ifdef HGFS_OPLOCKS
 void
 HgfsServerOplockBreak(ServerLockData *data);
diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerOplockMonitor.c b/open-vm-tools/lib/hgfsServer/hgfsServerOplockMonitor.c
new file mode 100644 (file)
index 0000000..b19159b
--- /dev/null
@@ -0,0 +1,440 @@
+/*********************************************************
+ * Copyright (C) 2020 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 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 Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ *
+ *********************************************************/
+
+/*
+ * hgfsServerOplockMonitor.c --
+ *
+ *      Implements functions for HGFS server opportunistic lock monitoring
+ *      subfeature.
+ */
+
+
+#include "vmware.h"
+#include "hashTable.h"
+#include "hgfsServerOplockMonitor.h"
+#include "mutexRankLib.h"
+#include "util.h"
+
+ /*
+  * Local data
+  */
+#define AS_KEY(_x)  ((const void *)(uintptr_t)(_x))
+
+/*
+ * Define the max count for hash table gOplockMonitorMap.
+ */
+#define OPLOCK_MONITOR_MAP_MAX_COUNT HGFS_OPLOCK_MAX_COUNT
+
+/*
+ * Define the max count for hash table gOplockMonitorHandleMap.
+ * Different monitor requests may target the same file, for each file there is
+ * one item in hash table gOplockMonitorMap, and for each monitor request there
+ * is one item in hash table gOplockMonitorHandleMap.
+ * We support 4 monitor requests for each file.
+ */
+#define OPLOCK_MONITOR_HANDLE_MAP_MAX_COUNT (4 * OPLOCK_MONITOR_MAP_MAX_COUNT)
+
+
+/*
+ * This structure is the type of oplockMonitorData.callbackList.
+ */
+typedef struct {
+   DblLnkLst_Links links;
+   uint64 handle;
+   HgfsOplockCallback callback;
+   void *data;
+} oplockMonitorCallbackList;
+
+/*
+ * This structure is the value field of hash table gOplockMonitorMap.
+ */
+typedef struct {
+   fileDesc fileDesc;
+   char *utf8Name;
+   MXUserExclLock *lock;
+   DblLnkLst_Links callbackList;
+} oplockMonitorData;
+
+/*
+ * Caller can use oplock module to monitor the file change event by providing
+ * the file path instead of file descriptor.
+ * This hash table maps the file path to structure oplockMonitorData
+ * which stores the information for the file, for example the file descriptor.
+ * This hash table is mainly used to check if a file has already been opened,
+ * which means when many callers monitor the same file, we only need to open
+ * that file once.
+ */
+static HashTable *gOplockMonitorMap = NULL;
+
+/*
+ * This hash table is used to map the monitor handle to structure
+ * oplockMonitorData.
+ * This hash table is used when un-monitor the file change.
+ */
+static HashTable *gOplockMonitorHandleMap = NULL;
+
+/* Lock for gOplockMonitorMap and gOplockMonitorHandleMap. */
+static MXUserExclLock *oplockMonitorLock;
+
+/* Indicates if the oplock monitor module is initialized. */
+static Bool gOplockMonitorInit = FALSE;
+
+void
+HgfsOplockUnmonitorFileChangeInternal(HOM_HANDLE handle);
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsOplockMonitorInit --
+ *
+ *      Set up any related state for monitoring.
+ *
+ * Results:
+ *      TRUE on success, FALSE on failure.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+HgfsOplockMonitorInit(void)
+{
+   if (gOplockMonitorInit) {
+      return TRUE;
+   }
+
+   // Oplock module must be initialized first.
+   if (!HgfsServerOplockIsInited()) {
+      Log("%s: Oplock module is not inited\n", __FUNCTION__);
+      return FALSE;
+   }
+
+   gOplockMonitorMap = HashTable_Alloc(OPLOCK_MONITOR_MAP_MAX_COUNT,
+                                      HASH_ISTRING_KEY | HASH_FLAG_COPYKEY,
+                                      NULL);
+   ASSERT(gOplockMonitorMap);
+
+   gOplockMonitorHandleMap = HashTable_Alloc(OPLOCK_MONITOR_HANDLE_MAP_MAX_COUNT,
+                                            HASH_INT_KEY,
+                                            NULL);
+   ASSERT(gOplockMonitorHandleMap);
+
+   oplockMonitorLock = MXUser_CreateExclLock("HgfsoplockMonitorLock",
+                                             RANK_hgfsSharedFolders);
+
+   gOplockMonitorInit = TRUE;
+   return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsOplockMonitorDestroy --
+ *
+ *      Tear down any related state for monitoring.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HgfsOplockMonitorDestroy(void)
+{
+   if (!gOplockMonitorInit) {
+      return;
+   }
+
+   HashTable_Free(gOplockMonitorMap);
+   HashTable_Free(gOplockMonitorHandleMap);
+   MXUser_DestroyExclLock(oplockMonitorLock);
+   gOplockMonitorInit = FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsOplockMonitorFileChangeCallback --
+ *
+ *    A callback function that called when the target file/directory is
+ *    changed.
+ *    Calls the caller provided callback.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HgfsOplockMonitorFileChangeCallback(HgfsSessionInfo *session,   // IN:
+                                    void *data)                 // IN:
+{
+   oplockMonitorData *monitorData = data;
+   DblLnkLst_Links *link, *nextLink;
+   oplockMonitorCallbackList *callbackItem;
+
+   ASSERT(monitorData);
+   MXUser_AcquireExclLock(oplockMonitorLock);
+   if (HashTable_Lookup(gOplockMonitorMap, monitorData->utf8Name, NULL)) {
+      DblLnkLst_ForEachSafe(link, nextLink, &monitorData->callbackList) {
+         callbackItem = DblLnkLst_Container(link, oplockMonitorCallbackList, links);
+         callbackItem->callback(session, callbackItem->data);
+         /*
+          * callbackItem->data has been freed in the user callback.
+          */
+         callbackItem->data = NULL;
+         HgfsOplockUnmonitorFileChangeInternal(callbackItem->handle);
+         /*
+          * callbackItem has been freed in above function.
+          */
+         callbackItem = NULL;
+      }
+   }
+   MXUser_ReleaseExclLock(oplockMonitorLock);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsOplockMonitorFileChange --
+ *
+ *    Monitor the file/directory change event by using oplock.
+ *    The caller provided callback will be called if the file/directory is
+ *    changed.
+ *    This is one-shot action, after the event is fired, the oplock will be
+ *    removed.
+ *    The data that caller provides will be freed by:
+ *       1. caller callback if the callback is called;
+ *       2. caller callback if this function failed;
+ *       3. this module if caller cancels the file change monitor.
+ *
+ * Results:
+ *    HGFS_OPLOCK_INVALID_MONITOR_HANDLE on fail, handle on success.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+HOM_HANDLE
+HgfsOplockMonitorFileChange(char *utf8Name,             // IN: Name in UTF8
+                            HgfsSessionInfo *session,   // IN:
+                            HgfsOplockCallback callback,// IN:
+                            void *data)                 // IN:
+{
+   oplockMonitorData *monitorData = NULL;
+   oplockMonitorCallbackList *callbackItem;
+   HOM_HANDLE handle = HGFS_OPLOCK_INVALID_MONITOR_HANDLE;
+   HgfsFileOpenInfo openInfo;
+   HgfsLocalId localId;
+   fileDesc newHandle;
+   HgfsInternalStatus status;
+   HgfsLockType serverLock = HGFS_LOCK_SHARED;
+
+   MXUser_AcquireExclLock(oplockMonitorLock);
+   if (!gOplockMonitorInit) {
+      LOG(4, "%s: Oplock monitor is not inited\n", __FUNCTION__);
+      goto error;
+   }
+
+   if (   HashTable_GetNumElements(gOplockMonitorMap)
+       >= OPLOCK_MONITOR_MAP_MAX_COUNT) {
+      LOG(4, "%s: Exceeds OPLOCK_MONITOR_MAP_MAX_COUNT\n", __FUNCTION__);
+      goto error;
+   }
+
+   if (   HashTable_GetNumElements(gOplockMonitorHandleMap)
+       >= OPLOCK_MONITOR_HANDLE_MAP_MAX_COUNT) {
+      LOG(4, "%s: Exceeds OPLOCK_MONITOR_HANDLE_MAP_MAX_COUNT\n", __FUNCTION__);
+      goto error;
+   }
+
+   /*
+    * If there are multiple monitor request for the same file, we should open
+    * the file only once, and add all the callback functions into one double
+    * link list.
+    */
+   if (HashTable_Lookup(gOplockMonitorMap, utf8Name, (void **)&monitorData)) {
+      callbackItem = Util_SafeMalloc(sizeof *callbackItem);
+      handle = (HOM_HANDLE)callbackItem;
+      DblLnkLst_Init(&callbackItem->links);
+      callbackItem->handle = handle;
+      callbackItem->callback = callback;
+      callbackItem->data = data;
+      DblLnkLst_LinkLast(&monitorData->callbackList,
+                         &callbackItem->links);
+      HashTable_Insert(gOplockMonitorHandleMap,
+                       AS_KEY(handle),
+                       (void *)monitorData);
+      MXUser_ReleaseExclLock(oplockMonitorLock);
+      return handle;
+   }
+
+   memset(&openInfo, 0, sizeof(openInfo));
+   openInfo.mask = HGFS_OPEN_VALID_MODE | HGFS_OPEN_VALID_SHARE_ACCESS;
+   openInfo.mode = HGFS_OPEN_MODE_READ_ONLY;
+#ifdef _WIN32
+   openInfo.shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+#endif
+   openInfo.flags = HGFS_OPEN;
+   openInfo.utf8Name = utf8Name;
+   openInfo.shareInfo.readPermissions = TRUE;
+   status = HgfsPlatformValidateOpen(&openInfo, TRUE, session,
+                                     &localId, &newHandle);
+
+   if (status != HGFS_ERROR_SUCCESS) {
+      LOG(4, "%s: Failed to open file: %s\n", __FUNCTION__, utf8Name);
+      goto error;
+   }
+
+   monitorData = Util_SafeMalloc(sizeof *monitorData);
+   monitorData->fileDesc = newHandle;
+   monitorData->utf8Name = Util_SafeStrdup(utf8Name);
+   DblLnkLst_Init(&monitorData->callbackList);
+
+   if (!HgfsAcquireAIOServerLock(newHandle,
+                                 session,
+                                 &serverLock,
+                                 HgfsOplockMonitorFileChangeCallback,
+                                 monitorData)) {
+      HgfsPlatformCloseFile(newHandle, NULL);
+      LOG(4, "%s: Failed to acquire server lock for file: %s\n", __FUNCTION__, utf8Name);
+      goto error;
+   }
+
+   callbackItem = Util_SafeMalloc(sizeof *callbackItem);
+   handle = (HOM_HANDLE)callbackItem;
+   DblLnkLst_Init(&callbackItem->links);
+   callbackItem->handle = handle;
+   callbackItem->callback = callback;
+   callbackItem->data = data;
+   DblLnkLst_LinkLast(&monitorData->callbackList,
+                      &callbackItem->links);
+
+   HashTable_Insert(gOplockMonitorMap, utf8Name, (void *)monitorData);
+   HashTable_Insert(gOplockMonitorHandleMap, AS_KEY(handle), (void *)monitorData);
+   MXUser_ReleaseExclLock(oplockMonitorLock);
+   return handle;
+
+error:
+   if (monitorData) {
+      free(monitorData->utf8Name);
+      free(monitorData);
+   }
+
+   MXUser_ReleaseExclLock(oplockMonitorLock);
+   return HGFS_OPLOCK_INVALID_MONITOR_HANDLE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsOplockUnmonitorFileChangeInternal --
+ *
+ *    Cancel the monitor action by closing the file descriptor.
+ *    The lock for oplockMonitorLock should be acquired before calling this
+ *    funcion.
+ *    All the objects that related to handle will be released when returns
+ *    from this function.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HgfsOplockUnmonitorFileChangeInternal(HOM_HANDLE handle)             // IN:
+{
+   oplockMonitorData *monitorData = NULL;
+   DblLnkLst_Links *link, *nextLink;
+   oplockMonitorCallbackList *callbackItem;
+
+   if (HashTable_Lookup(gOplockMonitorHandleMap,
+                        AS_KEY(handle),
+                        (void **)&monitorData)) {
+      HashTable_Delete(gOplockMonitorHandleMap, AS_KEY(handle));
+
+      DblLnkLst_ForEachSafe(link, nextLink, &monitorData->callbackList) {
+         callbackItem = DblLnkLst_Container(link, oplockMonitorCallbackList, links);
+         if (callbackItem->handle == handle) {
+            DblLnkLst_Unlink1(&callbackItem->links);
+            free(callbackItem->data);
+            free(callbackItem);
+            break;
+         }
+      }
+
+      /*
+       * Close the file if no one is monitoring it anymore.
+       */
+      if (DblLnkLst_IsLinked(&monitorData->callbackList) == FALSE) {
+         HashTable_Delete(gOplockMonitorMap, monitorData->utf8Name);
+         HgfsRemoveAIOServerLock(monitorData->fileDesc);
+         free(monitorData->utf8Name);
+         free(monitorData);
+      }
+   }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsOplockUnmonitorFileChange --
+ *
+ *    Cancel the monitor action.
+ *    All the objects that related to handle will be released when returns
+ *    from this function.
+ *    the caller provided callback will not be called.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HgfsOplockUnmonitorFileChange(HOM_HANDLE handle)             // IN:
+{
+   MXUser_AcquireExclLock(oplockMonitorLock);
+   HgfsOplockUnmonitorFileChangeInternal(handle);
+   MXUser_ReleaseExclLock(oplockMonitorLock);
+}
diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerOplockMonitor.h b/open-vm-tools/lib/hgfsServer/hgfsServerOplockMonitor.h
new file mode 100644 (file)
index 0000000..1c41921
--- /dev/null
@@ -0,0 +1,58 @@
+/*********************************************************
+ * Copyright (C) 2020 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 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 Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ *
+ *********************************************************/
+
+/*
+ * hgfsServerOplockMonitor.h --
+ *
+ *     Header file for public common data types used in the HGFS
+ *     opportunistic lock monitoring subfeature.
+ */
+
+#ifndef _HGFS_SERVER_OPLOCK_MONITOR_H_
+#define _HGFS_SERVER_OPLOCK_MONITOR_H_
+
+#include "hgfsServerOplockInt.h"
+
+
+/*
+ * Data structures
+ */
+#define HOM_HANDLE uintptr_t
+
+/*
+ * Global variables
+ */
+#define HGFS_OPLOCK_INVALID_MONITOR_HANDLE 0
+
+
+/*
+ * Global functions
+ */
+
+Bool
+HgfsOplockMonitorInit(void);
+void
+HgfsOplockMonitorDestroy(void);
+HOM_HANDLE
+HgfsOplockMonitorFileChange(char *utf8Name,
+                            HgfsSessionInfo *session,
+                            HgfsOplockCallback callback,
+                            void *data);
+void
+HgfsOplockUnmonitorFileChange(HOM_HANDLE handle);
+#endif // ifndef _HGFS_SERVER_OPLOCK_MONITOR_H_
index da3510f7c723168328cf7d890c5f72dee0041f32..6be2edc6a09c9513c982ed5d14db560a232ee077 100644 (file)
@@ -126,6 +126,7 @@ typedef uint32 HgfsConfigFlags;
 #define HGFS_CONFIG_OPLOCK_ENABLED                   (1 << 3)
 #define HGFS_CONFIG_SHARE_ALL_HOST_DRIVES_ENABLED    (1 << 4)
 #define HGFS_CONFIG_THREADPOOL_ENABLED               (1 << 5)
+#define HGFS_CONFIG_OPLOCK_MONITOR_ENABLED           (1 << 6)
 
 typedef struct HgfsServerConfig {
    HgfsConfigFlags flags;