X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Ftxg.c;h=340c42ae84a395333d314507616ec4eb6deba848;hb=e2448b0e62f73f8b9574d74c5b327707b67b703a;hp=9b308ca4e71a1e789fc8193d7e690dd489e3fed5;hpb=572e285762521df27fe5b026f409ba1a21abb7ac;p=zfs.git diff --git a/module/zfs/txg.c b/module/zfs/txg.c index 9b308ca..340c42a 100644 --- a/module/zfs/txg.c +++ b/module/zfs/txg.c @@ -49,7 +49,7 @@ txg_init(dsl_pool_t *dp, uint64_t txg) int c; bzero(tx, sizeof (tx_state_t)); - tx->tx_cpu = kmem_zalloc(max_ncpus * sizeof (tx_cpu_t), KM_SLEEP); + tx->tx_cpu = vmem_zalloc(max_ncpus * sizeof (tx_cpu_t), KM_SLEEP); for (c = 0; c < max_ncpus; c++) { int i; @@ -107,7 +107,7 @@ txg_fini(dsl_pool_t *dp) if (tx->tx_commit_cb_taskq != NULL) taskq_destroy(tx->tx_commit_cb_taskq); - kmem_free(tx->tx_cpu, max_ncpus * sizeof (tx_cpu_t)); + vmem_free(tx->tx_cpu, max_ncpus * sizeof (tx_cpu_t)); bzero(tx, sizeof (tx_state_t)); } @@ -166,10 +166,10 @@ txg_thread_wait(tx_state_t *tx, callb_cpr_t *cpr, kcondvar_t *cv, uint64_t time) CALLB_CPR_SAFE_BEGIN(cpr); if (time) - (void) cv_timedwait(cv, &tx->tx_sync_lock, + (void) cv_timedwait_interruptible(cv, &tx->tx_sync_lock, ddi_get_lbolt() + time); else - cv_wait(cv, &tx->tx_sync_lock); + cv_wait_interruptible(cv, &tx->tx_sync_lock); CALLB_CPR_SAFE_END(cpr, &tx->tx_sync_lock); } @@ -335,21 +335,35 @@ txg_dispatch_callbacks(dsl_pool_t *dp, uint64_t txg) * Commit callback taskq hasn't been created yet. */ tx->tx_commit_cb_taskq = taskq_create("tx_commit_cb", - max_ncpus, minclsyspri, max_ncpus, max_ncpus * 2, - TASKQ_PREPOPULATE); + 100, minclsyspri, max_ncpus, INT_MAX, + TASKQ_THREADS_CPU_PCT | TASKQ_PREPOPULATE); } cb_list = kmem_alloc(sizeof (list_t), KM_SLEEP); list_create(cb_list, sizeof (dmu_tx_callback_t), offsetof(dmu_tx_callback_t, dcb_node)); - list_move_tail(&tc->tc_callbacks[g], cb_list); + list_move_tail(cb_list, &tc->tc_callbacks[g]); (void) taskq_dispatch(tx->tx_commit_cb_taskq, (task_func_t *) txg_do_callbacks, cb_list, TQ_SLEEP); } } +/* + * Wait for pending commit callbacks of already-synced transactions to finish + * processing. + * Calling this function from within a commit callback will deadlock. + */ +void +txg_wait_callbacks(dsl_pool_t *dp) +{ + tx_state_t *tx = &dp->dp_tx; + + if (tx->tx_commit_cb_taskq != NULL) + taskq_wait(tx->tx_commit_cb_taskq); +} + static void txg_sync_thread(dsl_pool_t *dp) { @@ -358,6 +372,19 @@ txg_sync_thread(dsl_pool_t *dp) callb_cpr_t cpr; uint64_t start, delta; +#ifdef _KERNEL + /* + * Disable the normal reclaim path for the txg_sync thread. This + * ensures the thread will never enter dmu_tx_assign() which can + * otherwise occur due to direct reclaim. If this is allowed to + * happen the system can deadlock. Direct reclaim call path: + * + * ->shrink_icache_memory->prune_icache->dispose_list-> + * clear_inode->zpl_clear_inode->zfs_inactive->dmu_tx_assign + */ + current->flags |= PF_MEMALLOC; +#endif /* _KERNEL */ + txg_thread_enter(tx, &cpr); start = delta = 0; @@ -722,3 +749,20 @@ txg_list_next(txg_list_t *tl, void *p, uint64_t txg) return (tn == NULL ? NULL : (char *)tn - tl->tl_offset); } + +#if defined(_KERNEL) && defined(HAVE_SPL) +EXPORT_SYMBOL(txg_init); +EXPORT_SYMBOL(txg_fini); +EXPORT_SYMBOL(txg_sync_start); +EXPORT_SYMBOL(txg_sync_stop); +EXPORT_SYMBOL(txg_hold_open); +EXPORT_SYMBOL(txg_rele_to_quiesce); +EXPORT_SYMBOL(txg_rele_to_sync); +EXPORT_SYMBOL(txg_register_callbacks); +EXPORT_SYMBOL(txg_delay); +EXPORT_SYMBOL(txg_wait_synced); +EXPORT_SYMBOL(txg_wait_open); +EXPORT_SYMBOL(txg_wait_callbacks); +EXPORT_SYMBOL(txg_stalled); +EXPORT_SYMBOL(txg_sync_waiting); +#endif