Considere un dispositivo de bloque sin procesar de 100 MB como un ejemplo simple. Es decir, 204800 bloques de 512 bytes cada uno para un total de 102760448 bytes.
El desafío es cambiar los primeros 98 MB (bloques 200704) para que haya un espacio de 2 MB (4096 bloques) delante. Hacer esto en el lugar requiere que no se escriba nada en un sector que no se haya leído. Una forma de lograr esto es introducir un búfer:
$ dd if=/dev/sdj2 count=200704 | mbuffer -s 512 -b 4096 -P 100 | dd of=/dev/sdj2 seek=4096
La expectativa es que mbuffer
almacenará 4096 bloques antes de pasar cualquier cosa al escritor, asegurando así que no se escriba nada en un área que no se haya leído y que el escritor retrase al lector por el tamaño del búfer. El búfer debe permitir que el lector y el escritor operen lo más rápido posible dentro de esos constriantes.
Sin embargo, no parece funcionar de manera confiable. Intenté usar dispositivos reales pero nunca funciona en ellos, mientras que los experimentos con un archivo funcionaron en mi caja de 64 bits pero no en mi caja de 32 bits.
Primero, algo de preparación:
$ dd if=/dev/sdj2 count=200704 | md5sum
0f0727f6644dac7a6ec60ea98ffc6da9
$ dd if=/dev/sdj2 count=200704 of=testfile
Esto no funciona:
$ dd if=/dev/sdj2 count=200704 | mbuffer -s 512 -b 4096 -P 100 -H | dd of=/dev/sdj2 seek=4096
summary: 98.0 MiByte in 4.4sec - average of 22.0 MiB/s
md5 hash: 3cbf1ca59a250d19573285458e320ade
Esto funciona en el sistema de 64 bits pero no en el sistema de 32 bits:
$ dd if=testfile count=200704 | mbuffer -s 512 -b 4096 -P 100 -H | dd of=testfile seek=4096 conv=notrunc
summary: 98.0 MiByte in 0.9sec - average of 111 MiB/s
md5 hash: 0f0727f6644dac7a6ec60ea98ffc6da9
¿Cómo se puede hacer esto de manera confiable?
notas
He leído otras preguntas acerca de búfer y mirado pv
, buffer
y mbuffer
. Solo pude hacer que este último funcione con el tamaño de búfer requerido.
El uso del almacenamiento intermedio es una solución obvia para el problema que siempre funciona, pero no es práctico cuando no hay suficiente capacidad disponible.
Pruebe las plataformas que ejecutan Arch Linux con la mbuffer
versión 20140302.
fuente
mbuffer
? ¿Por qué no hacerdd
leer todo el contenido del dispositivo de bloque de una vezdd bs=102760448
? Por supuesto, de una forma u otra está almacenado en la RAM.mbuffer
realidad, debería forzar al segundodd
a retrasarse por el primero y solo necesita suficiente RAM para amortiguar el tamaño del turno. Lástimadd
que no admite bloques de lectura y escritura en orden inverso ya que eso eliminaría el problema-H
argumento habilita esta función).Respuestas:
Sin un búfer, podría ir hacia atrás, un bloque a la vez.
Tenga en cuenta que este ejemplo es peligroso debido a la falta de comprobación de errores.
También es lento debido a la cantidad de
dd
llamadas. Si tiene memoria de sobra, podría usar un tamaño de bloque más grande.Con un amortiguador, tenga cuidado con las trampas . Es no suficiente para garantizar un llenado previo del 100%. Lo que necesita es un llenado mínimo durante todo el proceso. El búfer nunca debe caer a continuación
2M
porque, de lo contrario, habrá sobrescrito sus datos aún por leer nuevamente.Entonces, en teoría, podría prescindir de cualquier tipo de búfer y solo encadenar
dd
:En la práctica, esto no funciona de manera confiable porque no hay garantía de que el primero
dd
logre seguir leyendo datos, mientras que el últimodd
(con2M
"buffer" en el medio) ya está escribiendo.Puede aumentar sus posibilidades considerablemente haciendo que el buffer intermedio sea considerablemente mayor, pero aun así, no es confiable.
Lamentablemente, no conozco un buen programa de búfer con propiedad de relleno mínimo. Necesita uno que detenga la salida siempre que haya menos de su margen de seguridad dentro del búfer.
fuente
dd
podría usarse. Sin embargo, creo que la solución real es no usar,dd
sino optar por algo diseñado para funcionar al revésddrescue
. Describí una forma de hacerlo en una respuesta.ddrescue
aquí. No si espera trabajar en diferentes dispositivos, y tienes que engañarlo para que acepte tus argumentos. Es posible que tampoco tenga la propiedad de "relleno mínimo de búfer" internamente (ya que con diferentes dispositivos no es necesaria), por lo que nuevamente podría dañar sus datos. Tendría que verificar en el código fuente si realmente está diseñado para su caso de uso.Está leyendo 4096 bloques y luego escribe esos 4096 bloques en los siguientes 4096 bloques del disco, sobrescribiendo así los segundos 4096 bloques antes de que puedan leerse. Debe leer 8129 bloques para obtener esos segundos 4096 antes de comenzar cualquier escritura, y luego solo necesita escribir 4096 bloques antes de leer los siguientes 4096.
No mencionaste qué tipo de sistema de archivos es este. Si es ext [234] y tiene una versión reciente de e2fsprogs, puede usarla
e2image -ra -O 512 /dev/sdj2
. Esto también tiene el beneficio adicional de ser lo suficientemente inteligente como para omitir el espacio libre en el volumen.fuente
ext4
pero para la copia del dispositivo de bloque, cualquier sistema de archivos debería ser irrelevante.dd
no funciona.Una solución confiable requiere que se asegure de que nada escriba en un área que podría no haber sido leída y la única forma real de lograrlo es realizar la copia en una dirección inversa.
los
ddrescue
herramienta puede funcionar en una dirección inversa, pero se niega a ejecutarse con la entrada y la salida iguales. Sin embargo, es posible engañarlo duplicando el nodo del dispositivo.He realizado algunos experimentos rápidos y parece funcionar. La línea de comando es:
Los argumentos son
-f
se requiere para forzarlo a escribir en un dispositivo de salida existente-R
le dice que trabaje en una dirección inversa-s
le dice cuánto de la entrada copiar (utilicé els
sufijo para especificar el número de sectores)-o
le dice que busque hacia delante en el dispositivo de salida antes de escribir (especificado en sectores nuevamente con els
sufijo)/dev/sdj11
es el dispositivo de bloque para leer/dev/sdj11_copy
es el dispositivo de bloque para escribirCreé
/dev/sdj11_copy
conmknod
para que coincida con los parámetros de/dev/sdj11
.Solo he hecho algunas pruebas muy rápidas, pero parece funcionar bien para copiar un dispositivo sin formato. No funciona en un archivo (no podría engañarlo para que vaya más allá de que los archivos sean iguales)
Esto no responde a mi pregunta original que preguntaba cómo lograr esto,
dd
pero creo que, después de leer las otras respuestas, la respuesta es quedd
no puede hacerlo.fuente
ddrescue
descubre un bloqueo malo en este escenario? Si salta a otra área del disco (para evitar bloques defectuosos) y continúa copiando desde allí, sobrescribirá nuevamente las partes aún no copiadas de sus datos. Si no espera trabajar con el mismo dispositivo, no tiene ninguna razón para tomar medidas especiales para prevenir varios posibles casos de corrupción de datos.ddrescue
opciones para limitar sus intentos de recuperar datos incorrectos, pero no he considerado usarlos.