NetBSD Clone Disk - hpaluch/hpaluch.github.io GitHub Wiki

NetBSD clone disk

Scenario: I have installed NetBSD 11 Beta on small 20GB disk in BIOS mode and MBR partitioning. I want to clone it to bigger 64GB disk. I will use dump|restore combo to clone filesystem to bigger disk.

Useful resource: BSD Dump-Restore - section on NetBSD.

Getting list of disks in system:

$ sysctl hw.disknames

hw.disknames = ld0 ld1 cd0

Where:

  • ld0 is original 20GB disk with installed NetBSD 11 Beta (Virtio-BLK device)
  • ld1 is empty 64GB target disk (Virtio-BLK device)
  • cd0 is CD-ROM (not used)

Setup MBR partition table

Print existing 20GB MBR partition:

fdisk ld0
...
total sectors: 41943040
...

Partition table:
0: NetBSD (sysid 169)
    bootmenu: NetBSD
    start 64, size 41942976 (20480 MB, Cyls 0-2610/212/34), Active
1: <UNUSED>
2: <UNUSED>
3: <UNUSED>

Verifying partition size vs. disk size:

$ echo $(( 41943040 - 64 ))

41942976  # OK matches partition size

Print new disk table (empty)

$ fdisk ld1

total sectors: 134217728

We must compute new partition size for target 64GB disk with total_sectors - partition_start:

$ echo $(( 134217728 - 64 ))

134217664

Now let's create partition table with single NetBSD partition (ID=169) following fdisk manual:

# note: should add -a - make partition active
$ fdisk -f -u -0 -i -s 169/64/134217664 -c /usr/mdec/mbr -b 1023/255/63  ld1

(no output)

Printing target partition table:

$ fdisk ld1

fdisk: Cannot determine the number of heads
Disk: /dev/rld1
NetBSD disklabel disk geometry:
cylinders: 16383, heads: 16, sectors/track: 63 (1008 sectors/cylinder)
total sectors: 134217728, bytes/sector: 512
...
Partition table:
0: NetBSD (sysid 169)
    start 64, size 134217664 (65536 MB, Cyls 0-8354/170/8)
        PBR is not bootable: All bytes are identical (0x00)
1: <UNUSED>
2: <UNUSED>
3: <UNUSED>
Bootselector disabled.
No active partition.
Drive serial number: 0 (0x00000000)

WARNING! There is serious error No active partition.. We have to fix it (standard NetBSD MBR will refuse to boot from non-active partition which is expected behaviour). To fix it:

$ fdisk -a -0 ld1

# answer 'y' to all questions

Checking that partition is now active:

$ fdisk ld1 | grep Active

    start 64, size 134217664 (65536 MB, Cyls 0-8354/170/8), Active

Verifying that target MBR contains MBR boot loader:

  • peeking 1st sector MBR of source disk:

dd if=/dev/ld0 count=1 | hexdump -C

1+0 records in 1+0 records out 512 bytes transferred in 0.001 secs (512000 bytes/sec)

... 00000110 00 00 00 45 72 72 6f 72 20 00 0d 0a 00 4e 65 74 |...Error ....Net| 00000120 42 53 44 20 4d 42 52 20 62 6f 6f 74 00 4e 6f 20 |BSD MBR boot.No | 00000130 61 63 74 69 76 65 20 70 61 72 74 69 74 69 6f 6e |active partition| 00000140 00 44 69 73 6b 20 72 65 61 64 20 65 72 72 6f 72 |.Disk read error| 00000150 00 4e 6f 20 6f 70 65 72 61 74 69 6e 67 20 73 79 |.No operating sy| 00000160 73 74 65 6d 00 49 6e 76 61 6c 69 64 20 43 48 53 |stem.Invalid CHS| 00000170 20 72 65 61 64 00 e8 03 00 be 1a 89 60 ac b4 0e | read.......`...| 00000180 bb 01 00 cd 10 ac 84 c0 75 f4 61 c3 00 00 00 00 |........u.a.....| 00000190 1c 00 b6 00 4e 65 74 42 53 44 00 00 00 00 00 00 |....NetBSD......| ...


- now same for target disk:

```shell
# dd if=/dev/ld1 count=1 | hexdump -C
1+0 records in
1+0 records out
512 bytes transferred in 0.001 secs (512000 bytes/sec)
00000000  31 c0 8e d0 bc 00 7c 8e  c0 8e d8 bf 1d 88 be 1d  |1.....|.........|
00000010  7c 50 57 b9 e3 01 f3 a4  b5 03 f3 ab cb 80 fa 8f  ||PW.............|
00000020  7e 02 b2 80 52 52 be 1d  89 e8 4a 01 bb 94 89 8d  |~...RR....J.....|
...
00000110  00 00 00 45 72 72 6f 72  20 00 0d 0a 00 4e 65 74  |...Error ....Net|
00000120  42 53 44 20 4d 42 52 20  62 6f 6f 74 00 4e 6f 20  |BSD MBR boot.No |
00000130  61 63 74 69 76 65 20 70  61 72 74 69 74 69 6f 6e  |active partition|
00000140  00 44 69 73 6b 20 72 65  61 64 20 65 72 72 6f 72  |.Disk read error|
00000150  00 4e 6f 20 6f 70 65 72  61 74 69 6e 67 20 73 79  |.No operating sy|
00000160  73 74 65 6d 00 49 6e 76  61 6c 69 64 20 43 48 53  |stem.Invalid CHS|
00000170  20 72 65 61 64 00 e8 03  00 be 1a 89 60 ac b4 0e  | read.......`...|
  • looks OK

Setup disklabel

Dumping disklabel on source disk:

# disklabel ld0

4 partitions:
#        size    offset     fstype [fsize bsize cpg/sgs]
 a:  33554368        64     4.2BSD      0     0     0  # (Cyl.      0*-  33288*)
 b:   8388608  33554432       swap                     # (Cyl.  33288*-  41610*)
 c:  41942976        64     unused      0     0        # (Cyl.      0*-  41610*)
 d:  41943040         0     unused      0     0        # (Cyl.      0 -  41610*)

I want to create target disklabel where there will be

  • same swap size - b: 8388608 sectors (4GB)
  • but maximal size of root partition a:

Now we will try to create and edit disklabel on target disk (following disklabel(8) manual page):

# NOTE: replace (-e) with (-i) if disklabel already exists:
disklabel -e -I ld1

VI editor will spun and I removed e: and added a: and b: where I adjusted offset of swap to:

# End of new HDD (d: size) minus swap size (8388608):
$ echo $(( 134217728 - 8388608 ))
125829120

#  I must reduce a: size by 64:
$ echo $(( 125829120 - 64 ))
125829056

Disklabel to be saved in vi editor (:wq command):

4 partitions:
#        size    offset     fstype [fsize bsize cpg/sgs]
 a: 125829056        64     4.2BSD      0     0     0  # (Cyl.      0*- 124830*)
 b:   8388608 125829120       swap                     # (Cyl. 124830*- 133152*)
 c: 134217664        64     unused      0     0        # (Cyl.      0*- 133152*)
 d: 134217728         0     unused      0     0        # (Cyl.      0 - 133152*)

Now you can dump disklabel to see if there is any warning:

disklabel ld1

... change name after label: to something handy ...
label: netbsd64gb
...
4 partitions:
#        size    offset     fstype [fsize bsize cpg/sgs]
 a: 125829056        64     4.2BSD      0     0     0  # (Cyl.      0*- 124830*)
 b:   8388608 125829120       swap                     # (Cyl. 124830*- 133152*)
 c: 134217664        64     unused      0     0        # (Cyl.      0*- 133152*)
 d: 134217728         0     unused      0     0        # (Cyl.      0 - 133152*)

Now we will dump bootsector and disklabel

  • 64th sector => bootsector (so far empty - all zeroes)
  • 65th sector => diklsable - should be there disklabel name
# dd if=/dev/ld1 skip=64 count=2 | hexdump -C
2+0 records in
2+0 records out
1024 bytes transferred in 0.001 secs (1024000 bytes/sec)
# 1st sector (offset 0): boot sector (empty so far)
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
# 2nd sector (offset 512): disklabel:
00000200  57 45 56 82 0f 00 00 00  6c 64 31 00 00 00 00 00  |WEV.....ld1.....|
00000210  00 00 00 00 00 00 00 00  6e 65 74 62 73 64 36 34  |........netbsd64|
00000220  67 62 00 00 00 00 00 00  00 02 00 00 3f 00 00 00  |gb..........?...|
00000230  10 00 00 00 ff 3f 00 00  f0 03 00 00 00 00 00 08  |.....?..........|
00000240  00 00 00 00 00 00 00 00  10 0e 01 00 00 00 00 00  |................|
00000250  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000280  00 00 00 00 57 45 56 82  91 26 04 00 00 20 00 00  |....WEV..&... ..|
00000290  00 20 00 00 c0 ff 7f 07  40 00 00 00 00 00 00 00  |. ......@.......|
000002a0  07 00 00 00 00 00 80 00  00 00 80 07 00 00 00 00  |................|
000002b0  01 00 00 00 c0 ff ff 07  40 00 00 00 00 00 00 00  |........@.......|

Prepare target filesystem

Now we can mostly adapt existing guide BSD Dump Restore.

First verify version of existing filesystem (so we know right argument for newfs command):

$ dumpfs -s ld0a | head -3

file system: /dev/rld0a
format  FFSv2
endian  little-endian

Now install bootblock to future target filesystem:

$ installboot -v /dev/rld1a /usr/mdec/bootxx_ffsv2

File system:         /dev/rld1a
Primary bootstrap:   /usr/mdec/bootxx_ffsv2
Ignoring PBR with invalid magic in sector 0 of `/dev/rld1a'
Boot options:        timeout 5, flags 0, speed 9600, ioaddr 0, console pc

Command fdisk ld1 should no longer report PBR invalid because now there is valid bootsector.

Finally we can format target filesystem:

$ newfs -O 2 /dev/rld1a

/dev/rld1a: 61440.0MB (125829056 sectors) block size 16384, fragment size 2048
        using 333 cylinder groups of 184.52MB, 11809 blks, 22912 inodes.
...

Double-check that reported filesystem size is expected (61GB in my case).

Copy filesystem

Finally we will combine dump/restore in single command to clone live filesystem (using snapshot) to empty filesystem target.

Mount target filesystem (using log to increase speed):

mkdir /mnt/target
mount -o log /dev/ld1a /mnt/target/

And issue dump/restore:

cd /mnt/target
dump -0uaX -f - / | restore rf -

There should be no error, just info messages with prefix DUMP: ...

Now verify that Used column is same for Source and Target filesystem:

$ df -h / /mnt/target

Filesystem     Size   Used  Avail %Cap Mounted on
/dev/ld0a       16G    12G   3.0G  79% /
/dev/ld1a       58G    12G    43G  21% /mnt/target

OK - both have used 12GB

Now unmount target:

cd /
umount /mnt/target

Finally:

  • halt machine with halt -p
  • disconnect 1st HDD and try booting from its clone
  • verify with df that filesystem is indeed bigger (58GB vs 16GB in my case)

Bugs

WARNING! Under some conditions dump/restore commands may trigger kernel panic, due buffers exhaustion. Please see https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=59663 for details.

⚠️ **GitHub.com Fallback** ⚠️