summaryrefslogtreecommitdiffstats
path: root/module/zfs/dmu_objset.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/dmu_objset.c')
-rw-r--r--module/zfs/dmu_objset.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c
index add4417ac..47e1b2d08 100644
--- a/module/zfs/dmu_objset.c
+++ b/module/zfs/dmu_objset.c
@@ -1927,6 +1927,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;
@@ -1950,7 +1951,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;
@@ -1975,9 +1981,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);
+ 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);
@@ -2020,16 +2028,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);
@@ -2044,6 +2061,8 @@ out:
mutex_exit(dcp->dc_error_lock);
}
+ if (dcp->dc_ddname != NULL)
+ spa_strfree(dcp->dc_ddname);
kmem_free(dcp, sizeof (*dcp));
}
@@ -2088,6 +2107,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;