From owner-svn-src-all@FreeBSD.ORG Fri Oct 23 18:44:53 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id AB3AD106566B; Fri, 23 Oct 2009 18:44:53 +0000 (UTC) (envelope-from rnoland@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 98B148FC1A; Fri, 23 Oct 2009 18:44:53 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n9NIirIq069178; Fri, 23 Oct 2009 18:44:53 GMT (envelope-from rnoland@svn.freebsd.org) Received: (from rnoland@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n9NIir6v069173; Fri, 23 Oct 2009 18:44:53 GMT (envelope-from rnoland@svn.freebsd.org) Message-Id: <200910231844.n9NIir6v069173@svn.freebsd.org> From: Robert Noland Date: Fri, 23 Oct 2009 18:44:53 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r198420 - in head/sys: boot/i386/zfsboot boot/zfs cddl/boot/zfs X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Oct 2009 18:44:53 -0000 Author: rnoland Date: Fri Oct 23 18:44:53 2009 New Revision: 198420 URL: http://svn.freebsd.org/changeset/base/198420 Log: Correct some issues with zfs boot. - Teach it to read gang blocks. (essentially untested) If you see "ZFS: gang block detected!", please let me know, so we can either remove the printf if it works, or fix it if it doesn't. - If multiple partitions exist on a disk, probe them all. We also need to reset dsk->start to 0 to read the right sector here. - With GPT, we can have 128 partitions. - If the bootfs property has ever been set on a pool it seems that it never goes away. zpool won't allow you to add to the pool with the bootfs property set. However, if you clear the property back to default we end up getting 0 for the object number and read a bogus block pointer and fail to boot. - Fix some error printfs. The printf in the loader is only capable of c,s and u formats. - Teach printf how to display %llu Reviewed by: dfr, jhb MFC after: 2 weeks Modified: head/sys/boot/i386/zfsboot/zfsboot.c head/sys/boot/zfs/zfs.c head/sys/boot/zfs/zfsimpl.c head/sys/cddl/boot/zfs/zfsimpl.h Modified: head/sys/boot/i386/zfsboot/zfsboot.c ============================================================================== --- head/sys/boot/i386/zfsboot/zfsboot.c Fri Oct 23 18:41:00 2009 (r198419) +++ head/sys/boot/i386/zfsboot/zfsboot.c Fri Oct 23 18:44:53 2009 (r198420) @@ -474,6 +474,7 @@ probe_drive(struct dsk *dsk, spa_t **spa slba = hdr.hdr_lba_table; elba = slba + hdr.hdr_entries / entries_per_sec; while (slba < elba) { + dsk->start = 0; if (drvread(dsk, sec, slba, 1)) return; for (part = 0; part < entries_per_sec; part++) { @@ -494,7 +495,6 @@ probe_drive(struct dsk *dsk, spa_t **spa */ dsk = copy_dsk(dsk); } - break; } } slba++; @@ -857,12 +857,13 @@ static void printf(const char *fmt,...) { va_list ap; - char buf[10]; + char buf[20]; char *s; - unsigned u; + unsigned long long u; int c; int minus; int prec; + int l; int len; int pad; @@ -871,6 +872,7 @@ printf(const char *fmt,...) if (c == '%') { minus = 0; prec = 0; + l = 0; nextfmt: c = *fmt++; switch (c) { @@ -892,6 +894,9 @@ printf(const char *fmt,...) case 'c': putchar(va_arg(ap, int)); continue; + case 'l': + l++; + goto nextfmt; case 's': s = va_arg(ap, char *); if (prec) { @@ -914,7 +919,17 @@ printf(const char *fmt,...) } continue; case 'u': - u = va_arg(ap, unsigned); + switch (l) { + case 2: + u = va_arg(ap, unsigned long long); + break; + case 1: + u = va_arg(ap, unsigned long); + break; + default: + u = va_arg(ap, unsigned); + break; + } s = buf; do *s++ = '0' + u % 10U; Modified: head/sys/boot/zfs/zfs.c ============================================================================== --- head/sys/boot/zfs/zfs.c Fri Oct 23 18:41:00 2009 (r198419) +++ head/sys/boot/zfs/zfs.c Fri Oct 23 18:44:53 2009 (r198420) @@ -100,7 +100,7 @@ zfs_open(const char *upath, struct open_ f->f_fsdata = (void *)fp; if (spa->spa_root_objset.os_type != DMU_OST_ZFS) { - printf("Unexpected object set type %lld\n", + printf("Unexpected object set type %llu\n", spa->spa_root_objset.os_type); rc = EIO; goto out; @@ -413,7 +413,7 @@ zfs_dev_init(void) if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0)) close(fd); - for (slice = 1; slice <= 4; slice++) { + for (slice = 1; slice <= 128; slice++) { sprintf(devname, "disk%dp%d:", unit, slice); fd = open(devname, O_RDONLY); if (fd == -1) { Modified: head/sys/boot/zfs/zfsimpl.c ============================================================================== --- head/sys/boot/zfs/zfsimpl.c Fri Oct 23 18:41:00 2009 (r198419) +++ head/sys/boot/zfs/zfsimpl.c Fri Oct 23 18:44:53 2009 (r198420) @@ -53,6 +53,8 @@ static char *zfs_temp_buf, *zfs_temp_end #define TEMP_SIZE (1*SPA_MAXBLOCKSIZE) +static int zio_read(spa_t *spa, const blkptr_t *bp, void *buf); + static void zfs_init(void) { @@ -897,6 +899,33 @@ ilog2(int n) } static int +zio_read_gang(spa_t *spa, const blkptr_t *bp, const dva_t *dva, void *buf) +{ + zio_gbh_phys_t zio_gb; + vdev_t *vdev; + int vdevid; + off_t offset; + int i; + + vdevid = DVA_GET_VDEV(dva); + offset = DVA_GET_OFFSET(dva); + STAILQ_FOREACH(vdev, &spa->spa_vdevs, v_childlink) + if (vdev->v_id == vdevid) + break; + if (!vdev || !vdev->v_read) + return (EIO); + if (vdev->v_read(vdev, bp, &zio_gb, offset, SPA_GANGBLOCKSIZE)) + return (EIO); + + for (i = 0; i < SPA_GBH_NBLKPTRS; i++) { + if (zio_read(spa, &zio_gb.zg_blkptr[i], buf)) + return (EIO); + } + + return (0); +} + +static int zio_read(spa_t *spa, const blkptr_t *bp, void *buf) { int cpfunc = BP_GET_COMPRESS(bp); @@ -920,20 +949,27 @@ zio_read(spa_t *spa, const blkptr_t *bp, if (!dva->dva_word[0] && !dva->dva_word[1]) continue; - vdevid = DVA_GET_VDEV(dva); - offset = DVA_GET_OFFSET(dva); - STAILQ_FOREACH(vdev, &spa->spa_vdevs, v_childlink) - if (vdev->v_id == vdevid) - break; - if (!vdev || !vdev->v_read) - continue; - if (vdev->v_read(vdev, bp, pbuf, offset, psize)) - continue; + if (DVA_GET_GANG(dva)) { + printf("ZFS: gang block detected!\n"); + if (zio_read_gang(spa, bp, dva, buf)) + return (EIO); + } else { + vdevid = DVA_GET_VDEV(dva); + offset = DVA_GET_OFFSET(dva); + STAILQ_FOREACH(vdev, &spa->spa_vdevs, v_childlink) + if (vdev->v_id == vdevid) + break; + if (!vdev || !vdev->v_read) { + continue; + } + if (vdev->v_read(vdev, bp, pbuf, offset, psize)) + continue; - if (cpfunc != ZIO_COMPRESS_OFF) { - if (zio_decompress_data(cpfunc, pbuf, psize, - buf, lsize)) - return (EIO); + if (cpfunc != ZIO_COMPRESS_OFF) { + if (zio_decompress_data(cpfunc, pbuf, psize, + buf, lsize)) + return (EIO); + } } return (0); @@ -1331,13 +1367,13 @@ zfs_mount_dataset(spa_t *spa, uint64_t o dsl_dataset_phys_t *ds; if (objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset)) { - printf("ZFS: can't find dataset %lld\n", objnum); + printf("ZFS: can't find dataset %llu\n", objnum); return (EIO); } ds = (dsl_dataset_phys_t *) &dataset.dn_bonus; if (zio_read(spa, &ds->ds_bp, objset)) { - printf("ZFS: can't read object set for dataset %lld\n", objnum); + printf("ZFS: can't read object set for dataset %llu\n", objnum); return (EIO); } @@ -1367,7 +1403,8 @@ zfs_mount_root(spa_t *spa, objset_phys_t */ if (zap_lookup(spa, &dir, DMU_POOL_PROPS, &props) == 0 && objset_get_dnode(spa, &spa->spa_mos, props, &propdir) == 0 - && zap_lookup(spa, &propdir, "bootfs", &bootfs) == 0) + && zap_lookup(spa, &propdir, "bootfs", &bootfs) == 0 + && bootfs != 0) return zfs_mount_dataset(spa, bootfs, objset); /* @@ -1425,7 +1462,7 @@ zfs_lookup(spa_t *spa, const char *upath int symlinks_followed = 0; if (spa->spa_root_objset.os_type != DMU_OST_ZFS) { - printf("ZFS: unexpected object set type %lld\n", + printf("ZFS: unexpected object set type %llu\n", spa->spa_root_objset.os_type); return (EIO); } Modified: head/sys/cddl/boot/zfs/zfsimpl.h ============================================================================== --- head/sys/cddl/boot/zfs/zfsimpl.h Fri Oct 23 18:41:00 2009 (r198419) +++ head/sys/cddl/boot/zfs/zfsimpl.h Fri Oct 23 18:44:53 2009 (r198420) @@ -374,6 +374,24 @@ typedef struct vdev_label { #define VDEV_LABEL_END_SIZE (2 * sizeof (vdev_label_t)) #define VDEV_LABELS 4 +/* + * Gang block headers are self-checksumming and contain an array + * of block pointers. + */ +#define SPA_GANGBLOCKSIZE SPA_MINBLOCKSIZE +#define SPA_GBH_NBLKPTRS ((SPA_GANGBLOCKSIZE - \ + sizeof (zio_block_tail_t)) / sizeof (blkptr_t)) +#define SPA_GBH_FILLER ((SPA_GANGBLOCKSIZE - \ + sizeof (zio_block_tail_t) - \ + (SPA_GBH_NBLKPTRS * sizeof (blkptr_t))) /\ + sizeof (uint64_t)) + +typedef struct zio_gbh { + blkptr_t zg_blkptr[SPA_GBH_NBLKPTRS]; + uint64_t zg_filler[SPA_GBH_FILLER]; + zio_block_tail_t zg_tail; +} zio_gbh_phys_t; + enum zio_checksum { ZIO_CHECKSUM_INHERIT = 0, ZIO_CHECKSUM_ON,