From 0f399f5b78e19243f4f505884a35252bee93cee1 Mon Sep 17 00:00:00 2001 From: nfshp Date: Sat, 14 Dec 2002 12:05:49 +0000 Subject: [PATCH] as Zach's pointed out, fix the potential deadlock, use wait_event() to sync between threads when liod start/stop. --- lustre/llite/iod.c | 50 +++++++++++++------------------------------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/lustre/llite/iod.c b/lustre/llite/iod.c index c748064..a2f58c6 100644 --- a/lustre/llite/iod.c +++ b/lustre/llite/iod.c @@ -34,18 +34,16 @@ static int liod_main(void *arg) sprintf(current->comm, "liod"); unlock_kernel(); - /* declear we are ready */ - spin_lock(&iod->io_lock); - iod->io_flag |= LIOD_FLAG_ALIVE; + /* declare we are ready */ + set_bit(LIOD_FLAG_ALIVE, &iod->io_flag); wake_up(&iod->io_waitq); - spin_unlock(&iod->io_lock); CDEBUG(D_NET, "liod(%d) started\n", current->pid); while (1) { int t; /* check the stop command */ - if (iod->io_flag & LIOD_FLAG_STOP) + if (test_bit(LIOD_FLAG_STOP, &iod->io_flag)) break; t = interruptible_sleep_on_timeout(&iod->io_sleepq, @@ -54,11 +52,8 @@ static int liod_main(void *arg) (t ? "wakeup" : "timeout")); } - spin_lock(&iod->io_lock); - iod->io_flag &= ~LIOD_FLAG_ALIVE; - iod->io_flag |= LIOD_FLAG_STOPPED; + clear_bit(LIOD_FLAG_ALIVE, &iod->io_flag); wake_up(&iod->io_waitq); - spin_unlock(&iod->io_lock); CDEBUG(D_NET, "liod(%d) exit\n", current->pid); RETURN(0); @@ -66,40 +61,25 @@ static int liod_main(void *arg) int liod_start(struct ll_io_daemon *iod) { - DECLARE_WAITQUEUE(queue, current); int rc; /* initialize */ iod->io_flag = 0; - spin_lock_init(&iod->io_lock); init_waitqueue_head(&iod->io_sleepq); init_waitqueue_head(&iod->io_waitq); - spin_lock(&iod->io_lock); - rc = kernel_thread(liod_main, (void *) iod, CLONE_VM | CLONE_FS | CLONE_FILES); if (rc < 0) { CERROR("fail to start liod, error %d\n", rc); - spin_unlock(&iod->io_lock); return rc; } - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&iod->io_waitq, &queue); - spin_unlock(&iod->io_lock); - /* wait liod start */ - schedule(); - - set_current_state(TASK_RUNNING); - remove_wait_queue(&iod->io_waitq, &queue); + wait_event(iod->io_waitq, test_bit(LIOD_FLAG_ALIVE, &iod->io_flag)); - if (iod->io_flag & LIOD_FLAG_ALIVE) - return 0; - else - return -ENOMEM; + return 0; } void liod_wakeup(struct ll_io_daemon *iod) @@ -109,23 +89,19 @@ void liod_wakeup(struct ll_io_daemon *iod) void liod_stop(struct ll_io_daemon *iod) { - DECLARE_WAITQUEUE(queue, current); - - spin_lock(&iod->io_lock); + if (!test_bit(LIOD_FLAG_ALIVE, &iod->io_flag)) { + CERROR("liod died unexpectedly!\n"); + return; + } /* send the kill command */ - iod->io_flag |= LIOD_FLAG_STOP; + set_bit(LIOD_FLAG_STOP, &iod->io_flag); /* if wakeup daemon */ wake_up(&iod->io_sleepq); - /* wait daemon's exit */ - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&iod->io_waitq, &queue); - spin_unlock(&iod->io_lock); - - schedule(); - /* must woken up by liod */ + /* wait liod exit */ + wait_event(iod->io_waitq, !test_bit(LIOD_FLAG_ALIVE, &iod->io_flag)); return; } -- 1.8.3.1