lunes, 29 de diciembre de 2008

VMware 1.0.8-126538 en kernels nuevos, una odisea

Actualizacion: los problemas de vmmon descriptos en este articulo y algunos mas se resolvieron en el patch que publico y describo en este post

Desde hace unas semanas que me hice un tiempo e instale fedora 10 con kde4 y toda la magia, pero llego el momento en que necesite virtualización, ahí empezó una entretenida historia (entretenida ahora que termino bien :D )
Si algunos de los que están leyendo esto comparten la experiencia de haber intentado instalar la ultima versión de VMware en uno de los últimos linux con el kernel 2.6.27.9 o alguna versión parecida, (encontré foros de personas que decían que este mismo problema pasa también en el ultimo ubuntu, seguro en otras distribuciones tambien ), habrán leído en la pantalla unas groserías particulares, cuando ejecutaron el famoso vmware-config.pl:

"/tmp/vmware-config1/vmmon-only/./include/compat_semaphore.h:23:27: error: asm/semaphore.h: No such file or directory"
"/tmp/vmware-config24/vmmon-only/linux/driver.c:153: error: se especificó el campo desconocido ‘nopage’ en el inicializador"

y asi...

No aguante mas y entre a meter mano en el codigo, primero lo del semaphore.h, no era complejo, simplemente cambiaron al .h de lugar, ahora esta en linux/semaphore.h en lugar de asm/semaphore.h en el nuevo kernel:




#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
#include "asm/semaphore.h"
#else
#include "linux/semaphore.h"
#endif



respecto a lo de nopage, no se bien que significa :(, lo unico que hice fue comentar las dos lineas que causaban problemas:


...

static void LinuxDriverPollTimeout(unsigned long clientData);

static struct vm_operations_struct vmuser_mops = {
// .nopage = LinuxDriverNoPage
};

struct vm_operations_struct vmuser_locked_mops = {
// .nopage = LinuxDriverLockedNoPage
};

static struct file_operations vmuser_fops;
static struct timer_list tscTimer;

...


Tomar nota de esto ultimo, queda pendiente evaluar el significado de todo eso


Y eso no fue todo, como todo un clásico de la programación C, al corregir errores, el compilador revela los otros errores que antes no se mostraron al no llegar a compilar esas secciones, quedo un desbarajuste en la función smp_call_function, que según el smp.h del kernel, tomaba 3 argumentos, y en driver.c y hostif.c del codigo fuente de vmmon, lo llamaba pasando 4 parámetros, a esto, lo resolvi eliminando el tercer argumento de todas las llamadas a la función smp_call_function ( y compat_smp_call_function, que era un sinónimo en ese código ). Elimine el tercer parametro porque en la definición de la funcion smp_call_function en el código del kernel mas viejo era el "retry" el tercer parámetro extra que había demás en relacion al nuevo



// version nueva EN linux/smp.h

/*
* Call a function on all other processors
*/
int smp_call_function(void(*func)(void *info), void *info, int wait);

// version vieja en linux/smp.h

/*
* Call a function on all other processors
*/
int smp_call_function(void(*func)(void *info), void *info, int retry, int wait);



Por ultimo, queda una llamada a kill_proc en linux/hostif.c, que segun el compilador no existe un kill_proc definido, ahi simplemente comente la linea :p

Y por ultimo, al compilar vmnet, surge el mismo problema del semaphore.h, la solución es exactamente la misma que con la compilación del otro modulo

Al final funciono todo, al punto que compilo todo, pude configurar todo lo que necesite y pude crear y bootear una maquina virtual, si embargo dos cosas (que habia mencionado antes) quedaron atadas con alambre:

1) el .nopage = LinuxDriverNoPage comentado casi al principio de linux/driver.c
2) el kill_proc comentado casi al final de linux/hostif.c
3) La version del kernel que no supe precisar en el #if que incluye el semaphore.h

Disculpen no haber subido el parche que genere, pero esos últimos dos puntos me parece que quedaron muy truchos y no quiero que cause problemas tratándose este código que toque de nada mas y nada menos que de módulos del kernel

Lo probe un poco, y al parecer el cambio del kill_proc genera algunos problemas, ya que al correr la mayoria de las maquinas virtuales, vmserverd termina por un error causado en el kernel,

con este problema:

Kernel failure message 1:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
IP: [<0000000000000000>] 0x0
PGD 12944067 PUD 12942067 PMD 12941067 PTE 0
Oops: 0010 [1] SMP

y con este backtrace:

[] ? HostIF_SetFastClockRate+0xb0/0x137 [vmmon]
[] Vmx86_SetHostClockRate+0xb4/0xc9 [vmmon]
[] LinuxDriver_Ioctl+0x3d3/0x923 [vmmon]
[] ? inode_has_perm+0x5b/0x61
[] ? __dequeue_entity+0x61/0x6a
[] ? remove_wait_queue+0x2f/0x39
[] ? file_has_perm+0x83/0x8e
[] LinuxDriver_CompatIoctl+0x2b/0x40 [vmmon]

Fijense que la funcion con problemas, es la que modifique comentando el kill_proc, se resolveria cuando encuentre una implementacion de kill_proc que use las posibilidades de este nuevo kernel

Después de un rato, corregí la función , reemplazando a kill_proc por su equivalente el nuevo kernel, tal como explica en esta pagina , cuando compilo, siguió existiendo el mismo error, buscando por la web, encontré algo acerca de please revert commit 53f1b1433da7eac2607a4...; aparentemente, un chabon hizo un commit, que crashea el kernel cuando cierta función se llama de cierta forma, espero que actualizando el kernel cuando se corrija o patcheandolo pueda solventar este problema

No hay comentarios: