Creare un archivio tar (o altro), con i dati allineati a blocchi come nei file originali per una migliore deduplicazione a livello di blocco?


8

Come si può generare un file tar, in modo che il contenuto dei file tarred sia allineato a blocchi come nei file originali, in modo che si possa beneficiare della deduplicazione a livello di blocco ( https://unix.stackexchange.com/a/208847/9689 ) ?

(Ho ragione a dire che non c'è nulla di intrinseco nel formato tar che ci impedisce di ottenere tali benefici? Altrimenti, se non tar, c'è forse un altro archiviatore che ha una tale funzionalità integrata?)

PS Intendo "tar non compresso" - non tar + gz o qualcosa del genere - tar non compresso e la domanda richiede qualche trucco che consenta di allineare il livello di blocco dei file. AFAIRecall tar è stato progettato per l'uso con macchine a nastro, quindi forse l'aggiunta di alcuni bit extra per l'allineamento è possibile e facile nel formato file? Spero che ci possa essere anche uno strumento per farlo;). Per quanto ricordo, i file tar possono essere concatenati, quindi forse ci sarebbe un trucco per riempire lo spazio per l'allineamento.


Normalmente si combina tar con una sorta di compressione, che, anche se funzionerebbe solo con tar, certamente non con la compressione.
psusi,

Wow! Domanda buona e intelligente.
Adam Ryczkowski,

Risposte:


3

Si può fare, in teoria. Ma è molto brutto e in sostanza comporta la costruzione del nostro archivio a mano.

Quello che stiamo affrontando

Il tarformato funziona su blocchi da 512 byte . Questa dimensione è fissa e deve corrispondere alla dimensione tradizionale del settore del disco. Quando si memorizza un file in un archivio, il primo blocco da 512 byte è un'intestazione che contiene metadati del file (nome, dimensione, tipo, ecc.), Mentre i blocchi seguenti contengono il contenuto del file. Quindi i nostri dati archiviati saranno disallineati di 512 byte.

La dimensione del blocco ("--sectorize") di btrfs è in genere 4096 byte . In teoria possiamo scegliere questo, ma in pratica sembra che debba corrispondere alle dimensioni della pagina della nostra CPU. Quindi non possiamo ridurre i blocchi di btrfs.

Il tarprogramma ha un concetto di una dimensione "record" più grande, definita come un multiplo della dimensione del blocco, che sembra quasi utile. Si scopre che questo ha lo scopo di specificare la dimensione del settore di una determinata unità nastro, in modo da tarevitare la scrittura di record di nastro parziali. Tuttavia, i dati sono ancora costruiti e raggruppati in unità di 512 byte, quindi non possiamo usarli per far crescere tari blocchi come speravi.

Un ultimo punto di dati da sapere è che tar's indicatore di fine-archivio è a due consecutivi blocchi tutti-zeri, tranne quando i blocchi sono i dati dei file all'interno. Quindi, qualsiasi tipo di ingenuo blocco di imbottitura probabilmente non verrà accettato.

L'hack

Quello che possiamo fare è inserire i file di riempimento. All'inizio del nostro archivio, prima di aggiungere il file che vogliamo deduplicare (chiamarlo dup), aggiungiamo un file pad, dimensionato in modo che

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

In questo modo, dupi dati iniziano a un limite di blocco e possono essere deduplicati.

Quindi, per ogni file successivo, dobbiamo anche tenere traccia delle dimensioni del file precedente per calcolare il corretto riempimento. Dobbiamo anche prevedere se sarà necessaria una sorta di estensione dell'intestazione: ad esempio, l' intestazione tar di base ha spazio solo per 100 byte di percorso del file, quindi i percorsi più lunghi vengono codificati utilizzando quello che è strutturalmente un file con nome speciale i cui dati sono il percorso completo. In generale c'è molta potenziale complessità nel prevedere la dimensione dell'intestazione - il tarformato del file ha molta rotta da più implementazioni storiche.

Una piccola sfumatura argentata è che tutti i file di riempimento possono condividere lo stesso nome, quindi quando apriremo la memoria finiremo con un solo file extra di dimensioni inferiori a 4096 byte.

Il modo più pulito per creare in modo affidabile un archivio come questo è probabilmente quello di modificare il tarprogramma GNU . Ma se vuoi essere veloce e sporco a spese della CPU e del tempo di I / O, puoi, per ogni file, fare qualcosa del tipo:

#!/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_
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.