Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=87124e581bfeaa5864662a435b6ee2a19e91b905
Commit:     87124e581bfeaa5864662a435b6ee2a19e91b905
Parent:     bbf25010f1a6b761914430f5fca081ec8c7accd1
Author:     Steven Whitehouse <[EMAIL PROTECTED]>
AuthorDate: Mon Jul 23 09:54:36 2007 +0100
Committer:  Steven Whitehouse <[EMAIL PROTECTED]>
CommitDate: Wed Oct 10 08:54:39 2007 +0100

    [GFS2] Fix two races relating to glock callbacks
    
    One of the races relates to referencing a variable while not holding
    its protecting spinlock. The patch simply moves the test inside the
    spin lock. The other races occurs when a demote to unlocked request
    occurs during the time a demote to shared request is already running.
    This of course only happens in the case that the lock was in the
    exclusive mode to start with. The patch adds a check to see if another
    demote request has occurred in the mean time and if it has, then it
    performs a second demote.
    
    Signed-off-by: Steven Whitehouse <[EMAIL PROTECTED]>
---
 fs/gfs2/glock.c |   24 ++++++++++++++++++------
 1 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 3f0974e..6a3eeba 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -545,12 +545,14 @@ static int rq_demote(struct gfs2_glock *gl)
                return 0;
        }
        set_bit(GLF_LOCK, &gl->gl_flags);
-       spin_unlock(&gl->gl_spin);
        if (gl->gl_demote_state == LM_ST_UNLOCKED ||
-           gl->gl_state != LM_ST_EXCLUSIVE)
+           gl->gl_state != LM_ST_EXCLUSIVE) {
+               spin_unlock(&gl->gl_spin);
                gfs2_glock_drop_th(gl);
-       else
+       } else {
+               spin_unlock(&gl->gl_spin);
                gfs2_glock_xmote_th(gl, NULL);
+       }
        spin_lock(&gl->gl_spin);
 
        return 0;
@@ -760,10 +762,20 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int 
ret)
 
        if (!gh) {
                gl->gl_stamp = jiffies;
-               if (ret & LM_OUT_CANCELED)
+               if (ret & LM_OUT_CANCELED) {
                        op_done = 0;
-               else
+               } else {
+                       spin_lock(&gl->gl_spin);
+                       if (gl->gl_state != gl->gl_demote_state) {
+                               gl->gl_req_bh = NULL;
+                               spin_unlock(&gl->gl_spin);
+                               gfs2_glock_drop_th(gl);
+                               gfs2_glock_put(gl);
+                               return;
+                       }
                        gfs2_demote_wake(gl);
+                       spin_unlock(&gl->gl_spin);
+               }
        } else {
                spin_lock(&gl->gl_spin);
                list_del_init(&gh->gh_list);
@@ -817,7 +829,7 @@ out:
  *
  */
 
-void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
+static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
 {
        struct gfs2_sbd *sdp = gl->gl_sbd;
        int flags = gh ? gh->gh_flags : 0;
-
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