Пример #1
0
static void
zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
{
    dev_data_t *dp = data;
    char *path;
    uint_t c, children;
    nvlist_t **child;

    /*
     * First iterate over any children.
     */
    if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_CHILDREN,
                                   &child, &children) == 0) {
        for (c = 0; c < children; c++)
            zfs_iter_vdev(zhp, child[c], data);
        return;
    }

    /* once a vdev was matched and processed there is nothing left to do */
    if (dp->dd_found)
        return;

    /*
     * 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) {
            return;
        }
        zed_log_msg(LOG_INFO, "  zfs_iter_vdev: matched on %llu", guid);
        dp->dd_found = B_TRUE;

    } else if (dp->dd_compare != NULL) {
        /*
         * NOTE: On Linux there is an event for partition, so unlike
         * illumos, substring matching is not required to accomodate
         * the partition suffix. An exact match will be present in
         * the dp->dd_compare value.
         */
        if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 ||
                strcmp(dp->dd_compare, path) != 0) {
            return;
        }
        zed_log_msg(LOG_INFO, "  zfs_iter_vdev: matched %s on %s",
                    dp->dd_prop, path);
        dp->dd_found = B_TRUE;

        /* pass the new devid for use by replacing code */
        if (dp->dd_islabeled && dp->dd_new_devid != NULL) {
            (void) nvlist_add_string(nvl, "new_devid",
                                     dp->dd_new_devid);
        }
    }

    (dp->dd_func)(zhp, nvl, dp->dd_islabeled);
}
Пример #2
0
static void
zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
{
	dev_data_t *dp = data;
	char *path;
	uint_t c, children;
	nvlist_t **child;
	size_t len;
	uint64_t guid;

	/*
	 * First iterate over any children.
	 */
	if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_CHILDREN,
	    &child, &children) == 0) {
		for (c = 0; c < children; c++)
			zfs_iter_vdev(zhp, child[c], data);
		return;
	}

	if (dp->dd_vdev_guid != 0) {
		if (nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID,
		    &guid) != 0 || guid != dp->dd_vdev_guid)
			return;
	} else if (dp->dd_compare != NULL) {
		len = strlen(dp->dd_compare);

		if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 ||
		    strncmp(dp->dd_compare, path, len) != 0)
			return;

		/*
		 * Normally, we want to have an exact match for the comparison
		 * string.  However, we allow substring matches in the following
		 * cases:
		 *
		 * 	<path>:		This is a devpath, and the target is one
		 * 			of its children.
		 *
		 * 	<path/>		This is a devid for a whole disk, and
		 * 			the target is one of its children.
		 */
		if (path[len] != '\0' && path[len] != ':' &&
		    path[len - 1] != '/')
			return;
	}

	(dp->dd_func)(zhp, nvl, dp->dd_isdisk);
}
Пример #3
0
static int
zfs_iter_pool(zpool_handle_t *zhp, void *data)
{
    nvlist_t *config, *nvl;
    dev_data_t *dp = data;
    uint64_t pool_guid;
    unavailpool_t *pool;

    zed_log_msg(LOG_INFO, "zfs_iter_pool: evaluating vdevs on %s (by %s)",
                zpool_get_name(zhp), dp->dd_vdev_guid ? "GUID" : dp->dd_prop);

    /*
     * For each vdev in this pool, look for a match to apply dd_func
     */
    if ((config = zpool_get_config(zhp, NULL)) != NULL) {
        if (dp->dd_pool_guid == 0 ||
                (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
                                      &pool_guid) == 0 && pool_guid == dp->dd_pool_guid)) {
            (void) nvlist_lookup_nvlist(config,
                                        ZPOOL_CONFIG_VDEV_TREE, &nvl);
            zfs_iter_vdev(zhp, nvl, data);
        }
    }

    /*
     * if this pool was originally unavailable,
     * then enable its datasets asynchronously
     */
    if (g_enumeration_done)  {
        for (pool = list_head(&g_pool_list); pool != NULL;
                pool = list_next(&g_pool_list, pool)) {

            if (pool->uap_enable_tid != 0)
                continue;	/* entry already processed */
            if (strcmp(zpool_get_name(zhp),
                       zpool_get_name(pool->uap_zhp)))
                continue;
            if (zfs_toplevel_state(zhp) >= VDEV_STATE_DEGRADED) {
                /* send to a background thread; keep on list */
                (void) pthread_create(&pool->uap_enable_tid,
                                      NULL, zfs_enable_ds, pool);
                break;
            }
        }
    }

    zpool_close(zhp);
    return (dp->dd_found);	/* cease iteration after a match */
}
Пример #4
0
/*
 * This function handles the ESC_ZFS_config_sync event. It will iterate over
 * the pools vdevs and to update the FRU property.
 */
int
zfs_deliver_sync(nvlist_t *nvl)
{
	dev_data_t dd = { 0 };
	char *pname;
	zpool_handle_t *zhp;
	nvlist_t *config, *vdev;

	if (nvlist_lookup_string(nvl, "pool_name", &pname) != 0) {
		syseventd_print(9, "zfs_deliver_sync: no pool name\n");
		return (-1);
	}

	/*
	 * If this event was triggered by a pool export or destroy we cannot
	 * open the pool. This is not an error, just return 0 as we don't care
	 * about these events.
	 */
	zhp = zpool_open_canfail(g_zfshdl, pname);
	if (zhp == NULL)
		return (0);

	config = zpool_get_config(zhp, NULL);
	if (config == NULL) {
		syseventd_print(9, "zfs_deliver_sync: "
		    "failed to get pool config for %s\n", pname);
		zpool_close(zhp);
		return (-1);
	}

	if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &vdev) != 0) {
		syseventd_print(0, "zfs_deliver_sync: "
		    "failed to get vdev tree for %s\n", pname);
		zpool_close(zhp);
		return (-1);
	}

	libzfs_fru_refresh(g_zfshdl);

	dd.dd_func = zfs_sync_vdev_fru;
	zfs_iter_vdev(zhp, vdev, &dd);

	zpool_close(zhp);
	return (0);
}
Пример #5
0
static int
zfs_iter_pool(zpool_handle_t *zhp, void *data)
{
	nvlist_t *config, *nvl;
	dev_data_t *dp = data;
	uint64_t pool_guid;
	unavailpool_t *pool;

	if ((config = zpool_get_config(zhp, NULL)) != NULL) {
		if (dp->dd_pool_guid == 0 ||
		    (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
		    &pool_guid) == 0 && pool_guid == dp->dd_pool_guid)) {
			(void) nvlist_lookup_nvlist(config,
			    ZPOOL_CONFIG_VDEV_TREE, &nvl);
			zfs_iter_vdev(zhp, nvl, data);
		}
	}
	if (g_enumeration_done)  {
		for (pool = list_head(&g_pool_list); pool != NULL;
		    pool = list_next(&g_pool_list, pool)) {

			if (strcmp(zpool_get_name(zhp),
			    zpool_get_name(pool->uap_zhp)))
				continue;
			if (zfs_toplevel_state(zhp) >= VDEV_STATE_DEGRADED) {
				list_remove(&g_pool_list, pool);
				(void) tpool_dispatch(g_tpool, zfs_enable_ds,
				    pool);
				break;
			}
		}
	}

	zpool_close(zhp);
	return (0);
}