Skip to content

Commit

Permalink
The way ZFS searches for its vdevs is the following: first it looks for
Browse files Browse the repository at this point in the history
a vdev that has the same name as the one stored in metadata and that has
all VDEV labels in place. If it cannot find a GEOM provider with the given
name and all VDEV labels it will scan all GEOM providers for the best match
(the most VDEV labels available), but here the name is ignored.

In case the ZFS pool is created, eg. using GPT partition label:

	# zpool create tank /dev/gpt/tank

everything works, and on every import ZFS will pick /dev/gpt/tank and
not /dev/da0p4.

The problem occurs when da0p4 is extended and ZFS is unable to find all
VDEV labels in /dev/gpt/tank anymore (the VDEV labels stored at the end
of the partition are now somewhere else). In this case it will scan all
GEOM providers and will pick the first one with the best match, ie. da0p4.

Fix this problem by checking the VDEV/provider name even if we get the same
match. If the name is the same as the one we have in pool's metadata, prefer
this GEOM provider.

Reported by:	oshogbo, Michal Mroz <m.mroz@fudosecurity.com>
Tested by:	Michal Mroz <m.mroz@fudosecurity.com>
Obtained from:	Fudo Security
  • Loading branch information
Pawel Jakub Dawidek authored and Pawel Jakub Dawidek committed Feb 19, 2019
1 parent 827e6ec commit 11c8759
Showing 1 changed file with 6 additions and 0 deletions.
6 changes: 6 additions & 0 deletions sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
Expand Up @@ -692,10 +692,12 @@ vdev_geom_attach_by_guids(vdev_t *vd)
struct g_geom *gp;
struct g_provider *pp, *best_pp;
struct g_consumer *cp;
const char *vdpath;
enum match match, best_match;

g_topology_assert();

vdpath = vd->vdev_path + sizeof("/dev/") - 1;
cp = NULL;
best_pp = NULL;
best_match = NO_MATCH;
Expand All @@ -710,6 +712,10 @@ vdev_geom_attach_by_guids(vdev_t *vd)
if (match > best_match) {
best_match = match;
best_pp = pp;
} else if (match == best_match) {
if (strcmp(pp->name, vdpath) == 0) {
best_pp = pp;
}
}
if (match == FULL_MATCH)
goto out;
Expand Down

0 comments on commit 11c8759

Please sign in to comment.