From fb02ae025247e3b662600e5a9c1b4c33ecab7d72 Mon Sep 17 00:00:00 2001 From: George Wilson Date: Sun, 24 Mar 2013 15:59:22 -0800 Subject: [PATCH] 3639 zpool.cache should skip over readonly pools 3640 want automatic devid updates Reviewed by: Eric Schrock Reviewed by: Adam Leventhal Reviewed by: Basil Crow Approved by: Gordon Ross --- usr/src/uts/common/fs/zfs/spa_config.c | 10 ++++++++- usr/src/uts/common/fs/zfs/vdev_disk.c | 28 ++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/usr/src/uts/common/fs/zfs/spa_config.c b/usr/src/uts/common/fs/zfs/spa_config.c index 366545035d6c..b113ce9e0c6d 100644 --- a/usr/src/uts/common/fs/zfs/spa_config.c +++ b/usr/src/uts/common/fs/zfs/spa_config.c @@ -222,7 +222,15 @@ spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent) */ nvl = NULL; while ((spa = spa_next(spa)) != NULL) { - if (spa == target && removing) + /* + * Skip over our own pool if we're about to remove + * ourselves from the spa namespace or any pool that + * is readonly. Since we cannot guarantee that a + * readonly pool would successfully import upon reboot, + * we don't allow them to be written to the cache file. + */ + if ((spa == target && removing) || + !spa_writeable(spa)) continue; mutex_enter(&spa->spa_props_lock); diff --git a/usr/src/uts/common/fs/zfs/vdev_disk.c b/usr/src/uts/common/fs/zfs/vdev_disk.c index aa5b67d54459..c526363dae9d 100644 --- a/usr/src/uts/common/fs/zfs/vdev_disk.c +++ b/usr/src/uts/common/fs/zfs/vdev_disk.c @@ -139,6 +139,8 @@ vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, int error; dev_t dev; int otyp; + boolean_t validate_devid = B_FALSE; + ddi_devid_t devid; /* * We must have a pathname, and it must be absolute. @@ -187,7 +189,6 @@ vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, error = EINVAL; /* presume failure */ if (vd->vdev_path != NULL) { - ddi_devid_t devid; if (vd->vdev_wholedisk == -1ULL) { size_t len = strlen(vd->vdev_path) + 3; @@ -236,9 +237,10 @@ vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, * If we were unable to open by path, or the devid check fails, open by * devid instead. */ - if (error != 0 && vd->vdev_devid != NULL) + if (error != 0 && vd->vdev_devid != NULL) { error = ldi_open_by_devid(dvd->vd_devid, dvd->vd_minor, spa_mode(spa), kcred, &dvd->vd_lh, zfs_li); + } /* * If all else fails, then try opening by physical path (if available) @@ -247,6 +249,9 @@ vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, * level vdev validation will prevent us from opening the wrong device. */ if (error) { + if (vd->vdev_devid != NULL) + validate_devid = B_TRUE; + if (vd->vdev_physpath != NULL && (dev = ddi_pathname_to_dev_t(vd->vdev_physpath)) != NODEV) error = ldi_open_by_dev(&dev, OTYP_BLK, spa_mode(spa), @@ -267,6 +272,25 @@ vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, return (error); } + /* + * Now that the device has been successfully opened, update the devid + * if necessary. + */ + if (validate_devid && spa_writeable(spa) && + ldi_get_devid(dvd->vd_lh, &devid) == 0) { + if (ddi_devid_compare(devid, dvd->vd_devid) != 0) { + char *vd_devid; + + vd_devid = ddi_devid_str_encode(devid, dvd->vd_minor); + zfs_dbgmsg("vdev %s: update devid from %s, " + "to %s", vd->vdev_path, vd->vdev_devid, vd_devid); + spa_strfree(vd->vdev_devid); + vd->vdev_devid = spa_strdup(vd_devid); + ddi_devid_str_free(vd_devid); + } + ddi_devid_free(devid); + } + /* * Once a device is opened, verify that the physical device path (if * available) is up to date.