ブロックレベルの重複排除を改善するために、データを元のファイルのようにブロック配置して、tar(またはその他の)アーカイブを作成しますか?


8

タールを塗ったファイルの内容は、ブロック整列1は、ブロックレベルの重複排除機能の恩恵を受けることができるように、元のファイルに似ているので、どのように1は、tarファイルを生成することができます(https://unix.stackexchange.com/a/208847/9689) ?

(私は、そのような利点を得ることを妨げるtar形式に固有のものは何もないことを訂正しますか?そうでなければ、もしtarでなければ、おそらくそのような機能が組み込まれた別のアーカイバがあるのでしょうか?)

PS私は「非圧縮tar」を意味します-tar + gzや何かではありません-非圧縮tarと質問は、ファイルのブロックレベルを揃えることを可能にするいくつかのトリックを要求します。AFAIRecall tarはテープマシンで使用するように設計されているので、ファイル形式内で位置合わせのためにビットを追加することは可能で簡単ですか?私はそれのためのツールさえあるといいのですが;)。私が思い出す限り、tarファイルは連結できるので、整列のためにスペースを埋めるトリックがあるかもしれません。


通常、tarとある種の圧縮を組み合わせます。これは、これがtarだけで機能する場合でも、圧縮では確実に機能しません。
psusi

うわー!良い賢い質問。
アダムRyczkowski

回答:


3

理論的にはそれが可能です。しかし、それは非常に醜く、本質的に手作業でアーカイブを構築する必要があります。

私たちが直面していること

このtarフォーマットは512バイトのブロックで動作します。このサイズは固定されており、従来のディスクセクターサイズと一致するように設計されています。ファイルをアーカイブに保存する場合、最初の512バイトのブロックは、ファイルメタデータ(名前、サイズ、タイプなど)を含むヘッダーであり、次のブロックにはファイルの内容が含まれます。そのため、アーカイブされたデータは512バイトだけずれてしまいます。

btrfsのブロックサイズ( "--sectorsize")は通常4096バイトです。理論的にはこれを選択できますが、実際にはCPUのページサイズと一致している必要があります。したがって、btrfsのブロックを縮小することはできません。

tarプログラムは、それが有用であろうように、ほとんど見えブロックサイズの倍数として定義され、より大きな「記録」サイズの概念を持っています。これは、特定のテープドライブのセクターサイズを指定することを目的tarとしているため、部分的なテープレコードの書き込みを回避できます。ただし、データは引き続き512バイト単位で構築およびパックされるため、tar希望どおりにこれを使用してのブロックを拡張することはできません。

知るために、データの最後のポイントは、ということであるtarエンド・オブ・アーカイブマーカーは、これらのブロックは内部のファイルデータである場合を除き、二つの連続オールゼロブロックです。したがって、あらゆる種類の単純なパディングブロックはおそらく受け入れられません。

ハック

私たちにできることは、パディングファイルを挿入することです。アーカイブの先頭で、重複排除したいファイルを追加する前に(それを呼び出すdup)、次のpadようなサイズのファイルを追加します

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

このように、dupのデータはブロック境界で始まり、重複排除が可能です。

次に、後続のファイルごとに、前のファイルのサイズを追跡して、正しいパディングを計算する必要があります。ある種のヘッダー拡張が必要になるかどうかも予測する必要があります。たとえば、基本的なtarヘッダーには100バイトのファイルパスしか格納できないため、長いパスは構造的に特別な名前のファイルのデータを使用してエンコードされますフルパス。一般に、ヘッダーサイズの予測には多くの潜在的な複雑さがありtarます。ファイル形式には、過去の複数の実装からの多くの欠けがあります。

小さな銀の裏地は、すべてのパディングファイルが同じ名前を共有できることです。そのため、解凍すると、サイズが4096バイト未満の1つの追加ファイルのみが作成されます。

このようなアーカイブを確実に作成する最もクリーンな方法は、おそらくGNU tarプログラムを変更することです。しかし、CPUとI / Oの時間を犠牲にして迅速かつダーティになりたい場合は、ファイルごとに次のようなことを行うことができます。

#!/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_
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.