diff options
| author | Robert Noland <rnoland@FreeBSD.org> | 2009-11-21 15:02:35 +0000 |
|---|---|---|
| committer | Robert Noland <rnoland@FreeBSD.org> | 2009-11-21 15:02:35 +0000 |
| commit | 262b2ce07603d5390335b5e647577f3cad3a3cc3 (patch) | |
| tree | ddd4a3276fce6d9401a0d0426e6ba82c78fda9ed /sys/boot | |
| parent | 4cb9493f3f10be6e549db0f74e3685fba43cab29 (diff) | |
Notes
Diffstat (limited to 'sys/boot')
| -rw-r--r-- | sys/boot/i386/zfsboot/zfsboot.c | 23 | ||||
| -rw-r--r-- | sys/boot/zfs/zfs.c | 4 | ||||
| -rw-r--r-- | sys/boot/zfs/zfsimpl.c | 71 |
3 files changed, 75 insertions, 23 deletions
diff --git a/sys/boot/i386/zfsboot/zfsboot.c b/sys/boot/i386/zfsboot/zfsboot.c index a654393f1840..c0dedd7cc865 100644 --- a/sys/boot/i386/zfsboot/zfsboot.c +++ b/sys/boot/i386/zfsboot/zfsboot.c @@ -474,6 +474,7 @@ probe_drive(struct dsk *dsk, spa_t **spap) 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 **spap) */ 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; diff --git a/sys/boot/zfs/zfs.c b/sys/boot/zfs/zfs.c index 9784ef97d504..52df7738ff35 100644 --- a/sys/boot/zfs/zfs.c +++ b/sys/boot/zfs/zfs.c @@ -100,7 +100,7 @@ zfs_open(const char *upath, struct open_file *f) 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) { diff --git a/sys/boot/zfs/zfsimpl.c b/sys/boot/zfs/zfsimpl.c index ff567a462ef3..497fd7c94be2 100644 --- a/sys/boot/zfs/zfsimpl.c +++ b/sys/boot/zfs/zfsimpl.c @@ -53,6 +53,8 @@ static char *zfs_temp_buf, *zfs_temp_end, *zfs_temp_ptr; #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, void *buf) 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 objnum, objset_phys_t *objset) 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 *objset) */ 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, dnode_phys_t *dnode) 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); } |
