Index: sys/boot/efi/boot1/zfs_module.c =================================================================== --- sys/boot/efi/boot1/zfs_module.c +++ sys/boot/efi/boot1/zfs_module.c @@ -68,6 +68,7 @@ { spa_t *spa; dev_info_t *tdev; + uint64_t size; EFI_STATUS status; /* ZFS consumes the dev on success so we need a copy. */ @@ -79,7 +80,8 @@ } memcpy(tdev, dev, sizeof(*dev)); - if (vdev_probe(vdev_read, tdev, &spa) != 0) { + size = (tdev->dev->Media->LastBlock + 1) * tdev->dev->Media->BlockSize; + if (vdev_probe(vdev_read, tdev, size, &spa) != 0) { (void)bs->FreePool(tdev); return (EFI_UNSUPPORTED); } Index: sys/boot/i386/zfsboot/zfsboot.c =================================================================== --- sys/boot/i386/zfsboot/zfsboot.c +++ sys/boot/i386/zfsboot/zfsboot.c @@ -481,13 +481,15 @@ #endif struct dos_partition *dp; + uint64_t size; char *sec; unsigned i; /* * If we find a vdev on the whole disk, stop here. */ - if (vdev_probe(vdev_read, dsk, NULL) == 0) + size = drvsize(dsk) * DEV_BSIZE; /* XXX 512b sector size assumed */ + if (vdev_probe(vdev_read, dsk, size, NULL) == 0) return; #ifdef LOADER_GELI_SUPPORT @@ -503,7 +505,7 @@ } if (geli_taste(vdev_read, dsk, elba) == 0) { if (geli_passphrase(&gelipw, dsk->unit, ':', 0, dsk) == 0) { - if (vdev_probe(vdev_read, dsk, NULL) == 0) { + if (vdev_probe(vdev_read, dsk, size, NULL) == 0) { return; } } @@ -549,7 +551,8 @@ dsk->start = ent->ent_lba_start; dsk->slice = part + 1; dsk->part = 255; - if (vdev_probe(vdev_read, dsk, NULL) == 0) { + size = (ent->ent_lba_end - ent->ent_lba_start + 1) * DEV_BSIZE; + if (vdev_probe(vdev_read, dsk, size, NULL) == 0) { /* * This slice had a vdev. We need a new dsk * structure now since the vdev now owns this one. @@ -563,7 +566,7 @@ /* * This slice has GELI, check it for ZFS. */ - if (vdev_probe(vdev_read, dsk, NULL) == 0) { + if (vdev_probe(vdev_read, dsk, size, NULL) == 0) { /* * This slice had a vdev. We need a new dsk * structure now since the vdev now owns this one. @@ -591,7 +594,8 @@ continue; dsk->start = dp[i].dp_start; dsk->slice = i + 1; - if (vdev_probe(vdev_read, dsk, NULL) == 0) { + size = dp->dp_size * DEV_BSIZE; + if (vdev_probe(vdev_read, dsk, size, NULL) == 0) { dsk = copy_dsk(dsk); } #ifdef LOADER_GELI_SUPPORT @@ -601,7 +605,7 @@ /* * This slice has GELI, check it for ZFS. */ - if (vdev_probe(vdev_read, dsk, NULL) == 0) { + if (vdev_probe(vdev_read, dsk, size, NULL) == 0) { /* * This slice had a vdev. We need a new dsk * structure now since the vdev now owns this one. Index: sys/boot/zfs/zfs.c =================================================================== --- sys/boot/zfs/zfs.c +++ sys/boot/zfs/zfs.c @@ -427,12 +427,12 @@ } static int -zfs_probe(int fd, uint64_t *pool_guid) +zfs_probe(int fd, uint64_t size, uint64_t *pool_guid) { spa_t *spa; int ret; - ret = vdev_probe(vdev_read, (void *)(uintptr_t)fd, &spa); + ret = vdev_probe(vdev_read, (void *)(uintptr_t)fd, size, &spa); if (ret == 0 && pool_guid != NULL) *pool_guid = spa->spa_guid; return (ret); @@ -459,7 +459,8 @@ pa.fd = open(devname, O_RDONLY); if (pa.fd == -1) return (0); - ret = zfs_probe(pa.fd, ppa->pool_guid); + ret = zfs_probe(pa.fd, (part->end - part->start + 1) * DEV_BSIZE, + ppa->pool_guid); if (ret == 0) return (0); /* Do we have BSD label here? */ @@ -490,7 +491,8 @@ if (pa.fd == -1) return (ENXIO); /* Probe the whole disk */ - ret = zfs_probe(pa.fd, pool_guid); + ioctl(pa.fd, DIOCGMEDIASIZE, &mediasz); + ret = zfs_probe(pa.fd, mediasz, pool_guid); if (ret == 0) return (0); /* Probe each partition */ Index: sys/boot/zfs/zfsimpl.c =================================================================== --- sys/boot/zfs/zfsimpl.c +++ sys/boot/zfs/zfsimpl.c @@ -879,8 +879,17 @@ } } +static uint64_t +vdev_label_offset(uint64_t psize, int l, uint64_t offset) +{ + + return (offset + l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ? + 0 : psize - VDEV_LABELS * sizeof (vdev_label_t))); +} + static int -vdev_probe(vdev_phys_read_t *read, void *read_priv, spa_t **spap) +vdev_probe_label(vdev_phys_read_t *read, void *read_priv, uint64_t psize, int l, + spa_t **spap) { vdev_t vtmp; vdev_phys_t *vdev_label = (vdev_phys_t *) zap_scratch; @@ -907,7 +916,8 @@ memset(&vtmp, 0, sizeof(vtmp)); vtmp.v_phys_read = read; vtmp.v_read_priv = read_priv; - off = offsetof(vdev_label_t, vl_vdev_phys); + off = vdev_label_offset(psize , l, + offsetof(vdev_label_t, vl_vdev_phys)); BP_ZERO(&bp); BP_SET_LSIZE(&bp, sizeof(vdev_phys_t)); BP_SET_PSIZE(&bp, sizeof(vdev_phys_t)); @@ -1086,6 +1096,24 @@ } static int +vdev_probe(vdev_phys_read_t *read, void *read_priv, uint64_t msize, + spa_t **spap) +{ + uint64_t psize; + int err, err2; + int l; + + psize = P2ALIGN(msize, (uint64_t)sizeof(vdev_label_t)); + err = EIO; + for (l = 0; l < VDEV_LABELS; l++) { + err2 = vdev_probe_label(read, read_priv, psize, l, spap); + if (err != 0) + err = err2; + } + return (err); +} + +static int ilog2(int n) { int v; Index: tools/tools/zfsboottest/Makefile =================================================================== --- tools/tools/zfsboottest/Makefile +++ tools/tools/zfsboottest/Makefile @@ -17,6 +17,7 @@ -fdiagnostics-show-option \ -W -Wextra -Wno-sign-compare -Wno-unused-parameter CFLAGS+=-m32 +LIBADD+= geom LIBADD+= md .if ${MACHINE_CPUARCH} == "amd64" Index: tools/tools/zfsboottest/zfsboottest.c =================================================================== --- tools/tools/zfsboottest/zfsboottest.c +++ tools/tools/zfsboottest/zfsboottest.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -97,8 +98,10 @@ #endif spa_t *spa; off_t off; + off_t size; ssize_t n; int i, failures, *fd; + int g_handle; zfs_init(); if (argc == 1) { @@ -130,7 +133,14 @@ warn("open(%s) failed", argv[i]); continue; } - if (vdev_probe(vdev_read, &fd[i - 1], NULL) != 0) { + g_handle = g_open(argv[i], 0); + if (g_handle < 0) { + warn("g_open(%s) failed", argv[i]); + continue; + } + size = g_mediasize(g_handle); + g_close(g_handle); + if (vdev_probe(vdev_read, &fd[i - 1], size, NULL) != 0) { warnx("vdev_probe(%s) failed", argv[i]); close(fd[i - 1]); }