首页 > 代码库 > Linux 更新后异常(kernel 版本 3.17) VMware player

Linux 更新后异常(kernel 版本 3.17) VMware player

前几天手欠把linux的内和从3.16 升级到 3.17,结果就悲剧了,VMware不能正常启动了,一直报一个错误。

我这里的linux版本为:fedora20,其他发行版本也一样;

VMware player版本: VMware-Player-6.0.4-2249910.x86_64.bundle

错误信息大概为:

before you can run vmware several modules must be compiled and loaded into the running kernel;

大概的意思就是说,运行vmware虚拟机前需要编译linux的内核;

我天朝大百度搜不出来什么结果..希望提醒后来者低碳生活,远离百度;

好了,不说废话,放上解决方案:

第一步、cd到这个目录下找到文件:vmnet.tar

cd /usr/lib/vmware/modules/source/

第二步、修改这个文件前最好先备份一下,重新建立个文件夹:

mkdir vmnet_bak

第三步、将vmnet.tar 拷贝到 vmnet_bak下

cp vmnet.tar vmnet_bak/

第四步、用tar命令解压 vmnet.tar 并修改文件 netif.c 找到行号130:

文件内容:

/*********************************************************
 * Copyright (C) 1998-2013 VMware, Inc. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation version 2 and no later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 *
 *********************************************************/
#include "driver-config.h"
#define EXPORT_SYMTAB
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/mm.h>
#include "compat_skbuff.h"
#include <linux/sockios.h>
#include "compat_sock.h"
#define __KERNEL_SYSCALLS__
#include <asm/io.h>
#include <linux/proc_fs.h>
#include <linux/file.h>
#include "vnetInt.h"
#include "compat_netdevice.h"
#include "vmnetInt.h"
typedef struct VNetNetIF {
   VNetPort                port;
   struct net_device      *dev;
   struct net_device_stats stats;
} VNetNetIF;
static void VNetNetIfFree(VNetJack *this);
static void VNetNetIfReceive(VNetJack *this, struct sk_buff *skb);
static Bool VNetNetIfCycleDetect(VNetJack *this, int generation);
static int  VNetNetifOpen(struct net_device *dev);
static int  VNetNetifProbe(struct net_device *dev);
static int  VNetNetifClose(struct net_device *dev);
static int  VNetNetifStartXmit(struct sk_buff *skb, struct net_device *dev);
static struct net_device_stats *VNetNetifGetStats(struct net_device *dev);
static int  VNetNetifSetMAC(struct net_device *dev, void *addr);
static void VNetNetifSetMulticast(struct net_device *dev);
static int  VNetNetIfProcRead(char *page, char **start, off_t off,
                              int count, int *eof, void *data);
/*
 *----------------------------------------------------------------------
 *
 * VNetNetIfSetup --
 *
 *      Sets initial netdevice state.
 * 
 * Results: 
 *      None.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
static void
VNetNetIfSetup(struct net_device *dev)  // IN:
{
#if !COMPAT_LINUX_VERSION_CHECK_LT(3, 1, 0) || defined(HAVE_NET_DEVICE_OPS)
   static const struct net_device_ops vnetNetifOps = {
      .ndo_init = VNetNetifProbe,
      .ndo_open = VNetNetifOpen,
      .ndo_start_xmit = VNetNetifStartXmit,
      .ndo_stop = VNetNetifClose,
      .ndo_get_stats = VNetNetifGetStats,
      .ndo_set_mac_address = VNetNetifSetMAC,
#if COMPAT_LINUX_VERSION_CHECK_LT(3, 2, 0)
      .ndo_set_multicast_list = VNetNetifSetMulticast,
#else
      .ndo_set_rx_mode = VNetNetifSetMulticast,
#endif
   };
#endif
   ether_setup(dev); // turns on IFF_BROADCAST, IFF_MULTICAST
#if COMPAT_LINUX_VERSION_CHECK_LT(3, 1, 0) && !defined(HAVE_NET_DEVICE_OPS) 
   dev->init = VNetNetifProbe;
   dev->open = VNetNetifOpen;
   dev->hard_start_xmit = VNetNetifStartXmit;
   dev->stop = VNetNetifClose;
   dev->get_stats = VNetNetifGetStats;
   dev->set_mac_address = VNetNetifSetMAC;
   dev->set_multicast_list = VNetNetifSetMulticast;
#else
   dev->netdev_ops = &vnetNetifOps;
   #endif /* HAVE_NET_DEVICE_OPS */
}
/*
 *----------------------------------------------------------------------
 *
 * VNetNetIf_Create --
 *
 *      Create a net level port to the wonderful world of virtual
 *      networking.
 * 
 * Results: 
 *      Errno. Also returns an allocated port to connect to,
 *      NULL on error.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
int
VNetNetIf_Create(char *devName,  // IN:
                 VNetPort **ret, // OUT:
                 int hubNum)     // IN: 
{
   VNetNetIF *netIf;
   struct net_device *dev;
   int retval;
   static unsigned id = 0;
   char deviceName[VNET_NAME_LEN];
   memcpy(deviceName, devName, sizeof deviceName);
   NULL_TERMINATE_STRING(deviceName);
   dev = alloc_netdev(sizeof *netIf, deviceName, VNetNetIfSetup);
   if (!dev) {
      retval = -ENOMEM;
      goto out;
   }
   netIf = netdev_priv(dev);
   netIf->dev = dev;
   netIf->port.id = id++;
   netIf->port.next = NULL;
   netIf->port.jack.peer = NULL;
   netIf->port.jack.numPorts = 1;
   VNetSnprintf(netIf->port.jack.name, sizeof netIf->port.jack.name,
                "netif%u", netIf->port.id);
   netIf->port.jack.private = netIf;
   netIf->port.jack.index = 0;
   netIf->port.jack.procEntry = NULL;
   netIf->port.jack.free = VNetNetIfFree;
   netIf->port.jack.rcv = VNetNetIfReceive;
   netIf->port.jack.cycleDetect = VNetNetIfCycleDetect;
   netIf->port.jack.portsChanged = NULL;
   netIf->port.jack.isBridged = NULL;
   netIf->port.exactFilterLen = 0;
   /*
    * Make proc entry for this jack.
    */
   retval = VNetProc_MakeEntry(netIf->port.jack.name, S_IFREG, netIf,
                               VNetNetIfProcRead, &netIf->port.jack.procEntry);
   if (retval) {
      netIf->port.jack.procEntry = NULL;
      if (retval != -ENXIO) {
         goto outFreeDev;
      }
   }
   /*
    * Rest of fields.
    */
   netIf->port.flags = IFF_RUNNING;
   memset(netIf->port.paddr, 0, sizeof netIf->port.paddr);
   memset(netIf->port.ladrf, 0, sizeof netIf->port.ladrf);
   memset(netIf->port.exactFilter, 0, sizeof netIf->port.exactFilter);
   /* This will generate the reserved MAC address c0:00:?? where ?? == hubNum. */
   VMX86_BUILD_MAC(netIf->port.paddr, hubNum);
   /* Make sure the MAC is unique. */
   retval = VNetSetMACUnique(&netIf->port, netIf->port.paddr);
   if (retval) {
     goto outRemoveProc;
   }
   netIf->port.fileOpRead = NULL;
   netIf->port.fileOpWrite = NULL;
   netIf->port.fileOpIoctl = NULL;
   netIf->port.fileOpPoll = NULL;
   memset(&netIf->stats, 0, sizeof netIf->stats);
   memcpy(dev->dev_addr, netIf->port.paddr, sizeof netIf->port.paddr);
   if (register_netdev(dev) != 0) {
      LOG(0, (KERN_NOTICE "%s: could not register network device\n",
          dev->name));
      retval = -ENODEV;
      goto outRemoveProc;
   }
   *ret = &netIf->port;
   return 0;
outRemoveProc:
   if (netIf->port.jack.procEntry) {
      VNetProc_RemoveEntry(netIf->port.jack.procEntry);
   }
outFreeDev:
   free_netdev(dev);
out:
   return retval;
}
/*
 *----------------------------------------------------------------------
 *
 * VNetNetIfFree --
 *
 *      Free the net interface port.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
void
VNetNetIfFree(VNetJack *this) // IN: jack
{
   VNetNetIF *netIf = container_of(this, VNetNetIF, port.jack);
   if (this->procEntry) {
      VNetProc_RemoveEntry(this->procEntry);
   }
   unregister_netdev(netIf->dev);
   free_netdev(netIf->dev);
}
/*
 *----------------------------------------------------------------------
 *
 * VNetNetIfReceive --
 *
 *      This jack is receiving a packet. Take appropriate action.
 *
 * Results: 
 *      None.
 *
 * Side effects:
 *      Frees skb.
 *
 *----------------------------------------------------------------------
 */
void
VNetNetIfReceive(VNetJack        *this, // IN: jack
         struct sk_buff  *skb)  // IN: packet 
{
   VNetNetIF *netIf = this->private;
   uint8 *dest = SKB_2_DESTMAC(skb);
 
   if (!NETDEV_UP_AND_RUNNING(netIf->dev)) {
      goto drop_packet;
   }
   if (!VNetPacketMatch(dest,
                        netIf->dev->dev_addr,
                        NULL,
                        0,
                        allMultiFilter,
                        netIf->dev->flags)) {
      goto drop_packet;
   }
   
   /* send to the host interface */
   skb->dev = netIf->dev;
   skb->protocol = eth_type_trans(skb, netIf->dev);
   netif_rx_ni(skb);
   netIf->stats.rx_packets++;
   return;
   
 drop_packet:
   dev_kfree_skb(skb);
}
/*
 *----------------------------------------------------------------------
 *
 * VNetNetIfCycleDetect --
 *
 *      Cycle detection algorithm.
 * 
 * Results: 
 *      TRUE if a cycle was detected, FALSE otherwise.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
Bool
VNetNetIfCycleDetect(VNetJack *this,       // IN: jack
                     int       generation) // IN: 
{
   VNetNetIF *netIf = this->private;
   return VNetCycleDetectIf(netIf->dev->name, generation);
}
/*
 *----------------------------------------------------------------------
 *
 * VNetNetifOpen --
 *
 *      The virtual network‘s open dev operation. 
 *
 * Results: 
 *      errno.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
int
VNetNetifOpen(struct net_device *dev) // IN:
{
   /*
    * The host interface is not available if the hub is bridged.
    *
    * It‘s actually okay to support both.  We just need
    * to tag packets when VNetXmitPacket gives them to the interface
    * so they can be dropped by VNetBridgeReceive().
    *
    *  if so return -EBUSY;
    */
   netif_start_queue(dev);
   // xxx need to change flags
   return 0;
}
/*
 *----------------------------------------------------------------------
 *
 * VNetNetifProbe --
 *
 *      ???
 *
 * Results: 
 *      0.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
int
VNetNetifProbe(struct net_device *dev) // IN: unused
{
   return 0;
}
/*
 *----------------------------------------------------------------------
 *
 * VNetNetifClose --
 *
 *      The virtual network‘s close dev operation. 
 *
 * Results: 
 *      errno.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
int
VNetNetifClose(struct net_device *dev) // IN:
{
   netif_stop_queue(dev);
   // xxx need to change flags
   return 0;
}
/*
 *----------------------------------------------------------------------
 *
 * VNetNetifStartXmit --
 *
 *      The virtual network‘s start xmit dev operation. 
 *
 * Results: 
 *      ???, 0.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
int
VNetNetifStartXmit(struct sk_buff    *skb, // IN:
                   struct net_device *dev) // IN:
{
   VNetNetIF *netIf = netdev_priv(dev);
   if(skb == NULL) {
      return 0;
   }
   /*
    * Block a timer-based transmit from overlapping.  This could better be
    * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
    * If this ever occurs the queue layer is doing something evil!
    */
   VNetSend(&netIf->port.jack, skb);
   netIf->stats.tx_packets++;
   dev->trans_start = jiffies;
   return 0;
}
/*
 *----------------------------------------------------------------------
 *
 * VNetNetifSetMAC --
 *
 *      Sets MAC address (i.e. via ifconfig) of netif device.
 *
 * Results: 
 *      Errno.
 *
 * Side effects:
 *      The MAC address may be changed.
 *
 *----------------------------------------------------------------------
 */
int
VNetNetifSetMAC(struct net_device *dev, // IN:
                void *p)                // IN:
{
   VNetNetIF *netIf = netdev_priv(dev);
   struct sockaddr const *addr = p;
   if (!VMX86_IS_STATIC_MAC(addr->sa_data)) {
      return -EINVAL;
   }
   memcpy(netIf->port.paddr, addr->sa_data, dev->addr_len);
   memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
   return 0;
}
/*
 *----------------------------------------------------------------------
 *
 * VNetNetifSetMulticast --
 *
 *      Sets or clears the multicast address list.  This information
 *      comes from an array in dev->mc_list, and with a counter in
 *      dev->mc_count.
 *
 *      Since host-only network ifaces can‘t be bridged, it‘s debatable
 *      whether this is at all useful, but at least now you can turn it 
 *      on from ifconfig without getting an ioctl error.
 * Results: 
 *      Void.
 *
 * Side effects:
 *      Multicast address list might get changed.
 *
 *----------------------------------------------------------------------
 */
void
VNetNetifSetMulticast(struct net_device *dev) // IN: unused
{
}
/*
 *----------------------------------------------------------------------
 *
 * VNetNetifGetStats --
 *
 *      The virtual network‘s get stats dev operation. 
 *
 * Results: 
 *      A struct full of stats.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
static struct net_device_stats *
VNetNetifGetStats(struct net_device *dev) // IN:
{
   VNetNetIF *netIf = netdev_priv(dev);
   return &netIf->stats;
}
/*
 *----------------------------------------------------------------------
 *
 * VNetNetIfProcRead --
 *
 *      Callback for read operation on this netif entry in vnets proc fs.
 *
 * Results: 
 *      Length of read operation.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
int
VNetNetIfProcRead(char   *page,  // IN/OUT: buffer to write into
                  char  **start, // OUT: 0 if file < 4k, else offset into page
                  off_t   off,   // IN: (unused) offset of read into the file
                  int     count, // IN: (unused) maximum number of bytes to read
                  int    *eof,   // OUT: TRUE if there is nothing more to read
                  void   *data)  // IN: client data
{
   VNetNetIF *netIf = data; 
   int len = 0;
   
   if (!netIf) {
      return len;
   }
   
   len += VNetPrintPort(&netIf->port, page+len);
   len += sprintf(page+len, "dev %s ", netIf->dev->name);
   
   len += sprintf(page+len, "\n");
   *start = 0;
   *eof   = 1;
   return len;
}

dev = alloc_netdev(sizeof *netIf, deviceName, VNetNetIfSetup);

将上面这个函数添加一个型参 :NET_NAME_UNKNOWN

dev = alloc_netdev(sizeof *netIf, deviceName, NET_NAME_UNKNOWN, VNetNetIfSetup);

这样就ok了。将文件保存。退出vim就可以了。

第五步、将解压前的文件夹重新打包,并将VMware原始的文件重命名为:vmnet_bak.tar

tar czvf vmnet.tar vmnet-only/

mv vmnet.tar vmnet_bak.tar

第六步、将修改后的vmnet.tar 复制到 原文件的路径下,直接覆盖原始文件(因为前面已经被分vmware的vmnet.tar)

cp /usr/lib/vmware/modules/source/vmnet_bak/vmnet.tar /usr/lib/vmware/modules/source/

到这里就ok了,重新启动vmware player 虚拟机启动成功,你会看到你所熟悉熟悉的界面。

以上经历告诉我们,linux的内核不要随便升级,特别是服务器的操作系统,否则后果不堪设想....

Linux 更新后异常(kernel 版本 3.17) VMware player