diff options
author | Benjamin Marzinski <bmarzins@redhat.com> | 2007-08-23 14:19:05 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2007-10-10 03:55:48 -0400 |
commit | c4f68a130fc1795e4a75ec5bdaf9e85d86c22419 (patch) | |
tree | 37251ae5634d4b73b5224e3e8679f92472de0ebe /fs/gfs2/incore.h | |
parent | d1e2777d4f419a865ddccdb9b3412021d0e4de51 (diff) |
[GFS2] delay glock demote for a minimum hold time
When a lot of IO, with some distributed mmap IO, is run on a GFS2 filesystem in
a cluster, it will deadlock. The reason is that do_no_page() will repeatedly
call gfs2_sharewrite_nopage(), because each node keeps giving up the glock
too early, and is forced to call unmap_mapping_range(). This bumps the
mapping->truncate_count sequence count, forcing do_no_page() to retry. This
patch institutes a minimum glock hold time a tenth a second. This insures
that even in heavy contention cases, the node has enough time to get some
useful work done before it gives up the glock.
A second issue is that when gfs2_glock_dq() is called from within a page fault
to demote a lock, and the associated page needs to be written out, it will
try to acqire a lock on it, but it has already been locked at a higher level.
This patch puts makes gfs2_glock_dq() use the work queue as well, to avoid this
issue. This is the same patch as Steve Whitehouse originally proposed to fix
this issue, execpt that gfs2_glock_dq() now grabs a reference to the glock
before it queues up the work on it.
Signed-off-by: Benjamin E. Marzinski <bmarzins@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/incore.h')
-rw-r--r-- | fs/gfs2/incore.h | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 1390b30daf19..23b611aa70d2 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #define __INCORE_DOT_H__ | 11 | #define __INCORE_DOT_H__ |
12 | 12 | ||
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | #include <linux/workqueue.h> | ||
14 | 15 | ||
15 | #define DIO_WAIT 0x00000010 | 16 | #define DIO_WAIT 0x00000010 |
16 | #define DIO_METADATA 0x00000020 | 17 | #define DIO_METADATA 0x00000020 |
@@ -130,6 +131,7 @@ struct gfs2_glock_operations { | |||
130 | int (*go_lock) (struct gfs2_holder *gh); | 131 | int (*go_lock) (struct gfs2_holder *gh); |
131 | void (*go_unlock) (struct gfs2_holder *gh); | 132 | void (*go_unlock) (struct gfs2_holder *gh); |
132 | const int go_type; | 133 | const int go_type; |
134 | const unsigned long go_min_hold_time; | ||
133 | }; | 135 | }; |
134 | 136 | ||
135 | enum { | 137 | enum { |
@@ -161,6 +163,7 @@ enum { | |||
161 | GLF_LOCK = 1, | 163 | GLF_LOCK = 1, |
162 | GLF_STICKY = 2, | 164 | GLF_STICKY = 2, |
163 | GLF_DEMOTE = 3, | 165 | GLF_DEMOTE = 3, |
166 | GLF_PENDING_DEMOTE = 4, | ||
164 | GLF_DIRTY = 5, | 167 | GLF_DIRTY = 5, |
165 | }; | 168 | }; |
166 | 169 | ||
@@ -193,6 +196,7 @@ struct gfs2_glock { | |||
193 | 196 | ||
194 | u64 gl_vn; | 197 | u64 gl_vn; |
195 | unsigned long gl_stamp; | 198 | unsigned long gl_stamp; |
199 | unsigned long gl_tchange; | ||
196 | void *gl_object; | 200 | void *gl_object; |
197 | 201 | ||
198 | struct list_head gl_reclaim; | 202 | struct list_head gl_reclaim; |
@@ -203,6 +207,7 @@ struct gfs2_glock { | |||
203 | struct gfs2_log_element gl_le; | 207 | struct gfs2_log_element gl_le; |
204 | struct list_head gl_ail_list; | 208 | struct list_head gl_ail_list; |
205 | atomic_t gl_ail_count; | 209 | atomic_t gl_ail_count; |
210 | struct delayed_work gl_work; | ||
206 | }; | 211 | }; |
207 | 212 | ||
208 | struct gfs2_alloc { | 213 | struct gfs2_alloc { |