Archivo

Archivo para junio, 2010

Free Pascal y Lazarus en Ubuntu

domingo, 20 de junio de 2010 6 comentarios

Creo que la gran mayoría de los programadores debemos recordar aquellos primeros momentos en que uno pasaba tardes y noches enteras escribiendo y escribiendo líneas de código en aquellas XT, AT, Commodores 64/128, etc., sólo por amor al arte y puro fanatismo. Supongo que diríamos lo mismo de los primeros años de facultad, cuando en materias de título «Programación I» uno repasaba el paradigma de la Programación Estructurada, casi siempre en el lenguaje de aprendizaje facultativo por excelencia, al menos acá en Argentina: Pascal, usando Turbo Pascal, su versión más popular.

Viniendo más acá en el tiempo, y buscando alguna herramienta donde aprovechar mis conocimientos de este lenguaje pero para desarrollar sobre Linux, supe de la existencia de Free Pascal, un compilador Pascal libre, multiplataforma y con soporte a diferentes arquitecturas, que genera ejecutables binarios con dependencias mínimas. También estaba disponible Lazarus, su inseparable IDE, no casualmente muy parecido a Delphi.

El problema era que hasta Ubuntu 9.04 y por una cuestión de madurez, las bibliotecas gráficas de Lazarus aún dependían de GTK 1.2 ( completamente en desuso desde hace «siglos» en las distribuciones Linux), y se veía así:

Se veía «duro», anticuado y lejos de toda amigabilidad con el usuario programador, carente de características básicas hoy en día tales como Unicode, antialiasing y mucho más… por lo tanto, concluí en ese momento que uno no podía encarar ningún desarrollo nuevo para Linux/Unix usando GTK 1.2 (y por ende Free Pascal+Lazarus), sucedido por la versión 2.0 allá por el año 2002.

En estos días leí un mail en la lista de Ubuntu-Ar sobre Lazarus y Free Pascal, y decidí a instalarlo para echarle un vistazo otra vez. Por suerte la situación cambió bastante, me encontré con un bonito e importante cambio:

Ahora, con Lazarus sobre GTK 2, ¡sí que está mucho más decente! Junto a Gambas es lo más parecido a un entorno RAD «estilo Visual Basic» que hay dando vueltas para Linux. Y es aún mejor que éstos dos:

  • Libre: Licencia LGPL (salvo el compilador que es GPL). Permite desarrollar software con cualquier licencia, incluso comercial.
  • Gratuito: Viene con los fuentes de sí mismo ¡y se compila a sí mismo!
  • Multiplataforma: DOS, Linux, Windows, Mac OSX, FreeBSD, Solaris, y más.
  • Soporte de diferentes arquitecturas: Intel, AMD64, ARM, PowerPC, Sparc…
  • Diferentes Toolkits GUI: Win32/Win64, GTK1/2, QT3/4, Carbon, Cocoa, (aunque en diferentes estados de madurez).
  • Compatibilidad en un alto porcentaje con Object Pascal y Delphi.

Por último, me hice un «Hola Mundo» muy muy sencillo y lo compilé. Luego, ejecuté el comando ldd, para saber de qué bibliotecas dependía. El binario, que ocupaba 14 MB (ojo, era todo info de debug, luego de pasarle un strip ocupó 5.1 MB) dependía de esto:

marcelo@marcelo-laptop:/tmp$ ldd project1
	linux-vdso.so.1 =>  (0x00007fff441ff000)
	libX11.so.6 => /usr/lib/libX11.so.6 (0x00007f6603e2f000)
	libgdk_pixbuf-2.0.so.0 =>; /usr/lib/libgdk_pixbuf-2.0.so.0 (0x00007f6603c13000)
	libgtk-x11-2.0.so.0 => /usr/lib/libgtk-x11-2.0.so.0 (0x00007f66035f0000)
	libgdk-x11-2.0.so.0 => /usr/lib/libgdk-x11-2.0.so.0 (0x00007f6603343000)
	libgobject-2.0.so.0 => /usr/lib/libgobject-2.0.so.0 (0x00007f66030fb000)
	libglib-2.0.so.0 => /lib/libglib-2.0.so.0 (0x00007f6602e1c000)
	libgthread-2.0.so.0 => /usr/lib/libgthread-2.0.so.0 (0x00007f6602c17000)
	libgmodule-2.0.so.0 => /usr/lib/libgmodule-2.0.so.0 (0x00007f6602a13000)
	libpango-1.0.so.0 => /usr/lib/libpango-1.0.so.0 (0x00007f66027c8000)
	libpthread.so.0 => /lib/libpthread.so.0 (0x00007f66025ab000)
	libatk-1.0.so.0 => /usr/lib/libatk-1.0.so.0 (0x00007f660238a000)
	libcairo.so.2 => /usr/lib/libcairo.so.2 (0x00007f6602106000)
	libdl.so.2 => /lib/libdl.so.2 (0x00007f6601f02000)
	libc.so.6 => /lib/libc.so.6 (0x00007f6601b80000)
	libxcb.so.1 => /usr/lib/libxcb.so.1 (0x00007f6601963000)
	libgio-2.0.so.0 => /usr/lib/libgio-2.0.so.0 (0x00007f66016b0000)
	librt.so.1 => /lib/librt.so.1 (0x00007f66014a8000)
	libm.so.6 => /lib/libm.so.6 (0x00007f6601224000)
	libXext.so.6 => /usr/lib/libXext.so.6 (0x00007f6601012000)
	libXrender.so.1 => /usr/lib/libXrender.so.1 (0x00007f6600e08000)
	libXinerama.so.1 => /usr/lib/libXinerama.so.1 (0x00007f6600c04000)
	libXi.so.6 => /usr/lib/libXi.so.6 (0x00007f66009f4000)
	libXrandr.so.2 => /usr/lib/libXrandr.so.2 (0x00007f66007eb000)
	libXcursor.so.1 => /usr/lib/libXcursor.so.1 (0x00007f66005e0000)
	libpangocairo-1.0.so.0 => /usr/lib/libpangocairo-1.0.so.0 (0x00007f66003d3000)
	libXcomposite.so.1 => /usr/lib/libXcomposite.so.1 (0x00007f66001d0000)
	libXdamage.so.1 => /usr/lib/libXdamage.so.1 (0x00007f65fffcc000)
	libXfixes.so.3 => /usr/lib/libXfixes.so.3 (0x00007f65ffdc6000)
	libpangoft2-1.0.so.0 => /usr/lib/libpangoft2-1.0.so.0 (0x00007f65ffb9c000)
	libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x00007f65ff915000)
	libz.so.1 => /lib/libz.so.1 (0x00007f65ff6fe000)
	libfontconfig.so.1 => /usr/lib/libfontconfig.so.1 (0x00007f65ff4c9000)
	libpcre.so.3 => /lib/libpcre.so.3 (0x00007f65ff29a000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f6604184000)
	libpixman-1.so.0 => /usr/lib/libpixman-1.so.0 (0x00007f65ff041000)
	libdirectfb-1.2.so.0 => /usr/lib/libdirectfb-1.2.so.0 (0x00007f65fedbd000)
	libfusion-1.2.so.0 => /usr/lib/libfusion-1.2.so.0 (0x00007f65febb3000)
	libdirect-1.2.so.0 => /usr/lib/libdirect-1.2.so.0 (0x00007f65fe99a000)
	libpng12.so.0 => /lib/libpng12.so.0 (0x00007f65fe772000)
	libxcb-render-util.so.0 => /usr/lib/libxcb-render-util.so.0 (0x00007f65fe56e000)
	libxcb-render.so.0 => /usr/lib/libxcb-render.so.0 (0x00007f65fe365000)
	libXau.so.6 => /usr/lib/libXau.so.6 (0x00007f65fe160000)
	libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x00007f65fdf5a000)
	libresolv.so.2 => /lib/libresolv.so.2 (0x00007f65fdd41000)
	libselinux.so.1 => /lib/libselinux.so.1 (0x00007f65fdb22000)
	libexpat.so.1 => /lib/libexpat.so.1 (0x00007f65fd8f9000)

Si bien 5 MB sigue siendo un poco mucho (y no incluye GTK ni nada, aunque no jugué con las opciones del compilador) para un simple binario, a partir de ahora FreePascal + Lazarus en mi ranking personal entran en la categoría de «interesantes» 🙂

Es bastante tarde, es cierto, más cuando gracias a Python disfruto y me divierto al programar; tengo todo lo que necesito y más que lo que podría tener con FreePascal + Lazarus (siempre lo digo, Python no sería Python si no fuera por PyAr), pero… bueno, rescato y festejo que haya otra herramienta de desarrollo libre, potente y al alcance de cualquiera. 🙂

Saludos

Categories: codear, linux, programación, ubuntu-ar Tags:

Sincronizar carpetas a un Servidor Casero automáticamente

viernes, 18 de junio de 2010 Sin comentarios

Introducción

Supongamos que tengo un equipo donde usualmente estoy trabajando y otro equipo que está siempre encendido, ambos separados por Internet. En este último, el único puerto abierto sobre una IP Pública es el 22 para usar SSH, con lo cual me viene perfecta la capacidad de rsync de sincronizar carpetas y los últimos cambios mientras estoy trabajando, todo mediante un canal seguro.

El Script de sincronización

Lo único que necesito es este script en la carpeta personal de mi equipo «cliente», o sea, donde hago mis quehaceres diarios:

#!/bin/bash
# Script para sincronización a Servidor vía Casero rsync/ssh.
#
# Copyleft 2010 - Licencia BSD
# Autor: Marcelo Fernández.
# Email: marcelo.fidel.fernandez@gmail.com
#
# Características:
#  - Guarda la salida en un archivo de log (~/sync.log).
#  - Sincronización de una vía; pisa las modificaciones (y elimina) en el destino.
#  - Envía notificaciones al escritorio del usuario.
#  - Se sugiere ser llamado desde cron (gnome-schedule para el usuario final).
#  - Sincroniza (una sola vía) el directorio Documentos de mi Carpeta Personal y el Escritorio,
#    se pueden agregar más carpetas a gusto al momento de ejecutar el comando rsync.
#    También debe personalizarse el destino del backup, ahora en /media/Disco1/Backup
#
# Requerimientos:
#  - Rsync
#  - Paquete libnotify-bin (Debian/Ubuntu), que brinda el comando notify-send.
#
# Parámetros:
#  - Host destino. El script se lo llama "./sync.sh mi_host".
#    El login debe ser vía public keys, y la passphrase la maneja Gnome.
 
HOST=$1
LOG_FILE="sync.log"
export DISPLAY=:0.0 # Para el notify
export SSH_AUTH_SOCK="$(find /tmp/keyring*/ -perm 0755 -type s -user $LOGNAME -group $LOGNAME -name '*ssh' | head -n 1)"
 
notify-send -u normal --icon=gtk-refresh --category=transfer "Sincronizando a Casa..."
echo `date` >> $LOG_FILE
rsync -avz -e 'ssh' --delete ~/Documentos ~/Escritorio $HOST:/media/Disco1/Backup/ &>> $LOG_FILE
RETVAL=$?
if [ $RETVAL -ne 0 ]; then
    notify-send -u critical --icon=gtk-dialog-error --category=transfer.error  "Error al Sincronizar";
else
    notify-send -u normal --icon=gtk-apply --category=transfer.complete "Sincronización Completa";
fi

Programando su ejecución automática

Este script está pensado y preparado para ser llamado desde la aplicación «Tareas Programadas» de Gnome (disponible en el Centro de Software de Ubuntu o se instala haciendo click aquí):

Este es el detalle de la configuración de la tarea:

Y además nos avisa de que está trabajando y si tuvo éxito o no al sincronizar:

Algunas cuestiones para destacar

Como se aclara en los comentarios, cada vez que rsync copia las modificaciones al servidor, «pisa» lo que había anteriormente, lo que comúnmente se denomina sincronización de archivos «de una vía«.

Lo más interesante es que a pesar de ser ejecutado desde Cron, aprovecha las llaves SSH desbloqueadas por Gnome en la sesión de escritorio del usuario, es decir que la primera sincronización, si previamente no me había conectado al equipo remoto, me pide la frase de paso para desbloquear la clave privada; a partir de ese momento ésta queda compartida, gracias al ssh-agent que utiliza Gnome en background. Luego, mientras siga la sesión de escritorio establecida, va a aprovechar la llave desbloqueada por el usuario y hacer la sincronización sin mayor problema. Esto es mucho mejor en cuanto a seguridad que usar una clave privada sin frase de paso contra el servidor, y me permite desbloquearla sólo la primera vez y no cada vez que se hace la sincronización, siendo un perfecto balance (al menos para mí) entre seguridad, automatización y comodidad. Lógicamente esto sirve para utilizar en cualquier conexión SSH que se quiera establecer, y la solución, después de dar muchas vueltas y probar muchas alternativas (¡el ssh del cron no «veía» al agente!), la encontré en este post.

Conclusión

Este script fue creciendo desde algo muy simple, totalmente manual y que ejecutaba «cada vez que me acordaba» a mejorarlo un poco en cuanto a la automatización y hacerlo más «lindo» como está hoy. Si bien hay muchísimos mecanismos más robustos o con más facilidades (usando los snapshots de rsync por ejemplo y/o sincronizando ida y vuelta), éste es el que funciona para mí. Es bien claro lo que hace y no hay ninguna «magia» en el medio; trabaja sin que me moleste en mi actividad diaria y me despreocupo totalmente de que tenía que hacer backup. 🙂

Espero que les sirva como a mí. Acá hay mucha más información sobre rsync y una explicación más profunda de las diferentes opciones y alternativas, que por supuesto se pueden utilizar con esto como base.

¡Saludos!

Actualización – Ubuntu 11.10

En Ubuntu 11.10 hay que tocar levemente la línea donde define la variable SSH_AUTH_SOCK, cambia esto:

export SSH_AUTH_SOCK="$(find /tmp/keyring*/ -perm 0755 -type s -user $LOGNAME -group $LOGNAME -name '*ssh' | head -n 1)"

por esto, reemplazar $USER por el nombre de usuario («marcelo» en mi caso):

export SSH_AUTH_SOCK="$(find /tmp/keyring*/ -type s -user $USER -group $USER -name '*ssh' | head -n 1)"

Actualización – Ubuntu 12.10

En Ubuntu 12.10 hay que tocar levemente la línea donde define la variable SSH_AUTH_SOCK, cambia esto:

export SSH_AUTH_SOCK="$(find /tmp/keyring*/ -perm 0755 -type s -user $LOGNAME -group $LOGNAME -name '*ssh' | head -n 1)"

por esto, reemplazar $USER por el nombre de usuario («marcelo» en mi caso):

export SSH_AUTH_SOCK="$(find /run/user/$USER/keyring*/ -type s -user $USER -group $USER -name '*ssh' | head -n 1)"
Categories: codear, linux, sysadmin, ubuntu-ar Tags:

Reiniciando las conexiones de red automáticamente en Ubuntu

miércoles, 16 de junio de 2010 Sin comentarios

Hace un tiempo que tengo una interfaz Wifi USB Encore; siempre la usé ocasionalmente, en Ubuntu se conectaba y tenía red sin problemas, pero al momento de usarla en forma constante nunca supuse que el módulo rtl8187, responsable de su funcionamiento, iba a tener tantos bugs. 🙁

En Ubuntu 10.04 funciona sin instalar nada adicional, pero los principales problemas son que funciona sólo a 11Mbps y que aleatoriamente se desconecta, sin causa aparente, y el Network Manager vuelve a reconectarse. El problema es más serio cuando Network Manager se cansa de revivir a la placa, y el equipo se queda desconectado definitivamente. Y más si no estoy cerca para reconectarla a mano. 😛

Luego de probar unas cuantas recetas (y de esquivar Ndiswrapper porque es un equipo de 64 bits), decidí que voy a dejarlo así, y me hice un scriptcito de cron para reiniciar Network Manager si la interfaz está caída:

#!/bin/bash
 
# /usr/bin/network_respawn
# Network respawn -- rtl8187b dies randomly and despite Network-Manager usually
# reconnects again, sometimes it gives up and dies without connection.
 
# If wlan0 is not connected, it restarts Network-Manager
# This script is meant to be called from a cron job. 
 
IFACE="wlan0"
 
CONNECTED=`grep $IFACE /var/run/network/ifstate`
if [ "$CONNECTED" == "" ]; then  # Disconnected. Respawning...
    /usr/bin/service network-manager restart
fi

Además, hay que crear el archivo en /etc/cron.d/network_respawn para que el sistema llame al script anterior, cada 3 minutos en mi caso:

# Network respawn -- rtl8187b dies randomly and despite Network-Manager usually
# reconnects again, sometimes it gives up and dies without connection.
# If wlan0 is not connected, it restarts Network-Manager
 
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 
*/3 * * * * root /usr/bin/network_respawn

Es un script sencillo, y puede ser utilizado para cualquier propósito como el mío. Lo malo es que reinicia todas las conexiones del equipo, ya que reinicia el Network Manager .

¿A alguien se le ocurre cómo hacerlo mejor? 🙂

Saludos

Categories: codear, linux, sysadmin, ubuntu-ar Tags:

Discos Rígidos con Sectores de 4KB en Linux

domingo, 13 de junio de 2010 16 comentarios

Actualización (Julio 2010): Armé y redacté no tan informalmente este post en forma de artículo; el mismo está disponible para su consulta, crítica y mejoras en la sección de Publicaciones del sitio.

Los nuevos discos de Western Digital

En estos días tuve la oportunidad de comprar y configurar una máquina Ubuntu con un disco rígido Western Digital de 1,5 Terabytes (1500 Gigabytes aprox.); más precisamente el modelo WD15EARS, con 64 MB de caché, velocidad de rotación que varía entre 5400 y 7200 RPMs (llamado «IntelliSeek«), interfaz SATA II (3 Gb/seg), y que incluye una nueva tecnología de la marca conocida como «Advanced Format Drive» (paper aquí).

Si bien yo pensé que estaba comprando un disco más aunque sólo de mayor capacidad, luego al mirarlo más de cerca en su etiqueta decía:

Resumiendo, dice que:

  • Si va a utilizar el disco con Windows XP con una sola partición en el disco, sólo ponga el Jumper en los pins 7-8 del HD.
  • Si va a utilizar el disco con Windows XP con más de una partición en el disco, use la utilidad «WD Align».
  • Si va a utilizar otro SO (Windows Vista/7, Mac OS X, o Linux), el disco no requiere preparación adicional para el particionamiento.

«Bueno, total no uso Windows», pensé. Particioné y formatié con el GParted el disco y me puse a utilizarlo normalmente. No noté nada raro, hasta que unos días después googleando sobre experiencias con éste disco y Linux me encontré con este hilo en el foro de WDProblem with WD Advanced Format drive in LINUX (WD15EARS)«). Al parecer, mucha gente utilizando Linux con estos discos notaba una lentitud excesiva en cada cosa que hacía, como si hubiera un problema, no del hardware fallando y perdiendo datos, sino de demoras muy grandes en lectura/escritura. Resultó que aún usando Linux, el disco sí requiere preparación adicional, al contrario de lo que dice el fabricante, como veremos más adelante.

Sectores de 4 KBytes en vez de 512 Bytes, ¿Por qué?

Desde los primeros días de los discos rígidos, la mínima unidad de almacenamiento direccionable fue el sector, de 512 Bytes de capacidad. Esta granularidad se eligió porque siempre fue un buen balance entre la fragmentación interna de los archivos* y el manejo físico del disco relativo a la corrección de errores, flags de inicio/fin del sector más la separación inter-sector (gap). Toda la industria de la PC y el software creado para ella se apoyó en este estándar de facto, y casi ningún utilitario, BIOSes, ni Sistema Operativo se pensaron para un posible cambio… sólo hasta hace unos pocos años.

Western Digital es una de las primeras marcas en sacar al mercado discos con sectores 8 veces más grandes que los anteriores, de 4 KBytes (4096 Bytes); estos discos son etiquetados como que poseen «Advanced Format Technology» («Tecnología de Formato Avanzado»), y es lo primero que uno debería empezar a mirar al comprar discos nuevos de gran tamaño (1 TB o superior), ya sean de WD o de otros fabricantes. Casualmente (o no tanto), esto incluye al disco que compré.

El motivo del cambio, según lo que explica este excelente post de AnandTech, se debe a que existen 3 factores esenciales que deben compensarse para buscar capacidades de almacenamiento cada vez mayores en el mismo tamaño de disco (que por lo general es de 3,5 pulgadas):

  1. Densidad de área: Cuántos bits se pueden guardar en un área determinada (Bits/Pulgada cuadrada). Hasta ahora, con la Grabación Perpendicular, estamos en el orden de unos 300/500 Gigabits por pulgada cuadrada (12).
  2. Relación Señal/Ruido: Al leer de los platos del disco, pueden ocurrir fallos, ya que el almacenamiento magnético en definitiva es analógico; y la señal, para ser convertida desde/hacia binario, debe ser procesada. Cuanto mejor sea la relación de la señal con respecto al ruido en el momento de leer o escribir en los platos, más confiable es la operación.
  3. El uso del Código de Corrección de Errores – ECC: Cada sector del disco incluye un área reservada para almacenar el ECC, imprescindible para recuperarse ante cualquier error de lectura/escritura.

A medida que la Densidad del Area se incrementa, los sectores (siempre de 512 Bytes) lógicamente se reducen en el área que ocupan físicamente. Esto hace que se incremente el Ruido con respecto a la Señal porque las señales son más débiles y hay más interferencia de los datos adyacentes; por lo tanto el valor de SNR disminuye, y a su vez, la probabilidad de errores de lectura aumenta. Entonces, es necesario mejorar la capacidad del ECC para detectar y corregir errores, generalmente agregándole más bits. Esto requiere de más espacio físico reservado para un sector (siempre de 512 Bytes), y aquí volvemos a empezar.

Lo que sucede es que aquí está el punto; se está llegando a un límite donde no se puede seguir con sectores de 512 Bytes y aumentar el tamaño total del disco, ya que todo este nuevo espacio obtenido con una mayor densidad termina no siendo utilizable, sino que será mayormente para el ECC (es decir, redundancia para contemplar posibles errores).

La solución al problema es que, para almacenar más información globalmente, hay que incrementar la eficiencia del ECC. Y esto se logra haciendo que éste abarque más datos que sólo 512 Bytes; el ECC es mucho más eficiente (ocupa menos espacio en comparación) si su código de corrección abarca más datos, digamos, 4096 Bytes.

Por ejemplo, para detectar y corregir corregir 4096 Bytes divididos en 8 sectores de 512 Bytes (de la vieja forma), necesitamos «gastar» 320 Bytes de ECC (ya que tenemos 40 Bytes por cada ECC de 512 Bytes), mientras que si usamos 1 sector de 4096 Bytes sólo vamos a usar 100 Bytes de ECC. Como se puede ver, uno se ahorra 220 Bytes de overhead por cada 4KB que tiene el disco para guardar cosas; en 1500 GB (= 1.500.000.000 KB / 4 = 375.000.000 sectores de 4 KB * 0,22 KB) son 82,5 GB más de espacio disponible para almacenar datos de usuario y no ECC (un 5,5% más). Esto y sin contar el espacio «desperdiciado» para los gaps entre sectores y el flag de sincronización/inicio de sector (para 4 KB, antes eran 8 y ahora es sólo 1). Además, estos 100 Bytes de ECC mejoran en un 50% la capacidad de detectar errores en «ráfaga» comparado con el anterior, es decir, el nuevo es un mejor y más eficiente ECC.

Por todo esto, para tamaños tan grandes de disco, usar sectores de 4KB nos permite aprovechar de manera más eficiente la mayor densidad del área que disponemos. ¿Y por qué 4 KB? No es un número al azar; coincide con el tamaño de las páginas de memoria en la arquitectura x86 y con el tamaño de cluster por defecto de la mayoría de los sistemas de archivos que pululan por ahí, con lo cual la velocidad de transferencia de páginas desde/hacia el disco no se ve afectada, y la fragmentación interna de los archivos almacenados es la misma que con sectores de 512 Bytes.

Quizás con el gráfico se entienda un poco más; allí se ve cómo ocupan más lugar los 8 sectores de 512 Bytes puestos a la par del sector de 4 KB:

Nuevamente (espero comentarios y corrijo en todo caso), toda esta info está bien explicada en el artículo de AnandTech, en este artículo de Ars Technica, en el Paper de WD y en este artículo de IBM.

Bien, «¿Y qué gano con sectores más grandes? ¿en qué me afecta?», es lo primero que uno se pregunta. Claramente, y por lo explicado recientemente, se gana en confiabilidad y capacidad de almacenamiento hoy y a futuro. ¿Cuáles son las contras? básicamente, el proceso de migración, que como ya se dijo, deben afrontarse desde varias capas de software, desde el BIOS, pasando por el Sistema Operativo y llegando a las herramientas de defragmentación, clonado y administración de discos.

¿Y qué problema hay con Linux? Particiones desalineadas.

Teniendo en mente esto, esta serie de discos de WD emula ser un disco con sectores «lógicos»de 512 bytes, pero en realidad trabaja internamente con sectores «físicos» de 4 KB. De esta manera, los sectores de 512 bytes lógicos se ven así, dentro de uno de 4 KB:

Recordemos, la mínima unidad «direccionable» real del disco son 4 KB (un sector), y el tamaño de cluster por defecto (la mínima unidad «direccionable» por el sistema de archivos) son 4 KB; esto quiere decir en definitiva que el disco, cada vez que lee y escribe lo hace en unidades de 4 KB. Luego le agregamos la capa de emulación, para hacerlo compatible con los SOs que tenemos ahora. Bien, supongamos que vamos a crear una sola partición en el disco. ¿Qué pasa si esta partición, donde vamos a guardar los datos, comienza en el sector 1 (o cualquier sector no múltiplo de 8 ) del disco en vez del sector 0? Va a pasar esto:

Lo que sucede es que el primer cluster empieza y termina en dos sectores físicos; está «desalineado» con respecto a ellos. En realidad, todos los clusters de la partición estarán de esta forma, comenzando y finalizando a «destiempo» respecto de los bloques físicos. El problema que esto conlleva es que si el SO va a escribir algo en el disco (donde el «algo» es como mínimo generalmente un cluster de 4 KB), supongamos el cluster resaltado en azul, esto se transforma físicamente en:

  1. Leer los 4 KB del sector físico 0.
  2. Modificar los 7 sectores lógicos afectados por esta operación.
  3. Grabar los 4 KB del sector físico 0.
  4. Leer los 4 KB del sector físico 1.
  5. Modificar el 8vo sector lógico.
  6. Grabar los 4 KB del sector físico 1.

Esto es, 2 operaciones de Leer-Modificar-Grabar (RMW) atómicas, una para cada sector físico, que involucra una vuelta (spin) de disco por cada lectura/escritura de la lista enumerada. Es decir, que una partición comience en un sector lógico de 512 Bytes no múltiplo de 8 hace excesivamente lento el acceso al disco porque las operaciones llevan mucho, mucho más tiempo que antes.

Y la cuestión reside aquí; si bien Linux a esta altura ya está preparado para manejar discos con sectores de 4 KB, el problema es que el disco «le dice» a Linux que tiene sectores físicos de 512 bytes por la emulación, cuando internamente trabaja con 4 KB:

marcelo@marcelo:~$ sudo hdparm -I /dev/sdb | grep Sector
	Logical/Physical Sector size:           512 bytes

¿Y cuál es la consecuencia? La posibilidad de no tener los sectores alineados. Fdisk y cualquier software particionador de discos de Linux comienza la primer partición en el sector 63 de aquellos discos que reconoce como de sectores de 512 Bytes**. Esto hace que el disco funcione muy lento, como se describía en el foro de WD que cité al comienzo.

Cómo particionar estos discos en general y en Linux en particular

Bueno, ¿cómo se hace para crear particiones de manera alineada? Es relativamente fácil. Según Ted Ts’o, donde explica que hay un problema parecido con los nuevos discos SSD, hay que ejecutar fdisk con los parámetros «-H 224 -S 56 /dev/sdX», siendo /dev/sdX el disco en cuestión; esto hace que todas las particiones se creen en la sesión interactiva de fdisk en sectores múltiplos de 8. Otra opción es usar GNU Parted con los parámetros «unit s», y de esta manera deja a uno configurar el primer sector de cada partición (más info acá).

En mi caso necesitaba crear 4 particiones. Este es un ejemplo de particiones bien alineadas, el último comando es para mostrar el tamaño de cada partición nada más:

marcelo@marcelo:~$ sudo parted /dev/sdb unit s print
Modelo: ATA WDC WD15EARS-00S (scsi)
Disco /dev/sdb: 2930277168s
Tamaño de sector (lógico/físico): 512B/512B
Tabla de particiones. msdos
 
Numero  Inicio       Fin          Tamaño       Tipo     Sistema de ficheros  Banderas
 1      56s          41959679s    41959624s    primary  ext4
 2      41959680s    46161919s    4202240s     primary
 3      46161920s    1673570303s  1627408384s  primary  ext4
 4      1673570304s  2930265855s  1256695552s  primary                       raid
 
marcelo@marcelo:~$ sudo fdisk -lu /dev/sdb
 
Disco /dev/sdb: 1500.3 GB, 1500301910016 bytes
224 cabezas, 56 sectores/pista, 233599 cilindros, 2930277168 sectores en total
Unidades = sectores de 1 * 512 = 512 bytes
Tamaño de sector (lógico / físico): 512 bytes / 512 bytes
Tamaño E/S (mínimo/óptimo): 512 bytes / 512 bytes
Identificador de disco: 0x00094da1
 
Dispositivo Inicio    Comienzo      Fin      Bloques  Id  Sistema
/dev/sdb1   *          56    41959679    20979812   83  Linux
/dev/sdb2        41959680    46161919     2101120   82  Linux swap / Solaris
/dev/sdb3        46161920  1673570303   813704192   83  Linux
/dev/sdb4      1673570304  2930265855   628347776   fd  Linux raid autodetect
 
marcelo@marcelo:~$ sudo parted /dev/sdb print
Modelo: ATA WDC WD15EARS-00S (scsi)
Disco /dev/sdb: 1500GB
Tamaño de sector (lógico/físico): 512B/512B
Tabla de particiones. msdos
 
Numero  Inicio  Fin     Tamaño  Tipo     Sistema de ficheros  Banderas
 1      28,7kB  21,5GB  21,5GB  primary  ext4
 2      21,5GB  23,6GB  2152MB  primary
 3      23,6GB  857GB   833GB   primary  ext4
 4      857GB   1500GB  643GB   primary                       raid

Nuevamente: Lo más importante para que los clusters estén alineados con los sectores físicos del disco es que cada partición debe comenzar en un sector múltiplo de 8, como el 56, 41959680, 46161920 y 1673570304 de este caso.

Conclusión

Bueno, fue un artículo muy largo, donde me pareció que servía explayarse en el porqué de los sectores más grandes y qué problemas trae.  Tuve la grata oportunidad de intercambiar algunos mails al respecto con Aleksander Adamowski, la persona que en la lista de util-linux-ng «descubrió» el inconveniente de la lentitud con esta serie de discos WD a base de un lote de pruebas disponible aquí.

Aleksander me recomendó, en resumidas cuentas, al trabajar con discos > 1 TB «sospechosos» de tener sectores de 4 KB:

  • «Las unidades de medida son críticas. Asegúrate que estás realmente operando a nivel de sectores***
  • Después , hacer un test de performance es buena idea.
  • Para esto, primero trata de crear una partición desalineada, crea un sistema de archivos, y ejecuta el benchmark de postmark usando el archivo de configuración que publiqué (http://olo.org.pl/files/hw/postmark-automated/postmark-quick.conf – por supuesto, modifica la opción «location» en ese archivo acorde al disco a comprobar.
  • Luego, borra todas las particiones y haz lo mismo en una partición alineada. Los resultados deben ser mucho mejores en cuanto al rendimiento. Si no lo son, el disco probablemente tiene sectores físicos de 512 Bytes.»

En resumen, hay que estar atentos. Sería bueno que los futuros discos que salgan con sectores de 4 KB informaran al SO qué estructura real tienen, y eliminar el «modo compatibilidad» de una vez por todas.

Espero que les sirva.
Saludos

* En tiempos donde la capacidad de los discos era muy pequeña comparada con los de ahora, el tamaño de un cluster del sistema de archivos era igual al de un sector.

** La utilización del sector 63 corresponde a que generalmente (y por herencia histórica del modelo de direccionamiento CHS) es el primer sector del track número 1. El track 0 siempre se utilizó para el MBR / Master Boot Record.

*** Esto porque por defecto las herramientas de particionamiento Linux no trabajan con sectores; fdisk trabaja con cilindros por ejemplo.

Categories: codear, linux, tests, ubuntu-ar Tags: