오래된 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는 데이터가 깨질 때까지 데이터를 추출할 수 있음) 종종 실패하고 데이터를 전혀 읽지 못합니다.
테이프에 데이터를 (분명히) 성공적으로 썼고, 테이프를 다른 드라이브로 옮긴 다음, 데이터의 끝을 찾아 더 많이 썼기 때문에 데이터를 드라이브에 쓰는 데는 별 어려움이 없을 것 같습니다. 다시 .
저는 두 개의 LTO-3 드라이브를 사용하고 있습니다. 하나는 절반 높이 HP Ultrium 920이고 다른 하나는 전체 높이 HP Ultrium 960입니다. 둘 다 이런 문제가 있습니다. 두 개의 서로 다른 SCSI 카드(LSI Logic Ultra320 카드 및 Adaptec Ultra2/SE 40MB/sec 카드)를 사용해 보았지만 두 카드 모두 동일한 오류가 발생했습니다.
터미네이터가 있는 케이블을 사용해 보았고(Ultra320 카드에서도 40MB/초를 얻었습니다) 듀얼 커넥터 케이블을 사용해 보았습니다. 이는 하나의 드라이브만 연결할 수 있다는 의미이므로 해당 드라이브에서 "term power" 점퍼를 활성화했습니다. Ultra160(드라이브와 컨트롤러가 모두 Ultra320임에도 불구하고)은 아무 것도 변경되지 않았으며 프로세스 전반에 걸쳐 드라이브에서 데이터를 읽으려고 할 때 여전히 동일한 오류가 발생했습니다.
Linux 커널 4.10.13에서 4.4.3(이 시스템의 이전 버전)으로 다운그레이드했는데 오류 메시지가 "메모리를 할당할 수 없습니다"에서 "입력/출력 오류"로 변경되었지만 문제는 여전히 동일합니다.
이 오류의 원인이 무엇인지 아시나요?
편집하다:40MB/초 문제는 SE 활성 터미네이터를 사용했기 때문에 발생합니다. LVD 터미네이터로 교체하니 속도가 Ultra160까지 올라갔습니다. Ultra320을 연결하려면 새 케이블이 필요할 것 같지만 이제 테이프 대역폭(최대 80MB/초)의 두 배이므로 지금은 괜찮습니다. 그러나 오류 메시지에는 차이가 없습니다.
답변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
드라이브에 읽기 작업을 실행하면 블록 크기의 데이터 청크가 반환됩니다. 블록의 절반을 읽을 수 없습니다. 테이프에서 읽을 수 있는 최소 데이터 양은 한 블록입니다. 물론 블록 크기에 따라 실제 바이트 수는 제한되지 않습니다.
이는 16kB 메모리 버퍼를 제공하는 프로그램을 사용하는 경우 블록이 16kB 버퍼에 정확히 맞기 때문에 512바이트 블록이 있는 테이프에서 한 번에 최대 32개의 블록을 읽을 수 있음을 의미합니다. 하지만 넌 읽을 수 없을 거야아무것64kB 청크가 있는 테이프에서 데이터를 읽으십시오. 해당 청크 중 하나도 16kB 버퍼에 맞출 수 없기 때문입니다. 그리고 한 번에 전체 청크보다 작은 것은 읽을 수 없다는 점을 기억하십시오.
한 블록에 비해 너무 작은 버퍼를 사용하여 이렇게 하려고 하면 드라이버(이 경우 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
~해야 한다예, 해당 항목으로 전환하고 명령줄에 제공된 값을 무시합니다. 이는 두 번째 및 후속 블록을 더 이상 읽을 수 없음을 의미합니다!
해결책
해결책은 읽기 버퍼 크기를 우리가 볼 수 있는 가장 큰 청크를 수용할 수 있을 만큼 큰 값으로 설정할 수 있는 다른 프로그램을 사용하여 테이프에서 데이터를 읽는 것입니다.
dd
이렇게 하려면 다음과 같이 하면 됩니다.
dd if=/dev/nst0 bs=256k | tar tvf -
256k
테이프에 더 큰 블록이 있으면 늘려야 할 수도 있지만 이것이 제게는 효과적이었습니다. 1M
또한 꽤 잘 작동하므로 값이 너무 크면 합리적으로 문제가되지 않는 것 같습니다.