Solucionando el error “attempt to access beyond end of device” con reglas de udev, hal y/o un parche del kernel
Recientemente actualicé mi Debian Lenny/Testing como suelo hacer de vez en cuando. No sé exactamente qué paquetes se actualizarían pero empezó a ocurrir algo que no me gustaba: Tres veces durante el arranque se me llenaba la pantalla de cientos de mensajes como el siguiente:
attempt to access beyond end of device sdb: rw=0, want=3636361172, limit=398297088 attempt to access beyond end of device sdb: rw=0, want=3636361176, limit=398297088
Y uno de los problemas que me generaban estos errores es que me llenaban el buffer circular de mensajes del kernel y no podía ver los mensajes de arranque del kernel con dmesg.
Yo tengo dos discos Maxtor SATA iguales en RAID 0 usando los servicios de la placa con el chipset NVidia NForce 4. El RAID se activa automáticamente durante el arranque gracias a que el initrd ejecuta el comando dmraid durante el arranque (ya salió esto en Hibernación en Linux con TuxOnIce. Notas sobre los initrd y sobre cpio.). Tras ejecutar el dmraid, unos nuevos ficheros de dispositivo que representan al disco lógico formado por los dos discos físicos son creados en /dev/mapper/ :
# ll /dev/mapper/ total 0 drwxr-xr-x 2 root root 180 2007-11-18 22:03 ./ drwxr-xr-x 14 root root 5880 2007-11-18 21:04 ../ crw-rw---- 1 root root 10, 63 2007-11-18 22:03 control brw-rw---- 1 root disk 254, 0 2007-11-18 22:03 nvidia_bdehcbaa brw-rw---- 1 root disk 254, 1 2007-11-18 22:03 nvidia_bdehcbaa1 brw-rw---- 1 root disk 254, 2 2007-11-18 22:03 nvidia_bdehcbaa2 brw-rw---- 1 root disk 254, 3 2007-11-18 21:03 nvidia_bdehcbaa3 brw-rw---- 1 root disk 254, 4 2007-11-18 22:03 nvidia_bdehcbaa5 brw-rw---- 1 root disk 254, 5 2007-11-18 22:03 nvidia_bdehcbaa6
Los ficheros de dispositivo de los discos físicos (en mi caso /dev/sdb y /dev/sdc) no tienen ninguna utilidad desde ese momento.
Sin embargo, en el primer sector del primero de los de los discos del RAID, en /dev/sdb sí hay una tabla de particiones, lo que pasa es que no tiene sentido aplicada a ese disco, y sí aplicada a todo el RAID:
# fdisk /dev/mapper/nvidia_bdehcbaa
Command (m for help): p
Disk /dev/mapper/nvidia_bdehcbaa: 407.8 GB, 407856087040 bytes
255 heads, 63 sectors/track, 49585 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xffffffff
Device Boot Start End Blocks Id System
/dev/mapper/nvidia_bdehcbaa1 * 1 4079 32764536 7 HPFS/NTFS
/dev/mapper/nvidia_bdehcbaa2 4080 8158 32764567+ c W95 FAT32 (LBA)
/dev/mapper/nvidia_bdehcbaa3 8159 9375 9775552+ 83 Linux
/dev/mapper/nvidia_bdehcbaa4 9376 49585 322986825 f W95 Ext'd (LBA)
/dev/mapper/nvidia_bdehcbaa5 9376 9862 3911796 82 Linux swap / Solaris
/dev/mapper/nvidia_bdehcbaa6 9863 49585 319074966 83 Linux
# fdisk /dev/sdb
Command (m for help): p
Disk /dev/sdb: 203.9 GB, 203928109056 bytes
255 heads, 63 sectors/track, 24792 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x00100058
Device Boot Start End Blocks Id System
/dev/sdb1 * 92547 133645 330121216 ec Unknown
Partition 1 does not end on cylinder boundary.
/dev/sdb2 158380 304655 1174951567+ 0 Empty
Partition 2 does not end on cylinder boundary.
/dev/sdb3 226354 301364 602522742 83 Linux
Partition 3 does not end on cylinder boundary.
/dev/sdb4 4 4 0 0 Empty
Partition 4 does not end on cylinder boundary.
Por tanto, cualquier acceso a esas particioness (sdbn) tendrá como resultado el error del que hablábamos al principio.
# dd if=/dev/sdb1 of=/dev/null count=1 bs=512 2>&1 attempt to access beyond end of device sdb: rw=0, want=1486754274, limit=398297088 Buffer I/O error on device sdb1, logical block 0 attempt to access beyond end of device sdb: rw=0, want=1486754282, limit=398297088 Buffer I/O error on device sdb1, logical block 1 attempt to access beyond end of device sdb: rw=0, want=1486754290, limit=398297088 Buffer I/O error on device sdb1, logical block 2 attempt to access beyond end of device sdb: rw=0, want=1486754298, limit=398297088 Buffer I/O error on device sdb1, logical block 3 attempt to access beyond end of device sdb: rw=0, want=1486754274, limit=398297088 Buffer I/O error on device sdb1, logical block 0 dd: reading `/dev/sdb1': Input/output error 0+0 records in 0+0 records out 0 bytes (0 B) copied, 0.129062 seconds, 0.0 kB/s
Entonces, ¿por qué salen tres bloques con cientos de errores durante el arranque? ¿Qué hay durante el arranque que trate de acceder a dichas particiones?
Tras muchas pruebas, conseguí determinar que el demonio udevd que se ejecuta desde el initrd, el que se ejecuta de nuevo una vez montado el sistema de ficheros raíz y el demonio hald eran los tres procesos que causaban la avalancha de errores.
Por tanto, toca repasar la entrada Creación de reglas udev para personalizar el nombre de los ficheros de dispositivo de las memorias USB y el documento Writing udev rules para ver cómo podemos evitar que el udevd trate de escanear dichas particiones inexistentes.
Y es en la opción ignore_device donde encontramos una solución al problema. ¡Pero ojo! Si creamos una regla como esta:
BUS=="scsi", ATTRS{model}=="Maxtor 6B200M0 ", OPTIONS+="ignore_device"
los ficheros de los discos sdb y sdc no se crearán, el dmraid no podrá formar el RAID y no conseguiremos arrancar el sistema (el kernel nos dará un panic, de hecho). Es mucho mejor decirle al udev que simplemente no nos cree los ficheros de dispositivo de las particiones:
KERNEL=="sdb1", OPTIONS+="ignore_device" KERNEL=="sdb2", OPTIONS+="ignore_device" KERNEL=="sdb3", OPTIONS+="ignore_device" KERNEL=="sdb4", OPTIONS+="ignore_device"
Si reiniciamos tras crear la regla, no tendremos los errores de uno de los udevd pero sí del que se ejecuta desde el initrd. Para evitarlo, no tenemos que olvidar hacer un mkinitramfs para que las reglas se actualicen también en el initrd.
Comprobamos que ya no se crean los ficheros de dispositivo de las particiones:
# ll /dev/sdb* brw-rw---- 1 root disk 8, 16 2007-11-18 23:02 sdb
Tras modificar las reglas, como ya no hay ficheros de dispositivo, el hald ya no genera errores tampoco, pero en mis pruebas he encontrado la forma de que no dé errores aunque los ficheros de dispositivo existieran. Usando como ejemplo las reglas existentes para ejecutar antes de probar los dispositivos en /usr/share/hal/fdi/preprobe/, creo el fichero etc/hal/fdi/preprobe/10-vicente.fdi con el siguiente contenido:
<?xml version="1.0" encoding="UTF-8"?>
<deviceinfo version="0.2">
<device>
<match key="scsi.model" string="Maxtor 6B200M0">
<merge key="info.ignore" type="bool">true</merge>
</match>
</device>
</deviceinfo>
Con esta regla, estoy diciéndole al hald que ignore los dispositivos con el scsi.model que a mí me interesa. La información necesaria para construir las reglas la podemos obtener del comando lshal. Precisamente, tras crear la regla y hacer un /etc/init.d/hald restart vemos que en la salida del lshal ya nos aparece el dato de que el dispositivo va a ser ignorado (info.ignore = true (bool)):
udi = '/org/freedesktop/Hal/devices/temp/30' info.bus = 'scsi' (string) info.ignore = true (bool) info.linux.driver = 'sd' (string) info.parent = '/org/freedesktop/Hal/devices/pci_10de_55_scsi_host_0' (string) info.product = 'Ignored Device' (string) info.subsystem = 'scsi' (string) info.udi = '/org/freedesktop/Hal/devices/ignored-device' (string) linux.hotplug_type = 2 (0x2) (int) linux.subsystem = 'scsi' (string) linux.sysfs_path = '/sys/devices/pci0000:00/0000:00:08.0/host4/target4:0:0/4:0:0:0' (string) scsi.bus = 0 (0x0) (int) scsi.host = 4 (0x4) (int) scsi.lun = 0 (0x0) (int) scsi.model = 'Maxtor 6B200M0' (string) scsi.target = 0 (0x0) (int) scsi.type = 'disk' (string) scsi.vendor = 'ATA' (string)
Esto podemos usarlo también si no nos interesa por algún motivo que al introducir ciertas memorias USB no nos salga el típico diálogo de posibles acciones a realizar con el dispositivo introducido. Y también podemos configurar el montaje automático de las unidades extraíbles con reglas del hald. Podemos echarle un vistazo a las reglas comentadas de /etc/hal/fdi/policy/preferences.fdi para entender un poco cómo funciona.
Pero aún tenemos una alternativa mejor que crear reglas de udev o hal. En avoid creation of partitions beyond actual capacity (patch for 2.6.15), Gerte Hoogewerf propone un parche para que el kernel evite las particiones que supuestamente van más allá de la capacidad del disco. Se trata únicamente de una pequeña modificación en el fichero fs/partitions/check.c. Como el parche no se aplica sobre el kernel 2.6.22.10 lo he adaptado y lo dejo aquí a disposición del que lo quiera usar: partition_check_2.6.22.10.patch
Para aplicarlo hacemos:
# cd /usr/src/linux # patch -p1 < /path_al_parche/partition_check_2.6.22.10.patch patching file fs/partitions/check.c
Y si queremos quitarlo hacemos lo mismo pero con la opción -R:
# patch -p1 -R < /path_al_parche/partition_check_2.6.22.10.patch patching file fs/partitions/check.c
El parche debería de servir para otras versiones del kernel recientes. Podemos probar a aplicarlo en otras versiones. Si no es aplicable, simplemente no lo aplicará:
# patch -p1 < /path_al_parche/partition_check_2.6.22.10.patch patching file fs/partitions/check.c Hunk #1 FAILED at 182. 1 out of 1 hunk FAILED -- saving rejects to file fs/partitions/check.c.rej
Tras aplicar el parche, recompilar el kernel y reiniciar con el nuevo kernel parcheado, vemos que las particiones erróneas son descartadas:
sd 3:0:0:0: [sdb] 398297088 512-byte hardware sectors (203928 MB) sd 3:0:0:0: [sdb] Write Protect is off sd 3:0:0:0: [sdb] Mode Sense: 00 3a 00 00 sd 3:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA sd 3:0:0:0: [sdb] 398297088 512-byte hardware sectors (203928 MB) sd 3:0:0:0: [sdb] Write Protect is off sd 3:0:0:0: [sdb] Mode Sense: 00 3a 00 00 sd 3:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA sdb: sdb1 sdb2 sdb3 sdb: partition sdb1 beyond device capacity sdb: partition sdb2 beyond device capacity sdb: partition sdb3 beyond device capacity sd 3:0:0:0: [sdb] Attached SCSI disk
¡Así que ya está el problema resuelto por este otro camino! ¿No os parece que este parche se debería de incluir en el kernel estándar?
Anexo sobre cómo crear un parche del kernel
Para crear un parche del kernel, nos preparamos dos directorios iguales con las fuentes del kernel totalmente limpias. Podemos descomprimir las fuentes del kernel y renombrar el directorio donde se han descomprimido o hacer un make mrproper al un kernel que ya hemos configurado y compilado, pero perderemos el .config y habrá que recompilar todo desde cero.
Por ejemplo, podemos hacer (cuidado con no reemplazar las fuentes que solemos usar si descomprimimos en /usr/src):
# tar xvfz linux-2.6.XX.YY.tar.bz2 # mv linux-2.6.XX.YY linux-2.6.XX.YY-vanila # cp -rp linux-2.6.XX.YY-vanila linux-2.6.XX.YY-new
Hacemos las modificaciones en el kernel del directorio linux-2.6.XX.YY-new y obtenemos el parche ejecutando, desde fuera de ambos directorios:
# diff -uNr linux-2.6.XX.YY-vanila linux-2.6.XX.YY-new > foobar.patch
Actualización 9/12/07: El parche parece que funciona bien con el kernel 2.6.23.9.
:wq





Muy interesante la entrada!, siempre aprendo algo nuevo con tus posts. Sigo echando de menos ese artículo sobre las distintas maneras de compilar el kernel
.
Saludos, Iván.
@Iván ¡Gracias! Te prometo que está en la cola
¡Uauh!! Ya me gustaría a mi dominar linux tan a fondo como tú. Por otro lado, estaría bien que hubiera un apartado “Sobre mí”, donde hicieras un resumen sobre cómo has cogido estos conocimientos, nada personal, simplemente para saber qué hay que hacer para llegar a este nivel y dejar de pensar que eres de otra galaxia
, sino que es posible con trabajo y constancia.
De verdad, con sinceridad, a los lectores como yo les pica la curiosidad sobre la trayectoria profesional de los que nos sorprenden por su competencia.
@Ringmaster Desde luego, realmente te has empeñado en sonrojarme
.
Hace unos meses ya escribí una especie de “Sobre mí y Linux”: Los Linux de mi vida
Así que es sólo eso, la experiencia y leer documentación y más documentación
.
Gracias por el enlace a tan nostálgico anuncio, ¡Super Coco! ¿Para cuándo un listado de tus entradas más leídas? (Y así no se me pasarían entradas tan interesantes como esa, ya sé que no sería una solución perfecta, pero bueno)…
@Ringmaster Aunque la hubiera, ya te digo yo que precisamente esa no estaría entre ellas
Muy buen artículo, interesante y bien explicado
@RuBiCK Gracias
Hola Super Coco, tengo una duda sobre ‘preferencias’: ¿dmraid o mdadm?
Me he fijado en que usas dmraid y, ‘sabiendo que sabes’ más que yo, me he preguntado ‘qué sabe él que yo (que nunca he usado dmraid, sólo mdadm) no sé’
Por ahora a mi me ha ido muy bien con mdadm, concretamente me ha sorprendido la flexibilidad:
Comparto dos discos (/dev/hdb y /dev/sda; ¡funcionando sobre controladoras diferentes!: uno IDE, el otro SATA) con una partición RAID 0 (juegos), una partición RAID 1 (mis documentos / home) y una partición linear/extendida (para aprovechar el resto de espacio, que no es el mismo en ambos discos, para ‘descargas’) entre un Windows XP* y Ubuntu (y hay mas particiones en esos dos discos).
Por lo que tengo entendido a diferencia de mdadm (que es ‘softwareRAID’) dmraid es para usar con ‘fakeRAID’. Esto supongo que limitará su uso a placas base con controladoras que soporten RAID en la BIOS (mi controladora SATA lo soporta, la IDE no). Pero en cualquier caso el ‘fakeRAID’ (a diferencia del ‘RAID hardware’ de verdad) acaba realizándose a nivel software (aunque inicialmente este software sea la BIOS), con lo que no deberían existir diferencias de rendimiento significativas.
Así que volviendo al principio: ¿qué sabes tú que yo no sé
? ¿por qué en tu caso usas dmraid?, en resumen: ¿donde tiene ventaja dmraid sobre mdadm?
Y ya que estamos, otra pregunta: ¿alguien ha probado a montar desde mdadm discos antes montados con dmraid o viceversa?
* Por si alguien no lo sabe: Windows XP sólo soporta oficialmente RAID 0 por software**, pero se puede parchear para que soporte RAID 1 (y RAID 5) por software; ver http://www.tomshardware.com/2004/11/19/using_windowsxp_to_make_raid_5_happen/ o un resumen en español en http://wiki.mundodisco.net/index.php/RAID-1_y_RAID-5_en_Windows_XP
** Windows soporta RAID software para todos los discos menos el del sistema: no puede arrancar desde RAID software; pero si soporta arrancar desde fakeRAID. (Linux no tiene esta restricción.)
@NeoPolus Has explicado perfectamente la diferencia entre
mdadmydmraid. Yo uso el RAID de la BIOS porque me permite tener dos discos iguales SATA en RAID0 de forma transparente independientemente de si estoy en Windows o en Linux. Probablemente, para un sistema sólo con Linux sea mucho más flexible usarmdadm, pero así puedo usar las mismas particiones en RAID0 desde ambos sistemas operativos.