From owner-svn-src-all@FreeBSD.ORG Thu Sep 9 21:18:01 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 31AEA1065675; Thu, 9 Sep 2010 21:18:01 +0000 (UTC) (envelope-from pjd@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 20BEE8FC13; Thu, 9 Sep 2010 21:18:01 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o89LI1G2034340; Thu, 9 Sep 2010 21:18:01 GMT (envelope-from pjd@svn.freebsd.org) Received: (from pjd@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o89LI0an034338; Thu, 9 Sep 2010 21:18:00 GMT (envelope-from pjd@svn.freebsd.org) Message-Id: <201009092118.o89LI0an034338@svn.freebsd.org> From: Pawel Jakub Dawidek Date: Thu, 9 Sep 2010 21:18:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r212383 - head/sys/boot/zfs X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Sep 2010 21:18:01 -0000 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; }