Mercurial > illumos > illumos-gate
changeset 3778:7ea2cf578078
6452589 zl_lock still held excessively long
author | johansen |
---|---|
date | Thu, 08 Mar 2007 15:03:17 -0800 |
parents | 011706b8765c |
children | f34a44686f8b |
files | usr/src/uts/common/fs/zfs/zil.c |
diffstat | 1 files changed, 19 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/zil.c Thu Mar 08 06:23:41 2007 -0800 +++ b/usr/src/uts/common/fs/zfs/zil.c Thu Mar 08 15:03:17 2007 -0800 @@ -880,23 +880,39 @@ { uint64_t synced_txg = spa_last_synced_txg(zilog->zl_spa); uint64_t freeze_txg = spa_freeze_txg(zilog->zl_spa); + list_t clean_list; itx_t *itx; + list_create(&clean_list, sizeof (itx_t), offsetof(itx_t, itx_node)); + mutex_enter(&zilog->zl_lock); /* wait for a log writer to finish walking list */ while (zilog->zl_writer) { cv_wait(&zilog->zl_cv_writer, &zilog->zl_lock); } - /* no need to set zl_writer as we never drop zl_lock */ + + /* + * Move the sync'd log transactions to a separate list so we can call + * kmem_free without holding the zl_lock. + * + * There is no need to set zl_writer as we don't drop zl_lock here + */ while ((itx = list_head(&zilog->zl_itx_list)) != NULL && itx->itx_lr.lrc_txg <= MIN(synced_txg, freeze_txg)) { list_remove(&zilog->zl_itx_list, itx); zilog->zl_itx_list_sz -= itx->itx_lr.lrc_reclen; + list_insert_tail(&clean_list, itx); + } + cv_broadcast(&zilog->zl_cv_writer); + mutex_exit(&zilog->zl_lock); + + /* destroy sync'd log transactions */ + while ((itx = list_head(&clean_list)) != NULL) { + list_remove(&clean_list, itx); kmem_free(itx, offsetof(itx_t, itx_lr) + itx->itx_lr.lrc_reclen); } - cv_broadcast(&zilog->zl_cv_writer); - mutex_exit(&zilog->zl_lock); + list_destroy(&clean_list); } /*