diff --git a/0006-Fix-vmxnet-module-on-kernels-3.16.patch b/0001-Fix-vmxnet-module-on-kernels-3.16.patch similarity index 60% rename from 0006-Fix-vmxnet-module-on-kernels-3.16.patch rename to 0001-Fix-vmxnet-module-on-kernels-3.16.patch index 0b29ddd..92f7239 100644 --- a/0006-Fix-vmxnet-module-on-kernels-3.16.patch +++ b/0001-Fix-vmxnet-module-on-kernels-3.16.patch @@ -1,19 +1,19 @@ -From 4601d767d60e9a377c285994266c6fef49cae550 Mon Sep 17 00:00:00 2001 +From 08836a47c56b47b658025e41a20027c5d915f836 Mon Sep 17 00:00:00 2001 From: "Scott M. Kroll" Date: Fri, 15 Aug 2014 10:40:38 -0400 -Subject: [PATCH 10/11] Fix vmxnet module on kernels >= 3.16 +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 ++++++++----- + modules/linux/shared/compat_netdevice.h | 4 ++++ + 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 +diff --git a/modules/linux/shared/compat_netdevice.h b/modules/linux/shared/compat_netdevice.h index 3aec25b..a65d59b 100644 ---- a/open-vm-tools/modules/linux/shared/compat_netdevice.h -+++ b/open-vm-tools/modules/linux/shared/compat_netdevice.h +--- 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 @@ -23,11 +23,11 @@ index 3aec25b..a65d59b 100644 +#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 54b4590..7fb5692 100644 ---- a/open-vm-tools/modules/linux/vmxnet/vmxnet.c -+++ b/open-vm-tools/modules/linux/vmxnet/vmxnet.c -@@ -283,8 +283,7 @@ vmxnet_change_mtu(struct net_device *dev, int new_mtu) +diff --git a/modules/linux/vmxnet/vmxnet.c b/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 @@ -37,7 +37,7 @@ index 54b4590..7fb5692 100644 /* *---------------------------------------------------------------------------- * -@@ -530,7 +529,7 @@ vmxnet_ethtool_ops = { +@@ -526,7 +525,7 @@ vmxnet_ethtool_ops = { }; @@ -46,7 +46,7 @@ index 54b4590..7fb5692 100644 /* -@@ -743,7 +742,7 @@ vmxnet_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +@@ -739,7 +738,7 @@ vmxnet_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } return -EOPNOTSUPP; } @@ -70,5 +70,5 @@ index 54b4590..7fb5692 100644 dev->do_ioctl = vmxnet_ioctl; #endif -- -2.0.4 +2.3.4 diff --git a/0001-Remove-unused-DEPRECATED-macro.patch b/0001-Remove-unused-DEPRECATED-macro.patch deleted file mode 100644 index 06e9451..0000000 --- a/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" -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/open-vm-tools/lib/include/vm_assert.h -+++ b/open-vm-tools/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/0002-Conditionally-define-g_info-macro.patch b/0002-Conditionally-define-g_info-macro.patch deleted file mode 100644 index 0501412..0000000 --- a/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" -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/open-vm-tools/lib/include/vmware/tools/log.h -+++ b/open-vm-tools/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/0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch b/0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch new file mode 100644 index 0000000..ded67a0 --- /dev/null +++ b/0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch @@ -0,0 +1,42 @@ +From 8df98f3c779fa43d073a42e82bd18cf28c2bd4af Mon Sep 17 00:00:00 2001 +From: Wendell Smith +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 + +--- + a/modules/linux/vmhgfs/inode.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Index: open-vm-tools-9.10.0-2476743/modules/linux/vmhgfs/inode.c +=================================================================== +--- open-vm-tools-9.10.0-2476743.orig/modules/linux/vmhgfs/inode.c ++++ open-vm-tools-9.10.0-2476743/modules/linux/vmhgfs/inode.c +@@ -1917,7 +1917,12 @@ HgfsPermission(struct inode *inode, + p, + #endif + &inode->i_dentry, +- d_alias) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 1) ++ d_u.d_alias ++#else ++ d_alias ++#endif ++ ) { + int dcount = hgfs_d_count(dentry); + if (dcount) { + LOG(4, ("Found %s %d \n", dentry->d_name.name, dcount)); +@@ -1970,7 +1975,13 @@ 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, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 1) ++ d_u.d_alias ++#else ++ d_alias ++#endif ++ ); + dcount = hgfs_d_count(dentry); + if (dcount) { + LOG(4, ("Found %s %d \n", (dentry)->d_name.name, dcount)); diff --git a/0003-Add-kuid_t-kgid_t-compatibility-layer.patch b/0003-Add-kuid_t-kgid_t-compatibility-layer.patch deleted file mode 100644 index 38210fc..0000000 --- a/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" -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/open-vm-tools/modules/linux/vmhgfs/filesystem.c -+++ b/open-vm-tools/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/open-vm-tools/modules/linux/vmhgfs/fsutil.c -+++ b/open-vm-tools/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/open-vm-tools/modules/linux/vmhgfs/fsutil.h -+++ b/open-vm-tools/modules/linux/vmhgfs/fsutil.h -@@ -32,6 +32,7 @@ - #include - #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/open-vm-tools/modules/linux/vmhgfs/inode.c -+++ b/open-vm-tools/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/open-vm-tools/modules/linux/vmhgfs/module.h -+++ b/open-vm-tools/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/0003-Fix-f_dentry-msghdr-kernel-3.19.patch b/0003-Fix-f_dentry-msghdr-kernel-3.19.patch new file mode 100644 index 0000000..b63521d --- /dev/null +++ b/0003-Fix-f_dentry-msghdr-kernel-3.19.patch @@ -0,0 +1,429 @@ +From 61751db8cd4679fc76034a5d1f99df6c64c48de6 Mon Sep 17 00:00:00 2001 +From: lotan +Date: Mon, 30 Mar 2015 08:58:56 +0200 +Subject: [PATCH 3/3] Make vmhgfs work on kernel 3.19. + +--- + modules/linux/vmhgfs/dir.c | 35 ++++++------ + modules/linux/vmhgfs/file.c | 65 +++++++++++----------- + modules/linux/vmhgfs/fsutil.c | 3 +- + modules/linux/vmhgfs/shared/compat_dentry.h | 10 ++++ + 4 files changed, 63 insertions(+), 50 deletions(-) + create mode 100644 open-vm-tools/modules/linux/vmhgfs/shared/compat_dentry.h + +diff --git a/modules/linux/vmhgfs/dir.c b/modules/linux/vmhgfs/dir.c +index 809611a..c6a87bd 100644 +--- a/modules/linux/vmhgfs/dir.c ++++ b/modules/linux/vmhgfs/dir.c +@@ -31,6 +31,7 @@ + #include "compat_kernel.h" + #include "compat_slab.h" + #include "compat_mutex.h" ++#include "shared/compat_dentry.h" + + #include "cpName.h" + #include "hgfsEscape.h" +@@ -414,7 +415,7 @@ HgfsPackDirOpenRequest(struct file *file, // IN: File pointer for this open + + /* Build full name to send to server. */ + if (HgfsBuildPath(name, req->bufferSize - (requestSize - 1), +- file->f_dentry) < 0) { ++ DENTRY(file)) < 0) { + LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackDirOpenRequest: build path failed\n")); + return -EINVAL; + } +@@ -560,8 +561,8 @@ HgfsPrivateDirRelease(struct file *file, // IN: File for the dir getting relea + int result = 0; + + ASSERT(file); +- ASSERT(file->f_dentry); +- ASSERT(file->f_dentry->d_sb); ++ ASSERT(DENTRY(file)); ++ ASSERT(DENTRY(file)->d_sb); + + LOG(6, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: close fh %u\n", handle)); + +@@ -704,7 +705,7 @@ HgfsDirLlseek(struct file *file, + loff_t offset, + int origin) + { +- struct dentry *dentry = file->f_dentry; ++ struct dentry *dentry = DENTRY(file); + struct inode *inode = dentry->d_inode; + compat_mutex_t *mtx; + +@@ -853,7 +854,7 @@ HgfsReaddirRefreshEntries(struct file *file) // IN: File pointer for this ope + } + + LOG(6, (KERN_DEBUG "VMware hgfs: %s: error: stale handle (%s) return %d)\n", +- __func__, file->f_dentry->d_name.name, result)); ++ __func__, DENTRY(file)->d_name.name, result)); + return result; + } + +@@ -988,9 +989,9 @@ HgfsReaddirNextEntry(struct file *file, // IN: file + char *fileName = NULL; + int result; + +- ASSERT(file->f_dentry->d_inode->i_sb); ++ ASSERT(DENTRY(file)->d_inode->i_sb); + +- si = HGFS_SB_TO_COMMON(file->f_dentry->d_inode->i_sb); ++ si = HGFS_SB_TO_COMMON(DENTRY(file)->d_inode->i_sb); + *entryIgnore = FALSE; + + /* +@@ -1079,18 +1080,18 @@ HgfsReaddirNextEntry(struct file *file, // IN: file + */ + if (!strncmp(entryName, ".", sizeof ".")) { + if (!dotAndDotDotIgnore) { +- *entryIno = file->f_dentry->d_inode->i_ino; ++ *entryIno = DENTRY(file)->d_inode->i_ino; + } else { + *entryIgnore = TRUE; + } + } else if (!strncmp(entryName, "..", sizeof "..")) { + if (!dotAndDotDotIgnore) { +- *entryIno = compat_parent_ino(file->f_dentry); ++ *entryIno = compat_parent_ino(DENTRY(file)); + } else { + *entryIgnore = TRUE; + } + } else { +- *entryIno = HgfsGetFileInode(&entryAttrs, file->f_dentry->d_inode->i_sb); ++ *entryIno = HgfsGetFileInode(&entryAttrs, DENTRY(file)->d_inode->i_sb); + } + + if (*entryIgnore) { +@@ -1170,16 +1171,16 @@ HgfsDoReaddir(struct file *file, // IN: + ASSERT(filldirCtx); + + if (!file || +- !(file->f_dentry) || +- !(file->f_dentry->d_inode)) { ++ !(DENTRY(file)) || ++ !(DENTRY(file)->d_inode)) { + LOG(4, (KERN_DEBUG "VMware hgfs: HgfsReaddir: null input\n")); + return -EFAULT; + } + + LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s, inum %lu, pos %Lu)\n", + __func__, +- file->f_dentry->d_name.name, +- file->f_dentry->d_inode->i_ino, ++ DENTRY(file)->d_name.name, ++ DENTRY(file)->d_inode->i_ino, + *currentPos)); + + /* +@@ -1294,7 +1295,7 @@ HgfsReaddir(struct file *file, // IN: + /* If either dot and dotdot are filled in for us we can exit. */ + if (!dir_emit_dots(file, ctx)) { + LOG(6, (KERN_DEBUG "VMware hgfs: %s: dir_emit_dots(%s, @ %Lu)\n", +- __func__, file->f_dentry->d_name.name, ctx->pos)); ++ __func__, DENTRY(file)->d_name.name, ctx->pos)); + return 0; + } + +@@ -1464,8 +1465,8 @@ HgfsDirRelease(struct inode *inode, // IN: Inode that the file* points to + + ASSERT(inode); + ASSERT(file); +- ASSERT(file->f_dentry); +- ASSERT(file->f_dentry->d_sb); ++ ASSERT(DENTRY(file)); ++ ASSERT(DENTRY(file)->d_sb); + + handle = FILE_GET_FI_P(file)->handle; + +diff --git a/modules/linux/vmhgfs/file.c b/modules/linux/vmhgfs/file.c +index bbde3f4..39502d0 100644 +--- a/modules/linux/vmhgfs/file.c ++++ b/modules/linux/vmhgfs/file.c +@@ -32,6 +32,7 @@ + #include "compat_fs.h" + #include "compat_kernel.h" + #include "compat_slab.h" ++#include "shared/compat_dentry.h" + + /* Must be after compat_fs.h */ + #if defined VMW_USE_AIO +@@ -384,7 +385,7 @@ HgfsPackOpenRequest(struct inode *inode, // IN: Inode of the file to open + /* Build full name to send to server. */ + if (HgfsBuildPath(name, + req->bufferSize - (requestSize - 1), +- file->f_dentry) < 0) { ++ DENTRY(file)) < 0) { + LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackOpenRequest: build path " + "failed\n")); + return -EINVAL; +@@ -523,8 +524,8 @@ HgfsOpen(struct inode *inode, // IN: Inode of the file to open + ASSERT(inode); + ASSERT(inode->i_sb); + ASSERT(file); +- ASSERT(file->f_dentry); +- ASSERT(file->f_dentry->d_inode); ++ ASSERT(DENTRY(file)); ++ ASSERT(DENTRY(file)->d_inode); + + iinfo = INODE_GET_II_P(inode); + +@@ -605,7 +606,7 @@ HgfsOpen(struct inode *inode, // IN: Inode of the file to open + * This is not the root of our file system so there should always + * be a parent. + */ +- ASSERT(file->f_dentry->d_parent); ++ ASSERT(DENTRY(file)->d_parent); + + /* + * Here we obtain a reference on the parent to make sure it doesn't +@@ -620,10 +621,10 @@ HgfsOpen(struct inode *inode, // IN: Inode of the file to open + * We could do this if we were willing to give up support for + * O_EXCL on 2.4 kernels. + */ +- dparent = dget(file->f_dentry->d_parent); ++ dparent = dget(DENTRY(file)->d_parent); + iparent = dparent->d_inode; + +- HgfsSetUidGid(iparent, file->f_dentry, ++ HgfsSetUidGid(iparent, DENTRY(file), + current_fsuid(), current_fsgid()); + + dput(dparent); +@@ -683,7 +684,7 @@ out: + * forcing a revalidate on one will not force it on any others. + */ + if (result != 0 && iinfo->createdAndUnopened == TRUE) { +- HgfsDentryAgeForce(file->f_dentry); ++ HgfsDentryAgeForce(DENTRY(file)); + } + return result; + } +@@ -772,13 +773,13 @@ HgfsFileRead(struct kiocb *iocb, // IN: I/O control block + + ASSERT(iocb); + ASSERT(iocb->ki_filp); +- ASSERT(iocb->ki_filp->f_dentry); ++ ASSERT(DENTRY(iocb->ki_filp)); + ASSERT(iov); + + pos = HGFS_IOCB_TO_POS(iocb, offset); + iovSegs = HGFS_IOV_TO_SEGS(iov, numSegs); + +- readDentry = iocb->ki_filp->f_dentry; ++ readDentry = DENTRY(iocb->ki_filp); + + LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s/%s)\n", + __func__, readDentry->d_parent->d_name.name, +@@ -882,13 +883,13 @@ HgfsFileWrite(struct kiocb *iocb, // IN: I/O control block + + ASSERT(iocb); + ASSERT(iocb->ki_filp); +- ASSERT(iocb->ki_filp->f_dentry); ++ ASSERT(DENTRY(iocb->ki_filp)); + ASSERT(iov); + + pos = HGFS_IOCB_TO_POS(iocb, offset); + iovSegs = HGFS_IOV_TO_SEGS(iov, numSegs); + +- writeDentry = iocb->ki_filp->f_dentry; ++ writeDentry = DENTRY(iocb->ki_filp); + + LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s/%s)\n", + __func__, writeDentry->d_parent->d_name.name, +@@ -951,7 +952,7 @@ HgfsRead(struct file *file, // IN: File to read from + int result; + + ASSERT(file); +- ASSERT(file->f_dentry); ++ ASSERT(DENTRY(file)); + ASSERT(buf); + ASSERT(offset); + +@@ -959,7 +960,7 @@ HgfsRead(struct file *file, // IN: File to read from + __func__, file->f_dentry->d_parent->d_name.name, + file->f_dentry->d_name.name, count, (long long) *offset)); + +- result = HgfsRevalidate(file->f_dentry); ++ result = HgfsRevalidate(DENTRY(file)); + if (result) { + LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRead: invalid dentry\n")); + goto out; +@@ -1002,8 +1003,8 @@ HgfsWrite(struct file *file, // IN: File to write to + int result; + + ASSERT(file); +- ASSERT(file->f_dentry); +- ASSERT(file->f_dentry->d_inode); ++ ASSERT(DENTRY(file)); ++ ASSERT(DENTRY(file)->d_inode); + ASSERT(buf); + ASSERT(offset); + +@@ -1011,7 +1012,7 @@ HgfsWrite(struct file *file, // IN: File to write to + __func__, file->f_dentry->d_parent->d_name.name, + file->f_dentry->d_name.name, count, (long long) *offset)); + +- result = HgfsRevalidate(file->f_dentry); ++ result = HgfsRevalidate(DENTRY(file)); + if (result) { + LOG(4, (KERN_DEBUG "VMware hgfs: HgfsWrite: invalid dentry\n")); + goto out; +@@ -1051,7 +1052,7 @@ HgfsSeek(struct file *file, // IN: File to seek + loff_t result = -1; + + ASSERT(file); +- ASSERT(file->f_dentry); ++ ASSERT(DENTRY(file)); + + LOG(6, (KERN_DEBUG "VMware hgfs: %s(%s/%s, %u, %lld, %d)\n", + __func__, +@@ -1059,7 +1060,7 @@ HgfsSeek(struct file *file, // IN: File to seek + file->f_dentry->d_name.name, + FILE_GET_FI_P(file)->handle, offset, origin)); + +- result = (loff_t) HgfsRevalidate(file->f_dentry); ++ result = (loff_t) HgfsRevalidate(DENTRY(file)); + if (result) { + LOG(6, (KERN_DEBUG "VMware hgfs: %s: invalid dentry\n", __func__)); + goto out; +@@ -1143,8 +1144,8 @@ HgfsFlush(struct file *file // IN: file to flush + int ret = 0; + + LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s/%s)\n", +- __func__, file->f_dentry->d_parent->d_name.name, +- file->f_dentry->d_name.name)); ++ __func__, DENTRY(file)->d_parent->d_name.name, ++ DENTRY(file)->d_name.name)); + + if ((file->f_mode & FMODE_WRITE) == 0) { + goto exit; +@@ -1157,7 +1158,7 @@ HgfsFlush(struct file *file // IN: file to flush + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) + ret = vfs_fsync(file, 0); + #else +- ret = HgfsDoFsync(file->f_dentry->d_inode); ++ ret = HgfsDoFsync(DENTRY(file)->d_inode); + #endif + + exit: +@@ -1215,13 +1216,13 @@ HgfsFsync(struct file *file, // IN: File we operate on + + LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s/%s, %lld, %lld, %d)\n", + __func__, +- file->f_dentry->d_parent->d_name.name, +- file->f_dentry->d_name.name, ++ DENTRY(file)->d_parent->d_name.name, ++ DENTRY(file)->d_name.name, + startRange, endRange, + datasync)); + + /* Flush writes to the server and return any errors */ +- inode = file->f_dentry->d_inode; ++ inode = DENTRY(file)->d_inode; + #if defined VMW_FSYNC_31 + ret = filemap_write_and_wait_range(inode->i_mapping, startRange, endRange); + #else +@@ -1261,14 +1262,14 @@ HgfsMmap(struct file *file, // IN: File we operate on + + ASSERT(file); + ASSERT(vma); +- ASSERT(file->f_dentry); ++ ASSERT(DENTRY(file)); + + LOG(6, (KERN_DEBUG "VMware hgfs: %s(%s/%s)\n", + __func__, + file->f_dentry->d_parent->d_name.name, + file->f_dentry->d_name.name)); + +- result = HgfsRevalidate(file->f_dentry); ++ result = HgfsRevalidate(DENTRY(file)); + if (result) { + LOG(4, (KERN_DEBUG "VMware hgfs: %s: invalid dentry\n", __func__)); + goto out; +@@ -1309,8 +1310,8 @@ HgfsRelease(struct inode *inode, // IN: Inode that this file points to + + ASSERT(inode); + ASSERT(file); +- ASSERT(file->f_dentry); +- ASSERT(file->f_dentry->d_sb); ++ ASSERT(DENTRY(file)); ++ ASSERT(DENTRY(file)->d_sb); + + handle = FILE_GET_FI_P(file)->handle; + LOG(6, (KERN_DEBUG "VMware hgfs: %s(%s/%s, %u)\n", +@@ -1443,14 +1444,14 @@ HgfsSendfile(struct file *file, // IN: File to read from + ssize_t result; + + ASSERT(file); +- ASSERT(file->f_dentry); ++ ASSERT(DENTRY(file)); + ASSERT(target); + ASSERT(offset); + ASSERT(actor); + + LOG(6, (KERN_DEBUG "VMware hgfs: HgfsSendfile: was called\n")); + +- result = HgfsRevalidate(file->f_dentry); ++ result = HgfsRevalidate(DENTRY(file)); + if (result) { + LOG(4, (KERN_DEBUG "VMware hgfs: HgfsSendfile: invalid dentry\n")); + goto out; +@@ -1497,7 +1498,7 @@ HgfsSpliceRead(struct file *file, // IN: File to read from + ssize_t result; + + ASSERT(file); +- ASSERT(file->f_dentry); ++ ASSERT(DENTRY(file)); + + LOG(6, (KERN_DEBUG "VMware hgfs: %s(%s/%s, %lu@%Lu)\n", + __func__, +@@ -1505,7 +1506,7 @@ HgfsSpliceRead(struct file *file, // IN: File to read from + file->f_dentry->d_name.name, + (unsigned long) len, (unsigned long long) *offset)); + +- result = HgfsRevalidate(file->f_dentry); ++ result = HgfsRevalidate(DENTRY(file)); + if (result) { + LOG(4, (KERN_DEBUG "VMware hgfs: %s: invalid dentry\n", __func__)); + goto out; +diff --git a/modules/linux/vmhgfs/fsutil.c b/modules/linux/vmhgfs/fsutil.c +index 5023324..a2e794c 100644 +--- a/modules/linux/vmhgfs/fsutil.c ++++ b/modules/linux/vmhgfs/fsutil.c +@@ -36,6 +36,7 @@ + #include "compat_sched.h" + #include "compat_slab.h" + #include "compat_spinlock.h" ++#include "shared/compat_dentry.h" + + #include "vm_assert.h" + #include "cpName.h" +@@ -1924,7 +1925,7 @@ HgfsCreateFileInfo(struct file *file, // IN: File pointer to attach to + + ASSERT(file); + +- inodeInfo = INODE_GET_II_P(file->f_dentry->d_inode); ++ inodeInfo = INODE_GET_II_P(DENTRY(file)->d_inode); + ASSERT(inodeInfo); + + /* Get the mode of the opened file. */ +diff --git a/modules/linux/vmhgfs/shared/compat_dentry.h b/modules/linux/vmhgfs/shared/compat_dentry.h +new file mode 100644 +index 0000000..dd53760 +--- /dev/null ++++ b/modules/linux/vmhgfs/shared/compat_dentry.h +@@ -0,0 +1,10 @@ ++#ifndef __COMPAT_DENTRY_H__ ++# define __COMPAT_DENTRY_H__ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++# define DENTRY(file) (file->f_path.dentry) ++#else ++# define DENTRY(file) (file->f_dentry) ++#endif ++ ++#endif /* __COMPAT_DENTRY_H__ */ +-- +2.3.4 + diff --git a/0004-Use-new-link-helpers.patch b/0004-Use-new-link-helpers.patch deleted file mode 100644 index 6a89795..0000000 --- a/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" -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/open-vm-tools/modules/linux/vmhgfs/link.c -+++ b/open-vm-tools/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/0004-vmhgfs-bdi-kernel-4.0.patch b/0004-vmhgfs-bdi-kernel-4.0.patch new file mode 100644 index 0000000..02a039e --- /dev/null +++ b/0004-vmhgfs-bdi-kernel-4.0.patch @@ -0,0 +1,77 @@ +This patch fixes a nasty bug with vmhgfs on kernel 4.x: files modified +on shared folders becomes 0 bytes on host. + +(Patch found at https://github.com/rasa/vmware-tools-patches) + + +Index: open-vm-tools-9.10.0-2476743/modules/linux/vmhgfs/filesystem.c +=================================================================== +--- open-vm-tools-9.10.0-2476743.orig/modules/linux/vmhgfs/filesystem.c ++++ open-vm-tools-9.10.0-2476743/modules/linux/vmhgfs/filesystem.c +@@ -386,8 +386,20 @@ HgfsReadSuper(struct super_block *sb, // + return PTR_ERR(si); + } + HGFS_SET_SB_TO_COMMON(sb, si); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ result = bdi_setup_and_register(&si->bdi, "vmhgfs"); ++ if (result) { ++ kfree(si->shareName); ++ kfree(si); ++ } ++#endif ++ + sb->s_magic = HGFS_SUPER_MAGIC; + sb->s_op = &HgfsSuperOperations; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ sb->s_bdi = &si->bdi; ++#endif + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) + sb->s_d_op = &HgfsDentryOperations; +@@ -427,6 +439,9 @@ HgfsReadSuper(struct super_block *sb, // + exit: + if (result) { + dput(rootDentry); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ bdi_destroy(&si->bdi); ++#endif + kfree(si->shareName); + kfree(si); + } +Index: open-vm-tools-9.10.0-2476743/modules/linux/vmhgfs/module.h +=================================================================== +--- open-vm-tools-9.10.0-2476743.orig/modules/linux/vmhgfs/module.h ++++ open-vm-tools-9.10.0-2476743/modules/linux/vmhgfs/module.h +@@ -29,6 +29,7 @@ + #include "driver-config.h" + + #include ++#include + #include "compat_fs.h" + #include "compat_semaphore.h" + #include "compat_slab.h" +@@ -130,6 +131,9 @@ typedef struct HgfsSuperInfo { + uint32 ttl; /* Maximum dentry age (in ticks). */ + char *shareName; /* Mounted share name. */ + size_t shareNameLen; /* To avoid repeated strlen() calls. */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ struct backing_dev_info bdi; ++#endif + } HgfsSuperInfo; + + /* +Index: open-vm-tools-9.10.0-2476743/modules/linux/vmhgfs/super.c +=================================================================== +--- open-vm-tools-9.10.0-2476743.orig/modules/linux/vmhgfs/super.c ++++ open-vm-tools-9.10.0-2476743/modules/linux/vmhgfs/super.c +@@ -152,6 +152,9 @@ HgfsPutSuper(struct super_block *sb) // + + si = HGFS_SB_TO_COMMON(sb); + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) ++ bdi_destroy(&si->bdi); ++#endif + kfree(si->shareName); + kfree(si); + } diff --git a/0005-Update-hgfs-file-operations-for-newer-kernels.patch b/0005-Update-hgfs-file-operations-for-newer-kernels.patch deleted file mode 100644 index 5b146cf..0000000 --- a/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" -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/open-vm-tools/modules/linux/vmhgfs/file.c -+++ b/open-vm-tools/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/open-vm-tools/modules/linux/vmhgfs/filesystem.c -+++ b/open-vm-tools/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/open-vm-tools/modules/linux/vmhgfs/fsutil.c -+++ b/open-vm-tools/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/open-vm-tools/modules/linux/vmhgfs/fsutil.h -+++ b/open-vm-tools/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/open-vm-tools/modules/linux/vmhgfs/inode.c -+++ b/open-vm-tools/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/open-vm-tools/modules/linux/vmhgfs/link.c -+++ b/open-vm-tools/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/open-vm-tools/modules/linux/vmhgfs/module.h -+++ b/open-vm-tools/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/open-vm-tools/modules/linux/vmhgfs/page.c -+++ b/open-vm-tools/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/0007-Fix-vmhgfs-module-on-kernels-3.16.patch b/0007-Fix-vmhgfs-module-on-kernels-3.16.patch deleted file mode 100644 index dcbc31f..0000000 --- a/0007-Fix-vmhgfs-module-on-kernels-3.16.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 6497dbbabb9506df8e16b60bf2cd396a8c6bb26b Mon Sep 17 00:00:00 2001 -From: "Scott M. Kroll" -Date: Fri, 15 Aug 2014 10:42:30 -0400 -Subject: [PATCH 11/11] Fix vmhgfs module on kernels >= 3.16 - -* Use read_iter/write_iter file operations on kernels >= 3.16. -* Do not set aio_read/aio_write on kernels >= 3.16. ---- - open-vm-tools/modules/linux/vmhgfs/file.c | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - -diff --git a/open-vm-tools/modules/linux/vmhgfs/file.c b/open-vm-tools/modules/linux/vmhgfs/file.c -index 825cebe..67606fd 100644 ---- a/open-vm-tools/modules/linux/vmhgfs/file.c -+++ b/open-vm-tools/modules/linux/vmhgfs/file.c -@@ -76,6 +76,7 @@ static int HgfsGetOpenFlags(uint32 flags); - static int HgfsOpen(struct inode *inode, - struct file *file); - #if defined VMW_USE_AIO -+# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) - static ssize_t HgfsAioRead(struct kiocb *iocb, - const struct iovec *iov, - unsigned long numSegs, -@@ -84,6 +85,7 @@ static ssize_t HgfsAioWrite(struct kiocb *iocb, - const struct iovec *iov, - unsigned long numSegs, - loff_t offset); -+# endif - #else - static ssize_t HgfsRead(struct file *file, - char __user *buf, -@@ -150,15 +152,20 @@ struct file_operations HgfsFileFileOperations = { - .open = HgfsOpen, - .llseek = HgfsSeek, - .flush = HgfsFlush, --#if defined VMW_USE_AIO -+#ifdef VMW_USE_AIO - .read = do_sync_read, - .write = do_sync_write, -+# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) -+ .read_iter = generic_file_read_iter, -+ .write_iter = generic_file_write_iter, -+# else - .aio_read = HgfsAioRead, - .aio_write = HgfsAioWrite, --#else -+# endif -+#else /* !VMW_USE_AIO */ - .read = HgfsRead, - .write = HgfsWrite, --#endif -+#endif /* !VMW_USE_AIO */ - .fsync = HgfsFsync, - .mmap = HgfsMmap, - .release = HgfsRelease, -@@ -748,6 +755,7 @@ out: - - - #if defined VMW_USE_AIO -+# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) - /* - *---------------------------------------------------------------------- - * -@@ -883,7 +891,7 @@ out: - return result; - } - -- -+# endif /* if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) */ - #else - /* - *---------------------------------------------------------------------- --- -2.0.4 - diff --git a/0008-Fix-segfault-in-vmhgfs.patch b/0008-Fix-segfault-in-vmhgfs.patch deleted file mode 100644 index d15427b..0000000 --- a/0008-Fix-segfault-in-vmhgfs.patch +++ /dev/null @@ -1,110 +0,0 @@ -From e75a7401a72607476f7a248f5a7fe4f11d6d129d Mon Sep 17 00:00:00 2001 -From: "Scott M. Kroll" -Date: Fri, 15 Aug 2014 11:11:12 -0400 -Subject: [PATCH 12/12] Fix segfault in vmhgfs - -* Need to use sync read/write but also set the read_iter/write_iter - operations. ---- - open-vm-tools/modules/linux/shared/compat_fs.h | 3 ++- - open-vm-tools/modules/linux/vmhgfs/file.c | 23 ++++++++++++----------- - 2 files changed, 14 insertions(+), 12 deletions(-) - -diff --git a/open-vm-tools/modules/linux/shared/compat_fs.h b/open-vm-tools/modules/linux/shared/compat_fs.h -index f762f6f..eb53ee7 100644 ---- a/open-vm-tools/modules/linux/shared/compat_fs.h -+++ b/open-vm-tools/modules/linux/shared/compat_fs.h -@@ -89,7 +89,8 @@ - * changed over time, so for simplicity, we'll only enable it from 2.6.19 and - * on. - */ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) && \ -+ LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) - # define VMW_USE_AIO - #endif - -diff --git a/open-vm-tools/modules/linux/vmhgfs/file.c b/open-vm-tools/modules/linux/vmhgfs/file.c -index 67606fd..fcf0681 100644 ---- a/open-vm-tools/modules/linux/vmhgfs/file.c -+++ b/open-vm-tools/modules/linux/vmhgfs/file.c -@@ -76,7 +76,6 @@ static int HgfsGetOpenFlags(uint32 flags); - static int HgfsOpen(struct inode *inode, - struct file *file); - #if defined VMW_USE_AIO --# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) - static ssize_t HgfsAioRead(struct kiocb *iocb, - const struct iovec *iov, - unsigned long numSegs, -@@ -85,7 +84,6 @@ static ssize_t HgfsAioWrite(struct kiocb *iocb, - const struct iovec *iov, - unsigned long numSegs, - loff_t offset); --# endif - #else - static ssize_t HgfsRead(struct file *file, - char __user *buf, -@@ -155,14 +153,13 @@ struct file_operations HgfsFileFileOperations = { - #ifdef VMW_USE_AIO - .read = do_sync_read, - .write = do_sync_write, --# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) -- .read_iter = generic_file_read_iter, -- .write_iter = generic_file_write_iter, --# else - .aio_read = HgfsAioRead, - .aio_write = HgfsAioWrite, --# endif - #else /* !VMW_USE_AIO */ -+# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) -+ .read_iter = generic_file_read_iter, -+ .write_iter = generic_file_write_iter, -+# endif - .read = HgfsRead, - .write = HgfsWrite, - #endif /* !VMW_USE_AIO */ -@@ -755,7 +752,6 @@ out: - - - #if defined VMW_USE_AIO --# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) - /* - *---------------------------------------------------------------------- - * -@@ -890,8 +886,6 @@ out: - spin_unlock(&writeDentry->d_inode->i_lock); - return result; - } -- --# endif /* if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) */ - #else - /* - *---------------------------------------------------------------------- -@@ -933,8 +927,11 @@ HgfsRead(struct file *file, // IN: File to read from - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRead: invalid dentry\n")); - goto out; - } -- -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) -+ result = new_sync_read(file, buf, count, offset); -+#else - result = generic_file_read(file, buf, count, offset); -+#endif - out: - return result; - } -@@ -985,7 +982,11 @@ HgfsWrite(struct file *file, // IN: File to write to - goto out; - } - -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) -+ result = new_sync_write(file, buf, count, offset); -+#else - result = generic_file_write(file, buf, count, offset); -+#endif - out: - return result; - } --- -2.0.4 - diff --git a/enable-gcc46+.patch b/enable-gcc46+.patch new file mode 100644 index 0000000..ac1bd0d --- /dev/null +++ b/enable-gcc46+.patch @@ -0,0 +1,60 @@ +When compiling under gcc4.6+, the following errors can be seen: + +[ 93s] In file included from /usr/include/sigc++-2.0/sigc++/signal.h:8:0, +[ 93s] from /usr/include/sigc++-2.0/sigc++/connection.h:22, +[ 93s] from ../../../services/plugins/dndcp/dnd/copyPasteRpc.hh:28, +[ 93s] from dndGuest/copyPasteRpcV3.hh:29, +[ 93s] from dndGuest/copyPasteRpcV3.cc:26: +[ 93s] /usr/include/sigc++-2.0/sigc++/signal_base.h:46:11: error: 'size_t' does not name a type +[ 93s] typedef size_t size_type; +[ 93s] ^ +[ 93s] /usr/include/sigc++-2.0/sigc++/signal_base.h:95:3: error: 'size_type' does not name a type +[ 93s] size_type size() const; +[ 93s] ^ +[ 93s] /usr/include/sigc++-2.0/sigc++/signal_base.h:239:11: error: 'size_t' does not name a type +[ 93s] typedef size_t size_type; +[ 93s] ^ +[ 93s] /usr/include/sigc++-2.0/sigc++/signal_base.h:261:3: error: 'size_type' does not name a type +[ 93s] size_type size() const; + +As per https://gcc.gnu.org/gcc-4.6/porting_to.html, this is fixed through: + + #include + + +Index: open-vm-tools-9.10.0-2476743/services/plugins/dndcp/dnd/copyPasteRpc.hh +=================================================================== +--- open-vm-tools-9.10.0-2476743.orig/services/plugins/dndcp/dnd/copyPasteRpc.hh ++++ open-vm-tools-9.10.0-2476743/services/plugins/dndcp/dnd/copyPasteRpc.hh +@@ -25,6 +25,7 @@ + #ifndef COPY_PASTE_RPC_HH + #define COPY_PASTE_RPC_HH + ++#include + #include + #include "dndCPLibExport.hh" + #include "rpcBase.h" +Index: open-vm-tools-9.10.0-2476743/services/plugins/dndcp/dnd/dndRpc.hh +=================================================================== +--- open-vm-tools-9.10.0-2476743.orig/services/plugins/dndcp/dnd/dndRpc.hh ++++ open-vm-tools-9.10.0-2476743/services/plugins/dndcp/dnd/dndRpc.hh +@@ -25,6 +25,7 @@ + #ifndef DND_RPC_HH + #define DND_RPC_HH + ++#include + #include + #include "dndCPLibExport.hh" + #include "rpcBase.h" +Index: open-vm-tools-9.10.0-2476743/services/plugins/dndcp/dnd/fileTransferRpc.hh +=================================================================== +--- open-vm-tools-9.10.0-2476743.orig/services/plugins/dndcp/dnd/fileTransferRpc.hh ++++ open-vm-tools-9.10.0-2476743/services/plugins/dndcp/dnd/fileTransferRpc.hh +@@ -25,6 +25,7 @@ + #ifndef FILE_TRANSFER_RPC_HH + #define FILE_TRANSFER_RPC_HH + ++#include + #include + #include "dndCPLibExport.hh" + #include "rpcBase.h" diff --git a/open-vm-tools-9.10.0-2476743.tar.gz b/open-vm-tools-9.10.0-2476743.tar.gz new file mode 100644 index 0000000..f45b444 --- /dev/null +++ b/open-vm-tools-9.10.0-2476743.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e146ad53d744d7793ee72c5271fc49a916613534c14827c227fdaef4b3579c96 +size 4093306 diff --git a/open-vm-tools-9.4.6-1770165.tar.gz b/open-vm-tools-9.4.6-1770165.tar.gz deleted file mode 100644 index 5705075..0000000 --- a/open-vm-tools-9.4.6-1770165.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:54d7a83d8115124e4b809098b08d7017ba50828801c2f105cdadbc85a064a079 -size 2434586 diff --git a/open-vm-tools-KMP.changes b/open-vm-tools-KMP.changes index cee1e57..70d7ac2 100644 --- a/open-vm-tools-KMP.changes +++ b/open-vm-tools-KMP.changes @@ -1,15 +1,88 @@ +------------------------------------------------------------------- +Mon May 21 23:04:48 UTC 2015 - mlatimer@suse.com + +- Build using gcc4.7 for SLES11 environments to avoid mul64.h + dependency problem for i586 architectures +- Include cstddef to resolve compile problems under gcc4.7 + enable-gcc46+.patch +- Ensure xutils builds properly under older versions of gcc + xutils-add-cstring.patch +- Prevent files on shared folders from being truncated to 0 bytes + under 4.0 kernel + 0004-vmhgfs-bdi-kernel-4.0.patch + +------------------------------------------------------------------- +Wed May 18 00:01:07 UTC 2015 - mlatimer@suse.com + +- Update to open-vm-tools-9.10.0-2476743: + + vgauth added + + deploypkg added + + guest proxycerttool added + + hgfs and vmci/vsock fixes + + asyncsocket enhancements + + library fixes and improvements + + locking and logging fixes and improvements + + foundry fixes + + vm-support script fixes +- Replace obsolete patches with rebased versions (from ArchLinux): + - Drop 0001-Remove-unused-DEPRECATED-macro.patch + - Drop 0002-Conditionally-define-g_info-macro.patch + - Drop 0003-Add-kuid_t-kgid_t-compatibility-layer.patch + - Drop 0004-Use-new-link-helpers.patch + - Drop 0005-Update-hgfs-file-operations-for-newer-kernels.patch + - Drop 0006-Fix-vmxnet-module-on-kernels-3.16.patch + - Drop 0007-Fix-vmhgfs-module-on-kernels-3.16.patch + - Drop 0008-Fix-segfault-in-vmhgfs.patch + - Drop open-vm-tools-linux-3.17.7.patch + - Drop open-vm-tools-linux-3.17.patch + - Drop open-vm-tools-linux-3.18.0.patch + - Add 0001-Fix-vmxnet-module-on-kernels-3.16.patch + - Add 0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch + - Add 0003-Fix-f_dentry-msghdr-kernel-3.19.patch +- Add libmspack BuildRequires (deploypkg). +- Add openssl BuildRequires (grabbitmqproxy and vgauth). +- Compile using --without-xmlsecurity and --without-xerces as + pkgconfig(xml-security-c) is not yet available in the build service, + (disables vgauth support). +- Disable deploypkg for older versions of SLES and openSUSE. +- Disable ssl for older versions of SLES and openSUSE (disables + grabbitmqproxy and vgauth). +- Update spec file to be compatible with SLES and openSUSE. + ------------------------------------------------------------------- Tue May 5 14:31:19 UTC 2015 - dimstar@opensuse.org - Handle kernel 4.0: we can't just compare the 'minor' part of the version anymore when applying patches. +------------------------------------------------------------------- +Thu Mar 12 00:05:55 UTC 2015 - mlatimer@suse.com + +- Prevent autoinstallation of open-vm-tools in SLES11SP4 environments + due to potential conflict with VMware tools. (bsc#921618) + ------------------------------------------------------------------- Thu Feb 19 13:35:44 UTC 2015 - dimstar@opensuse.org - Add open-vm-tools-linux-3.19.0.patch: Fix building of vmhgfs with Kernel 3.19.0+. +------------------------------------------------------------------- +Wed Jan 21 23:58:08 UTC 2015 - mlatimer@suse.com + +- Remove modprobe of deprecated vmsync module from SysV init script. + +------------------------------------------------------------------- +Fri Jan 16 02:55:39 UTC 2015 - mlatimer@suse.com + +- Update specfile to ensure kernel modules are not built or required + for SLES11SP4 and SLES12. + +------------------------------------------------------------------- +Fri Jan 9 23:57:56 UTC 2015 - mlatimer@suse.com + +- Use fuse-devel instead of pkgconfig(fuse) in SLES11SP4. + ------------------------------------------------------------------- Mon Jan 5 10:07:50 UTC 2015 - dimstar@opensuse.org diff --git a/open-vm-tools-KMP.spec b/open-vm-tools-KMP.spec index 01b3030..b278e19 100644 --- a/open-vm-tools-KMP.spec +++ b/open-vm-tools-KMP.spec @@ -17,32 +17,36 @@ # -%define with_systemd 1 %define KMP 1 -# The vmhgfs modules is used with all versions -%define vmhgfs vmhgfs - -# disable systemd if before 13.1 -%if 0%{suse_version} < 1310 -%define with_systemd 0 +# systemd and deploypkg should be enabled by default on versions >= 13.1 +%if 0%{?suse_version} >= 1310 +%bcond_without systemd +%bcond_without deploypkg +%else +%bcond_with systemd +%bcond_with deploypkg %endif +# The vmhgfs module is currently built for all versions +# (Shared Folders are not supported under ESX/ESXi, so this driver is not necessary for SLES11/12) +%define vmhgfs vmhgfs + # exclude AMD PCnet32 LANCE pci.id from Supplements list [bnc#397554] %define __find_supplements sh -c '/usr/lib/rpm/find-supplements %{name} | grep -v pci:v00001022d00002000' -%if 0%{?suse_version} <= 1230 -# Modules to be built up to openSUSE 12.3, possibly not building on newer versions. +# Modules to be built up to openSUSE 12.3 (excluding SLES11), possibly not building on newer versions. +%if 0%{?suse_version} <= 1230 && 0%{?suse_version} != 1110 %define vm_modules1230 vmci vsock %endif -%if 0%{?suse_version} <= 1220 -# Modules to be built up to openSUSE 12.1, possibly not building on newer versions. +%if 0%{?suse_version} <= 1220 && 0%{?suse_version} != 1110 +# Modules to be built up to openSUSE 12.1 (excluding SLES11), possibly not building on newer versions. %define vm_modules1220 vmsync %endif -%if 0%{?suse_version} <= 1210 -# Modules to be built up to openSUSE 12.1, possibly not building on newer versions. +%if 0%{?suse_version} <= 1210 && 0%{?suse_version} != 1110 +# Modules to be built up to openSUSE 12.1 (excluding SLES11), possibly not building on newer versions. %define vm_modules1210 vmxnet %endif @@ -54,14 +58,14 @@ Name: open-vm-tools-KMP %define tarname open-vm-tools -Version: 9.4.6 +Version: 9.10.0 Release: 0 -%define svn_rev 1770165 +%define svn_rev 2476743 Summary: Open Virtual Machine Tools License: BSD-3-Clause and GPL-2.0 and LGPL-2.1 Group: System/Emulators/PC Url: http://open-vm-tools.sourceforge.net/ -Source: http://sourceforge.net/projects/open-vm-tools/files/open-vm-tools/stable-9.4.x/%{tarname}-%{version}-%{svn_rev}.tar.gz +Source: http://sourceforge.net/projects/open-vm-tools/files/open-vm-tools/stable-9.10.0/%{tarname}-%{version}-%{svn_rev}.tar.gz Source1: vmtoolsd Source2: vmtoolsd.service Source3: vmware-user-autostart.desktop @@ -69,25 +73,19 @@ Source5: vmware-user-autostart-wrapper Source6: open-vm-tools-modprobe.conf Source7: tools.conf Source98: preamble -Patch1: 0001-Remove-unused-DEPRECATED-macro.patch -Patch2: 0002-Conditionally-define-g_info-macro.patch -Patch3: 0003-Add-kuid_t-kgid_t-compatibility-layer.patch -Patch4: 0004-Use-new-link-helpers.patch -Patch5: 0005-Update-hgfs-file-operations-for-newer-kernels.patch -Patch6: 0006-Fix-vmxnet-module-on-kernels-3.16.patch -Patch7: 0007-Fix-vmhgfs-module-on-kernels-3.16.patch -Patch8: 0008-Fix-segfault-in-vmhgfs.patch -Patch10: open-vm-tools-linux-3.17.patch -Patch11: open-vm-tools-linux-3.17.7.patch -Patch12: open-vm-tools-linux-3.18.0.patch -Patch13: open-vm-tools-linux-3.19.0.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build +# SUSE versions below 1110 (SLES11 SP4) must use gcc 4.7 to compile under i586 +%if 0%{?suse_version} <= 1110 +BuildRequires: gcc47 +BuildRequires: gcc47-c++ +%else BuildRequires: gcc-c++ +%endif # don't use pkgconfig(gtk+-2.0) so we can build on SLE BuildRequires: gtk2-devel BuildRequires: gtkmm2-devel # Only require kernel packages if kernel modules are being built -%if "%{?vm_modules}" != " " && %{KMP} +%if %{KMP} BuildRequires: kernel-source BuildRequires: kernel-syms BuildRequires: module-init-tools @@ -97,12 +95,13 @@ BuildRequires: automake BuildRequires: doxygen BuildRequires: libdnet-devel BuildRequires: libicu-devel +BuildRequires: libmspack-devel BuildRequires: libtool +BuildRequires: openssl-devel BuildRequires: pam-devel BuildRequires: pcre-devel BuildRequires: update-desktop-files BuildRequires: xorg-x11-devel -BuildRequires: pkgconfig(fuse) # libprocps is required with 12.3 and above %if 0%{?suse_version} >= 1230 BuildRequires: procps-devel @@ -117,19 +116,26 @@ Requires: tar %if 0%{?suse_version} >= 1310 Requires: which %endif -%if 0%{?suse_version} < 1310 Requires: vmware-guest-kmp -%endif +# To prevent autoinstallation on SLES11, exclude supplements from that version +%if 0%{?suse_version} != 1110 Supplements: modalias(pci:v000015ADd*sv*sd*bc*sc*i*) +%endif Requires(pre): %fillup_prereq Requires(pre): %insserv_prereq ExclusiveArch: %ix86 x86_64 +Patch0: xutils-add-cstring.patch +Patch1: enable-gcc46+.patch +Patch2: 0001-Fix-vmxnet-module-on-kernels-3.16.patch +Patch3: 0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch +Patch4: 0003-Fix-f_dentry-msghdr-kernel-3.19.patch +Patch5: 0004-vmhgfs-bdi-kernel-4.0.patch %if %{KMP} %suse_kernel_module_package -n vmware-guest -p %{SOURCE98} xen um %endif -%if %{with_systemd} +%if %{with systemd} %systemd_requires %endif @@ -212,7 +218,7 @@ such as vmware-toolbox-cmd and vmtoolsd (and its plugins). %package -n libvmtools-devel Summary: Open Virtual Machine Tools - Development headers -Group: Development +Group: Development/Libraries/C and C++ Requires: libvmtools0 = %{version} %description -n libvmtools-devel @@ -224,22 +230,12 @@ if you intend to create own plugins for vmtoolsd. chmod -x AUTHORS COPYING ChangeLog NEWS README # fix for an rpmlint warning regarding wrong line feeds sed -i -e "s/\r//" README -%patch1 -p2 -%patch2 -p2 -%patch3 -p2 -%patch4 -p2 -%patch5 -p2 -%patch6 -p2 -%patch7 -p2 -%patch8 -p2 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -KVERMAJ=$(rpm -q kernel-syms --qf %%{version}\n | awk -F. '{print $1}') -KVERMIN=$(rpm -q kernel-syms --qf %%{version}\n | awk -F. '{print $2}') -if [ $KVERMAJ -ge 4 -o $KVERMIN -ge 19 ]; then -%patch13 -p1 -fi +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 %build %if ! %{KMP} @@ -247,12 +243,19 @@ fi # disable warning deprecated-declarations which will raise error because of -Werror # disable warning sizeof-pointer-memaccess which will raise error because of -Werror # (this is because of 'g_static_mutex_init' usage which is now deprecated) +# disable deploypkg due to old versions of libmspack not providing pkgconfig +# disable ssl due to 'discards qualifiers' error in SLES11 +# compile without pkgconfig(xml-security-c), as this is not yet available in OBS +# compile without pkgconfig(xerces-c), which requires xml-security-c to provide vgauth %if 0%{?suse_version} > 1110 export CFLAGS="%{optflags} -Wno-unused-local-typedefs -Wno-unused-but-set-variable -Wno-deprecated-declarations -Wno-sizeof-pointer-memaccess -Wno-cpp -fPIE" export CXXFLAGS="%{optflags} -Wno-unused-local-typedefs -Wno-unused-but-set-variable -Wno-deprecated-declarations -Wno-sizeof-pointer-memaccess -Wno-cpp -fPIE" %else export CFLAGS="%{optflags} -Wno-deprecated-declarations -fPIE" export CXXFLAGS="%{optflags} -Wno-deprecated-declarations -fPIE" +# SUSE versions below 1110 (SLES11 SP4) must use gcc 4.7 to compile under i586 +export CC=gcc-4.7 +export CXX=g++-4.7 %endif export LDFLAGS="-pie" # Required for version 9.4.0 @@ -265,13 +268,19 @@ echo 'HTML_TIMESTAMP=NO' >> docs/api/doxygen.conf %if 0%{?suse_version} < 1230 --without-procps \ %endif +%if ! %{with deploypkg} + --disable-deploypkg \ + --without-ssl \ +%endif %if %{with_X} --with-x \ %else --without-x \ %endif --disable-dependency-tracking \ - --disable-static + --disable-static \ + --without-xmlsecurity \ + --without-xerces make %endif @@ -289,7 +298,13 @@ for flavor in %{flavors_to_build}; do if [ -f ../vmci/Module.symvers ]; then cp ../vmci/Module.symvers . fi - make -C /usr/src/linux-obj/%{_target_cpu}/$flavor modules M=$PWD VM_CCVER=$(gcc -dumpversion) HEADER_DIR="/usr/src/linux-obj/$(uname -i)/default/include" SRCROOT=$PWD OVT_SOURCE_DIR=$TOPDIR + # SUSE versions below 1110 must use gcc 4.7 to compile for i586 + %if 0%{?suse_version} > 1110 + export CC_VER_OPTS="VM_CCVER=$(gcc -dumpversion)" + %else + export CC_VER_OPTS="CC=gcc-4.7 VM_CCVER=4.7" + %endif + make -C /usr/src/linux-obj/%{_target_cpu}/$flavor modules M=$PWD $CC_VER_OPTS HEADER_DIR="/usr/src/linux-obj/$(uname -i)/default/include" SRCROOT=$PWD OVT_SOURCE_DIR=$TOPDIR popd done popd @@ -336,7 +351,7 @@ rm -f docs/api/build/html/FreeSans.ttf mv %{buildroot}%{_sysconfdir}/vmware-tools/vm-support %{buildroot}%{_bindir} # install systemd/sysvinit init scripts and symlinks -%if %{with_systemd} +%if %{with systemd} install -p -m 644 -D %{SOURCE2} %{buildroot}%{_unitdir}/vmtoolsd.service ln -sf service %{buildroot}%{_sbindir}/rcvmtoolsd %else @@ -382,13 +397,13 @@ find %{buildroot} -name '*vmhgfs*' -delete -print %endif %pre -%if %{with_systemd} +%if %{with systemd} %service_add_pre vmtoolsd.service %endif %post /sbin/ldconfig -%if %{with_systemd} +%if %{with systemd} %service_add_post vmtoolsd.service %else %{fillup_and_insserv -Y vmtoolsd} @@ -409,7 +424,7 @@ find %{buildroot} -name '*vmhgfs*' -delete -print %endif %preun -%if %{with_systemd} +%if %{with systemd} %service_del_preun vmtoolsd.service %else # stop service with the old name (if exists) on update (something like %%stop_on_update) @@ -431,7 +446,7 @@ if [ "$1" = "0" -a \ fi %postun -%if %{with_systemd} +%if %{with systemd} %service_del_postun vmtoolsd.service %else %restart_on_update vmtoolsd @@ -486,8 +501,14 @@ rm -rf %{buildroot} %dir %{_sysconfdir}/modprobe.d %config %{_sysconfdir}/modprobe.d/50-vmnics.conf %endif +%if %{with deploypkg} +%{_bindir}/vmware-guestproxycerttool +%{_libdir}/%{name}/plugins/vmsvc/libdeployPkgPlugin.so +%{_libdir}/%{name}/plugins/vmsvc/libgrabbitmqProxy.so +%config(noreplace) %{_sysconfdir}/vmware-tools/guestproxy-ssl.conf +%endif %{_datadir}/%{name}/ -%if %{with_systemd} +%if %{with systemd} %{_unitdir}/vmtoolsd.service %else %{_sysconfdir}/init.d/vmtoolsd @@ -499,7 +520,7 @@ rm -rf %{buildroot} %files desktop %defattr(-, root, root) -%{_sysconfdir}/xdg/autostart/vmware-user-autostart.desktop +%config %{_sysconfdir}/xdg/autostart/vmware-user-autostart.desktop %verify(not mode) %attr(0755, root, root) %{_bindir}/vmware-user-suid-wrapper %{_libdir}/%{name}/plugins/vmusr/ %{_bindir}/vmware-user-autostart-wrapper @@ -511,6 +532,9 @@ rm -rf %{buildroot} %{_libdir}/libvmtools.so.* %{_libdir}/libguestlib.so.* %{_libdir}/libhgfs.so.* +%if %{with deploypkg} +%{_libdir}/libDeployPkg.so.* +%endif %files -n libvmtools-devel %defattr(-,root,root) @@ -518,6 +542,10 @@ rm -rf %{buildroot} %{_includedir}/vmGuestLib %{_libdir}/*.so %{_libdir}/pkgconfig/vmguestlib.pc +%if %{with deploypkg} +%{_includedir}/libDeployPkg +%{_libdir}/pkgconfig/libDeployPkg.pc +%endif %endif %changelog diff --git a/open-vm-tools-linux-3.17.7.patch b/open-vm-tools-linux-3.17.7.patch deleted file mode 100644 index ffaf8fb..0000000 --- a/open-vm-tools-linux-3.17.7.patch +++ /dev/null @@ -1,17 +0,0 @@ -Index: open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/inode.c -=================================================================== ---- open-vm-tools-9.4.6-1770165.orig/modules/linux/vmhgfs/inode.c -+++ open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/inode.c -@@ -1900,7 +1900,11 @@ HgfsPermission(struct inode *inode, - p, - #endif - &inode->i_dentry, -- d_alias) { -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 7) -+ d_alias) { -+#else -+ d_u.d_alias) { -+#endif - int dcount = compat_d_count(dentry); - if (dcount) { - LOG(4, ("Found %s %d \n", dentry->d_name.name, dcount)); diff --git a/open-vm-tools-linux-3.17.patch b/open-vm-tools-linux-3.17.patch deleted file mode 100644 index af778a9..0000000 --- a/open-vm-tools-linux-3.17.patch +++ /dev/null @@ -1,14 +0,0 @@ -Index: open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/page.c -=================================================================== ---- open-vm-tools-9.4.6-1770165.orig/modules/linux/vmhgfs/page.c -+++ open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/page.c -@@ -1385,7 +1385,9 @@ HgfsWbRequestWait(HgfsWbPage *req) // I - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) - return wait_on_bit(&req->wb_flags, - PG_BUSY, -+# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) - HgfsWbRequestWaitUninterruptible, -+# endif - TASK_UNINTERRUPTIBLE); - #else - wait_event(req->wb_queue, diff --git a/open-vm-tools-linux-3.18.0.patch b/open-vm-tools-linux-3.18.0.patch deleted file mode 100644 index 5479b83..0000000 --- a/open-vm-tools-linux-3.18.0.patch +++ /dev/null @@ -1,23 +0,0 @@ -Index: open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/page.c -=================================================================== ---- open-vm-tools-9.4.6-1770165.orig/modules/linux/vmhgfs/page.c -+++ open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/page.c -@@ -1444,9 +1444,18 @@ HgfsWbRequestUnlock(HgfsWbPage *req) // - LOG(6, (KERN_WARNING "VMware Hgfs: HgfsWbRequestUnlock: Invalid unlock attempted\n")); - return; - } -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) - smp_mb__before_clear_bit(); -+#else -+ smp_mb__before_atomic(); -+#endif - clear_bit(PG_BUSY, &req->wb_flags); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) - smp_mb__after_clear_bit(); -+#else -+ smp_mb__after_atomic(); -+#endif -+ - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) - wake_up_bit(&req->wb_flags, PG_BUSY); - #else diff --git a/open-vm-tools-linux-3.19.0.patch b/open-vm-tools-linux-3.19.0.patch deleted file mode 100644 index 585baec..0000000 --- a/open-vm-tools-linux-3.19.0.patch +++ /dev/null @@ -1,379 +0,0 @@ -Index: open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/dir.c -=================================================================== ---- open-vm-tools-9.4.6-1770165.orig/modules/linux/vmhgfs/dir.c -+++ open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/dir.c -@@ -414,7 +414,7 @@ HgfsPackDirOpenRequest(struct file *file - - /* Build full name to send to server. */ - if (HgfsBuildPath(name, req->bufferSize - (requestSize - 1), -- file->f_dentry) < 0) { -+ file->f_path.dentry) < 0) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackDirOpenRequest: build path failed\n")); - return -EINVAL; - } -@@ -560,8 +560,8 @@ HgfsPrivateDirRelease(struct file *file, - int result = 0; - - ASSERT(file); -- ASSERT(file->f_dentry); -- ASSERT(file->f_dentry->d_sb); -+ ASSERT(file->f_path.dentry); -+ ASSERT(file->f_path.dentry->d_sb); - - LOG(6, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: close fh %u\n", handle)); - -@@ -704,7 +704,7 @@ HgfsDirLlseek(struct file *file, - loff_t offset, - int origin) - { -- struct dentry *dentry = file->f_dentry; -+ struct dentry *dentry = file->f_path.dentry; - struct inode *inode = dentry->d_inode; - compat_mutex_t *mtx; - -@@ -853,7 +853,7 @@ HgfsReaddirRefreshEntries(struct file *f - } - - LOG(6, (KERN_DEBUG "VMware hgfs: %s: error: stale handle (%s) return %d)\n", -- __func__, file->f_dentry->d_name.name, result)); -+ __func__, file->f_path.dentry->d_name.name, result)); - return result; - } - -@@ -988,9 +988,9 @@ HgfsReaddirNextEntry(struct file *file, - char *fileName = NULL; - int result; - -- ASSERT(file->f_dentry->d_inode->i_sb); -+ ASSERT(file->f_path.dentry->d_inode->i_sb); - -- si = HGFS_SB_TO_COMMON(file->f_dentry->d_inode->i_sb); -+ si = HGFS_SB_TO_COMMON(file->f_path.dentry->d_inode->i_sb); - *entryIgnore = FALSE; - - /* -@@ -1079,18 +1079,18 @@ HgfsReaddirNextEntry(struct file *file, - */ - if (!strncmp(entryName, ".", sizeof ".")) { - if (!dotAndDotDotIgnore) { -- *entryIno = file->f_dentry->d_inode->i_ino; -+ *entryIno = file->f_path.dentry->d_inode->i_ino; - } else { - *entryIgnore = TRUE; - } - } else if (!strncmp(entryName, "..", sizeof "..")) { - if (!dotAndDotDotIgnore) { -- *entryIno = compat_parent_ino(file->f_dentry); -+ *entryIno = compat_parent_ino(file->f_path.dentry); - } else { - *entryIgnore = TRUE; - } - } else { -- *entryIno = HgfsGetFileInode(&entryAttrs, file->f_dentry->d_inode->i_sb); -+ *entryIno = HgfsGetFileInode(&entryAttrs, file->f_path.dentry->d_inode->i_sb); - } - - if (*entryIgnore) { -@@ -1170,16 +1170,16 @@ HgfsDoReaddir(struct file *file, - ASSERT(filldirCtx); - - if (!file || -- !(file->f_dentry) || -- !(file->f_dentry->d_inode)) { -+ !(file->f_path.dentry) || -+ !(file->f_path.dentry->d_inode)) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsReaddir: null input\n")); - return -EFAULT; - } - - LOG(4, (KERN_DEBUG "VMware hgfs: %s(%s, inum %lu, pos %Lu)\n", - __func__, -- file->f_dentry->d_name.name, -- file->f_dentry->d_inode->i_ino, -+ file->f_path.dentry->d_name.name, -+ file->f_path.dentry->d_inode->i_ino, - *currentPos)); - - /* -@@ -1294,7 +1294,7 @@ HgfsReaddir(struct file *file, / - /* If either dot and dotdot are filled in for us we can exit. */ - if (!dir_emit_dots(file, ctx)) { - LOG(6, (KERN_DEBUG "VMware hgfs: %s: dir_emit_dots(%s, @ %Lu)\n", -- __func__, file->f_dentry->d_name.name, ctx->pos)); -+ __func__, file->f_path.dentry->d_name.name, ctx->pos)); - return 0; - } - -@@ -1464,8 +1464,8 @@ HgfsDirRelease(struct inode *inode, // - - ASSERT(inode); - ASSERT(file); -- ASSERT(file->f_dentry); -- ASSERT(file->f_dentry->d_sb); -+ ASSERT(file->f_path.dentry); -+ ASSERT(file->f_path.dentry->d_sb); - - handle = FILE_GET_FI_P(file)->handle; - -Index: open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/file.c -=================================================================== ---- open-vm-tools-9.4.6-1770165.orig/modules/linux/vmhgfs/file.c -+++ open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/file.c -@@ -362,7 +362,7 @@ HgfsPackOpenRequest(struct inode *inode, - /* Build full name to send to server. */ - if (HgfsBuildPath(name, - req->bufferSize - (requestSize - 1), -- file->f_dentry) < 0) { -+ file->f_path.dentry) < 0) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackOpenRequest: build path " - "failed\n")); - return -EINVAL; -@@ -589,8 +589,8 @@ HgfsOpen(struct inode *inode, // IN: In - ASSERT(inode); - ASSERT(inode->i_sb); - ASSERT(file); -- ASSERT(file->f_dentry); -- ASSERT(file->f_dentry->d_inode); -+ ASSERT(file->f_path.dentry); -+ ASSERT(file->f_path.dentry->d_inode); - - iinfo = INODE_GET_II_P(inode); - -@@ -667,7 +667,7 @@ HgfsOpen(struct inode *inode, // IN: In - * This is not the root of our file system so there should always - * be a parent. - */ -- ASSERT(file->f_dentry->d_parent); -+ ASSERT(file->f_path.dentry->d_parent); - - /* - * Here we obtain a reference on the parent to make sure it doesn't -@@ -682,10 +682,10 @@ HgfsOpen(struct inode *inode, // IN: In - * We could do this if we were willing to give up support for - * O_EXCL on 2.4 kernels. - */ -- dparent = dget(file->f_dentry->d_parent); -+ dparent = dget(file->f_path.dentry->d_parent); - iparent = dparent->d_inode; - -- HgfsSetUidGid(iparent, file->f_dentry, -+ HgfsSetUidGid(iparent, file->f_path.dentry, - current_fsuid(), current_fsgid()); - - dput(dparent); -@@ -745,7 +745,7 @@ out: - * forcing a revalidate on one will not force it on any others. - */ - if (result != 0 && iinfo->createdAndUnopened == TRUE) { -- HgfsDentryAgeForce(file->f_dentry); -+ HgfsDentryAgeForce(file->f_path.dentry); - } - return result; - } -@@ -781,12 +781,12 @@ HgfsAioRead(struct kiocb *iocb, // - - ASSERT(iocb); - ASSERT(iocb->ki_filp); -- ASSERT(iocb->ki_filp->f_dentry); -+ ASSERT(iocb->ki_filp->f_path.dentry); - ASSERT(iov); - - LOG(6, (KERN_DEBUG "VMware hgfs: HgfsAioRead: was called\n")); - -- result = HgfsRevalidate(iocb->ki_filp->f_dentry); -+ result = HgfsRevalidate(iocb->ki_filp->f_path.dentry); - if (result) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsAioRead: invalid dentry\n")); - goto out; -@@ -832,10 +832,10 @@ HgfsAioWrite(struct kiocb *iocb, // - - ASSERT(iocb); - ASSERT(iocb->ki_filp); -- ASSERT(iocb->ki_filp->f_dentry); -+ ASSERT(iocb->ki_filp->f_path.dentry); - ASSERT(iov); - -- writeDentry = iocb->ki_filp->f_dentry; -+ writeDentry = iocb->ki_filp->f_path.dentry; - iinfo = INODE_GET_II_P(writeDentry->d_inode); - - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsAioWrite(%s/%s, %lu@%Ld)\n", -@@ -915,14 +915,14 @@ HgfsRead(struct file *file, // IN: Fil - int result; - - ASSERT(file); -- ASSERT(file->f_dentry); -+ ASSERT(file->f_path.dentry); - ASSERT(buf); - ASSERT(offset); - - LOG(6, (KERN_DEBUG "VMware hgfs: HgfsRead: read %Zu bytes from fh %u " - "at offset %Lu\n", count, FILE_GET_FI_P(file)->handle, *offset)); - -- result = HgfsRevalidate(file->f_dentry); -+ result = HgfsRevalidate(file->f_path.dentry); - if (result) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsRead: invalid dentry\n")); - goto out; -@@ -968,15 +968,15 @@ HgfsWrite(struct file *file, // IN: - int result; - - ASSERT(file); -- ASSERT(file->f_dentry); -- ASSERT(file->f_dentry->d_inode); -+ ASSERT(file->f_path.dentry); -+ ASSERT(file->f_path.dentry->d_inode); - ASSERT(buf); - ASSERT(offset); - - LOG(6, (KERN_DEBUG "VMware hgfs: HgfsWrite: write %Zu bytes to fh %u " - "at offset %Lu\n", count, FILE_GET_FI_P(file)->handle, *offset)); - -- result = HgfsRevalidate(file->f_dentry); -+ result = HgfsRevalidate(file->f_path.dentry); - if (result) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsWrite: invalid dentry\n")); - goto out; -@@ -1020,12 +1020,12 @@ HgfsSeek(struct file *file, // IN: Fil - loff_t result = -1; - - ASSERT(file); -- ASSERT(file->f_dentry); -+ ASSERT(file->f_path.dentry); - - LOG(6, (KERN_DEBUG "VMware hgfs: HgfsSeek: seek to %Lu bytes from fh %u " - "from position %d\n", offset, FILE_GET_FI_P(file)->handle, origin)); - -- result = (loff_t) HgfsRevalidate(file->f_dentry); -+ result = (loff_t) HgfsRevalidate(file->f_path.dentry); - if (result) { - LOG(6, (KERN_DEBUG "VMware hgfs: HgfsSeek: invalid dentry\n")); - goto out; -@@ -1108,8 +1108,8 @@ HgfsFlush(struct file *file - 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)); -+ file->f_path.dentry->d_parent->d_name.name, -+ file->f_path.dentry->d_name.name)); - - if ((file->f_mode & FMODE_WRITE) == 0) { - goto exit; -@@ -1121,7 +1121,7 @@ HgfsFlush(struct file *file - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) - ret = vfs_fsync(file, 0); - #else -- ret = HgfsDoFsync(file->f_dentry->d_inode); -+ ret = HgfsDoFsync(file->f_path.dentry->d_inode); - #endif - - exit: -@@ -1177,13 +1177,13 @@ HgfsFsync(struct file *file, // IN: Fil - #endif - - 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, -+ file->f_path.dentry->d_parent->d_name.name, -+ file->f_path.dentry->d_name.name, - startRange, endRange, - datasync)); - - /* Flush writes to the server and return any errors */ -- inode = file->f_dentry->d_inode; -+ inode = file->f_path.dentry->d_inode; - #if defined VMW_FSYNC_31 - ret = filemap_write_and_wait_range(inode->i_mapping, startRange, endRange); - #else -@@ -1223,11 +1223,11 @@ HgfsMmap(struct file *file, // IN: File - - ASSERT(file); - ASSERT(vma); -- ASSERT(file->f_dentry); -+ ASSERT(file->f_path.dentry); - - LOG(6, (KERN_DEBUG "VMware hgfs: HgfsMmap: was called\n")); - -- result = HgfsRevalidate(file->f_dentry); -+ result = HgfsRevalidate(file->f_path.dentry); - if (result) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsMmap: invalid dentry\n")); - goto out; -@@ -1268,8 +1268,8 @@ HgfsRelease(struct inode *inode, // IN: - - ASSERT(inode); - ASSERT(file); -- ASSERT(file->f_dentry); -- ASSERT(file->f_dentry->d_sb); -+ ASSERT(file->f_path.dentry); -+ ASSERT(file->f_path.dentry->d_sb); - - handle = FILE_GET_FI_P(file)->handle; - LOG(6, (KERN_DEBUG "VMware hgfs: HgfsRelease: close fh %u\n", handle)); -@@ -1398,14 +1398,14 @@ HgfsSendfile(struct file *file, // IN - ssize_t result; - - ASSERT(file); -- ASSERT(file->f_dentry); -+ ASSERT(file->f_path.dentry); - ASSERT(target); - ASSERT(offset); - ASSERT(actor); - - LOG(6, (KERN_DEBUG "VMware hgfs: HgfsSendfile: was called\n")); - -- result = HgfsRevalidate(file->f_dentry); -+ result = HgfsRevalidate(file->f_path.dentry); - if (result) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsSendfile: invalid dentry\n")); - goto out; -@@ -1452,11 +1452,11 @@ HgfsSpliceRead(struct file *file, - ssize_t result; - - ASSERT(file); -- ASSERT(file->f_dentry); -+ ASSERT(file->f_path.dentry); - - LOG(6, (KERN_DEBUG "VMware hgfs: HgfsSpliceRead: was called\n")); - -- result = HgfsRevalidate(file->f_dentry); -+ result = HgfsRevalidate(file->f_path.dentry); - if (result) { - LOG(4, (KERN_DEBUG "VMware hgfs: HgfsSpliceRead: invalid dentry\n")); - goto out; -Index: open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/fsutil.c -=================================================================== ---- open-vm-tools-9.4.6-1770165.orig/modules/linux/vmhgfs/fsutil.c -+++ open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/fsutil.c -@@ -1936,7 +1936,7 @@ HgfsCreateFileInfo(struct file *file, / - - ASSERT(file); - -- inodeInfo = INODE_GET_II_P(file->f_dentry->d_inode); -+ inodeInfo = INODE_GET_II_P(file->f_path.dentry->d_inode); - ASSERT(inodeInfo); - - /* Get the mode of the opened file. */ -Index: open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/tcp.c -=================================================================== ---- open-vm-tools-9.4.6-1770165.orig/modules/linux/vmhgfs/tcp.c -+++ open-vm-tools-9.4.6-1770165/modules/linux/vmhgfs/tcp.c -@@ -250,7 +250,7 @@ HgfsSocketRecvMsg(struct socket *socket, - size_t bufferLen) // IN: Buffer length - { - struct iovec iov; -- struct msghdr msg; -+ struct user_msghdr msg; - int ret; - int flags = MSG_DONTWAIT | MSG_NOSIGNAL; - mm_segment_t oldfs = get_fs(); -@@ -765,7 +765,7 @@ HgfsSocketSendMsg(struct socket *socket, - size_t bufferLen) // IN: Buffer length - { - struct iovec iov; -- struct msghdr msg; -+ struct user_msghdr msg; - int ret = 0; - int i = 0; - mm_segment_t oldfs = get_fs(); diff --git a/open-vm-tools.changes b/open-vm-tools.changes index cee1e57..70d7ac2 100644 --- a/open-vm-tools.changes +++ b/open-vm-tools.changes @@ -1,15 +1,88 @@ +------------------------------------------------------------------- +Mon May 21 23:04:48 UTC 2015 - mlatimer@suse.com + +- Build using gcc4.7 for SLES11 environments to avoid mul64.h + dependency problem for i586 architectures +- Include cstddef to resolve compile problems under gcc4.7 + enable-gcc46+.patch +- Ensure xutils builds properly under older versions of gcc + xutils-add-cstring.patch +- Prevent files on shared folders from being truncated to 0 bytes + under 4.0 kernel + 0004-vmhgfs-bdi-kernel-4.0.patch + +------------------------------------------------------------------- +Wed May 18 00:01:07 UTC 2015 - mlatimer@suse.com + +- Update to open-vm-tools-9.10.0-2476743: + + vgauth added + + deploypkg added + + guest proxycerttool added + + hgfs and vmci/vsock fixes + + asyncsocket enhancements + + library fixes and improvements + + locking and logging fixes and improvements + + foundry fixes + + vm-support script fixes +- Replace obsolete patches with rebased versions (from ArchLinux): + - Drop 0001-Remove-unused-DEPRECATED-macro.patch + - Drop 0002-Conditionally-define-g_info-macro.patch + - Drop 0003-Add-kuid_t-kgid_t-compatibility-layer.patch + - Drop 0004-Use-new-link-helpers.patch + - Drop 0005-Update-hgfs-file-operations-for-newer-kernels.patch + - Drop 0006-Fix-vmxnet-module-on-kernels-3.16.patch + - Drop 0007-Fix-vmhgfs-module-on-kernels-3.16.patch + - Drop 0008-Fix-segfault-in-vmhgfs.patch + - Drop open-vm-tools-linux-3.17.7.patch + - Drop open-vm-tools-linux-3.17.patch + - Drop open-vm-tools-linux-3.18.0.patch + - Add 0001-Fix-vmxnet-module-on-kernels-3.16.patch + - Add 0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch + - Add 0003-Fix-f_dentry-msghdr-kernel-3.19.patch +- Add libmspack BuildRequires (deploypkg). +- Add openssl BuildRequires (grabbitmqproxy and vgauth). +- Compile using --without-xmlsecurity and --without-xerces as + pkgconfig(xml-security-c) is not yet available in the build service, + (disables vgauth support). +- Disable deploypkg for older versions of SLES and openSUSE. +- Disable ssl for older versions of SLES and openSUSE (disables + grabbitmqproxy and vgauth). +- Update spec file to be compatible with SLES and openSUSE. + ------------------------------------------------------------------- Tue May 5 14:31:19 UTC 2015 - dimstar@opensuse.org - Handle kernel 4.0: we can't just compare the 'minor' part of the version anymore when applying patches. +------------------------------------------------------------------- +Thu Mar 12 00:05:55 UTC 2015 - mlatimer@suse.com + +- Prevent autoinstallation of open-vm-tools in SLES11SP4 environments + due to potential conflict with VMware tools. (bsc#921618) + ------------------------------------------------------------------- Thu Feb 19 13:35:44 UTC 2015 - dimstar@opensuse.org - Add open-vm-tools-linux-3.19.0.patch: Fix building of vmhgfs with Kernel 3.19.0+. +------------------------------------------------------------------- +Wed Jan 21 23:58:08 UTC 2015 - mlatimer@suse.com + +- Remove modprobe of deprecated vmsync module from SysV init script. + +------------------------------------------------------------------- +Fri Jan 16 02:55:39 UTC 2015 - mlatimer@suse.com + +- Update specfile to ensure kernel modules are not built or required + for SLES11SP4 and SLES12. + +------------------------------------------------------------------- +Fri Jan 9 23:57:56 UTC 2015 - mlatimer@suse.com + +- Use fuse-devel instead of pkgconfig(fuse) in SLES11SP4. + ------------------------------------------------------------------- Mon Jan 5 10:07:50 UTC 2015 - dimstar@opensuse.org diff --git a/open-vm-tools.spec b/open-vm-tools.spec index 02dde65..c783b3f 100644 --- a/open-vm-tools.spec +++ b/open-vm-tools.spec @@ -17,32 +17,36 @@ # -%define with_systemd 1 -%define KMP 0 +%define KMP 0 -# The vmhgfs modules is used with all versions -%define vmhgfs vmhgfs - -# disable systemd if before 13.1 -%if 0%{suse_version} < 1310 -%define with_systemd 0 +# systemd and deploypkg should be enabled by default on versions >= 13.1 +%if 0%{?suse_version} >= 1310 +%bcond_without systemd +%bcond_without deploypkg +%else +%bcond_with systemd +%bcond_with deploypkg %endif +# The vmhgfs module is currently built for all versions +# (Shared Folders are not supported under ESX/ESXi, so this driver is not necessary for SLES11/12) +%define vmhgfs vmhgfs + # exclude AMD PCnet32 LANCE pci.id from Supplements list [bnc#397554] %define __find_supplements sh -c '/usr/lib/rpm/find-supplements %{name} | grep -v pci:v00001022d00002000' -%if 0%{?suse_version} <= 1230 -# Modules to be built up to openSUSE 12.3, possibly not building on newer versions. +# Modules to be built up to openSUSE 12.3 (excluding SLES11), possibly not building on newer versions. +%if 0%{?suse_version} <= 1230 && 0%{?suse_version} != 1110 %define vm_modules1230 vmci vsock %endif -%if 0%{?suse_version} <= 1220 -# Modules to be built up to openSUSE 12.1, possibly not building on newer versions. +%if 0%{?suse_version} <= 1220 && 0%{?suse_version} != 1110 +# Modules to be built up to openSUSE 12.1 (excluding SLES11), possibly not building on newer versions. %define vm_modules1220 vmsync %endif -%if 0%{?suse_version} <= 1210 -# Modules to be built up to openSUSE 12.1, possibly not building on newer versions. +%if 0%{?suse_version} <= 1210 && 0%{?suse_version} != 1110 +# Modules to be built up to openSUSE 12.1 (excluding SLES11), possibly not building on newer versions. %define vm_modules1210 vmxnet %endif @@ -54,14 +58,14 @@ Name: open-vm-tools %define tarname open-vm-tools -Version: 9.4.6 +Version: 9.10.0 Release: 0 -%define svn_rev 1770165 +%define svn_rev 2476743 Summary: Open Virtual Machine Tools License: BSD-3-Clause and GPL-2.0 and LGPL-2.1 Group: System/Emulators/PC Url: http://open-vm-tools.sourceforge.net/ -Source: http://sourceforge.net/projects/open-vm-tools/files/open-vm-tools/stable-9.4.x/%{tarname}-%{version}-%{svn_rev}.tar.gz +Source: http://sourceforge.net/projects/open-vm-tools/files/open-vm-tools/stable-9.10.0/%{tarname}-%{version}-%{svn_rev}.tar.gz Source1: vmtoolsd Source2: vmtoolsd.service Source3: vmware-user-autostart.desktop @@ -69,25 +73,19 @@ Source5: vmware-user-autostart-wrapper Source6: open-vm-tools-modprobe.conf Source7: tools.conf Source98: preamble -Patch1: 0001-Remove-unused-DEPRECATED-macro.patch -Patch2: 0002-Conditionally-define-g_info-macro.patch -Patch3: 0003-Add-kuid_t-kgid_t-compatibility-layer.patch -Patch4: 0004-Use-new-link-helpers.patch -Patch5: 0005-Update-hgfs-file-operations-for-newer-kernels.patch -Patch6: 0006-Fix-vmxnet-module-on-kernels-3.16.patch -Patch7: 0007-Fix-vmhgfs-module-on-kernels-3.16.patch -Patch8: 0008-Fix-segfault-in-vmhgfs.patch -Patch10: open-vm-tools-linux-3.17.patch -Patch11: open-vm-tools-linux-3.17.7.patch -Patch12: open-vm-tools-linux-3.18.0.patch -Patch13: open-vm-tools-linux-3.19.0.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build +# SUSE versions below 1110 (SLES11 SP4) must use gcc 4.7 to compile under i586 +%if 0%{?suse_version} <= 1110 +BuildRequires: gcc47 +BuildRequires: gcc47-c++ +%else BuildRequires: gcc-c++ +%endif # don't use pkgconfig(gtk+-2.0) so we can build on SLE BuildRequires: gtk2-devel BuildRequires: gtkmm2-devel # Only require kernel packages if kernel modules are being built -%if "%{?vm_modules}" != " " && %{KMP} +%if %{KMP} BuildRequires: kernel-source BuildRequires: kernel-syms BuildRequires: module-init-tools @@ -97,12 +95,13 @@ BuildRequires: automake BuildRequires: doxygen BuildRequires: libdnet-devel BuildRequires: libicu-devel +BuildRequires: libmspack-devel BuildRequires: libtool +BuildRequires: openssl-devel BuildRequires: pam-devel BuildRequires: pcre-devel BuildRequires: update-desktop-files BuildRequires: xorg-x11-devel -BuildRequires: pkgconfig(fuse) # libprocps is required with 12.3 and above %if 0%{?suse_version} >= 1230 BuildRequires: procps-devel @@ -117,19 +116,26 @@ Requires: tar %if 0%{?suse_version} >= 1310 Requires: which %endif -%if 0%{?suse_version} < 1310 Requires: vmware-guest-kmp -%endif +# To prevent autoinstallation on SLES11, exclude supplements from that version +%if 0%{?suse_version} != 1110 Supplements: modalias(pci:v000015ADd*sv*sd*bc*sc*i*) +%endif Requires(pre): %fillup_prereq Requires(pre): %insserv_prereq ExclusiveArch: %ix86 x86_64 +Patch0: xutils-add-cstring.patch +Patch1: enable-gcc46+.patch +Patch2: 0001-Fix-vmxnet-module-on-kernels-3.16.patch +Patch3: 0002-Fix-d_alias-to-d_u.d_alias-for-kernel-3.18.patch +Patch4: 0003-Fix-f_dentry-msghdr-kernel-3.19.patch +Patch5: 0004-vmhgfs-bdi-kernel-4.0.patch %if %{KMP} %suse_kernel_module_package -n vmware-guest -p %{SOURCE98} xen um %endif -%if %{with_systemd} +%if %{with systemd} %systemd_requires %endif @@ -212,7 +218,7 @@ such as vmware-toolbox-cmd and vmtoolsd (and its plugins). %package -n libvmtools-devel Summary: Open Virtual Machine Tools - Development headers -Group: Development +Group: Development/Libraries/C and C++ Requires: libvmtools0 = %{version} %description -n libvmtools-devel @@ -224,22 +230,12 @@ if you intend to create own plugins for vmtoolsd. chmod -x AUTHORS COPYING ChangeLog NEWS README # fix for an rpmlint warning regarding wrong line feeds sed -i -e "s/\r//" README -%patch1 -p2 -%patch2 -p2 -%patch3 -p2 -%patch4 -p2 -%patch5 -p2 -%patch6 -p2 -%patch7 -p2 -%patch8 -p2 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -KVERMAJ=$(rpm -q kernel-syms --qf %%{version}\n | awk -F. '{print $1}') -KVERMIN=$(rpm -q kernel-syms --qf %%{version}\n | awk -F. '{print $2}') -if [ $KVERMAJ -ge 4 -o $KVERMIN -ge 19 ]; then -%patch13 -p1 -fi +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 %build %if ! %{KMP} @@ -247,12 +243,19 @@ fi # disable warning deprecated-declarations which will raise error because of -Werror # disable warning sizeof-pointer-memaccess which will raise error because of -Werror # (this is because of 'g_static_mutex_init' usage which is now deprecated) +# disable deploypkg due to old versions of libmspack not providing pkgconfig +# disable ssl due to 'discards qualifiers' error in SLES11 +# compile without pkgconfig(xml-security-c), as this is not yet available in OBS +# compile without pkgconfig(xerces-c), which requires xml-security-c to provide vgauth %if 0%{?suse_version} > 1110 export CFLAGS="%{optflags} -Wno-unused-local-typedefs -Wno-unused-but-set-variable -Wno-deprecated-declarations -Wno-sizeof-pointer-memaccess -Wno-cpp -fPIE" export CXXFLAGS="%{optflags} -Wno-unused-local-typedefs -Wno-unused-but-set-variable -Wno-deprecated-declarations -Wno-sizeof-pointer-memaccess -Wno-cpp -fPIE" %else export CFLAGS="%{optflags} -Wno-deprecated-declarations -fPIE" export CXXFLAGS="%{optflags} -Wno-deprecated-declarations -fPIE" +# SUSE versions below 1110 (SLES11 SP4) must use gcc 4.7 to compile under i586 +export CC=gcc-4.7 +export CXX=g++-4.7 %endif export LDFLAGS="-pie" # Required for version 9.4.0 @@ -265,13 +268,19 @@ echo 'HTML_TIMESTAMP=NO' >> docs/api/doxygen.conf %if 0%{?suse_version} < 1230 --without-procps \ %endif +%if ! %{with deploypkg} + --disable-deploypkg \ + --without-ssl \ +%endif %if %{with_X} --with-x \ %else --without-x \ %endif --disable-dependency-tracking \ - --disable-static + --disable-static \ + --without-xmlsecurity \ + --without-xerces make %endif @@ -289,7 +298,13 @@ for flavor in %{flavors_to_build}; do if [ -f ../vmci/Module.symvers ]; then cp ../vmci/Module.symvers . fi - make -C /usr/src/linux-obj/%{_target_cpu}/$flavor modules M=$PWD VM_CCVER=$(gcc -dumpversion) HEADER_DIR="/usr/src/linux-obj/$(uname -i)/default/include" SRCROOT=$PWD OVT_SOURCE_DIR=$TOPDIR + # SUSE versions below 1110 must use gcc 4.7 to compile for i586 + %if 0%{?suse_version} > 1110 + export CC_VER_OPTS="VM_CCVER=$(gcc -dumpversion)" + %else + export CC_VER_OPTS="CC=gcc-4.7 VM_CCVER=4.7" + %endif + make -C /usr/src/linux-obj/%{_target_cpu}/$flavor modules M=$PWD $CC_VER_OPTS HEADER_DIR="/usr/src/linux-obj/$(uname -i)/default/include" SRCROOT=$PWD OVT_SOURCE_DIR=$TOPDIR popd done popd @@ -336,7 +351,7 @@ rm -f docs/api/build/html/FreeSans.ttf mv %{buildroot}%{_sysconfdir}/vmware-tools/vm-support %{buildroot}%{_bindir} # install systemd/sysvinit init scripts and symlinks -%if %{with_systemd} +%if %{with systemd} install -p -m 644 -D %{SOURCE2} %{buildroot}%{_unitdir}/vmtoolsd.service ln -sf service %{buildroot}%{_sbindir}/rcvmtoolsd %else @@ -382,13 +397,13 @@ find %{buildroot} -name '*vmhgfs*' -delete -print %endif %pre -%if %{with_systemd} +%if %{with systemd} %service_add_pre vmtoolsd.service %endif %post /sbin/ldconfig -%if %{with_systemd} +%if %{with systemd} %service_add_post vmtoolsd.service %else %{fillup_and_insserv -Y vmtoolsd} @@ -409,7 +424,7 @@ find %{buildroot} -name '*vmhgfs*' -delete -print %endif %preun -%if %{with_systemd} +%if %{with systemd} %service_del_preun vmtoolsd.service %else # stop service with the old name (if exists) on update (something like %%stop_on_update) @@ -431,7 +446,7 @@ if [ "$1" = "0" -a \ fi %postun -%if %{with_systemd} +%if %{with systemd} %service_del_postun vmtoolsd.service %else %restart_on_update vmtoolsd @@ -486,8 +501,14 @@ rm -rf %{buildroot} %dir %{_sysconfdir}/modprobe.d %config %{_sysconfdir}/modprobe.d/50-vmnics.conf %endif +%if %{with deploypkg} +%{_bindir}/vmware-guestproxycerttool +%{_libdir}/%{name}/plugins/vmsvc/libdeployPkgPlugin.so +%{_libdir}/%{name}/plugins/vmsvc/libgrabbitmqProxy.so +%config(noreplace) %{_sysconfdir}/vmware-tools/guestproxy-ssl.conf +%endif %{_datadir}/%{name}/ -%if %{with_systemd} +%if %{with systemd} %{_unitdir}/vmtoolsd.service %else %{_sysconfdir}/init.d/vmtoolsd @@ -499,7 +520,7 @@ rm -rf %{buildroot} %files desktop %defattr(-, root, root) -%{_sysconfdir}/xdg/autostart/vmware-user-autostart.desktop +%config %{_sysconfdir}/xdg/autostart/vmware-user-autostart.desktop %verify(not mode) %attr(0755, root, root) %{_bindir}/vmware-user-suid-wrapper %{_libdir}/%{name}/plugins/vmusr/ %{_bindir}/vmware-user-autostart-wrapper @@ -511,6 +532,9 @@ rm -rf %{buildroot} %{_libdir}/libvmtools.so.* %{_libdir}/libguestlib.so.* %{_libdir}/libhgfs.so.* +%if %{with deploypkg} +%{_libdir}/libDeployPkg.so.* +%endif %files -n libvmtools-devel %defattr(-,root,root) @@ -518,6 +542,10 @@ rm -rf %{buildroot} %{_includedir}/vmGuestLib %{_libdir}/*.so %{_libdir}/pkgconfig/vmguestlib.pc +%if %{with deploypkg} +%{_includedir}/libDeployPkg +%{_libdir}/pkgconfig/libDeployPkg.pc +%endif %endif %changelog diff --git a/vmtoolsd b/vmtoolsd index 62ab72c..4feb6fb 100644 --- a/vmtoolsd +++ b/vmtoolsd @@ -88,7 +88,6 @@ case "$1" in -o subtype=vmware-vmblock,default_permissions,allow_other \ /var/run/vmblock-fuse modprobe $VMBALLOON - modprobe vmsync ## Start daemon with startproc(8). If this fails ## the return value is set appropriately by startproc. /sbin/startproc $VMTOOLSD_BIN @@ -109,7 +108,6 @@ case "$1" in fi /sbin/killproc -TERM $VMTOOLSD_BIN umount /var/run/vmblock-fuse || : - modprobe -r vmsync || : modprobe -r $VMBALLOON || : # Remember status and be verbose diff --git a/xutils-add-cstring.patch b/xutils-add-cstring.patch new file mode 100644 index 0000000..7a11d12 --- /dev/null +++ b/xutils-add-cstring.patch @@ -0,0 +1,12 @@ +Index: open-vm-tools-9.10.0-2476743/services/plugins/dndcp/xutils/xutils.cc +=================================================================== +--- open-vm-tools-9.10.0-2476743.orig/services/plugins/dndcp/xutils/xutils.cc ++++ open-vm-tools-9.10.0-2476743/services/plugins/dndcp/xutils/xutils.cc +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + extern "C" { + #include "vm_assert.h"