試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

VMware製品のカーネルモジュールがLinux 2.6.26に対してビルドできない件とその対処

Linux(カーネル)のバージョン2.6.25のときに続いて、2.6.26でも、VMware製品のカーネルモジュールがビルドできない問題が起きた。

(2008/9/8)vmware-any-any-update117d.tar.gzを使用したところ、そのまま問題なくビルドできた。下は一般的な適用例。

$ tar zxf [vmware-any-any-update117d.tar.gzの場所]
$ cd vmware-any-any-update117d/
$ sudo ./runme.pl

Gentoovmware-modules-1.0.0.20を使用する場合は下のebuildを使用する(any-anyの.tar.gzファイルは手動でダウンロード後配置)。
ファイル名: vmware-modules-1.0.0.20-r1.ebuild

# Copyright 1999-2008 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

inherit linux-mod vmware-mod

KEYWORDS="~amd64 ~x86"
VMWARE_VER="VME_V605" # THIS VALUE IS JUST A PLACE HOLDER
ANY_VER="117d"
VMWARE_MOD_DIR="vmware-any-any-update${ANY_VER}"
VMWARE_MODULE_LIST="vmmon vmnet vmblock"

SRC_URI="vmware-any-any-update${ANY_VER}.tar.gz"
RESTRICT="fetch"

pkg_nofetch() {
	elog "Please download vmware-any-any-update${ANY_VER}.tar.gz from:"
	elog "http://groups.google.com/group/vmkernelnewbies/files"
	elog "then put this file in ${DISTDIR}"
}

src_unpack() {
	unpack ${A}
	cd "${S}"
	for mod in ${VMWARE_MODULE_LIST}; do
		unpack ./"${VMWARE_MOD_DIR}"/${mod}.tar
		convert_to_m "${S}"/${mod}-only/Makefile
	done
}

また、VMware Playerのバージョン2.0.5(Build 109488)でも、Linux 2.6.26でビルドが通るようになっている。
以下、以前の内容。

  1. エラーメッセージ
    1. vmware-any-any-update117cのvmblock
    2. Gentoo Linuxのvmware-modules(2.6.25対応)
  2. 解決策
    1. Gentoo Linuxのvmware-modulesを修正
    2. 一般的な修正方法
  3. 更に新しい問題が...

エラーメッセージ

vmware-any-any-update117cのvmblock

2008/7/27現在の最新のvmware-any-any-updateであるvmware-any-any-update117c.tar.gzを使用すると、vmmonとvmnetはビルドできたが、vmblockは失敗した。

Using 2.6.x kernel build system.
make: Entering directory `/tmp/work/vmblock-only'
make -C /lib/modules/2.6.26-tuxonice/build/include/.. SUBDIRS=$PWD SRCROOT=$PWD/
. modules
make[1]: Entering directory `/usr/src/linux-2.6.26-tuxonice'
  CC [M]  /tmp/work/vmblock-only/linux/block.o
  CC [M]  /tmp/work/vmblock-only/linux/control.o
/tmp/work/vmblock-only/linux/control.c: In function 'SetupProcDevice':
/tmp/work/vmblock-only/linux/control.c:153: error: 'proc_root_fs' undeclared (first use in this function)
/tmp/work/vmblock-only/linux/control.c:153: error: (Each undeclared identifier is reported only once
/tmp/work/vmblock-only/linux/control.c:153: error: for each function it appears in.)
/tmp/work/vmblock-only/linux/control.c: In function 'CleanupProcDevice':
/tmp/work/vmblock-only/linux/control.c:213: error: 'proc_root_fs' undeclared (first use in this function)
make[2]: *** [/tmp/work/vmblock-only/linux/control.o] Error 1
make[1]: *** [_module_/tmp/work/vmblock-only] Error 2
make[1]: Leaving directory `/usr/src/linux-2.6.26-tuxonice'
make: *** [vmblock.ko] Error 2
make: Leaving directory `/tmp/work/vmblock-only'

Gentoo Linuxvmware-modules(2.6.25対応)
Linux 2.6.25に対応したパッチの当たっているGentoo向けパッケージ(vmware-modules 1.0.0.20)では、2008/7/27現在

Using 2.6.x kernel build system.
make -C /usr/src/linux M=$PWD SRCROOT=$PWD/. modules
make[1]: Entering directory `/usr/src/linux-2.6.26-tuxonice'
make[1]: warning: jobserver unavailable: using -j1.  Add `+' to parent make rule
. 
  CC [M]  /var/tmp/portage/app-emulation/vmware-modules-1.0.0.20/work/vmmon-only
/linux/driver.o
/var/tmp/portage/app-emulation/vmware-modules-1.0.0.20/work/vmmon-only/linux/dri
ver.c:197: error: unknown field 'nopage' specified in initializer
/var/tmp/portage/app-emulation/vmware-modules-1.0.0.20/work/vmmon-only/linux/dri
ver.c:198: warning: initialization from incompatible pointer type
make[3]: *** [/var/tmp/portage/app-emulation/vmware-modules-1.0.0.20/work/vmmon-
only/linux/driver.o] Error 1
make[2]: *** [_module_/var/tmp/portage/app-emulation/vmware-modules-1.0.0.20/wor
k/vmmon-only] Error 2
make[1]: *** [sub-make] Error 2
make[1]: Leaving directory `/usr/src/linux-2.6.26-tuxonice'
make: *** [vmmon.ko] Error 2

となってビルドに失敗する。

解決策

大変ありがたいことに、
bugs.gentoo.org/show_bug.cgi?id=227303
にvmblock/vmmon/vmnetの全てに対するパッチ(vmware-modules-1.0.0.20-patches.tar.gz)がアップロードされている。このファイルに含まれるパッチはVMware Playerのバージョン2.0.4 build-93057*1に付属(vmware-player-distrib/lib/modules/source/以下)のtarファイルを展開したものに対して差分を取ったもの。*2
なお、vmblock-2.6.26.patchには機械語形式のモジュールなどの余計なファイルが含まれているため、手動でのビルドに使用する場合は一度vmblock-onlyディレクトリで「make clean」を実行したほうがよさそう。
なお、このパッチは、以下の事情により、そのまま公式のPortageツリーに入る予定はなさそう。

Gentoo Linuxvmware-modulesを修正
以下、Gentoo Linuxの「vmware-modules」パッケージを修正してインストールする作業例。*3

$ tar zxvf vmware-modules-1.0.0.20-patches.tar.gz
vmblock-2.6.26.patch
vmmon-2.6.26.patch
vmnet-2.6.26.patch
vmware-modules-1.0.0.20.ebuild.patch
$ sudo mkdir -p [ローカルOverlay]/app-emulation/ 2>/dev/null
$ sudo cp -a /usr/portage/app-emulation/vmware-modules/ [ローカルOverlay]/app-emulation/
$ sudo cp vm*2.6.26.patch [ローカルOverlay]/app-emulation/vmware-modules/files/patches/
$ cd [ローカルOverlay]/app-emulation/vmware-modules/
$ sudo patch -p0 < [vmware-modules-1.0.0.20.ebuild.patchの場所]
patching file vmware-modules-1.0.0.20.ebuild
$ sudo ebuild vmware-modules-1.0.0.20.ebuild digest
$ cd -
$ rm vm*2.6.26.patch *.ebuild.patch vmware-modules-1.0.0.20-patches.tar.gz -f
$ sudo emerge -av1 vmware-modules

一般的な修正方法
アップロードされている差分がVMware Playerの本体に付属しているソースと比較したものなので、本体の巨大な.tar.gzファイルを用意しなくてはならずに不便な気がしたため、パッチ適用済みの状態とvmware-any-any-update-117cのモジュールとの差分を取ったものを貼り付ける。*4
Linux 2.6.26未満に対しては適用しないように注意。
[転載][任意]ファイル名: any-any-update117c-2.6.26.patch

diff -ur any-any-update117c/vmblock-only/linux/dentry.c 2.6.26/vmblock-only/linux/dentry.c
--- any-any-update117c/vmblock-only/linux/dentry.c
+++ 2.6.26/vmblock-only/linux/dentry.c
@@ -112,8 +112,14 @@
       LOG(4, "DentryOpRevalidate: [%s] no longer exists\n", iinfo->name);
       return 0;
    }
-   ret = actualNd.path.dentry && actualNd.path.dentry->d_inode;
-   path_put(&(actualNd.path));
+   // FIXME: am comentat asta din cauza ca spune ca: 'struct nameidata' has no member named 'dentry'
+   // cel mai bine e daca gasesti patchul pentru vmware pentru kernelu ista, altfel se incep miracole
+//   ret = actualNd.dentry && actualNd.dentry->d_inode;
+   ret = 1;
+
+   // FIXME: functia asta nu pre are prototip undeva declarat, credca e legat de vreun kernel mai vechi
+   // incearca asta: http://forums.fedoraforum.org/printthread.php?t=192282
+//   path_release(&actualNd);
 
    LOG(8, "DentryOpRevalidate: [%s] %s revalidated\n",
        iinfo->name, ret ? "" : "not");
diff -ur any-any-update117c/vmblock-only/linux/filesystem.c 2.6.26/vmblock-only/linux/filesystem.c
--- any-any-update117c/vmblock-only/linux/filesystem.c
+++ 2.6.26/vmblock-only/linux/filesystem.c
@@ -218,23 +218,6 @@
    return ret;
 }
 
-static struct inode *vmware_iget(struct super_block *sb, unsigned long ino)
-{
-	struct inode *inode;
-	inode = iget_locked(sb, ino);
-	if (!inode)
-		return ERR_PTR(-ENOMEM);
-	if (!(inode->i_state & I_NEW))
-		return inode;
-
-	unlock_new_inode(inode);
-	return inode;
-/*
-error:
-	iget_failed(inode);
-	return ERR_PTR(ret);
-*/
-}
 
 /*
  *----------------------------------------------------------------------------
@@ -244,7 +227,7 @@
  *    Lookup or create a new inode.
  *
  *    Inode creation in detail:
- *    Throughout the file system, we call the VFS vmware_iget() function to get a new
+ *    Throughout the file system, we call the VFS iget() function to get a new
  *    inode.  This in turn invokes our file system's SuperOpAllocInode()
  *    function, which allocates an inode info structure (VMBlockInodeInfo)
  *    using the kernel's slab allocator.  When a new slab is created, each
@@ -252,7 +235,7 @@
  *    occurs only once per struct (e.g., when a struct from a slab is freed and
  *    reused, the constructor is not invoked again).  SuperOpAllocInode() then
  *    returns the address of the inode struct that is embedded within the inode
- *    info we have allocated.  vmware_iget() also invokes our SuperOpReadInode()
+ *    info we have allocated.  iget() also invokes our SuperOpReadInode()
  *    function to do any further file system wide initialization to the inode,
  *    then returns the inode to us (this function).
  *
@@ -290,20 +273,14 @@
 
    ASSERT(sb);
 
-   inode = vmware_iget(sb, ino);
-
-/*
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+   inode = iget_locked(sb, ino);
+#else
+   inode = iget(sb, ino);
+#endif
    if (!inode) {
       return NULL;
    }
-*/
-
-   if (IS_ERR(inode)) {
-/*
-	ret = PTR_ERR(inode);
-*/
-	goto error_inode;
-   }
 
    iinfo = INODE_TO_IINFO(inode);
    if (!iinfo) {
@@ -328,8 +305,13 @@
       return inode;
    }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
    iinfo->actualDentry = actualNd.path.dentry;
-   path_put(&(actualNd.path));
+   path_put(&actualNd.path);
+#else
+   iinfo->actualDentry = actualNd.dentry;
+   path_release(&actualNd);
+#endif
 
    return inode;
 
diff -ur any-any-update117c/vmblock-only/linux/super.c 2.6.26/vmblock-only/linux/super.c
--- any-any-update117c/vmblock-only/linux/super.c
+++ 2.6.26/vmblock-only/linux/super.c
@@ -37,9 +37,9 @@
 #else
 static void SuperOpClearInode(struct inode *inode);
 #endif
-/*
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
 static void SuperOpReadInode(struct inode *inode);
-*/
+#endif
 #ifdef VMW_STATFS_2618
 static int SuperOpStatfs(struct dentry *dentry, struct compat_kstatfs *stat);
 #else
@@ -54,9 +54,9 @@
 #else
    .clear_inode   = SuperOpClearInode,
 #endif
-/*
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
    .read_inode    = SuperOpReadInode,
-*/
+#endif
    .statfs        = SuperOpStatfs,
 };
 
@@ -142,7 +142,7 @@
  *----------------------------------------------------------------------------
  */
 
-/*
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
 static void
 SuperOpReadInode(struct inode *inode)  // IN: Inode to initialize
 {
@@ -152,7 +152,7 @@
    iinfo->nameLen = 0;
    iinfo->actualDentry = NULL;
 }
-*/
+#endif
 
 
 /*
diff -ur any-any-update117c/vmblock-only/linux/vmblockInt.h 2.6.26/vmblock-only/linux/vmblockInt.h
--- any-any-update117c/vmblock-only/linux/vmblockInt.h
+++ 2.6.26/vmblock-only/linux/vmblockInt.h
@@ -64,7 +64,8 @@
 #endif /* __KERNEL__ */
 
 #define VMBLOCK_CONTROL_MODE       S_IRUSR | S_IFREG
-#define VMBLOCK_CONTROL_PARENT     proc_root_fs
+//#define VMBLOCK_CONTROL_PARENT     proc_root_fs
+	#define VMBLOCK_CONTROL_PARENT     create_proc_entry( "fs", S_IFDIR, 0 )
 
 /*
  * Our modules may be compatible with kernels built for different processors.

(処理上無関係な)改行の追加のみの修正やvmblock-only/modules.orderに関する差分は外している。
以下、vmware-any-any-update117cをもとにした修正例。

$ tar zxf [vmware-any-any-update117c.tar.gzの場所]
$ for f in vmware-any-any-update117c/*.tar; do tar xf ${f}; done
$ patch -p1 < [any-any-update117c-2.6.26.patchの場所]
patching file vmblock-only/linux/dentry.c
patching file vmblock-only/linux/filesystem.c
patching file vmblock-only/linux/super.c
patching file vmblock-only/linux/vmblockInt.h
$ for f in vmblock vmmon vmnet; do tar cf vmware-any-any-update117c/${f}.tar ${f}-only; rm ${f}-only -fr; done
$ cd vmware-any-any-update117c/
$ sudo ./runme.pl

tarファイルを更新してrunme.plを実行するように書いているが、(手元の)Gentooではrunme.plは使用しないため、実際に実行しての確認はしていない。

更に新しい問題が...

これでモジュールのビルドはできるようになり、動作自体も正常に行われる。

このように、VMware Playerが動作していることが分かる。
しかし、これまでにない新しい問題が発生した。詳しくは別記事

参考URL:

使用したバージョン:

  • Linux 2.6.26(tuxonice-sources 2.6.26)
  • VMware Player 2.0.4 Build 93057
  • vmware-any-any-update 117c
  • GCC 4.2.4

*1:x86_64版のファイル名はVMware-player-2.0.4-93057.x86_64.tar.gz

*2:一部適用済み部分があるように見えるが、問題はない

*3:Gentooでは、モジュールビルドの際に付属のスクリプトは使用せず、ソースを直接展開してビルドし、パッケージとしてインストールする形をとる

*4:vmmonとvmnetがそのままでビルドできることもあって、差分が出たのはvmblockのみだった