Date: Wed, 6 Nov 2019 08:58:03 +0000 (UTC) From: Andriy Gapon <avg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r354382 - vendor-sys/illumos/dist/common/zfs vendor-sys/illumos/dist/uts/common/fs/zfs vendor-sys/illumos/dist/uts/common/fs/zfs/sys vendor-sys/illumos/dist/uts/common/sys/fs vendor/ill... Message-ID: <201911060858.xA68w3xb047144@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avg Date: Wed Nov 6 08:58:03 2019 New Revision: 354382 URL: https://svnweb.freebsd.org/changeset/base/354382 Log: 10601 10757 Pool allocation classes illumos/illumos-gate@663207adb1669640c01c5ec6949ce78fd806efae https://github.com/illumos/illumos-gate/commit/663207adb1669640c01c5ec6949ce78fd806efae 10601 Pool allocation classes https://www.illumos.org/issues/10601 illumos port of ZoL Pool allocation classes. Includes at least these two commits: 441709695 Pool allocation classes misplacing small file blocks cc99f275a Pool allocation classes 10757 Add -gLp to zpool subcommands for alt vdev names https://www.illumos.org/issues/10757 Port from ZoL of d2f3e292d Add -gLp to zpool subcommands for alt vdev names Note that a subsequent ZoL commit changed -p to -P a77f29f93 Change full path subcommand flag from -p to -P Portions contributed by: Jerry Jelinek <jerry.jelinek@joyent.com> Portions contributed by: HÃ¥kan Johansson <f96hajo@chalmers.se> Portions contributed by: Richard Yao <ryao@gentoo.org> Portions contributed by: Chunwei Chen <david.chen@nutanix.com> Portions contributed by: loli10K <ezomori.nozomu@gmail.com> Author: Don Brady <don.brady@delphix.com> Modified: vendor-sys/illumos/dist/common/zfs/zfeature_common.c vendor-sys/illumos/dist/common/zfs/zfeature_common.h vendor-sys/illumos/dist/common/zfs/zfs_prop.c vendor-sys/illumos/dist/uts/common/fs/zfs/dmu.c vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_objset.c vendor-sys/illumos/dist/uts/common/fs/zfs/metaslab.c vendor-sys/illumos/dist/uts/common/fs/zfs/spa.c vendor-sys/illumos/dist/uts/common/fs/zfs/spa_misc.c vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu.h vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu_objset.h vendor-sys/illumos/dist/uts/common/fs/zfs/sys/metaslab.h vendor-sys/illumos/dist/uts/common/fs/zfs/sys/spa.h vendor-sys/illumos/dist/uts/common/fs/zfs/sys/spa_impl.h vendor-sys/illumos/dist/uts/common/fs/zfs/sys/vdev.h vendor-sys/illumos/dist/uts/common/fs/zfs/sys/vdev_impl.h vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zio.h vendor-sys/illumos/dist/uts/common/fs/zfs/vdev.c vendor-sys/illumos/dist/uts/common/fs/zfs/vdev_label.c vendor-sys/illumos/dist/uts/common/fs/zfs/vdev_removal.c vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_ioctl.c vendor-sys/illumos/dist/uts/common/fs/zfs/zio.c vendor-sys/illumos/dist/uts/common/sys/fs/zfs.h Changes in other areas also in this revision: Modified: vendor/illumos/dist/cmd/zdb/zdb.c vendor/illumos/dist/cmd/zpool/zpool_main.c vendor/illumos/dist/cmd/zpool/zpool_vdev.c vendor/illumos/dist/cmd/ztest/ztest.c vendor/illumos/dist/lib/libzfs/common/libzfs.h vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c vendor/illumos/dist/lib/libzfs/common/libzfs_pool.c vendor/illumos/dist/lib/libzpool/common/util.c vendor/illumos/dist/man/man1m/zfs.1m vendor/illumos/dist/man/man1m/zpool.1m vendor/illumos/dist/man/man5/zpool-features.5 Modified: vendor-sys/illumos/dist/common/zfs/zfeature_common.c ============================================================================== --- vendor-sys/illumos/dist/common/zfs/zfeature_common.c Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/common/zfs/zfeature_common.c Wed Nov 6 08:58:03 2019 (r354382) @@ -20,11 +20,12 @@ */ /* - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. * Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014 Integros [integros.com] + * Copyright (c) 2017, Intel Corporation. */ #ifdef _KERNEL @@ -298,4 +299,11 @@ zpool_feature_init(void) "Reduce memory used by removed devices when their blocks are " "freed or remapped.", ZFEATURE_FLAG_READONLY_COMPAT, obsolete_counts_deps); + + { + zfeature_register(SPA_FEATURE_ALLOCATION_CLASSES, + "org.zfsonlinux:allocation_classes", "allocation_classes", + "Support for separate allocation classes.", + ZFEATURE_FLAG_READONLY_COMPAT, NULL); + } } Modified: vendor-sys/illumos/dist/common/zfs/zfeature_common.h ============================================================================== --- vendor-sys/illumos/dist/common/zfs/zfeature_common.h Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/common/zfs/zfeature_common.h Wed Nov 6 08:58:03 2019 (r354382) @@ -24,6 +24,7 @@ * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. * Copyright (c) 2014 Integros [integros.com] + * Copyright (c) 2017, Intel Corporation. */ #ifndef _ZFEATURE_COMMON_H @@ -61,6 +62,7 @@ typedef enum spa_feature { SPA_FEATURE_OBSOLETE_COUNTS, SPA_FEATURE_POOL_CHECKPOINT, SPA_FEATURE_SPACEMAP_V2, + SPA_FEATURE_ALLOCATION_CLASSES, SPA_FEATURES } spa_feature_t; Modified: vendor-sys/illumos/dist/common/zfs/zfs_prop.c ============================================================================== --- vendor-sys/illumos/dist/common/zfs/zfs_prop.c Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/common/zfs/zfs_prop.c Wed Nov 6 08:58:03 2019 (r354382) @@ -435,6 +435,9 @@ zfs_prop_init(void) zprop_register_number(ZFS_PROP_RECORDSIZE, "recordsize", SPA_OLD_MAXBLOCKSIZE, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, "512 to 1M, power of 2", "RECSIZE"); + zprop_register_number(ZFS_PROP_SPECIAL_SMALL_BLOCKS, + "special_small_blocks", 0, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, + "zero or 512 to 128K, power of 2", "SPECIAL_SMALL_BLOCKS"); /* hidden properties */ zprop_register_hidden(ZFS_PROP_REMAPTXG, "remaptxg", PROP_TYPE_NUMBER, Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dmu.c ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/dmu.c Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/dmu.c Wed Nov 6 08:58:03 2019 (r354382) @@ -2201,6 +2201,8 @@ dmu_write_policy(objset_t *os, dnode_t *dn, int level, zp->zp_dedup = dedup; zp->zp_dedup_verify = dedup && dedup_verify; zp->zp_nopwrite = nopwrite; + zp->zp_zpl_smallblk = DMU_OT_IS_FILE(zp->zp_type) ? + os->os_zpl_special_smallblock : 0; } int Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_objset.c ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_objset.c Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_objset.c Wed Nov 6 08:58:03 2019 (r354382) @@ -304,6 +304,20 @@ dnodesize_changed_cb(void *arg, uint64_t newval) } static void +smallblk_changed_cb(void *arg, uint64_t newval) +{ + objset_t *os = arg; + + /* + * Inheritance and range checking should have been done by now. + */ + ASSERT(newval <= SPA_OLD_MAXBLOCKSIZE); + ASSERT(ISP2(newval)); + + os->os_zpl_special_smallblock = newval; +} + +static void logbias_changed_cb(void *arg, uint64_t newval) { objset_t *os = arg; @@ -515,6 +529,12 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, bl err = dsl_prop_register(ds, zfs_prop_to_name(ZFS_PROP_DNODESIZE), dnodesize_changed_cb, os); + } + if (err == 0) { + err = dsl_prop_register(ds, + zfs_prop_to_name( + ZFS_PROP_SPECIAL_SMALL_BLOCKS), + smallblk_changed_cb, os); } } if (needlock) Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/metaslab.c ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/metaslab.c Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/metaslab.c Wed Nov 6 08:58:03 2019 (r354382) @@ -23,6 +23,7 @@ * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2014 Integros [integros.com] + * Copyright (c) 2017, Intel Corporation. */ #include <sys/zfs_context.h> @@ -288,7 +289,7 @@ metaslab_class_validate(metaslab_class_t *mc) return (0); } -void +static void metaslab_class_space_update(metaslab_class_t *mc, int64_t alloc_delta, int64_t defer_delta, int64_t space_delta, int64_t dspace_delta) { @@ -325,7 +326,8 @@ metaslab_class_get_dspace(metaslab_class_t *mc) void metaslab_class_histogram_verify(metaslab_class_t *mc) { - vdev_t *rvd = mc->mc_spa->spa_root_vdev; + spa_t *spa = mc->mc_spa; + vdev_t *rvd = spa->spa_root_vdev; uint64_t *mc_hist; int i; @@ -831,7 +833,8 @@ metaslab_group_histogram_verify(metaslab_group_t *mg) for (int m = 0; m < vd->vdev_ms_count; m++) { metaslab_t *msp = vd->vdev_ms[m]; - if (msp->ms_sm == NULL) + /* skip if not active or not a member */ + if (msp->ms_sm == NULL || msp->ms_group != mg) continue; for (i = 0; i < SPACE_MAP_HISTOGRAM_SIZE; i++) @@ -964,12 +967,14 @@ metaslab_group_fragmentation(metaslab_group_t *mg) if (msp->ms_fragmentation == ZFS_FRAG_INVALID) continue; + if (msp->ms_group != mg) + continue; valid_ms++; fragmentation += msp->ms_fragmentation; } - if (valid_ms <= vd->vdev_ms_count / 2) + if (valid_ms <= mg->mg_vd->vdev_ms_count / 2) return (ZFS_FRAG_INVALID); fragmentation /= valid_ms; @@ -1000,7 +1005,10 @@ metaslab_group_allocatable(metaslab_group_t *mg, metas * groups to select from. Otherwise, we always consider it eligible * for allocations. */ - if (mc != spa_normal_class(spa) || mc->mc_groups <= 1) + if ((mc != spa_normal_class(spa) && + mc != spa_special_class(spa) && + mc != spa_dedup_class(spa)) || + mc->mc_groups <= 1) return (B_TRUE); /* @@ -1534,12 +1542,26 @@ metaslab_unload(metaslab_t *msp) msp->ms_max_size = 0; } +static void +metaslab_space_update(vdev_t *vd, metaslab_class_t *mc, int64_t alloc_delta, + int64_t defer_delta, int64_t space_delta) +{ + vdev_space_update(vd, alloc_delta, defer_delta, space_delta); + + ASSERT3P(vd->vdev_spa->spa_root_vdev, ==, vd->vdev_parent); + ASSERT(vd->vdev_ms_count != 0); + + metaslab_class_space_update(mc, alloc_delta, defer_delta, space_delta, + vdev_deflated_space(vd, space_delta)); +} + int metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg, metaslab_t **msp) { vdev_t *vd = mg->mg_vd; - objset_t *mos = vd->vdev_spa->spa_meta_objset; + spa_t *spa = vd->vdev_spa; + objset_t *mos = spa->spa_meta_objset; metaslab_t *ms; int error; @@ -1596,8 +1618,8 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint6 /* * If metaslab_debug_load is set and we're initializing a metaslab - * that has an allocated space map object then load the its space - * map so that can verify frees. + * that has an allocated space map object then load the space map + * so that we can verify frees. */ if (metaslab_debug_load && ms->ms_sm != NULL) { mutex_enter(&ms->ms_lock); @@ -1619,16 +1641,19 @@ void metaslab_fini(metaslab_t *msp) { metaslab_group_t *mg = msp->ms_group; + vdev_t *vd = mg->mg_vd; metaslab_group_remove(mg, msp); mutex_enter(&msp->ms_lock); VERIFY(msp->ms_group == NULL); - vdev_space_update(mg->mg_vd, -space_map_allocated(msp->ms_sm), - 0, -msp->ms_size); + metaslab_space_update(vd, mg->mg_class, + -space_map_allocated(msp->ms_sm), 0, -msp->ms_size); + space_map_close(msp->ms_sm); metaslab_unload(msp); + range_tree_destroy(msp->ms_allocatable); range_tree_destroy(msp->ms_freeing); range_tree_destroy(msp->ms_freed); @@ -2643,7 +2668,7 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) ASSERT3P(msp->ms_checkpointing, ==, NULL); msp->ms_checkpointing = range_tree_create(NULL, NULL); - vdev_space_update(vd, 0, 0, msp->ms_size); + metaslab_space_update(vd, mg->mg_class, 0, 0, msp->ms_size); } ASSERT0(range_tree_space(msp->ms_freeing)); ASSERT0(range_tree_space(msp->ms_checkpointing)); @@ -2665,7 +2690,8 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) defer_delta -= range_tree_space(*defer_tree); } - vdev_space_update(vd, alloc_delta + defer_delta, defer_delta, 0); + metaslab_space_update(vd, mg->mg_class, alloc_delta + defer_delta, + defer_delta, 0); /* * If there's a metaslab_load() in progress, wait for it to complete @@ -2764,21 +2790,25 @@ metaslab_sync_reassess(metaslab_group_t *mg) spa_config_exit(spa, SCL_ALLOC, FTAG); } -static uint64_t -metaslab_distance(metaslab_t *msp, dva_t *dva) +/* + * When writing a ditto block (i.e. more than one DVA for a given BP) on + * the same vdev as an existing DVA of this BP, then try to allocate it + * on a different metaslab than existing DVAs (i.e. a unique metaslab). + */ +static boolean_t +metaslab_is_unique(metaslab_t *msp, dva_t *dva) { - uint64_t ms_shift = msp->ms_group->mg_vd->vdev_ms_shift; - uint64_t offset = DVA_GET_OFFSET(dva) >> ms_shift; - uint64_t start = msp->ms_id; + uint64_t dva_ms_id; + if (DVA_GET_ASIZE(dva) == 0) + return (B_TRUE); + if (msp->ms_group->mg_vd->vdev_id != DVA_GET_VDEV(dva)) - return (1ULL << 63); + return (B_TRUE); - if (offset < start) - return ((start - offset) << ms_shift); - if (offset > start) - return ((offset - start) << ms_shift); - return (0); + dva_ms_id = DVA_GET_OFFSET(dva) >> msp->ms_group->mg_vd->vdev_ms_shift; + + return (msp->ms_id != dva_ms_id); } /* @@ -3012,7 +3042,7 @@ metaslab_block_alloc(metaslab_t *msp, uint64_t size, u */ static metaslab_t * find_valid_metaslab(metaslab_group_t *mg, uint64_t activation_weight, - dva_t *dva, int d, uint64_t min_distance, uint64_t asize, int allocator, + dva_t *dva, int d, boolean_t want_unique, uint64_t asize, int allocator, zio_alloc_list_t *zal, metaslab_t *search, boolean_t *was_active) { avl_index_t idx; @@ -3047,13 +3077,10 @@ find_valid_metaslab(metaslab_group_t *mg, uint64_t act if (activation_weight == METASLAB_WEIGHT_PRIMARY || *was_active) break; - uint64_t target_distance = min_distance - + (space_map_allocated(msp->ms_sm) != 0 ? 0 : - min_distance >> 1); - for (i = 0; i < d; i++) { - if (metaslab_distance(msp, &dva[i]) < target_distance) - break; + if (want_unique && + !metaslab_is_unique(msp, &dva[i])) + break; /* try another metaslab */ } if (i == d) break; @@ -3071,8 +3098,8 @@ find_valid_metaslab(metaslab_group_t *mg, uint64_t act /* ARGSUSED */ static uint64_t metaslab_group_alloc_normal(metaslab_group_t *mg, zio_alloc_list_t *zal, - uint64_t asize, uint64_t txg, uint64_t min_distance, dva_t *dva, int d, - int allocator) + uint64_t asize, uint64_t txg, boolean_t want_unique, dva_t *dva, + int d, int allocator) { metaslab_t *msp = NULL; uint64_t offset = -1ULL; @@ -3126,7 +3153,7 @@ metaslab_group_alloc_normal(metaslab_group_t *mg, zio_ was_active = B_TRUE; } else { msp = find_valid_metaslab(mg, activation_weight, dva, d, - min_distance, asize, allocator, zal, search, + want_unique, asize, allocator, zal, search, &was_active); } @@ -3264,6 +3291,7 @@ next: * metaslab. */ ASSERT(!metaslab_should_allocate(msp, asize)); + mutex_exit(&msp->ms_lock); } mutex_exit(&msp->ms_lock); @@ -3273,14 +3301,14 @@ next: static uint64_t metaslab_group_alloc(metaslab_group_t *mg, zio_alloc_list_t *zal, - uint64_t asize, uint64_t txg, uint64_t min_distance, dva_t *dva, int d, - int allocator) + uint64_t asize, uint64_t txg, boolean_t want_unique, dva_t *dva, + int d, int allocator) { uint64_t offset; ASSERT(mg->mg_initialized); - offset = metaslab_group_alloc_normal(mg, zal, asize, txg, - min_distance, dva, d, allocator); + offset = metaslab_group_alloc_normal(mg, zal, asize, txg, want_unique, + dva, d, allocator); mutex_enter(&mg->mg_lock); if (offset == -1ULL) { @@ -3308,14 +3336,6 @@ metaslab_group_alloc(metaslab_group_t *mg, zio_alloc_l } /* - * If we have to write a ditto block (i.e. more than one DVA for a given BP) - * on the same vdev as an existing DVA of this BP, then try to allocate it - * at least (vdev_asize / (2 ^ ditto_same_vdev_distance_shift)) away from the - * existing DVAs. - */ -int ditto_same_vdev_distance_shift = 3; - -/* * Allocate a block for the specified i/o. */ int @@ -3331,6 +3351,7 @@ metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, u /* * For testing, make some blocks above a certain size be gang blocks. + * This will also test spilling from special to normal. */ if (psize >= metaslab_force_ganging && (ddi_get_lbolt() & 3) == 0) { metaslab_trace_add(zal, NULL, NULL, psize, d, TRACE_FORCE_GANG, @@ -3382,6 +3403,7 @@ metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, u vd = vdev_lookup_top(spa, DVA_GET_VDEV(&dva[d - 1])); mg = vd->vdev_mg->mg_next; } else { + ASSERT(mc->mc_rotor != NULL); mg = mc->mc_rotor; } @@ -3446,25 +3468,17 @@ top: ASSERT(mg->mg_class == mc); - /* - * If we don't need to try hard, then require that the - * block be 1/8th of the device away from any other DVAs - * in this BP. If we are trying hard, allow any offset - * to be used (distance=0). - */ - uint64_t distance = 0; - if (!try_hard) { - distance = vd->vdev_asize >> - ditto_same_vdev_distance_shift; - if (distance <= (1ULL << vd->vdev_ms_shift)) - distance = 0; - } - uint64_t asize = vdev_psize_to_asize(vd, psize); ASSERT(P2PHASE(asize, 1ULL << vd->vdev_ashift) == 0); + /* + * If we don't need to try hard, then require that the + * block be on an different metaslab from any other DVAs + * in this BP (unique=true). If we are trying hard, then + * allow any metaslab to be used (unique=false). + */ uint64_t offset = metaslab_group_alloc(mg, zal, asize, txg, - distance, dva, d, allocator); + !try_hard, dva, d, allocator); if (offset != -1ULL) { /* @@ -3843,7 +3857,8 @@ metaslab_class_throttle_reserve(metaslab_class_t *mc, if (reserved_slots < max) available_slots = max - reserved_slots; - if (slots <= available_slots || GANG_ALLOCATION(flags)) { + if (slots <= available_slots || GANG_ALLOCATION(flags) || + flags & METASLAB_MUST_RESERVE) { /* * We reserve the slots individually so that we can unreserve * them individually when an I/O completes. @@ -4126,9 +4141,11 @@ metaslab_claim(spa_t *spa, const blkptr_t *bp, uint64_ spa_config_enter(spa, SCL_ALLOC, FTAG, RW_READER); - for (int d = 0; d < ndvas; d++) - if ((error = metaslab_claim_dva(spa, &dva[d], txg)) != 0) + for (int d = 0; d < ndvas; d++) { + error = metaslab_claim_dva(spa, &dva[d], txg); + if (error != 0) break; + } spa_config_exit(spa, SCL_ALLOC, FTAG); Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/spa.c ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/spa.c Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/spa.c Wed Nov 6 08:58:03 2019 (r354382) @@ -28,6 +28,7 @@ * Copyright (c) 2014 Integros [integros.com] * Copyright 2016 Toomas Soome <tsoome@me.com> * Copyright 2018 Joyent, Inc. + * Copyright (c) 2017, Intel Corporation. * Copyright (c) 2017 Datto Inc. * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. */ @@ -274,8 +275,14 @@ spa_prop_get_config(spa_t *spa, nvlist_t **nvp) ASSERT(MUTEX_HELD(&spa->spa_props_lock)); if (rvd != NULL) { - alloc = metaslab_class_get_alloc(spa_normal_class(spa)); - size = metaslab_class_get_space(spa_normal_class(spa)); + alloc = metaslab_class_get_alloc(mc); + alloc += metaslab_class_get_alloc(spa_special_class(spa)); + alloc += metaslab_class_get_alloc(spa_dedup_class(spa)); + + size = metaslab_class_get_space(mc); + size += metaslab_class_get_space(spa_special_class(spa)); + size += metaslab_class_get_space(spa_dedup_class(spa)); + spa_prop_add_list(*nvp, ZPOOL_PROP_NAME, spa_name(spa), 0, src); spa_prop_add_list(*nvp, ZPOOL_PROP_SIZE, NULL, size, src); spa_prop_add_list(*nvp, ZPOOL_PROP_ALLOCATED, NULL, alloc, src); @@ -1137,6 +1144,8 @@ spa_activate(spa_t *spa, int mode) spa->spa_normal_class = metaslab_class_create(spa, zfs_metaslab_ops); spa->spa_log_class = metaslab_class_create(spa, zfs_metaslab_ops); + spa->spa_special_class = metaslab_class_create(spa, zfs_metaslab_ops); + spa->spa_dedup_class = metaslab_class_create(spa, zfs_metaslab_ops); /* Try to create a covering process */ mutex_enter(&spa->spa_proc_lock); @@ -1232,6 +1241,12 @@ spa_deactivate(spa_t *spa) metaslab_class_destroy(spa->spa_log_class); spa->spa_log_class = NULL; + metaslab_class_destroy(spa->spa_special_class); + spa->spa_special_class = NULL; + + metaslab_class_destroy(spa->spa_dedup_class); + spa->spa_dedup_class = NULL; + /* * If this was part of an import or the open otherwise failed, we may * still have errors left in the queues. Empty them just in case. @@ -4834,7 +4849,8 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_ char *poolname; nvlist_t *nvl; - if (nvlist_lookup_string(props, + if (props == NULL || + nvlist_lookup_string(props, zpool_prop_to_name(ZPOOL_PROP_TNAME), &poolname) != 0) poolname = (char *)pool; @@ -4922,9 +4938,15 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_ (error = vdev_create(rvd, txg, B_FALSE)) == 0 && (error = spa_validate_aux(spa, nvroot, txg, VDEV_ALLOC_ADD)) == 0) { - for (int c = 0; c < rvd->vdev_children; c++) { - vdev_metaslab_set_size(rvd->vdev_child[c]); - vdev_expand(rvd->vdev_child[c], txg); + /* + * instantiate the metaslab groups (this will dirty the vdevs) + * we can no longer error exit past this point + */ + for (int c = 0; error == 0 && c < rvd->vdev_children; c++) { + vdev_t *vd = rvd->vdev_child[c]; + + vdev_metaslab_set_size(vd); + vdev_expand(vd, txg); } } @@ -7082,8 +7104,14 @@ spa_async_thread(void *arg) mutex_enter(&spa_namespace_lock); old_space = metaslab_class_get_space(spa_normal_class(spa)); + old_space += metaslab_class_get_space(spa_special_class(spa)); + old_space += metaslab_class_get_space(spa_dedup_class(spa)); + spa_config_update(spa, SPA_CONFIG_UPDATE_POOL); + new_space = metaslab_class_get_space(spa_normal_class(spa)); + new_space += metaslab_class_get_space(spa_special_class(spa)); + new_space += metaslab_class_get_space(spa_dedup_class(spa)); mutex_exit(&spa_namespace_lock); /* @@ -7780,6 +7808,9 @@ spa_sync(spa_t *spa, uint64_t txg) dsl_pool_t *dp = spa->spa_dsl_pool; objset_t *mos = spa->spa_meta_objset; bplist_t *free_bpl = &spa->spa_free_bplist[txg & TXG_MASK]; + metaslab_class_t *normal = spa_normal_class(spa); + metaslab_class_t *special = spa_special_class(spa); + metaslab_class_t *dedup = spa_dedup_class(spa); vdev_t *rvd = spa->spa_root_vdev; vdev_t *vd; dmu_tx_t *tx; @@ -7872,11 +7903,15 @@ spa_sync(spa_t *spa, uint64_t txg) for (int c = 0; c < rvd->vdev_children; c++) { vdev_t *tvd = rvd->vdev_child[c]; metaslab_group_t *mg = tvd->vdev_mg; + metaslab_class_t *mc; - if (mg == NULL || mg->mg_class != spa_normal_class(spa) || - !metaslab_group_initialized(mg)) + if (mg == NULL || !metaslab_group_initialized(mg)) continue; + mc = mg->mg_class; + if (mc != normal && mc != special && mc != dedup) + continue; + /* * It is safe to do a lock-free check here because only async * allocations look at mg_max_alloc_queue_depth, and async @@ -7893,12 +7928,18 @@ spa_sync(spa_t *spa, uint64_t txg) } slots_per_allocator += zfs_vdev_def_queue_depth; } - metaslab_class_t *mc = spa_normal_class(spa); + for (int i = 0; i < spa->spa_alloc_count; i++) { - ASSERT0(zfs_refcount_count(&mc->mc_alloc_slots[i])); - mc->mc_alloc_max_slots[i] = slots_per_allocator; + ASSERT0(zfs_refcount_count(&normal->mc_alloc_slots[i])); + ASSERT0(zfs_refcount_count(&special->mc_alloc_slots[i])); + ASSERT0(zfs_refcount_count(&dedup->mc_alloc_slots[i])); + normal->mc_alloc_max_slots[i] = slots_per_allocator; + special->mc_alloc_max_slots[i] = slots_per_allocator; + dedup->mc_alloc_max_slots[i] = slots_per_allocator; } - mc->mc_alloc_throttle_enabled = zio_dva_throttle_enabled; + normal->mc_alloc_throttle_enabled = zio_dva_throttle_enabled; + special->mc_alloc_throttle_enabled = zio_dva_throttle_enabled; + dedup->mc_alloc_throttle_enabled = zio_dva_throttle_enabled; for (int c = 0; c < rvd->vdev_children; c++) { vdev_t *vd = rvd->vdev_child[c]; Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/spa_misc.c ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/spa_misc.c Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/spa_misc.c Wed Nov 6 08:58:03 2019 (r354382) @@ -26,6 +26,7 @@ * Copyright 2013 Saso Kiselkov. All rights reserved. * Copyright (c) 2014 Integros [integros.com] * Copyright (c) 2017 Datto Inc. + * Copyright (c) 2017, Intel Corporation. */ #include <sys/zfs_context.h> @@ -388,6 +389,19 @@ spa_load_note(spa_t *spa, const char *fmt, ...) } /* + * By default dedup and user data indirects land in the special class + */ +int zfs_ddt_data_is_special = B_TRUE; +int zfs_user_indirect_is_special = B_TRUE; + +/* + * The percentage of special class final space reserved for metadata only. + * Once we allocate 100 - zfs_special_class_metadata_reserve_pct we only + * let metadata into the class. + */ +int zfs_special_class_metadata_reserve_pct = 25; + +/* * ========================================================================== * SPA config locking * ========================================================================== @@ -1173,6 +1187,8 @@ spa_vdev_config_exit(spa_t *spa, vdev_t *vd, uint64_t */ ASSERT(metaslab_class_validate(spa_normal_class(spa)) == 0); ASSERT(metaslab_class_validate(spa_log_class(spa)) == 0); + ASSERT(metaslab_class_validate(spa_special_class(spa)) == 0); + ASSERT(metaslab_class_validate(spa_dedup_class(spa)) == 0); spa_config_exit(spa, SCL_ALL, spa); @@ -1516,6 +1532,16 @@ zfs_strtonum(const char *str, char **nptr) return (val); } +void +spa_activate_allocation_classes(spa_t *spa, dmu_tx_t *tx) +{ + /* + * We bump the feature refcount for each special vdev added to the pool + */ + ASSERT(spa_feature_is_enabled(spa, SPA_FEATURE_ALLOCATION_CLASSES)); + spa_feature_incr(spa, SPA_FEATURE_ALLOCATION_CLASSES, tx); +} + /* * ========================================================================== * Accessor functions @@ -1763,6 +1789,79 @@ metaslab_class_t * spa_log_class(spa_t *spa) { return (spa->spa_log_class); +} + +metaslab_class_t * +spa_special_class(spa_t *spa) +{ + return (spa->spa_special_class); +} + +metaslab_class_t * +spa_dedup_class(spa_t *spa) +{ + return (spa->spa_dedup_class); +} + +/* + * Locate an appropriate allocation class + */ +metaslab_class_t * +spa_preferred_class(spa_t *spa, uint64_t size, dmu_object_type_t objtype, + uint_t level, uint_t special_smallblk) +{ + if (DMU_OT_IS_ZIL(objtype)) { + if (spa->spa_log_class->mc_groups != 0) + return (spa_log_class(spa)); + else + return (spa_normal_class(spa)); + } + + boolean_t has_special_class = spa->spa_special_class->mc_groups != 0; + + if (DMU_OT_IS_DDT(objtype)) { + if (spa->spa_dedup_class->mc_groups != 0) + return (spa_dedup_class(spa)); + else if (has_special_class && zfs_ddt_data_is_special) + return (spa_special_class(spa)); + else + return (spa_normal_class(spa)); + } + + /* Indirect blocks for user data can land in special if allowed */ + if (level > 0 && (DMU_OT_IS_FILE(objtype) || objtype == DMU_OT_ZVOL)) { + if (has_special_class && zfs_user_indirect_is_special) + return (spa_special_class(spa)); + else + return (spa_normal_class(spa)); + } + + if (DMU_OT_IS_METADATA(objtype) || level > 0) { + if (has_special_class) + return (spa_special_class(spa)); + else + return (spa_normal_class(spa)); + } + + /* + * Allow small file blocks in special class in some cases (like + * for the dRAID vdev feature). But always leave a reserve of + * zfs_special_class_metadata_reserve_pct exclusively for metadata. + */ + if (DMU_OT_IS_FILE(objtype) && + has_special_class && size <= special_smallblk) { + metaslab_class_t *special = spa_special_class(spa); + uint64_t alloc = metaslab_class_get_alloc(special); + uint64_t space = metaslab_class_get_space(special); + uint64_t limit = + (space * (100 - zfs_special_class_metadata_reserve_pct)) + / 100; + + if (alloc < limit) + return (special); + } + + return (spa_normal_class(spa)); } void Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu.h ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu.h Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu.h Wed Nov 6 08:58:03 2019 (r354382) @@ -21,13 +21,14 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2012, Joyent, Inc. All rights reserved. * Copyright 2013 DEY Storage Systems, Inc. * Copyright 2014 HybridCluster. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright 2013 Saso Kiselkov. All rights reserved. + * Copyright (c) 2017, Intel Corporation. * Copyright (c) 2014 Integros [integros.com] */ @@ -126,6 +127,16 @@ typedef enum dmu_object_byteswap { ((ot) & DMU_OT_METADATA) : \ dmu_ot[(ot)].ot_metadata) +#define DMU_OT_IS_DDT(ot) \ + ((ot) == DMU_OT_DDT_ZAP) + +#define DMU_OT_IS_ZIL(ot) \ + ((ot) == DMU_OT_INTENT_LOG) + +/* Note: ztest uses DMU_OT_UINT64_OTHER as a proxy for file blocks */ +#define DMU_OT_IS_FILE(ot) \ + ((ot) == DMU_OT_PLAIN_FILE_CONTENTS || (ot) == DMU_OT_UINT64_OTHER) + #define DMU_OT_IS_METADATA_CACHED(ot) (((ot) & DMU_OT_NEWTYPE) ? \ B_TRUE : dmu_ot[(ot)].ot_dbuf_metadata_cache) @@ -216,6 +227,7 @@ typedef enum dmu_object_type { * * The DMU_OTN_* types do not have entries in the dmu_ot table, * use the DMU_OT_IS_METDATA() and DMU_OT_BYTESWAP() macros instead + * use the DMU_OT_IS_METADATA() and DMU_OT_BYTESWAP() macros instead * of indexing into dmu_ot directly (this works for both DMU_OT_* types * and DMU_OTN_* types). */ Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu_objset.h ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu_objset.h Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu_objset.h Wed Nov 6 08:58:03 2019 (r354382) @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 by Delphix. All rights reserved. + * Copyright (c) 2012, 2018 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright (c) 2014 Integros [integros.com] @@ -113,6 +113,11 @@ struct objset { uint64_t os_normalization; uint64_t os_utf8only; uint64_t os_casesensitivity; + /* + * The largest zpl file block allowed in special class. + * cached here instead of zfsvfs for easier access. + */ + int os_zpl_special_smallblock; /* * Pointer is constant; the blkptr it points to is protected by Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/sys/metaslab.h ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/sys/metaslab.h Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/sys/metaslab.h Wed Nov 6 08:58:03 2019 (r354382) @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2018 by Delphix. All rights reserved. + * Copyright (c) 2017, Intel Corporation. */ #ifndef _SYS_METASLAB_H @@ -56,12 +57,17 @@ void metaslab_sync_done(metaslab_t *, uint64_t); void metaslab_sync_reassess(metaslab_group_t *); uint64_t metaslab_block_maxsize(metaslab_t *); +/* + * metaslab alloc flags + */ #define METASLAB_HINTBP_FAVOR 0x0 #define METASLAB_HINTBP_AVOID 0x1 #define METASLAB_GANG_HEADER 0x2 #define METASLAB_GANG_CHILD 0x4 #define METASLAB_ASYNC_ALLOC 0x8 #define METASLAB_DONT_THROTTLE 0x10 +#define METASLAB_MUST_RESERVE 0x20 +#define METASLAB_FASTWRITE 0x40 int metaslab_alloc(spa_t *, metaslab_class_t *, uint64_t, blkptr_t *, int, uint64_t, blkptr_t *, int, zio_alloc_list_t *, zio_t *, @@ -92,8 +98,6 @@ boolean_t metaslab_class_throttle_reserve(metaslab_cla zio_t *, int); void metaslab_class_throttle_unreserve(metaslab_class_t *, int, int, zio_t *); -void metaslab_class_space_update(metaslab_class_t *, int64_t, int64_t, - int64_t, int64_t); uint64_t metaslab_class_get_alloc(metaslab_class_t *); uint64_t metaslab_class_get_space(metaslab_class_t *); uint64_t metaslab_class_get_dspace(metaslab_class_t *); Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/sys/spa.h ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/sys/spa.h Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/sys/spa.h Wed Nov 6 08:58:03 2019 (r354382) @@ -27,6 +27,7 @@ * Copyright (c) 2014 Integros [integros.com] * Copyright 2017 Joyent, Inc. * Copyright (c) 2017 Datto Inc. + * Copyright (c) 2017, Intel Corporation. */ #ifndef _SYS_SPA_H @@ -801,6 +802,11 @@ extern uint64_t spa_version(spa_t *spa); extern boolean_t spa_deflate(spa_t *spa); extern metaslab_class_t *spa_normal_class(spa_t *spa); extern metaslab_class_t *spa_log_class(spa_t *spa); +extern metaslab_class_t *spa_special_class(spa_t *spa); +extern metaslab_class_t *spa_dedup_class(spa_t *spa); +extern metaslab_class_t *spa_preferred_class(spa_t *spa, uint64_t size, + dmu_object_type_t objtype, uint_t level, uint_t special_smallblk); + extern void spa_evicting_os_register(spa_t *, objset_t *os); extern void spa_evicting_os_deregister(spa_t *, objset_t *os); extern void spa_evicting_os_wait(spa_t *spa); @@ -862,6 +868,7 @@ extern boolean_t spa_trust_config(spa_t *spa); extern uint64_t spa_missing_tvds_allowed(spa_t *spa); extern void spa_set_missing_tvds(spa_t *spa, uint64_t missing); extern boolean_t spa_top_vdevs_spacemap_addressable(spa_t *spa); +extern void spa_activate_allocation_classes(spa_t *, dmu_tx_t *); extern int spa_mode(spa_t *spa); extern uint64_t zfs_strtonum(const char *str, char **nptr); Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/sys/spa_impl.h ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/sys/spa_impl.h Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/sys/spa_impl.h Wed Nov 6 08:58:03 2019 (r354382) @@ -25,6 +25,7 @@ * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright 2013 Saso Kiselkov. All rights reserved. * Copyright (c) 2017 Datto Inc. + * Copyright (c) 2017, Intel Corporation. */ #ifndef _SYS_SPA_IMPL_H @@ -218,6 +219,8 @@ struct spa { boolean_t spa_is_initializing; /* true while opening pool */ metaslab_class_t *spa_normal_class; /* normal data class */ metaslab_class_t *spa_log_class; /* intent log data class */ + metaslab_class_t *spa_special_class; /* special allocation class */ + metaslab_class_t *spa_dedup_class; /* dedup allocation class */ uint64_t spa_first_txg; /* first txg after spa_open() */ uint64_t spa_final_txg; /* txg of export/destroy */ uint64_t spa_freeze_txg; /* freeze pool at this txg */ Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/sys/vdev.h ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/sys/vdev.h Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/sys/vdev.h Wed Nov 6 08:58:03 2019 (r354382) @@ -22,6 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2017, Intel Corporation. */ #ifndef _SYS_VDEV_H @@ -106,6 +107,8 @@ extern boolean_t vdev_children_are_offline(vdev_t *vd) extern void vdev_space_update(vdev_t *vd, int64_t alloc_delta, int64_t defer_delta, int64_t space_delta); + +extern int64_t vdev_deflated_space(vdev_t *vd, int64_t space); extern uint64_t vdev_psize_to_asize(vdev_t *vd, uint64_t psize); Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/sys/vdev_impl.h ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/sys/vdev_impl.h Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/sys/vdev_impl.h Wed Nov 6 08:58:03 2019 (r354382) @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2018 by Delphix. All rights reserved. + * Copyright (c) 2017, Intel Corporation. */ #ifndef _SYS_VDEV_IMPL_H @@ -146,6 +147,14 @@ struct vdev_queue { kmutex_t vq_lock; }; +typedef enum vdev_alloc_bias { + VDEV_BIAS_NONE, + VDEV_BIAS_LOG, /* dedicated to ZIL data (SLOG) */ + VDEV_BIAS_SPECIAL, /* dedicated to ddt, metadata, and small blks */ + VDEV_BIAS_DEDUP /* dedicated to dedup metadata */ +} vdev_alloc_bias_t; + + /* * On-disk indirect vdev state. * @@ -239,6 +248,7 @@ struct vdev { boolean_t vdev_ishole; /* is a hole in the namespace */ kmutex_t vdev_queue_lock; /* protects vdev_queue_depth */ uint64_t vdev_top_zap; + vdev_alloc_bias_t vdev_alloc_bias; /* metaslab allocation bias */ /* pool checkpoint related */ space_map_t *vdev_checkpoint_sm; /* contains reserved blocks */ Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zio.h ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zio.h Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zio.h Wed Nov 6 08:58:03 2019 (r354382) @@ -313,6 +313,7 @@ typedef struct zio_prop { boolean_t zp_dedup; boolean_t zp_dedup_verify; boolean_t zp_nopwrite; + uint32_t zp_zpl_smallblk; } zio_prop_t; typedef struct zio_cksum_report zio_cksum_report_t; @@ -433,6 +434,7 @@ struct zio { vdev_t *io_vd; void *io_vsd; const zio_vsd_ops_t *io_vsd_ops; + metaslab_class_t *io_metaslab_class; /* dva throttle class */ uint64_t io_offset; hrtime_t io_timestamp; Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/vdev.c ============================================================================== --- vendor-sys/illumos/dist/uts/common/fs/zfs/vdev.c Wed Nov 6 08:55:23 2019 (r354381) +++ vendor-sys/illumos/dist/uts/common/fs/zfs/vdev.c Wed Nov 6 08:58:03 2019 (r354382) @@ -26,6 +26,7 @@ * Copyright (c) 2014 Integros [integros.com] * Copyright 2016 Toomas Soome <tsoome@me.com> * Copyright 2017 Joyent, Inc. + * Copyright (c) 2017, Intel Corporation. */ #include <sys/zfs_context.h> @@ -192,6 +193,25 @@ vdev_getops(const char *type) return (ops); } +/* + * Derive the enumerated alloction bias from string input. + * String origin is either the per-vdev zap or zpool(1M). + */ +static vdev_alloc_bias_t +vdev_derive_alloc_bias(const char *bias) +{ + vdev_alloc_bias_t alloc_bias = VDEV_BIAS_NONE; + + if (strcmp(bias, VDEV_ALLOC_BIAS_LOG) == 0) + alloc_bias = VDEV_BIAS_LOG; + else if (strcmp(bias, VDEV_ALLOC_BIAS_SPECIAL) == 0) + alloc_bias = VDEV_BIAS_SPECIAL; + else if (strcmp(bias, VDEV_ALLOC_BIAS_DEDUP) == 0) + alloc_bias = VDEV_BIAS_DEDUP; + + return (alloc_bias); +} + /* ARGSUSED */ void vdev_default_xlate(vdev_t *vd, const range_seg_t *in, range_seg_t *res) @@ -515,6 +535,8 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vde uint64_t guid = 0, islog, nparity; vdev_t *vd; vdev_indirect_config_t *vic; + vdev_alloc_bias_t alloc_bias = VDEV_BIAS_NONE; + boolean_t top_level = (parent && !parent->vdev_parent); ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL); @@ -601,11 +623,32 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vde } ASSERT(nparity != -1ULL); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201911060858.xA68w3xb047144>