Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=55c0c4ac0be144014651b19e77c9b77f367955de
Commit:     55c0c4ac0be144014651b19e77c9b77f367955de
Parent:     d66f8277f53407754f50ae6bada68f1b68d04d48
Author:     Bob Peterson <[EMAIL PROTECTED]>
AuthorDate: Fri Sep 14 09:27:59 2007 -0500
Committer:  Steven Whitehouse <[EMAIL PROTECTED]>
CommitDate: Wed Oct 10 08:56:22 2007 +0100

    [GFS2] GFS2: chmod hung - fix race in thread creation
    
    The problem boiled down to a race between the gdlm_init_threads()
    function initializing thread1 and its setting of blist = 1.
    Essentially, "if (current == ls->thread1)" was checked by the thread
    before the thread creator set ls->thread1.
    
    Since thread1 is the only thread who is allowed to work on the
    blocking queue, and since neither thread thought it was thread1, no one
    was working on the queue.  So everything just sat.
    
    This patch reuses the ls->async_lock spin_lock to fix the race,
    and it fixes the problem.  I've done more than 2000 iterations of the
    loop that was recreating the failure and it seems to work.
    
    Signed-off-by: Bob Peterson <[EMAIL PROTECTED]>
    Signed-off-by: Steven Whitehouse <[EMAIL PROTECTED]>
    
    --
---
 fs/gfs2/locking/dlm/thread.c |   20 +++++++++++++-------
 1 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c
index 1aca51e..bd938f0 100644
--- a/fs/gfs2/locking/dlm/thread.c
+++ b/fs/gfs2/locking/dlm/thread.c
@@ -268,20 +268,16 @@ static inline int check_drop(struct gdlm_ls *ls)
        return 0;
 }
 
-static int gdlm_thread(void *data)
+static int gdlm_thread(void *data, int blist)
 {
        struct gdlm_ls *ls = (struct gdlm_ls *) data;
        struct gdlm_lock *lp = NULL;
-       int blist = 0;
        uint8_t complete, blocking, submit, drop;
        DECLARE_WAITQUEUE(wait, current);
 
        /* Only thread1 is allowed to do blocking callbacks since gfs
           may wait for a completion callback within a blocking cb. */
 
-       if (current == ls->thread1)
-               blist = 1;
-
        while (!kthread_should_stop()) {
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&ls->thread_wait, &wait);
@@ -333,12 +329,22 @@ static int gdlm_thread(void *data)
        return 0;
 }
 
+static int gdlm_thread1(void *data)
+{
+       return gdlm_thread(data, 1);
+}
+
+static int gdlm_thread2(void *data)
+{
+       return gdlm_thread(data, 0);
+}
+
 int gdlm_init_threads(struct gdlm_ls *ls)
 {
        struct task_struct *p;
        int error;
 
-       p = kthread_run(gdlm_thread, ls, "lock_dlm1");
+       p = kthread_run(gdlm_thread1, ls, "lock_dlm1");
        error = IS_ERR(p);
        if (error) {
                log_error("can't start lock_dlm1 thread %d", error);
@@ -346,7 +352,7 @@ int gdlm_init_threads(struct gdlm_ls *ls)
        }
        ls->thread1 = p;
 
-       p = kthread_run(gdlm_thread, ls, "lock_dlm2");
+       p = kthread_run(gdlm_thread2, ls, "lock_dlm2");
        error = IS_ERR(p);
        if (error) {
                log_error("can't start lock_dlm2 thread %d", error);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to