FreeBSD neumí zmenšit svůj výchozí FS UFS. Pokud potřebujeme zmenšit rootfs, je potřeba vytvořit nový ufs na jiném zařízení a data tam přenést. Tento návod ukáže, jak na to.

Výchozí stav, systém máme na jednom 1TB disku (zařízení da0).

root@bsdtest:~ # gpart show
=>        40  2097151920  da0  GPT  (1.0T)
          40        1024    1  freebsd-boot  (512K)
        1064  2088762368    2  freebsd-ufs  (996G)
  2088763432     8388527    3  freebsd-swap  (4.0G)
  2097151959           1       - free -  (512B)

Přičemž data jsou poměrně malá (toto je výchozí instalace FreeBSD 11.2, ale na zaběhaném systému nemusí rootfs přesáhnout 20GB, pokud tam nemáme /usr/home nebo jiné datové adresáře - což většinou nemáme):

root@bsdtest:~ # df -h /
Filesystem    Size    Used   Avail Capacity  Mounted on
/dev/da0p2    965G    1.6G    886G     0%    /

Na novém disku (v tomto případě da1) si připravíme oddíly.

Je velmi důležité zachovat pořadí (čísla) oddílů stejné jako je na původním systémovém disku.

V případě větších disků se 4k bloky (Advanced Format), nebo SSD budeme chtít oddíly zarovnat (buď na 4k nebo rovnou 1M). K zarovnání slouží parametr -a příkazu gpart add.

root@bsdtest:~ # gpart create -s gpt da1
da1 created
root@bsdtest:~ # gpart add -i 1 -t freebsd-boot -s 512K da1
da1p1 added
root@bsdtest:~ # gpart add -i 2 -s 28G -t freebsd-ufs -l rootfs da1
da1p2 added
root@bsdtest:~ # gpart add -i 3 -t freebsd-swap  da1
da1p3 added
root@bsdtest:~ # gpart show da1
=>      40  67108784  da1  GPT  (32G)
        40      1024    1  freebsd-boot  (512K)
      1064  58720256    2  freebsd-ufs  (28G)
  58721320   8387504    3  freebsd-swap  (4.0G)

a nainstalujeme bootloader:

root@bsdtest:~ # gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 da1
partcode written to da1p1
bootcode written to da1

a rovnou vytvoříme nový FS na datovém oddílu:

Pokud máme SSD, můžeme zapnout TRIM parametrem -t. Dá se to změnit i později programem tunefs, ale opět v single user režimu.

root@bsdtest:~ # newfs -U /dev/da1p2
/dev/da1p3: 28671.5MB (58719152 sectors) block size 32768, fragment size 4096
        using 46 cylinder groups of 626.09MB, 20035 blks, 80256 inodes.
        with soft updates
super-block backups (for fsck_ffs -b #) at:
 192, ....

Tímto máme vše připraveno pro přenesení dat.

Vlastně nikoliv, pokud chceme využít toho, že UFS umí snapshoty, je potřeba na starém systémovém disku vypnout vlastnost soft-updates.

Ve skutečnosti tou vlastností, která brání použití UFS snapshotů je journal, případně gjournal. Ty lze vypnout pomocí tunefs -j disable, resp. tunefs -J disable. Vypnutím soft-updates se toto provede automaticky jedním příkazem.

To musíme udělat na read-only fs, nejlépe v single user režimu. Nabootujeme tedy do single user:

root@bsdtest:~ # nextboot -o "-s" -k kernel
root@bsdtest:~ # shutdown -r now

a vypneme soft-updates na rootfs:

# tunefs -n disable /
# shutdown -r now

po rebootu zpět do normálního režimu už můžeme přenést data. Připojíme si nově vytvořený FS na novém disku a vlezem do něj:

root@bsdtest:~ # mount /dev/da1p2 /mnt
root@bsdtest:~ # cd /mnt

a přeneseme data:

root@bsdtest:/mnt # dump -L -C32 -f - / | restore -r -f -
  DUMP: Date of this level 0 dump: Fri Aug 10 17:53:08 2018
  DUMP: Date of last level 0 dump: the epoch
  DUMP: Dumping snapshot of /dev/da0p2 (/) to standard output
  DUMP: mapping (Pass I) [regular files]
  DUMP: Cache 32 MB, blocksize = 65536
  DUMP: mapping (Pass II) [directories]
  DUMP: estimated 1356150 tape blocks.
  DUMP: dumping (Pass III) [directories]
  DUMP: dumping (Pass IV) [regular files]
warning: ./.snap: File exists
./tmp/rstdir1533916388: (inode 51845383) not found on tape
./tmp/rstmode1533916388: (inode 51845384) not found on tape
expected next file 11, got 10

  DUMP: DUMP: 1341320 tape blocks
  DUMP: finished in 60 seconds, throughput 22355 KBytes/sec

  DUMP: DUMP IS DONE

Kde:

  • -L příkazu dump znamená použití UFS snaphotů
  • -C32 je velikost cache
  • -f - výstup půjde na stdout
  • \ je dumpovaný oddíl (takže náš starý systémový root)
  • příkaz restore -r -f - potom obnoví stream z stdin do aktuálního adresáře.

Odpojíme /mnt.

Tímto bychom měli mít hotovo a po fyzickém přehození disků by měl systém nabootovat z nového disku.

Na co si dát pozor:

  • Je potřeba zachovat pořadí oddílů. Jinak bychom museli upravovat parametry bootu, fstab apod.
  • Nezapomenout na bootloader!
  • Nikdy nedumpovat živý systém (příkaz dump to umožňuje), obnovený systém nebude konzistentní. Je lepší použít snapshoty (je nutné vypnout soft-updates).
  • Pokud nelze vypnout soft-updates (přes single user režim), je potřeba celou operaci dělat z LiveCD prostředí - což je, podle mě, náročnější.

Většina návodů dostupných na internetu dělá dump v single user režimu a dumpuje data na jiné zařízení. Následně v normálním režimu obnovuje data na cílový disk. Tohle je také možné udělat (navíc tím získáme backup na externím zařízení), ale je to náročnější na manipulaci s více zařízeními (krom starého a nového disku potřebujeme ještě záložní), a navíc je potřeba provádět tyto operace v poměrně strohém prostředí single user, kde nemáme k dispocici ani normální shell. Proto jsem v tomto návodu postupoval jinak a v single user režimu pouštím pouze jeden jednoduchý příkaz, který umožní na FS vytvářet snapshoty. (Jinak jsou soft-updates velmi zajímavá vlastnost a pro normální běh systému ji určitě doporučuji mít zapnutou.)

Skvělý článek s užitečnými radami pro zarovnání oddílů a aktivaci TRIM.