zfs – a helper script for labelling all those drives

I now have a Dell R7425 with 12 x 12TB HDD in the basement.

A raidz2 zpool would give me about 120TB – with a significant resilver time.

I have also thought about a creating 6 x mirrors and striping across them. That would give me about 72TB – that’s still a lot.

However I do it, I’m going to label the partitions with the drive slot and serial number. I’m going to write a little helper script. I’m guessing by the time I finish writing this blog post, I could have done the labelling manually. However, if I have to redo the labelling because I messed up, I think that’s where the script will pay off.

Some background

This is the zpool status from r730-03:

[16:42 r730-03 dvl ~] % zpool status
  pool: data01
 state: ONLINE
  scan: scrub repaired 0B in 1 days 04:29:00 with 0 errors on Fri May 29 08:31:09 2026
config:

	NAME                   STATE     READ WRITE CKSUM
	data01                 ONLINE       0     0     0
	  mirror-0             ONLINE       0     0     0
	    gpt/SEAG_ZJV4HFPE  ONLINE       0     0     0
	    gpt/SEAG_ZHZ16KEX  ONLINE       0     0     0
	  mirror-1             ONLINE       0     0     0
	    gpt/SG_ZHZ03BAT    ONLINE       0     0     0
	    gpt/HGST_8CJW1G4E  ONLINE       0     0     0
	  mirror-2             ONLINE       0     0     0
	    gpt/SG_ZL2NJBT2    ONLINE       0     0     0
	    gpt/HGST_5PGGTH3D  ONLINE       0     0     0

errors: No known data errors

  pool: zroot
 state: ONLINE
status: Some supported and requested features are not enabled on the pool.
	The pool can still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
	the pool may no longer be accessible by software that does not support
	the features. See zpool-features(7) for details.
  scan: scrub repaired 0B in 00:01:49 with 0 errors on Thu May 28 04:04:13 2026
config:

	NAME        STATE     READ WRITE CKSUM
	zroot       ONLINE       0     0     0
	  mirror-0  ONLINE       0     0     0
	    ada1p3  ONLINE       0     0     0
	    ada0p3  ONLINE       0     0     0

errors: No known data errors

Notice how the drives in data01 are labelled with the drive brand (e.g. Seagate) and the serial number (ZJV4HFPE).

This helps to correctly identify the drive you want to remove, should one need replacing.

These are the drives in the Dell R7425 (the hostname is r7425-01).

root@r7425-01:~ # sesutil show
ses0: <DP BP14G+EXP 2.52>; ID: 500056b345a433ff
Desc            Dev     Model                     Ident                Size/Status
Drive Slot 0    da0     ATA HGST HUH721212AL      8CGSV9DG             Unknown
Drive Slot 1    da1     ATA HGST HUH721212AL      8CGSXG6G             Unknown
Drive Slot 2    da2     ATA HGST HUH721212AL      8HGAWR3H             Unknown
Drive Slot 3    da3     ATA HGST HUH721212AL      8CGSVS3G             Unknown
Drive Slot 4    da4     ATA HGST HUH721212AL      8CGSB6YG             Unknown
Drive Slot 5    da5     ATA HGST HUH721212AL      8CGSZ0VG             Unknown
Drive Slot 6    da6     ATA HGST HUH721212AL      8CGSZY5G             Unknown
Drive Slot 7    da7     ATA HGST HUH721212AL      8CGSV8YG             Unknown
Drive Slot 8    da8     ATA HGST HUH721212AL      8CGS875G             Unknown
Drive Slot 9    da9     ATA HGST HUH721212AL      8CGSBA2G             Unknown
Drive Slot 10   da10    ATA HGST HUH721212AL      8CGSX4UG             Unknown
Drive Slot 11   da11    ATA HGST HUH721212AL      8CGSDEHG             Unknown
Drive Slot 12   da12    ATA ST1000NM0018-2F2      ZFA0NVQD             Unknown
Drive Slot 13   -       -                         -                    Not Installed
Drive Slot 14   da13    ATA MTFDDAK480TDN         191821E45D17         Unknown
Drive Slot 15   da14    ATA MTFDDAK480TDN         191821E45DA1         Unknown
Drive Slot 16   -       -                         -                    Not Installed
Drive Slot 17   -       -                         -                    Not Installed

Some notes:

  • Slots 0-11 are in the front of the chassis. They are the main data drives and are the subjects of this blog post.
  • Slot 12 is mounted in the rear of the chassis and is a 1TB drive
  • slots 14-15 are 2.5″ SSDs mounted internally – they contain the zroot

From the past

I went searching my blog for zpool create and found Copying everything off a zpool, destroying it, creating a new one, and copying everything back – in there, I found this command:

sudo gpart add -a 4K -i 1 -t freebsd-zfs -s 1953520000 -l S59VNS0N809087J_S00 da0

Let’s write a script to output that.

Listing the drives

This is my starting point:

root@r7425-01:~ # sesutil show | grep 'Drive Slot' | grep -vE 'Drive Slot (12|13|14|15|16|17)'
Drive Slot 0    da0     ATA HGST HUH721212AL      8CGSV9DG             Unknown
Drive Slot 1    da1     ATA HGST HUH721212AL      8CGSXG6G             Unknown
Drive Slot 2    da2     ATA HGST HUH721212AL      8HGAWR3H             Unknown
Drive Slot 3    da3     ATA HGST HUH721212AL      8CGSVS3G             Unknown
Drive Slot 4    da4     ATA HGST HUH721212AL      8CGSB6YG             Unknown
Drive Slot 5    da5     ATA HGST HUH721212AL      8CGSZ0VG             Unknown
Drive Slot 6    da6     ATA HGST HUH721212AL      8CGSZY5G             Unknown
Drive Slot 7    da7     ATA HGST HUH721212AL      8CGSV8YG             Unknown
Drive Slot 8    da8     ATA HGST HUH721212AL      8CGS875G             Unknown
Drive Slot 9    da9     ATA HGST HUH721212AL      8CGSBA2G             Unknown
Drive Slot 10   da10    ATA HGST HUH721212AL      8CGSX4UG             Unknown
Drive Slot 11   da11    ATA HGST HUH721212AL      8CGSDEHG             Unknown
root@r7425-01:~ # 

Let’s save that into a file:

root@r7425-01:~ # sesutil show | grep 'Drive Slot' | grep -vE 'Drive Slot (12|13|14|15|16|17)' > data_drives
root@r7425-01:~ # cat data_drives
Drive Slot 0    da0     ATA HGST HUH721212AL      8CGSV9DG             Unknown
Drive Slot 1    da1     ATA HGST HUH721212AL      8CGSXG6G             Unknown
Drive Slot 2    da2     ATA HGST HUH721212AL      8HGAWR3H             Unknown
Drive Slot 3    da3     ATA HGST HUH721212AL      8CGSVS3G             Unknown
Drive Slot 4    da4     ATA HGST HUH721212AL      8CGSB6YG             Unknown
Drive Slot 5    da5     ATA HGST HUH721212AL      8CGSZ0VG             Unknown
Drive Slot 6    da6     ATA HGST HUH721212AL      8CGSZY5G             Unknown
Drive Slot 7    da7     ATA HGST HUH721212AL      8CGSV8YG             Unknown
Drive Slot 8    da8     ATA HGST HUH721212AL      8CGS875G             Unknown
Drive Slot 9    da9     ATA HGST HUH721212AL      8CGSBA2G             Unknown
Drive Slot 10   da10    ATA HGST HUH721212AL      8CGSX4UG             Unknown
Drive Slot 11   da11    ATA HGST HUH721212AL      8CGSDEHG             Unknown
root@r7425-01:~ # 

gpart create

Next, let’s compose a command to create gpart partitions on each drive.

NOTE, this command creates the partitions, it’s not echoing out the commands for you to run that.

root@r7425-01:~ # cat data_drives | cut -f 4 -w | xargs -n 1 -I % gpart create -s gpt %
da0 created
da1 created
da2 created
da3 created
da4 created
da5 created
da6 created
da7 created
da8 created
da9 created
da10 created
da11 created
root@r7425-01:~ # 

Next, let’s create a partition, and label it with the drive slot and the serial number.

Partition size?

On FreeBSD, it has been routine procedure to partition the drive and use a partition for the vdev, not the whole raw device. I recall reading the reasoning behind that. I will continue with that routine.

For that, I need to know drive size, and let’s look at this command for that information:

root@r7425-01:~ # diskinfo -v da0
da0
	512         	# sectorsize
	12000138625024	# mediasize in bytes (11T)
	23437770752 	# mediasize in sectors
	4096        	# stripesize
	0           	# stripeoffset
	1458933     	# Cylinders according to firmware.
	255         	# Heads according to firmware.
	63          	# Sectors according to firmware.
	ATA HGST HUH721212AL	# Disk descr.
	8CGSV9DG    	# Disk ident.
	mpr0        	# Attachment
	id1,enc@n500056b345a433fd/type@0/slot@1/elmdesc@Drive_Slot_0	# Physical path
	No          	# TRIM/UNMAP support
	7200        	# Rotation rate in RPM
	Not_Zoned   	# Zone Mode

root@r7425-01:~ # 

We have 23,437,770,752 sectors (mediasize in sectors), each one being 512 bytes (sectorsize)

I’m going to leave 2.5M free at the end of that drive, just in case any replacement drive comes up a little bit short. 2.5M is 2,621,440 bytes. 2,621,440 bytes / 512 bytes per sector is 5,120 sectors.

The size on the gpart command will be 23,437,770,752 – 5,120 = 23,437,765,632

The partition add

The script I came up with is. This command echos the commands you want to run later.

root@r7425-01:~ # cat data_drives | awk '{  print "gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_" $3 "_" $8 " " $4 }'
gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_0_8CGSV9DG da0
gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_1_8CGSXG6G da1
gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_2_8HGAWR3H da2
gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_3_8CGSVS3G da3
gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_4_8CGSB6YG da4
gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_5_8CGSZ0VG da5
gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_6_8CGSZY5G da6
gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_7_8CGSV8YG da7
gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_8_8CGS875G da8
gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_9_8CGSBA2G da9
gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_10_8CGSX4UG da10
gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_11_8CGSDEHG da11

Let’s try running that first command:

root@r7425-01:~ # gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_0_8CGSV9DG da0
da0p1 added
root@r7425-01:~ # gpart show da0
=>         40  23437770672  da0  GPT  (11T)
           40  23437765632    1  freebsd-zfs  (11T)
  23437765672         5040       - free -  (2.5M)

root@r7425-01:~ # gpart show -l da0
=>         40  23437770672  da0  GPT  (11T)
           40  23437765632    1  slot_0_8CGSV9DG  (11T)
  23437765672         5040       - free -  (2.5M)

root@r7425-01:~ # ls -l /dev/gpt
total 0
crw-r-----  1 root operator 0xd1 May 30 16:27 efiboot0
crw-r-----  1 root operator 0xc5 May 30 16:27 efiboot1
crw-r-----  1 root operator 0xf5 May 30 17:34 slot_0_8CGSV9DG
root@r7425-01:~ # 

That looks right. Let’s run the rest:

root@r7425-01:~ # gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_1_8CGSXG6G da1
da1p1 added
root@r7425-01:~ # gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_2_8HGAWR3H da2
da2p1 added
root@r7425-01:~ # gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_3_8CGSVS3G da3
da3p1 added
root@r7425-01:~ # gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_4_8CGSB6YG da4
da4p1 added
root@r7425-01:~ # gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_5_8CGSZ0VG da5
da5p1 added
root@r7425-01:~ # gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_6_8CGSZY5G da6
da6p1 added
root@r7425-01:~ # gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_7_8CGSV8YG da7
da7p1 added
root@r7425-01:~ # gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_8_8CGS875G da8
da8p1 added
root@r7425-01:~ # gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_9_8CGSBA2G da9
da9p1 added
root@r7425-01:~ # gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_10_8CGSX4UG da10
da10p1 added
root@r7425-01:~ # gpart add -a 4K -i 1 -t freebsd-zfs -s 23437765632 -l slot_11_8CGSDEHG da11
da11p1 added
root@r7425-01:~ # ls -l /dev/gpt
total 0
crw-r-----  1 root operator  0xd1 May 30 16:27 efiboot0
crw-r-----  1 root operator  0xc5 May 30 16:27 efiboot1
crw-r-----  1 root operator  0xf5 May 30 17:34 slot_0_8CGSV9DG
crw-r-----  1 root operator 0x135 May 30 17:36 slot_10_8CGSX4UG
crw-r-----  1 root operator 0x13b May 30 17:36 slot_11_8CGSDEHG
crw-r-----  1 root operator  0xff May 30 17:36 slot_1_8CGSXG6G
crw-r-----  1 root operator 0x105 May 30 17:36 slot_2_8HGAWR3H
crw-r-----  1 root operator 0x10b May 30 17:36 slot_3_8CGSVS3G
crw-r-----  1 root operator 0x111 May 30 17:36 slot_4_8CGSB6YG
crw-r-----  1 root operator 0x117 May 30 17:36 slot_5_8CGSZ0VG
crw-r-----  1 root operator 0x11d May 30 17:36 slot_6_8CGSZY5G
crw-r-----  1 root operator 0x123 May 30 17:36 slot_7_8CGSV8YG
crw-r-----  1 root operator 0x129 May 30 17:36 slot_8_8CGS875G
crw-r-----  1 root operator 0x12f May 30 17:36 slot_9_8CGSBA2G

So far so good.

The zpool create

I thought about this.. how best to mirror the drives. The drives are stacked 3 high and 4 across. I thought: put mirrored drives right beside each other. Would that help with future tasks?

Then I thought: hell, no, that might take some interesting maneuvers in the zpool create command…. Let’s keep this part simple.

Next, so I did not have to copy / paste the device names, I did this:

root@r7425-01:~ # cat data_drives | awk '{  print "/dev/gpt/slot_" $3 "_" $8}'
/dev/gpt/slot_0_8CGSV9DG
/dev/gpt/slot_1_8CGSXG6G
/dev/gpt/slot_2_8HGAWR3H
/dev/gpt/slot_3_8CGSVS3G
/dev/gpt/slot_4_8CGSB6YG
/dev/gpt/slot_5_8CGSZ0VG
/dev/gpt/slot_6_8CGSZY5G
/dev/gpt/slot_7_8CGSV8YG
/dev/gpt/slot_8_8CGS875G
/dev/gpt/slot_9_8CGSBA2G
/dev/gpt/slot_10_8CGSX4UG
/dev/gpt/slot_11_8CGSDEHG

And yes, those all exist:

root@r7425-01:~ # cat data_drives | awk '{  print "/dev/gpt/slot_" $3 "_" $8}' | xargs ls -l
crw-r-----  1 root operator  0xf5 May 30 17:34 /dev/gpt/slot_0_8CGSV9DG
crw-r-----  1 root operator 0x135 May 30 17:36 /dev/gpt/slot_10_8CGSX4UG
crw-r-----  1 root operator 0x13b May 30 17:36 /dev/gpt/slot_11_8CGSDEHG
crw-r-----  1 root operator  0xff May 30 17:36 /dev/gpt/slot_1_8CGSXG6G
crw-r-----  1 root operator 0x105 May 30 17:36 /dev/gpt/slot_2_8HGAWR3H
crw-r-----  1 root operator 0x10b May 30 17:36 /dev/gpt/slot_3_8CGSVS3G
crw-r-----  1 root operator 0x111 May 30 17:36 /dev/gpt/slot_4_8CGSB6YG
crw-r-----  1 root operator 0x117 May 30 17:36 /dev/gpt/slot_5_8CGSZ0VG
crw-r-----  1 root operator 0x11d May 30 17:36 /dev/gpt/slot_6_8CGSZY5G
crw-r-----  1 root operator 0x123 May 30 17:36 /dev/gpt/slot_7_8CGSV8YG
crw-r-----  1 root operator 0x129 May 30 17:36 /dev/gpt/slot_8_8CGS875G
crw-r-----  1 root operator 0x12f May 30 17:36 /dev/gpt/slot_9_8CGSBA2G

Next, I went one step farther:

root@r7425-01:~ # cat data_drives | awk '{  print "/dev/gpt/slot_" $3 "_" $8}' | xargs -n 2 echo  mirror
mirror /dev/gpt/slot_0_8CGSV9DG /dev/gpt/slot_1_8CGSXG6G
mirror /dev/gpt/slot_2_8HGAWR3H /dev/gpt/slot_3_8CGSVS3G
mirror /dev/gpt/slot_4_8CGSB6YG /dev/gpt/slot_5_8CGSZ0VG
mirror /dev/gpt/slot_6_8CGSZY5G /dev/gpt/slot_7_8CGSV8YG
mirror /dev/gpt/slot_8_8CGS875G /dev/gpt/slot_9_8CGSBA2G
mirror /dev/gpt/slot_10_8CGSX4UG /dev/gpt/slot_11_8CGSDEHG

That output now just needs a zpool create data01 in front of it. Let’s go.

Oh, that’s wrong. That failed. It created a zpool of two drives. I need trailing \ on each line.

I tried mucking about with the script. I failed. Instead, I copied the output to an editor, added the trailing \ and came up with this:

zpool create data01 \
mirror /dev/gpt/slot_0_8CGSV9DG /dev/gpt/slot_1_8CGSXG6G \
mirror /dev/gpt/slot_2_8HGAWR3H /dev/gpt/slot_3_8CGSVS3G \
mirror /dev/gpt/slot_4_8CGSB6YG /dev/gpt/slot_5_8CGSZ0VG \
mirror /dev/gpt/slot_6_8CGSZY5G /dev/gpt/slot_7_8CGSV8YG \
mirror /dev/gpt/slot_8_8CGS875G /dev/gpt/slot_9_8CGSBA2G \
mirror /dev/gpt/slot_10_8CGSX4UG /dev/gpt/slot_11_8CGSDEHG

And I ran it:

root@r7425-01:~ # zpool create data01 \
> mirror /dev/gpt/slot_0_8CGSV9DG /dev/gpt/slot_1_8CGSXG6G \
> mirror /dev/gpt/slot_2_8HGAWR3H /dev/gpt/slot_3_8CGSVS3G \
> mirror /dev/gpt/slot_4_8CGSB6YG /dev/gpt/slot_5_8CGSZ0VG \
> mirror /dev/gpt/slot_6_8CGSZY5G /dev/gpt/slot_7_8CGSV8YG \
> mirror /dev/gpt/slot_8_8CGS875G /dev/gpt/slot_9_8CGSBA2G \
> mirror /dev/gpt/slot_10_8CGSX4UG /dev/gpt/slot_11_8CGSDEHG

root@r7425-01:~ # 

And I have:

root@r7425-01:~ # zpool list
NAME     SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
data01  65.4T   480K  65.4T        -         -     0%     0%  1.00x    ONLINE  -
zroot    436G  1.14G   435G        -         -     0%     0%  1.00x    ONLINE  -
root@r7425-01:~ # zpool status data01
  pool: data01
 state: ONLINE
config:

	NAME                      STATE     READ WRITE CKSUM
	data01                    ONLINE       0     0     0
	  mirror-0                ONLINE       0     0     0
	    gpt/slot_0_8CGSV9DG   ONLINE       0     0     0
	    gpt/slot_1_8CGSXG6G   ONLINE       0     0     0
	  mirror-1                ONLINE       0     0     0
	    gpt/slot_2_8HGAWR3H   ONLINE       0     0     0
	    gpt/slot_3_8CGSVS3G   ONLINE       0     0     0
	  mirror-2                ONLINE       0     0     0
	    gpt/slot_4_8CGSB6YG   ONLINE       0     0     0
	    gpt/slot_5_8CGSZ0VG   ONLINE       0     0     0
	  mirror-3                ONLINE       0     0     0
	    gpt/slot_6_8CGSZY5G   ONLINE       0     0     0
	    gpt/slot_7_8CGSV8YG   ONLINE       0     0     0
	  mirror-4                ONLINE       0     0     0
	    gpt/slot_8_8CGS875G   ONLINE       0     0     0
	    gpt/slot_9_8CGSBA2G   ONLINE       0     0     0
	  mirror-5                ONLINE       0     0     0
	    gpt/slot_10_8CGSX4UG  ONLINE       0     0     0
	    gpt/slot_11_8CGSDEHG  ONLINE       0     0     0

errors: No known data errors
root@r7425-01:~ # 
Website Pin Facebook Twitter Myspace Friendfeed Technorati del.icio.us Digg Google StumbleUpon Premium Responsive

Leave a Comment

Scroll to Top