aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2010-01-29 10:21:27 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2010-02-03 04:56:21 -0500
commit8f05228ee7c8f409ae3c6f9c3e13d7ccb9c18360 (patch)
tree34e8cf87485edf4ecb6878ade96704975e5d5bf5 /fs/gfs2
parente402746a945ceb9d0486a8e3d5917c9228fa4404 (diff)
GFS2: Extend umount wait coverage to full glock lifetime
Although all glocks are, by the time of the umount glock wait, scheduled for demotion, some of them haven't made it far enough through the process for the original set of waiting code to wait for them. This extends the ref count to the whole glock lifetime in order to ensure that the waiting does catch all glocks. It does make it a bit more invasive, but it seems the only sensible solution at the moment. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/glock.c4
-rw-r--r--fs/gfs2/glock.h2
-rw-r--r--fs/gfs2/lock_dlm.c6
-rw-r--r--fs/gfs2/ops_fstype.c10
-rw-r--r--fs/gfs2/super.c2
5 files changed, 17 insertions, 7 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index f455a03a09e..f4266332593 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -769,6 +769,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
769 if (!gl) 769 if (!gl)
770 return -ENOMEM; 770 return -ENOMEM;
771 771
772 atomic_inc(&sdp->sd_glock_disposal);
772 gl->gl_flags = 0; 773 gl->gl_flags = 0;
773 gl->gl_name = name; 774 gl->gl_name = name;
774 atomic_set(&gl->gl_ref, 1); 775 atomic_set(&gl->gl_ref, 1);
@@ -1538,6 +1539,9 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
1538 up_write(&gfs2_umount_flush_sem); 1539 up_write(&gfs2_umount_flush_sem);
1539 msleep(10); 1540 msleep(10);
1540 } 1541 }
1542 flush_workqueue(glock_workqueue);
1543 wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0);
1544 gfs2_dump_lockstate(sdp);
1541} 1545}
1542 1546
1543void gfs2_glock_finish_truncate(struct gfs2_inode *ip) 1547void gfs2_glock_finish_truncate(struct gfs2_inode *ip)
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index 13f0bd22813..c0262faf472 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -123,7 +123,7 @@ struct lm_lockops {
123 int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname); 123 int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname);
124 void (*lm_unmount) (struct gfs2_sbd *sdp); 124 void (*lm_unmount) (struct gfs2_sbd *sdp);
125 void (*lm_withdraw) (struct gfs2_sbd *sdp); 125 void (*lm_withdraw) (struct gfs2_sbd *sdp);
126 void (*lm_put_lock) (struct kmem_cache *cachep, void *gl); 126 void (*lm_put_lock) (struct kmem_cache *cachep, struct gfs2_glock *gl);
127 unsigned int (*lm_lock) (struct gfs2_glock *gl, 127 unsigned int (*lm_lock) (struct gfs2_glock *gl,
128 unsigned int req_state, unsigned int flags); 128 unsigned int req_state, unsigned int flags);
129 void (*lm_cancel) (struct gfs2_glock *gl); 129 void (*lm_cancel) (struct gfs2_glock *gl);
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index cdd0755d782..0e5e0e7022e 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -167,15 +167,16 @@ static unsigned int gdlm_lock(struct gfs2_glock *gl,
167 return LM_OUT_ASYNC; 167 return LM_OUT_ASYNC;
168} 168}
169 169
170static void gdlm_put_lock(struct kmem_cache *cachep, void *ptr) 170static void gdlm_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl)
171{ 171{
172 struct gfs2_glock *gl = ptr;
173 struct gfs2_sbd *sdp = gl->gl_sbd; 172 struct gfs2_sbd *sdp = gl->gl_sbd;
174 struct lm_lockstruct *ls = &sdp->sd_lockstruct; 173 struct lm_lockstruct *ls = &sdp->sd_lockstruct;
175 int error; 174 int error;
176 175
177 if (gl->gl_lksb.sb_lkid == 0) { 176 if (gl->gl_lksb.sb_lkid == 0) {
178 kmem_cache_free(cachep, gl); 177 kmem_cache_free(cachep, gl);
178 if (atomic_dec_and_test(&sdp->sd_glock_disposal))
179 wake_up(&sdp->sd_glock_wait);
179 return; 180 return;
180 } 181 }
181 182
@@ -187,7 +188,6 @@ static void gdlm_put_lock(struct kmem_cache *cachep, void *ptr)
187 (unsigned long long)gl->gl_name.ln_number, error); 188 (unsigned long long)gl->gl_name.ln_number, error);
188 return; 189 return;
189 } 190 }
190 atomic_inc(&sdp->sd_glock_disposal);
191} 191}
192 192
193static void gdlm_cancel(struct gfs2_glock *gl) 193static void gdlm_cancel(struct gfs2_glock *gl)
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 9390fc7d8d4..8a102f73100 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -985,9 +985,17 @@ static const match_table_t nolock_tokens = {
985 { Opt_err, NULL }, 985 { Opt_err, NULL },
986}; 986};
987 987
988static void nolock_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl)
989{
990 struct gfs2_sbd *sdp = gl->gl_sbd;
991 kmem_cache_free(cachep, gl);
992 if (atomic_dec_and_test(&sdp->sd_glock_disposal))
993 wake_up(&sdp->sd_glock_wait);
994}
995
988static const struct lm_lockops nolock_ops = { 996static const struct lm_lockops nolock_ops = {
989 .lm_proto_name = "lock_nolock", 997 .lm_proto_name = "lock_nolock",
990 .lm_put_lock = kmem_cache_free, 998 .lm_put_lock = nolock_put_lock,
991 .lm_tokens = &nolock_tokens, 999 .lm_tokens = &nolock_tokens,
992}; 1000};
993 1001
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 66242b32db5..b9dd3da22c0 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -861,8 +861,6 @@ restart:
861 gfs2_jindex_free(sdp); 861 gfs2_jindex_free(sdp);
862 /* Take apart glock structures and buffer lists */ 862 /* Take apart glock structures and buffer lists */
863 gfs2_gl_hash_clear(sdp); 863 gfs2_gl_hash_clear(sdp);
864 /* Wait for dlm to reply to all our unlock requests */
865 wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0);
866 /* Unmount the locking protocol */ 864 /* Unmount the locking protocol */
867 gfs2_lm_unmount(sdp); 865 gfs2_lm_unmount(sdp);
868 866