summaryrefslogtreecommitdiffstats
path: root/sys/cddl
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2017-03-23 07:57:42 +0000
committeravg <avg@FreeBSD.org>2017-03-23 07:57:42 +0000
commite079d85984993337144c8d5e90358d16e9521dc6 (patch)
treee5031ea5df086e449f46a146099bf19f4d1a4320 /sys/cddl
parent2cb842c2751b8391dddbd62eac9b234f1bdba69f (diff)
downloadFreeBSD-src-e079d85984993337144c8d5e90358d16e9521dc6.zip
FreeBSD-src-e079d85984993337144c8d5e90358d16e9521dc6.tar.gz
MFC r314912: MFV r314910: 7843 get_clones_stat() is suboptimal for lots of clones
Diffstat (limited to 'sys/cddl')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
index 5053bdf..4193f76 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
@@ -1766,11 +1766,22 @@ get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv)
zap_cursor_t zc;
zap_attribute_t za;
nvlist_t *propval = fnvlist_alloc();
- nvlist_t *val = fnvlist_alloc();
+ nvlist_t *val;
ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool));
/*
+ * We use nvlist_alloc() instead of fnvlist_alloc() because the
+ * latter would allocate the list with NV_UNIQUE_NAME flag.
+ * As a result, every time a clone name is appended to the list
+ * it would be (linearly) searched for for a duplicate name.
+ * We already know that all clone names must be unique and we
+ * want avoid the quadratic complexity of double-checking that
+ * because we can have a large number of clones.
+ */
+ VERIFY0(nvlist_alloc(&val, 0, KM_SLEEP));
+
+ /*
* There may be missing entries in ds_next_clones_obj
* due to a bug in a previous version of the code.
* Only trust it if it has the right number of entries.
OpenPOWER on IntegriCloud