After upgrading a zpool, a message is displayed to execute something along the lines of "sudo gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0" (my quote is not along the lines, rather the instructions are to make substitutions to the quoted text as needed). I'm sure I'm not the only one that has executed that text as-is forgetting to substitute `da0` with whatever device `zroot` is on. This is the output of `zpool status`: ``` ... NAME STATE READ WRITE CKSUM tank ONLINE 0 0 0 mirror-0 ONLINE 0 0 0 da0 ONLINE 0 0 0 da1 ONLINE 0 0 0 ... NAME STATE READ WRITE CKSUM zroot ONLINE 0 0 0 gptid/c3ae7a7e-bc4c-11e3-ab8c-4437e6acfe08 ONLINE 0 0 0 ``` Here, `gptid/c3ae7a7e-bc4c-11e3-ab8c-4437e6acfe08` is da2, and as such, I should have substituted `da0` for `da2` before executing `gpart` above. However, `da0`, `da1`, and `da2` are all valid devices: ``` mqudsi@freebsd ~> sysctl -a kern.disks kern.disks: da2 da1 da0 cd0 mqudsi@freebsd ~> geom disk list | grep "Geom name" Geom name: cd0 Geom name: da0 Geom name: da1 Geom name: da2 ``` However, the problem is that the error code is bubbled up from the actual target of the gpart command (after taking into account the `-i` parameter) such that ultimately an operation was attempted on `/dev/da0p1` which is indeed NOT a geom device (since the disk is consumed whole by zfs in this configuration) but then the error code is munged into an error _message_ that drops the index but keeps the drive, leading to a misleading error about `da0` not being a geom device. Solution: The error message should by `sprintf("%sp%d", arg_geom_disk, arg_p_index)`.
gpart is utility that works with geom objects of class PART. It accepts only objects of class PART, when it is required. So, if you are trying to list partitions of object of class PART, you need to check if there are some objects of that class. You can use "gpart show", or "geom part show", or "geom part list" to see if there are some objects. At the same time there can be some geom objects of class DISK, e.g. da0 and da1. Also in the same time there can be geom objects of type PART da0 and da1. But they are different objects. If geom object of type PART with name da0 doesn't exist. gpart(8) can't assume you mean gptid/c3ae7a7e-bc4c-11e3-ab8c-4437e6acfe08. It is different object with different name.
@Andrey I'm intimately familiar with geom and gpart. Please refer to the final section of my PR concerning suggested fix. As you say, gpart works on partitions only, so it is a mistake for it to assert that an object of the disk class does not exist. The problem is that the _partition_ specified on this disk is not a geom object, and the error message should reflect that.
(In reply to Mahmoud Al-Qudsi from comment #2) > @Andrey I'm intimately familiar with geom and gpart. Please refer to the > final section of my PR concerning suggested fix. As you say, gpart works on > partitions only, so it is a mistake for it to assert that an object of the > disk class does not exist. The problem is that the _partition_ specified on > this disk is not a geom object, and the error message should reflect that. No. There are no objects of type partitions. And gpart doesn't work with objects of class DISK. When you issue `gpart create -t gpt da0`, da0 - is geom provider, it is not an object of class PART. But when the command completes, there will be geom object of class PART with the same name. This object has some internal data, like how many partition it can have, which partitions it has, how these partitions are called, i.e. what name they have "p", or "s", or "a", or some other; and many other info. gpart(8) utility knows how obtain this information from *object of class PART*. When you use gpart(8) utility with geom objects of different classes, there are no such info. Since there are no object with name da0 and class PART, gpart(8) can not assume that the name of such object is da0p1, because it doesn't know what name should be used for partition with index 1.
I understand what you're saying now. While I have a geom disk object named da0, I do not have a geom part object with that name, and that's the object that `gpart` is reporting does not exist. I interpreted the error message in a global sense. How can this error be made friendlier? Here `gpart` is universally declaring there is no geom by that name, but technically it's that there is no geom _of this class_ by that name, as `geom disk list | grep 'Geom name'` does return `Geom name: da0`. (In this particular instance it's too bad geom names are not unique across classes, that would have cleared up a lot of confusion.)
I just realized that while gpart may not work on DISK objects, it *does* know about their existence, at the very least. `gpart create -s mbr aoneuh` returns an error while `gpart create -s mbr nvd0` (where `nvd0` is a valid DISK object and not (yet) the name of a valid PART object) will succeed. That means that when `gpart bootcode -b ... -p ... -i $N $DISK` is executed, gpart _could_ distinguish between $DISK not existing at all (which the current error message could be taken to assert universally) vs $DISK being a valid disk but not a valid PART object. My proposal is for the permutation of $N and $DISK to determine which of the following messages is displayed: * $DISK is not a valid disk * $DISK is not partitioned for use with gpart * $N is not a valid partition on $DISK (if $N is too big) (text is obviously just a first stab at clarifying the situation and can use refinement)
(In reply to Mahmoud Al-Qudsi from comment #5) > I just realized that while gpart may not work on DISK objects, it *does* > know about their existence, at the very least. `gpart create -s mbr aoneuh` > returns an error while `gpart create -s mbr nvd0` (where `nvd0` is a valid > DISK object and not (yet) the name of a valid PART object) will succeed. gpart(8) has several sub-commands that require different objects to work with. When you are creating PART object, it assumes that the name in argument is GEOM provider. Many geom classes have providers, not only the DISK class. > That means that when `gpart bootcode -b ... -p ... -i $N $DISK` is executed, > gpart _could_ distinguish between $DISK not existing at all (which the > current error message could be taken to assert universally) vs $DISK being a > valid disk but not a valid PART object. The "bootcode" command works with objects of class PART, since it requires some knowledge about partition table. The -b argument assumes that the bootcode should be written to the special area of partition table, that is specific for different partitioning schemes. The -p argument assumes that bootcode should be written to specified by -i partition, this means that PART object should exists to be able find the name of GEOM provider, that will be open like open("/dev/%s", provider_name). > My proposal is for the permutation of $N and $DISK to determine which of the > following messages is displayed: > > * $DISK is not a valid disk > * $DISK is not partitioned for use with gpart > * $N is not a valid partition on $DISK (if $N is too big) > > (text is obviously just a first stab at clarifying the situation and can use > refinement) As you may see in the SYNOPSIS of gpart(8) manual page, there is only one command, that accepts provider - it is "create", any other commands require geom object of class PART. So, I'm not sure your suggestion fits to this requirements.