Author: pjd
Date: Mon Oct 18 09:26:39 2010
New Revision: 214014
URL: http://svn.freebsd.org/changeset/base/214014

Log:
  MFC r212382,r212383,r212384,r212387:
  
  r212382:
  
  Remove duplicated code.
  
  r212383:
  
  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.
  
  r212384:
  
  Ignore log vdevs.
  
  r212387:
  
  Remove empty lines committed by accident.

Modified:
  stable/8/sys/boot/zfs/zfsimpl.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/boot/zfs/zfsimpl.c
==============================================================================
--- stable/8/sys/boot/zfs/zfsimpl.c     Mon Oct 18 08:54:33 2010        
(r214013)
+++ stable/8/sys/boot/zfs/zfsimpl.c     Mon Oct 18 09:26:39 2010        
(r214014)
@@ -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)
@@ -430,12 +451,13 @@ vdev_init_from_nvlist(const unsigned cha
 
        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 +467,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 +478,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);
 
@@ -483,7 +509,16 @@ vdev_init_from_nvlist(const unsigned cha
                                vdev->v_name = strdup(type);
                        }
                }
+       } else {
+               is_new = 0;
+       }
 
+       if (is_new || is_newer) {
+               /*
+                * This is either new vdev or we've already seen this vdev,
+                * but from an older vdev label, so let's refresh its state
+                * from the newer label.
+                */
                if (is_offline)
                        vdev->v_state = VDEV_STATE_OFFLINE;
                else if (is_removed)
@@ -492,28 +527,10 @@ 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;
-       } else {
-               is_new = 0;
-
-               if (is_newer) {
-                       /*
-                        * We've already seen this vdev, but from an older
-                        * vdev label, so let's refresh its state from the
-                        * newer label.
-                        */
-                       if (is_offline)
-                               vdev->v_state = VDEV_STATE_OFFLINE;
-                       else if (is_removed)
-                               vdev->v_state = VDEV_STATE_REMOVED;
-                       else if (is_faulted)
-                               vdev->v_state = VDEV_STATE_FAULTED;
-                       else if (is_degraded)
-                               vdev->v_state = VDEV_STATE_DEGRADED;
-                       else
-                               vdev->v_state = VDEV_STATE_HEALTHY;
-               }
        }
 
        rc = nvlist_find(nvlist, ZPOOL_CONFIG_CHILDREN,
@@ -749,6 +766,7 @@ vdev_probe(vdev_phys_read_t *read, void 
        uint64_t val;
        uint64_t guid;
        uint64_t pool_txg, pool_guid;
+       uint64_t is_log;
        const char *pool_name;
        const unsigned char *vdevs;
        int i, rc, is_newer;
@@ -825,6 +843,12 @@ vdev_probe(vdev_phys_read_t *read, void 
                return (EIO);
        }
 
+       is_log = 0;
+       (void) nvlist_find(nvlist, ZPOOL_CONFIG_IS_LOG, DATA_TYPE_UINT64, 0,
+           &is_log);
+       if (is_log)
+               return (EIO);
+
        /*
         * Create the pool if this is the first time we've seen it.
         */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to