Afin d’améliorer le fonctionnement et les performances des machines virtuelles, VMware fournit les VMware tools.
Ces »tools » se décomposent en :
- une application graphique (wait whaaat ? did you say UI ??)
- des kernel modules pré-compilés, ainsi que les sources pour les autres noyaux.
J’aurais pu me contenter de fournir les patches, lesquels auraient été suffisant pour compiler les modules, mais en plus d’avoir des codes sources obsolètes, l’installeur s’est mis à dysfonctionner. Impossible donc de compter sur lui pour faire le boulot.
En décortiquant l’installeur, je suis arrivé à un binaire, qui est responsable de la localisation des linux headers sur ma machine, c’est lui qui pour une raison qui m’échappe, ne trouve plus les linux-headers, mais de par sa forme binaire, c’est une voie sans issue (je ne suis pas expert en reverse engineering, et encore moins sous Linux)…
Aucune importance : j’ai trouvé mieux. En décompressant les sources qui se trouvent dans ~/lib/modules/sources , il m’a suffit de lancer un make et la magie s’est opérée : j’avais mes modules (enfin… après quelques petites modifications) !!
Ce script fonctionne précisément pour les kernels de la branche 3.8 patchés avec grsec. En enlevant les appels à pax_open_kernel et pax_close_kernel ou en mettant la bonne pré-condition, on pourrait le rendre compatible avec n’importe quel kernel de la branche 3.8 je pense.
J’aurais pu fournir les fichiers patch à part, mais j’ai préféré ne garder qu’un seul fichier, afin de conserver une certaine simplicité de gestion pour la maintenance du script.
# sources: # https://bugs.gentoo.org/attachment.cgi?id=289757&action=edit # http://pastebin.com/dVPszctW # https://bugs.gentoo.org/show_bug.cgi?id=461872 mount /mnt/cdrom tar -xvzf /mnt/cdrom/vmware-tools-distrib.tar.gz /root/ cd /root/vmware-tools-distrib/lib/modules/source echo compiling vmmemctl... tar -xvf vmmemctl.tar cd vmmemctl-only make cd .. echo compiling vmsync tar -xvf vmsync.tar cd vmsync-only echo ' --- driver/sync.c 2013-04-16 21:52:23.277342798 +0200 +++ driver/sync.c 2013-04-16 21:53:43.094056640 +0200 @@ -162,7 +162,7 @@ cancel_delayed_work(&state->thawTask); list_for_each_safe(cur, tmp, &state->devices) { dev = list_entry(cur, VmSyncBlockDevice, list); - if (dev->sb != NULL && dev->sb->s_frozen != SB_UNFROZEN) { + if (dev->sb != NULL && dev->sb->s_writers.frozen != SB_UNFROZEN) { thaw_bdev(dev->bdev, dev->sb); atomic_dec(&gFreezeCount); } @@ -237,7 +237,7 @@ * the superblock is already frozen. */ if (inode->i_sb->s_bdev == NULL || - inode->i_sb->s_frozen != SB_UNFROZEN) { + inode->i_sb->s_writers.frozen != SB_UNFROZEN) { result = (inode->i_sb->s_bdev == NULL) ? -EINVAL : -EALREADY; compat_path_release(&nd); goto exit; ' | patch sync.c make cd .. echo compiling vmci tar -xvf vmci.tar cd vmci-only echo ' --- linux/driver.c 2013-04-17 20:19:38.778514246 +0200 +++ linux/driver.c 2013-04-17 20:43:31.109809776 +0200 @@ -124,7 +124,7 @@ .name = "vmci", .id_table = vmci_ids, .probe = vmci_probe_device, - .remove = __devexit_p(vmci_remove_device), + .remove = vmci_remove_device, }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) @@ -252,7 +252,21 @@ #define LinuxDriverUnlockIoctlPerFD(mutex) do {} while (0) #endif -static struct file_operations vmuser_fops; +/* Initialize the file_operations structure */ +static struct file_operations vmuser_fops = { + .owner = THIS_MODULE, + .poll = LinuxDriverPoll, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = LinuxDriver_UnlockedIoctl, +#else + .ioctl = LinuxDriver_Ioctl, +#endif +#ifdef HAVE_COMPAT_IOCTL + .compat_ioctl = LinuxDriver_UnlockedIoctl, +#endif + .open = LinuxDriver_Open, + .release = LinuxDriver_Close +}; /* @@ -389,26 +403,6 @@ return -ENOMEM; } - /* - * Initialize the file_operations structure. Because this code is always - * compiled as a module, this is fine to do it here and not in a static - * initializer. - */ - - memset(&vmuser_fops, 0, sizeof vmuser_fops); - vmuser_fops.owner = THIS_MODULE; - vmuser_fops.poll = LinuxDriverPoll; -#ifdef HAVE_UNLOCKED_IOCTL - vmuser_fops.unlocked_ioctl = LinuxDriver_UnlockedIoctl; -#else - vmuser_fops.ioctl = LinuxDriver_Ioctl; -#endif -#ifdef HAVE_COMPAT_IOCTL - vmuser_fops.compat_ioctl = LinuxDriver_UnlockedIoctl; -#endif - vmuser_fops.open = LinuxDriver_Open; - vmuser_fops.release = LinuxDriver_Close; - sprintf(linuxState.deviceName, "vmci"); linuxState.major = 10; linuxState.misc.minor = MISC_DYNAMIC_MINOR; @@ -1750,7 +1744,7 @@ *----------------------------------------------------------------------------- */ -static int __devinit +static int vmci_probe_device(struct pci_dev *pdev, // IN: vmci PCI device const struct pci_device_id *id) // IN: matching device ID { @@ -1978,7 +1972,7 @@ *----------------------------------------------------------------------------- */ -static void __devexit +static void vmci_remove_device(struct pci_dev* pdev) { struct vmci_device *dev = pci_get_drvdata(pdev); ' | patch linux/driver.c make cd .. echo compiling vsock tar -xvf vsock.tar cd vsock-only cat ../vmci-only/Module.symvers >> Module.symvers cp linux/af_vsock.c linux/af_vsock.c.bak echo ' --- linux/af_vsock.c 2013-04-17 20:25:44.093536289 +0200 +++ linux/af_vsock.c 2013-04-17 20:27:51.518312015 +0200 @@ -3160,11 +3160,15 @@ * else in the future. */ for (i = NPROTO - 1; i >= 0; i--) { - vsockVmciFamilyOps.family = i; + pax_open_kernel(); + *(int *)&vsockVmciFamilyOps.family = i; + pax_close_kernel(); err = sock_register(&vsockVmciFamilyOps); if (err) { Warning("Could not register address family %d.\n", i); - vsockVmciFamilyOps.family = VSOCK_INVALID_FAMILY; + pax_open_kernel(); + *(int *)&vsockVmciFamilyOps.family = VSOCK_INVALID_FAMILY; + pax_close_kernel(); } else { vsockVmciDgramOps.family = i; vsockVmciStreamOps.family = i; @@ -3202,7 +3206,9 @@ sock_unregister(vsockVmciFamilyOps.family); } - vsockVmciDgramOps.family = vsockVmciFamilyOps.family = VSOCK_INVALID_FAMILY; + pax_open_kernel(); + vsockVmciDgramOps.family = *(int*)&vsockVmciFamilyOps.family = VSOCK_INVALID_FAMILY; + pax_close_kernel(); vsockVmciStreamOps.family = vsockVmciFamilyOps.family; }' | patch -l linux/af_sock.c make cd .. if [ -f pvscsi.tar ] tar -xvf pvscsi.tar cd pvscsi-only echo ' --- pvscsi.c 2013-05-14 23:24:04.801773269 +0200 +++ pvscsi.c 2013-05-14 23:25:34.701065554 +0200 @@ -455,7 +455,7 @@ SCSI_SENSE_BUFFERSIZE, PCI_DMA_FROMDEVICE); } -static int __devinit pvscsi_allocate_rings(struct pvscsi_adapter *adapter) +static int pvscsi_allocate_rings(struct pvscsi_adapter *adapter) { adapter->rings_state = pci_alloc_consistent(adapter->dev, PAGE_SIZE, &adapter->ringStatePA); @@ -1234,7 +1234,7 @@ * just use a statically allocated scatter list. * */ -static int __devinit pvscsi_allocate_sg(struct pvscsi_adapter *adapter) +static int pvscsi_allocate_sg(struct pvscsi_adapter *adapter) { struct pvscsi_ctx *ctx; int i; @@ -1317,7 +1317,7 @@ return numPhys; } -static int __devinit pvscsi_probe(struct pci_dev *pdev, +static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct pvscsi_adapter *adapter; @@ -1535,7 +1535,7 @@ .name = "pvscsi", .id_table = pvscsi_pci_tbl, .probe = pvscsi_probe, - .remove = __devexit_p(pvscsi_remove), + .remove = pvscsi_remove, COMPAT_PCI_SHUTDOWN(pvscsi_shutdown) };' | patch pvscsi.c make cd .. fi echo installing LIBDIR=/lib/modules/`uname -r`/misc [ -d "$LIBDIR" ] || mkdir "$LIBDIR" cp vmmemctl.o "$LIBDIR/vmmemctl.ko" cp vmsync.o "$LIBDIR/vmsync.ko" cp vmci.o "$LIBDIR/vmci.ko" cp vsock.o "$LIBDIR/vsock.ko" [ -f pvscsi.o ] && cp pvscsi.o "$LIBDIR/pvscsi.o" // clean up rm -R vmci-only vmsync-only vsock-only vmmemctl-only [ -d pvscsi-only ] && rm -R pvscsi-only // finished ! # refresh modules.dep.bin for modprobe depmod echo "You just have to add this line on /etc/conf.d/modules to auto-load the vmware modules" echo "module_$(uname -r | sed -e 's/[-.]/_/g')=\"vmmemctl vmsync vmci vsock pvscsi\""
Le petit plus du script : il évite d’installer les VMware tools. Sans interface graphique, ils ne servent à rien, et sous Gentoo, ça pollue la sortie de revdep-rebuild .
Ce script ne compile pas les modules vmxnet ni vmxnet3 , le premier parce qu’il est déprécié et parce que je ne l’utilise pas, le second parce qu’il est déjà intégré au noyau linux.
Dans des versions ultérieures de linux, il se pourrait que je n’ai même plus à gérer la compilation de vmci et vsock : en effet ces derniers pourraient faire une entrée dans le noyau linux.
Notes
J’ai finis de rédiger le script hier soir en compilant mes commandes balancées dans le terminal. Je n’ai jamais testé le script, donc à vos risques et périls !
En revanche, je peux prendre en compte vos remarques.