Skip to content

Commit 55d85d5

Browse files
grwilsonbehlendorf
authored andcommitted
Illumos #3329, #3330, #3331, #3335
3329 spa_sync() spends 10-20% of its time in spa_free_sync_cb() 3330 space_seg_t should have its own kmem_cache 3331 deferred frees should happen after sync_pass 1 3335 make SYNC_PASS_* constants tunable Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Matt Ahrens <matthew.ahrens@delphix.com> Reviewed by: Christopher Siden <chris.siden@delphix.com> Reviewed by: Eric Schrock <eric.schrock@delphix.com> Reviewed by: Richard Lowe <richlowe@richlowe.net> Reviewed by: Dan McDonald <danmcd@nexenta.com> Approved by: Eric Schrock <eric.schrock@delphix.com> References: illumos/illumos-gate@01f55e4 https://www.illumos.org/issues/3329 https://www.illumos.org/issues/3330 https://www.illumos.org/issues/3331 https://www.illumos.org/issues/3335 Ported-by: Brian Behlendorf <behlendorf1@llnl.gov>
1 parent 5853fe7 commit 55d85d5

File tree

9 files changed

+75
-22
lines changed

9 files changed

+75
-22
lines changed

include/sys/metaslab_impl.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
/*
2222
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2323
* Use is subject to license terms.
24-
* Copyright (c) 2011 by Delphix. All rights reserved.
24+
*/
25+
26+
/*
27+
* Copyright (c) 2012 by Delphix. All rights reserved.
2528
*/
2629

2730
#ifndef _SYS_METASLAB_IMPL_H

include/sys/spa.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -486,13 +486,7 @@ extern int spa_scan_stop(spa_t *spa);
486486
extern void spa_sync(spa_t *spa, uint64_t txg); /* only for DMU use */
487487
extern void spa_sync_allpools(void);
488488

489-
/*
490-
* DEFERRED_FREE must be large enough that regular blocks are not
491-
* deferred. XXX so can't we change it back to 1?
492-
*/
493-
#define SYNC_PASS_DEFERRED_FREE 2 /* defer frees after this pass */
494-
#define SYNC_PASS_DONT_COMPRESS 4 /* don't compress after this pass */
495-
#define SYNC_PASS_REWRITE 1 /* rewrite new bps after this pass */
489+
extern int zfs_sync_pass_deferred_free;
496490

497491
/* spa namespace global mutex */
498492
extern kmutex_t spa_namespace_lock;

include/sys/space_map.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
* Use is subject to license terms.
2424
*/
2525

26+
/*
27+
* Copyright (c) 2012 by Delphix. All rights reserved.
28+
*/
29+
2630
#ifndef _SYS_SPACE_MAP_H
2731
#define _SYS_SPACE_MAP_H
2832

@@ -136,6 +140,8 @@ struct space_map_ops {
136140

137141
typedef void space_map_func_t(space_map_t *sm, uint64_t start, uint64_t size);
138142

143+
extern void space_map_init(void);
144+
extern void space_map_fini(void);
139145
extern void space_map_create(space_map_t *sm, uint64_t start, uint64_t size,
140146
uint8_t shift, kmutex_t *lp);
141147
extern void space_map_destroy(space_map_t *sm);

include/sys/zio_impl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
* Use is subject to license terms.
2424
*/
2525

26+
/*
27+
* Copyright (c) 2012 by Delphix. All rights reserved.
28+
*/
29+
2630
#ifndef _ZIO_IMPL_H
2731
#define _ZIO_IMPL_H
2832

@@ -143,6 +147,7 @@ enum zio_stage {
143147
#define ZIO_FREE_PIPELINE \
144148
(ZIO_INTERLOCK_STAGES | \
145149
ZIO_STAGE_FREE_BP_INIT | \
150+
ZIO_STAGE_ISSUE_ASYNC | \
146151
ZIO_STAGE_DVA_FREE)
147152

148153
#define ZIO_DDT_FREE_PIPELINE \

module/zfs/metaslab.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -899,8 +899,9 @@ metaslab_activate(metaslab_t *msp, uint64_t activation_weight)
899899
if ((msp->ms_weight & METASLAB_ACTIVE_MASK) == 0) {
900900
space_map_load_wait(sm);
901901
if (!sm->sm_loaded) {
902-
int error = space_map_load(sm, sm_ops, SM_FREE,
903-
&msp->ms_smo,
902+
space_map_obj_t *smo = &msp->ms_smo;
903+
904+
int error = space_map_load(sm, sm_ops, SM_FREE, smo,
904905
spa_meta_objset(msp->ms_group->mg_vd->vdev_spa));
905906
if (error) {
906907
metaslab_group_sort(msp->ms_group, msp, 0);

module/zfs/spa.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6078,7 +6078,7 @@ spa_sync(spa_t *spa, uint64_t txg)
60786078
spa_errlog_sync(spa, txg);
60796079
dsl_pool_sync(dp, txg);
60806080

6081-
if (pass <= SYNC_PASS_DEFERRED_FREE) {
6081+
if (pass < zfs_sync_pass_deferred_free) {
60826082
zio_t *zio = zio_root(spa, NULL, NULL, 0);
60836083
bplist_iterate(free_bpl, spa_free_sync_cb,
60846084
zio, tx);

module/zfs/spa_misc.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,7 @@ spa_init(int mode)
16331633
fm_init();
16341634
refcount_init();
16351635
unique_init();
1636+
space_map_init();
16361637
zio_init();
16371638
dmu_init();
16381639
zil_init();
@@ -1655,6 +1656,7 @@ spa_fini(void)
16551656
zil_fini();
16561657
dmu_fini();
16571658
zio_fini();
1659+
space_map_fini();
16581660
unique_fini();
16591661
refcount_fini();
16601662
fm_fini();

module/zfs/space_map.c

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,23 @@
2929
#include <sys/zio.h>
3030
#include <sys/space_map.h>
3131

32+
static kmem_cache_t *space_seg_cache;
33+
34+
void
35+
space_map_init(void)
36+
{
37+
ASSERT(space_seg_cache == NULL);
38+
space_seg_cache = kmem_cache_create("space_seg_cache",
39+
sizeof (space_seg_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
40+
}
41+
42+
void
43+
space_map_fini(void)
44+
{
45+
kmem_cache_destroy(space_seg_cache);
46+
space_seg_cache = NULL;
47+
}
48+
3249
/*
3350
* Space map routines.
3451
* NOTE: caller is responsible for all locking.
@@ -121,7 +138,7 @@ space_map_add(space_map_t *sm, uint64_t start, uint64_t size)
121138
avl_remove(sm->sm_pp_root, ss_after);
122139
}
123140
ss_after->ss_start = ss_before->ss_start;
124-
kmem_free(ss_before, sizeof (*ss_before));
141+
kmem_cache_free(space_seg_cache, ss_before);
125142
ss = ss_after;
126143
} else if (merge_before) {
127144
ss_before->ss_end = end;
@@ -134,7 +151,7 @@ space_map_add(space_map_t *sm, uint64_t start, uint64_t size)
134151
avl_remove(sm->sm_pp_root, ss_after);
135152
ss = ss_after;
136153
} else {
137-
ss = kmem_alloc(sizeof (*ss), KM_PUSHPAGE);
154+
ss = kmem_cache_alloc(space_seg_cache, KM_PUSHPAGE);
138155
ss->ss_start = start;
139156
ss->ss_end = end;
140157
avl_insert(&sm->sm_root, ss, where);
@@ -181,7 +198,7 @@ space_map_remove(space_map_t *sm, uint64_t start, uint64_t size)
181198
avl_remove(sm->sm_pp_root, ss);
182199

183200
if (left_over && right_over) {
184-
newseg = kmem_alloc(sizeof (*newseg), KM_PUSHPAGE);
201+
newseg = kmem_cache_alloc(space_seg_cache, KM_PUSHPAGE);
185202
newseg->ss_start = end;
186203
newseg->ss_end = ss->ss_end;
187204
ss->ss_end = start;
@@ -194,7 +211,7 @@ space_map_remove(space_map_t *sm, uint64_t start, uint64_t size)
194211
ss->ss_start = end;
195212
} else {
196213
avl_remove(&sm->sm_root, ss);
197-
kmem_free(ss, sizeof (*ss));
214+
kmem_cache_free(space_seg_cache, ss);
198215
ss = NULL;
199216
}
200217

@@ -234,7 +251,7 @@ space_map_vacate(space_map_t *sm, space_map_func_t *func, space_map_t *mdest)
234251
while ((ss = avl_destroy_nodes(&sm->sm_root, &cookie)) != NULL) {
235252
if (func != NULL)
236253
func(mdest, ss->ss_start, ss->ss_end - ss->ss_start);
237-
kmem_free(ss, sizeof (*ss));
254+
kmem_cache_free(space_seg_cache, ss);
238255
}
239256
sm->sm_space = 0;
240257
}
@@ -406,7 +423,7 @@ space_map_sync(space_map_t *sm, uint8_t maptype,
406423
spa_t *spa = dmu_objset_spa(os);
407424
void *cookie = NULL;
408425
space_seg_t *ss;
409-
uint64_t bufsize, start, size, run_len;
426+
uint64_t bufsize, start, size, run_len, delta, sm_space;
410427
uint64_t *entry, *entry_map, *entry_map_end;
411428

412429
ASSERT(MUTEX_HELD(sm->sm_lock));
@@ -435,11 +452,13 @@ space_map_sync(space_map_t *sm, uint8_t maptype,
435452
SM_DEBUG_SYNCPASS_ENCODE(spa_sync_pass(spa)) |
436453
SM_DEBUG_TXG_ENCODE(dmu_tx_get_txg(tx));
437454

455+
delta = 0;
456+
sm_space = sm->sm_space;
438457
while ((ss = avl_destroy_nodes(&sm->sm_root, &cookie)) != NULL) {
439458
size = ss->ss_end - ss->ss_start;
440459
start = (ss->ss_start - sm->sm_start) >> sm->sm_shift;
441460

442-
sm->sm_space -= size;
461+
delta += size;
443462
size >>= sm->sm_shift;
444463

445464
while (size) {
@@ -461,7 +480,7 @@ space_map_sync(space_map_t *sm, uint8_t maptype,
461480
start += run_len;
462481
size -= run_len;
463482
}
464-
kmem_free(ss, sizeof (*ss));
483+
kmem_cache_free(space_seg_cache, ss);
465484
}
466485

467486
if (entry != entry_map) {
@@ -473,8 +492,15 @@ space_map_sync(space_map_t *sm, uint8_t maptype,
473492
smo->smo_objsize += size;
474493
}
475494

495+
/*
496+
* Ensure that the space_map's accounting wasn't changed
497+
* while we were in the middle of writing it out.
498+
*/
499+
VERIFY3U(sm->sm_space, ==, sm_space);
500+
476501
zio_buf_free(entry_map, bufsize);
477502

503+
sm->sm_space -= delta;
478504
VERIFY3U(sm->sm_space, ==, 0);
479505
}
480506

module/zfs/zio.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,22 @@ extern vmem_t *zio_alloc_arena;
8484
#endif
8585
extern int zfs_mg_alloc_failures;
8686

87+
/*
88+
* The following actions directly effect the spa's sync-to-convergence logic.
89+
* The values below define the sync pass when we start performing the action.
90+
* Care should be taken when changing these values as they directly impact
91+
* spa_sync() performance. Tuning these values may introduce subtle performance
92+
* pathologies and should only be done in the context of performance analysis.
93+
* These tunables will eventually be removed and replaced with #defines once
94+
* enough analysis has been done to determine optimal values.
95+
*
96+
* The 'zfs_sync_pass_deferred_free' pass must be greater than 1 to ensure that
97+
* regular blocks are not deferred.
98+
*/
99+
int zfs_sync_pass_deferred_free = 2; /* defer frees starting in this pass */
100+
int zfs_sync_pass_dont_compress = 5; /* don't compress starting in this pass */
101+
int zfs_sync_pass_rewrite = 2; /* rewrite new bps starting in this pass */
102+
87103
/*
88104
* An allocating zio is one that either currently has the DVA allocate
89105
* stage set or will have it later in its lifetime.
@@ -771,7 +787,7 @@ zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
771787

772788
ASSERT(!BP_IS_HOLE(bp));
773789
ASSERT(spa_syncing_txg(spa) == txg);
774-
ASSERT(spa_sync_pass(spa) <= SYNC_PASS_DEFERRED_FREE);
790+
ASSERT(spa_sync_pass(spa) < zfs_sync_pass_deferred_free);
775791

776792
zio = zio_create(pio, spa, txg, bp, NULL, BP_GET_PSIZE(bp),
777793
NULL, NULL, ZIO_TYPE_FREE, ZIO_PRIORITY_FREE, flags,
@@ -1068,7 +1084,7 @@ zio_write_bp_init(zio_t *zio)
10681084
ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
10691085
ASSERT(!BP_GET_DEDUP(bp));
10701086

1071-
if (pass > SYNC_PASS_DONT_COMPRESS)
1087+
if (pass >= zfs_sync_pass_dont_compress)
10721088
compress = ZIO_COMPRESS_OFF;
10731089

10741090
/* Make sure someone doesn't change their mind on overwrites */
@@ -1097,7 +1113,7 @@ zio_write_bp_init(zio_t *zio)
10971113
* There should only be a handful of blocks after pass 1 in any case.
10981114
*/
10991115
if (bp->blk_birth == zio->io_txg && BP_GET_PSIZE(bp) == psize &&
1100-
pass > SYNC_PASS_REWRITE) {
1116+
pass >= zfs_sync_pass_rewrite) {
11011117
enum zio_stage gang_stages = zio->io_pipeline & ZIO_GANG_STAGES;
11021118
ASSERT(psize != 0);
11031119
zio->io_pipeline = ZIO_REWRITE_PIPELINE | gang_stages;

0 commit comments

Comments
 (0)