Commit a3a71ca9 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes

* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes:
  GFS2: Extend umount wait coverage to full glock lifetime
  GFS2: Wait for unlock completion on umount
parents 6f14a668 8f05228e
...@@ -769,6 +769,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, ...@@ -769,6 +769,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
if (!gl) if (!gl)
return -ENOMEM; return -ENOMEM;
atomic_inc(&sdp->sd_glock_disposal);
gl->gl_flags = 0; gl->gl_flags = 0;
gl->gl_name = name; gl->gl_name = name;
atomic_set(&gl->gl_ref, 1); atomic_set(&gl->gl_ref, 1);
...@@ -1538,6 +1539,9 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) ...@@ -1538,6 +1539,9 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
up_write(&gfs2_umount_flush_sem); up_write(&gfs2_umount_flush_sem);
msleep(10); msleep(10);
} }
flush_workqueue(glock_workqueue);
wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0);
gfs2_dump_lockstate(sdp);
} }
void gfs2_glock_finish_truncate(struct gfs2_inode *ip) void gfs2_glock_finish_truncate(struct gfs2_inode *ip)
......
...@@ -123,7 +123,7 @@ struct lm_lockops { ...@@ -123,7 +123,7 @@ struct lm_lockops {
int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname); int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname);
void (*lm_unmount) (struct gfs2_sbd *sdp); void (*lm_unmount) (struct gfs2_sbd *sdp);
void (*lm_withdraw) (struct gfs2_sbd *sdp); void (*lm_withdraw) (struct gfs2_sbd *sdp);
void (*lm_put_lock) (struct kmem_cache *cachep, void *gl); void (*lm_put_lock) (struct kmem_cache *cachep, struct gfs2_glock *gl);
unsigned int (*lm_lock) (struct gfs2_glock *gl, unsigned int (*lm_lock) (struct gfs2_glock *gl,
unsigned int req_state, unsigned int flags); unsigned int req_state, unsigned int flags);
void (*lm_cancel) (struct gfs2_glock *gl); void (*lm_cancel) (struct gfs2_glock *gl);
......
...@@ -544,6 +544,8 @@ struct gfs2_sbd { ...@@ -544,6 +544,8 @@ struct gfs2_sbd {
struct gfs2_holder sd_live_gh; struct gfs2_holder sd_live_gh;
struct gfs2_glock *sd_rename_gl; struct gfs2_glock *sd_rename_gl;
struct gfs2_glock *sd_trans_gl; struct gfs2_glock *sd_trans_gl;
wait_queue_head_t sd_glock_wait;
atomic_t sd_glock_disposal;
/* Inode Stuff */ /* Inode Stuff */
......
...@@ -21,6 +21,7 @@ static void gdlm_ast(void *arg) ...@@ -21,6 +21,7 @@ static void gdlm_ast(void *arg)
{ {
struct gfs2_glock *gl = arg; struct gfs2_glock *gl = arg;
unsigned ret = gl->gl_state; unsigned ret = gl->gl_state;
struct gfs2_sbd *sdp = gl->gl_sbd;
BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED); BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED);
...@@ -30,6 +31,8 @@ static void gdlm_ast(void *arg) ...@@ -30,6 +31,8 @@ static void gdlm_ast(void *arg)
switch (gl->gl_lksb.sb_status) { switch (gl->gl_lksb.sb_status) {
case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */ case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */
kmem_cache_free(gfs2_glock_cachep, gl); kmem_cache_free(gfs2_glock_cachep, gl);
if (atomic_dec_and_test(&sdp->sd_glock_disposal))
wake_up(&sdp->sd_glock_wait);
return; return;
case -DLM_ECANCEL: /* Cancel while getting lock */ case -DLM_ECANCEL: /* Cancel while getting lock */
ret |= LM_OUT_CANCELED; ret |= LM_OUT_CANCELED;
...@@ -164,14 +167,16 @@ static unsigned int gdlm_lock(struct gfs2_glock *gl, ...@@ -164,14 +167,16 @@ static unsigned int gdlm_lock(struct gfs2_glock *gl,
return LM_OUT_ASYNC; return LM_OUT_ASYNC;
} }
static void gdlm_put_lock(struct kmem_cache *cachep, void *ptr) static void gdlm_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl)
{ {
struct gfs2_glock *gl = ptr; struct gfs2_sbd *sdp = gl->gl_sbd;
struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; struct lm_lockstruct *ls = &sdp->sd_lockstruct;
int error; int error;
if (gl->gl_lksb.sb_lkid == 0) { if (gl->gl_lksb.sb_lkid == 0) {
kmem_cache_free(cachep, gl); kmem_cache_free(cachep, gl);
if (atomic_dec_and_test(&sdp->sd_glock_disposal))
wake_up(&sdp->sd_glock_wait);
return; return;
} }
......
...@@ -82,6 +82,8 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) ...@@ -82,6 +82,8 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
gfs2_tune_init(&sdp->sd_tune); 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_statfs_spin);
spin_lock_init(&sdp->sd_rindex_spin); spin_lock_init(&sdp->sd_rindex_spin);
...@@ -983,9 +985,17 @@ static const match_table_t nolock_tokens = { ...@@ -983,9 +985,17 @@ static const match_table_t nolock_tokens = {
{ Opt_err, NULL }, { Opt_err, NULL },
}; };
static void nolock_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl)
{
struct gfs2_sbd *sdp = gl->gl_sbd;
kmem_cache_free(cachep, gl);
if (atomic_dec_and_test(&sdp->sd_glock_disposal))
wake_up(&sdp->sd_glock_wait);
}
static const struct lm_lockops nolock_ops = { static const struct lm_lockops nolock_ops = {
.lm_proto_name = "lock_nolock", .lm_proto_name = "lock_nolock",
.lm_put_lock = kmem_cache_free, .lm_put_lock = nolock_put_lock,
.lm_tokens = &nolock_tokens, .lm_tokens = &nolock_tokens,
}; };
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/gfs2_ondisk.h> #include <linux/gfs2_ondisk.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/wait.h>
#include "gfs2.h" #include "gfs2.h"
#include "incore.h" #include "incore.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment