linux – 4096バイトセクタのディスクで512バイトセクタのMBRを修正するには?

hard-drive linux mbr partitioning

Final update:

この問題を解決するために必要なことはすでにわかっていました。それを自動的に行うための既製のツールがあるのではないかと期待していたのですが、見つかりませんでした。私の問題を直接解決したわけではありませんが、セクタサイズの問題について非常に良い背景を与えてくれましたし、問題は本当にパーティションのアライメントとアドレス指定にあると確信しました。同じ問題を抱えてこの質問に来た人のために、何かをする前に、コメントを含めて徹底的に注意深く読んでください


はじめに

私はコンピュータを持っていたし、より多くのスペースを必要としていた私は新しい500GBのドライブとUSBエンクロージャを購入しました。すぐに私は、私はエンクロージャ上のドライブを分割し、コンピュータに移動した場合、それは(およびその逆)パーティションを認識しないだろうことに気づいた。私はそれが筐体の問題であると仮定し、それを気にしていませんでした

Then, tragedy

素晴らしい日、私のコンピュータはもう電源を入れないことにしました。マザーボード(ブランド品ではなく、中国製と印刷されています)が死んでいることがわかりました。私はファイルサーバーとしてそれを使用してきましたが、その500GBのドライブは、私が失うことができないデータでいっぱいになりました。私は今、破産していて、新しいコンピュータを買う余裕がないので、私の唯一の希望は、”欠陥のある “USBエンクロージャでした

The investigation

いくつかのLinuxディストリビューション、ラップトップ、VirtualBox、エンクロージャーで武装して、この問題についてフォレンジック分析を行いました。そこで、ハードドライブのデータシートを調べ、ゼロからセクタ数を計算し、ddを使って手動でドライブの境界をテストしましたが、fdiskを起動するまでは、すべて問題ないように見えました

    Note: Sector size is 4096 (not 512).

なんと謙虚なfdisk。この「ノート」がすべての問題の根源でした。もう少しいじった後、これらの結論が導き出されました

  • USBの筐体は不良品ではありません

  • 今は亡きマザーボードに搭載されているSATAコントローラは、少なくとも「奇妙な」ものでした。4096バイトのセクタをOSに報告しなかったので、OSは喜んで512バイトのセクタアドレスを使ってMBRを作成していました

  • 今、パーティションにアクセスしようとすると、OSは4096バイトのセクタドライブの512バイトベースのアドレスを使おうとしますが、もちろんうまくいきません

The question

  • では、どのようにMBRのアドレスを修正すれば、4096バイトのセクタサイズで有効になるのでしょうか?

  • 4096バイトセクタでパーティションが整列していません。別のドライブにコピーして出し入れする以外に、整列させるためのツールはありますか?(私は予備のドライブを持っていません)、または私は一度に少しずつデータの塊を横に “シフト “するツールを作成する必要がありますか?パーティションはext3です

Thanks!

Update:

この質問の中に、ddを使ってパーティションをその場で移動させる巧妙な方法があるのを見つけました。GNU/Linux でパーティションを移動するには?今はテストできませんが、時間があればテストしてみます

Update 2:

ということで、上記の方法でパーティションの位置合わせに成功し、ヘキサエディタでMBRを手編集してみました。HDDを接続し直すとすぐに、パーティションが自動的にマウントされました。このプロセス中にI/Oエラーが発生して、すべてを失う可能性があるので、お勧めしません。他のパーティションについては、私はリスクを冒さず、古いHDDを使用して、データをコピーして、別の位置に貼り付けることによって、一度にチャンクを整列させるでしょう

  24  NothingsImpossible  2013-11-23


ベストアンサー

セクターサイズの問題はかなり複雑になってきています。2009年後半までは、ハードディスクの大半が512バイトのセクタを使用しており、それだけであった。2009年後半、ディスクメーカーは4096バイトのセクタを使用する、いわゆるアドバンスドフォーマット(AF)ディスクの導入を開始しました。これらの最初の AF ディスク (および、現在のすべての AF ディスク) は、各 4096 バイトの物理セクタが 8 つの 512 バイトの論理セクタに分割されていることをコンピュータに表示するインターフェイスを提供しています。この変換により、512 バイトを前提に構築された多くの BIOS を含む古いツールが動作し続けることが可能になります。お使いのディスクがAFを使用しているかどうかはわかりませんが、どちらの場合もほぼ間違いなく512バイトの論理セクタサイズを使用しており、OSとのインターフェースは512バイトのセクタを使用する必要があることを意味しています

問題を複雑にしているのは、特定のUSBディスクエンクロージャです。これらのエンクロージャの中には、AFがすることとは逆のことをするものがある。彼らは8つのディスクセクターを取り、1つの新しい4096バイトのセクターにそれらをバンドルします。私はこの動きの背後にある理由が何であるかを確認していない, しかし、1つの実用的な利点は、2TiBよりも大きいディスクは、古いMBRパーティションシステムで使用することができるということです.1つの大きな欠点は、これらのエンクロージャのいずれかにパーティションされたディスクを直接使用することができないこと、またはこのタイプの変換を行わないエンクロージャで使用することができないことです。同様に、このタイプの変換を行わないディスクは、そのようなエンクロージャに転送されたときに使用することができません。この問題は MBR 自体にとどまらないことに注意してください。ディスクは最初のパーティションが (512 バイト) セクター 2048 から始まっていると認識しているかもしれませんが、OS が (4096 バイト) セクター 2048 を探しても、そのパーティションの先頭が見つからないのです。この問題に遭遇してしまいました。このように、最初にUSBエンクロージャのせいだと思っていたあなたの考えは、最近のマザーボードのせいだと思っていたあなたの考えよりも、より正確なものです。マザーボードがこのようにセクタサイズを変換するという話は聞いたことがありません。(いくつかのハードウェアRAIDデバイスはそうしていますが)

Linux のセクタサイズを強制的に調整する方法は知りませんが、十分なディスク容量がある場合は、低レベルのディスクを別のディスクにコピーしてみると良いかもしれません。例えば、以下のようにします

dd if=/dev/sdb of=~/image.img

これにより、ディスクが /dev/sdb (USB ディスク。必要に応じて調整してください) からファイル ~/image.img にコピーされます。その後、以下のスクリプトを使ってイメージのパーティションをマウントすることができます

#!/bin/bash
gdisk -l $1 > /tmp/mount_image.tmp
let StartSector=`egrep "^   $2|^  $2" /tmp/mount_image.tmp | fmt -u -s | sed -e 's/^[ \t]*//' | head -1 | cut -d " " -f 2`

let StartByte=($StartSector*512)

echo "Mounting partition $2, which begins at sector $StartSector"

mount -o loop,offset=$StartByte $1 $3

rm /tmp/mount_image.tmp

スクリプトをmount_imageのように保存して、次のように使用します

./mount_image ~/image.img 2 /mnt

これは image.img のパーティション 2 を /mnt にマウントします。このスクリプトは GPT fdisk (gdisk) に依存していることに注意してください

長期的には、より良い解決策は、セクタサイズ変換を行わないディスクを接続する方法を見つけることです。新しいマザーボードへの直接接続がトリックを行う必要があります;または、おそらく変換を行わない外部エンクロージャを見つけることができます。実際には、いくつかのエンクロージャは、USBポートではなく、eSATAポートで変換を行うので、エンクロージャがeSATAポートを持っている場合、あなたはそれを使用してみてください。私は、これらのソリューションは、すべてあなたが持っていないと言うお金がかかる可能性が高いことを認識していますが、多分あなたは、翻訳を行わない1つのためにあなたの翻訳エンクロージャを交換することができます

もう一つの選択肢は、VirtualBox のような仮想マシンを使ってみることです。このようなツールは、ディスクデバイスにアクセスする際に 512 バイトのセクタサイズを想定し、効果的に変換を元に戻すことができるかもしれません

25  Rod Smith  2013-11-23


このスクリプトは、あなたがレイドやクリプトを持っているときに、ロッドスミスの提案を一般化しました。保証はありません。ご自由に改善してください。(mdadmについての最新の知見を取り入れて更新しました)

#!/bin/sh
#
# This script solve the following problem:
#
# 1. create a GPT partition on a large disk while attached directly via SATA
#    when the device present itself with 512 bytes of block size:
#    sd 3:0:0:0: [sda] 5860533168 512-byte logical blocks: (3.00 TB/2.72 TiB)
#
# 2. try to use a SATA to USB adapter like ID 067b:2773 Prolific Technology, Inc.
#    this present the device with 4096 bytes of block size:
#    sd 19:0:0:0: [sdc] 732566646 4096-byte logical blocks: (3.00 TB/2.72 TiB)
#
# 3. The kernel is unable to read correctly the partition table with
#    the USB adaper.
#
#
# With the current tools (kernel and gdisk) in debian wheezy is
# possible to use losetup to remap the partitions to loop devices so
# you can use them as usual with any filesystem, raid or crypto
#
# I still do not know if this issue is originated by the adapter or by
# the disk and if there are any others workarounds.
#
# Known version of the software:
# $ apt-show-versions linux-image-3.2.0-4-amd64
# linux-image-3.2.0-4-amd64/wheezy uptodate 3.2.54-2
# $ apt-show-versions gdisk
# gdisk/wheezy uptodate 0.8.5-1


attach_device() {

device="$1";

MYTMPDIR=`mktemp -d`
trap "rm -rf $MYTMPDIR" EXIT

# gdisk on the device use the 4096 sector size
# but we need to force it to 512
# this is a knwon workaround from http://superuser.com/a/679800
# basically we make a copy of the gpt partition table on a file
dd if="/dev/$device" bs=16384 count=1 of="$MYTMPDIR/gpt" 2> /dev/null

# we extract the offset and the size of each partition
#
# FIXME: the "+ 1" seems strange, but it is needed to get the same
#        size value from:
#
#        blockdev --getsize64
#
#        without the "+ 1" some funny things happens, for example
#        you will not be able to start a recognized md device:
#
#        md: loop1 does not have a valid v1.2 superblock, not importing!
#        md: md_import_device returned -22
#
#        even if
#
#        mdadm --examine /dev/loop1
#
#        does not complaint

gdisk -l \
"$MYTMPDIR/gpt" 2> /dev/null | \
awk '/^ *[0-9]/ {printf "%.0f %.0f\n", $2 * 512, ($3 - $2 + 1) * 512}' > $MYTMPDIR/offset-size

# we create a loop device with the give offset and size
while read line;
do
offset=$(printf "$line" | cut -d ' ' -f 1);
size=$(printf "$line" | cut -d ' ' -f 2);
losetup --verbose --offset "$offset" --sizelimit "$size" `losetup -f` /dev/$device;
done < $MYTMPDIR/offset-size;
}

detach_device() {

device="$1";

for loopdevice in `losetup -a | grep "$device" | cut -d : -f 1`;
do
losetup --verbose --detach "$loopdevice";
done;
}

usage() {
cat <<EOF
Usage:
- $0 -h to print this help
- $0 sda to attach the gpt partitions of sda
- $0 -d sda to detach the gpt partitions of sda
EOF
}


detach=0;

while getopts hd action
do
case "$action" in
d) detach=1;;
h) usage;;
esac
done
shift $(($OPTIND-1))

if [ $# -ne 1 ];
then
usage;
fi

if [ "x$detach" = "x0" ]; then
attach_device $1;
else
detach_device $1;
fi

4  user302662  2014-02-23


WD My Bookの外付けエンクロージャーから4TBのディスクを取り出したときにこの問題が発生しました。問題の内容は

  1. MBR パーティションテーブルが 8 倍もずれています
  2. セクタサイズが 512 の場合、MBR パーティションテーブルが 2TB を超えて処理できない

解決策。パーティションテーブルをGPTに書き換え、512バイトのセクタを使用するように値を変換します

私の場合、パーティションは 1MB オフセットで始まり、ディスクの終わりの前(~856kB)で終了しました。これは、パーティションの前に MBR+GPT (17408 バイト)を、ディスクの最後にバックアップ GPT (16896 バイト)を入れることができたからです

念のために両領域の画像を作ってみました(ddを使用)

fdisk -l /dev/sdeからの出力に注目しました

gdiskを使って最初のパーティションを削除しました。よろしければ、私のようにして、できるだけ多くのスペースを使うために、alignの値を8(4096)に変更します。そして、開始を2048、終了をディスクの最後にして新しいパーティションを作成しました。ファイルシステムは後ほど育ててみます

ありがたいことに、セクタサイズの変更はファイルシステム、LVM、LUKSには影響しません

4  Duane  2016-05-01


これを行うもう一つのかなりストレートな方法は、parted のレスキュー機能を使うことです。しかし、これは新しいディスクラベルを作成する必要があるので、リスクを伴います。parted はディスク上で直接動作しますので、parted を実行する前に必要に応じてバックアップを取ってください。それから起動してください

parted /dev/sdb

parted は、パーティションテーブルが作成されたときとは異なるセクタサイズのディスクを読もうとしたときに、以下のようなことを教えてくれます

Error: /dev/sdb: unrecognised disk label

mklabel を使用して、以前に使用したものに合わせて新しい MBR または GPT を作成します

(parted) mklabel
New disk label type? mbr

そして、レスキューを実行して古いパーティションを探します

(parted) rescue
Start? 0
End? 4001GB
Information: A ext4 primary partition was found at 1049kB -> 2000GB.  Do you
want to add it to the partition table?
Yes/No/Cancel? y

パーティションが増えた場合は、レスキュー処理を繰り返してください。これで完了です

3  Johan Ehnberg  2015-11-16


タイトルとURLをコピーしました