summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Ahrens <mahrens@delphix.com>2016-11-29 13:22:41 -0800
committerMatthew Ahrens <mahrens@delphix.com>2016-11-30 12:51:54 -0800
commit7588687e6ba67c47bf7c9805086dec4a97fcac7b (patch)
tree04f13ee7f535b6b5f5c9fef0861113d53a9981ea
parent25b5cdf490cfb7bdfcb7a5e9d28355fdd92cba88 (diff)
downloadillumos-joyent-7588687e6ba67c47bf7c9805086dec4a97fcac7b.tar.gz
7606 dmu_objset_find_dp() takes a long time while importing pool
Reviewed by: Steve Gonczi <steve.gonczi@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Prashanth Sreenivasa <prashksp@gmail.com> Approved by: Gordon Ross <gordon.w.ross@gmail.com>
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_objset.c29
1 files 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;