Commit 7cf8dcd3 authored by Bob Peterson's avatar Bob Peterson Committed by Steven Whitehouse

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: default avatarBob Peterson <rpeterso@redhat.com>
Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent 17d539f0
...@@ -409,6 +409,10 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state) ...@@ -409,6 +409,10 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
if (held1 && held2 && list_empty(&gl->gl_holders)) if (held1 && held2 && list_empty(&gl->gl_holders))
clear_bit(GLF_QUEUED, &gl->gl_flags); clear_bit(GLF_QUEUED, &gl->gl_flags);
if (new_state != gl->gl_target)
/* shorten our minimum hold time */
gl->gl_hold_time = max(gl->gl_hold_time - GL_GLOCK_HOLD_DECR,
GL_GLOCK_MIN_HOLD);
gl->gl_state = new_state; gl->gl_state = new_state;
gl->gl_tchange = jiffies; gl->gl_tchange = jiffies;
} }
...@@ -668,7 +672,7 @@ static void glock_work_func(struct work_struct *work) ...@@ -668,7 +672,7 @@ static void glock_work_func(struct work_struct *work)
gl->gl_demote_state != LM_ST_EXCLUSIVE) { gl->gl_demote_state != LM_ST_EXCLUSIVE) {
unsigned long holdtime, now = jiffies; unsigned long holdtime, now = jiffies;
holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time; holdtime = gl->gl_tchange + gl->gl_hold_time;
if (time_before(now, holdtime)) if (time_before(now, holdtime))
delay = holdtime - now; delay = holdtime - now;
...@@ -679,9 +683,14 @@ static void glock_work_func(struct work_struct *work) ...@@ -679,9 +683,14 @@ static void glock_work_func(struct work_struct *work)
} }
run_queue(gl, 0); run_queue(gl, 0);
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
if (!delay || if (!delay)
queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)
gfs2_glock_put(gl); gfs2_glock_put(gl);
else {
if (gl->gl_name.ln_type != LM_TYPE_INODE)
delay = 0;
if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)
gfs2_glock_put(gl);
}
if (drop_ref) if (drop_ref)
gfs2_glock_put(gl); gfs2_glock_put(gl);
} }
...@@ -743,6 +752,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, ...@@ -743,6 +752,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
gl->gl_tchange = jiffies; gl->gl_tchange = jiffies;
gl->gl_object = NULL; gl->gl_object = NULL;
gl->gl_sbd = sdp; gl->gl_sbd = sdp;
gl->gl_hold_time = GL_GLOCK_DFT_HOLD;
INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); INIT_DELAYED_WORK(&gl->gl_work, glock_work_func);
INIT_WORK(&gl->gl_delete, delete_work_func); INIT_WORK(&gl->gl_delete, delete_work_func);
...@@ -855,8 +865,15 @@ static int gfs2_glock_demote_wait(void *word) ...@@ -855,8 +865,15 @@ static int gfs2_glock_demote_wait(void *word)
static void wait_on_holder(struct gfs2_holder *gh) static void wait_on_holder(struct gfs2_holder *gh)
{ {
unsigned long time1 = jiffies;
might_sleep(); might_sleep();
wait_on_bit(&gh->gh_iflags, HIF_WAIT, gfs2_glock_holder_wait, TASK_UNINTERRUPTIBLE); wait_on_bit(&gh->gh_iflags, HIF_WAIT, gfs2_glock_holder_wait, TASK_UNINTERRUPTIBLE);
if (time_after(jiffies, time1 + HZ)) /* have we waited > a second? */
/* Lengthen the minimum hold time. */
gh->gh_gl->gl_hold_time = min(gh->gh_gl->gl_hold_time +
GL_GLOCK_HOLD_INCR,
GL_GLOCK_MAX_HOLD);
} }
static void wait_on_demote(struct gfs2_glock *gl) static void wait_on_demote(struct gfs2_glock *gl)
...@@ -1093,8 +1110,9 @@ void gfs2_glock_dq(struct gfs2_holder *gh) ...@@ -1093,8 +1110,9 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
gfs2_glock_hold(gl); gfs2_glock_hold(gl);
if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
!test_bit(GLF_DEMOTE, &gl->gl_flags)) !test_bit(GLF_DEMOTE, &gl->gl_flags) &&
delay = gl->gl_ops->go_min_hold_time; gl->gl_name.ln_type == LM_TYPE_INODE)
delay = gl->gl_hold_time;
if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)
gfs2_glock_put(gl); gfs2_glock_put(gl);
} }
...@@ -1273,12 +1291,13 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) ...@@ -1273,12 +1291,13 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
unsigned long now = jiffies; unsigned long now = jiffies;
gfs2_glock_hold(gl); gfs2_glock_hold(gl);
holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time; holdtime = gl->gl_tchange + gl->gl_hold_time;
if (test_bit(GLF_QUEUED, &gl->gl_flags)) { if (test_bit(GLF_QUEUED, &gl->gl_flags) &&
gl->gl_name.ln_type == LM_TYPE_INODE) {
if (time_before(now, holdtime)) if (time_before(now, holdtime))
delay = holdtime - now; delay = holdtime - now;
if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags)) if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
delay = gl->gl_ops->go_min_hold_time; delay = gl->gl_hold_time;
} }
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
...@@ -1667,7 +1686,7 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl) ...@@ -1667,7 +1686,7 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
dtime *= 1000000/HZ; /* demote time in uSec */ dtime *= 1000000/HZ; /* demote time in uSec */
if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) if (!test_bit(GLF_DEMOTE, &gl->gl_flags))
dtime = 0; dtime = 0;
gfs2_print_dbg(seq, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu a:%d v:%d r:%d\n", 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",
state2str(gl->gl_state), state2str(gl->gl_state),
gl->gl_name.ln_type, gl->gl_name.ln_type,
(unsigned long long)gl->gl_name.ln_number, (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,7 +1695,7 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
state2str(gl->gl_demote_state), dtime, state2str(gl->gl_demote_state), dtime,
atomic_read(&gl->gl_ail_count), atomic_read(&gl->gl_ail_count),
atomic_read(&gl->gl_revokes), atomic_read(&gl->gl_revokes),
atomic_read(&gl->gl_ref)); atomic_read(&gl->gl_ref), gl->gl_hold_time);
list_for_each_entry(gh, &gl->gl_holders, gh_list) { list_for_each_entry(gh, &gl->gl_holders, gh_list) {
error = dump_holder(seq, gh); error = dump_holder(seq, gh);
......
...@@ -113,6 +113,12 @@ enum { ...@@ -113,6 +113,12 @@ enum {
#define GLR_TRYFAILED 13 #define GLR_TRYFAILED 13
#define GL_GLOCK_MAX_HOLD (long)(HZ / 5)
#define GL_GLOCK_DFT_HOLD (long)(HZ / 5)
#define GL_GLOCK_MIN_HOLD (long)(10)
#define GL_GLOCK_HOLD_INCR (long)(HZ / 20)
#define GL_GLOCK_HOLD_DECR (long)(HZ / 40)
struct lm_lockops { struct lm_lockops {
const char *lm_proto_name; const char *lm_proto_name;
int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname); int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname);
......
...@@ -551,7 +551,6 @@ const struct gfs2_glock_operations gfs2_inode_glops = { ...@@ -551,7 +551,6 @@ const struct gfs2_glock_operations gfs2_inode_glops = {
.go_lock = inode_go_lock, .go_lock = inode_go_lock,
.go_dump = inode_go_dump, .go_dump = inode_go_dump,
.go_type = LM_TYPE_INODE, .go_type = LM_TYPE_INODE,
.go_min_hold_time = HZ / 5,
.go_flags = GLOF_ASPACE, .go_flags = GLOF_ASPACE,
}; };
...@@ -562,7 +561,6 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = { ...@@ -562,7 +561,6 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = {
.go_unlock = rgrp_go_unlock, .go_unlock = rgrp_go_unlock,
.go_dump = gfs2_rgrp_dump, .go_dump = gfs2_rgrp_dump,
.go_type = LM_TYPE_RGRP, .go_type = LM_TYPE_RGRP,
.go_min_hold_time = HZ / 5,
.go_flags = GLOF_ASPACE, .go_flags = GLOF_ASPACE,
}; };
......
...@@ -163,7 +163,6 @@ struct gfs2_glock_operations { ...@@ -163,7 +163,6 @@ struct gfs2_glock_operations {
int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl); int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl);
void (*go_callback) (struct gfs2_glock *gl); void (*go_callback) (struct gfs2_glock *gl);
const int go_type; const int go_type;
const unsigned long go_min_hold_time;
const unsigned long go_flags; const unsigned long go_flags;
#define GLOF_ASPACE 1 #define GLOF_ASPACE 1
}; };
...@@ -221,6 +220,7 @@ struct gfs2_glock { ...@@ -221,6 +220,7 @@ struct gfs2_glock {
unsigned int gl_hash; unsigned int gl_hash;
unsigned long gl_demote_time; /* time of first demote request */ unsigned long gl_demote_time; /* time of first demote request */
long gl_hold_time;
struct list_head gl_holders; struct list_head gl_holders;
const struct gfs2_glock_operations *gl_ops; const struct gfs2_glock_operations *gl_ops;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment