Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 54451
b: refs/heads/master
c: 3b8249f
h: refs/heads/master
i:
  54449: 6ccd704
  54447: 5ab621a
v: v3
  • Loading branch information
Steven Whitehouse committed May 1, 2007
1 parent d8f9621 commit 652b5c7
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 180 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1de913909263ba7f7054debeda1b79771a7233db
refs/heads/master: 3b8249f6178cb2b68b9d683587797270125cc06a
233 changes: 62 additions & 171 deletions trunk/fs/gfs2/glock.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct glock_iter {
typedef void (*glock_examiner) (struct gfs2_glock * gl);

static int gfs2_dump_lockstate(struct gfs2_sbd *sdp);
static void gfs2_glock_xmote_th(struct gfs2_holder *gh);
static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh);
static void gfs2_glock_drop_th(struct gfs2_glock *gl);
static DECLARE_RWSEM(gfs2_umount_flush_sem);
static struct dentry *gfs2_root;
Expand Down Expand Up @@ -212,7 +212,6 @@ int gfs2_glock_put(struct gfs2_glock *gl)
gfs2_assert(sdp, list_empty(&gl->gl_reclaim));
gfs2_assert(sdp, list_empty(&gl->gl_holders));
gfs2_assert(sdp, list_empty(&gl->gl_waiters1));
gfs2_assert(sdp, list_empty(&gl->gl_waiters2));
gfs2_assert(sdp, list_empty(&gl->gl_waiters3));
glock_free(gl);
rv = 1;
Expand Down Expand Up @@ -399,7 +398,7 @@ void gfs2_holder_reinit(unsigned int state, unsigned flags, struct gfs2_holder *
{
gh->gh_state = state;
gh->gh_flags = flags;
gh->gh_iflags &= 1 << HIF_ALLOCED;
gh->gh_iflags = 0;
gh->gh_ip = (unsigned long)__builtin_return_address(0);
}

Expand All @@ -416,54 +415,8 @@ void gfs2_holder_uninit(struct gfs2_holder *gh)
gh->gh_ip = 0;
}

/**
* gfs2_holder_get - get a struct gfs2_holder structure
* @gl: the glock
* @state: the state we're requesting
* @flags: the modifier flags
* @gfp_flags:
*
* Figure out how big an impact this function has. Either:
* 1) Replace it with a cache of structures hanging off the struct gfs2_sbd
* 2) Leave it like it is
*
* Returns: the holder structure, NULL on ENOMEM
*/

static struct gfs2_holder *gfs2_holder_get(struct gfs2_glock *gl,
unsigned int state,
int flags, gfp_t gfp_flags)
{
struct gfs2_holder *gh;

gh = kmalloc(sizeof(struct gfs2_holder), gfp_flags);
if (!gh)
return NULL;

gfs2_holder_init(gl, state, flags, gh);
set_bit(HIF_ALLOCED, &gh->gh_iflags);
gh->gh_ip = (unsigned long)__builtin_return_address(0);
return gh;
}

/**
* gfs2_holder_put - get rid of a struct gfs2_holder structure
* @gh: the holder structure
*
*/

static void gfs2_holder_put(struct gfs2_holder *gh)
{
gfs2_holder_uninit(gh);
kfree(gh);
}

static void gfs2_holder_dispose_or_wake(struct gfs2_holder *gh)
static void gfs2_holder_wake(struct gfs2_holder *gh)
{
if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) {
gfs2_holder_put(gh);
return;
}
clear_bit(HIF_WAIT, &gh->gh_iflags);
smp_mb();
wake_up_bit(&gh->gh_iflags, HIF_WAIT);
Expand Down Expand Up @@ -529,7 +482,7 @@ static int rq_promote(struct gfs2_holder *gh)
gfs2_reclaim_glock(sdp);
}

gfs2_glock_xmote_th(gh);
gfs2_glock_xmote_th(gh->gh_gl, gh);
spin_lock(&gl->gl_spin);
}
return 1;
Expand All @@ -552,7 +505,7 @@ static int rq_promote(struct gfs2_holder *gh)
gh->gh_error = 0;
set_bit(HIF_HOLDER, &gh->gh_iflags);

gfs2_holder_dispose_or_wake(gh);
gfs2_holder_wake(gh);

return 0;
}
Expand All @@ -564,32 +517,24 @@ static int rq_promote(struct gfs2_holder *gh)
* Returns: 1 if the queue is blocked
*/

static int rq_demote(struct gfs2_holder *gh)
static int rq_demote(struct gfs2_glock *gl)
{
struct gfs2_glock *gl = gh->gh_gl;

if (!list_empty(&gl->gl_holders))
return 1;

if (gl->gl_state == gh->gh_state || gl->gl_state == LM_ST_UNLOCKED) {
list_del_init(&gh->gh_list);
gh->gh_error = 0;
spin_unlock(&gl->gl_spin);
gfs2_holder_dispose_or_wake(gh);
spin_lock(&gl->gl_spin);
} else {
gl->gl_req_gh = gh;
set_bit(GLF_LOCK, &gl->gl_flags);
spin_unlock(&gl->gl_spin);

if (gh->gh_state == LM_ST_UNLOCKED ||
gl->gl_state != LM_ST_EXCLUSIVE)
gfs2_glock_drop_th(gl);
else
gfs2_glock_xmote_th(gh);

spin_lock(&gl->gl_spin);
if (gl->gl_state == gl->gl_demote_state ||
gl->gl_state == LM_ST_UNLOCKED) {
clear_bit(GLF_DEMOTE, &gl->gl_flags);
return 0;
}
set_bit(GLF_LOCK, &gl->gl_flags);
spin_unlock(&gl->gl_spin);
if (gl->gl_demote_state == LM_ST_UNLOCKED ||
gl->gl_state != LM_ST_EXCLUSIVE)
gfs2_glock_drop_th(gl);
else
gfs2_glock_xmote_th(gl, NULL);
spin_lock(&gl->gl_spin);

return 0;
}
Expand Down Expand Up @@ -617,16 +562,8 @@ static void run_queue(struct gfs2_glock *gl)
else
gfs2_assert_warn(gl->gl_sbd, 0);

} else if (!list_empty(&gl->gl_waiters2) &&
!test_bit(GLF_SKIP_WAITERS2, &gl->gl_flags)) {
gh = list_entry(gl->gl_waiters2.next,
struct gfs2_holder, gh_list);

if (test_bit(HIF_DEMOTE, &gh->gh_iflags))
blocked = rq_demote(gh);
else
gfs2_assert_warn(gl->gl_sbd, 0);

} else if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
blocked = rq_demote(gl);
} else if (!list_empty(&gl->gl_waiters3)) {
gh = list_entry(gl->gl_waiters3.next,
struct gfs2_holder, gh_list);
Expand Down Expand Up @@ -717,50 +654,24 @@ static void gfs2_glmutex_unlock(struct gfs2_glock *gl)
}

/**
* handle_callback - add a demote request to a lock's queue
* handle_callback - process a demote request
* @gl: the glock
* @state: the state the caller wants us to change to
*
* Note: This may fail sliently if we are out of memory.
* There are only two requests that we are going to see in actual
* practise: LM_ST_SHARED and LM_ST_UNLOCKED
*/

static void handle_callback(struct gfs2_glock *gl, unsigned int state)
{
struct gfs2_holder *gh, *new_gh = NULL;

restart:
spin_lock(&gl->gl_spin);

list_for_each_entry(gh, &gl->gl_waiters2, gh_list) {
if (test_bit(HIF_DEMOTE, &gh->gh_iflags) &&
gl->gl_req_gh != gh) {
if (gh->gh_state != state)
gh->gh_state = LM_ST_UNLOCKED;
goto out;
}
}

if (new_gh) {
list_add_tail(&new_gh->gh_list, &gl->gl_waiters2);
new_gh = NULL;
} else {
spin_unlock(&gl->gl_spin);

new_gh = gfs2_holder_get(gl, state, LM_FLAG_TRY, GFP_NOFS);
if (!new_gh)
return;
set_bit(HIF_DEMOTE, &new_gh->gh_iflags);
set_bit(HIF_DEALLOC, &new_gh->gh_iflags);
set_bit(HIF_WAIT, &new_gh->gh_iflags);

goto restart;
if (test_and_set_bit(GLF_DEMOTE, &gl->gl_flags) == 0) {
gl->gl_demote_state = state;
gl->gl_demote_time = jiffies;
} else if (gl->gl_demote_state != LM_ST_UNLOCKED) {
gl->gl_demote_state = state;
}

out:
spin_unlock(&gl->gl_spin);

if (new_gh)
gfs2_holder_put(new_gh);
}

/**
Expand Down Expand Up @@ -820,56 +731,37 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)

/* Deal with each possible exit condition */

if (!gh)
if (!gh) {
gl->gl_stamp = jiffies;
else if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
if (ret & LM_OUT_CANCELED)
op_done = 0;
else
clear_bit(GLF_DEMOTE, &gl->gl_flags);
} else {
spin_lock(&gl->gl_spin);
list_del_init(&gh->gh_list);
gh->gh_error = -EIO;
spin_unlock(&gl->gl_spin);
} else if (test_bit(HIF_DEMOTE, &gh->gh_iflags)) {
spin_lock(&gl->gl_spin);
list_del_init(&gh->gh_list);
if (gl->gl_state == gh->gh_state ||
gl->gl_state == LM_ST_UNLOCKED) {
if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
goto out;
gh->gh_error = GLR_CANCELED;
if (ret & LM_OUT_CANCELED)
goto out;
if (relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) {
list_add_tail(&gh->gh_list, &gl->gl_holders);
gh->gh_error = 0;
} else {
if (gfs2_assert_warn(sdp, gh->gh_flags &
(LM_FLAG_TRY | LM_FLAG_TRY_1CB)) == -1)
fs_warn(sdp, "ret = 0x%.8X\n", ret);
gh->gh_error = GLR_TRYFAILED;
set_bit(HIF_HOLDER, &gh->gh_iflags);
set_bit(HIF_FIRST, &gh->gh_iflags);
op_done = 0;
goto out;
}
spin_unlock(&gl->gl_spin);

if (ret & LM_OUT_CANCELED)
handle_callback(gl, LM_ST_UNLOCKED);

} else if (ret & LM_OUT_CANCELED) {
spin_lock(&gl->gl_spin);
list_del_init(&gh->gh_list);
gh->gh_error = GLR_CANCELED;
spin_unlock(&gl->gl_spin);

} else if (relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) {
spin_lock(&gl->gl_spin);
list_move_tail(&gh->gh_list, &gl->gl_holders);
gh->gh_error = 0;
set_bit(HIF_HOLDER, &gh->gh_iflags);
spin_unlock(&gl->gl_spin);

set_bit(HIF_FIRST, &gh->gh_iflags);

op_done = 0;

} else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) {
spin_lock(&gl->gl_spin);
list_del_init(&gh->gh_list);
gh->gh_error = GLR_TRYFAILED;
spin_unlock(&gl->gl_spin);

} else {
if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))
goto out;
gh->gh_error = -EINVAL;
if (gfs2_assert_withdraw(sdp, 0) == -1)
fs_err(sdp, "ret = 0x%.8X\n", ret);
out:
spin_unlock(&gl->gl_spin);
}

if (glops->go_xmote_bh)
Expand All @@ -887,7 +779,7 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
gfs2_glock_put(gl);

if (gh)
gfs2_holder_dispose_or_wake(gh);
gfs2_holder_wake(gh);
}

/**
Expand All @@ -898,12 +790,11 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
*
*/

void gfs2_glock_xmote_th(struct gfs2_holder *gh)
void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
{
struct gfs2_glock *gl = gh->gh_gl;
struct gfs2_sbd *sdp = gl->gl_sbd;
int flags = gh->gh_flags;
unsigned state = gh->gh_state;
int flags = gh ? gh->gh_flags : 0;
unsigned state = gh ? gh->gh_state : gl->gl_demote_state;
const struct gfs2_glock_operations *glops = gl->gl_ops;
int lck_flags = flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB |
LM_FLAG_NOEXP | LM_FLAG_ANY |
Expand Down Expand Up @@ -953,6 +844,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
gfs2_assert_warn(sdp, !ret);

state_change(gl, LM_ST_UNLOCKED);
clear_bit(GLF_DEMOTE, &gl->gl_flags);

if (glops->go_inval)
glops->go_inval(gl, DIO_METADATA);
Expand All @@ -974,7 +866,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
gfs2_glock_put(gl);

if (gh)
gfs2_holder_dispose_or_wake(gh);
gfs2_holder_wake(gh);
}

/**
Expand Down Expand Up @@ -1291,9 +1183,8 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
if (glops->go_unlock)
glops->go_unlock(gh);

gl->gl_stamp = jiffies;

spin_lock(&gl->gl_spin);
gl->gl_stamp = jiffies;
}

clear_bit(GLF_LOCK, &gl->gl_flags);
Expand Down Expand Up @@ -1981,16 +1872,16 @@ static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl)
if (error)
goto out;
}
list_for_each_entry(gh, &gl->gl_waiters2, gh_list) {
error = dump_holder(gi, "Waiter2", gh);
if (error)
goto out;
}
list_for_each_entry(gh, &gl->gl_waiters3, gh_list) {
error = dump_holder(gi, "Waiter3", gh);
if (error)
goto out;
}
if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
print_dbg(gi, " Demotion req to state %u (%llu uS ago)\n",
gl->gl_demote_state,
(u64)(jiffies - gl->gl_demote_time)*1000000/HZ);
}
if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) {
if (!test_bit(GLF_LOCK, &gl->gl_flags) &&
list_empty(&gl->gl_holders)) {
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/gfs2/glock.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl)
{
int ret;
spin_lock(&gl->gl_spin);
ret = !list_empty(&gl->gl_waiters2) || !list_empty(&gl->gl_waiters3);
ret = test_bit(GLF_DEMOTE, &gl->gl_flags) || !list_empty(&gl->gl_waiters3);
spin_unlock(&gl->gl_spin);
return ret;
}
Expand Down
Loading

0 comments on commit 652b5c7

Please sign in to comment.