summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/zfs/vdev_disk.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs/zfs/vdev_disk.c')
-rw-r--r--usr/src/uts/common/fs/zfs/vdev_disk.c40
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;
}