lkml.org 
[lkml]   [2008]   [Jan]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 01/58] [GFS2] Handle multiple glock demote requests
    Date
    From: Wendy Cheng <wcheng@redhat.com>

    Fix a race condition where multiple glock demote requests are sent to
    a node back-to-back. This patch does a check inside handle_callback()
    to see whether a demote request is in progress. If true, it sets a flag
    to make sure run_queue() will loop again to handle the new request,
    instead of erronously setting gl_demote_state to a different state.

    Signed-off-by: S. Wendy Cheng <wcheng@redhat.com>
    Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>

    diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
    index a37efe4..104e83f 100644
    --- a/fs/gfs2/glock.c
    +++ b/fs/gfs2/glock.c
    @@ -567,7 +567,10 @@ static int rq_demote(struct gfs2_glock *gl)
    gfs2_demote_wake(gl);
    return 0;
    }
    +
    set_bit(GLF_LOCK, &gl->gl_flags);
    + set_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
    +
    if (gl->gl_demote_state == LM_ST_UNLOCKED ||
    gl->gl_state != LM_ST_EXCLUSIVE) {
    spin_unlock(&gl->gl_spin);
    @@ -576,7 +579,9 @@ static int rq_demote(struct gfs2_glock *gl)
    spin_unlock(&gl->gl_spin);
    gfs2_glock_xmote_th(gl, NULL);
    }
    +
    spin_lock(&gl->gl_spin);
    + clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);

    return 0;
    }
    @@ -606,6 +611,11 @@ static void run_queue(struct gfs2_glock *gl)

    } else if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
    blocked = rq_demote(gl);
    + if (gl->gl_waiters2 && !blocked) {
    + set_bit(GLF_DEMOTE, &gl->gl_flags);
    + gl->gl_demote_state = LM_ST_UNLOCKED;
    + }
    + gl->gl_waiters2 = 0;
    } else if (!list_empty(&gl->gl_waiters3)) {
    gh = list_entry(gl->gl_waiters3.next,
    struct gfs2_holder, gh_list);
    @@ -722,7 +732,10 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state,
    }
    } else if (gl->gl_demote_state != LM_ST_UNLOCKED &&
    gl->gl_demote_state != state) {
    - gl->gl_demote_state = LM_ST_UNLOCKED;
    + if (test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags))
    + gl->gl_waiters2 = 1;
    + else
    + gl->gl_demote_state = LM_ST_UNLOCKED;
    }
    spin_unlock(&gl->gl_spin);
    }
    diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
    index eaddfb5..662182b 100644
    --- a/fs/gfs2/incore.h
    +++ b/fs/gfs2/incore.h
    @@ -171,6 +171,7 @@ enum {
    GLF_DEMOTE = 3,
    GLF_PENDING_DEMOTE = 4,
    GLF_DIRTY = 5,
    + GLF_DEMOTE_IN_PROGRESS = 6,
    };

    struct gfs2_glock {
    @@ -190,6 +191,7 @@ struct gfs2_glock {
    struct list_head gl_holders;
    struct list_head gl_waiters1; /* HIF_MUTEX */
    struct list_head gl_waiters3; /* HIF_PROMOTE */
    + int gl_waiters2; /* GIF_DEMOTE */

    const struct gfs2_glock_operations *gl_ops;

    --
    1.5.1.2


    \
     
     \ /
      Last update: 2008-01-21 11:05    [W:0.031 / U:30.100 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site