web-dev-qa-db-ja.com

SCSIテープからの読み取り時に「メモリを割り当てられません」

私はいくつかの古い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オプションですが、どれも効果がありませんでした。

時々、テープの最初のブロックから数kBのデータを読み取ることができます(データが途切れるまでtarが抽出できます)が、通常はまったく読み取られず、失敗します。

(どうやら)データをテープに正常に書き込んだ後、テープを他のドライブに移動し、データの最後までシークしてからさらに書き込んだので、ドライブにデータを書き込むことは問題ないように見えます。再び。

2つのLTO-3ドライブを使用しています。 1つはハーフハイトHP Ultrium 920で、もう1つはフルハイトHP Ultrium 960です。どちらにもこの問題があります。 2つの異なるSCSIカード(LSI Logic Ultra320カードとAdaptec Ultra2/SE 40MB /秒カード)を試しましたが、どちらも同じエラーが発生します。

ターミネーターが付いたケーブル(Ultra320カードでも40MB /秒)を試しましたが、2つのコネクターケーブルで1つのドライブしか接続できないため、ドライブの "term power"ジャンパーを有効にしました。 (ドライブとコントローラーが両方ともUltra320であるにもかかわらず)Ultra160になりましたが、これは何も変更せず、ドライブ全体から読み取ろうとすると、同じエラーが発生しました。

Linuxカーネル4.10.13から4.4.3(このマシンの以前のバージョン)にダウングレードすると、エラーメッセージが「メモリを割り当てられません」から「入出力エラー」に変わりますが、問題は同じままです。

このエラーの原因となるアイデアはありますか?

編集: SEアクティブターミネータを使用していたため、40MB /秒の問題が発生しました。これをLVDターミネーターに置き換えると、速度はUltra160に上がりました。 Ultra320に接続するには新しいケーブルが必要だと思いますが、これはテープの帯域幅が2倍(最大80MB /秒)になっているので、しばらくは問題ありません。ただし、エラーメッセージに違いはありません。

7
Malvineous

わかりました。これで解決したと思います。

TL; DR

代わりに、大きなブロックサイズでddを使用して、テープから読み取ります。

dd if=/dev/nst0 bs=1M | tar tvf -

バックグラウンド

テープに書き込む場合、データはブロックと呼ばれる単位で書き込まれます。これらは、ハードディスク上のセクターのようなものです。ハードディスクブロックが長年512バイトに固定されていて、つい最近になって4096バイトブロックに移動した場合、テープブロックは任意のサイズに設定できます。

使用するブロックサイズは、mt-stsetblkサブコマンドで設定します。

mt-st -f /dev/nst0 setblk 512    # Use 512-byte blocks
mt-st -f /dev/nst0 setblk 64k    # Use 65536-byte blocks

ドライブに読み取り操作を発行すると、ブロックサイズのチャンクでデータが返されます。ブロックの半分を読み取ることはできません-テープから読み取ることができるデータの最小量は1ブロックです。もちろん、ブロックサイズに応じて、実際のバイト数はいくつでもかまいません。

つまり、使用しているプログラムが16kBのメモリバッファを提供する場合、512バイトのブロックが16kBバッファに正確に収まるため、テープから一度に最大32ブロックを読み取ることができます。ただし、64kBブロックのテープから何かを読み取ることはできません。それらの1つでも16kBバッファーに収めることができないためです。一度に読むことができるのは1つのブロック全体にすぎないことを覚えておいてください。

1つのブロックに対して小さすぎるバッファを使用してこれを行おうとすると、ドライバ(この場合はst SCSIテープドライバ)がメモリ割り当てエラーコードを返し、読み取りバッファが小さすぎて1つのブロックも保持できません。

問題をさらに複雑にするために、一部のテープドライブ(明らかに私が使用している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も正常に機能するため、値が大きすぎても、妥当な範囲内で問題にはならないようです。

11
Malvineous