diff --git a/sys/boot/i386/gptzfsboot/Makefile b/sys/boot/i386/gptzfsboot/Makefile index 20dca79..8998edc 100644 --- a/sys/boot/i386/gptzfsboot/Makefile +++ b/sys/boot/i386/gptzfsboot/Makefile @@ -59,7 +59,7 @@ CLEANFILES+= gptzfsboot.bin gptzfsboot.out zfsboot.o sio.o cons.o \ gptzfsboot.bin: gptzfsboot.out objcopy -S -O binary gptzfsboot.out ${.TARGET} -gptzfsboot.out: ${BTXCRT} zfsboot.o sio.o gpt.o drv.o cons.o util.o +gptzfsboot.out: ${BTXCRT} zfsboot.o sio.o gpt.o drv.o cons.o ${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND} zfsboot.o: ${.CURDIR}/../../zfs/zfsimpl.c diff --git a/sys/boot/i386/zfsboot/Makefile b/sys/boot/i386/zfsboot/Makefile index 5a23a3b..673c135 100644 --- a/sys/boot/i386/zfsboot/Makefile +++ b/sys/boot/i386/zfsboot/Makefile @@ -72,7 +72,7 @@ zfsboot.ldr: zfsboot.bin: zfsboot.out objcopy -S -O binary zfsboot.out ${.TARGET} -zfsboot.out: ${BTXCRT} zfsboot.o sio.o drv.o cons.o util.o +zfsboot.out: ${BTXCRT} zfsboot.o sio.o drv.o cons.o ${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND} SRCS= zfsboot.c diff --git a/sys/boot/zfs/zfsimpl.c b/sys/boot/zfs/zfsimpl.c index 2a59927..1931cac 100644 --- a/sys/boot/zfs/zfsimpl.c +++ b/sys/boot/zfs/zfsimpl.c @@ -787,7 +787,7 @@ pager_printf(const char *fmt, ...) #define STATUS_FORMAT " %s %s\n" static void -print_state(int indent, const char *name, vdev_state_t state) +print_state(int indent, const char *name, uint64_t guid, vdev_state_t state) { int i; char buf[512]; @@ -795,16 +795,15 @@ print_state(int indent, const char *name, vdev_state_t state) buf[0] = 0; for (i = 0; i < indent; i++) strcat(buf, " "); - strcat(buf, name); + sprintf(buf + indent, "%s %llu", name, guid); pager_printf(STATUS_FORMAT, buf, state_name(state)); - } static void vdev_status(vdev_t *vdev, int indent) { vdev_t *kid; - print_state(indent, vdev->v_name, vdev->v_state); + print_state(indent, vdev->v_name, vdev->v_guid, vdev->v_state); STAILQ_FOREACH(kid, &vdev->v_children, v_childlink) { vdev_status(kid, indent + 1); @@ -820,14 +819,7 @@ spa_status(spa_t *spa) int good_kids, bad_kids, degraded_kids; vdev_state_t state; - pager_printf(" pool: %s\n", spa->spa_name); - if (zfs_get_root(spa, &rootid) == 0 && - zfs_rlookup(spa, rootid, bootfs) == 0) { - if (bootfs[0] == '\0') - pager_printf("bootfs: %s\n", spa->spa_name); - else - pager_printf("bootfs: %s/%s\n", spa->spa_name, bootfs); - } + pager_printf(" pool: %s %llu\n", spa->spa_name, spa->spa_guid); pager_printf("config:\n\n"); pager_printf(STATUS_FORMAT, "NAME", "STATE"); @@ -849,10 +841,13 @@ spa_status(spa_t *spa) else if ((good_kids + degraded_kids) > 0) state = VDEV_STATE_DEGRADED; - print_state(0, spa->spa_name, state); + print_state(0, spa->spa_name, spa->spa_guid, state); STAILQ_FOREACH(vdev, &spa->spa_vdevs, v_childlink) { vdev_status(vdev, 1); } + if (spa->spa_vdev_count != (good_kids + degraded_kids + bad_kids)) + pager_printf("\n%d top level vdevs could be missing\n", + spa->spa_vdev_count - good_kids - degraded_kids - bad_kids); } static void @@ -883,6 +878,7 @@ vdev_probe(vdev_phys_read_t *read, void *read_priv, spa_t **spap) uint64_t guid; uint64_t pool_txg, pool_guid; uint64_t is_log; + uint64_t top_vdev_count; const char *pool_name; const unsigned char *vdevs; const unsigned char *features; @@ -967,6 +963,10 @@ vdev_probe(vdev_phys_read_t *read, void *read_priv, spa_t **spap) if (is_log) return (EIO); + top_vdev_count = 1; + (void) nvlist_find(nvlist, ZPOOL_CONFIG_VDEV_CHILDREN, DATA_TYPE_UINT64, + 0, &top_vdev_count); + /* * Create the pool if this is the first time we've seen it. */ @@ -977,6 +977,7 @@ vdev_probe(vdev_phys_read_t *read, void *read_priv, spa_t **spap) } if (pool_txg > spa->spa_txg) { spa->spa_txg = pool_txg; + spa->spa_vdev_count = top_vdev_count; is_newer = 1; } else is_newer = 0; @@ -1085,6 +1086,28 @@ ilog2(int n) return -1; } +static void +printf_blkptr_compact(const blkptr_t *bp) +{ + const dva_t *dva = bp->blk_dva; + int ndvas = BP_GET_NDVAS(bp); + int i; + + for (i = 0; i < ndvas; i++) + printf("%llu:%llx:%llx ", + (uint64_t)DVA_GET_VDEV(&dva[i]), + (uint64_t)DVA_GET_OFFSET(&dva[i]), + (uint64_t)DVA_GET_ASIZE(&dva[i])); + + printf("%llxL/%llxP F=%llu B=%llu/%llu prop=%llx\n", + (uint64_t)BP_GET_LSIZE(bp), + (uint64_t)BP_GET_PSIZE(bp), + (uint64_t)bp->blk_fill, + (uint64_t)bp->blk_birth, + (uint64_t)BP_PHYSICAL_BIRTH(bp), + (uint64_t)bp->blk_prop); +} + static int zio_read_gang(const spa_t *spa, const blkptr_t *bp, void *buf) { @@ -1132,7 +1155,7 @@ zio_read(const spa_t *spa, const blkptr_t *bp, void *buf) error = EIO; - for (i = 0; i < SPA_DVAS_PER_BP; i++) { + for (i = 0; i < BP_GET_NDVAS(bp); i++) { const dva_t *dva = &bp->blk_dva[i]; vdev_t *vdev; int vdevid; @@ -1177,8 +1200,10 @@ zio_read(const spa_t *spa, const blkptr_t *bp, void *buf) if (error == 0) break; } - if (error != 0) + if (error != 0) { printf("ZFS: i/o error - all block copies unavailable\n"); + printf_blkptr_compact(bp); + } return (error); } @@ -1922,6 +1947,9 @@ zfs_spa_init(spa_t *spa) if (zio_read(spa, &spa->spa_uberblock.ub_rootbp, &spa->spa_mos)) { printf("ZFS: can't read MOS of pool %s\n", spa->spa_name); + spa_all_status(); + printf("ub txg = %llx\n", spa->spa_uberblock.ub_txg); + printf("ub timestamp = %llx\n", spa->spa_uberblock.ub_timestamp); return (EIO); } if (spa->spa_mos.os_type != DMU_OST_META) { diff --git a/sys/cddl/boot/zfs/zfsimpl.h b/sys/cddl/boot/zfs/zfsimpl.h index 394a5e3..669e5bc 100644 --- a/sys/cddl/boot/zfs/zfsimpl.h +++ b/sys/cddl/boot/zfs/zfsimpl.h @@ -616,6 +616,7 @@ typedef enum { #define ZPOOL_CONFIG_IS_LOG "is_log" #define ZPOOL_CONFIG_TIMESTAMP "timestamp" /* not stored on disk */ #define ZPOOL_CONFIG_FEATURES_FOR_READ "features_for_read" +#define ZPOOL_CONFIG_VDEV_CHILDREN "vdev_children" /* * The persistent vdev state is stored as separate values rather than a single @@ -1341,5 +1342,6 @@ typedef struct spa { struct uberblock spa_uberblock; /* best uberblock so far */ vdev_list_t spa_vdevs; /* list of all toplevel vdevs */ objset_phys_t spa_mos; /* MOS for this pool */ + int spa_vdev_count; /* expected number of toplevel vdevs */ int spa_inited; /* initialized */ } spa_t;