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:
Brian Behlendorf 2012-08-23 15:36:28 -07:00
parent 3e904f40b4
commit cd5ca4b2f8
3 changed files with 6 additions and 7 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);