¿Hacer un archivo tar (u otro), con datos alineados en bloques como en los archivos originales para una mejor deduplicación a nivel de bloque?


8

¿Cómo se puede generar un archivo tar, para que el contenido de los archivos tarred esté alineado en bloques como en los archivos originales, de modo que uno pueda beneficiarse de la deduplicación a nivel de bloque ( https://unix.stackexchange.com/a/208847/9689 ) ?

(¿Estoy en lo cierto al decir que no hay nada intrínseco en el formato tar que nos impida obtener tal beneficio? De lo contrario, si no es tar, ¿hay quizás otro archivador que tenga esa característica incorporada?)

PD: me refiero a "tar sin comprimir" - no tar + gz o algo así - tar sin comprimir y la pregunta pide algún truco que permita alinear los archivos a nivel de bloque. AFAIRecall tar se diseñó para usar con máquinas de cinta, por lo que ¿quizás sea posible y fácil agregar algunos bits adicionales para la alineación dentro del formato de archivo? Espero que haya incluso una herramienta para ello;). Por lo que recuerdo, los archivos tar pueden concatenarse, por lo que tal vez haya un truco para llenar el espacio para la alineación.


Uno normalmente combina alquitrán con algún tipo de compresión, que, incluso si esto funcionara solo con alquitrán, ciertamente no lo hará con la compresión.
psusi

¡Guauu! Buena e inteligente pregunta.
Adam Ryczkowski

Respuestas:


3

Se puede hacer, en teoría. Pero es muy feo y esencialmente implica construir nuestro archivo a mano.

A lo que nos enfrentamos

El tarformato funciona en bloques de 512 bytes . Este tamaño es fijo y está destinado a coincidir con el tamaño tradicional del sector del disco. Al almacenar un archivo en un archivo, el primer bloque de 512 bytes es un encabezado que contiene metadatos del archivo (nombre, tamaño, tipo, etc.), y los siguientes bloques contienen el contenido del archivo. Entonces nuestros datos archivados estarán desalineados por 512 bytes.

El tamaño de bloque ("--sectorsize") de btrfs es típicamente 4096 bytes . En teoría podemos elegir esto, pero en la práctica parece que tiene que coincidir con el tamaño de página de nuestra CPU. Entonces no podemos reducir los bloques de btrfs.

El tarprograma tiene un concepto de un tamaño de "registro" más grande, definido como un múltiplo del tamaño de bloque, que casi parece que sería útil. Resulta que esto está destinado a especificar el tamaño del sector de una unidad de cinta dada, para tarevitar escribir registros de cinta parciales. Sin embargo, los datos aún se construyen y empaquetan en unidades de 512 bytes, por lo que no podemos usar esto para aumentar tarlos bloques como esperaba.

Un último punto de datos para saber es que tarel marcador de fin de archivo es dos bloques consecutivos de todos ceros, excepto cuando esos bloques están dentro de los datos del archivo. Por lo tanto, es probable que no se acepte ningún tipo de relleno ingenuo.

El truco

Lo que podemos hacer es insertar archivos de relleno. Al comienzo de nuestro archivo, antes de agregar el archivo que queremos deduplicar (llamarlo dup), agregamos un archivo pad, dimensionado para que

pad's header + pad's data + dup's header = 4096 bytes.

De esa manera, duplos datos comienzan en un límite de bloque y pueden deduplicarse.

Luego, para cada archivo posterior, también tenemos que hacer un seguimiento del tamaño del archivo anterior para calcular el relleno correcto. También tenemos que predecir si se necesitará algún tipo de extensión de encabezado: por ejemplo, el encabezado tar básico solo tiene espacio para 100 bytes de ruta de archivo, por lo que las rutas más largas se codifican utilizando lo que estructuralmente es un archivo especialmente nombrado cuyos datos son El camino completo. En general, existe una gran complejidad potencial en la predicción del tamaño del encabezado: el tarformato del archivo tiene muchas complicaciones de múltiples implementaciones históricas.

Un pequeño resquicio de esperanza es que todos los archivos de relleno pueden compartir el mismo nombre, por lo que cuando descomprimimos solo terminaremos con un solo archivo adicional de menos de 4096 bytes de tamaño.

La forma más limpia de crear de manera confiable un archivo como este es probablemente modificar el tarprograma GNU . Pero si desea ser rápido y sucio a expensas de la CPU y el tiempo de E / S, puede, para cada archivo, hacer algo como:

#!/bin/bash

# Proof of concept and probably buggy.
# If I ever find this script in a production environment,
# I don't know whether I'll laugh or cry.

my_file="$2"
my_archive="$1"

file_size="$(wc -c <"$my_file")"
arch_size="$(tar cb 1 "$my_file" | wc -c)"  # "b 1": Remember that record size I mentioned?  Set it to equal the block size so we can measure usefully.
end_marker_size=1024  # End-of-archive marker: 2 blocks' worth of 0 bytes

hdr_size="$(( (arch_size - file_size - end_marker_size) % 4096 ))"
pad_size="$(( (4096 - 512 - hdr_size) % 4096 ))"
(( pad_size < 512 )) && pad_size="$(( pad_size + 4096 ))"

# Assume the pre-existing archive is already a multiple of 4096 bytes long
# (not including the end-of-archive marker), and add extra padding to the end
# so that it stays that way.
file_blocks_size="$(( ((file_size+511) / 512) * 512 ))"
end_pad_size="$(( 4096 - 512 - (file_blocks_size % 4096) ))"
(( end_pad_size < 512 )) && end_pad_size="$(( end_pad_size + 4096 ))"

head -c $pad_size /dev/zero > _PADDING_
tar rf "$my_archive" _PADDING_ "$my_file"
head -c $end_pad_size /dev/zero > _PADDING_
tar rf "$my_archive" _PADDING_
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.