Skip to content

Commit

Permalink
GFS2: Wait for unlock completion on umount
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Steven Whitehouse committed Feb 3, 2010
1 parent 1a45dcf commit e402746
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 1 deletion.
2 changes: 2 additions & 0 deletions fs/gfs2/incore.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
7 changes: 6 additions & 1 deletion fs/gfs2/lock_dlm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions fs/gfs2/ops_fstype.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions fs/gfs2/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -860,6 +861,8 @@ static void gfs2_put_super(struct super_block *sb)
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);

Expand Down

0 comments on commit e402746

Please sign in to comment.