mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-27 03:19:35 +03:00
splat atomic:64-bit: Create thread outside spin lock
The Fedora 3.6 debug kernel identified the following issue where we create a thread under a spin lock. This isn't safe because sleeping could result in a deadlock. Therefore the lock is changed to a mutex so it's safe to sleep. BUG: sleeping function called from invalid context at mm/slub.c:930 in_atomic(): 1, irqs_disabled(): 0, pid: 10583, name: splat 1 lock held by splat/10583: Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
parent
0e149d4204
commit
b8296bf3e6
@ -51,7 +51,7 @@ typedef enum {
|
|||||||
typedef struct atomic_priv {
|
typedef struct atomic_priv {
|
||||||
unsigned long ap_magic;
|
unsigned long ap_magic;
|
||||||
struct file *ap_file;
|
struct file *ap_file;
|
||||||
spinlock_t ap_lock;
|
struct mutex ap_lock;
|
||||||
wait_queue_head_t ap_waitq;
|
wait_queue_head_t ap_waitq;
|
||||||
volatile uint64_t ap_atomic;
|
volatile uint64_t ap_atomic;
|
||||||
volatile uint64_t ap_atomic_exited;
|
volatile uint64_t ap_atomic_exited;
|
||||||
@ -69,10 +69,10 @@ splat_atomic_work(void *priv)
|
|||||||
ap = (atomic_priv_t *)priv;
|
ap = (atomic_priv_t *)priv;
|
||||||
ASSERT(ap->ap_magic == SPLAT_ATOMIC_TEST_MAGIC);
|
ASSERT(ap->ap_magic == SPLAT_ATOMIC_TEST_MAGIC);
|
||||||
|
|
||||||
spin_lock(&ap->ap_lock);
|
mutex_lock(&ap->ap_lock);
|
||||||
op = ap->ap_op;
|
op = ap->ap_op;
|
||||||
wake_up(&ap->ap_waitq);
|
wake_up(&ap->ap_waitq);
|
||||||
spin_unlock(&ap->ap_lock);
|
mutex_unlock(&ap->ap_lock);
|
||||||
|
|
||||||
splat_vprint(ap->ap_file, SPLAT_ATOMIC_TEST1_NAME,
|
splat_vprint(ap->ap_file, SPLAT_ATOMIC_TEST1_NAME,
|
||||||
"Thread %d successfully started: %lu/%lu\n", op,
|
"Thread %d successfully started: %lu/%lu\n", op,
|
||||||
@ -142,13 +142,13 @@ splat_atomic_test1(struct file *file, void *arg)
|
|||||||
|
|
||||||
ap.ap_magic = SPLAT_ATOMIC_TEST_MAGIC;
|
ap.ap_magic = SPLAT_ATOMIC_TEST_MAGIC;
|
||||||
ap.ap_file = file;
|
ap.ap_file = file;
|
||||||
spin_lock_init(&ap.ap_lock);
|
mutex_init(&ap.ap_lock);
|
||||||
init_waitqueue_head(&ap.ap_waitq);
|
init_waitqueue_head(&ap.ap_waitq);
|
||||||
ap.ap_atomic = SPLAT_ATOMIC_INIT_VALUE;
|
ap.ap_atomic = SPLAT_ATOMIC_INIT_VALUE;
|
||||||
ap.ap_atomic_exited = 0;
|
ap.ap_atomic_exited = 0;
|
||||||
|
|
||||||
for (i = 0; i < SPLAT_ATOMIC_COUNT_64; i++) {
|
for (i = 0; i < SPLAT_ATOMIC_COUNT_64; i++) {
|
||||||
spin_lock(&ap.ap_lock);
|
mutex_lock(&ap.ap_lock);
|
||||||
ap.ap_op = i;
|
ap.ap_op = i;
|
||||||
|
|
||||||
thr = (kthread_t *)thread_create(NULL, 0, splat_atomic_work,
|
thr = (kthread_t *)thread_create(NULL, 0, splat_atomic_work,
|
||||||
@ -156,14 +156,14 @@ splat_atomic_test1(struct file *file, void *arg)
|
|||||||
minclsyspri);
|
minclsyspri);
|
||||||
if (thr == NULL) {
|
if (thr == NULL) {
|
||||||
rc = -ESRCH;
|
rc = -ESRCH;
|
||||||
spin_unlock(&ap.ap_lock);
|
mutex_unlock(&ap.ap_lock);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare to wait, the new thread will wake us once it
|
/* Prepare to wait, the new thread will wake us once it
|
||||||
* has made a copy of the unique private passed data */
|
* has made a copy of the unique private passed data */
|
||||||
prepare_to_wait(&ap.ap_waitq, &wait, TASK_UNINTERRUPTIBLE);
|
prepare_to_wait(&ap.ap_waitq, &wait, TASK_UNINTERRUPTIBLE);
|
||||||
spin_unlock(&ap.ap_lock);
|
mutex_unlock(&ap.ap_lock);
|
||||||
schedule();
|
schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user