Path: blob/main/cddl/usr.sbin/zfsd/vdev_iterator.cc
104148 views
/*-1* Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions, and the following disclaimer,9* without modification.10* 2. Redistributions in binary form must reproduce at minimum a disclaimer11* substantially similar to the "NO WARRANTY" disclaimer below12* ("Disclaimer") and any redistribution must be conditioned upon13* including a substantially similar Disclaimer requirement for further14* binary redistribution.15*16* NO WARRANTY17* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS18* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT19* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR20* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT21* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL22* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS23* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)24* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,25* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING26* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE27* POSSIBILITY OF SUCH DAMAGES.28*29* Authors: Justin T. Gibbs (Spectra Logic Corporation)30*/3132/**33* \file vdev_iterator.cc34*35* Implementation of the VdevIterator class.36*/37#include <sys/cdefs.h>38#include <sys/byteorder.h>39#include <sys/fs/zfs.h>4041#include <stdint.h>42#include <syslog.h>4344#include <libzfs.h>4546#include <list>47#include <string>4849#include <devdctl/exception.h>50#include <devdctl/guid.h>5152#include "vdev.h"53#include "vdev_iterator.h"54#include "zfsd_exception.h"5556/*============================ Namespace Control =============================*/57using DevdCtl::Guid;5859/*=========================== Class Implementations ==========================*/60/*------------------------------- VdevIterator -------------------------------*/61VdevIterator::VdevIterator(zpool_handle_t *pool)62: m_poolConfig(zpool_get_config(pool, NULL))63{64Reset();65}6667VdevIterator::VdevIterator(nvlist_t *poolConfig)68: m_poolConfig(poolConfig)69{70Reset();71}7273void74VdevIterator::Reset()75{76nvlist_t *rootVdev;77nvlist **cache_child;78nvlist **spare_child;79int result;80uint_t cache_children;81uint_t spare_children;8283result = nvlist_lookup_nvlist(m_poolConfig,84ZPOOL_CONFIG_VDEV_TREE,85&rootVdev);86if (result != 0)87throw ZfsdException(m_poolConfig, "Unable to extract "88"ZPOOL_CONFIG_VDEV_TREE from pool.");89m_vdevQueue.assign(1, rootVdev);90result = nvlist_lookup_nvlist_array(rootVdev,91ZPOOL_CONFIG_L2CACHE,92&cache_child,93&cache_children);94if (result == 0)95for (uint_t c = 0; c < cache_children; c++)96m_vdevQueue.push_back(cache_child[c]);97result = nvlist_lookup_nvlist_array(rootVdev,98ZPOOL_CONFIG_SPARES,99&spare_child,100&spare_children);101if (result == 0)102for (uint_t c = 0; c < spare_children; c++)103m_vdevQueue.push_back(spare_child[c]);104}105106nvlist_t *107VdevIterator::Next()108{109nvlist_t *vdevConfig;110111for (vdevConfig = NULL; !m_vdevQueue.empty();) {112nvlist_t **vdevChildren;113int result;114u_int numChildren;115116vdevConfig = m_vdevQueue.front();117m_vdevQueue.pop_front();118119/* Expand non-leaf vdevs. */120result = nvlist_lookup_nvlist_array(vdevConfig,121ZPOOL_CONFIG_CHILDREN,122&vdevChildren, &numChildren);123if (result != 0) {124/* leaf vdev */125break;126}127128/*129* Insert children at the head of the queue to effect a130* depth first traversal of the tree.131*/132m_vdevQueue.insert(m_vdevQueue.begin(), vdevChildren,133vdevChildren + numChildren);134}135136return (vdevConfig);137}138139void140VdevIterator::Each(VdevCallback_t *callBack, void *callBackArg)141{142nvlist_t *vdevConfig;143144Reset();145while ((vdevConfig = Next()) != NULL) {146Vdev vdev(m_poolConfig, vdevConfig);147148if (callBack(vdev, callBackArg))149break;150}151}152153nvlist_t *154VdevIterator::Find(Guid vdevGUID)155{156nvlist_t *vdevConfig;157158Reset();159while ((vdevConfig = Next()) != NULL) {160Vdev vdev(m_poolConfig, vdevConfig);161162if (vdev.GUID() == vdevGUID)163return (vdevConfig);164}165return (NULL);166}167168169