Date: Thu, 15 Oct 2009 14:03:50 -0500 From: Robert Noland <rnoland@FreeBSD.org> To: Radek =?iso-8859-2?Q?Val=E1=B9ek?= <valin@buchlovice.org> Cc: freebsd-fs@freebsd.org, freebsd-current@freebsd.org Subject: Re: GPT boot with ZFS RAIDZ "ZFS: i/o error - all block copies unavailable" Message-ID: <1255633430.2175.12.camel@balrog.2hip.net> In-Reply-To: <4AD710D6.70404@buchlovice.org> References: <4AD710D6.70404@buchlovice.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--=-a2tiU1GGu1eRIpNGphrs Content-Type: text/plain; charset="iso-8859-2" Content-Transfer-Encoding: 8bit On Thu, 2009-10-15 at 14:08 +0200, Radek Valášek wrote: > Hi, > > I want to ask if there is something new in adding support to > gptzfsboot/zfsboot for reading gang-blocks? Ok, I can't figure out any way to test this... beyond the fact that it builds and doesn't break my currently working setup. Can you give this a try? It should still report if it finds gang blocks, but hopefully now will read them as well. robert. > From Sun's docs: > > Gang blocks > > When there is not enough contiguous space to write a complete block, the ZIO > pipeline will break the I/O up into smaller 'gang blocks' which can later be > assembled transparently to appear as complete blocks. > > Everything works fine for me, until I rewrite kernel/world after system > upgrade to latest one (releng_8). After this am I no longer able to boot > from zfs raidz1 pool with following messages: > > >/ ZFS: i/o error - all block copies unavailable > />/ ZFS: can't read MOS > />/ ZFS: unexpected object set type lld > />/ ZFS: unexpected object set type lld > />/ > />/ FreeBSD/i386 boot > />/ Default: z:/boot/kernel/kernel > />/ boot: > />/ ZFS: unexpected object set type lld > />/ > />/ FreeBSD/i386 boot > />/ Default: tank:/boot/kernel/kernel > />/ boot: > // > /I presume it's the same issue as talked in june-2009 current mailing > list > http://lists.freebsd.org/pipermail/freebsd-current/2009-June/008589.html > > Any success in that matter? > > Thnx for answer. > > vaLin > _______________________________________________ > freebsd-current@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-current > To unsubscribe, send any mail to "freebsd-current-unsubscribe@freebsd.org" -- Robert Noland <rnoland@FreeBSD.org> FreeBSD --=-a2tiU1GGu1eRIpNGphrs Content-Disposition: attachment; filename="zfs-gang-block.patch" Content-Type: text/x-patch; name="zfs-gang-block.patch"; charset="us-ascii" Content-Transfer-Encoding: 7bit diff --git a/sys/boot/zfs/zfsimpl.c b/sys/boot/zfs/zfsimpl.c index ff567a4..6a18b44 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,26 @@ 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); diff --git a/sys/cddl/boot/zfs/zfsimpl.h b/sys/cddl/boot/zfs/zfsimpl.h index a0b7b72..688bb5c 100644 --- a/sys/cddl/boot/zfs/zfsimpl.h +++ b/sys/cddl/boot/zfs/zfsimpl.h @@ -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, --=-a2tiU1GGu1eRIpNGphrs--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1255633430.2175.12.camel>