The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/module/os/freebsd/zfs/spa_os.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or https://opensource.org/licenses/CDDL-1.0.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 
   22 /*
   23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
   24  * Copyright (c) 2011 by Delphix. All rights reserved.
   25  * Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
   26  */
   27 
   28 
   29 #include <sys/zfs_context.h>
   30 #include <sys/fm/fs/zfs.h>
   31 #include <sys/spa_impl.h>
   32 #include <sys/zio.h>
   33 #include <sys/zio_checksum.h>
   34 #include <sys/dmu.h>
   35 #include <sys/dmu_tx.h>
   36 #include <sys/zap.h>
   37 #include <sys/zil.h>
   38 #include <sys/ddt.h>
   39 #include <sys/vdev_impl.h>
   40 #include <sys/vdev_os.h>
   41 #include <sys/vdev_removal.h>
   42 #include <sys/vdev_indirect_mapping.h>
   43 #include <sys/vdev_indirect_births.h>
   44 #include <sys/metaslab.h>
   45 #include <sys/metaslab_impl.h>
   46 #include <sys/uberblock_impl.h>
   47 #include <sys/txg.h>
   48 #include <sys/avl.h>
   49 #include <sys/bpobj.h>
   50 #include <sys/dmu_traverse.h>
   51 #include <sys/dmu_objset.h>
   52 #include <sys/unique.h>
   53 #include <sys/dsl_pool.h>
   54 #include <sys/dsl_dataset.h>
   55 #include <sys/dsl_dir.h>
   56 #include <sys/dsl_prop.h>
   57 #include <sys/dsl_synctask.h>
   58 #include <sys/fs/zfs.h>
   59 #include <sys/arc.h>
   60 #include <sys/callb.h>
   61 #include <sys/zfs_ioctl.h>
   62 #include <sys/dsl_scan.h>
   63 #include <sys/dmu_send.h>
   64 #include <sys/dsl_destroy.h>
   65 #include <sys/dsl_userhold.h>
   66 #include <sys/zfeature.h>
   67 #include <sys/zvol.h>
   68 #include <sys/abd.h>
   69 #include <sys/callb.h>
   70 #include <sys/zone.h>
   71 
   72 #include "zfs_prop.h"
   73 #include "zfs_comutil.h"
   74 
   75 static nvlist_t *
   76 spa_generate_rootconf(const char *name)
   77 {
   78         nvlist_t **configs, **tops;
   79         nvlist_t *config;
   80         nvlist_t *best_cfg, *nvtop, *nvroot;
   81         uint64_t *holes;
   82         uint64_t best_txg;
   83         uint64_t nchildren;
   84         uint64_t pgid;
   85         uint64_t count;
   86         uint64_t i;
   87         uint_t   nholes;
   88 
   89         if (vdev_geom_read_pool_label(name, &configs, &count) != 0)
   90                 return (NULL);
   91 
   92         ASSERT3U(count, !=, 0);
   93         best_txg = 0;
   94         for (i = 0; i < count; i++) {
   95                 uint64_t txg;
   96 
   97                 if (configs[i] == NULL)
   98                         continue;
   99                 txg = fnvlist_lookup_uint64(configs[i], ZPOOL_CONFIG_POOL_TXG);
  100                 if (txg > best_txg) {
  101                         best_txg = txg;
  102                         best_cfg = configs[i];
  103                 }
  104         }
  105 
  106         nchildren = 1;
  107         nvlist_lookup_uint64(best_cfg, ZPOOL_CONFIG_VDEV_CHILDREN, &nchildren);
  108         holes = NULL;
  109         nvlist_lookup_uint64_array(best_cfg, ZPOOL_CONFIG_HOLE_ARRAY,
  110             &holes, &nholes);
  111 
  112         tops = kmem_zalloc(nchildren * sizeof (void *), KM_SLEEP);
  113         for (i = 0; i < nchildren; i++) {
  114                 if (i >= count)
  115                         break;
  116                 if (configs[i] == NULL)
  117                         continue;
  118                 nvtop = fnvlist_lookup_nvlist(configs[i],
  119                     ZPOOL_CONFIG_VDEV_TREE);
  120                 tops[i] = fnvlist_dup(nvtop);
  121         }
  122         for (i = 0; holes != NULL && i < nholes; i++) {
  123                 if (i >= nchildren)
  124                         continue;
  125                 if (tops[holes[i]] != NULL)
  126                         continue;
  127                 tops[holes[i]] = fnvlist_alloc();
  128                 fnvlist_add_string(tops[holes[i]], ZPOOL_CONFIG_TYPE,
  129                     VDEV_TYPE_HOLE);
  130                 fnvlist_add_uint64(tops[holes[i]], ZPOOL_CONFIG_ID, holes[i]);
  131                 fnvlist_add_uint64(tops[holes[i]], ZPOOL_CONFIG_GUID, 0);
  132         }
  133         for (i = 0; i < nchildren; i++) {
  134                 if (tops[i] != NULL)
  135                         continue;
  136                 tops[i] = fnvlist_alloc();
  137                 fnvlist_add_string(tops[i], ZPOOL_CONFIG_TYPE,
  138                     VDEV_TYPE_MISSING);
  139                 fnvlist_add_uint64(tops[i], ZPOOL_CONFIG_ID, i);
  140                 fnvlist_add_uint64(tops[i], ZPOOL_CONFIG_GUID, 0);
  141         }
  142 
  143         /*
  144          * Create pool config based on the best vdev config.
  145          */
  146         config = fnvlist_dup(best_cfg);
  147 
  148         /*
  149          * Put this pool's top-level vdevs into a root vdev.
  150          */
  151         pgid = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID);
  152         nvroot = fnvlist_alloc();
  153         fnvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT);
  154         fnvlist_add_uint64(nvroot, ZPOOL_CONFIG_ID, 0ULL);
  155         fnvlist_add_uint64(nvroot, ZPOOL_CONFIG_GUID, pgid);
  156         fnvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
  157             (const nvlist_t * const *)tops, nchildren);
  158 
  159         /*
  160          * Replace the existing vdev_tree with the new root vdev in
  161          * this pool's configuration (remove the old, add the new).
  162          */
  163         fnvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, nvroot);
  164 
  165         /*
  166          * Drop vdev config elements that should not be present at pool level.
  167          */
  168         fnvlist_remove(config, ZPOOL_CONFIG_GUID);
  169         fnvlist_remove(config, ZPOOL_CONFIG_TOP_GUID);
  170 
  171         for (i = 0; i < count; i++)
  172                 fnvlist_free(configs[i]);
  173         kmem_free(configs, count * sizeof (void *));
  174         for (i = 0; i < nchildren; i++)
  175                 fnvlist_free(tops[i]);
  176         kmem_free(tops, nchildren * sizeof (void *));
  177         fnvlist_free(nvroot);
  178         return (config);
  179 }
  180 
  181 int
  182 spa_import_rootpool(const char *name, bool checkpointrewind)
  183 {
  184         spa_t *spa;
  185         vdev_t *rvd;
  186         nvlist_t *config, *nvtop;
  187         char *pname;
  188         int error;
  189 
  190         /*
  191          * Read the label from the boot device and generate a configuration.
  192          */
  193         config = spa_generate_rootconf(name);
  194 
  195         mutex_enter(&spa_namespace_lock);
  196         if (config != NULL) {
  197                 pname = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
  198                 VERIFY0(strcmp(name, pname));
  199 
  200                 if ((spa = spa_lookup(pname)) != NULL) {
  201                         /*
  202                          * The pool could already be imported,
  203                          * e.g., after reboot -r.
  204                          */
  205                         if (spa->spa_state == POOL_STATE_ACTIVE) {
  206                                 mutex_exit(&spa_namespace_lock);
  207                                 fnvlist_free(config);
  208                                 return (0);
  209                         }
  210 
  211                         /*
  212                          * Remove the existing root pool from the namespace so
  213                          * that we can replace it with the correct config
  214                          * we just read in.
  215                          */
  216                         spa_remove(spa);
  217                 }
  218                 spa = spa_add(pname, config, NULL);
  219 
  220                 /*
  221                  * Set spa_ubsync.ub_version as it can be used in vdev_alloc()
  222                  * via spa_version().
  223                  */
  224                 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
  225                     &spa->spa_ubsync.ub_version) != 0)
  226                         spa->spa_ubsync.ub_version = SPA_VERSION_INITIAL;
  227         } else if ((spa = spa_lookup(name)) == NULL) {
  228                 mutex_exit(&spa_namespace_lock);
  229                 fnvlist_free(config);
  230                 cmn_err(CE_NOTE, "Cannot find the pool label for '%s'",
  231                     name);
  232                 return (EIO);
  233         } else {
  234                 config = fnvlist_dup(spa->spa_config);
  235         }
  236         spa->spa_is_root = B_TRUE;
  237         spa->spa_import_flags = ZFS_IMPORT_VERBATIM;
  238         if (checkpointrewind) {
  239                 spa->spa_import_flags |= ZFS_IMPORT_CHECKPOINT;
  240         }
  241 
  242         /*
  243          * Build up a vdev tree based on the boot device's label config.
  244          */
  245         nvtop = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
  246         spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
  247         error = spa_config_parse(spa, &rvd, nvtop, NULL, 0,
  248             VDEV_ALLOC_ROOTPOOL);
  249         spa_config_exit(spa, SCL_ALL, FTAG);
  250         if (error) {
  251                 mutex_exit(&spa_namespace_lock);
  252                 fnvlist_free(config);
  253                 cmn_err(CE_NOTE, "Can not parse the config for pool '%s'",
  254                     name);
  255                 return (error);
  256         }
  257 
  258         spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
  259         vdev_free(rvd);
  260         spa_config_exit(spa, SCL_ALL, FTAG);
  261         mutex_exit(&spa_namespace_lock);
  262 
  263         fnvlist_free(config);
  264         return (0);
  265 }
  266 
  267 const char *
  268 spa_history_zone(void)
  269 {
  270         return ("freebsd");
  271 }
  272 
  273 void
  274 spa_import_os(spa_t *spa)
  275 {
  276         (void) spa;
  277 }
  278 
  279 void
  280 spa_export_os(spa_t *spa)
  281 {
  282         (void) spa;
  283 }
  284 
  285 void
  286 spa_activate_os(spa_t *spa)
  287 {
  288         (void) spa;
  289 }
  290 
  291 void
  292 spa_deactivate_os(spa_t *spa)
  293 {
  294         (void) spa;
  295 }

Cache object: e2dfe968a9d4bdf152e943b8b054390e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.