svn commit: r212383 - head/sys/boot/zfs

Pawel Jakub Dawidek pjd at FreeBSD.org
Thu Sep 9 21:18:01 UTC 2010


Author: pjd
Date: Thu Sep  9 21:18:00 2010
New Revision: 212383
URL: http://svn.freebsd.org/changeset/base/212383

Log:
  Allow to boot from a pool within which replacing is in progress.
  Before the change it wasn't possible and the following error was printed:
  
  	ZFS: can only boot from disk, mirror or raidz vdevs
  
  Now if the original vdev (the one we are replacing) is still present we will
  read from it, but if it is not present we won't read from the new vdev, as it
  might not have enough valid data yet.
  
  MFC after:	2 weeks

Modified:
  head/sys/boot/zfs/zfsimpl.c

Modified: head/sys/boot/zfs/zfsimpl.c
==============================================================================
--- head/sys/boot/zfs/zfsimpl.c	Thu Sep  9 21:15:16 2010	(r212382)
+++ head/sys/boot/zfs/zfsimpl.c	Thu Sep  9 21:18:00 2010	(r212383)
@@ -376,6 +376,27 @@ vdev_mirror_read(vdev_t *vdev, const blk
 	return (rc);
 }
 
+static int
+vdev_replacing_read(vdev_t *vdev, const blkptr_t *bp, void *buf,
+    off_t offset, size_t bytes)
+{
+	vdev_t *kid;
+
+	/*
+	 * Here we should have two kids:
+	 * First one which is the one we are replacing and we can trust
+	 * only this one to have valid data, but it might not be present.
+	 * Second one is that one we are replacing with. It is most likely
+	 * healthy, but we can't trust it has needed data, so we won't use it.
+	 */
+	kid = STAILQ_FIRST(&vdev->v_children);
+	if (kid == NULL)
+		return (EIO);
+	if (kid->v_state != VDEV_STATE_HEALTHY)
+		return (EIO);
+	return (kid->v_read(kid, bp, buf, offset, bytes));
+}
+
 static vdev_t *
 vdev_find(uint64_t guid)
 {
@@ -416,7 +437,7 @@ vdev_init_from_nvlist(const unsigned cha
 	vdev_t *vdev, *kid;
 	const unsigned char *kids;
 	int nkids, i, is_new;
-	uint64_t is_offline, is_faulted, is_degraded, is_removed;
+	uint64_t is_offline, is_faulted, is_degraded, is_removed, isnt_present;
 
 	if (nvlist_find(nvlist, ZPOOL_CONFIG_GUID,
 			DATA_TYPE_UINT64, 0, &guid)
@@ -428,14 +449,17 @@ vdev_init_from_nvlist(const unsigned cha
 		return (ENOENT);
 	}
 
+
+
 	if (strcmp(type, VDEV_TYPE_MIRROR)
 	    && strcmp(type, VDEV_TYPE_DISK)
-	    && strcmp(type, VDEV_TYPE_RAIDZ)) {
+	    && strcmp(type, VDEV_TYPE_RAIDZ)
+	    && strcmp(type, VDEV_TYPE_REPLACING)) {
 		printf("ZFS: can only boot from disk, mirror or raidz vdevs\n");
 		return (EIO);
 	}
 
-	is_offline = is_removed = is_faulted = is_degraded = 0;
+	is_offline = is_removed = is_faulted = is_degraded = isnt_present = 0;
 
 	nvlist_find(nvlist, ZPOOL_CONFIG_OFFLINE, DATA_TYPE_UINT64, 0,
 			&is_offline);
@@ -445,6 +469,8 @@ vdev_init_from_nvlist(const unsigned cha
 			&is_faulted);
 	nvlist_find(nvlist, ZPOOL_CONFIG_DEGRADED, DATA_TYPE_UINT64, 0,
 			&is_degraded);
+	nvlist_find(nvlist, ZPOOL_CONFIG_NOT_PRESENT, DATA_TYPE_UINT64, 0,
+			&isnt_present);
 
 	vdev = vdev_find(guid);
 	if (!vdev) {
@@ -454,6 +480,8 @@ vdev_init_from_nvlist(const unsigned cha
 			vdev = vdev_create(guid, vdev_mirror_read);
 		else if (!strcmp(type, VDEV_TYPE_RAIDZ))
 			vdev = vdev_create(guid, vdev_raidz_read);
+		else if (!strcmp(type, VDEV_TYPE_REPLACING))
+			vdev = vdev_create(guid, vdev_replacing_read);
 		else
 			vdev = vdev_create(guid, vdev_disk_read);
 
@@ -506,6 +534,8 @@ vdev_init_from_nvlist(const unsigned cha
 			vdev->v_state = VDEV_STATE_FAULTED;
 		else if (is_degraded)
 			vdev->v_state = VDEV_STATE_DEGRADED;
+		else if (isnt_present)
+			vdev->v_state = VDEV_STATE_CANT_OPEN;
 		else
 			vdev->v_state = VDEV_STATE_HEALTHY;
 	}


More information about the svn-src-all mailing list