diff options
author | gw25295 <none@none> | 2008-04-11 18:36:28 -0700 |
---|---|---|
committer | gw25295 <none@none> | 2008-04-11 18:36:28 -0700 |
commit | e7cbe64f7a72dae5cb44f100db60ca88f3313c65 (patch) | |
tree | 778467a6522111f338e4644cc2cb895dcecacee4 /usr/src/uts/common/fs/zfs/vdev_disk.c | |
parent | f635d46a9872dc5a02bbbd736f2bf18685c2c221 (diff) | |
download | illumos-gate-e7cbe64f7a72dae5cb44f100db60ca88f3313c65.tar.gz |
PSARC 2006/370 ZFS Boot Support
5008936 ZFS and/or zvol should support dumps
5070124 dumpadm -d /dev/... does not enforce block device requirement for savecore
6521468 ZFS Boot support Phase 2
6553503 bfu can't find 'rootdev' from /etc/vfstab on a zfs root filesystem
6574993 zfs_mountroot() may need to call clkset() to set the boot_time kstat
6633197 zvol should not permit newfs or createpool while it's in use by swap or dump
6661127 zfs_name_valid() does not support ZFS_TYPE_POOL
6684121 The changes to smf scripts for supporting canmount=noauto will cause a boot failure.
--HG--
rename : usr/src/psm/stand/bootblks/zfs/common/debug-zfs.fth => deleted_files/usr/src/psm/stand/bootblks/zfs/common/debug-zfs.fth
rename : usr/src/psm/stand/bootblks/zfs/common/big-zfs.fth => usr/src/psm/stand/bootblks/zfs/common/fs-zfs.fth
Diffstat (limited to 'usr/src/uts/common/fs/zfs/vdev_disk.c')
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev_disk.c | 107 |
1 files changed, 93 insertions, 14 deletions
diff --git a/usr/src/uts/common/fs/zfs/vdev_disk.c b/usr/src/uts/common/fs/zfs/vdev_disk.c index 933ed3e2bf..b586e23f71 100644 --- a/usr/src/uts/common/fs/zfs/vdev_disk.c +++ b/usr/src/uts/common/fs/zfs/vdev_disk.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -27,6 +27,7 @@ #include <sys/zfs_context.h> #include <sys/spa.h> +#include <sys/refcount.h> #include <sys/vdev_disk.h> #include <sys/vdev_impl.h> #include <sys/fs/zfs.h> @@ -266,29 +267,45 @@ vdev_disk_close(vdev_t *vd) vd->vdev_tsd = NULL; } +int +vdev_disk_physio(ldi_handle_t vd_lh, caddr_t data, size_t size, + uint64_t offset, int flags) +{ + buf_t *bp; + int error = 0; + + if (vd_lh == NULL) + return (EINVAL); + + ASSERT(flags & B_READ || flags & B_WRITE); + + bp = getrbuf(KM_SLEEP); + bp->b_flags = flags | B_BUSY | B_NOCACHE | B_FAILFAST; + bp->b_bcount = size; + bp->b_un.b_addr = (void *)data; + bp->b_lblkno = lbtodb(offset); + bp->b_bufsize = size; + + error = ldi_strategy(vd_lh, bp); + ASSERT(error == 0); + if ((error = biowait(bp)) == 0 && bp->b_resid != 0) + error = EIO; + freerbuf(bp); + + return (error); +} + static int vdev_disk_probe_io(vdev_t *vd, caddr_t data, size_t size, uint64_t offset, int flags) { - buf_t buf; int error = 0; vdev_disk_t *dvd = vd->vdev_tsd; if (vd == NULL || dvd == NULL || dvd->vd_lh == NULL) return (EINVAL); - ASSERT(flags & B_READ || flags & B_WRITE); - - bioinit(&buf); - buf.b_flags = flags | B_BUSY | B_NOCACHE | B_FAILFAST; - buf.b_bcount = size; - buf.b_un.b_addr = (void *)data; - buf.b_lblkno = lbtodb(offset); - buf.b_bufsize = size; - - error = ldi_strategy(dvd->vd_lh, &buf); - ASSERT(error == 0); - error = biowait(&buf); + error = vdev_disk_physio(dvd->vd_lh, data, size, offset, flags); if (zio_injection_enabled && error == 0) error = zio_handle_device_injection(vd, EIO); @@ -558,3 +575,65 @@ vdev_ops_t vdev_disk_ops = { VDEV_TYPE_DISK, /* name of this vdev type */ B_TRUE /* leaf vdev */ }; + +/* + * Given the root disk device pathname, read the label from the device, + * and construct a configuration nvlist. + */ +nvlist_t * +vdev_disk_read_rootlabel(char *devpath) +{ + nvlist_t *config = NULL; + ldi_handle_t vd_lh; + vdev_label_t *label; + uint64_t s, size; + int l; + + /* + * Read the device label and build the nvlist. + */ + if (ldi_open_by_name(devpath, FREAD, kcred, &vd_lh, zfs_li)) + return (NULL); + + if (ldi_get_size(vd_lh, &s)) + return (NULL); + + size = P2ALIGN_TYPED(s, sizeof (vdev_label_t), uint64_t); + label = kmem_alloc(sizeof (vdev_label_t), KM_SLEEP); + + for (l = 0; l < VDEV_LABELS; l++) { + uint64_t offset, state, txg = 0; + + /* read vdev label */ + offset = vdev_label_offset(size, l, 0); + if (vdev_disk_physio(vd_lh, (caddr_t)label, + VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE + + VDEV_PHYS_SIZE, offset, B_READ) != 0) + continue; + + if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist, + sizeof (label->vl_vdev_phys.vp_nvlist), &config, 0) != 0) { + config = NULL; + continue; + } + + if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, + &state) != 0 || state >= POOL_STATE_DESTROYED) { + nvlist_free(config); + config = NULL; + continue; + } + + if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG, + &txg) != 0 || txg == 0) { + nvlist_free(config); + config = NULL; + continue; + } + + break; + } + + kmem_free(label, sizeof (vdev_label_t)); + return (config); +} |