diff options
Diffstat (limited to 'usr/src/uts/common/fs/zfs/vdev_disk.c')
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev_disk.c | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/usr/src/uts/common/fs/zfs/vdev_disk.c b/usr/src/uts/common/fs/zfs/vdev_disk.c index 1cdc458974..cd5e80d769 100644 --- a/usr/src/uts/common/fs/zfs/vdev_disk.c +++ b/usr/src/uts/common/fs/zfs/vdev_disk.c @@ -301,6 +301,7 @@ vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, int otyp; boolean_t validate_devid = B_FALSE; uint64_t capacity = 0, blksz = 0, pbsize; + const char *rdpath = vdev_disk_preroot_force_path(); /* * We must have a pathname, and it must be absolute. @@ -328,7 +329,8 @@ vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, /* * Allow bypassing the devid. */ - if (vd->vdev_devid != NULL && vdev_disk_bypass_devid) { + if (vd->vdev_devid != NULL && + (vdev_disk_bypass_devid || rdpath != NULL)) { vdev_dbgmsg(vd, "vdev_disk_open, devid %s bypassed", vd->vdev_devid); spa_strfree(vd->vdev_devid); @@ -364,6 +366,17 @@ vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, error = EINVAL; /* presume failure */ + if (rdpath != NULL) { + /* + * We have been asked to open only a specific root device, and + * to fail otherwise. + */ + error = ldi_open_by_name((char *)rdpath, spa_mode(spa), kcred, + &dvd->vd_lh, zfs_li); + validate_devid = B_TRUE; + goto rootdisk_only; + } + if (vd->vdev_path != NULL) { if (vd->vdev_wholedisk == -1ULL) { size_t len = strlen(vd->vdev_path) + 3; @@ -501,6 +514,7 @@ vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, } } +rootdisk_only: if (error != 0) { vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; vdev_dbgmsg(vd, "vdev_disk_open: failed to open [error=%d]", @@ -1158,6 +1172,7 @@ vdev_disk_read_rootlabel(const char *devpath, const char *devid, struct veb { list_t veb_ents; boolean_t veb_scanned; + char *veb_force_path; }; struct veb_ent { @@ -1269,8 +1284,22 @@ vdev_disk_preroot_lookup(uint64_t pool_guid, uint64_t vdev_guid) return (path); } +const char * +vdev_disk_preroot_force_path(void) +{ + const char *force_path = NULL; + + mutex_enter(&veb_lock); + if (veb != NULL) { + force_path = veb->veb_force_path; + } + mutex_exit(&veb_lock); + + return (force_path); +} + void -vdev_disk_preroot_init(void) +vdev_disk_preroot_init(const char *force_path) { mutex_init(&veb_lock, NULL, MUTEX_DEFAULT, NULL); @@ -1279,6 +1308,9 @@ vdev_disk_preroot_init(void) list_create(&veb->veb_ents, sizeof (struct veb_ent), offsetof(struct veb_ent, vebe_link)); veb->veb_scanned = B_FALSE; + if (force_path != NULL) { + veb->veb_force_path = spa_strdup(force_path); + } } void @@ -1295,6 +1327,10 @@ vdev_disk_preroot_fini(void) kmem_free(vebe, sizeof (*vebe)); } + if (veb->veb_force_path != NULL) { + spa_strfree(veb->veb_force_path); + } + kmem_free(veb, sizeof (*veb)); veb = NULL; } |