I have a pile of hard drives. 3.5” Spinning rust. There’s like a dozen of them, some labeled cryptically (EBN D2), some infuriatingly (1) and some not-at-all. Probably most of them work. But how to effectively figure out what is on them? FreeBSD to the rescue.

Hotplug Just Works

All the drives are SATA. I do have an IDE drive, I use it for opening beer bottles. And an ST-225 for old-time’s sake. But SATA it is, and there’s spare SATA data- and power-cables dangling out the side of my PC. This particular machine runs FreeBSD 14.3, and connecting a drive (data first, then power) yields some messages in the system log. Old-school, the command to read these is still dmesg, which prints:

ada3 at ahcich0 bus 0 scbus0 target 0 lun 0
ada3: <WDC WD3200AAKS-00SBA0 12.01B01> ATA-7 SATA 2.x device
ada3: Serial Number WD-WMAPZ0561055
ada3: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
ada3: Command Queueing enabled
ada3: 305245MB (625142448 512 byte sectors)

That matches information printed on the label of the disk (this drive is from 2007, has a 1 written on it in black marker – it may have been a drive in the English Breakfast Network server back then). It also tells me that the disk is registered with the system as ada3.

FreeBSD’s disk subsystem is a stack of “GEOM classes”. The geom(4) manpage tells me that it is a modular disk I/O request transformation framework, but the important bit is geom(8), the command to query the disk subsystem. Running geom disk list ada3 tells me what is known about disks involved with ada3. This actually doesn’t tell me much I don’t already know:

Geom name: ada3
Providers:
1. Name: ada3
   Mediasize: 320072933376 (298G)
   Sectorsize: 512
   Mode: r0w0e0
   descr: WDC WD3200AAKS-00SBA0
   lunid: 50014ee0aabd8fe3
   ident: WD-WMAPZ0561055
   rotationrate: unknown
   fwsectors: 63
   fwheads: 16

Well, actually this tells me that the dmesg and geom output are in mibi- and gibi-bytes, and that they’re consistent. How about partitions on this disk, though? geom part list ada3 tells me (here I’ve removed several partitions, along with many other lines that are not very useful right now; the output is extensive):

Geom name: ada3
scheme: GPT
Providers:
1. Name: ada3p1
   Mediasize: 819200 (800K)
   efimedia: HD(1,GPT,a43a2da3-bb5f-11e5-8d81-f5e4d894ddb1,0x22,0x640)
   label: (null)
   type: efi
   index: 1
2. Name: ada3p2
   Mediasize: 315679277056 (294G)
   efimedia: HD(2,GPT,a43c9069-bb5f-11e5-8d81-f5e4d894ddb1,0x662,0x24bff9c0)
   label: (null)
   type: freebsd-ufs
   index: 2

So it is a GPT-partitioned disk, and at least one of the partitions is an “old-fashioned” UFS partition. That’s FreeBSD before ZFS became the de-facto standard filesystem (maybe just for me). This disk is simple to deal with (further notes below)!

After I’m done with the disk, I power it down first with camcontrol standby ada3. I can hear the disk stop spinning and then pull out the connectors (power first, then data). And move on to the next disk. After disconnecting, dmesg confirms that I unplugged the correct drive:

ada3 at ahcich0 bus 0 scbus0 target 0 lun 0
ada3: <WDC WD3200AAKS-00SBA0 12.01B01> s/n WD-WMAPZ0561055 detached
(ada3:ahcich0:0:0:0): Periph destroyed

This way I can step through all of the drives in my pile and then jot down what disk does what (or, in rare cases, decide they can be zeroed out and re-used for something else).

Dealing with non-GPT disks

The scheme reported by geom part list is GPT if you’re sensible, but of course it is possible to bump into MBR and BSD disklabels as well. The geom subsystem abstracts all that away, and the only realy difference is the names of devices.

Scheme BSD, also known as BSD disklabel, gives you ada3a and ada3d, rather than numbered partitions. It is possible to apply this to a whole disk. It is also possible to have a BSD disklabel inside an MBR partition, but that’s a late-90s kind of setup.

Scheme MBR gives you numbered partitions, but FreeBSD calls these slices instead of partitions and so you end up with ada3s1 instead of ada3p1.

Dealing with UFS

UFS partitions are pretty simple: mount them somewhere and things will be OK. I go for read-only, and I have a /mnt/tmp for all my arbitrary-disk-mounting activity. So mount -o ro /dev/ada3p2 /mnt/tmp it is (ada3p2 is the partition name found earlier).

This particular disk turned out to be my main workstation drive around 2017, with a handful of still-interesting files on it. Ones I would not have missed if I hadn’t looked, but it was nice to find a presentation PDF I gave to SIDN once-upon-a-time.

After looking, umount /mnt/tmp to unmount and release the disk. After that, power-down and disconnect as described above.

Dealing with ZFS

Slightly newer disks might be ZFS. Here’s the partition information for one:

Providers:
1. Name: ada3p1
   Mediasize: 250059309056 (233G)
   label: backup0
   type: freebsd-zfs
   index: 1

It’s a GPT partition with a label, and ZFS on it. That means it’s part of a ZFS pool, and is probably referred to within the pool by its label. Possibly by its ID. In any case, ZFS needs to be imported, not mounted, because the filesystems are contained as part of the storage pool. The command to discover what is available is zpool import , which doesn’t actually import anything.

   pool: zbackup
 config:
        zbackup        ONLINE
          gpt/backup0  ONLINE

That’s encouraging: the pool consists of a single drive and everything is online. To make the filesystems in this pool available, I need to import it. I’ll force it (-f, because it was probably untimely ripp’d from whatever machine it was in previously), without mounting any of the filesystems in it (-N), readonly (-o readonly=on) with a temporary name (-t zwhat), like so: zpool import -f -N -o readonly=on -t zbackup zwhat

After importing the pool, zfs list tells me what filesystems are available:

zwhat                       36.2G   189G    25K  /zwhat
zwhat/home                  36.2G   189G  36.0G  /tmp/foo/

I can mount a single ZFS filesystem just like a UFS filesystem. The ZFS filesystem knows where it would want to be mounted (/tmp/foo, I have no idea what I was doing back then), but we can treat it like a legacy filesystem: mount -t zfs zwhat/home /mnt/tmp

After looking, umount /mnt/tmp to unmount and release the disk. After that, power-down and disconnect as described above.

Dealing with Linux ext4

If the disk comes from a Linux machine, then it may have an ext4 filesystem on it. I still usually pick that when installing Linuxes. Here’s the partition information for one:

scheme: MBR
Providers:
2. Name: ada3s2
   Mediasize: 64428703744 (60G)
   rawtype: 131
   type: linux-data

There is ext4 support in the FreeBSD kernel, although it is named ext2 (and some ext4 filesystems use unsupported features, and then it won’t mount). But for simple cases: mount -o ro -t ext2fs /dev/ada3s2 /mnt/tmp does the job.

Dealing with linux-raid

I found two disks, both WD Caviar Blue, labeled EBN D1 and EBN D2 with similar layouts. Those are linux-raid disks, and this is something I can’t deal with in FreeBSD. Heck, I’m not confident I can deal with them under Linux anymore, either.

Providers:
1. Name: ada3s1
   Mediasize: 493928031744 (460G)
   efimedia: HD(1,MBR,0xa8a8a8a8,0x3f,0x398033d3)
   rawtype: 253
   type: linux-raid

Re-purposing Disks

KDE has a lovely partitioning tool, but I wouldn’t be me if I didn’t go for the command-line approach. Make sure the disk isn’t mounted anywhere, but is powered up.

Zero out the first gigabyte or so of the disk: dd if=/dev/zero of=/dev/ada3 bs=1M count=1024 I guess this isn’t strictly necessary, and geom warns during this operation that the GPT is corrupt and the backup GPT (at the other end of the disk) should probably be used. Ignore that.

Destroy the partition table some more: geom part destroy -F ada3 , now it is really dead.

Make a new GPT partition table on the disk: geom part create -s gpt ada3

Start adding partitions to the partition table. I (now) use labels with the last digits of the drive’s serial-number. This drive gets a gigabyte of swap (just in case) and the rest is a ZFS partition which I can add to a pool later.

  • geom part add -t freebsd-swap -s 1G -l swap-159666 ada3
  • geom part add -t freebsd-zfs -l zfs-159666 ada3

Why the labels-with-serial-numbers? Well, that’s so that I can subsequently create a ZFS pool from labeled partitions, and it remains obvious where the parts of the pool come from and also prevents name-collisions from naming everything backup0 and so.