aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2011-06-15 11:41:48 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2011-07-15 04:32:11 -0400
commit7cf8dcd3b68a760d66fbc7f0d75d3fbb8f21775d (patch)
treef529dace79c044e6128e9cf283a5c1a584fed5db /fs
parent17d539f0499fa2c0321b7c260831cca2bb36d119 (diff)
GFS2: Automatically adjust glock min hold time
This patch is a performance improvement for GFS2 in a clustered environment. It makes the glock hold time self-adjusting. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/gfs2/glock.c39
-rw-r--r--fs/gfs2/glock.h6
-rw-r--r--fs/gfs2/glops.c2
-rw-r--r--fs/gfs2/incore.h2
4 files changed, 36 insertions, 13 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 1c1336e7b3b2..88e8a23d0026 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -409,6 +409,10 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
409 if (held1 && held2 && list_empty(&gl->gl_holders)) 409 if (held1 && held2 && list_empty(&gl->gl_holders))
410 clear_bit(GLF_QUEUED, &gl->gl_flags); 410 clear_bit(GLF_QUEUED, &gl->gl_flags);
411 411
412 if (new_state != gl->gl_target)
413 /* shorten our minimum hold time */
414 gl->gl_hold_time = max(gl->gl_hold_time - GL_GLOCK_HOLD_DECR,
415 GL_GLOCK_MIN_HOLD);
412 gl->gl_state = new_state; 416 gl->gl_state = new_state;
413 gl->gl_tchange = jiffies; 417 gl->gl_tchange = jiffies;
414} 418}
@@ -668,7 +672,7 @@ static void glock_work_func(struct work_struct *work)
668 gl->gl_demote_state != LM_ST_EXCLUSIVE) { 672 gl->gl_demote_state != LM_ST_EXCLUSIVE) {
669 unsigned long holdtime, now = jiffies; 673 unsigned long holdtime, now = jiffies;
670 674
671 holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time; 675 holdtime = gl->gl_tchange + gl->gl_hold_time;
672 if (time_before(now, holdtime)) 676 if (time_before(now, holdtime))
673 delay = holdtime - now; 677 delay = holdtime - now;
674 678
@@ -679,9 +683,14 @@ static void glock_work_func(struct work_struct *work)
679 } 683 }
680 run_queue(gl, 0); 684 run_queue(gl, 0);
681 spin_unlock(&gl->gl_spin); 685 spin_unlock(&gl->gl_spin);
682 if (!delay || 686 if (!delay)
683 queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)
684 gfs2_glock_put(gl); 687 gfs2_glock_put(gl);
688 else {
689 if (gl->gl_name.ln_type != LM_TYPE_INODE)
690 delay = 0;
691 if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)
692 gfs2_glock_put(gl);
693 }
685 if (drop_ref) 694 if (drop_ref)
686 gfs2_glock_put(gl); 695 gfs2_glock_put(gl);
687} 696}
@@ -743,6 +752,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
743 gl->gl_tchange = jiffies; 752 gl->gl_tchange = jiffies;
744 gl->gl_object = NULL; 753 gl->gl_object = NULL;
745 gl->gl_sbd = sdp; 754 gl->gl_sbd = sdp;
755 gl->gl_hold_time = GL_GLOCK_DFT_HOLD;
746 INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); 756 INIT_DELAYED_WORK(&gl->gl_work, glock_work_func);
747 INIT_WORK(&gl->gl_delete, delete_work_func); 757 INIT_WORK(&gl->gl_delete, delete_work_func);
748 758
@@ -855,8 +865,15 @@ static int gfs2_glock_demote_wait(void *word)
855 865
856static void wait_on_holder(struct gfs2_holder *gh) 866static void wait_on_holder(struct gfs2_holder *gh)
857{ 867{
868 unsigned long time1 = jiffies;
869
858 might_sleep(); 870 might_sleep();
859 wait_on_bit(&gh->gh_iflags, HIF_WAIT, gfs2_glock_holder_wait, TASK_UNINTERRUPTIBLE); 871 wait_on_bit(&gh->gh_iflags, HIF_WAIT, gfs2_glock_holder_wait, TASK_UNINTERRUPTIBLE);
872 if (time_after(jiffies, time1 + HZ)) /* have we waited > a second? */
873 /* Lengthen the minimum hold time. */
874 gh->gh_gl->gl_hold_time = min(gh->gh_gl->gl_hold_time +
875 GL_GLOCK_HOLD_INCR,
876 GL_GLOCK_MAX_HOLD);
860} 877}
861 878
862static void wait_on_demote(struct gfs2_glock *gl) 879static void wait_on_demote(struct gfs2_glock *gl)
@@ -1093,8 +1110,9 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
1093 1110
1094 gfs2_glock_hold(gl); 1111 gfs2_glock_hold(gl);
1095 if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && 1112 if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
1096 !test_bit(GLF_DEMOTE, &gl->gl_flags)) 1113 !test_bit(GLF_DEMOTE, &gl->gl_flags) &&
1097 delay = gl->gl_ops->go_min_hold_time; 1114 gl->gl_name.ln_type == LM_TYPE_INODE)
1115 delay = gl->gl_hold_time;
1098 if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) 1116 if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)
1099 gfs2_glock_put(gl); 1117 gfs2_glock_put(gl);
1100} 1118}
@@ -1273,12 +1291,13 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
1273 unsigned long now = jiffies; 1291 unsigned long now = jiffies;
1274 1292
1275 gfs2_glock_hold(gl); 1293 gfs2_glock_hold(gl);
1276 holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time; 1294 holdtime = gl->gl_tchange + gl->gl_hold_time;
1277 if (test_bit(GLF_QUEUED, &gl->gl_flags)) { 1295 if (test_bit(GLF_QUEUED, &gl->gl_flags) &&
1296 gl->gl_name.ln_type == LM_TYPE_INODE) {
1278 if (time_before(now, holdtime)) 1297 if (time_before(now, holdtime))
1279 delay = holdtime - now; 1298 delay = holdtime - now;
1280 if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags)) 1299 if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
1281 delay = gl->gl_ops->go_min_hold_time; 1300 delay = gl->gl_hold_time;
1282 } 1301 }
1283 1302
1284 spin_lock(&gl->gl_spin); 1303 spin_lock(&gl->gl_spin);
@@ -1667,7 +1686,7 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
1667 dtime *= 1000000/HZ; /* demote time in uSec */ 1686 dtime *= 1000000/HZ; /* demote time in uSec */
1668 if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) 1687 if (!test_bit(GLF_DEMOTE, &gl->gl_flags))
1669 dtime = 0; 1688 dtime = 0;
1670 gfs2_print_dbg(seq, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu a:%d v:%d r:%d\n", 1689 gfs2_print_dbg(seq, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu a:%d v:%d r:%d m:%ld\n",
1671 state2str(gl->gl_state), 1690 state2str(gl->gl_state),
1672 gl->gl_name.ln_type, 1691 gl->gl_name.ln_type,
1673 (unsigned long long)gl->gl_name.ln_number, 1692 (unsigned long long)gl->gl_name.ln_number,
@@ -1676,7 +1695,7 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
1676 state2str(gl->gl_demote_state), dtime, 1695 state2str(gl->gl_demote_state), dtime,
1677 atomic_read(&gl->gl_ail_count), 1696 atomic_read(&gl->gl_ail_count),
1678 atomic_read(&gl->gl_revokes), 1697 atomic_read(&gl->gl_revokes),
1679 atomic_read(&gl->gl_ref)); 1698 atomic_read(&gl->gl_ref), gl->gl_hold_time);
1680 1699
1681 list_for_each_entry(gh, &gl->gl_holders, gh_list) { 1700 list_for_each_entry(gh, &gl->gl_holders, gh_list) {
1682 error = dump_holder(seq, gh); 1701 error = dump_holder(seq, gh);
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index 6b2f757b9281..66707118af25 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -113,6 +113,12 @@ enum {
113 113
114#define GLR_TRYFAILED 13 114#define GLR_TRYFAILED 13
115 115
116#define GL_GLOCK_MAX_HOLD (long)(HZ / 5)
117#define GL_GLOCK_DFT_HOLD (long)(HZ / 5)
118#define GL_GLOCK_MIN_HOLD (long)(10)
119#define GL_GLOCK_HOLD_INCR (long)(HZ / 20)
120#define GL_GLOCK_HOLD_DECR (long)(HZ / 40)
121
116struct lm_lockops { 122struct lm_lockops {
117 const char *lm_proto_name; 123 const char *lm_proto_name;
118 int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname); 124 int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname);
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 95788ae436c6..a4222c3f5993 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -551,7 +551,6 @@ const struct gfs2_glock_operations gfs2_inode_glops = {
551 .go_lock = inode_go_lock, 551 .go_lock = inode_go_lock,
552 .go_dump = inode_go_dump, 552 .go_dump = inode_go_dump,
553 .go_type = LM_TYPE_INODE, 553 .go_type = LM_TYPE_INODE,
554 .go_min_hold_time = HZ / 5,
555 .go_flags = GLOF_ASPACE, 554 .go_flags = GLOF_ASPACE,
556}; 555};
557 556
@@ -562,7 +561,6 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = {
562 .go_unlock = rgrp_go_unlock, 561 .go_unlock = rgrp_go_unlock,
563 .go_dump = gfs2_rgrp_dump, 562 .go_dump = gfs2_rgrp_dump,
564 .go_type = LM_TYPE_RGRP, 563 .go_type = LM_TYPE_RGRP,
565 .go_min_hold_time = HZ / 5,
566 .go_flags = GLOF_ASPACE, 564 .go_flags = GLOF_ASPACE,
567}; 565};
568 566
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 24cd55f60e60..892ac37de8ae 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -163,7 +163,6 @@ struct gfs2_glock_operations {
163 int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl); 163 int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl);
164 void (*go_callback) (struct gfs2_glock *gl); 164 void (*go_callback) (struct gfs2_glock *gl);
165 const int go_type; 165 const int go_type;
166 const unsigned long go_min_hold_time;
167 const unsigned long go_flags; 166 const unsigned long go_flags;
168#define GLOF_ASPACE 1 167#define GLOF_ASPACE 1
169}; 168};
@@ -221,6 +220,7 @@ struct gfs2_glock {
221 220
222 unsigned int gl_hash; 221 unsigned int gl_hash;
223 unsigned long gl_demote_time; /* time of first demote request */ 222 unsigned long gl_demote_time; /* time of first demote request */
223 long gl_hold_time;
224 struct list_head gl_holders; 224 struct list_head gl_holders;
225 225
226 const struct gfs2_glock_operations *gl_ops; 226 const struct gfs2_glock_operations *gl_ops;