APFS tools suck

APFS is now over two years old, its official release having been in March 2017 with iOS 10.3. Look at its supporting tools today, though, and you could be forgiven for thinking that it’s still in beta.

A couple of days ago, I looked at its limitations in terms of minimum size of containers and volumes, mainly using Disk Utility, and came away completely confused. I resolved to return and this time tackle the problem at the command line, using the all-powerful diskutil. This article is a report on the complications that result from trying to manage APFS using diskutil.

If you’ve used diskutil to manage HFS+ disks and volumes, you’ll be disappointed to discover that, rather than extend its standard set of verbs, Apple has effectively shoehorned in a second tool with its own set of verbs which are prefaced by
diskutil apfs
and using man diskutil is more like opening a disjoint library.

apfstools01

Erasing a disk and creating a single APFS container with a single APFS volume is simple using the eraseDisk verb, but what you can’t do is create any more than a single APFS container. For example, repartitioning an existing disk with
diskutil partitionDisk disk5 GPT apfs test1 125g apfs test2 0
which you’d expect to create one container of 125 GB and a second occupying the remainder of the disk, returns the error
You may not specify more than one APFS Container per partition map

Similarly, trying to cheat and splitting a second non-APFS partition into one APFS container and a journalled HFS+ volume using
diskutil splitPartition disk5s3 apfs test2 50g jhfs+ remains R
results in the doom-laden error
You may not cause more than one APFS Container to exist per partition map
which could make you assume that disks can only have a maximum of one APFS container after all.

Being persistent if not dogged, I then tried creating a single APFS container, shrinking it to the new size of 125 GB, then adding a second. I started with
diskutil apfs resizeContainer disk6 125g
which works fine, and leaves the remainder of the disk unallocated. But you can’t then use diskutil apfs createContainer to add the second container, nor can you allocate the remainder using a plain diskutil command.

One interesting feature of the createContainer option is that it allows you to make APFS ‘Fusion Drives’. If you have two APFS disks, each with single containers, you can link them together to function as one using a command like
diskutil apfs createContainer -main disk6 -secondary disk7
where disk6 becomes the primary caching store, and disk7 the secondary store, assumed to be the slower of the pair.

At this stage, I decided that my only option was to cheat, and see how Disk Utility manages to add a new container when you repartition an APFS disk. Its sequence runs:

  1. resize the existing container to its new size and check it;
  2. create a case-insensitive journalled HFS+ volume in the unallocated space;
  3. convert the HFS+ volume to a single APFS container with a single volume.

which is a workaround, not a solution.

Taking the hint, I found that I could create a disk with three APFS containers as follows. I created the first APFS container using
diskutil partitionDisk disk5 GPT apfs test1 125g jhfs+ test2 50g jhfs+ test3 0
then converted each of the two HFS+ partitions into APFS containers using
diskutil apfs convert disk5s3

If you want to add a container to an existing disk, though, things get more complicated, as you’ll first have to shrink an existing APFS container using something like
diskutil apfs resizeContainer disk6 125g
You then have to unmount the disk and use the gpt command to add the HFS+ partition, which is detailed in klanomath’s excellent answer here. I’m afraid that at that stage I chickened out and looked at adding volumes, which is consummately easy by comparison:
diskutil apfs addVolume disk6 APFS test1a
and so on.

I had finally divided my single external SSD into three APFS containers, each of which contains two volumes.

apfstools02

Returning to my point of entry, it perhaps isn’t surprising that there is little correlation between the minimum container size given in Apple’s APFS documentation and what actually happens, given the circuitous means by which containers have to be created. If Apple’s tools for working with APFS are anything to go by, we’re not supposed to be using multiple containers at all, which seems odd given that it was Apple which designed them into APFS in the first place.

Given that containers are a valuable feature in APFS, why, more than two years after its release, has Apple not provided command tools which fully support its features? Nor does there appear to be any sign of change coming in Catalina, as far as I can gather.

Should you know of any better solutions to these problems, I’d be delighted to learn of them, please.