md raid5: traduce los números del sector interno de md a compensaciones

8

Resumen de TL; DR : traduzca un número de sector de md en compensaciones dentro del /dev/mdXdispositivo y cómo investigarlo xfs_db. El número de sector es de sh->sectoradentro linux/drivers/md/raid5.c:handle_parity_checks5().

No conozco las partes internas de MD, por lo que no sé exactamente qué hacer con la salida del printkregistro que agregué.

Las compensaciones en los dispositivos componentes (para ddo un editor / visor hexadecimal) también serían interesantes.

Supongo que debería preguntar esto en la lista de correo de incursiones de Linux. ¿Es solo para suscriptores, o puedo publicar sin suscribirme?


Tengo xfs directamente sobre MD RAID5 de 4 discos en mi escritorio (sin LVM). Un matorral reciente detectó un valor distinto de cero mismatch_cnt(8 de hecho, porque md opera en páginas de 4 kB a la vez).

Este es un RAID5, no RAID1 / RAID10 donde mismatch_cnt! = 0 puede ocurrir durante la operación normal . (Los otros enlaces en la parte inferior de esta página wiki pueden ser útiles para algunas personas).

Podría hacerlo a ciegas repair, pero no tendría idea de qué archivo verificar para detectar posibles daños, además de perder cualquier oportunidad de elegir qué camino reconstruir. La respuesta de Frostschutz a una pregunta similar es la única sugerencia que encontré para rastrear una diferencia en el sistema de archivos. Es engorroso y lento, y prefiero usar algo mejor para reducirlo primero a unos pocos archivos.


Parche de kernel para agregar registro

Curiosamente, la función de verificación de md no informa dónde se encontró un error . Agregué un printkmd / raid5.c para iniciar sesión sh->sectoren la iframa que se incrementa mddev->resync_mismatchesenhandle_parity_checks5() (pequeño parche publicado en github , originalmente basado en 4.5-rc4 de kernel.org). Para que esto sea correcto para uso general, probablemente sea necesario evite inundar los registros en reparaciones con muchos desajustes (tal vez solo registre si el nuevo valor de resync_mismatcheses <1000?). También tal vez solo inicie sesión checky no repair.

Estoy bastante seguro de que estoy registrando algo útil (¡aunque no conozco los componentes internos de MD!), Porque la misma función imprime ese número de sector en el caso de manejo de errores delswitch .

Compilé mi kernel modificado y lo arranqué, luego volví a ejecutar el cheque:

[  399.957203] md: data-check of RAID array md125
...
[  399.957215] md: using 128k window, over a total of 2441757696k.
...
[21369.258985] md/raid:md125: check found mismatch at sector 4294708224    <-- custom log message
[25667.351869] md: md125: data-check done.

Ahora no sé exactamente qué hacer con ese número de sector. ¿Hay sh->sector * 512una dirección lineal dentro /dev/md/t-r5(aka /dev/md125)? ¿Es un número de sector dentro de cada dispositivo componente (por lo que se refiere a tres datos y un sector de paridad)? Supongo que esto último, ya que una falta de coincidencia de paridad en RAID5 significa que los sectores N-1 del dispositivo md están en peligro, compensados ​​entre sí por la unidad de banda. ¿Es el sector 0 el comienzo mismo del dispositivo componente, o es el sector después del superbloque o algo así? ¿Hubo más información handle_parity_checks5()que debería haber calculado / registrado?

Si quisiera obtener solo los bloques que no coinciden, ¿es esto correcto?

dd if=/dev/sda6 of=mmblock.0 bs=512 count=8 skip=4294708224
dd if=/dev/sdb6 of=mmblock.1 bs=512 count=8 skip=4294708224
dd if=/dev/sda6 of=mmblock.2 bs=512 count=8 skip=4294708224
dd if=/dev/sdd  of=mmblock.3 bs=512 count=8 skip=4294708224  ## not a typo: my 4th component is a smaller full-disk

# i.e.
sec_block() { for dev in {a,b,c}6 d; do dd if=/dev/sd"$dev" of="sec$1.$dev"  skip="$1"  bs=512 count=8;done; }; sec_block 123456

Supongo que no, porque obtengo 4k de ceros de los cuatro componentes de la incursión y 0^0 == 0, por lo tanto, esa debería ser la paridad correcta, ¿verdad?

Otro lugar en el que he visto mencionar el uso de direcciones de sector en md es para sync_miny sync_max(en sysfs). Neil Brown en la lista de incursiones de Linux , en respuesta a una pregunta sobre una unidad fallida con números de sector de hdrecover, donde Neil utilizó el número de sector de disco completo como un número de sector de MD. Eso no está bien, ¿verdad? ¿No serían los números de sector md relativos a los dispositivos componentes (particiones en ese caso), no al dispositivo completo del que forma parte la partición?


sector lineal a nombre de archivo XFS:

Antes de darme cuenta de que el número de sector md era probablemente para los componentes, no para el dispositivo RAID, intenté usarlo en solo lectura xfs_db:

La breve sugerencia de Dave Chinner sobre cómo encontrar cómo XFS está utilizando un bloque dado no me pareció en absoluto útil. (Hubiera esperado algún tipo de resultado, para algún sector, ya que el número no debería estar más allá del final del dispositivo, incluso si no es el sector no coincidente)

# xfs_db -r /dev/md/t-r5 
xfs_db> convert daddr 4294708224 fsblock
0x29ad5e00 (699227648)
xfs_db> blockget -nv -b 699227648
xfs_db> blockuse -n       # with or without -c 8
must run blockget first

eh? ¿Qué estoy haciendo mal aquí? Supongo que esta debería ser una pregunta separada. Reemplazaré esto con un enlace si / cuando lo pregunto o encuentro una respuesta a esta parte en otro lugar.

Mi RAID5 está esencialmente inactivo, sin actividad de escritura y lectura mínima (y noatime, por lo tanto, las lecturas no producen escrituras).


Cosas adicionales sobre mi configuración, nada importante aquí

Muchos de mis archivos son videos u otros datos comprimidos que brindan una manera efectiva de saber si los datos son correctos o no (ya sea sumas de verificación internas en el formato de archivo o simplemente si se decodifica sin errores). Eso haría viable este método de bucle invertido de solo lectura , una vez que sepa qué archivo verificar. Sin embargo, no quería ejecutar una diferencia de 4 vías de cada archivo en el sistema de archivos para encontrar la discrepancia, cuando el núcleo tiene la información necesaria durante la verificación, y podría registrarla fácilmente.


mi /proc/mdstatpara mi matriz de datos masivos:

md125 : active raid5 sdd[3] sda6[0] sdb6[1] sdc6[4]
      7325273088 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
      bitmap: 0/19 pages [0KB], 65536KB chunk

Está en particiones en tres unidades Toshiba de 3 TB y en una unidad WD25EZRS de energía verde (lenta) no particionada que estoy reemplazando por otra Toshiba. (Solía mdadm --replacehacerlo en línea sin vacíos en la redundancia. Después de una copia me di cuenta de que debería verificar el estado de RAID antes y después para detectar problemas. Fue entonces cuando detecté la falta de coincidencia. Es posible que haya existido durante mucho tiempo , ya que tuve algunos bloqueos hace casi un año, pero no tengo registros antiguos y mdadm no parece enviar correos sobre esto por defecto (Ubuntu 15.10).

Mis otros sistemas de archivos están en dispositivos RAID10f2 hechos de particiones anteriores en los tres HD más grandes (y RAID0 para / var / tmp). El RAID5 es solo para almacenamiento masivo, no /homeo /.

Mis unidades están bien: los recuentos de errores SMART son 0 todos los contadores de bloques defectuosos en todas las unidades, y se superaron las pruebas automáticas SMART cortas + largas.


casi duplicados de esta pregunta que no tienen respuestas:

Peter Cordes
fuente
Si el número en su printk es un sector relativo a la matriz, entonces debe dividirlo por el ancho de la franja y posiblemente agregar el desplazamiento inicial para convertirlo en un número de sector relativo al dispositivo componente. iirc, si está utilizando un formato de metadatos mdadm que no siempre inicia los datos en el desplazamiento cero, el desplazamiento donde comienza aparece en la salida de mdadm -E /dev/xxx.
psusi
También tenga en cuenta que incluso si encuentra la ubicación de los datos y puede verificar la falta de coincidencia, y tiene una forma de verificar la integridad del archivo que está dañado (si los datos incluso pertenecen a un archivo; puede que sea gratuito espacio o metadatos fs), entonces es bastante posible e incluso probable que la paridad también sea incorrecta y, por lo tanto, ninguna de las posibles respuestas que obtendrá al enmascarar cada una de las unidades de datos será correcta.
psusi
@psusi: gracias, sí, sé que podría no ser parte de un archivo. Fue difícil expresar eso sin hacer que mis oraciones fueran realmente torpes. Punto interesante de que tal vez ninguna de las reconstrucciones sea correcta, sí, eso es posible. De cualquier manera, estaría mucho más feliz de saber a qué archivo cambiarle el nombre .damagedo algo así, en lugar de saber que probablemente hay un archivo roto en alguna parte.
Peter Cordes

Respuestas:

2

TL; DR sh-> sector es el número de sectores en los discos físicos después del inicio de la sección de datos


Preparar

Aquí hay una configuración de prueba simple para ilustrar:

  • / dev / raidme / rd [0-3], dispositivos de 2GB
  • / dev / md127 creado como un raid5 sobre estos 5, iniciado como xfs y lleno de datos aleatorios

Ahora, para comenzar, obtenga un bloque distinto de cero y sobrescríbalo

# dd if=/dev/raidme/rd0 bs=1k count=1 skip=10240 | hexdump -C | head
...
# dd if=/dev/zero of=/dev/raidme/rd0 bs=1k count=1 seek=10240
...
# dd if=/dev/raidme/rd2 bs=1k count=1 skip=10240 | hexdump  -C | head
1024 bytes (1.0 kB, 1.0 KiB) copied, 8.6021e-05 s, 11.9 MB/s
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400

Asegúrese de que el caché dm / md se vacíe deteniendo / reensamblando la matriz y verifique:

# mdadm --stop /dev/md127
# mdadm --assemble /dev/md127 /dev/raidme/rd*
# echo check > /sys/class/block/md127/md/sync_action
# dmesg | tail
...
[ 1188.057900] md/raid:md127: check found mismatch at sector 16384

Bloquear en discos

Bien, entonces primero verifiquemos que 16384 coincida con lo que escribimos. Mi incursión tiene una banda de 512k, así que me aseguré de escribir algo alineado para que sea fácil de combinar, escribimos en 1024*10240ie0xa00000 .

Su parche proporciona la información 16384, una cosa a tener en cuenta es que los datos no comienzan en 0:

# mdadm -E /dev/raidme/rd0 | grep "Data Offset"
    Data Offset : 4096 sectors

Eso printf "%x\n" $(((4096+16384)*512))dice que también está 0xa00000bien. Bueno.


Bloquear en md

Ahora, para llegar a donde está en el extremo de md, en realidad es más fácil: es simplemente la posición dada en tiempos de sector number_of_stripes por ejemplo, para mí tengo 4 discos (3 + 1), así que 3 franjas.

Aquí, significa, 16384*3*512por ejemplo 0x1800000. Llené el disco bastante bien, así que es fácil verificarlo solo leyendo el disco y buscando 1k de ceros:

# dd if=/dev/md127 bs=1M | hexdump -C | grep -C 3 '00 00 00 00 00 00'
... some false positives...
01800000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
01800400  6b a8 9e e0 ad 88 a8 de  dd 2e 68 00 d8 7a a3 52  |k.........h..z.R|

Bloquear en xfs

Frio. Veamos dónde está eso en xfs ahora. 16384*3es 49152(daddr toma el número de sector):

# xfs_db -r /dev/md127
xfs_db> blockget -n
xfs_db> daddr 49152
xfs_db> blockuse -n
block 6144 (0/6144) type data inode 2052 d.1/f.1

Seguramente, los ceros están en ese archivo:

# dd if=/mnt/d.1/f.1 bs=1M | hexdump -C | grep -C 3 '00 00 00 00 00'
...
03680000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
03680400  6b a8 9e e0 ad 88 a8 de  dd 2e 68 00 d8 7a a3 52  |k.........h..z.R|

Si sobrescribimos ese archivo, los ceros desaparecen en / dev / raidme / rd0 en el desplazamiento correcto también (solo dd con otro archivo). Si vuelve a escribir / dev / raidme / rd0 (asegúrese de detener / iniciar la matriz nuevamente), los ceros están de vuelta. Se ve bien.

Sin embargo, hay un problema más, si el tamaño de su banda es tan grande como el mío aquí (512k), entonces no tenemos un solo bloque para tratar, pero 1.5 MB de posibles datos corrompidos ... A menudo, eso será suficiente en un solo archivo, pero necesita verificar eso, nuevamente en xfs_db. Recuerde que el inodo anterior era 2052.

xfs_db> inode 2052
xfs_db> bmap
data offset 0 startblock 256 (0/256) count 17536 flag 0
data offset 17536 startblock 122880 (0/122880) count 4992 flag 0
data offset 22528 startblock 91136 (0/91136) count 3072 flag 0

Un bloque tiene un tamaño de 4096 bytes aquí (ver xfs_info), por lo que nuestro 1.5MB son 384 bloques. Nuestro segmento dañado es el bloque 6144 a 6528, bien dentro del primer segmento de este archivo.

Otra cosa a tener en cuenta sería extraer los bloques a mano y verificar dónde no coinciden exactamente las sumas de comprobación, lo que con suerte le dará 3 fragmentos más pequeños para mirar.


Por último sobre su parche, no soy un desarrollador de md, pero como usuario de ex-mdadm raid5 me habría interesado bastante. Yo diría que definitivamente vale la pena el esfuerzo para impulsarlo un poco. La limpieza que mencionó podría ser útil y estoy seguro de que los desarrolladores tendrán algunos comentarios una vez que envíe un parche, ¡pero diablos, md debe ser más detallado sobre estos errores!

Asmadeus
fuente
Huh, me alegra que hayas señalado la posición en los dispositivos de bloque subyacentes. En mi caso, printf '%#x\n' $(( (259072+4294708224 )*512 ))es 0x20000000000, que obviamente no es una coincidencia. (Eso es 2TiB precisamente. Sospecho que algunas travesuras de grub-install o algún tipo de MBR). No habría notado esto si solo estuviera mirando las compensaciones dentro del dispositivo MD para encontrar el archivo afectado. (Por cierto, el %#xformato agrega el 0xprefijo para usted.)
Peter Cordes
xfs_dbsolo dice must run blockget first, a pesar de que acabo de hacerlo (exactamente como publiqué en la pregunta), después de seguir su ejemplo. Incluso si solía blockget -v -n -b 12884124672darle un bloque específico. Solía ddy hexdumpal descubrir que en realidad hay una falta de coincidencia en ese bloque, sin embargo. Tres son todos cero, y el cuarto tiene un único conjunto de un bit a 1 KB en la banda de 512k. (Muy conveniente que no tuve que encontrar una manera de bloquear XOR para verificar la redundancia.)
Peter Cordes
Si uso daddrprimero (antes del bloqueo), no recibo un mensaje de error, simplemente no hay salida de blockget -v -ny blockuse -v -n. En caso de que sea importante, mi xfsprogs es 3.2.1ubuntu1, y estoy usando Linux 4.2.0-36-generic (no mi parche -rc kernel). Mi FS está usando crc=1 isize=512, naming =version 2 bsize=4096 ascii-ci=0 ftype=1
Peter Cordes
De todos modos, esta respuesta identifica correctamente la ubicación del bloque que no coincide en los dispositivos componentes y en el dispositivo md. La única pieza que no funciona es la parte del bloque XFS-> nombre de archivo, que es realmente una pregunta separada. En teoría, podría usar find -exec xfs_bmap -vpl {} +para buscar un archivo que contenga el bloque conocido.
Peter Cordes
1
Desafortunadamente, no conozco ninguna forma de hacer que xfs_db ignore el diario de registro (por ejemplo, forzar el bloqueo incluso si no es 100% consistente), o hacer que el núcleo "vacíe" ese registro como lo haría un montaje / montaje y hacer feliz a xfs_db. .. Así que sí, a menos que quieras criticar algo, es posible que tengas que esperar un poco hasta que puedas volver a montar. Mantenme actualizado y no olvides intentar
subir