无法为内核3.19构建vmnet。

因为this answer仅适用于3.13内核,所以我想分享一个解决方案,用于解决3.19及早期版本的内核下发生的Failed to build vmnet问题。因此,这不是我的实际问题,只是希望能够帮助未来的读者。

问题

当我第一次尝试运行VMware Workstation或VMware Player时,它需要在内核级别部署一些软件包,但是出现了以下错误。

Failed to build vmnet. Failed to execute the build command.

我应该怎么解决这个问题?


请注意,这似乎不再是问题。截至今天在Linux系统上进行的全新安装中,我无法复制这个构建问题。 - Thomas Ward
3个回答

解决方案
  1. 进入vmware模块源代码目录。[1]

    cd /usr/lib/vmware/modules/source
    
  2. 解压缩vmnet模块。[1]

    sudo tar -xvf vmnet.tar
    
  3. 用您喜欢的文本编辑器打开vmnet-only/driver.c

    sudo gedit vmnet-only/driver.c
    
  4. 在第267行附近,更改以下内容[2]

    if (filp && filp->f_op && filp->f_op->ioctl == VNetFileOpIoctl) {
        ret = VNetFileOpIoctl(filp->f_dentry->d_inode, filp, iocmd, ioarg);
    }
    return ret;        
    

    #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
    if (filp && filp->f_op && filp->f_op->ioctl == VNetFileOpIoctl) {
        ret = VNetFileOpIoctl(filp->f_dentry->d_inode, filp, iocmd, ioarg);
    }
    return ret;
    #else 
    if (filp && filp->f_op && filp->f_op->ioctl == VNetFileOpIoctl) {
        ret = VNetFileOpIoctl(filp->f_path.dentry->d_inode, filp, iocmd, ioarg);
    }
    return ret;
    #endif
    
  5. 在第1194行附近,更改以下内容[2]

    if (filp && filp->f_dentry) {
        inode = filp->f_dentry->d_inode;
    }
    err = VNetFileOpIoctl(inode, filp, iocmd, ioarg);
    return err;
    

    #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
    if (filp && filp->f_dentry) {
        inode = filp->f_dentry->d_inode;
    }
    err = VNetFileOpIoctl(inode, filp, iocmd, ioarg);
    return err;
    #else 
    if (filp && filp->f_path.dentry) {
        inode = filp->f_path.dentry->d_inode;
    }
    err = VNetFileOpIoctl(inode, filp, iocmd, ioarg);
    return err;
    #endif
    
  6. 保存此文件,然后打开文件vmnet-only/userif.c

    sudo gedit vmnet-only/userif.c
    
  7. 在第526行附近,更改以下内容[2]

    return skb_copy_datagram_iovec(skb, 0, &iov, len);
    

    #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
    return skb_copy_datagram_iovec(skb, 0, &iov, len);
    #else
    struct iov_iter to;
    iov_iter_init(&to, READ, &iov, 1, len);
    return skb_copy_datagram_iter(skb, 0, &to, len);
    #endif
    
  8. 保存此文件,然后重新打包模块。[1]

    sudo tar -uvf vmnet.tar vmnet-only
    
  9. 删除先前的工作目录。[1]

    sudo rm -r vmnet-only
    
  10. 再次运

    参考资料

    [1] :来自answer的一个回答。
    [2] :来自Robert Gadsdon的一篇写作


2非常感谢您写得如此出色的帖子。这解决了我的问题。 - ChosSimbaOne

感谢budiap发布的Workstation 10补丁!只是花了我一些时间才弄清楚您需要使用该代码将其应用到一个补丁文件中。以下是我在vmware工作站论坛上发布的帖子。
好的!我明白了。在Ubuntu15.04或其他-buntu上的Workstation 10。我在Xubuntu 15.04内核3.19.0-18-generic上进行了测试。
为Workstation 10创建了新的pastie(10215458)来发布补丁。
在安装完Workstation 10.06之后,具体来说是VMware-Workstation-Full-10.0.6-2700073.x86_64.bundle。
必须以root身份运行,但基本上可以复制/粘贴。 curl http://pastie.org/pastes/10215458/download -o /tmp/vmnet-3.19.patch_ws10
cd /usr/lib/vmware/modules/source
tar -xf vmnet.tar
patch -p0 -i /tmp/vmnet-3.19.patch_ws10
mv vmnet.tar vmnet.tar.SAVED
tar -cf vmnet.tar vmnet-only
rm -r vmnet-only
vmware-modconfig --console --install-all

真不敢相信我是第一个点赞这个!这个回答太棒了,太棒了。(希望你不介意我的建议修改。) - Mark E. Haase
1我刚刚尝试了在Ubuntu 15.10上使用Kernel 4.2,但是没有成功。我找不到任何修补程序来使WS10在15.10上工作,只能回退到使用Kernel 3.19的14 LTS版本。 - Timothy C. Quinn
和@JavaScriptDude一样。如何为4.4内核打补丁? - akahunahi
@Ligemer - 我已经放弃了在Linux上尝试让旧版本的VMware Workstation工作,并转而使用VirtualBox,这个决定对我来说非常好。对于Linux和VMware,我认为唯一实际的解决方案是购买最新Workstation版本的许可证,或者只使用免费的VMware Player,并采用像ZFS或BTRFS这样的外部快照机制。 - Timothy C. Quinn
谢谢 @JavaScriptDude - 同意。我最终也选择了虚拟机。我很开心 :-) 希望这些评论能帮助其他Linux用户。愉快编码。 - akahunahi

如果您正在运行VMware Workstation 10,请应用此补丁以使其在Kernel 3.19上正常工作。
diff -rupN vmnet-only/driver.c vmnet-only-modified/driver.c
--- vmnet-only/driver.c 2015-01-17 09:25:58.000000000 +0800
+++ vmnet-only-modified/driver.c    2015-05-07 14:53:18.272218785 +0800
@@ -265,10 +265,17 @@ LinuxDriver_Ioctl32_Handler(unsigned int
 {
    int ret = -ENOTTY;

+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
    if (filp && filp->f_op && filp->f_op->ioctl == VNetFileOpIoctl) {
       ret = VNetFileOpIoctl(filp->f_dentry->d_inode, filp, iocmd, ioarg);
    }
    return ret;
+#else 
+   if (filp && filp->f_op && filp->f_op->ioctl == VNetFileOpIoctl) {
+      ret = VNetFileOpIoctl(filp->f_path.dentry->d_inode, filp, iocmd, ioarg);
+   }
+   return ret;
+#endif
 }


@@ -1191,11 +1198,19 @@ VNetFileOpUnlockedIoctl(struct file    *
    struct inode *inode = NULL;
    long err;

+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
    if (filp && filp->f_dentry) {
       inode = filp->f_dentry->d_inode;
    }
    err = VNetFileOpIoctl(inode, filp, iocmd, ioarg);
    return err;
+#else 
+   if (filp && filp->f_path.dentry) {
+      inode = filp->f_path.dentry->d_inode;
+   }
+   err = VNetFileOpIoctl(inode, filp, iocmd, ioarg);
+   return err;
+#endif
 }
 #endif

diff -rupN vmnet-only/netif.c vmnet-only-modified/netif.c
--- vmnet-only/netif.c  2015-01-17 09:25:58.000000000 +0800
+++ vmnet-only-modified/netif.c 2015-05-07 14:51:43.326885576 +0800
@@ -149,7 +149,7 @@ VNetNetIf_Create(char *devName,  // IN:
    memcpy(deviceName, devName, sizeof deviceName);
    NULL_TERMINATE_STRING(deviceName);

-   dev = alloc_netdev(sizeof *netIf, deviceName, VNetNetIfSetup);
+   dev = alloc_netdev(sizeof *netIf, deviceName, NET_NAME_UNKNOWN, VNetNetIfSetup);
    if (!dev) {
       retval = -ENOMEM;
       goto out;
diff -rupN vmnet-only/userif.c vmnet-only-modified/userif.c
--- vmnet-only/userif.c 2015-01-17 09:25:58.000000000 +0800
+++ vmnet-only-modified/userif.c    2015-05-07 14:52:32.095595913 +0800
@@ -523,7 +523,13 @@ VNetCopyDatagram(const struct sk_buff *s
       .iov_base = buf,
       .iov_len  = len,
    };
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
    return skb_copy_datagram_iovec(skb, 0, &iov, len);
+#else
+   struct iov_iter to;
+   iov_iter_init(&to, READ, &iov, 1, len);
+   return skb_copy_datagram_iter(skb, 0, &to, len);
+#endif
 }

1嗨budiap,有没有可能提供一个白痴指南,告诉我如何应用这个补丁?谢谢。 - Simmo