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
This commit is contained in:
commit
a3a71ca9a7
6 changed files with 27 additions and 5 deletions
|
@ -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)
|
||||||
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 {
|
||||||
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 {
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
|
|
||||||
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 = {
|
||||||
{ 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 @@
|
||||||
#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"
|
||||||
|
|
Loading…
Add table
Reference in a new issue