martes, 2 de octubre de 2007

Configurando un RAID-1 por software en Ubuntu

Siguiendo aquel viejo dicho de que el régimen permanente de cualquier disco duro es... LLENO; el disco de nuestro servidor de versiones ha llegado ya a un estado en el que se le salen los bits por las juntas. Por ello hemos decidido instalar no uno, sino dos nuevos discos para montar un RAID-1 por software y así ganar un poco de velocidad y, sobre todo, seguridad.

Ambos discos se han instalado como hdb y hdd. Las instrucciones que siguen se han tomado de este estupendo tutorial del blog de Iván López.

Lo primero que hay que hacer es particionar ambos discos con fdisk. Hemos creado una sola partición primaria (comando n de fdisk) y se ha etiquetado como fd (comando t), que es la correspondiente a "Linux raid autodetect". Después se ha escrito la tabla de particiones con el comando w antes de salir del programa.

El siguiente paso es crear el disco RAID. Para ello se usa el programa mdadm (si no está instalado, basta con instalar el paquete mdadm):

> sudo mdadm --create /dev/md0 --verbose --level=1 --raid-devices=2 /dev/hdb1 /dev/hdd1

El proceso de creación se puede ver así:

> cat /proc/mdstat

Cuando finalice este proceso tendremos un nuevo disco en /dev/md0, el cual habrá que formatear:

> sudo mkfs.ext3 /dev/md0

Para montarlo, primero se crea el punto de montaje:

> sudo mkdir /repositorio

Luego la entrada en fstab:

> su
> echo "/dev/md0 /repositorio ext3 defaults 0 1" >> /etc/fstab

Ahora ya podemos montar el nuevo disco:

> mount /repositorio

Y a partir de aquí ya podemos usarlo. Lo primero es copiar el repositorio antiguo:

> cp -a /repositorio.antiguo/* /repositorio

Y luego cambiar el dueño a svnuser

> chown svnuser repositorio
> chgrp svn repositorio

Para que el programa mdadm pueda gestionar nuestra matriz de discos es necesario crear el archivo de configuración:

> cd /etc/mdadm

Si existe un archivo de configuración anterior, seguro que es buena idea hacerle una copia de seguridad antes de crear el nuevo.

> mv mdadm.conf mdadm.conf.antiguo

El archivo se puede crear usando la información sobre los discos generada por mdadm:

> echo "DEVICE /dev/hdb1 /dev/hdd1" >> mdadm.conf
> mdadm --detail --scan >> mdadm.conf

Y ya si que está listo. Lo único que faltaría es probar a desconectar un disco y ver qué pasa...

jueves, 20 de septiembre de 2007

Fuentes de MicroSoft para OpenOffice

Al importar archivos de MS-Office en OpenOffice, no se ven del todo bien si no tenemos las fuentes originales.

Para instalarlas tenemos el paquete: msttcorefonts.

Para más info ver: http://www.educalibre.cl/node/843

viernes, 20 de julio de 2007

Uso de readline y history

Para mejorar el interfaz de usuario de la aplicación de control del maestro se han usado las librerías libreadline y libhistory para poder editar fácilmente los comandos y tener una historia de los comandos introducidos anteriormente.

Lo primero que hemos hecho es instalar el paquete de desarrollo de las librerías:

sudo apt-get install libreadline5-dev

El paquete anterior incluye ambas liberías.

El siguiente paso es adaptar nuestro programa para usar ambas liberías. Para ello hay que tener en cuenta lo siguiente:

Para leer una línea de entrada, en lugar de gets o fgets se usará readline. El prototipo de esta función es:

char *readline (const char *prompt);

La función recibe como argumento una cadena que se usará como prompt, aunque si no se necesita se puede usar NULL. readline permitirá que el usuario introduzca su comando facilitando la edición de éste. Cuando el usuario pulse enter, la función devuelve un puntero a una cadena con el comando introducido, pero sin el \n. La función asigna memoria dinámicamente para la cadena, por lo que cuando terminemos de usarla tendremos que liberarla con un free().

Para almacenar un comando en el histórico se usa la función:

void add_history (const char *string);

Esta función almacena la cadena string en el histórico.

El proceso a seguir es por tanto leer la cadena con el comando, almacenarla en el histórico, usarla (interpretándola y ejecutando el comando correspondiente) y luego liberar la memoria asignada. Lo más apropiado en este caso es hacer una función que se encarge de realizar todo el proceso anterior salvo la interpretación del comando. Esta función será un sustituto de gets. El código de esta función es el siguiente:

/* Lee una línea usando libreadline y libhistory para permitir
editar la línea y tener una historia de los comandos tecleados
*/

char *rl_gets(void)
{
static char *plinea=(char *)NULL; /* Para guardar la línea devuelta por
readline */
if(plinea!=NULL){/* En la llamada anterior se devolvió una línea válida.
Como ya no la necesitamos liberamos la memoria.*/
free(plinea);
plinea = (char *)NULL;
}

plinea = readline("Comando > ");
if(plinea != NULL && plinea[0] != '\0'){
/* Se ha introducido una línea válida*/
add_history(plinea);
}

return plinea;
}

El modo de llamar a esta función es el siguiente:

#include
#include

main()
{
char *pcomando;

do{
pcomando = rl_gets();
InterpretaComando(pcomando);
}while(strcmp(pcomando, "quit")!=0);
}

Por ello rl_gets lo primero que hace es liberar la memoria de la cadena de la ejecución anterior de rl_gets, salvo que sea la primera ejecución o que haya devuelto NULL (devuelve un NULL si sólo lee como entrada un EOF). Luego lee la siguiente línea y si se ha leído correctamente (no es NULL) y contiene algún carácter (plinea[0] no es el caracter nulo) se almacena dicha línea en el histórico.

Por último, para compilar el programa no hay que olvidar de decirle al linker que incluya las librerías:

gcc -o prog prog.c -lreadline -lhistory

Más información


La información mostrada aquí está obtenida de la siguiente página:
Programming with GNU Readline

También tiene más información en las páginas del manual.

  • man readline

  • man history

lunes, 16 de julio de 2007

Instalando ddd

La última herramienta que falta para poder desarrollar en condiciones es un debugger. Aunque ya hemos instalado gdb, el interfaz en modo texto es un poco incómodo. Un buen interfaz gráfico para gdb es el ddd (Data Display Debugger), pero éste no está en los repositiorios de Ubuntu. Para poder instalarlo es necesario habilitar el repositiorio "universe". Para ello basta con editar /etc/apt/sources.list y descomentar las líneas:

deb http://es.archive.ubuntu.com/ubuntu/ dapper universe
deb-src http://es.archive.ubuntu.com/ubuntu/ dapper universe

deb http://security.ubuntu.com/ubuntu dapper-security universe
deb-src http://security.ubuntu.com/ubuntu dapper-security universe

Las dos primeras están por la mitad del archivo y las dos últimas al final.

Una vez habilitado el repositiorio "universe" basta con actualizar la lista de paquetes:

sudo apt-get update

Y luego instalar el paquete ddd:

sudo apt-get install ddd ddd-doc

viernes, 13 de julio de 2007

Accediendo al bus ISA en la MOPSlcdLX (2ª parte)

Hoy hemos conseguido por fín acceder a la tarjeta. Para ello nos hemos hecho un programa de prueba que busca por toda la memoria un registro especial de la tarjeta que tiene la particularidad que cuando se escribe un 0x9a después se lee un 0x65. Además dicho registro está mapeado en la posición 0xF80004 del mapa de memoria de 16 MB del bus ISA. Por tanto la tarea es fácil: buscar en cada bloque de 16 MB de la tarjeta si existe dicho registro "mágico".

Acceder a la memoria en Linux desde un programa de usuario no es algo inmediato, pero tampoco es nada complicado una vez que te lo explican.

En primer lugar es necesario abrir el "fichero" /dev/mem que es una "copia" de la memoria física del ordenador. Ojo, para ello es necesario ser root, por lo que el programa tendrá que ejecutarse teniendo esto en cuenta. La manera de abrirlo es:


fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd<0) {
perror("open(\"/dev/mem\")");
exit(1);
}
}


Una vez abierto el fichero se mapea una página de la memoria a un puntero para poder acceder a la memoria. Para ello se usa la función mmap:


#define MAP_SIZE 4096
#define MAP_MASK ( MAP_SIZE - 1 )
....
map = mmap(0,
MAP_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
addr & ~MAP_MASK
);
if (map == (void*)-1 ) {
perror("mmap()");
exit(1);
}

regaddr = map + (addr & MAP_MASK);

val = *(uint16*) regaddr;
munmap(0,MAP_SIZE);

El primer parámetro de mmap se suele dejar siempre a 0, el segundo indica el tamaño del bloque (que en este caso es una página de 4 kB). El tercero indica que queremos leer y escribir en la memoria. El cuarto indica que este mapeo puede compartirse con otros procesos que soliciten acceder a la misma página física y que la escritura en el bloque mapeado se realiza también en el "fichero" (y por tanto en la memoria física en este caso). El quinto indica el fichero que se mapea y por último se indica el desplazamiento dentro del fichero. Nótese que en dicho desplazamiento se han puesto a cero los bits menos significativos correspondientes a la dirección dentro de la página, pues lo que se quiere mapear es la página que contiene la dirección (addr) a la que queremos acceder.

La siguiente línea calcula la dirección dentro del bloque mapeado en la que se encuentra la dirección física que buscábamos. En la siguiente accedemos a dicha dirección y por último antes de terminar liberamos mapeo pues el número de éstos disponibles es limitado.

Este código se ha obtenido del programa pxaregs.c, disponible como casi todo en google ;)

Dicho programa encapsula todo el proceso de lectura/escritura en memoria física en dos funciones:


static uint16 getmem(uint32 addr);
static void putmem(uint32 addr, uint16 val);


Usando estas funciones hemos creado un programa que barre la memoria de la tarjeta buscando en cada bloque de 16 MB un registro mágico situado en la dirección 0x??F80004. Esto se consigue con este bucle:


for(n=0; n<256; n++){
dir_mag = (n<<24) | TCNMAGIC;
putmem(dir_mag, 0x9A);
valor = getmem(dir_mag);
printf("Dir: %x, valor: %x\n", dir_mag, valor);
}


Al ejecutar el programa resulta que el registro mágico aparece en todos los sitios excepto en donde ya existía memoria; es decir, que la tarjeta en cuanto se intenta acceder a una dirección que no está dada de alta como memoria RAM o como espacio de direcciones del PCI, la envía al bus isa. la ejecución del programa resulta en:


Dir: f80004, valor: 9a
Dir: 1f80004, valor: 9a
...
Dir: 1bf80004, valor: 9a
Dir: 1cf80004, valor: 65
...
Dir: eff80004, valor: 65
Dir: f0f80004, valor: 3568
...
Dir: fef80004, valor: 3568
Dir: fff80004, valor: 3568

Si se hace un cat de /proc/iomem nos sale:

00000000-0009efff : System RAM
000a0000-000bffff : Video RAM area
000c0000-000c7fff : Video ROM
000f0000-000fffff : System ROM
00100000-1bfbffff : System RAM
00100000-002ee668 : Kernel code
002ee669-00385c03 : Kernel data
20000000-2000ffff : 0000:00:09.0
e0000000-e7ffffff : 0000:00:01.1
effa0000-effbffff : 0000:00:09.0
effa0000-effbffff : e100
effe8000-effebfff : 0000:00:01.1
effec000-effeffff : 0000:00:01.1
efff0000-efff3fff : 0000:00:01.1
efff4000-efff7fff : 0000:00:01.2
efff8000-efffbfff : 0000:00:01.1
efffd000-efffdfff : 0000:00:0f.5
efffd000-efffdfff : ehci_hcd
efffe000-efffefff : 0000:00:0f.4
efffe000-efffefff : ohci_hcd
effff000-efffffff : 0000:00:09.0
effff000-efffffff : e100
fffe8000-ffffffff : reserved

jueves, 12 de julio de 2007

Accediendo al bus ISA en la MOPSlcdLX

Después de unos días de baja, por culpa de una infección de garganta, no por los malos ratos que me está dando esta tarjeta; volvemos al trabajo.

Visto que con las X no hay manera y que tenemos que terminar el proyecto en curso, nos conformaremos con la Xubuntu 6.06LTS que funciona perfectamente salvo que en modo VESA, por lo que el ratón va a saltos, pero al menos el sistema es usable con un poco de paciencia.

Lo que tenemos que hacer ahora es conseguir acceder desde un programa de usuario a una tarjeta colocada en el bus PC/104, la cual dispone de un espacio de memoria de 1MB a la que es necesario leer para configurar la tarjeta y poder trabajar con ella. El problema es. ¿Dónde demonios está situado ese MB de memoria? Si se ejecuta un lspci, la salida es:
> lspci
0000:00:01.0 Host bridge: Advanced Micro Devices [AMD]: Unknown device 2080 (rev 30)
0000:00:01.1 VGA compatible controller: Advanced Micro Devices [AMD]: Unknown device 2081
0000:00:01.2 Entertainment encryption device: Advanced Micro Devices [AMD]: Unknown device 2082
0000:00:09.0 Ethernet controller: Intel Corporation 8255xER/82551IT Fast Ethernet Controller (rev 10)
0000:00:0f.0 ISA bridge: Advanced Micro Devices [AMD]: Unknown device 2090 (rev 03)
0000:00:0f.2 IDE interface: Advanced Micro Devices [AMD]: Unknown device 209a (rev 01)
0000:00:0f.4 USB Controller: Advanced Micro Devices [AMD]: Unknown device 2094 (rev 02)
0000:00:0f.5 USB Controller: Advanced Micro Devices [AMD]: Unknown device 2095 (rev 02)


Como podemos ver existe un ISA bridge en el bus 0, slot F, función 0 (0:f.0). Si obtenemos más información acerca del bridge obtenemos:


>lspci -v -s 0:f.0
0000:00:0f.0 ISA bridge: Advanced Micro Devices [AMD]: Unknown device 2090 (rev 03)
Subsystem: Advanced Micro Devices [AMD]: Unknown device 2090
Flags: 66MHz, medium devsel
I/O ports at 6000 [size=8]
I/O ports at 6100 [size=256]
I/O ports at 6200 [size=64]
I/O ports at 1000 [size=32]
I/O ports at 9d00 [size=128]
I/O ports at 9c00 [size=64]


Que como vemos dispone de muchos huecos para puertos de entradas/salida (supongo que serán los de periféricos como el ratón, teclado, etc.) pero no aparece nada de memoria RAM de dispositivos del bus ISA. Por tanto, para poder ver la memoria de la tarjeta desde la CPU habrá que hacer un poco de magia negra.

Lo primero que hemos hecho es buscar en la BIOS alguna opción que permita una configuración manual del bus ISA, pero no hemos encontrado nada.

Lo que sí hemos encontrado en la BIOS es una opción denominada algo parecido a:

PS/2 mouse DISABELED
Arghhhh. La m.... que p.... a los de Kontron. Por defecto ponen el ratón inhabilitado en la BIOS y no indican semejante cosa con luces de neón en sus manuales. ¡Vamos hombre! Pa matarlos.

Resulta que el ratón iba mal porque al inhabilitarlo en la BIOS las interrupciones del ratón no llegaban a la CPU y las pobres X debían de estar haciendo polling. Ahora el ratón ya va como la seda. Si pudiera les pedía indemnización a los de Kontron ;)

Volviendo al tema de la tarjeta, como vamos a tener que acceder al HW, necesitamos instalar los includes del kernel, y de paso aprovechamos también para instalar nuestro editor favorito: emacs y las páginas de manual para desarrollo (llamadas al sistema y a las librerias). Los paquetes elegidos son:
linux-headers-2.6.15-26 emacs21 manpages-dev glibc-doc

Con esto ya podemos empezar ha hacer pruebas con la dichosa tarjetita, pero eso será en el siguiente "post".

viernes, 6 de julio de 2007

Y seguimos reinstalando

Esto ya parece una pesadilla. Hemos verificado el CD y está grabado perfectamente. Para verificarlo hemos calculado el "checksum" del disco:

> umount /media/cdrom
> md5sum /dev/cdrom

La MD5 que nos dió era idéntica a la de la ISO de xubuntu. Por tanto, lo más probable es que el CD del PC104 estuviera ayer un poco vago.

Hemos probado a instalarlo de nuevo y ahora nos da problemas en otros ficheros. Tenemos por tanto dos alternativas: o volver a grabar el CD con la xubuntu o probar con una debian "netinstall" que lee todos los paquetes de la red. Como parece que el CD del PC104 no quiere trabajar mucho, vamos a probar con la segunda opción a ver si ya de una puñetera vez arranca esto.

La Debian elegida es la 4.0r etch (testing). Hemos descargado una de las imágenes generadas a diario, que contienen lo último de lo último. Está en la página:

http://cdimage.debian.org/cdimage/daily-builds/daily/arch-latest/i386/iso-cd/


y el archivo descargado ha sido: debian-testing-i386-netinst.iso

Una vez instalado, no sin dar un poco de guerra el CD de nuevo, resulta que las X no arrancan.

Antes de tirarnos por un barranco decidimos compilar el driver del dichoso lx800. Repetimos los pasos de la primera entrada y luego nos acordamos de la m... que p... al que ha escrito el driver, pues las instrucciones de instalación no dicen nada de nada.

Al final suponemos que se instala como la mayoría de estos chismes:
> ./autogen.sh
> make
> make install

Esto coloca los drivers en el directorio /usr/local/lib/xorg/modules/drivers/

Pero la debian los tiene en /usr/lib/xorg/modules/drivers

Por tanto basta con copiar el driver del amd_lx800 a su sitio y modificar el archivo /etc/X11/xorg.conf para que use el nuevo driver.

Tras cruzar los dedos mientras arranca el sistema, resulta que ahora se queda frito el ordenador entero (antes sólo la pantalla) y no podemos entrar ni desde fuera por ssh.

Moraleja: el driver del lx800 no tira muy bien que digamos. Creo que optaremos por usar la Xubuntu 6.06 aunque tenga las X sin aceleración hardware.

Mañana más.