aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/zed
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/zed')
-rw-r--r--cmd/zed/agents/zfs_mod.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/cmd/zed/agents/zfs_mod.c b/cmd/zed/agents/zfs_mod.c
index 0271fffe4..4fc8ceb9f 100644
--- a/cmd/zed/agents/zfs_mod.c
+++ b/cmd/zed/agents/zfs_mod.c
@@ -535,6 +535,7 @@ typedef struct dev_data {
boolean_t dd_islabeled;
uint64_t dd_pool_guid;
uint64_t dd_vdev_guid;
+ uint64_t dd_new_vdev_guid;
const char *dd_new_devid;
} dev_data_t;
@@ -545,6 +546,7 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
char *path = NULL;
uint_t c, children;
nvlist_t **child;
+ uint64_t guid = 0;
/*
* First iterate over any children.
@@ -572,17 +574,14 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
/* once a vdev was matched and processed there is nothing left to do */
if (dp->dd_found)
return;
+ (void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &guid);
/*
* Match by GUID if available otherwise fallback to devid or physical
*/
if (dp->dd_vdev_guid != 0) {
- uint64_t guid;
-
- if (nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID,
- &guid) != 0 || guid != dp->dd_vdev_guid) {
+ if (guid != dp->dd_vdev_guid)
return;
- }
zed_log_msg(LOG_INFO, " zfs_iter_vdev: matched on %llu", guid);
dp->dd_found = B_TRUE;
@@ -592,6 +591,12 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
* illumos, substring matching is not required to accommodate
* the partition suffix. An exact match will be present in
* the dp->dd_compare value.
+ * If the attached disk already contains a vdev GUID, it means
+ * the disk is not clean. In such a scenario, the physical path
+ * would be a match that makes the disk faulted when trying to
+ * online it. So, we would only want to proceed if either GUID
+ * matches with the last attached disk or the disk is in clean
+ * state.
*/
if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 ||
strcmp(dp->dd_compare, path) != 0) {
@@ -599,6 +604,12 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
__func__, dp->dd_compare, path);
return;
}
+ if (dp->dd_new_vdev_guid != 0 && dp->dd_new_vdev_guid != guid) {
+ zed_log_msg(LOG_INFO, " %s: no match (GUID:%llu"
+ " != vdev GUID:%llu)", __func__,
+ dp->dd_new_vdev_guid, guid);
+ return;
+ }
zed_log_msg(LOG_INFO, " zfs_iter_vdev: matched %s on %s",
dp->dd_prop, path);
@@ -680,7 +691,7 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
*/
static boolean_t
devphys_iter(const char *physical, const char *devid, zfs_process_func_t func,
- boolean_t is_slice)
+ boolean_t is_slice, uint64_t new_vdev_guid)
{
dev_data_t data = { 0 };
@@ -690,6 +701,7 @@ devphys_iter(const char *physical, const char *devid, zfs_process_func_t func,
data.dd_found = B_FALSE;
data.dd_islabeled = is_slice;
data.dd_new_devid = devid; /* used by auto replace code */
+ data.dd_new_vdev_guid = new_vdev_guid;
(void) zpool_iter(g_zfshdl, zfs_iter_pool, &data);
@@ -858,7 +870,7 @@ zfs_deliver_add(nvlist_t *nvl)
if (devid_iter(devid, zfs_process_add, is_slice))
return (0);
if (devpath != NULL && devphys_iter(devpath, devid, zfs_process_add,
- is_slice))
+ is_slice, vdev_guid))
return (0);
if (vdev_guid != 0)
(void) guid_iter(pool_guid, vdev_guid, devid, zfs_process_add,