mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 11:19:32 +03:00
Switch KM_SLEEP to KM_PUSHPAGE
Under certain circumstances the following functions may be called in a context where KM_SLEEP is unsafe and can result in a deadlocked system. To avoid this problem the unconditional KM_SLEEPs are converted to KM_PUSHPAGEs. This will prevent them from attempting to initiate any I/O during direct reclaim. Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
parent
3e904f40b4
commit
cd5ca4b2f8
@ -62,6 +62,7 @@ typedef struct taskq_ent {
|
|||||||
*/
|
*/
|
||||||
#define TQ_SLEEP KM_SLEEP
|
#define TQ_SLEEP KM_SLEEP
|
||||||
#define TQ_NOSLEEP KM_NOSLEEP
|
#define TQ_NOSLEEP KM_NOSLEEP
|
||||||
|
#define TQ_PUSHPAGE KM_PUSHPAGE
|
||||||
#define TQ_NOQUEUE 0x01000000
|
#define TQ_NOQUEUE 0x01000000
|
||||||
#define TQ_NOALLOC 0x02000000
|
#define TQ_NOALLOC 0x02000000
|
||||||
#define TQ_NEW 0x04000000
|
#define TQ_NEW 0x04000000
|
||||||
|
@ -50,8 +50,6 @@ task_alloc(taskq_t *tq, uint_t flags)
|
|||||||
SENTRY;
|
SENTRY;
|
||||||
|
|
||||||
ASSERT(tq);
|
ASSERT(tq);
|
||||||
ASSERT(flags & (TQ_SLEEP | TQ_NOSLEEP)); /* One set */
|
|
||||||
ASSERT(!((flags & TQ_SLEEP) && (flags & TQ_NOSLEEP))); /* Not both */
|
|
||||||
ASSERT(spin_is_locked(&tq->tq_lock));
|
ASSERT(spin_is_locked(&tq->tq_lock));
|
||||||
retry:
|
retry:
|
||||||
/* Acquire taskq_ent_t's from free list if available */
|
/* Acquire taskq_ent_t's from free list if available */
|
||||||
@ -554,7 +552,7 @@ __taskq_create(const char *name, int nthreads, pri_t pri,
|
|||||||
nthreads = MAX((num_online_cpus() * nthreads) / 100, 1);
|
nthreads = MAX((num_online_cpus() * nthreads) / 100, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
tq = kmem_alloc(sizeof(*tq), KM_SLEEP);
|
tq = kmem_alloc(sizeof(*tq), KM_PUSHPAGE);
|
||||||
if (tq == NULL)
|
if (tq == NULL)
|
||||||
SRETURN(NULL);
|
SRETURN(NULL);
|
||||||
|
|
||||||
@ -580,12 +578,12 @@ __taskq_create(const char *name, int nthreads, pri_t pri,
|
|||||||
|
|
||||||
if (flags & TASKQ_PREPOPULATE)
|
if (flags & TASKQ_PREPOPULATE)
|
||||||
for (i = 0; i < minalloc; i++)
|
for (i = 0; i < minalloc; i++)
|
||||||
task_done(tq, task_alloc(tq, TQ_SLEEP | TQ_NEW));
|
task_done(tq, task_alloc(tq, TQ_PUSHPAGE | TQ_NEW));
|
||||||
|
|
||||||
spin_unlock_irqrestore(&tq->tq_lock, tq->tq_lock_flags);
|
spin_unlock_irqrestore(&tq->tq_lock, tq->tq_lock_flags);
|
||||||
|
|
||||||
for (i = 0; i < nthreads; i++) {
|
for (i = 0; i < nthreads; i++) {
|
||||||
tqt = kmem_alloc(sizeof(*tqt), KM_SLEEP);
|
tqt = kmem_alloc(sizeof(*tqt), KM_PUSHPAGE);
|
||||||
INIT_LIST_HEAD(&tqt->tqt_thread_list);
|
INIT_LIST_HEAD(&tqt->tqt_thread_list);
|
||||||
INIT_LIST_HEAD(&tqt->tqt_active_list);
|
INIT_LIST_HEAD(&tqt->tqt_active_list);
|
||||||
tqt->tqt_tq = tq;
|
tqt->tqt_tq = tq;
|
||||||
|
@ -98,14 +98,14 @@ __thread_create(caddr_t stk, size_t stksize, thread_func_t func,
|
|||||||
/* Variable stack size unsupported */
|
/* Variable stack size unsupported */
|
||||||
ASSERT(stk == NULL);
|
ASSERT(stk == NULL);
|
||||||
|
|
||||||
tp = kmem_alloc(sizeof(thread_priv_t), KM_SLEEP);
|
tp = kmem_alloc(sizeof(thread_priv_t), KM_PUSHPAGE);
|
||||||
if (tp == NULL)
|
if (tp == NULL)
|
||||||
SRETURN(NULL);
|
SRETURN(NULL);
|
||||||
|
|
||||||
tp->tp_magic = TP_MAGIC;
|
tp->tp_magic = TP_MAGIC;
|
||||||
tp->tp_name_size = strlen(name) + 1;
|
tp->tp_name_size = strlen(name) + 1;
|
||||||
|
|
||||||
tp->tp_name = kmem_alloc(tp->tp_name_size, KM_SLEEP);
|
tp->tp_name = kmem_alloc(tp->tp_name_size, KM_PUSHPAGE);
|
||||||
if (tp->tp_name == NULL) {
|
if (tp->tp_name == NULL) {
|
||||||
kmem_free(tp, sizeof(thread_priv_t));
|
kmem_free(tp, sizeof(thread_priv_t));
|
||||||
SRETURN(NULL);
|
SRETURN(NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user