GFS2: Wait for unlock completion on umount
authorSteven Whitehouse <swhiteho@redhat.com>
Mon, 25 Jan 2010 11:20:19 +0000 (11:20 +0000)
committerSteven Whitehouse <swhiteho@redhat.com>
Wed, 3 Feb 2010 09:47:04 +0000 (09:47 +0000)
This patch adds a wait on umount between the point at which we
dispose of all glocks and the point at which we unmount the
lock protocol. This ensures that we've received all the replies
to our unlock requests before we stop the locking.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Reported-by: Fabio M. Di Nitto <fdinitto@redhat.com>
fs/gfs2/incore.h
fs/gfs2/lock_dlm.c
fs/gfs2/ops_fstype.c
fs/gfs2/super.c

index 4792200978c82ef16378a81487016814251fe1ae..bc0ad158e6b4925bc22579d9dff295b1b9fa22f6 100644 (file)
@@ -544,6 +544,8 @@ struct gfs2_sbd {
        struct gfs2_holder sd_live_gh;
        struct gfs2_glock *sd_rename_gl;
        struct gfs2_glock *sd_trans_gl;
+       wait_queue_head_t sd_glock_wait;
+       atomic_t sd_glock_disposal;
 
        /* Inode Stuff */
 
index 46df988323bc035285d5663429588038df6d6b9c..cdd0755d7823dff6610e0354fd024fae4477b17d 100644 (file)
@@ -21,6 +21,7 @@ static void gdlm_ast(void *arg)
 {
        struct gfs2_glock *gl = arg;
        unsigned ret = gl->gl_state;
+       struct gfs2_sbd *sdp = gl->gl_sbd;
 
        BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED);
 
@@ -30,6 +31,8 @@ static void gdlm_ast(void *arg)
        switch (gl->gl_lksb.sb_status) {
        case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */
                kmem_cache_free(gfs2_glock_cachep, gl);
+               if (atomic_dec_and_test(&sdp->sd_glock_disposal))
+                       wake_up(&sdp->sd_glock_wait);
                return;
        case -DLM_ECANCEL: /* Cancel while getting lock */
                ret |= LM_OUT_CANCELED;
@@ -167,7 +170,8 @@ static unsigned int gdlm_lock(struct gfs2_glock *gl,
 static void gdlm_put_lock(struct kmem_cache *cachep, void *ptr)
 {
        struct gfs2_glock *gl = ptr;
-       struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
+       struct gfs2_sbd *sdp = gl->gl_sbd;
+       struct lm_lockstruct *ls = &sdp->sd_lockstruct;
        int error;
 
        if (gl->gl_lksb.sb_lkid == 0) {
@@ -183,6 +187,7 @@ static void gdlm_put_lock(struct kmem_cache *cachep, void *ptr)
                       (unsigned long long)gl->gl_name.ln_number, error);
                return;
        }
+       atomic_inc(&sdp->sd_glock_disposal);
 }
 
 static void gdlm_cancel(struct gfs2_glock *gl)
index edfee24f3636d9c6db41cc756622b20cfabb1c3c..9390fc7d8d408ca6c768e5bcdb085b484693a837 100644 (file)
@@ -82,6 +82,8 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
 
        gfs2_tune_init(&sdp->sd_tune);
 
+       init_waitqueue_head(&sdp->sd_glock_wait);
+       atomic_set(&sdp->sd_glock_disposal, 0);
        spin_lock_init(&sdp->sd_statfs_spin);
 
        spin_lock_init(&sdp->sd_rindex_spin);
index c282ad41f3d1860bba4301495a7303de40b57d06..66242b32db5b950739b15dbf82d67ad1e4048ef8 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
 #include <linux/time.h>
+#include <linux/wait.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -860,6 +861,8 @@ restart:
        gfs2_jindex_free(sdp);
        /*  Take apart glock structures and buffer lists  */
        gfs2_gl_hash_clear(sdp);
+       /* Wait for dlm to reply to all our unlock requests */
+       wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0);
        /*  Unmount the locking protocol  */
        gfs2_lm_unmount(sdp);