I recently had to replace the system disk in a FreeBSD machine (SMART self-tests failed, better be safe than sorry), this is my recipe for an “online” replacement. I did this in multi-user mode with all services shut down.
ad4 is the disk that is going to be replaced (ie. the old disk) and ad6 is new the new one, the new disk was of identical size so I simply kept the old partition layout.
Be extremely careful when entering your disk names as one command to the wrong disk could make you loose data.
The layout of the old disk looked like this
Filesystem Size Used Avail Capacity Mounted on /dev/ad4s1a 496M 351M 105M 77% / /dev/ad4s1e 496M 213M 243M 47% /tmp /dev/ad4s1f 124G 29G 85G 26% /usr /dev/ad4s1d 3.9G 1.5G 2.0G 43% /var
Make sure the disk is treated as a new one (overwrite old slice information if any, should not be needed if it’s a brand new drive)
> dd if=/dev/zero of=/dev/ad6 bs=512 count=100 100+0 records in 100+0 records out 51200 bytes transferred in 0.038179 secs (1341054 bytes/sec)
Create a slice that covers the whole disk and install MBR on the new disk
> fdisk -v -B -I -a /dev/ad6
I was replacing the disk with one of identical size so I just used the same partitions as before, If your disk is larger you’ll need to adjust your partition sizes.
Read and save the label from the old disk
> bsdlabel /dev/ad4s1 > /tmp/label
Restore the label on the new disk and install boot code
> bsdlabel -R /dev/ad6s1 /tmp/label > bsdlabel -B /dev/ad6s1
I had a slight problem as the new disk which was “identical” in size actually was 2 MB larger so I had to adjust the c: partition in /tmp/label to cover the whole disk before restoring it onto the new one. fdisk /dev/ad6 reports the actual size.
Make sure the new partitions look OK and that bsdlabel doesn’t emit warning about overlapping partitions etc.
> bsdlabel /dev/ad6s1 # /dev/ad6s1: 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 1048576 0 4.2BSD 2048 16384 8 b: 4132160 1048576 swap c: 293046705 0 unused 0 0 # "raw" part, don't edit d: 8388608 5180736 4.2BSD 2048 16384 28528 e: 1048576 13569344 4.2BSD 2048 16384 8 f: 278423682 14617920 4.2BSD 2048 16384 14080
As far as partitioning and MBR/boot code the disk should be ready. Now what’s left is formatting the partition and copying the data.
Create a file system on the / partition, no soft updates.
> newfs /dev/ad6s1a
Create file system for /tmp, /var and /usr with soft updates
> newfs -U /dev/ad6s1d > newfs -U /dev/ad6s1e > newfs -U /dev/ad6s1f
Mount the NEW root onto /mnt (or any other suitable place)
> mount /dev/ad1s1a /mnt/
Do a live level 0 dump of the original / onto the new /
> dump -L -0 -f- / | (cd /mnt/ && restore -r -v -f-)
Mount the remaining partitions
> mount /dev/ad6s1e /mnt/tmp > mount /dev/ad6s1d /mnt/var > mount /dev/ad6s1f /mnt/usr
And do the dump/restore dance for these partitions as well.
> dump -L -0 -f- /tmp | (cd /mnt/tmp && restore -r -v -f-) > dump -L -0 -f- /var | (cd /mnt/var && restore -r -v -f-) > dump -L -0 -f- /usr | (cd /mnt/usr && restore -r -v -f-)
Now either adjust /mnt/etc/fstab so that the partitions refer to the new disk name (in my case that would have be to replace ad4 with ad6) or simply reconnect the new disk to the old disks’ (s)ata port (this is what I did). Disconnect the old disk and boot the system, it should now be running on the new disk with all data intact.
Depending on how much data there is to copy, down time can be kept to an hour or so.
If it doesn’t boot? Re-connect the old drive and redo the thing. Installing the boot code is very importat, otherwise it simply won’t boot.