web-dev-qa-db-ja.com

4096バイトのセクターディスクで512バイトのセクターMBRを修正する方法

最終更新:

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


初めに

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

その後、悲劇

素晴らしい一日でしたが、私のコンピューターはもうオンにしないことにしました。マザーボード(ブランド化されておらず、その上に大きなMADE IN CHINAが印刷されているだけ)が死んでいることがわかりました。私はこれをファイルサーバーとして使用しており、500 GBのドライブには、失うことのできないデータがいっぱいです。私は今壊れており、新しいコンピュータを買う余裕がないので、私の唯一の希望は「欠陥のある」USBエンクロージャでした。

調査

いくつかのLinuxディストリビューション、ラップトップ、VirtualBox、エンクロージャで武装して、この問題についてフォレンジック分析を行いました。 dmesgは、パーティションサイズがドライブの終わりを超えていると報告しました。だから私はハードドライブのデータシートを調べ、ゼロからセクター数を計算し、ドライブの境界をddで手動でテストしました。

    Note: Sector size is 4096 (not 512).

Fdiskの控えめさ。この「ノート」がすべての問題の根源でした。さらにいじくった後、これらの結論が引き出されました:

  • USBエンクロージャに欠陥はありません。

  • 現在死んでいるマザーボード上のSATAコントローラは、少なくとも「奇妙な」ものでした。オペレーティングシステムに4096バイトのセクターを報告しなかったため、OSは512バイトのセクターアドレスを使用してMBRを作成しました。

  • ここでパーティションにアクセスしようとすると、OSは4096バイトのセクタードライブ上の512バイトベースのアドレスを使用しようとしますが、もちろんそれは機能しません。

質問

  • それで、16進数エディターでMBRを手動で編集する以外に、MBRのアドレスを4096バイトのセクターサイズで有効にするにはどうすればよいですか。

  • パーティションは、4096バイトのセクターに対して整列されていません。別のドライブにコピーしたり、別のドライブからコピーしたりする以外に、それらを調整するために使用できるツールはありますか? (スペアドライブがありません)、または一度にデータを少しずつ横に「シフト」するツールを作成する必要がありますか?パーティションはext3です。

ありがとう!

更新:

この質問でddを使用してパーティションをインプレースで移動する巧妙な方法があることがわかりました: GNU/Linuxでパーティションを移動する方法は? しかし、それが動作するかどうかはわかりませんただし、セクターの一部です。今はテストできませんが、時間があればテストします。

アップデート2:

したがって、上記の方法を使用してパーティションを正常に位置合わせし、16進エディターでMBRを手動で編集しました。 HDDを再接続するとすぐに、boomパーティションが自動的にマウントされます!ただし、これはお勧めしません。プロセス中にI/Oエラーが発生し、すべてを失った可能性があります。Rodの回答に関するコメントを参照してください。他のパーティションについては、リスクを冒さず、古いHDDを使用し、データをコピーして別の位置に貼り付けて、チャンクを一度に整列します。

24

セクターサイズの問題は非常に複雑になっています。 2009年後半まで、ハードディスクの大部分は512バイトのセクターを使用していました。 2009年後半に、ディスクメーカーは、4096バイトセクターを使用する、いわゆるAdvanced Format(AF)ディスクの導入を開始しました。これらの最初のAFディスク(および今日のすべてのAFディスク)は、各4096バイト物理セクターを8つの512バイトlogicalセクター。この変換により、512バイトを前提として構築された多くのBIOSを含む古いツールが引き続き機能できるようになります。ディスクでAFが使用されているかどうかはわかりませんが、どちらの場合でも、ほぼ確実に512バイトの論理セクターサイズが使用されます。つまり、OSへのインターフェイスは512バイトのセクターを使用する必要があります。

問題を複雑にしているのは、特定のUSBディスクエンクロージャです。これらのエンクロージャーの一部は、AFの逆の動作をします。8つのディスクセクターを取り、それらを1つの新しい4096バイトセクターにバンドルします。この移動の背後にある理由はわかりませんが、1つの実用的な利点は、2TiBより大きいディスクを古いMBRパーティションシステムで使用できることです。主な欠点の1つは、これらのエンクロージャーの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 に依存していることに注意してください。ほとんどのディストリビューションでは、gptfdiskまたはgdiskというパッケージに含まれています。

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

私に発生する別のオプションは、VirtualBoxのような仮想マシンを使用することです。このようなツールは、ディスクデバイスにアクセスするときに512バイトのセクターサイズを想定して、変換を効果的に元に戻すことができます。または、仮想マシン内でディスクのコンテンツをそのままコピーして(dd if=/dev/sdc of=/dev/sdbのように)、コンテンツを圧縮してコピーし、イメージを元のディスクよりも少ないディスク領域に収めることができます。

24
Rod Smith

このスクリプトは、レイドまたはクリプトを持っているときのロッド・スミスの提案を一般化したものです。無保証。それを自由に改善してください! (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

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

これを行うもう1つのかなり簡単な方法は、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