Skip to content

Commit e197bb2

Browse files
authored
Optionally skip zil_close during zvol_create_minor_impl
If there were no zil entries to replay, skip zil_close. zil_close waits for a transaction to sync. That can take several seconds, for example during pool import of a resilvering pool. Skipping zil_close can cut the time for "zpool import" from 2 hours to 45 seconds on a resilvering pool with a thousand zvols. Reviewed-by: Richard Yao <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Sponsored-by: Axcient Closes #13999 Closes #14015
1 parent f224edd commit e197bb2

File tree

4 files changed

+22
-13
lines changed

4 files changed

+22
-13
lines changed

include/sys/zil.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -539,10 +539,10 @@ extern zilog_t *zil_open(objset_t *os, zil_get_data_t *get_data,
539539
zil_sums_t *zil_sums);
540540
extern void zil_close(zilog_t *zilog);
541541

542-
extern void zil_replay(objset_t *os, void *arg,
542+
extern boolean_t zil_replay(objset_t *os, void *arg,
543543
zil_replay_func_t *const replay_func[TX_MAX_TYPE]);
544544
extern boolean_t zil_replaying(zilog_t *zilog, dmu_tx_t *tx);
545-
extern void zil_destroy(zilog_t *zilog, boolean_t keep_first);
545+
extern boolean_t zil_destroy(zilog_t *zilog, boolean_t keep_first);
546546
extern void zil_destroy_sync(zilog_t *zilog, dmu_tx_t *tx);
547547

548548
extern itx_t *zil_itx_create(uint64_t txtype, size_t lrsize);

module/os/freebsd/zfs/zvol_os.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,6 +1386,7 @@ zvol_os_create_minor(const char *name)
13861386
uint64_t volsize;
13871387
uint64_t volmode, hash;
13881388
int error;
1389+
bool replayed_zil = B_FALSE;
13891390

13901391
ZFS_LOG(1, "Creating ZVOL %s...", name);
13911392
hash = zvol_name_hash(name);
@@ -1490,11 +1491,12 @@ zvol_os_create_minor(const char *name)
14901491
zv->zv_zilog = zil_open(os, zvol_get_data, &zv->zv_kstat.dk_zil_sums);
14911492
if (spa_writeable(dmu_objset_spa(os))) {
14921493
if (zil_replay_disable)
1493-
zil_destroy(zv->zv_zilog, B_FALSE);
1494+
replayed_zil = zil_destroy(zv->zv_zilog, B_FALSE);
14941495
else
1495-
zil_replay(os, zv, zvol_replay_vector);
1496+
replayed_zil = zil_replay(os, zv, zvol_replay_vector);
14961497
}
1497-
zil_close(zv->zv_zilog);
1498+
if (replayed_zil)
1499+
zil_close(zv->zv_zilog);
14981500
zv->zv_zilog = NULL;
14991501

15001502
/* TODO: prefetch for geom tasting */

module/os/linux/zfs/zvol_os.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,7 @@ zvol_os_create_minor(const char *name)
12791279
int error = 0;
12801280
int idx;
12811281
uint64_t hash = zvol_name_hash(name);
1282+
bool replayed_zil = B_FALSE;
12821283

12831284
if (zvol_inhibit_dev)
12841285
return (0);
@@ -1420,11 +1421,12 @@ zvol_os_create_minor(const char *name)
14201421
zv->zv_zilog = zil_open(os, zvol_get_data, &zv->zv_kstat.dk_zil_sums);
14211422
if (spa_writeable(dmu_objset_spa(os))) {
14221423
if (zil_replay_disable)
1423-
zil_destroy(zv->zv_zilog, B_FALSE);
1424+
replayed_zil = zil_destroy(zv->zv_zilog, B_FALSE);
14241425
else
1425-
zil_replay(os, zv, zvol_replay_vector);
1426+
replayed_zil = zil_replay(os, zv, zvol_replay_vector);
14261427
}
1427-
zil_close(zv->zv_zilog);
1428+
if (replayed_zil)
1429+
zil_close(zv->zv_zilog);
14281430
zv->zv_zilog = NULL;
14291431

14301432
/*

module/zfs/zil.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -887,8 +887,9 @@ zil_create(zilog_t *zilog)
887887
* txg_wait_synced() here either when keep_first is set, because both
888888
* zil_create() and zil_destroy() will wait for any in-progress destroys
889889
* to complete.
890+
* Return B_TRUE if there were any entries to replay.
890891
*/
891-
void
892+
boolean_t
892893
zil_destroy(zilog_t *zilog, boolean_t keep_first)
893894
{
894895
const zil_header_t *zh = zilog->zl_header;
@@ -904,7 +905,7 @@ zil_destroy(zilog_t *zilog, boolean_t keep_first)
904905
zilog->zl_old_header = *zh; /* debugging aid */
905906

906907
if (BP_IS_HOLE(&zh->zh_log))
907-
return;
908+
return (B_FALSE);
908909

909910
tx = dmu_tx_create(zilog->zl_os);
910911
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
@@ -937,6 +938,8 @@ zil_destroy(zilog_t *zilog, boolean_t keep_first)
937938
mutex_exit(&zilog->zl_lock);
938939

939940
dmu_tx_commit(tx);
941+
942+
return (B_TRUE);
940943
}
941944

942945
void
@@ -3849,8 +3852,9 @@ zil_incr_blks(zilog_t *zilog, const blkptr_t *bp, void *arg, uint64_t claim_txg)
38493852

38503853
/*
38513854
* If this dataset has a non-empty intent log, replay it and destroy it.
3855+
* Return B_TRUE if there were any entries to replay.
38523856
*/
3853-
void
3857+
boolean_t
38543858
zil_replay(objset_t *os, void *arg,
38553859
zil_replay_func_t *const replay_func[TX_MAX_TYPE])
38563860
{
@@ -3859,8 +3863,7 @@ zil_replay(objset_t *os, void *arg,
38593863
zil_replay_arg_t zr;
38603864

38613865
if ((zh->zh_flags & ZIL_REPLAY_NEEDED) == 0) {
3862-
zil_destroy(zilog, B_TRUE);
3863-
return;
3866+
return (zil_destroy(zilog, B_TRUE));
38643867
}
38653868

38663869
zr.zr_replay = replay_func;
@@ -3883,6 +3886,8 @@ zil_replay(objset_t *os, void *arg,
38833886
zil_destroy(zilog, B_FALSE);
38843887
txg_wait_synced(zilog->zl_dmu_pool, zilog->zl_destroy_txg);
38853888
zilog->zl_replay = B_FALSE;
3889+
3890+
return (B_TRUE);
38863891
}
38873892

38883893
boolean_t

0 commit comments

Comments
 (0)