diff options
author | Bob Peterson <rpeterso@redhat.com> | 2011-06-15 11:41:48 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2011-07-15 04:32:11 -0400 |
commit | 7cf8dcd3b68a760d66fbc7f0d75d3fbb8f21775d (patch) | |
tree | f529dace79c044e6128e9cf283a5c1a584fed5db /fs/gfs2 | |
parent | 17d539f0499fa2c0321b7c260831cca2bb36d119 (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/gfs2')
-rw-r--r-- | fs/gfs2/glock.c | 39 | ||||
-rw-r--r-- | fs/gfs2/glock.h | 6 | ||||
-rw-r--r-- | fs/gfs2/glops.c | 2 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 2 |
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 | ||
856 | static void wait_on_holder(struct gfs2_holder *gh) | 866 | static 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 | ||
862 | static void wait_on_demote(struct gfs2_glock *gl) | 879 | static 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 | |||
116 | struct lm_lockops { | 122 | struct 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; |