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 | |
| 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>
| -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; |
