Skip site navigation (1)Skip section navigation (2)
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>