From 7588687e6ba67c47bf7c9805086dec4a97fcac7b Mon Sep 17 00:00:00 2001 From: Matthew Ahrens Date: Tue, 29 Nov 2016 13:22:41 -0800 Subject: [PATCH] 7606 dmu_objset_find_dp() takes a long time while importing pool Reviewed by: Steve Gonczi Reviewed by: George Wilson Reviewed by: Prashanth Sreenivasa Approved by: Gordon Ross --- usr/src/uts/common/fs/zfs/dmu_objset.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/usr/src/uts/common/fs/zfs/dmu_objset.c b/usr/src/uts/common/fs/zfs/dmu_objset.c index 3ed68f7133..b71a43f7b5 100644 --- a/usr/src/uts/common/fs/zfs/dmu_objset.c +++ b/usr/src/uts/common/fs/zfs/dmu_objset.c @@ -1705,6 +1705,7 @@ typedef struct dmu_objset_find_ctx { taskq_t *dc_tq; dsl_pool_t *dc_dp; uint64_t dc_ddobj; + char *dc_ddname; /* last component of ddobj's name */ int (*dc_func)(dsl_pool_t *, dsl_dataset_t *, void *); void *dc_arg; int dc_flags; @@ -1716,7 +1717,6 @@ static void dmu_objset_find_dp_impl(dmu_objset_find_ctx_t *dcp) { dsl_pool_t *dp = dcp->dc_dp; - dmu_objset_find_ctx_t *child_dcp; dsl_dir_t *dd; dsl_dataset_t *ds; zap_cursor_t zc; @@ -1728,7 +1728,12 @@ dmu_objset_find_dp_impl(dmu_objset_find_ctx_t *dcp) if (*dcp->dc_error != 0) goto out; - err = dsl_dir_hold_obj(dp, dcp->dc_ddobj, NULL, FTAG, &dd); + /* + * Note: passing the name (dc_ddname) here is optional, but it + * improves performance because we don't need to call + * zap_value_search() to determine the name. + */ + err = dsl_dir_hold_obj(dp, dcp->dc_ddobj, dcp->dc_ddname, FTAG, &dd); if (err != 0) goto out; @@ -1753,9 +1758,11 @@ dmu_objset_find_dp_impl(dmu_objset_find_ctx_t *dcp) sizeof (uint64_t)); ASSERT3U(attr->za_num_integers, ==, 1); - child_dcp = kmem_alloc(sizeof (*child_dcp), KM_SLEEP); + dmu_objset_find_ctx_t *child_dcp = + kmem_alloc(sizeof (*child_dcp), KM_SLEEP); *child_dcp = *dcp; child_dcp->dc_ddobj = attr->za_first_integer; + child_dcp->dc_ddname = spa_strdup(attr->za_name); if (dcp->dc_tq != NULL) (void) taskq_dispatch(dcp->dc_tq, dmu_objset_find_dp_cb, child_dcp, TQ_SLEEP); @@ -1798,16 +1805,25 @@ dmu_objset_find_dp_impl(dmu_objset_find_ctx_t *dcp) } } - dsl_dir_rele(dd, FTAG); kmem_free(attr, sizeof (zap_attribute_t)); - if (err != 0) + if (err != 0) { + dsl_dir_rele(dd, FTAG); goto out; + } /* * Apply to self. */ err = dsl_dataset_hold_obj(dp, thisobj, FTAG, &ds); + + /* + * Note: we hold the dir while calling dsl_dataset_hold_obj() so + * that the dir will remain cached, and we won't have to re-instantiate + * it (which could be expensive due to finding its name via + * zap_value_search()). + */ + dsl_dir_rele(dd, FTAG); if (err != 0) goto out; err = dcp->dc_func(dp, ds, dcp->dc_arg); @@ -1822,6 +1838,8 @@ out: mutex_exit(dcp->dc_error_lock); } + if (dcp->dc_ddname != NULL) + spa_strfree(dcp->dc_ddname); kmem_free(dcp, sizeof (*dcp)); } @@ -1866,6 +1884,7 @@ dmu_objset_find_dp(dsl_pool_t *dp, uint64_t ddobj, dcp->dc_tq = NULL; dcp->dc_dp = dp; dcp->dc_ddobj = ddobj; + dcp->dc_ddname = NULL; dcp->dc_func = func; dcp->dc_arg = arg; dcp->dc_flags = flags; -- 2.11.4.GIT