6621355 panic in vdev_disk_io_start when trying to write to a faulted device
authorgw25295
Mon, 29 Oct 2007 17:24:59 -0700
changeset 5369 27c1235ef9a4
parent 5368 0557ad79abbf
child 5370 eb153afce98e
6621355 panic in vdev_disk_io_start when trying to write to a faulted device 6622732 Assertion failed: !(zio->io_flags & ZIO_FLAG_WRITE_RETRY), file ../../../uts/com mon/fs/zfs/zio.c 6623221 CIFS breaks ZFS root
usr/src/grub/grub-0.95/stage2/zfs-include/zfs_znode.h
usr/src/uts/common/fs/zfs/vdev.c
usr/src/uts/common/fs/zfs/vdev_disk.c
usr/src/uts/common/fs/zfs/vdev_file.c
usr/src/uts/common/fs/zfs/zio.c
--- a/usr/src/grub/grub-0.95/stage2/zfs-include/zfs_znode.h	Mon Oct 29 17:19:25 2007 -0700
+++ b/usr/src/grub/grub-0.95/stage2/zfs-include/zfs_znode.h	Mon Oct 29 17:24:59 2007 -0700
@@ -30,7 +30,7 @@
 #define	ZFS_ROOT_OBJ		"ROOT"
 #define	ZPL_VERSION_STR		"VERSION"
 
-#define	ZPL_VERSION		2ULL
+#define	ZPL_VERSION		3ULL
 
 #define	ZFS_DIRENT_OBJ(de) BF64_GET(de, 0, 48)
 
--- a/usr/src/uts/common/fs/zfs/vdev.c	Mon Oct 29 17:19:25 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/vdev.c	Mon Oct 29 17:24:59 2007 -0700
@@ -1778,8 +1778,7 @@
 int
 vdev_writeable(vdev_t *vd)
 {
-	return (vd->vdev_ops->vdev_op_leaf ?
-	    !vd->vdev_is_failing : !vdev_is_dead(vd));
+	return (!vdev_is_dead(vd) && !vd->vdev_is_failing);
 }
 
 int
--- a/usr/src/uts/common/fs/zfs/vdev_disk.c	Mon Oct 29 17:19:25 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/vdev_disk.c	Mon Oct 29 17:24:59 2007 -0700
@@ -296,6 +296,11 @@
 	return (error);
 }
 
+/*
+ * Determine if the underlying device is accessible by reading and writing
+ * to a known location. We must be able to do this during syncing context
+ * and thus we cannot set the vdev state directly.
+ */
 static int
 vdev_disk_probe(vdev_t *vd)
 {
@@ -341,11 +346,8 @@
 		retries++;
 
 		error = vdev_disk_open_common(nvd);
-		if (error) {
-			vdev_set_state(vd, B_TRUE, VDEV_STATE_CANT_OPEN,
-			    nvd->vdev_stat.vs_aux);
+		if (error)
 			break;
-		}
 	}
 
 	if (!error) {
@@ -523,7 +525,7 @@
 	 * If the device returned EIO, then attempt a DKIOCSTATE ioctl to see if
 	 * the device has been removed.  If this is the case, then we trigger an
 	 * asynchronous removal of the device. Otherwise, probe the device and
-	 * make sure it's still functional.
+	 * make sure it's still accessible.
 	 */
 	if (zio->io_error == EIO) {
 		vdev_t *vd = zio->io_vd;
--- a/usr/src/uts/common/fs/zfs/vdev_file.c	Mon Oct 29 17:19:25 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/vdev_file.c	Mon Oct 29 17:24:59 2007 -0700
@@ -149,6 +149,11 @@
 	return (0);
 }
 
+/*
+ * Determine if the underlying device is accessible by reading and writing
+ * to a known location. We must be able to do this during syncing context
+ * and thus we cannot set the vdev state directly.
+ */
 static int
 vdev_file_probe(vdev_t *vd)
 {
@@ -184,13 +189,11 @@
 		nvd = kmem_zalloc(sizeof (vdev_t), KM_SLEEP);
 		if (vd->vdev_path)
 			nvd->vdev_path = spa_strdup(vd->vdev_path);
+		retries++;
+
 		error = vdev_file_open_common(nvd);
-		if (error) {
-			vdev_set_state(vd, B_TRUE, VDEV_STATE_CANT_OPEN,
-			    nvd->vdev_stat.vs_aux);
+		if (error)
 			break;
-		}
-		retries++;
 	}
 
 	if ((spa_mode & FWRITE) && !error) {
@@ -288,8 +291,8 @@
 		zio->io_error = zio_handle_device_injection(zio->io_vd, EIO);
 
 	/*
-	 * If this device is truely gone, then attempt to remove it
-	 * from the configuration.
+	 * If an error has been encountered then attempt to probe the device
+	 * to determine if it's still accessible.
 	 */
 	if (zio->io_error == EIO) {
 		vdev_t *vd = zio->io_vd;
--- a/usr/src/uts/common/fs/zfs/zio.c	Mon Oct 29 17:19:25 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/zio.c	Mon Oct 29 17:24:59 2007 -0700
@@ -1137,13 +1137,14 @@
 		}
 
 		/*
-		 * If we are an allocating I/O then we retry on another
-		 * vdev unless the pool is out of space.  We handle this
-		 * condition based on the spa's failmode property.
+		 * If we are an allocating I/O or have been told to retry
+		 * then attempt to reissue the I/O on another vdev unless
+		 * the pool is out of space.  We handle this condition
+		 * based on the spa's failmode property.
 		 */
 		if (zio_write_retry && zio->io_error != ENOSPC &&
-		    IO_IS_ALLOCATING(zio) &&
-		    zio->io_flags & ZIO_FLAG_WRITE_RETRY) {
+		    (IO_IS_ALLOCATING(zio) ||
+		    zio->io_flags & ZIO_FLAG_WRITE_RETRY)) {
 			zio_vdev_retry_io(zio);
 			return;
 		}