古いSCSIテープドライブを使用しようとしていますが、一部のデータはテープに正常に書き込まれましたが、再読み込みに問題があります。
# tar tvf /dev/st0
tar: /dev/st0: Cannot read: Cannot allocate memory
tar: At beginning of tape, quitting now
tar: Error is not recoverable: exiting now
# dd if=/dev/st0 of=test
dd: error reading '/dev/st0': Cannot allocate memory
0+0 records in
0+0 records out
0 bytes copied, 3.20155 s, 0.0 kB/s
次のコマンドの後に次のようにdmesg
言います。
st 10:0:3:0: [st0] Block limits 1 - 16777215 bytes.
st 10:0:3:0: [st0] Failed to read 65536 byte block with 512 byte transfer.
st 10:0:3:0: [st0] Failed to read 131072 byte block with 65536 byte transfer.
st 10:0:3:0: [st0] Failed to read 65536 byte block with 10240 byte transfer.
st 10:0:3:0: [st0] Failed to read 94208 byte block with 69632 byte transfer.
st 10:0:3:0: [st0] Failed to read 65536 byte block with 10240 byte transfer.
st 10:0:3:0: [st0] Failed to read 65536 byte block with 512 byte transfer.
ほとんどは、tar -b
このオプションを使用してさまざまなブロックサイズをテストしたためですが、どちらも効果がありませんでした。
時にはテープの最初のブロックから数キロバイトのデータを読み取ることができます(tarはデータが壊れるまでデータを抽出できます)、しばしば失敗し、データをまったく読み取ることができません。
テープにデータを(明らかに)正常に書き込んだり、テープを別のドライブに移動した後、データの終わりを見つけてさらに書き込んだため、データをドライブに書き込むことはあまり難しくありません。再び。
私は2つのLTO-3ドライブを使用しています。 1つはハーフハイトHP Ultrium 920、もう1つはフルハイトHP Ultrium 960です。どちらにもこの問題があります。 2つの異なるSCSIカード(LSI Logic Ultra320カードとAdaptec Ultra2 / SE 40MB / secカード)を試しましたが、両方のカードで同じエラーが発生しました。
ターミネーター付きのケーブルを使ってみて(Ultra320カードでも40MB/秒を得ました)、デュアルコネクタケーブルを使ってみました。これは1つのドライブしか接続できないため、そのドライブで「term power」ジャンパを有効にしました。 Ultra160(ドライブとコントローラの両方がUltra320であるにもかかわらず)は何も変わらず、プロセス全体でドライブからデータを読み取ろうとしたときに同じエラーが発生しました。
Linuxカーネル4.10.13から4.4.3(このシステムの以前のバージョン)にダウングレードしましたが、エラーメッセージが「メモリを割り当てられません」から「入力/出力エラー」に変更されましたが、問題はまだ同じです。
このエラーの原因は何ですか?
編集する:40 MB /秒の問題は、SEアクティブターミネータを使用したために発生します。 LVDターミネーターと交換すると、速度がUltra160まで上がりました。 Ultra320を接続するには新しいケーブルが必要になりそうですが、今ではテープ帯域幅(最大80MB /秒)の2倍なので、今は問題ありません。ただし、エラーメッセージに違いはありません。
ベストアンサー1
さて、この問題を解決したと思います。
長い話を短く
dd
テープから読み取るには、ブロックサイズを使用してください。
dd if=/dev/nst0 bs=1M | tar tvf -
背景
テープに書き込むと、データはブロックと呼ばれる単位で書き込まれます。これはハードドライブのセクタと同じです。ハードディスクブロックは長年にわたり512バイトに固定されており、最近では4096バイトブロックに変更されました。一方、テープブロックは任意のサイズに設定できます。
使用するブロックサイズは、setblk
次のサブコマンドを使用して設定されますmt-st
。
mt-st -f /dev/nst0 setblk 512 # Use 512-byte blocks
mt-st -f /dev/nst0 setblk 64k # Use 65536-byte blocks
ドライブに対して読み取り操作を実行すると、ブロックサイズのデータチャンクが返されます。ブロックの半分を読み取れません。テープから読み取ることができる最小データ量は1ブロックです。もちろん、ブロックサイズによっては実際のバイト数は制限されません。
これは、16kBメモリバッファを提供するプログラムを使用する場合、ブロックが16kBバッファに正確に収まるため、512バイトのブロックを持つテープから一度に最大32個のブロックを読み取ることができることを意味します。しかし、あなたは読めないでしょう。何もない64kBチャンクのあるテープからデータを読みます。これは、チャンクの1つが16kBバッファに収まらないためです。そして、一度にチャンク全体より小さいものは読めないことを覚えておいてください。
1つのブロックに比べて小さすぎるバッファを使用してこれを試みると、ドライバ(この場合はst
SCSIテープドライバ)は読み取りバッファが小さすぎることを知らせるメモリ割り当てエラーコードを返します。モノブロックも収容できます。
状況をさらに複雑にするのは、一部のテープドライブ(明らかに私が使用しているLTOテープドライブ)も可変サイズのブロックをサポートしているということです。つまり、ブロックサイズは次のようになります。各書き込みジョブのサイズによって決まります。各ブロックのサイズは、最後のブロックのサイズと異なる場合があります。
このモードでは、ブロックサイズが0に設定されています。
mt-st -f /dev/nst0 setblk 0 # Use variable-sized blocks
これは、誤って設定されたプログラムがスペースを浪費しにくいと推測するため、デフォルトのオプションでもあります。たとえば、4kブロックを設定してもプログラムが一度に512バイトのデータのみを書き込むと、各512バイトのデータブロックがテープ上で4kを占有する危険性があります。
理由
すべてをまとめると、テープに512バイトブロックと64kBブロックがある可能性があることがわかります。プログラムが16kBバッファのあるテープを読み取ると、最初のブロックが正常に読み込まれますが、さらに多くのブロックを読み取ろうとすると、次の64kBブロックをバッファに合わせることができないため、ドライバプログラムはエラーを返します。
これはCannot allocate memory
、ほとんどの場合、エラーが発生する理由を説明します。時にはtarを使用して最初のいくつかのファイルを抽出することができますが、エラーが再発生します。ブロックサイズが設定されていないmt-st
ため、テープに書き込むときにデフォルトで可変サイズのブロックが使用され、現在使用されてtar
いるバッファが小さすぎてブロックの一部を読み取ることができませんでした。
tar
一つあるいくつかのオプションは独自の内部ブロックサイズ、つまり、およびを--blocking-factor
設定--read-full-records
するために使用されますが、--record-size
これはtar
テープを直接読み書きするために使用される場合にのみ有効です。
合格したからmbuffer
テープシューポリシングスケジュールを減らすために、tar
アーカイブのブロックサイズはテープのブロックサイズと一致しなくなりました。これはほとんど影響がないことを意味します。つまり、ブロック要素が何であるかを--blocking-factor
示すヘッダを含むテープの最初のブロックを読み取ることができます。tar
しなければならないはい、そのエントリに切り替えて、コマンドラインで指定された値を無視します。これは、2番目とそれ以降のブロックを読み取ることができないことを意味します!
解決策
解決策は、読み取りバッファサイズを、私たちが見ることができる最大のチャンクを収容するのに十分な大きさに設定できる他のプログラムを使用してテープからデータを読み取ることです。
dd
これを行うには、次のようにします。
dd if=/dev/nst0 bs=256k | tar tvf -
256k
テープに大きなブロックがある場合は増やす必要があるかもしれませんが、これは私にとって効果的でした。1M
また、かなりうまく動作するので、値が大きすぎると合理的に問題にならないようです。