Jak zvětšit disk virtuálního serveru a nepřijít o data

19. 9. 2013 13:43 Ondřej Caletka

Už několikrát jsem byl dotazován ohledně správného postupu zvětšení diskového prostoru u virtuálního serveru. Postup jsem si úspěšně vyzkoušel u sebe, poradil jak na to a… pak poslouchal nářky, že to nefunguje a data jsou pryč. Nejdřív popíšu celý postup:

  1. Předpokládáme virtuální server běžící v režimu plné virtualizace (třeba VMware, KVM, nebo Xen). Byl vytvořen s nějakou velikostí virtualizovaného disku, která nyní nestačí.
  2. Disk zvětšíme v nástroji pro správu virtuálního serveru. Po restartu virtuálního stroje tento vidí větší disk, místo na konci je však nealokované, takže jej není možné použít. Potřebujeme tedy zvětšit poslední oddíl přes veškeré nealokované místo.
  3. Pro jistotu zazálohujeme MBR, který obsahuje i tabulku rozdělení disku: #dd if=/dev/sda of=oldmbr.bin bs=512 count=1 #scp oldmbr.bin bezpecne-misto.example.cz:
  4. Příkazem fdisk /dev/sda nejprve vymažeme z tabulky rozdělení poslední oddíl a následně jej znovu vytvoříme se stejným počátečním blokem a větší velikostí.
  5. Protože systém běží, odmítne načíst novou tabulku rozdělení disku. Musíme tedy virtuální server znovu restartovat.
  6. Po restartu můžeme přistoupit ke zvětšení velikosti filesystému na oddílu (například pomocí resize2fs), nebo fyzického svazku LVM (pomocí  pvresize).

Tento postup je bez problému funkční na aktuálních distribucích. Když jsem jej ale nedávno zkoušel na CentOSu, virtuální server po druhém restartu už nenalezl žádná data na disku. Kde byl problém?

Může za to CHS

Problém je samozřejmě v kroku mazání a znovuvytváření oddílu nástrojem fdisk. V aktuálním RHELu a jeho klonech je totiž ještě verze fdisku, která ve výchozím stavu zarovnává oddíly na cylindry. Což u virtualizovaného disku dává ještě mnohem menší smysl než u fyzického disku (a u něj to aspoň 15 let smysl nedává žádný :) ). Tedy, pokud nerespektujeme upozornění, fdisk nám jednoduše bude lhát:

# fdisk /dev/sda

POZOR: Režim kompatibility s DOSem je zastaralý. Důrazně se doporučuje tento
       režim vypnout (příkaz „c“) a změnit jednotky výpisů na sektory
       (příkaz „u“).

Příkaz (m pro nápovědu): p

Disk /dev/sda: 10,7 GB, 10 737 418 240 bajtů
hlav: 181, sektorů na stopu: 40, cylindrů: 2 896
Jednotky = cylindry po 7240 * 512 = 3 706 880 bajtech
Velikost sektoru (logického/fyzického): 512 bajtů / 512 bajtů
Velikost I/O (minimální/optimální): 512 bajtů / 512 bajtů
Identifikátor disku: 0x00052b20

Zařízení Zavádět   Začátek       Konec    Bloky    Id  Systém
/dev/sda1   *           1        1449     5241856   83  Linux

O skutečném obsahu tabulky rozdělení disku se přesvědčíme příkazem p v expertním módu:

Příkaz (m pro nápovědu): x

Příkaz pro odborníky (m pro nápovědu): p

Disk /dev/sda: hlav: 181, sektorů: 40, cylindrů: 2 896

Č. AF  Hd Sek  Cyl  Hd Sek  Cyl    Začátek     Vel.   Id
 1 80  32  33    0 180  40  652       2048   10483712 83
 2 00   0   0    0   0   0    0          0          0 00
 3 00   0   0    0   0   0    0          0          0 00
 4 00   0   0    0   0   0    0          0          0 00

Teď schválně oddíl zrušíme a vytvoříme „naprosto totožný“:

Příkaz (m pro nápovědu): d
Vybrán oddíl 1

Příkaz (m pro nápovědu): n
Příkaz
   e   rozšířený diskový oddíl
   p   primární diskový oddíl (1-4)
p
Číslo diskového oddílu (1-4): 1
První cylindr (1-2896, implicitně 1):
Používám implicitní hodnotu 1
Poslední cylindr, +cylindry nebo +velikost{K,M,G} (1-2896, implicitně 2896): 1449

Příkaz (m pro nápovědu): p

Disk /dev/sda: 10,7 GB, 10 737 418 240 bajtů
hlav: 181, sektorů na stopu: 40, cylindrů: 2 896
Jednotky = cylindry po 7240 * 512 = 3 706 880 bajtech
Velikost sektoru (logického/fyzického): 512 bajtů / 512 bajtů
Velikost I/O (minimální/optimální): 512 bajtů / 512 bajtů
Identifikátor disku: 0x00052b20

Zařízení Zavádět   Začátek       Konec    Bloky    Id  Systém
/dev/sda1               1        1449     5245360   83  Linux

I když nový oddíl začíná a končí na stejném cylindru, rozdílná velikost počtu bloků nám může signalizovat, že tu něco nehraje. Expertní režim odhalí, že oddíl nyní začíná úplně jinde než předtím. Důležitá je hlavně hodnota označená „Začátek“. Ta totiž určuje LBA adresu prvního bloku daného oddílu. Vidíme, že „DOS-kompatibilní“ režim nám přesunul oddíl z bloku 2048 na blok 40. Není divu, že počítač po restartu nebyl schopen najít filesystém.

Příkaz (m pro nápovědu): x

Příkaz pro odborníky (m pro nápovědu): p

Disk /dev/sda: hlav: 181, sektorů: 40, cylindrů: 2 896

Č. AF  Hd Sek  Cyl  Hd Sek  Cyl    Začátek     Vel.   Id
 1 00   1   1    0 180  40 1023         40   10490720 83
 2 00   0   0    0   0   0    0          0          0 00
 3 00   0   0    0   0   0    0          0          0 00
 4 00   0   0    0   0   0    0          0          0 00

Řešení problému je přitom velmi snadné. Stačí neignorovat upozornění, které fdisk při spuštění vypisuje:

# fdisk /dev/sda

POZOR: Režim kompatibility s DOSem je zastaralý. Důrazně se doporučuje tento
       režim vypnout (příkaz „c“) a změnit jednotky výpisů na sektory
       (příkaz „u“).

Příkaz (m pro nápovědu): c
Příznak DOSOVÉ kompatibility není nastaven.

Příkaz (m pro nápovědu): u
Měním jednotky v nichž jsou vypisovány informace na sektory

Příkaz (m pro nápovědu): d
Vybrán oddíl 1

Příkaz (m pro nápovědu): n
Příkaz
   e   rozšířený diskový oddíl
   p   primární diskový oddíl (1-4)
p
Číslo diskového oddílu (1-4): 1
První sektor (2048-20971519, implicitně 2048):
Používám implicitní hodnotu 2048
Poslední sektor, +sektory nebo +velikost{K,M,G} (2048-20971519, implicitně 20971519):
Používám implicitní hodnotu 20971519

Příkaz (m pro nápovědu): p

Disk /dev/sda: 10,7 GB, 10 737 418 240 bajtů
hlav: 181, sektorů na stopu: 40, cylindrů: 2 896, celkem 20 971 520 sektorů
Jednotky = sektory po 1 * 512 = 512 bajtech
Velikost sektoru (logického/fyzického): 512 bajtů / 512 bajtů
Velikost I/O (minimální/optimální): 512 bajtů / 512 bajtů
Identifikátor disku: 0x00052b20

Zařízení Zavádět   Začátek       Konec    Bloky    Id  Systém
/dev/sda1            2048    20971519    10484736   83  Linux

Příkaz (m pro nápovědu): x

Příkaz pro odborníky (m pro nápovědu): p

Disk /dev/sda: hlav: 181, sektorů: 40, cylindrů: 2 896

Č. AF  Hd Sek  Cyl  Hd Sek  Cyl    Začátek     Vel.   Id
 1 00  51   9    0 111  40  848       2048   20969472 83
 2 00   0   0    0   0   0    0          0          0 00
 3 00   0   0    0   0   0    0          0          0 00
 4 00   0   0    0   0   0    0          0          0 00

Jak vidíte, po vypnutí kompatibility s DOSem začíná nově vytvořený oddíl na správném bloku číslo 2048. Trochu matoucí je, že nová tabulka i přesto obsahuje jiné CHS hodnoty začátku oddílu, to zřejmě souvisí se změnou virtuální geometrie zvětšeného virtuálního disku. Linux s tím ale nemá problém, tak to nejspíš nemá smysl řešit.

Poučení pro příště:

  • Neignorujte varování.
  • Měníte-li MBR na disku s daty, vždy si udělejte zálohu původního.

Sdílet