MFV 316895
7606 dmu_objset_find_dp() takes a long time while importing pool
illumos/illumos-gate@7588687e6b
7588687e6b
https://www.illumos.org/issues/7606
When importing a pool with a large number of filesystems within the same
parent filesystem, we see that dmu_objset_find_dp() takes a long time.
It is called from 3 places: spa_check_logs(), spa_ld_claim_log_blocks(),
and spa_load_verify().
There are several ways to improve performance here:
1. We don't really need to do spa_check_logs() or
spa_ld_claim_log_blocks() if the pool was closed cleanly.
2. spa_load_verify() uses dmu_objset_find_dp() to check that no
datasets have too long of names.
3. dmu_objset_find_dp() is slow because it's doing
zap_value_search() (which is O(N sibling datasets)) to determine
the name of each dsl_dir when it's opened. In this case we
actually know the name when we are opening it, so we can provide
it and avoid the lookup.
This change implements fix #3 from the above list; i.e. make
dmu_objset_find_dp() provide the name of the dataset so that we don't
have to search for it.
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>
Author: Matthew Ahrens <mahrens@delphix.com>
This commit is contained in:
parent
66577f8a50
commit
4c97ff8bf5
@ -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 @@ dmu_objset_find_dp_impl(dmu_objset_find_ctx_t *dcp)
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user