前几天手欠把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的内核不要随便升级,特别是服务器的操作系统,否则后果不堪设想....