aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2015-04-14 12:45:41 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2015-04-14 13:24:14 +0000
commit2b4f0c0beb18d468ff89457ce0b42b0fd35ff246 (patch)
treea177b1345f78b6b6d1bde52f4e5d173eafcc1ac9
parent9d86cf29d9853a68265193b3034bac36c84f9e13 (diff)
downloadaports-2b4f0c0beb18d468ff89457ce0b42b0fd35ff246.tar.bz2
aports-2b4f0c0beb18d468ff89457ce0b42b0fd35ff246.tar.xz
main/open-vm-tools: upgrade and rebuild against 3.18.11 kernel
-rw-r--r--main/open-vm-tools-grsec/0001-Fix-vmxnet-module-on-kernels-3.16.patch74
-rwxr-xr-xmain/open-vm-tools-grsec/0001-Remove-unused-DEPRECATED-macro.patch33
-rwxr-xr-xmain/open-vm-tools-grsec/0002-Conditionally-define-g_info-macro.patch34
-rw-r--r--main/open-vm-tools-grsec/0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch34
-rwxr-xr-xmain/open-vm-tools-grsec/0003-Add-kuid_t-kgid_t-compatibility-layer.patch311
-rwxr-xr-xmain/open-vm-tools-grsec/0004-Use-new-link-helpers.patch53
-rwxr-xr-xmain/open-vm-tools-grsec/0005-Update-hgfs-file-operations-for-newer-kernels.patch2688
-rw-r--r--main/open-vm-tools-grsec/APKBUILD45
-rw-r--r--main/open-vm-tools-grsec/vmhgfs-d_count-kernel-3.11-tools-9.6.0.patch40
9 files changed, 125 insertions, 3187 deletions
diff --git a/main/open-vm-tools-grsec/0001-Fix-vmxnet-module-on-kernels-3.16.patch b/main/open-vm-tools-grsec/0001-Fix-vmxnet-module-on-kernels-3.16.patch
new file mode 100644
index 0000000000..4f76f76f0a
--- /dev/null
+++ b/main/open-vm-tools-grsec/0001-Fix-vmxnet-module-on-kernels-3.16.patch
@@ -0,0 +1,74 @@
+From 08836a47c56b47b658025e41a20027c5d915f836 Mon Sep 17 00:00:00 2001
+From: "Scott M. Kroll" <skroll@gmail.com>
+Date: Fri, 15 Aug 2014 10:40:38 -0400
+Subject: [PATCH 1/3] Fix vmxnet module on kernels >= 3.16
+
+* Add compat check for ethtool_ops in net_device struct.
+* SET_ETHTOOL_OPS is no longer defined, but can be manually.
+---
+ open-vm-tools/modules/linux/shared/compat_netdevice.h | 4 ++++
+ open-vm-tools/modules/linux/vmxnet/vmxnet.c | 13 ++++++++-----
+ 2 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/open-vm-tools/modules/linux/shared/compat_netdevice.h b/open-vm-tools/modules/linux/shared/compat_netdevice.h
+index 3aec25b..a65d59b 100644
+--- a/modules/linux/shared/compat_netdevice.h
++++ b/modules/linux/shared/compat_netdevice.h
+@@ -337,4 +337,8 @@ typedef netdev_features_t compat_netdev_features_t;
+ typedef u32 compat_netdev_features_t;
+ #endif
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) || defined(SET_ETHTOOL_OPS)
++#define VMW_HAVE_ETHTOOL_OPS 1
++#endif
++
+ #endif /* __COMPAT_NETDEVICE_H__ */
+diff --git a/open-vm-tools/modules/linux/vmxnet/vmxnet.c b/open-vm-tools/modules/linux/vmxnet/vmxnet.c
+index 33afb9b..40abde5 100644
+--- a/modules/linux/vmxnet/vmxnet.c
++++ b/modules/linux/vmxnet/vmxnet.c
+@@ -279,8 +279,7 @@ vmxnet_change_mtu(struct net_device *dev, int new_mtu)
+
+ #endif
+
+-
+-#ifdef SET_ETHTOOL_OPS
++#ifdef VMW_HAVE_ETHTOOL_OPS
+ /*
+ *----------------------------------------------------------------------------
+ *
+@@ -526,7 +525,7 @@ vmxnet_ethtool_ops = {
+ };
+
+
+-#else /* !defined(SET_ETHTOOL_OPS) */
++#else /* !defined(VMW_HAVE_ETHTOOL_OPS) */
+
+
+ /*
+@@ -739,7 +738,7 @@ vmxnet_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ }
+ return -EOPNOTSUPP;
+ }
+-#endif /* SET_ETHTOOL_OPS */
++#endif /* !defined(VMW_HAVE_ETHTOOL_OPS) */
+
+
+ /*
+@@ -1142,8 +1141,12 @@ vmxnet_probe_device(struct pci_dev *pdev, // IN: vmxnet PCI device
+ dev->watchdog_timeo = VMXNET_WATCHDOG_TIMEOUT;
+ #endif
+
+-#ifdef SET_ETHTOOL_OPS
++#ifdef VMW_HAVE_ETHTOOL_OPS
++# ifdef SET_ETHTOOL_OPS
+ SET_ETHTOOL_OPS(dev, &vmxnet_ethtool_ops);
++# else
++ dev->ethtool_ops = &vmxnet_ethtool_ops;
++# endif
+ #else
+ dev->do_ioctl = vmxnet_ioctl;
+ #endif
+--
+2.3.4
+
diff --git a/main/open-vm-tools-grsec/0001-Remove-unused-DEPRECATED-macro.patch b/main/open-vm-tools-grsec/0001-Remove-unused-DEPRECATED-macro.patch
deleted file mode 100755
index ff230a7ef6..0000000000
--- a/main/open-vm-tools-grsec/0001-Remove-unused-DEPRECATED-macro.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 0a49c04428ff99fdf29edf32e043e04fae492b6d Mon Sep 17 00:00:00 2001
-From: "Scott M. Kroll" <skroll@gmail.com>
-Date: Mon, 14 Jul 2014 11:24:44 -0400
-Subject: [PATCH 1/5] Remove unused DEPRECATED macro
-
----
- open-vm-tools/lib/include/vm_assert.h | 10 ----------
- 1 file changed, 10 deletions(-)
-
-diff --git a/open-vm-tools/lib/include/vm_assert.h b/open-vm-tools/lib/include/vm_assert.h
-index 5b02eed..48c9f1d 100644
---- a/lib/include/vm_assert.h
-+++ b/lib/include/vm_assert.h
-@@ -282,16 +282,6 @@ void WarningThrottled(uint32 *count, const char *fmt, ...)
-
- #define LOG_ONCE(_s) DO_ONCE(Log _s)
-
--#ifdef VMX86_DEVEL
-- #define DEPRECATED(_fix) DO_ONCE( \
-- Warning("%s:%d: %s is DEPRECATED; %s\n", \
-- __FILE__, __LINE__, __FUNCTION__, \
-- _fix))
--#else
-- #define DEPRECATED(_fix) do {} while (0)
--#endif
--
--
- /*
- * Redefine macros that are only in debug versions
- */
---
-2.0.1
-
diff --git a/main/open-vm-tools-grsec/0002-Conditionally-define-g_info-macro.patch b/main/open-vm-tools-grsec/0002-Conditionally-define-g_info-macro.patch
deleted file mode 100755
index 71a586cd7c..0000000000
--- a/main/open-vm-tools-grsec/0002-Conditionally-define-g_info-macro.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 9a38a9da20c898c4c21e84e1cf4f97c5b63f6a87 Mon Sep 17 00:00:00 2001
-From: "Scott M. Kroll" <skroll@gmail.com>
-Date: Mon, 14 Jul 2014 11:25:10 -0400
-Subject: [PATCH 2/5] Conditionally define g_info macro
-
-* Some versions of GLib define this macro.
----
- open-vm-tools/lib/include/vmware/tools/log.h | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/open-vm-tools/lib/include/vmware/tools/log.h b/open-vm-tools/lib/include/vmware/tools/log.h
-index 526b7c2..fa7deb4 100644
---- a/lib/include/vmware/tools/log.h
-+++ b/lib/include/vmware/tools/log.h
-@@ -121,6 +121,7 @@
- # define FUNC __FUNCTION__
- #endif
-
-+#ifndef g_info
- /*
- *******************************************************************************
- * g_info -- */ /**
-@@ -135,7 +136,7 @@
- */
-
- #define g_info(fmt, ...) g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, fmt, ## __VA_ARGS__)
--
-+#endif
-
- /*
- *******************************************************************************
---
-2.0.1
-
diff --git a/main/open-vm-tools-grsec/0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch b/main/open-vm-tools-grsec/0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch
new file mode 100644
index 0000000000..53ccc3485d
--- /dev/null
+++ b/main/open-vm-tools-grsec/0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch
@@ -0,0 +1,34 @@
+From 8df98f3c779fa43d073a42e82bd18cf28c2bd4af Mon Sep 17 00:00:00 2001
+From: Wendell Smith <wendellwsmith@gmail.com>
+Date: Sat, 7 Feb 2015 15:42:13 -0500
+Subject: [PATCH 2/3] Fix d_alias to d_u.d_alias for kernel 3.18
+
+---
+ open-vm-tools/modules/linux/vmhgfs/inode.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/open-vm-tools/modules/linux/vmhgfs/inode.c b/open-vm-tools/modules/linux/vmhgfs/inode.c
+index 77b1669..2d289e3 100644
+--- a/modules/linux/vmhgfs/inode.c
++++ b/modules/linux/vmhgfs/inode.c
+@@ -1917,7 +1917,7 @@ HgfsPermission(struct inode *inode,
+ p,
+ #endif
+ &inode->i_dentry,
+- d_alias) {
++ d_u.d_alias) {
+ int dcount = hgfs_d_count(dentry);
+ if (dcount) {
+ LOG(4, ("Found %s %d \n", dentry->d_name.name, dcount));
+@@ -1970,7 +1970,7 @@ HgfsPermission(struct inode *inode,
+ /* Find a dentry with valid d_count. Refer bug 587879. */
+ list_for_each(pos, &inode->i_dentry) {
+ int dcount;
+- struct dentry *dentry = list_entry(pos, struct dentry, d_alias);
++ struct dentry *dentry = list_entry(pos, struct dentry, d_u.d_alias);
+ dcount = hgfs_d_count(dentry);
+ if (dcount) {
+ LOG(4, ("Found %s %d \n", (dentry)->d_name.name, dcount));
+--
+2.3.4
+
diff --git a/main/open-vm-tools-grsec/0003-Add-kuid_t-kgid_t-compatibility-layer.patch b/main/open-vm-tools-grsec/0003-Add-kuid_t-kgid_t-compatibility-layer.patch
deleted file mode 100755
index 33e9b13417..0000000000
--- a/main/open-vm-tools-grsec/0003-Add-kuid_t-kgid_t-compatibility-layer.patch
+++ /dev/null
@@ -1,311 +0,0 @@
-From 327938705e9223cdc15c5e0d85b0cdfafb4b6cd7 Mon Sep 17 00:00:00 2001
-From: "Scott M. Kroll" <skroll@gmail.com>
-Date: Sun, 13 Jul 2014 18:19:35 -0400
-Subject: [PATCH 3/5] Add kuid_t/kgid_t compatibility layer
-
----
- open-vm-tools/modules/linux/vmhgfs/filesystem.c | 20 ++--
- open-vm-tools/modules/linux/vmhgfs/fsutil.c | 118 ++++++++++++++++++++----
- open-vm-tools/modules/linux/vmhgfs/fsutil.h | 5 +-
- open-vm-tools/modules/linux/vmhgfs/inode.c | 18 +++-
- open-vm-tools/modules/linux/vmhgfs/module.h | 14 ++-
- 5 files changed, 145 insertions(+), 30 deletions(-)
-
-diff --git a/open-vm-tools/modules/linux/vmhgfs/filesystem.c b/open-vm-tools/modules/linux/vmhgfs/filesystem.c
-index f101ca7..c845b36 100644
---- a/modules/linux/vmhgfs/filesystem.c
-+++ b/modules/linux/vmhgfs/filesystem.c
-@@ -228,17 +228,25 @@ HgfsInitSuperInfo(HgfsMountInfo *mountInfo) // IN: Passed down from the user
- * or gid given to us by the server.
- */
- si->uidSet = mountInfo->uidSet;
-+ si->uid = current_uid();
- if (si->uidSet) {
-- si->uid = mountInfo->uid;
-- } else {
-- si->uid = current_uid();
-+ kuid_t mntUid = make_kuid(current_user_ns(), mountInfo->uid);
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
-+ if (uid_valid(mntUid))
-+#endif
-+ si->uid = mntUid;
- }
-+
- si->gidSet = mountInfo->gidSet;
-+ si->gid = current_gid();
- if (si->gidSet) {
-- si->gid = mountInfo->gid;
-- } else {
-- si->gid = current_gid();
-+ kgid_t mntGid = make_kgid(current_user_ns(), mountInfo->gid);
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
-+ if (gid_valid(mntGid))
-+#endif
-+ si->gid = mntGid;
- }
-+
- si->fmask = mountInfo->fmask;
- si->dmask = mountInfo->dmask;
- si->ttl = mountInfo->ttl * HZ; // in ticks
-diff --git a/open-vm-tools/modules/linux/vmhgfs/fsutil.c b/open-vm-tools/modules/linux/vmhgfs/fsutil.c
-index 28858bc..1028cc9 100644
---- a/modules/linux/vmhgfs/fsutil.c
-+++ b/modules/linux/vmhgfs/fsutil.c
-@@ -545,6 +545,105 @@ HgfsUnpackCommonAttr(HgfsReq *req, // IN: Reply packet
- /*
- *----------------------------------------------------------------------
- *
-+ * HgfsCalcBlockSize --
-+ *
-+ * Calculate the number of 512 byte blocks used.
-+ *
-+ * Round the size to the next whole block and divide by the block size
-+ * to get the number of 512 byte blocks.
-+ * Note, this is taken from the nfs client and is simply performing:
-+ * (size + 512-1)/ 512)
-+ *
-+ * Results:
-+ * The number of 512 byte blocks for the size.
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
-+static inline blkcnt_t
-+HgfsCalcBlockSize(uint64 tsize)
-+{
-+ blkcnt_t used = (tsize + 511) >> 9;
-+ return (used > ULONG_MAX) ? ULONG_MAX : used;
-+}
-+#else
-+static inline unsigned long
-+HgfsCalcBlockSize(uint64 tsize)
-+{
-+ loff_t used = (tsize + 511) >> 9;
-+ return (used > ULONG_MAX) ? ULONG_MAX : used;
-+}
-+#endif
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsSetInodeUidGid --
-+ *
-+ * Set the UID and GID of the inode.
-+ *
-+ * Update an inode's UID and GID to match those of the HgfsAttr returned
-+ * by the server.
-+ *
-+ * Results:
-+ * The number of 512 byte blocks for the size.
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static void
-+HgfsSetInodeUidGid(struct inode *inode, // IN/OUT: Inode
-+ HgfsSuperInfo *si, // IN: New attrs
-+ HgfsAttrInfo const *attr) // IN: New attrs
-+{
-+ /*
-+ * Use the stored uid and gid if we were given them at mount-time, or if
-+ * the server didn't give us a uid or gid.
-+ */
-+ if (si->uidSet || (attr->mask & HGFS_ATTR_VALID_USERID) == 0) {
-+ inode->i_uid = si->uid;
-+ } else {
-+ kuid_t attrUid = make_kuid(&init_user_ns, attr->userId);
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
-+ if (uid_valid(attrUid)) {
-+ inode->i_uid = attrUid;
-+ } else {
-+ inode->i_uid = si->uid;
-+ }
-+#else
-+ inode->i_uid = attrUid;
-+#endif
-+ LOG(6, (KERN_DEBUG "VMware hgfs: %s: inode uid %u\n",
-+ __func__, from_kuid(&init_user_ns, inode->i_uid)));
-+ }
-+ if (si->gidSet || (attr->mask & HGFS_ATTR_VALID_GROUPID) == 0) {
-+ inode->i_gid = si->gid;
-+ } else {
-+ kgid_t attrGid = make_kgid(&init_user_ns, attr->groupId);
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
-+ if (gid_valid(attrGid)) {
-+ inode->i_gid = attrGid;
-+ } else {
-+ inode->i_gid = si->gid;
-+ }
-+#else
-+ inode->i_gid = attrGid;
-+#endif
-+ LOG(6, (KERN_DEBUG "VMware hgfs: %s: inode gid %u\n",
-+ __func__, from_kgid(&init_user_ns, inode->i_gid)));
-+ }
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
- * HgfsChangeFileAttributes --
- *
- * Update an inode's attributes to match those of the HgfsAttr. May
-@@ -634,20 +733,7 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
- */
- set_nlink(inode, 1);
-
-- /*
-- * Use the stored uid and gid if we were given them at mount-time, or if
-- * the server didn't give us a uid or gid.
-- */
-- if (si->uidSet || (attr->mask & HGFS_ATTR_VALID_USERID) == 0) {
-- inode->i_uid = si->uid;
-- } else {
-- inode->i_uid = attr->userId;
-- }
-- if (si->gidSet || (attr->mask & HGFS_ATTR_VALID_GROUPID) == 0) {
-- inode->i_gid = si->gid;
-- } else {
-- inode->i_gid = attr->groupId;
-- }
-+ HgfsSetInodeUidGid(inode, si, attr);
-
- inode->i_rdev = 0; /* Device nodes are not supported */
- #if !defined VMW_INODE_2618
-@@ -1618,8 +1704,8 @@ HgfsStatusConvertToLinux(HgfsStatus hgfsStatus) // IN: Status code to convert
- void
- HgfsSetUidGid(struct inode *parent, // IN: parent inode
- struct dentry *dentry, // IN: dentry of file to update
-- uid_t uid, // IN: uid to set
-- gid_t gid) // IN: gid to set
-+ kuid_t uid, // IN: uid to set
-+ kgid_t gid) // IN: gid to set
- {
- struct iattr setUidGid;
-
-diff --git a/open-vm-tools/modules/linux/vmhgfs/fsutil.h b/open-vm-tools/modules/linux/vmhgfs/fsutil.h
-index da5c5a1..2767099 100644
---- a/modules/linux/vmhgfs/fsutil.h
-+++ b/modules/linux/vmhgfs/fsutil.h
-@@ -32,6 +32,7 @@
- #include <linux/signal.h>
- #include "compat_fs.h"
-
-+#include "module.h" /* For kuid_t kgid_t types. */
- #include "inode.h"
- #include "request.h"
- #include "vm_basic_types.h"
-@@ -91,8 +92,8 @@ int HgfsGetHandle(struct inode *inode,
- int HgfsStatusConvertToLinux(HgfsStatus hgfsStatus);
- void HgfsSetUidGid(struct inode *parent,
- struct dentry *dentry,
-- uid_t uid,
-- gid_t gid);
-+ kuid_t uid,
-+ kgid_t gid);
- struct inode *HgfsGetInode(struct super_block *sb, ino_t ino);
- void HgfsDoReadInode(struct inode *inode);
-
-diff --git a/open-vm-tools/modules/linux/vmhgfs/inode.c b/open-vm-tools/modules/linux/vmhgfs/inode.c
-index 859b3ff..caaa41a 100644
---- a/modules/linux/vmhgfs/inode.c
-+++ b/modules/linux/vmhgfs/inode.c
-@@ -404,6 +404,8 @@ HgfsPackSetattrRequest(struct iattr *iattr, // IN: Inode attrs to update from
- size_t reqBufferSize;
- size_t reqSize;
- int result = 0;
-+ uid_t attrUid = -1;
-+ gid_t attrGid = -1;
-
- ASSERT(iattr);
- ASSERT(dentry);
-@@ -412,6 +414,14 @@ HgfsPackSetattrRequest(struct iattr *iattr, // IN: Inode attrs to update from
-
- valid = iattr->ia_valid;
-
-+ if (valid & ATTR_UID) {
-+ attrUid = from_kuid(&init_user_ns, iattr->ia_uid);
-+ }
-+
-+ if (valid & ATTR_GID) {
-+ attrGid = from_kgid(&init_user_ns, iattr->ia_gid);
-+ }
-+
- switch (opUsed) {
- case HGFS_OP_SETATTR_V3: {
- HgfsRequest *requestHeader;
-@@ -488,13 +498,13 @@ HgfsPackSetattrRequest(struct iattr *iattr, // IN: Inode attrs to update from
-
- if (valid & ATTR_UID) {
- attrV2->mask |= HGFS_ATTR_VALID_USERID;
-- attrV2->userId = iattr->ia_uid;
-+ attrV2->userId = attrUid;
- *changed = TRUE;
- }
-
- if (valid & ATTR_GID) {
- attrV2->mask |= HGFS_ATTR_VALID_GROUPID;
-- attrV2->groupId = iattr->ia_gid;
-+ attrV2->groupId = attrGid;
- *changed = TRUE;
- }
-
-@@ -591,13 +601,13 @@ HgfsPackSetattrRequest(struct iattr *iattr, // IN: Inode attrs to update from
-
- if (valid & ATTR_UID) {
- attrV2->mask |= HGFS_ATTR_VALID_USERID;
-- attrV2->userId = iattr->ia_uid;
-+ attrV2->userId = attrUid;
- *changed = TRUE;
- }
-
- if (valid & ATTR_GID) {
- attrV2->mask |= HGFS_ATTR_VALID_GROUPID;
-- attrV2->groupId = iattr->ia_gid;
-+ attrV2->groupId = attrGid;
- *changed = TRUE;
- }
-
-diff --git a/open-vm-tools/modules/linux/vmhgfs/module.h b/open-vm-tools/modules/linux/vmhgfs/module.h
-index 3e0973b..b6bcd1e 100644
---- a/modules/linux/vmhgfs/module.h
-+++ b/modules/linux/vmhgfs/module.h
-@@ -74,6 +74,16 @@ extern int LOGLEVEL_THRESHOLD;
- * Macros for accessing members that are private to this code in
- * sb/inode/file structs.
- */
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
-+typedef uid_t kuid_t;
-+typedef gid_t kgid_t;
-+#define from_kuid(_ns, _kuid) (_kuid)
-+#define from_kgid(_ns, _kgid) (_kgid)
-+#define make_kuid(_ns, _uid) (_uid)
-+#define make_kgid(_ns, _gid) (_gid)
-+#endif
-+
- #define HGFS_SET_SB_TO_COMMON(sb, common) do { (sb)->s_fs_info = (common); } while (0)
- #define HGFS_SB_TO_COMMON(sb) ((HgfsSuperInfo *)(sb)->s_fs_info)
-
-@@ -110,9 +120,9 @@ extern int LOGLEVEL_THRESHOLD;
-
- /* Data kept in each superblock in sb->u. */
- typedef struct HgfsSuperInfo {
-- uid_t uid; /* UID of user who mounted this fs. */
-+ kuid_t uid; /* UID of user who mounted this fs. */
-+ kgid_t gid; /* GID of user who mounted this fs. */
- Bool uidSet; /* Was the UID specified at mount-time? */
-- gid_t gid; /* GID of user who mounted this fs. */
- Bool gidSet; /* Was the GID specified at mount-time? */
- mode_t fmask; /* File permission mask. */
- mode_t dmask; /* Directory permission mask. */
---
-2.0.1
-
diff --git a/main/open-vm-tools-grsec/0004-Use-new-link-helpers.patch b/main/open-vm-tools-grsec/0004-Use-new-link-helpers.patch
deleted file mode 100755
index a60fa6faed..0000000000
--- a/main/open-vm-tools-grsec/0004-Use-new-link-helpers.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From 20437d731289126ee5363a6f73e4171d39f2e3d9 Mon Sep 17 00:00:00 2001
-From: "Scott M. Kroll" <skroll@gmail.com>
-Date: Mon, 14 Jul 2014 11:32:35 -0400
-Subject: [PATCH 4/5] Use new link helpers
-
-* vfs_follow_link was removed in 3.12.
-* vfs_readlink was removed in 3.15.
----
- open-vm-tools/modules/linux/vmhgfs/link.c | 15 +++++++++++++++
- 1 file changed, 15 insertions(+)
-
-diff --git a/open-vm-tools/modules/linux/vmhgfs/link.c b/open-vm-tools/modules/linux/vmhgfs/link.c
-index 9fb95a5..06ea953 100644
---- a/modules/linux/vmhgfs/link.c
-+++ b/modules/linux/vmhgfs/link.c
-@@ -110,9 +110,15 @@ HgfsFollowlink(struct dentry *dentry, // IN: Dentry containing link
- "on something that wasn't a symlink\n"));
- error = -EINVAL;
- } else {
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: calling "
-+ "nd_set_link\n"));
-+ nd_set_link(nd, fileName);
-+#else
- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: calling "
- "vfs_follow_link\n"));
- error = vfs_follow_link(nd, fileName);
-+#endif
- }
- kfree(fileName);
- }
-@@ -172,9 +178,18 @@ HgfsReadlink(struct dentry *dentry, // IN: Dentry containing link
- "on something that wasn't a symlink\n"));
- error = -EINVAL;
- } else {
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsReadlink: calling "
-+ "readlink_copy\n"));
-+ LOG(6, (KERN_DEBUG "VMware hgfs: %s: calling "
-+ "readlink_copy\n",
-+ __func__));
-+ error = readlink_copy(buffer, buflen, fileName);
-+#else
- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsReadlink: calling "
- "vfs_readlink\n"));
- error = vfs_readlink(dentry, buffer, buflen, fileName);
-+#endif
- }
- kfree(fileName);
- }
---
-2.0.1
-
diff --git a/main/open-vm-tools-grsec/0005-Update-hgfs-file-operations-for-newer-kernels.patch b/main/open-vm-tools-grsec/0005-Update-hgfs-file-operations-for-newer-kernels.patch
deleted file mode 100755
index a885d84d47..0000000000
--- a/main/open-vm-tools-grsec/0005-Update-hgfs-file-operations-for-newer-kernels.patch
+++ /dev/null
@@ -1,2688 +0,0 @@
-From c1a0f4254812d3588b3716204190a521e8f87db8 Mon Sep 17 00:00:00 2001
-From: "Scott M. Kroll" <skroll@gmail.com>
-Date: Mon, 14 Jul 2014 12:42:06 -0400
-Subject: [PATCH 5/5] Update hgfs file operations for newer kernels
-
-* Keep track of write back pages so concurrent file validations do not
- invalidate the cache.
-* Handle file flush operations.
----
- open-vm-tools/modules/linux/vmhgfs/file.c | 210 +++++-
- open-vm-tools/modules/linux/vmhgfs/filesystem.c | 103 +--
- open-vm-tools/modules/linux/vmhgfs/fsutil.c | 743 ++++++++++++++++----
- open-vm-tools/modules/linux/vmhgfs/fsutil.h | 2 +
- open-vm-tools/modules/linux/vmhgfs/inode.c | 66 +-
- open-vm-tools/modules/linux/vmhgfs/link.c | 57 +-
- open-vm-tools/modules/linux/vmhgfs/module.h | 7 +
- open-vm-tools/modules/linux/vmhgfs/page.c | 862 ++++++++++++++++++++++--
- 8 files changed, 1735 insertions(+), 315 deletions(-)
-
-diff --git a/open-vm-tools/modules/linux/vmhgfs/file.c b/open-vm-tools/modules/linux/vmhgfs/file.c
-index 3568f4a..825cebe 100644
---- a/modules/linux/vmhgfs/file.c
-+++ b/modules/linux/vmhgfs/file.c
-@@ -47,6 +47,20 @@
- #include "vm_assert.h"
- #include "vm_basic_types.h"
-
-+/*
-+ * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
-+ * the O_SYNC flag. We continue to use the existing numerical value
-+ * for O_DSYNC semantics now, but using the correct symbolic name for it.
-+ * This new value is used to request true Posix O_SYNC semantics. It is
-+ * defined in this strange way to make sure applications compiled against
-+ * new headers get at least O_DSYNC semantics on older kernels.
-+ */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
-+#define HGFS_FILECTL_SYNC(flags) ((flags) & O_DSYNC)
-+#else
-+#define HGFS_FILECTL_SYNC(flags) ((flags) & O_SYNC)
-+#endif
-+
- /* Private functions. */
- static int HgfsPackOpenRequest(struct inode *inode,
- struct file *file,
-@@ -84,6 +98,15 @@ static ssize_t HgfsWrite(struct file *file,
- static loff_t HgfsSeek(struct file *file,
- loff_t offset,
- int origin);
-+static int HgfsFlush(struct file *file
-+#if !defined VMW_FLUSH_HAS_1_ARG
-+ ,fl_owner_t id
-+#endif
-+ );
-+
-+#if !defined VMW_FSYNC_31
-+static int HgfsDoFsync(struct inode *inode);
-+#endif
-
- static int HgfsFsync(struct file *file,
- #if defined VMW_FSYNC_OLD
-@@ -126,7 +149,10 @@ struct file_operations HgfsFileFileOperations = {
- .owner = THIS_MODULE,
- .open = HgfsOpen,
- .llseek = HgfsSeek,
-+ .flush = HgfsFlush,
- #if defined VMW_USE_AIO
-+ .read = do_sync_read,
-+ .write = do_sync_write,
- .aio_read = HgfsAioRead,
- .aio_write = HgfsAioWrite,
- #else
-@@ -797,22 +823,63 @@ HgfsAioWrite(struct kiocb *iocb, // IN: I/O control block
- loff_t offset) // IN: Offset at which to read
- {
- int result;
-+ struct dentry *writeDentry;
-+ HgfsInodeInfo *iinfo;
-
- ASSERT(iocb);
- ASSERT(iocb->ki_filp);
- ASSERT(iocb->ki_filp->f_dentry);
- ASSERT(iov);
-
-- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsAioWrite: was called\n"));
-+ writeDentry = iocb->ki_filp->f_dentry;
-+ iinfo = INODE_GET_II_P(writeDentry->d_inode);
-
-- result = HgfsRevalidate(iocb->ki_filp->f_dentry);
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsAioWrite(%s/%s, %lu@%Ld)\n",
-+ writeDentry->d_parent->d_name.name, writeDentry->d_name.name,
-+ (unsigned long) iov_length(iov, numSegs), (long long) offset));
-+
-+ spin_lock(&writeDentry->d_inode->i_lock);
-+ /*
-+ * Guard against dentry revalidation invalidating the inode underneath us.
-+ *
-+ * Data is being written and may have valid data in a page in the cache.
-+ * This action prevents any invalidating of the inode when a flushing of
-+ * cache data occurs prior to syncing the file with the server's attributes.
-+ * The flushing of cache data would empty our in memory write pages list and
-+ * would cause the inode modified write time to be updated and so the inode
-+ * would also be invalidated.
-+ */
-+ iinfo->numWbPages++;
-+ spin_unlock(&writeDentry->d_inode->i_lock);
-+
-+ result = HgfsRevalidate(writeDentry);
- if (result) {
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsAioWrite: invalid dentry\n"));
- goto out;
- }
-
- result = generic_file_aio_write(iocb, iov, numSegs, offset);
-- out:
-+
-+ if (result >= 0) {
-+ if (IS_SYNC(writeDentry->d_inode) ||
-+ HGFS_FILECTL_SYNC(iocb->ki_filp->f_flags)) {
-+ int error;
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
-+ error = vfs_fsync(iocb->ki_filp, 0);
-+#else
-+ error = HgfsDoFsync(writeDentry->d_inode);
-+#endif
-+
-+ if (error < 0) {
-+ result = error;
-+ }
-+ }
-+ }
-+
-+out:
-+ spin_lock(&writeDentry->d_inode->i_lock);
-+ iinfo->numWbPages--;
-+ spin_unlock(&writeDentry->d_inode->i_lock);
- return result;
- }
-
-@@ -962,6 +1029,98 @@ HgfsSeek(struct file *file, // IN: File to seek
- }
-
-
-+#if !defined VMW_FSYNC_31
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsDoFsync --
-+ *
-+ * Helper for HgfsFlush() and HgfsFsync().
-+ *
-+ * The hgfs protocol doesn't support fsync explicityly yet.
-+ * So for now, we flush all the pages to presumably honor the
-+ * intent of an app calling fsync() which is to get the
-+ * data onto persistent storage. As things stand now we're at
-+ * the whim of the hgfs server code running on the host to fsync or
-+ * not if and when it pleases.
-+ *
-+ *
-+ * Results:
-+ * Returns zero on success. Otherwise an error.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static int
-+HgfsDoFsync(struct inode *inode) // IN: File we operate on
-+{
-+ int ret;
-+
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDoFsync(%"FMT64"u)\n",
-+ INODE_GET_II_P(inode)->hostFileId));
-+
-+ ret = compat_filemap_write_and_wait(inode->i_mapping);
-+
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDoFsync: returns %d\n", ret));
-+
-+ return ret;
-+}
-+#endif
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsFlush --
-+ *
-+ * Called when user process calls fflush() on an hgfs file.
-+ * Flush all dirty pages and check for write errors.
-+ *
-+ *
-+ * Results:
-+ * Returns zero on success. (Currently always succeeds).
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static int
-+HgfsFlush(struct file *file // IN: file to flush
-+#if !defined VMW_FLUSH_HAS_1_ARG
-+ ,fl_owner_t id // IN: id not used
-+#endif
-+ )
-+{
-+ int ret = 0;
-+
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsFlush(%s/%s)\n",
-+ file->f_dentry->d_parent->d_name.name,
-+ file->f_dentry->d_name.name));
-+
-+ if ((file->f_mode & FMODE_WRITE) == 0) {
-+ goto exit;
-+ }
-+
-+
-+ /* Flush writes to the server and return any errors */
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFlush: calling vfs_sync ... \n"));
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
-+ ret = vfs_fsync(file, 0);
-+#else
-+ ret = HgfsDoFsync(file->f_dentry->d_inode);
-+#endif
-+
-+exit:
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsFlush: returns %d\n", ret));
-+ return ret;
-+}
-+
-+
- /*
- *----------------------------------------------------------------------
- *
-@@ -969,21 +1128,13 @@ HgfsSeek(struct file *file, // IN: File to seek
- *
- * Called when user process calls fsync() on hgfs file.
- *
-- * The hgfs protocol doesn't support fsync yet, so for now, we punt
-- * and just return success. This is a little less sketchy than it
-- * might sound, because hgfs skips the buffer cache in the guest
-- * anyway (we always write to the host immediately).
-- *
-- * In the future we might want to try harder though, since
-- * presumably the intent of an app calling fsync() is to get the
-+ * The hgfs protocol doesn't support fsync explicitly yet,
-+ * so for now, we flush all the pages to presumably honor the
-+ * intent of an app calling fsync() which is to get the
- * data onto persistent storage, and as things stand now we're at
- * the whim of the hgfs server code running on the host to fsync or
- * not if and when it pleases.
- *
-- * Note that do_fsync will call filemap_fdatawrite() before us and
-- * filemap_fdatawait() after us, so there's no need to do anything
-- * here w.r.t. writing out dirty pages.
-- *
- * Results:
- * Returns zero on success. (Currently always succeeds).
- *
-@@ -1003,9 +1154,36 @@ HgfsFsync(struct file *file, // IN: File we operate on
- #endif
- int datasync) // IN: fdatasync or fsync
- {
-- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFsync: was called\n"));
-+ int ret = 0;
-+ loff_t startRange;
-+ loff_t endRange;
-+ struct inode *inode;
-+
-+#if defined VMW_FSYNC_31
-+ startRange = start;
-+ endRange = end;
-+#else
-+ startRange = 0;
-+ endRange = MAX_INT64;
-+#endif
-
-- return 0;
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsFsync(%s/%s, %lld, %lld, %d)\n",
-+ file->f_dentry->d_parent->d_name.name,
-+ file->f_dentry->d_name.name,
-+ startRange, endRange,
-+ datasync));
-+
-+ /* Flush writes to the server and return any errors */
-+ inode = file->f_dentry->d_inode;
-+#if defined VMW_FSYNC_31
-+ ret = filemap_write_and_wait_range(inode->i_mapping, startRange, endRange);
-+#else
-+ ret = HgfsDoFsync(inode);
-+#endif
-+
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsFsync: written pages %lld, %lld returns %d)\n",
-+ startRange, endRange, ret));
-+ return ret;
- }
-
-
-diff --git a/open-vm-tools/modules/linux/vmhgfs/filesystem.c b/open-vm-tools/modules/linux/vmhgfs/filesystem.c
-index c845b36..dc0adcd 100644
---- a/modules/linux/vmhgfs/filesystem.c
-+++ b/modules/linux/vmhgfs/filesystem.c
-@@ -83,7 +83,6 @@ HgfsOp hgfsVersionCreateSymlink;
- static inline unsigned long HgfsComputeBlockBits(unsigned long blockSize);
- static compat_kmem_cache_ctor HgfsInodeCacheCtor;
- static HgfsSuperInfo *HgfsInitSuperInfo(HgfsMountInfo *mountInfo);
--static int HgfsGetRootDentry(struct super_block *sb, struct dentry **rootDentry);
- static int HgfsReadSuper(struct super_block *sb,
- void *rawData,
- int flags);
-@@ -335,103 +334,6 @@ HgfsInitSuperInfo(HgfsMountInfo *mountInfo) // IN: Passed down from the user
-
-
- /*
-- *----------------------------------------------------------------------------
-- *
-- * HgfsGetRootDentry --
-- *
-- * Gets the root dentry for a given super block.
-- *
-- * Results:
-- * zero and a valid root dentry on success
-- * negative value on failure
-- *
-- * Side effects:
-- * None.
-- *
-- *----------------------------------------------------------------------------
-- */
--
--static int
--HgfsGetRootDentry(struct super_block *sb, // IN: Super block object
-- struct dentry **rootDentry) // OUT: Root dentry
--{
-- int result = -ENOMEM;
-- struct inode *rootInode;
-- struct dentry *tempRootDentry = NULL;
-- struct HgfsAttrInfo rootDentryAttr;
-- HgfsInodeInfo *iinfo;
--
-- ASSERT(sb);
-- ASSERT(rootDentry);
--
-- LOG(6, (KERN_DEBUG "VMware hgfs: %s: entered\n", __func__));
--
-- rootInode = HgfsGetInode(sb, HGFS_ROOT_INO);
-- if (rootInode == NULL) {
-- LOG(6, (KERN_DEBUG "VMware hgfs: %s: Could not get the root inode\n",
-- __func__));
-- goto exit;
-- }
--
-- /*
-- * On an allocation failure in read_super, the inode will have been
-- * marked "bad". If it was, we certainly don't want to start playing with
-- * the HgfsInodeInfo. So quietly put the inode back and fail.
-- */
-- if (is_bad_inode(rootInode)) {
-- LOG(6, (KERN_DEBUG "VMware hgfs: %s: encountered bad inode\n",
-- __func__));
-- goto exit;
-- }
--
-- tempRootDentry = d_make_root(rootInode);
-- /*
-- * d_make_root() does iput() on failure; if d_make_root() completes
-- * successfully then subsequent dput() will do iput() for us, so we
-- * should just ignore root inode from now on.
-- */
-- rootInode = NULL;
--
-- if (tempRootDentry == NULL) {
-- LOG(4, (KERN_WARNING "VMware hgfs: %s: Could not get "
-- "root dentry\n", __func__));
-- goto exit;
-- }
--
-- result = HgfsPrivateGetattr(tempRootDentry, &rootDentryAttr, NULL);
-- if (result) {
-- LOG(4, (KERN_WARNING "VMware hgfs: HgfsReadSuper: Could not"
-- "instantiate the root dentry\n"));
-- goto exit;
-- }
--
-- iinfo = INODE_GET_II_P(tempRootDentry->d_inode);
-- iinfo->isFakeInodeNumber = FALSE;
-- iinfo->isReferencedInode = TRUE;
--
-- if (rootDentryAttr.mask & HGFS_ATTR_VALID_FILEID) {
-- iinfo->hostFileId = rootDentryAttr.hostFileId;
-- }
--
-- HgfsChangeFileAttributes(tempRootDentry->d_inode, &rootDentryAttr);
-- HgfsDentryAgeReset(tempRootDentry);
-- tempRootDentry->d_op = &HgfsDentryOperations;
--
-- *rootDentry = tempRootDentry;
-- result = 0;
--
-- LOG(6, (KERN_DEBUG "VMware hgfs: %s: finished\n", __func__));
--exit:
-- if (result) {
-- iput(rootInode);
-- dput(tempRootDentry);
-- *rootDentry = NULL;
-- }
-- return result;
--}
--
--
--/*
- *-----------------------------------------------------------------------------
- *
- * HgfsReadSuper --
-@@ -511,7 +413,10 @@ HgfsReadSuper(struct super_block *sb, // OUT: Superblock object
- sb->s_blocksize_bits = HgfsComputeBlockBits(HGFS_BLOCKSIZE);
- sb->s_blocksize = 1 << sb->s_blocksize_bits;
-
-- result = HgfsGetRootDentry(sb, &rootDentry);
-+ /*
-+ * Create the root dentry and its corresponding inode.
-+ */
-+ result = HgfsInstantiateRoot(sb, &rootDentry);
- if (result) {
- LOG(4, (KERN_WARNING "VMware hgfs: HgfsReadSuper: Could not instantiate "
- "root dentry\n"));
-diff --git a/open-vm-tools/modules/linux/vmhgfs/fsutil.c b/open-vm-tools/modules/linux/vmhgfs/fsutil.c
-index 1028cc9..72f81f1 100644
---- a/modules/linux/vmhgfs/fsutil.c
-+++ b/modules/linux/vmhgfs/fsutil.c
-@@ -1,5 +1,5 @@
- /*********************************************************
-- * Copyright (C) 2006 VMware, Inc. All rights reserved.
-+ * Copyright (C) 2006-2014 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
-@@ -53,10 +53,13 @@ static int HgfsUnpackGetattrReply(HgfsReq *req,
- HgfsAttrInfo *attr,
- char **fileName);
- static int HgfsPackGetattrRequest(HgfsReq *req,
-- struct dentry *dentry,
-+ HgfsOp opUsed,
- Bool allowHandleReuse,
-- HgfsOp opUsed,
-+ struct dentry *dentry,
- HgfsAttrInfo *attr);
-+static int HgfsBuildRootPath(char *buffer,
-+ size_t bufferLen,
-+ HgfsSuperInfo *si);
-
- /*
- * Private function implementations.
-@@ -234,13 +237,17 @@ HgfsUnpackGetattrReply(HgfsReq *req, // IN: Reply packet
- /*
- *----------------------------------------------------------------------
- *
-- * HgfsPackGetattrRequest --
-+ * HgfsPackCommonattr --
- *
-- * Setup the getattr request, depending on the op version. When possible,
-- * we will issue the getattr using an existing open HGFS handle.
-+ * This function abstracts the HgfsAttr struct behind HgfsAttrInfo.
-+ * Callers can pass one of four replies into it and receive back the
-+ * attributes for those replies.
-+ *
-+ * Callers must populate attr->requestType so that we know whether to
-+ * expect a V1 or V2 Attr struct.
- *
- * Results:
-- * Returns zero on success, or negative error on failure.
-+ * Zero on success, non-zero otherwise.
- *
- * Side effects:
- * None
-@@ -249,22 +256,18 @@ HgfsUnpackGetattrReply(HgfsReq *req, // IN: Reply packet
- */
-
- static int
--HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer
-- struct dentry *dentry, // IN: Dentry containing name
-- Bool allowHandleReuse, // IN: Can we use a handle?
-- HgfsOp opUsed, // IN: Op to be used
-- HgfsAttrInfo *attr) // OUT: Attrs to update
-+HgfsPackCommonattr(HgfsReq *req, // IN/OUT: request buffer
-+ HgfsOp opUsed, // IN: Op to be used
-+ Bool allowHandleReuse, // IN: Can we use a handle?
-+ struct inode *fileInode, // IN: file inode
-+ size_t *reqSize, // OUT: request size
-+ size_t *reqBufferSize, // OUT: request buffer size
-+ char **fileName, // OUT: pointer to request file name
-+ uint32 **fileNameLength, // OUT: pointer to request file name length
-+ HgfsAttrInfo *attr) // OUT: Attrs to update
- {
-- size_t reqBufferSize;
-- size_t reqSize;
-- int result = 0;
- HgfsHandle handle;
-- char *fileName = NULL;
-- uint32 *fileNameLength = NULL;
--
-- ASSERT(attr);
-- ASSERT(dentry);
-- ASSERT(req);
-+ int result = 0;
-
- attr->requestType = opUsed;
-
-@@ -287,24 +290,25 @@ HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer
- * by name.
- */
- requestV3->hints = 0;
-- if (allowHandleReuse && HgfsGetHandle(dentry->d_inode,
-+ if (allowHandleReuse && HgfsGetHandle(fileInode,
- 0,
- &handle) == 0) {
- requestV3->fileName.flags = HGFS_FILE_NAME_USE_FILE_DESC;
- requestV3->fileName.fid = handle;
- requestV3->fileName.length = 0;
- requestV3->fileName.caseType = HGFS_FILE_NAME_DEFAULT_CASE;
-- fileName = NULL;
-+ *fileName = NULL;
-+ *fileNameLength = NULL;
- } else {
-- fileName = requestV3->fileName.name;
-- fileNameLength = &requestV3->fileName.length;
-+ *fileName = requestV3->fileName.name;
-+ *fileNameLength = &requestV3->fileName.length;
- requestV3->fileName.flags = 0;
- requestV3->fileName.fid = HGFS_INVALID_HANDLE;
- requestV3->fileName.caseType = HGFS_FILE_NAME_CASE_SENSITIVE;
- }
- requestV3->reserved = 0;
-- reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(requestV3);
-- reqBufferSize = HGFS_NAME_BUFFER_SIZET(req->bufferSize, reqSize);
-+ *reqSize = HGFS_REQ_PAYLOAD_SIZE_V3(requestV3);
-+ *reqBufferSize = HGFS_NAME_BUFFER_SIZET(req->bufferSize, *reqSize);
- break;
- }
-
-@@ -321,19 +325,20 @@ HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer
- * correct regardless. If we don't find a handle, fall back on getattr
- * by name.
- */
-- if (allowHandleReuse && HgfsGetHandle(dentry->d_inode,
-+ if (allowHandleReuse && HgfsGetHandle(fileInode,
- 0,
- &handle) == 0) {
- requestV2->hints = HGFS_ATTR_HINT_USE_FILE_DESC;
- requestV2->file = handle;
-- fileName = NULL;
-+ *fileName = NULL;
-+ *fileNameLength = NULL;
- } else {
- requestV2->hints = 0;
-- fileName = requestV2->fileName.name;
-- fileNameLength = &requestV2->fileName.length;
-+ *fileName = requestV2->fileName.name;
-+ *fileNameLength = &requestV2->fileName.length;
- }
-- reqSize = sizeof *requestV2;
-- reqBufferSize = HGFS_NAME_BUFFER_SIZE(req->bufferSize, requestV2);
-+ *reqSize = sizeof *requestV2;
-+ *reqBufferSize = HGFS_NAME_BUFFER_SIZE(req->bufferSize, requestV2);
- break;
- }
-
-@@ -344,10 +349,10 @@ HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer
- requestV1->header.op = opUsed;
- requestV1->header.id = req->id;
-
-- fileName = requestV1->fileName.name;
-- fileNameLength = &requestV1->fileName.length;
-- reqSize = sizeof *requestV1;
-- reqBufferSize = HGFS_NAME_BUFFER_SIZE(req->bufferSize, requestV1);
-+ *fileName = requestV1->fileName.name;
-+ *fileNameLength = &requestV1->fileName.length;
-+ *reqSize = sizeof *requestV1;
-+ *reqBufferSize = HGFS_NAME_BUFFER_SIZE(req->bufferSize, requestV1);
- break;
- }
-
-@@ -355,6 +360,57 @@ HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackGetattrRequest: unexpected "
- "OP type encountered\n"));
- result = -EPROTO;
-+ break;
-+ }
-+
-+ return result;
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsPackGetattrRequest --
-+ *
-+ * Setup the getattr request, depending on the op version. When possible,
-+ * we will issue the getattr using an existing open HGFS handle.
-+ *
-+ * Results:
-+ * Returns zero on success, or negative error on failure.
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static int
-+HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer
-+ HgfsOp opUsed, // IN: Op to be used
-+ Bool allowHandleReuse, // IN: Can we use a handle?
-+ struct dentry *dentry, // IN: Dentry containing name
-+ HgfsAttrInfo *attr) // OUT: Attrs to update
-+{
-+ size_t reqBufferSize;
-+ size_t reqSize;
-+ char *fileName = NULL;
-+ uint32 *fileNameLength = NULL;
-+ int result = 0;
-+
-+ ASSERT(attr);
-+ ASSERT(dentry);
-+ ASSERT(req);
-+
-+ result = HgfsPackCommonattr(req,
-+ opUsed,
-+ allowHandleReuse,
-+ dentry->d_inode,
-+ &reqSize,
-+ &reqBufferSize,
-+ &fileName,
-+ &fileNameLength,
-+ attr);
-+ if (0 > result) {
- goto out;
- }
-
-@@ -364,8 +420,90 @@ HgfsPackGetattrRequest(HgfsReq *req, // IN/OUT: Request buffer
- /* Build full name to send to server. */
- if (HgfsBuildPath(fileName, reqBufferSize,
- dentry) < 0) {
-- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackGetattrRequest: build path "
-- "failed\n"));
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackGetattrRequest: build path failed\n"));
-+ result = -EINVAL;
-+ goto out;
-+ }
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsPackGetattrRequest: getting attrs for \"%s\"\n",
-+ fileName));
-+
-+ /* Convert to CP name. */
-+ result = CPName_ConvertTo(fileName,
-+ reqBufferSize,
-+ fileName);
-+ if (result < 0) {
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackGetattrRequest: CP conversion failed\n"));
-+ result = -EINVAL;
-+ goto out;
-+ }
-+
-+ *fileNameLength = result;
-+ }
-+
-+ req->payloadSize = reqSize + result;
-+ result = 0;
-+
-+out:
-+ return result;
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsPackGetattrRootRequest --
-+ *
-+ * Setup the getattr request for the root of the HGFS file system.
-+ *
-+ * When possible, we will issue the getattr using an existing open HGFS handle.
-+ *
-+ * Results:
-+ * Returns zero on success, or negative error on failure.
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static int
-+HgfsPackGetattrRootRequest(HgfsReq *req, // IN/OUT: Request buffer
-+ HgfsOp opUsed, // IN: Op to be used
-+ struct super_block *sb, // IN: Super block entry
-+ HgfsAttrInfo *attr) // OUT: Attrs to update
-+{
-+ size_t reqBufferSize;
-+ size_t reqSize;
-+ char *fileName = NULL;
-+ uint32 *fileNameLength = NULL;
-+ int result = 0;
-+
-+ ASSERT(attr);
-+ ASSERT(sb);
-+ ASSERT(req);
-+
-+ result = HgfsPackCommonattr(req,
-+ opUsed,
-+ FALSE,
-+ NULL,
-+ &reqSize,
-+ &reqBufferSize,
-+ &fileName,
-+ &fileNameLength,
-+ attr);
-+ if (0 > result) {
-+ goto out;
-+ }
-+
-+ /* Avoid all this extra work when we're doing a getattr by handle. */
-+ if (fileName != NULL) {
-+ HgfsSuperInfo *si = HGFS_SB_TO_COMMON(sb);
-+
-+ /* Build full name to send to server. */
-+ if (HgfsBuildRootPath(fileName,
-+ reqBufferSize,
-+ si) < 0) {
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackGetattrRootRequest: build path failed\n"));
- result = -EINVAL;
- goto out;
- }
-@@ -511,7 +649,8 @@ HgfsUnpackCommonAttr(HgfsReq *req, // IN: Reply packet
- attrInfo->groupId = attrV2->groupId;
- attrInfo->mask |= HGFS_ATTR_VALID_GROUPID;
- }
-- if (attrV2->mask & HGFS_ATTR_VALID_FILEID) {
-+ if (attrV2->mask & (HGFS_ATTR_VALID_FILEID |
-+ HGFS_ATTR_VALID_NON_STATIC_FILEID)) {
- attrInfo->hostFileId = attrV2->hostFileId;
- attrInfo->mask |= HGFS_ATTR_VALID_FILEID;
- }
-@@ -578,6 +717,18 @@ HgfsCalcBlockSize(uint64 tsize)
- }
- #endif
-
-+
-+static inline int
-+hgfs_timespec_compare(const struct timespec *lhs, const struct timespec *rhs)
-+{
-+ if (lhs->tv_sec < rhs->tv_sec)
-+ return -1;
-+ if (lhs->tv_sec > rhs->tv_sec)
-+ return 1;
-+ return lhs->tv_nsec - rhs->tv_nsec;
-+}
-+
-+
- /*
- *----------------------------------------------------------------------
- *
-@@ -640,6 +791,74 @@ HgfsSetInodeUidGid(struct inode *inode, // IN/OUT: Inode
- }
- }
-
-+/*
-+ *-----------------------------------------------------------------------------
-+ *
-+ * HgfsIsInodeWritable --
-+ *
-+ * Helper function for verifying if a file is under write access.
-+ *
-+ * Results:
-+ * TRUE if file is writable, FALSE otherwise.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *-----------------------------------------------------------------------------
-+ */
-+
-+static Bool
-+HgfsIsInodeWritable(struct inode *inode) // IN: File we're writing to
-+{
-+ HgfsInodeInfo *iinfo;
-+ struct list_head *cur;
-+ Bool isWritable = FALSE;
-+
-+ iinfo = INODE_GET_II_P(inode);
-+ /*
-+ * Iterate over the open handles for this inode, and find if there
-+ * is one that allows the write mode.
-+ * Note, the mode is stored as incremented by one to prevent overload of
-+ * the zero value.
-+ */
-+ spin_lock(&hgfsBigLock);
-+ list_for_each(cur, &iinfo->files) {
-+ HgfsFileInfo *finfo = list_entry(cur, HgfsFileInfo, list);
-+
-+ if (0 != (finfo->mode & (HGFS_OPEN_MODE_WRITE_ONLY + 1))) {
-+ isWritable = TRUE;
-+ break;
-+ }
-+ }
-+ spin_unlock(&hgfsBigLock);
-+
-+ return isWritable;
-+}
-+
-+
-+/*
-+ *-----------------------------------------------------------------------------
-+ *
-+ * HgfsIsSafeToChange --
-+ *
-+ * Helper function for verifying if a file inode size and time fields is safe
-+ * to update. It is deemed safe only if there is not an open writer to the file.
-+ *
-+ * Results:
-+ * TRUE if safe to change inode, FALSE otherwise.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *-----------------------------------------------------------------------------
-+ */
-+
-+static Bool
-+HgfsIsSafeToChange(struct inode *inode) // IN: File we're writing to
-+{
-+ return !HgfsIsInodeWritable(inode);
-+}
-+
-
- /*
- *----------------------------------------------------------------------
-@@ -665,13 +884,34 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
- HgfsAttrInfo const *attr) // IN: New attrs
- {
- HgfsSuperInfo *si;
-+ HgfsInodeInfo *iinfo;
- Bool needInvalidate = FALSE;
-+ Bool isSafeToChange;
-
- ASSERT(inode);
- ASSERT(inode->i_sb);
- ASSERT(attr);
-
- si = HGFS_SB_TO_COMMON(inode->i_sb);
-+ iinfo = INODE_GET_II_P(inode);
-+
-+ /*
-+ * We do not want to update the file size from server or invalidate the inode
-+ * for inodes open for write. We need to avoid races with the write page
-+ * extending the file. This also will cause the server to possibly update the
-+ * server side file's mod time too. For those situations we do not want to blindly
-+ * go and invalidate the inode pages thus losing changes in flight and corrupting the
-+ * file.
-+ * We only need to invalidate the inode pages if the file has truly been modified
-+ * on the server side by another server side application, not by our writes.
-+ * If there are no writers it is safe to assume that newer mod time means the file
-+ * changed on the server side underneath us.
-+ */
-+ isSafeToChange = HgfsIsSafeToChange(inode);
-+
-+ spin_lock(&inode->i_lock);
-+
-+ iinfo = INODE_GET_II_P(inode);
-
- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: entered\n"));
- HgfsSetFileType(inode, attr);
-@@ -742,21 +982,23 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
-
- /*
- * Invalidate cached pages if we didn't receive the file size, or if it has
-- * changed on the server.
-+ * changed on the server, and no writes in flight.
- */
- if (attr->mask & HGFS_ATTR_VALID_SIZE) {
- loff_t oldSize = compat_i_size_read(inode);
- inode->i_blocks = (attr->size + HGFS_BLOCKSIZE - 1) / HGFS_BLOCKSIZE;
- if (oldSize != attr->size) {
-- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: new file "
-- "size: %"FMT64"u, old file size: %Lu\n", attr->size, oldSize));
-- needInvalidate = TRUE;
-+ if (oldSize < attr->size || (iinfo->numWbPages == 0 && isSafeToChange)) {
-+ needInvalidate = TRUE;
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: new file "
-+ "size: %"FMT64"u, old file size: %Lu\n", attr->size, oldSize));
-+ inode->i_blocks = HgfsCalcBlockSize(attr->size);
-+ compat_i_size_write(inode, attr->size);
-+ }
- }
-- compat_i_size_write(inode, attr->size);
- } else {
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: did not "
- "get file size\n"));
-- needInvalidate = TRUE;
- }
-
- if (attr->mask & HGFS_ATTR_VALID_ACCESS_TIME) {
-@@ -767,12 +1009,15 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
-
- /*
- * Invalidate cached pages if we didn't receive the modification time, or if
-- * it has changed on the server.
-+ * it has changed on the server and we don't have writes in flight and any open
-+ * open writers.
- */
- if (attr->mask & HGFS_ATTR_VALID_WRITE_TIME) {
- HGFS_DECLARE_TIME(newTime);
- HGFS_SET_TIME(newTime, attr->writeTime);
-- if (!HGFS_EQUAL_TIME(newTime, inode->i_mtime)) {
-+ if (hgfs_timespec_compare(&newTime, &inode->i_mtime) > 0 &&
-+ iinfo->numWbPages == 0 &&
-+ isSafeToChange) {
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: new mod "
- "time: %ld:%lu, old mod time: %ld:%lu\n",
- HGFS_PRINT_TIME(newTime), HGFS_PRINT_TIME(inode->i_mtime)));
-@@ -780,7 +1025,6 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
- }
- HGFS_SET_TIME(inode->i_mtime, attr->writeTime);
- } else {
-- needInvalidate = TRUE;
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsChangeFileAttributes: did not "
- "get mod time\n"));
- HGFS_SET_TIME(inode->i_mtime, HGFS_GET_CURRENT_TIME());
-@@ -798,6 +1042,8 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
- HGFS_SET_TIME(inode->i_ctime, HGFS_GET_CURRENT_TIME());
- }
-
-+ spin_unlock(&inode->i_lock);
-+
- /*
- * Compare old size and write time with new size and write time. If there's
- * a difference (or if we didn't get a new size or write time), the file
-@@ -815,17 +1061,14 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
- /*
- *----------------------------------------------------------------------
- *
-- * HgfsPrivateGetattr --
-+ * HgfsCanRetryGetattrRequest --
- *
-- * Internal getattr routine. Send a getattr request to the server
-- * for the indicated remote name, and if it succeeds copy the
-- * results of the getattr into the provided HgfsAttrInfo.
-- *
-- * fileName (if supplied) will be set to a newly allocated string
-- * if the file is a symlink; it's the caller's duty to free it.
-+ * Checks the getattr request version and downgrades the global getattr
-+ * version if we can.
- *
- * Results:
-- * Returns zero on success, or a negative error on failure.
-+ * Returns TRUE on success and downgrades the global getattr protocol version,
-+ * or FALSE if no retry is possible.
- *
- * Side effects:
- * None
-@@ -833,44 +1076,63 @@ HgfsChangeFileAttributes(struct inode *inode, // IN/OUT: Inode
- *----------------------------------------------------------------------
- */
-
--int
--HgfsPrivateGetattr(struct dentry *dentry, // IN: Dentry containing name
-- HgfsAttrInfo *attr, // OUT: Attr to copy into
-- char **fileName) // OUT: pointer to allocated file name
-+static Bool
-+HgfsCanRetryGetattrRequest(HgfsOp getattrOp) // IN: getattrOp version used
- {
-- HgfsReq *req;
-- HgfsStatus replyStatus;
-- HgfsOp opUsed;
-- int result = 0;
-- Bool allowHandleReuse = TRUE;
-+ Bool canRetry = FALSE;
-+
-+ /* Retry with older version(s). Set globally. */
-+ if (getattrOp == HGFS_OP_GETATTR_V3) {
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsCanRetryGetattrRequest: Version 3 "
-+ "not supported. Falling back to version 2.\n"));
-+ hgfsVersionGetattr = HGFS_OP_GETATTR_V2;
-+ canRetry = TRUE;
-+ } else if (getattrOp == HGFS_OP_GETATTR_V2) {
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsCanRetryGetattrRequest: Version 2 "
-+ "not supported. Falling back to version 1.\n"));
-+ hgfsVersionGetattr = HGFS_OP_GETATTR;
-+ canRetry = TRUE;
-+ }
-+ return canRetry;
-+}
-
-- ASSERT(dentry);
-- ASSERT(dentry->d_sb);
-- ASSERT(attr);
-
-- req = HgfsGetNewRequest();
-- if (!req) {
-- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: out of memory "
-- "while getting new request\n"));
-- result = -ENOMEM;
-- goto out;
-- }
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsSendGetattrRequest --
-+ *
-+ * Send the getattr request and handle the reply.
-+ *
-+ * Results:
-+ * Returns zero on success, or a negative error on failure.
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-
-- retry:
-+int
-+HgfsSendGetattrRequest(HgfsReq *req, // IN: getattr request
-+ Bool *doRetry, // OUT: Retry getattr request
-+ Bool *allowHandleReuse, // IN/OUT: handle reuse
-+ HgfsAttrInfo *attr, // OUT: Attr to copy into
-+ char **fileName) // OUT: pointer to allocated file name
-+{
-+ int result;
-
-- opUsed = hgfsVersionGetattr;
-- result = HgfsPackGetattrRequest(req, dentry, allowHandleReuse, opUsed, attr);
-- if (result != 0) {
-- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: no attrs\n"));
-- goto out;
-- }
-+ *doRetry = FALSE;
-
- result = HgfsSendRequest(req);
- if (result == 0) {
-- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: got reply\n"));
-- replyStatus = HgfsReplyStatus(req);
-+ HgfsStatus replyStatus = HgfsReplyStatus(req);
-+
- result = HgfsStatusConvertToLinux(replyStatus);
-
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsSendGetattrRequest: reply status %d -> %d\n",
-+ replyStatus, result));
-+
- /*
- * If the getattr succeeded on the server, copy the stats
- * into the HgfsAttrInfo, otherwise return an error.
-@@ -889,7 +1151,7 @@ HgfsPrivateGetattr(struct dentry *dentry, // IN: Dentry containing name
- * and it doesn't display any valid shares too. So as a workaround, we
- * remap EIO to success and create minimal fake attributes.
- */
-- LOG(1, (KERN_DEBUG "Hgfs:Server returned EIO on unknown file\n"));
-+ LOG(1, (KERN_DEBUG "Hgfs: HgfsSetInodeUidGid: Server returned EIO on unknown file\n"));
- /* Create fake attributes */
- attr->mask = HGFS_ATTR_VALID_TYPE | HGFS_ATTR_VALID_SIZE;
- attr->type = HGFS_FILE_TYPE_DIRECTORY;
-@@ -906,9 +1168,9 @@ HgfsPrivateGetattr(struct dentry *dentry, // IN: Dentry containing name
- * "goto retry" would cause an infinite loop. Instead, let's retry
- * with a getattr by name.
- */
-- if (allowHandleReuse) {
-- allowHandleReuse = FALSE;
-- goto retry;
-+ if (*allowHandleReuse) {
-+ *allowHandleReuse = FALSE;
-+ *doRetry = TRUE;
- }
-
- /*
-@@ -920,19 +1182,11 @@ HgfsPrivateGetattr(struct dentry *dentry, // IN: Dentry containing name
-
- case -EPROTO:
- /* Retry with older version(s). Set globally. */
-- if (attr->requestType == HGFS_OP_GETATTR_V3) {
-- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: Version 3 "
-- "not supported. Falling back to version 2.\n"));
-- hgfsVersionGetattr = HGFS_OP_GETATTR_V2;
-- goto retry;
-- } else if (attr->requestType == HGFS_OP_GETATTR_V2) {
-- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: Version 2 "
-- "not supported. Falling back to version 1.\n"));
-- hgfsVersionGetattr = HGFS_OP_GETATTR;
-- goto retry;
-+ if (HgfsCanRetryGetattrRequest(attr->requestType)) {
-+ *doRetry = TRUE;
- }
-+ break;
-
-- /* Fallthrough. */
- default:
- break;
- }
-@@ -942,8 +1196,129 @@ HgfsPrivateGetattr(struct dentry *dentry, // IN: Dentry containing name
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: server "
- "returned error: %d\n", result));
- } else {
-- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: unknown error: "
-- "%d\n", result));
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsSendGetattrRequest: unknown error: %d\n",
-+ result));
-+ }
-+
-+ return result;
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsPrivateGetattrRoot --
-+ *
-+ * The getattr for the root. Send a getattr request to the server
-+ * for the indicated remote name, and if it succeeds copy the
-+ * results of the getattr into the provided HgfsAttrInfo.
-+ *
-+ * fileName (of the root) will be set to a newly allocated string.
-+ *
-+ * Results:
-+ * Returns zero on success, or a negative error on failure.
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+int
-+HgfsPrivateGetattrRoot(struct super_block *sb, // IN: Super block object
-+ HgfsAttrInfo *attr) // OUT: Attr to copy into
-+{
-+ HgfsReq *req;
-+ HgfsOp opUsed;
-+ int result = 0;
-+ Bool doRetry;
-+ Bool allowHandleReuse = FALSE;
-+
-+ ASSERT(sb);
-+ ASSERT(attr);
-+
-+ req = HgfsGetNewRequest();
-+ if (!req) {
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattrRoot: out of memory "
-+ "while getting new request\n"));
-+ result = -ENOMEM;
-+ goto out;
-+ }
-+
-+retry:
-+ opUsed = hgfsVersionGetattr;
-+ result = HgfsPackGetattrRootRequest(req, opUsed, sb, attr);
-+ if (result != 0) {
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattrRoot: no attrs\n"));
-+ goto out;
-+ }
-+
-+ result = HgfsSendGetattrRequest(req, &doRetry, &allowHandleReuse, attr, NULL);
-+ if (0 != result && doRetry) {
-+ goto retry;
-+ }
-+
-+out:
-+ HgfsFreeRequest(req);
-+ return result;
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsPrivateGetattr --
-+ *
-+ * Internal getattr routine. Send a getattr request to the server
-+ * for the indicated remote name, and if it succeeds copy the
-+ * results of the getattr into the provided HgfsAttrInfo.
-+ *
-+ * fileName (if supplied) will be set to a newly allocated string
-+ * if the file is a symlink; it's the caller's duty to free it.
-+ *
-+ * Results:
-+ * Returns zero on success, or a negative error on failure.
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+int
-+HgfsPrivateGetattr(struct dentry *dentry, // IN: Dentry containing name
-+ HgfsAttrInfo *attr, // OUT: Attr to copy into
-+ char **fileName) // OUT: pointer to allocated file name
-+{
-+ HgfsReq *req;
-+ HgfsOp opUsed;
-+ int result = 0;
-+ Bool doRetry;
-+ Bool allowHandleReuse = TRUE;
-+
-+ ASSERT(dentry);
-+ ASSERT(dentry->d_sb);
-+ ASSERT(attr);
-+
-+ req = HgfsGetNewRequest();
-+ if (!req) {
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: out of memory "
-+ "while getting new request\n"));
-+ result = -ENOMEM;
-+ goto out;
-+ }
-+
-+retry:
-+ opUsed = hgfsVersionGetattr;
-+ result = HgfsPackGetattrRequest(req, opUsed, allowHandleReuse, dentry, attr);
-+ if (result != 0) {
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateGetattr: no attrs\n"));
-+ goto out;
-+ }
-+
-+ result = HgfsSendGetattrRequest(req, &doRetry, &allowHandleReuse, attr, fileName);
-+ if (0 != result && doRetry) {
-+ goto retry;
- }
-
- out:
-@@ -1099,6 +1474,106 @@ HgfsIget(struct super_block *sb, // IN: Superblock of this fs
- /*
- *-----------------------------------------------------------------------------
- *
-+ * HgfsInstantiateRoot --
-+ *
-+ * Gets the root dentry for a given super block.
-+ *
-+ * Results:
-+ * zero and a valid root dentry on success
-+ * negative value on failure
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *-----------------------------------------------------------------------------
-+ */
-+
-+int
-+HgfsInstantiateRoot(struct super_block *sb, // IN: Super block object
-+ struct dentry **rootDentry) // OUT: Root dentry
-+{
-+ int result = -ENOMEM;
-+ struct inode *rootInode;
-+ struct dentry *tempRootDentry = NULL;
-+ struct HgfsAttrInfo rootDentryAttr;
-+ HgfsInodeInfo *iinfo;
-+
-+ ASSERT(sb);
-+ ASSERT(rootDentry);
-+
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsInstantiateRoot: entered\n"));
-+
-+ rootInode = HgfsGetInode(sb, HGFS_ROOT_INO);
-+ if (rootInode == NULL) {
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsInstantiateRoot: Could not get the root inode\n"));
-+ goto exit;
-+ }
-+
-+ /*
-+ * On an allocation failure in read_super, the inode will have been
-+ * marked "bad". If it was, we certainly don't want to start playing with
-+ * the HgfsInodeInfo. So quietly put the inode back and fail.
-+ */
-+ if (is_bad_inode(rootInode)) {
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsInstantiateRoot: encountered bad inode\n"));
-+ goto exit;
-+ }
-+
-+ LOG(8, (KERN_DEBUG "VMware hgfs: HgfsInstantiateRoot: retrieve root attrs\n"));
-+ result = HgfsPrivateGetattrRoot(sb, &rootDentryAttr);
-+ if (result) {
-+ LOG(4, (KERN_WARNING "VMware hgfs: HgfsInstantiateRoot: Could not the root attrs\n"));
-+ goto exit;
-+ }
-+
-+ iinfo = INODE_GET_II_P(rootInode);
-+ iinfo->isFakeInodeNumber = FALSE;
-+ iinfo->isReferencedInode = TRUE;
-+
-+ if (rootDentryAttr.mask & HGFS_ATTR_VALID_FILEID) {
-+ iinfo->hostFileId = rootDentryAttr.hostFileId;
-+ }
-+
-+ HgfsChangeFileAttributes(rootInode, &rootDentryAttr);
-+
-+ /*
-+ * Now the initialization of the inode is complete we can create
-+ * the root dentry which has flags initialized from the inode itself.
-+ */
-+ tempRootDentry = d_make_root(rootInode);
-+ /*
-+ * d_make_root() does iput() on failure; if d_make_root() completes
-+ * successfully then subsequent dput() will do iput() for us, so we
-+ * should just ignore root inode from now on.
-+ */
-+ rootInode = NULL;
-+
-+ if (tempRootDentry == NULL) {
-+ LOG(4, (KERN_WARNING "VMware hgfs: HgfsInstantiateRoot: Could not get "
-+ "root dentry\n"));
-+ goto exit;
-+ }
-+
-+ HgfsDentryAgeReset(tempRootDentry);
-+ tempRootDentry->d_op = &HgfsDentryOperations;
-+
-+ *rootDentry = tempRootDentry;
-+ result = 0;
-+
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsInstantiateRoot: finished\n"));
-+exit:
-+ if (result) {
-+ iput(rootInode);
-+ dput(tempRootDentry);
-+ *rootDentry = NULL;
-+ }
-+ return result;
-+}
-+
-+
-+/*
-+ *-----------------------------------------------------------------------------
-+ *
- * HgfsInstantiate --
- *
- * Tie a dentry to a looked up or created inode. Callers may choose to
-@@ -1163,6 +1638,45 @@ HgfsInstantiate(struct dentry *dentry, // IN: Dentry to use
- /*
- *-----------------------------------------------------------------------------
- *
-+ * HgfsBuildRootPath --
-+ *
-+ * Constructs the root path given the super info.
-+ *
-+ * Results:
-+ * If non-negative, the length of the buffer written.
-+ * Otherwise, an error code.
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *-----------------------------------------------------------------------------
-+ */
-+
-+int
-+HgfsBuildRootPath(char *buffer, // IN/OUT: Buffer to write into
-+ size_t bufferLen, // IN: Size of buffer
-+ HgfsSuperInfo *si) // IN: First dentry to walk
-+{
-+ size_t shortestNameLength;
-+ /*
-+ * Buffer must hold at least the share name (which is already prefixed with
-+ * a forward slash), and nul.
-+ */
-+ shortestNameLength = si->shareNameLen + 1;
-+ if (bufferLen < shortestNameLength) {
-+ return -ENAMETOOLONG;
-+ }
-+ memcpy(buffer, si->shareName, shortestNameLength);
-+
-+ /* Short-circuit if we're at the root already. */
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsBuildRootPath: root path \"%s\"\n", buffer));
-+ return shortestNameLength;
-+}
-+
-+
-+/*
-+ *-----------------------------------------------------------------------------
-+ *
- * HgfsBuildPath --
- *
- * Constructs the full path given a dentry by walking the dentry and its
-@@ -1184,7 +1698,7 @@ HgfsBuildPath(char *buffer, // IN/OUT: Buffer to write into
- size_t bufferLen, // IN: Size of buffer
- struct dentry *dentry) // IN: First dentry to walk
- {
-- int retval = 0;
-+ int retval;
- size_t shortestNameLength;
- HgfsSuperInfo *si;
-
-@@ -1194,26 +1708,23 @@ HgfsBuildPath(char *buffer, // IN/OUT: Buffer to write into
-
- si = HGFS_SB_TO_COMMON(dentry->d_sb);
-
-- /*
-- * Buffer must hold at least the share name (which is already prefixed with
-- * a forward slash), and nul.
-- */
-- shortestNameLength = si->shareNameLen + 1;
-- if (bufferLen < shortestNameLength) {
-- return -ENAMETOOLONG;
-+ retval = HgfsBuildRootPath(buffer, bufferLen, si);
-+ if (0 > retval) {
-+ return retval;
- }
-- memcpy(buffer, si->shareName, shortestNameLength);
-
- /* Short-circuit if we're at the root already. */
- if (IS_ROOT(dentry)) {
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsBuildPath: Sending root \"%s\"\n",
- buffer));
-- return shortestNameLength;
-+ return retval;
- }
-
- /* Skip the share name, but overwrite our previous nul. */
-+ shortestNameLength = retval;
- buffer += shortestNameLength - 1;
- bufferLen -= shortestNameLength - 1;
-+ retval = 0;
-
- /*
- * Build the path string walking the tree backward from end to ROOT
-@@ -1230,8 +1741,8 @@ HgfsBuildPath(char *buffer, // IN/OUT: Buffer to write into
- if (bufferLen < 0) {
- compat_unlock_dentry(dentry);
- dput(dentry);
-- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsBuildPath: Ran out of space "
-- "while writing dentry name\n"));
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsBuildPath: Ran out of space "
-+ "while writing dentry name\n"));
- return -ENAMETOOLONG;
- }
- buffer[bufferLen] = '/';
-@@ -1305,7 +1816,7 @@ HgfsDentryAgeReset(struct dentry *dentry) // IN: Dentry whose age to reset
- /*
- *-----------------------------------------------------------------------------
- *
-- * HgfsDentryAgeReset --
-+ * HgfsDentryAgeForce --
- *
- * Set the dentry's time to 0. This makes the dentry's age "too old" and
- * forces subsequent HgfsRevalidates to go to the server for attributes.
-@@ -1808,5 +2319,7 @@ HgfsDoReadInode(struct inode *inode) // IN: Inode to initialize
- iinfo->isReferencedInode = FALSE;
- iinfo->isFakeInodeNumber = FALSE;
- iinfo->createdAndUnopened = FALSE;
-+ iinfo->numWbPages = 0;
-+ INIT_LIST_HEAD(&iinfo->listWbPages);
-
- }
-diff --git a/open-vm-tools/modules/linux/vmhgfs/fsutil.h b/open-vm-tools/modules/linux/vmhgfs/fsutil.h
-index 2767099..6cfc71a 100644
---- a/modules/linux/vmhgfs/fsutil.h
-+++ b/modules/linux/vmhgfs/fsutil.h
-@@ -74,6 +74,8 @@ int HgfsPrivateGetattr(struct dentry *dentry,
- struct inode *HgfsIget(struct super_block *sb,
- ino_t ino,
- HgfsAttrInfo const *attr);
-+int HgfsInstantiateRoot(struct super_block *sb,
-+ struct dentry **rootDentry);
- int HgfsInstantiate(struct dentry *dentry,
- ino_t ino,
- HgfsAttrInfo const *attr);
-diff --git a/open-vm-tools/modules/linux/vmhgfs/inode.c b/open-vm-tools/modules/linux/vmhgfs/inode.c
-index caaa41a..93e28bf 100644
---- a/modules/linux/vmhgfs/inode.c
-+++ b/modules/linux/vmhgfs/inode.c
-@@ -159,6 +159,38 @@ struct inode_operations HgfsFileInodeOperations = {
- * Private functions implementations.
- */
-
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsClearReadOnly --
-+ *
-+ * Try to remove the file/dir read only attribute.
-+ *
-+ * Note when running on Windows servers the entry may have the read-only
-+ * flag set and prevent a rename or delete operation from occuring.
-+ *
-+ * Results:
-+ * Returns zero on success, or a negative error on failure.
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static int
-+HgfsClearReadOnly(struct dentry *dentry) // IN: file/dir to remove read only
-+{
-+ struct iattr enableWrite;
-+
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsClearReadOnly: removing read-only\n"));
-+ enableWrite.ia_mode = (dentry->d_inode->i_mode | S_IWUSR);
-+ enableWrite.ia_valid = ATTR_MODE;
-+ return HgfsSetattr(dentry, &enableWrite);
-+}
-+
-+
- /*
- *----------------------------------------------------------------------
- *
-@@ -309,14 +341,8 @@ HgfsDelete(struct inode *dir, // IN: Parent dir of file/dir to delete
- * safe?
- */
- if (!secondAttempt) {
-- struct iattr enableWrite;
- secondAttempt = TRUE;
--
-- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDelete: access denied, "
-- "attempting to work around read-only bit\n"));
-- enableWrite.ia_mode = (dentry->d_inode->i_mode | S_IWUSR);
-- enableWrite.ia_valid = ATTR_MODE;
-- result = HgfsSetattr(dentry, &enableWrite);
-+ result = HgfsClearReadOnly(dentry);
- if (result == 0) {
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDelete: file is no "
- "longer read-only, retrying delete\n"));
-@@ -1336,6 +1362,7 @@ HgfsRename(struct inode *oldDir, // IN: Inode of original directory
- HgfsReq *req = NULL;
- char *oldName;
- char *newName;
-+ Bool secondAttempt=FALSE;
- uint32 *oldNameLength;
- uint32 *newNameLength;
- int result = 0;
-@@ -1500,6 +1527,31 @@ retry:
- "returned error: %d\n", result));
- goto out;
- }
-+ } else if ((-EACCES == result) || (-EPERM == result)) {
-+ /*
-+ * It's possible that we're talking to a Windows server with
-+ * a file marked read-only. Let's try again, after removing
-+ * the read-only bit from the file.
-+ *
-+ * XXX: I think old servers will send -EPERM here. Is this entirely
-+ * safe?
-+ */
-+ if (!secondAttempt) {
-+ secondAttempt = TRUE;
-+ result = HgfsClearReadOnly(newDentry);
-+ if (result == 0) {
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRename: file is no "
-+ "longer read-only, retrying rename\n"));
-+ goto retry;
-+ }
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRename: failed to remove "
-+ "read-only property\n"));
-+ } else {
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRename: second attempt at "
-+ "rename failed\n"));
-+ }
-+ } else if (0 != result) {
-+ LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRename: failed with result %d\n", result));
- }
- } else if (result == -EIO) {
- LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRename: timed out\n"));
-diff --git a/open-vm-tools/modules/linux/vmhgfs/link.c b/open-vm-tools/modules/linux/vmhgfs/link.c
-index 06ea953..9140f4e 100644
---- a/modules/linux/vmhgfs/link.c
-+++ b/modules/linux/vmhgfs/link.c
-@@ -45,11 +45,20 @@ static int HgfsFollowlink(struct dentry *dentry,
- static int HgfsReadlink(struct dentry *dentry,
- char __user *buffer,
- int buflen);
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+static void HgfsPutlink(struct dentry *dentry,
-+ struct nameidata *nd,
-+ void *cookie);
-+#else
-+static void HgfsPutlink(struct dentry *dentry,
-+ struct nameidata *nd);
-+#endif
-
- /* HGFS inode operations structure for symlinks. */
- struct inode_operations HgfsLinkInodeOperations = {
- .follow_link = HgfsFollowlink,
- .readlink = HgfsReadlink,
-+ .put_link = HgfsPutlink,
- };
-
- /*
-@@ -109,6 +118,7 @@ HgfsFollowlink(struct dentry *dentry, // IN: Dentry containing link
- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: got called "
- "on something that wasn't a symlink\n"));
- error = -EINVAL;
-+ kfree(fileName);
- } else {
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: calling "
-@@ -120,7 +130,6 @@ HgfsFollowlink(struct dentry *dentry, // IN: Dentry containing link
- error = vfs_follow_link(nd, fileName);
- #endif
- }
-- kfree(fileName);
- }
- out:
-
-@@ -181,9 +190,6 @@ HgfsReadlink(struct dentry *dentry, // IN: Dentry containing link
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsReadlink: calling "
- "readlink_copy\n"));
-- LOG(6, (KERN_DEBUG "VMware hgfs: %s: calling "
-- "readlink_copy\n",
-- __func__));
- error = readlink_copy(buffer, buflen, fileName);
- #else
- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsReadlink: calling "
-@@ -195,3 +201,46 @@ HgfsReadlink(struct dentry *dentry, // IN: Dentry containing link
- }
- return error;
- }
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsPutlink --
-+ *
-+ * Modeled after page_put_link from a 2.6.9 kernel so it'll work
-+ * across all kernel revisions we care about.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+static void
-+HgfsPutlink(struct dentry *dentry, // dentry
-+ struct nameidata *nd, // lookup name information
-+ void *cookie) // cookie
-+#else
-+static void
-+HgfsPutlink(struct dentry *dentry, // dentry
-+ struct nameidata *nd) // lookup name information
-+#endif
-+{
-+ char *fileName = NULL;
-+
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsPutlink: put for %s\n",
-+ dentry->d_name.name));
-+
-+ fileName = nd_get_link(nd);
-+ if (!IS_ERR(fileName)) {
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsPutlink: putting %s\n",
-+ fileName));
-+ kfree(fileName);
-+ nd_set_link(nd, NULL);
-+ }
-+}
-diff --git a/open-vm-tools/modules/linux/vmhgfs/module.h b/open-vm-tools/modules/linux/vmhgfs/module.h
-index b6bcd1e..0c0a842 100644
---- a/modules/linux/vmhgfs/module.h
-+++ b/modules/linux/vmhgfs/module.h
-@@ -147,6 +147,13 @@ typedef struct HgfsInodeInfo {
- /* Is this a fake inode created in HgfsCreate that has yet to be opened? */
- Bool createdAndUnopened;
-
-+ /*
-+ * The number of write back pages to the file which is tracked so any
-+ * concurrent file validations such as reads will not invalidate the cache.
-+ */
-+ unsigned long numWbPages;
-+ struct list_head listWbPages;
-+
- /* Is this inode referenced by HGFS? (needed by HgfsInodeLookup()) */
- Bool isReferencedInode;
-
-diff --git a/open-vm-tools/modules/linux/vmhgfs/page.c b/open-vm-tools/modules/linux/vmhgfs/page.c
-index 6d8b50f..cf3b8c9 100644
---- a/modules/linux/vmhgfs/page.c
-+++ b/modules/linux/vmhgfs/page.c
-@@ -1,5 +1,5 @@
- /*********************************************************
-- * Copyright (C) 2006 VMware, Inc. All rights reserved.
-+ * Copyright (C) 2006-2014 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
-@@ -64,15 +64,18 @@ static int HgfsDoWritepage(HgfsHandle handle,
- struct page *page,
- unsigned pageFrom,
- unsigned pageTo);
--static void HgfsDoWriteBegin(struct page *page,
-- unsigned pageFrom,
-- unsigned pageTo);
-+static int HgfsDoWriteBegin(struct file *file,
-+ struct page *page,
-+ unsigned pageFrom,
-+ unsigned pageTo);
- static int HgfsDoWriteEnd(struct file *file,
- struct page *page,
- unsigned pageFrom,
- unsigned pageTo,
- loff_t writeTo,
- unsigned copied);
-+static void HgfsDoExtendFile(struct inode *inode,
-+ loff_t writeTo);
-
- /* HGFS address space operations. */
- static int HgfsReadpage(struct file *file,
-@@ -128,6 +131,27 @@ struct address_space_operations HgfsAddressSpaceOperations = {
- .set_page_dirty = __set_page_dirty_nobuffers,
- };
-
-+enum {
-+ PG_BUSY = 0,
-+};
-+
-+typedef struct HgfsWbPage {
-+ struct list_head wb_list; /* Defines state of page: */
-+ struct page *wb_page; /* page to read in/write out */
-+ pgoff_t wb_index; /* Offset >> PAGE_CACHE_SHIFT */
-+ struct kref wb_kref; /* reference count */
-+ unsigned long wb_flags;
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
-+ wait_queue_head_t wb_queue;
-+#endif
-+} HgfsWbPage;
-+
-+static void HgfsInodePageWbAdd(struct inode *inode,
-+ struct page *page);
-+static void HgfsInodePageWbRemove(struct inode *inode,
-+ struct page *page);
-+static void HgfsWbRequestDestroy(HgfsWbPage *req);
-+
-
- /*
- * Private functions.
-@@ -690,11 +714,11 @@ HgfsDoWritepage(HgfsHandle handle, // IN: Handle to use for writing
- pageFrom += result;
-
- /* Update the inode's size now rather than waiting for a revalidate. */
-- if (curOffset > compat_i_size_read(inode)) {
-- compat_i_size_write(inode, curOffset);
-- }
-+ HgfsDoExtendFile(inode, curOffset);
- } while ((result > 0) && (remainingCount > 0));
-
-+ HgfsInodePageWbRemove(inode, page);
-+
- result = 0;
-
- out:
-@@ -866,7 +890,7 @@ HgfsWritepage(struct page *page, // IN: Page to write from
- * Initialize the page if the file is to be appended.
- *
- * Results:
-- * None.
-+ * Zero on success, always.
- *
- * Side effects:
- * None.
-@@ -874,37 +898,35 @@ HgfsWritepage(struct page *page, // IN: Page to write from
- *-----------------------------------------------------------------------------
- */
-
--static void
--HgfsDoWriteBegin(struct page *page, // IN: Page to be written
-+static int
-+HgfsDoWriteBegin(struct file *file, // IN: File to be written
-+ struct page *page, // IN: Page to be written
- unsigned pageFrom, // IN: Starting page offset
- unsigned pageTo) // IN: Ending page offset
- {
-- loff_t offset;
-- loff_t currentFileSize;
--
- ASSERT(page);
-
-- offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
-- currentFileSize = compat_i_size_read(page->mapping->host);
-
-- /*
-- * If we are doing a partial write into a new page (beyond end of
-- * file), then intialize it. This allows other writes to this page
-- * to accumulate before we need to write it to the server.
-- */
-- if ((offset >= currentFileSize) ||
-- ((pageFrom == 0) && (offset + pageTo) >= currentFileSize)) {
-- void *kaddr = compat_kmap_atomic(page);
--
-- if (pageFrom) {
-+ if (!PageUptodate(page)) {
-+ /*
-+ * If we are doing a partial write into a new page (beyond end of
-+ * file), then intialize it. This allows other writes to this page
-+ * to accumulate before we need to write it to the server.
-+ */
-+ if (pageTo - pageFrom != PAGE_CACHE_SIZE) {
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
-+ zero_user_segments(page, 0, pageFrom, pageTo, PAGE_CACHE_SIZE);
-+#else
-+ void *kaddr = compat_kmap_atomic(page);
- memset(kaddr, 0, pageFrom);
-- }
-- if (pageTo < PAGE_CACHE_SIZE) {
- memset(kaddr + pageTo, 0, PAGE_CACHE_SIZE - pageTo);
-+ flush_dcache_page(page);
-+ compat_kunmap_atomic(kaddr);
-+#endif
- }
-- compat_kunmap_atomic(kaddr);
-- flush_dcache_page(page);
- }
-+
-+ return 0;
- }
-
-
-@@ -919,7 +941,7 @@ HgfsDoWriteBegin(struct page *page, // IN: Page to be written
- * receiving the write.
- *
- * Results:
-- * Always zero.
-+ * On success zero, always.
- *
- * Side effects:
- * None.
-@@ -928,14 +950,12 @@ HgfsDoWriteBegin(struct page *page, // IN: Page to be written
- */
-
- static int
--HgfsPrepareWrite(struct file *file, // IN: Ignored
-+HgfsPrepareWrite(struct file *file, // IN: File to be written
- struct page *page, // IN: Page to prepare
- unsigned pageFrom, // IN: Beginning page offset
- unsigned pageTo) // IN: Ending page offset
- {
-- HgfsDoWriteBegin(page, pageFrom, pageTo);
--
-- return 0;
-+ return HgfsDoWriteBegin(file, page, pageFrom, pageTo);
- }
-
- #else
-@@ -971,18 +991,29 @@ HgfsWriteBegin(struct file *file, // IN: File to be written
- void **clientData) // OUT: Opaque to pass to write_end, unused
- {
- pgoff_t index = pos >> PAGE_CACHE_SHIFT;
-- unsigned pageFrom = pos & (PAGE_CACHE_SHIFT - 1);
-- unsigned pageTo = pos + len;
-+ unsigned pageFrom = pos & (PAGE_CACHE_SIZE - 1);
-+ unsigned pageTo = pageFrom + len;
- struct page *page;
-+ int result;
-
- page = compat_grab_cache_page_write_begin(mapping, index, flags);
- if (page == NULL) {
-- return -ENOMEM;
-+ result = -ENOMEM;
-+ goto exit;
- }
- *pagePtr = page;
-
-- HgfsDoWriteBegin(page, pageFrom, pageTo);
-- return 0;
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsWriteBegin: file size %Lu @ %Lu page %u to %u\n",
-+ (loff_t)compat_i_size_read(page->mapping->host),
-+ (loff_t)page->index << PAGE_CACHE_SHIFT,
-+ pageFrom, pageTo));
-+
-+ result = HgfsDoWriteBegin(file, page, pageFrom, pageTo);
-+ ASSERT(result == 0);
-+
-+exit:
-+ LOG(6, (KERN_DEBUG "VMware hgfs: HgfsWriteBegin: return %d\n", result));
-+ return result;
- }
- #endif
-
-@@ -990,6 +1021,40 @@ HgfsWriteBegin(struct file *file, // IN: File to be written
- /*
- *-----------------------------------------------------------------------------
- *
-+ * HgfsDoExtendFile --
-+ *
-+ * Helper function for extending a file size.
-+ *
-+ * This function updates the inode->i_size, under the inode lock.
-+ *
-+ * Results:
-+ * None.
-+ *
-+ * Side effects:
-+ * None.
-+ *
-+ *-----------------------------------------------------------------------------
-+ */
-+
-+static void
-+HgfsDoExtendFile(struct inode *inode, // IN: File we're writing to
-+ loff_t writeTo) // IN: Offset we're written to
-+{
-+ loff_t currentFileSize;
-+
-+ spin_lock(&inode->i_lock);
-+ currentFileSize = compat_i_size_read(inode);
-+
-+ if (writeTo > currentFileSize) {
-+ compat_i_size_write(inode, writeTo);
-+ }
-+ spin_unlock(&inode->i_lock);
-+}
-+
-+
-+/*
-+ *-----------------------------------------------------------------------------
-+ *
- * HgfsDoWriteEnd --
- *
- * Helper function for HgfsWriteEnd.
-@@ -1014,54 +1079,31 @@ HgfsDoWriteEnd(struct file *file, // IN: File we're writing to
- loff_t writeTo, // IN: File position to write to
- unsigned copied) // IN: Number of bytes copied to the page
- {
-- HgfsHandle handle;
- struct inode *inode;
-- loff_t currentFileSize;
-- loff_t offset;
-
- ASSERT(file);
- ASSERT(page);
- inode = page->mapping->host;
-- currentFileSize = compat_i_size_read(inode);
-- offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
--
-- if (writeTo > currentFileSize) {
-- compat_i_size_write(inode, writeTo);
-- }
--
-- /* We wrote a complete page, so it is up to date. */
-- if (copied == PAGE_CACHE_SIZE) {
-- SetPageUptodate(page);
-- }
-
- /*
-- * Check if this is a partial write to a new page, which was
-- * initialized in HgfsDoWriteBegin.
-+ * Zero any uninitialised parts of the page, and then mark the page
-+ * as up to date if it turns out that we're extending the file.
- */
-- if ((offset >= currentFileSize) ||
-- ((pageFrom == 0) && (writeTo >= currentFileSize))) {
-+ if (!PageUptodate(page)) {
- SetPageUptodate(page);
- }
-
- /*
-- * If the page is uptodate, then just mark it dirty and let
-- * the page cache write it when it wants to.
-+ * Track the pages being written.
- */
-- if (PageUptodate(page)) {
-- set_page_dirty(page);
-- return 0;
-- }
-+ HgfsInodePageWbAdd(inode, page);
-
-- /*
-- * We've recieved a partial write to page that is not uptodate, so
-- * do the write now while the page is still locked. Another
-- * alternative would be to read the page in HgfsDoWriteBegin, which
-- * would make it uptodate (ie a complete cached page).
-- */
-- handle = FILE_GET_FI_P(file)->handle;
-- LOG(6, (KERN_WARNING "VMware hgfs: %s: writing to handle %u\n", __func__,
-- handle));
-- return HgfsDoWritepage(handle, page, pageFrom, pageTo);
-+ HgfsDoExtendFile(inode, writeTo);
-+
-+ set_page_dirty(page);
-+
-+ LOG(6, (KERN_WARNING "VMware hgfs: HgfsDoWriteEnd: return 0\n"));
-+ return 0;
- }
-
-
-@@ -1143,7 +1185,7 @@ HgfsWriteEnd(struct file *file, // IN: File to write
- void *clientData) // IN: From write_begin, unused.
- {
- unsigned pageFrom = pos & (PAGE_CACHE_SIZE - 1);
-- unsigned pageTo = pageFrom + copied;
-+ unsigned pageTo = pageFrom + len;
- loff_t writeTo = pos + copied;
- int ret;
-
-@@ -1151,6 +1193,10 @@ HgfsWriteEnd(struct file *file, // IN: File to write
- ASSERT(mapping);
- ASSERT(page);
-
-+ if (copied < len) {
-+ zero_user_segment(page, pageFrom + copied, pageFrom + len);
-+ }
-+
- ret = HgfsDoWriteEnd(file, page, pageFrom, pageTo, writeTo, copied);
- if (ret == 0) {
- ret = copied;
-@@ -1161,3 +1207,671 @@ HgfsWriteEnd(struct file *file, // IN: File to write
- return ret;
- }
- #endif
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbPageAlloc --
-+ *
-+ * Allocates a write-back page object.
-+ *
-+ * Results:
-+ * The write-back page object
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static inline HgfsWbPage *
-+HgfsWbPageAlloc(void)
-+{
-+ return kmalloc(sizeof (HgfsWbPage), GFP_KERNEL);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbPageAlloc --
-+ *
-+ * Frees a write-back page object.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+
-+static inline void
-+HgfsWbPageFree(HgfsWbPage *page) // IN: request of page data to write
-+{
-+ ASSERT(page);
-+ kfree(page);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbRequestFree --
-+ *
-+ * Frees the resources for a write-back page request.
-+ * Calls the request destroy and then frees the object memory.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static void
-+HgfsWbRequestFree(struct kref *kref) // IN: ref field request of page data to write
-+{
-+ HgfsWbPage *req = container_of(kref, HgfsWbPage, wb_kref);
-+
-+ /* Release write back request page and free it. */
-+ HgfsWbRequestDestroy(req);
-+ HgfsWbPageFree(req);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbRequestGet --
-+ *
-+ * Reference the write-back page request.
-+ * Calls the request destroy and then frees the object memory.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+void
-+HgfsWbRequestGet(HgfsWbPage *req) // IN: request of page data to write
-+{
-+ kref_get(&req->wb_kref);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbRequestPut --
-+ *
-+ * Remove a reference the write-back page request.
-+ * Calls the request free to tear down the object memory if it was the
-+ * final one.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * Destroys the request if last one.
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+void
-+HgfsWbRequestPut(HgfsWbPage *req) // IN: request of page data to write
-+{
-+ kref_put(&req->wb_kref, HgfsWbRequestFree);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbRequestWaitUninterruptible --
-+ *
-+ * Sleep function while waiting for requests to complete.
-+ *
-+ * Results:
-+ * Always zero.
-+ *
-+ * Side effects:
-+* None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+static int
-+HgfsWbRequestWaitUninterruptible(void *word) // IN:unused
-+{
-+ io_schedule();
-+ return 0;
-+}
-+#endif
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbRequestWait --
-+ *
-+ * Wait for a write-back page request to complete.
-+ * Interruptible by fatal signals only.
-+ * The user is responsible for holding a count on the request.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+
-+int
-+HgfsWbRequestWait(HgfsWbPage *req) // IN: request of page data to write
-+{
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+ return wait_on_bit(&req->wb_flags,
-+ PG_BUSY,
-+ HgfsWbRequestWaitUninterruptible,
-+ TASK_UNINTERRUPTIBLE);
-+#else
-+ wait_event(req->wb_queue,
-+ !test_bit(PG_BUSY, &req->wb_flags));
-+ return 0;
-+#endif
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbRequestLock --
-+ *
-+ * Lock the write-back page request.
-+ *
-+ * Results:
-+ * Non-zero if the lock was not already locked
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static inline int
-+HgfsWbRequestLock(HgfsWbPage *req) // IN: request of page data to write
-+{
-+ return !test_and_set_bit(PG_BUSY, &req->wb_flags);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbRequestUnlock --
-+ *
-+ * Unlock the write-back page request.
-+ * Wakes up any waiting threads on the lock.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static void
-+HgfsWbRequestUnlock(HgfsWbPage *req) // IN: request of page data to write
-+{
-+ if (!test_bit(PG_BUSY,&req->wb_flags)) {
-+ LOG(6, (KERN_WARNING "VMware Hgfs: HgfsWbRequestUnlock: Invalid unlock attempted\n"));
-+ return;
-+ }
-+ smp_mb__before_clear_bit();
-+ clear_bit(PG_BUSY, &req->wb_flags);
-+ smp_mb__after_clear_bit();
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+ wake_up_bit(&req->wb_flags, PG_BUSY);
-+#else
-+ wake_up(&req->wb_queue);
-+#endif
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbRequestUnlockAndPut --
-+ *
-+ * Unlock the write-back page request and removes a reference.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static void
-+HgfsWbRequestUnlockAndPut(HgfsWbPage *req) // IN: request of page data to write
-+{
-+ HgfsWbRequestUnlock(req);
-+ HgfsWbRequestPut(req);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbRequestListAdd --
-+ *
-+ * Add the write-back page request into the list.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static inline void
-+HgfsWbRequestListAdd(HgfsWbPage *req, // IN: request of page data to write
-+ struct list_head *head) // IN: list of requests
-+{
-+ list_add_tail(&req->wb_list, head);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbRequestListRemove --
-+ *
-+ * Remove the write-back page request from the list.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static inline void
-+HgfsWbRequestListRemove(HgfsWbPage *req) // IN: request of page data to write
-+{
-+ if (!list_empty(&req->wb_list)) {
-+ list_del_init(&req->wb_list);
-+ }
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbRequestCreate --
-+ *
-+ * Create the write-back page request.
-+ *
-+ * Results:
-+ * The new write-back page request.
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+HgfsWbPage *
-+HgfsWbRequestCreate(struct page *page) // IN: page of data to write
-+{
-+ HgfsWbPage *wbReq;
-+ /* try to allocate the request struct */
-+ wbReq = HgfsWbPageAlloc();
-+ if (wbReq == NULL) {
-+ wbReq = ERR_PTR(-ENOMEM);
-+ goto exit;
-+ }
-+
-+ /*
-+ * Initialize the request struct. Initially, we assume a
-+ * long write-back delay. This will be adjusted in
-+ * update_nfs_request below if the region is not locked.
-+ */
-+ wbReq->wb_flags = 0;
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
-+ init_waitqueue_head(&wbReq->wb_queue);
-+#endif
-+ INIT_LIST_HEAD(&wbReq->wb_list);
-+ wbReq->wb_page = page;
-+ wbReq->wb_index = page->index;
-+ page_cache_get(page);
-+ kref_init(&wbReq->wb_kref);
-+
-+exit:
-+ LOG(6, (KERN_WARNING "VMware hgfs: HgfsWbRequestCreate: (%p, %p)\n",
-+ wbReq, page));
-+ return wbReq;
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsWbRequestDestroy --
-+ *
-+ * Destroys by freeing up all resources allocated to the request.
-+ * Release page associated with a write-back request after it has completed.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static void
-+HgfsWbRequestDestroy(HgfsWbPage *req) // IN: write page request
-+{
-+ struct page *page = req->wb_page;
-+
-+ LOG(6, (KERN_WARNING"VMware hgfs: HgfsWbRequestDestroy: (%p, %p)\n",
-+ req, req->wb_page));
-+
-+ if (page != NULL) {
-+ page_cache_release(page);
-+ req->wb_page = NULL;
-+ }
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsInodeFindWbRequest --
-+ *
-+ * Finds if there is a write-back page request on this inode and returns it.
-+ *
-+ * Results:
-+ * NULL or the write-back request for the page.
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static HgfsWbPage *
-+HgfsInodeFindWbRequest(struct inode *inode, // IN: inode of file to write to
-+ struct page *page) // IN: page of data to write
-+{
-+ HgfsInodeInfo *iinfo;
-+ HgfsWbPage *req = NULL;
-+ HgfsWbPage *cur;
-+
-+ iinfo = INODE_GET_II_P(inode);
-+
-+ /* Linearly search the write back list for the correct req */
-+ list_for_each_entry(cur, &iinfo->listWbPages, wb_list) {
-+ if (cur->wb_page == page) {
-+ req = cur;
-+ break;
-+ }
-+ }
-+
-+ if (req != NULL) {
-+ HgfsWbRequestGet(req);
-+ }
-+
-+ return req;
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsInodeFindExistingWbRequest --
-+ *
-+ * Finds if there is a write-back page request on this inode and returns
-+ * locked.
-+ * If the request is busy (locked) then it drops the lock and waits for it
-+ * be not locked and searches the list again.
-+ *
-+ * Results:
-+ * NULL or the write-back request for the page.
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static HgfsWbPage *
-+HgfsInodeFindExistingWbRequest(struct inode *inode, // IN: inode of file to write to
-+ struct page *page) // IN: page of data to write
-+{
-+ HgfsWbPage *req;
-+ int error;
-+
-+ spin_lock(&inode->i_lock);
-+
-+ for (;;) {
-+ req = HgfsInodeFindWbRequest(inode, page);
-+ if (req == NULL) {
-+ goto out_exit;
-+ }
-+
-+ /*
-+ * Try and lock the request if not already locked.
-+ * If we find it is already locked, busy, then we drop
-+ * the reference and wait to try again. Otherwise,
-+ * once newly locked we break out and return to the caller.
-+ */
-+ if (HgfsWbRequestLock(req)) {
-+ break;
-+ }
-+
-+ /* The request was in use, so wait and then retry */
-+ spin_unlock(&inode->i_lock);
-+ error = HgfsWbRequestWait(req);
-+ HgfsWbRequestPut(req);
-+ if (error != 0) {
-+ goto out_nolock;
-+ }
-+
-+ spin_lock(&inode->i_lock);
-+ }
-+
-+out_exit:
-+ spin_unlock(&inode->i_lock);
-+ return req;
-+
-+out_nolock:
-+ return ERR_PTR(error);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsInodeAddWbRequest --
-+ *
-+ * Add a write-back page request to an inode.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static void
-+HgfsInodeAddWbRequest(struct inode *inode, // IN: inode of file to write to
-+ HgfsWbPage *req) // IN: page write request
-+{
-+ HgfsInodeInfo *iinfo = INODE_GET_II_P(inode);
-+
-+ LOG(6, (KERN_WARNING "VMware hgfs: HgfsInodeAddWbRequest: (%p, %p, %lu)\n",
-+ inode, req->wb_page, iinfo->numWbPages));
-+
-+ /* Lock the request! */
-+ HgfsWbRequestLock(req);
-+
-+ HgfsWbRequestListAdd(req, &iinfo->listWbPages);
-+ iinfo->numWbPages++;
-+ HgfsWbRequestGet(req);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsInodeAddWbRequest --
-+ *
-+ * Remove a write-back page request from an inode.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static void
-+HgfsInodeRemoveWbRequest(struct inode *inode, // IN: inode of file written to
-+ HgfsWbPage *req) // IN: page write request
-+{
-+ HgfsInodeInfo *iinfo = INODE_GET_II_P(inode);
-+
-+ LOG(6, (KERN_CRIT "VMware hgfs: HgfsInodeRemoveWbRequest: (%p, %p, %lu)\n",
-+ inode, req->wb_page, iinfo->numWbPages));
-+
-+ iinfo->numWbPages--;
-+ HgfsWbRequestListRemove(req);
-+ HgfsWbRequestPut(req);
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsInodeAddWbRequest --
-+ *
-+ * Add a write-back page request to an inode.
-+ * If the page is already exists in the list for this inode nothing is
-+ * done, otherwise a new object is created for the page and added to the
-+ * inode list.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static void
-+HgfsInodePageWbAdd(struct inode *inode, // IN: inode of file to write to
-+ struct page *page) // IN: page of data to write
-+{
-+ HgfsWbPage *req;
-+
-+ LOG(6, (KERN_CRIT "VMware hgfs: HgfsInodePageWbAdd: (%p, %p)\n",
-+ inode, page));
-+
-+ req = HgfsInodeFindExistingWbRequest(inode, page);
-+ if (req != NULL) {
-+ goto exit;
-+ }
-+
-+ /*
-+ * We didn't find an existing write back request for that page so
-+ * we create one.
-+ */
-+ req = HgfsWbRequestCreate(page);
-+ if (IS_ERR(req)) {
-+ goto exit;
-+ }
-+
-+ spin_lock(&inode->i_lock);
-+ /*
-+ * Add the new write request for the page into our inode list to track.
-+ */
-+ HgfsInodeAddWbRequest(inode, req);
-+ spin_unlock(&inode->i_lock);
-+
-+exit:
-+ if (!IS_ERR(req)) {
-+ HgfsWbRequestUnlockAndPut(req);
-+ }
-+}
-+
-+
-+/*
-+ *----------------------------------------------------------------------
-+ *
-+ * HgfsInodePageWbRemove --
-+ *
-+ * Remove a write-back page request from an inode.
-+ *
-+ * Results:
-+ * None
-+ *
-+ * Side effects:
-+ * None
-+ *
-+ *----------------------------------------------------------------------
-+ */
-+
-+static void
-+HgfsInodePageWbRemove(struct inode *inode, // IN: inode of file written to
-+ struct page *page) // IN: page of data written
-+{
-+ HgfsWbPage *req;
-+
-+ LOG(6, (KERN_WARNING "VMware hgfs: HgfsInodePageWbRemove: (%p, %p)\n",
-+ inode, page));
-+
-+ req = HgfsInodeFindExistingWbRequest(inode, page);
-+ if (req == NULL) {
-+ goto exit;
-+ }
-+ spin_lock(&inode->i_lock);
-+ /*
-+ * Add the new write request for the page into our inode list to track.
-+ */
-+ HgfsInodeRemoveWbRequest(inode, req);
-+ HgfsWbRequestUnlockAndPut(req);
-+ spin_unlock(&inode->i_lock);
-+
-+exit:
-+ return;
-+}
-+
---
-2.0.1
-
diff --git a/main/open-vm-tools-grsec/APKBUILD b/main/open-vm-tools-grsec/APKBUILD
index a4c260e592..f8ddaa3aba 100644
--- a/main/open-vm-tools-grsec/APKBUILD
+++ b/main/open-vm-tools-grsec/APKBUILD
@@ -3,10 +3,10 @@
_flavor=grsec
_kpkg=linux-$_flavor
_realname=open-vm-tools
-_kver=3.14.37
-_kpkgrel=3
+_kver=3.18.11
+_kpkgrel=0
-_realver=9.4.6_p1770165
+_realver=9.10.0_p2476743
_ver=${_realver/_p/-}
_mypkgrel=0
@@ -39,13 +39,9 @@ subpackages=""
depends="linux-${_flavor}=${_kernelver}"
depends_dev="bash glib-dev gettext-dev linux-${_flavor}-dev=${_kernelver}"
makedepends="$depends_dev autoconf automake libtool linux-headers"
-source="http://downloads.sourceforge.net/project/open-vm-tools/open-vm-tools/stable-${_realver%.*}.x/open-vm-tools-${_ver}.tar.gz
-
- 0001-Remove-unused-DEPRECATED-macro.patch
- 0002-Conditionally-define-g_info-macro.patch
- 0003-Add-kuid_t-kgid_t-compatibility-layer.patch
- 0004-Use-new-link-helpers.patch
- 0005-Update-hgfs-file-operations-for-newer-kernels.patch
+source="http://downloads.sourceforge.net/project/open-vm-tools/open-vm-tools/stable-${_realver%_p*}/open-vm-tools-${_ver}.tar.gz
+ 0001-Fix-vmxnet-module-on-kernels-3.16.patch
+ 0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch
vmware-modules.initd
"
@@ -70,11 +66,13 @@ build() {
./configure \
--build=$CBUILD \
--host=$CHOST \
+ --disable-deploypkg \
--without-pam \
--without-x \
--without-dnet \
--without-icu \
--without-procps \
+ --without-ssl \
--with-kernel-release="${_abi_release}" \
|| return 1
cd "$_builddir"/modules
@@ -92,24 +90,15 @@ package() {
done
}
-md5sums="3969daf1535d34e1c5f0c87a779b7642 open-vm-tools-9.4.6-1770165.tar.gz
-dc9753f2f617a8b3db9176c440e8450c 0001-Remove-unused-DEPRECATED-macro.patch
-be1dc71ed74d6dc53c198f248d668f7b 0002-Conditionally-define-g_info-macro.patch
-51cc014684037f5a0fc0a3744615da0f 0003-Add-kuid_t-kgid_t-compatibility-layer.patch
-1be086d0028447ba310fcb1e39c08573 0004-Use-new-link-helpers.patch
-cb6b4214604d4cd116ffa824d515581e 0005-Update-hgfs-file-operations-for-newer-kernels.patch
+md5sums="d19439b499f0cbc7001e0cc65aa1a5a7 open-vm-tools-9.10.0-2476743.tar.gz
+3254b99481cea970acd6d65863ce6b48 0001-Fix-vmxnet-module-on-kernels-3.16.patch
+c0d137a271fc987024efbea698602681 0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch
afba2c3487d0b12cee80eb2f04b05ba1 vmware-modules.initd"
-sha256sums="54d7a83d8115124e4b809098b08d7017ba50828801c2f105cdadbc85a064a079 open-vm-tools-9.4.6-1770165.tar.gz
-1458c4133a96f12a98c3d87df9893a02620b4b8700fb6aa5db0d3268da8102a5 0001-Remove-unused-DEPRECATED-macro.patch
-1f5e61ee1f025ba02abfe1557e55b1871ada68b9289e78fc6d65f974689ad69e 0002-Conditionally-define-g_info-macro.patch
-b11776423f3579217b67dda65c60e8e7e2cb72ba10325e18c45a4f6b199416b2 0003-Add-kuid_t-kgid_t-compatibility-layer.patch
-bdc6d05d3ef409b1ed639448c0d74d2905ab5d6e0a09c13868a4084148947ebb 0004-Use-new-link-helpers.patch
-ac099e639fc6aa0edf9c6f16a31cf50915bc670947c5a1ecc8940389fd74d065 0005-Update-hgfs-file-operations-for-newer-kernels.patch
+sha256sums="e146ad53d744d7793ee72c5271fc49a916613534c14827c227fdaef4b3579c96 open-vm-tools-9.10.0-2476743.tar.gz
+85be67ed9827e685d55dd5cba25144d95296159ff1be73f491b343c395dd6a7d 0001-Fix-vmxnet-module-on-kernels-3.16.patch
+d3dfe8f5af380afb9b32a1916a6b1e296ad3a55d1db7ac21fa7a3c35ce2d248a 0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch
6ceb5c75b002991c511d9dadb6cf91720771e76b701e5f2d91ac9ede4b168265 vmware-modules.initd"
-sha512sums="a16dc51a51a182031c1849776be9ac0e13bef9d9cb85807e03fbb816d4e9109b64e60f1919f6686a471c79042f30ca93f0193985c2150c6254bc72e3fd8ffa49 open-vm-tools-9.4.6-1770165.tar.gz
-707f6458a9492d2c7f0ac344711ac24d05e0c3423859c140379e46a7c0905a53daf7b2b24a47a8a03c07be51c40bdfba3e75f5d429769463e6af4010e1f88358 0001-Remove-unused-DEPRECATED-macro.patch
-c364f35f6aae7c34c2bb1d4f69016b761302853fa1a606e40829cd024f152e3d764c02fbbfaac0efcb4cc44c269843a410c35f528d3523ff1447b329a6f26b42 0002-Conditionally-define-g_info-macro.patch
-75ccda4d30ec872fa3950e4076fd157f30c49134763551082765eb94b73b1c777c0953257fbdf16043dd5192f1fc9f04c7031f00199b8f180a5ac4efb2aaaf21 0003-Add-kuid_t-kgid_t-compatibility-layer.patch
-319cd1879ead9b6d89971c2a3a38d0a65e2c98808325db1db6d1f99b54d8062080a1fb7ba445ac40d5ac9b64659e9a0ebf1dcc2daec9fca0b4a6276a6ee98982 0004-Use-new-link-helpers.patch
-d055fa759e2bedc0476de4d1b6df8018b56eefcf3e1b64cc662a9676d332b0cd26c623c2c0f7206d905a2d771d84cb4d6ef121385d5c2612595a996b91656c36 0005-Update-hgfs-file-operations-for-newer-kernels.patch
+sha512sums="8c8e4a559c0374e020c8261d4c8f6855efbe3f509745ee02ec03ab9ebce7e1327ec1e5e18f674cb464630ace9dc33b4262ffd119fc237c286ee44327e4590385 open-vm-tools-9.10.0-2476743.tar.gz
+c445631b7faf8badfbf8e66518bfb70aec1049c1a0393ff038253e70190d7f8580cbcd3e7037c43664ee0ee48d26edd8f8eaca06383bbd7fa763a182050f9551 0001-Fix-vmxnet-module-on-kernels-3.16.patch
+bb063ca0aac0a76633eec2878197ae977f48523da79afcd6e5b25a8d199fbc13247ea23a106ca5d44473881ad814c175084c28af7d344e83ed0e4b9321e4d6c3 0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch
639098221975cadaed0ae0f32454a6718ceaa5f43f17d949a84a85dee56fbf5f9e6248899c10a46b12c9c9cf28b837d83a37c25aba62b11cb7849a1cf8d32e1e vmware-modules.initd"
diff --git a/main/open-vm-tools-grsec/vmhgfs-d_count-kernel-3.11-tools-9.6.0.patch b/main/open-vm-tools-grsec/vmhgfs-d_count-kernel-3.11-tools-9.6.0.patch
deleted file mode 100644
index 68294794d9..0000000000
--- a/main/open-vm-tools-grsec/vmhgfs-d_count-kernel-3.11-tools-9.6.0.patch
+++ /dev/null
@@ -1,40 +0,0 @@
---- a/modules/linux/vmhgfs/inode.c 2013-08-15 22:32:22.000000000 -0700
-+++ b/modules/linux/vmhgfs/inode.c 2013-09-16 21:31:12.323041668 -0700
-@@ -31,6 +31,9 @@
- #include <linux/namei.h>
- #endif
- #include <linux/highmem.h>
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
-+#include <linux/dcache.h>
-+#endif
-
- #include "compat_cred.h"
- #include "compat_fs.h"
-@@ -1890,7 +1893,11 @@
- #endif
- &inode->i_dentry,
- d_alias) {
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
-+ int dcount = d_count(dentry);
-+#else
- int dcount = dentry->d_count;
-+#endif
- if (dcount) {
- LOG(4, ("Found %s %d \n", dentry->d_name.name, dcount));
- return HgfsAccessInt(dentry, mask & (MAY_READ | MAY_WRITE | MAY_EXEC));
-@@ -1943,10 +1950,12 @@
- list_for_each(pos, &inode->i_dentry) {
- int dcount;
- struct dentry *dentry = list_entry(pos, struct dentry, d_alias);
--#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38)
-- dcount = atomic_read(&dentry->d_count);
--#else
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
-+ dcount = d_count(dentry);
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
- dcount = dentry->d_count;
-+#else
-+ dcount = atomic_read(&dentry->d_count);
- #endif
- if (dcount) {
- LOG(4, ("Found %s %d \n", (dentry)->d_name.name, dcount));