[GFS2] Don't do recursive locking in glock layer
This patch changes the last user of recursive locking so that it no longer needs this feature and removes it from the glock layer. This makes the glock code a lot simpler and easier to understand. Its also a prerequsite to adding support for the AOP_TRUNCATED_PAGE return code (or at least it is if you don't want your brain to melt in the process) I've left in a couple of checks just in case there is some place else in the code which is still using this feature that I didn't spot yet, but they can probably be removed long term. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
parent
3a2a9c96ac
commit
5965b1f479
3 changed files with 46 additions and 196 deletions
162
fs/gfs2/glock.c
162
fs/gfs2/glock.c
|
@ -449,86 +449,6 @@ void gfs2_holder_put(struct gfs2_holder *gh)
|
|||
kfree(gh);
|
||||
}
|
||||
|
||||
/**
|
||||
* handle_recurse - put other holder structures (marked recursive)
|
||||
* into the holders list
|
||||
* @gh: the holder structure
|
||||
*
|
||||
*/
|
||||
|
||||
static void handle_recurse(struct gfs2_holder *gh)
|
||||
{
|
||||
struct gfs2_glock *gl = gh->gh_gl;
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
struct gfs2_holder *tmp_gh, *safe;
|
||||
int found = 0;
|
||||
|
||||
BUG_ON(!spin_is_locked(&gl->gl_spin));
|
||||
|
||||
printk(KERN_INFO "recursion %016llx, %u\n", gl->gl_name.ln_number,
|
||||
gl->gl_name.ln_type);
|
||||
|
||||
if (gfs2_assert_warn(sdp, gh->gh_owner))
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(tmp_gh, safe, &gl->gl_waiters3, gh_list) {
|
||||
if (tmp_gh->gh_owner != gh->gh_owner)
|
||||
continue;
|
||||
|
||||
gfs2_assert_warn(sdp,
|
||||
test_bit(HIF_RECURSE, &tmp_gh->gh_iflags));
|
||||
|
||||
list_move_tail(&tmp_gh->gh_list, &gl->gl_holders);
|
||||
tmp_gh->gh_error = 0;
|
||||
set_bit(HIF_HOLDER, &tmp_gh->gh_iflags);
|
||||
|
||||
complete(&tmp_gh->gh_wait);
|
||||
|
||||
found = 1;
|
||||
}
|
||||
|
||||
gfs2_assert_warn(sdp, found);
|
||||
}
|
||||
|
||||
/**
|
||||
* do_unrecurse - a recursive holder was just dropped of the waiters3 list
|
||||
* @gh: the holder
|
||||
*
|
||||
* If there is only one other recursive holder, clear its HIF_RECURSE bit.
|
||||
* If there is more than one, leave them alone.
|
||||
*
|
||||
*/
|
||||
|
||||
static void do_unrecurse(struct gfs2_holder *gh)
|
||||
{
|
||||
struct gfs2_glock *gl = gh->gh_gl;
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
struct gfs2_holder *tmp_gh, *last_gh = NULL;
|
||||
int found = 0;
|
||||
|
||||
BUG_ON(!spin_is_locked(&gl->gl_spin));
|
||||
|
||||
if (gfs2_assert_warn(sdp, gh->gh_owner))
|
||||
return;
|
||||
|
||||
list_for_each_entry(tmp_gh, &gl->gl_waiters3, gh_list) {
|
||||
if (tmp_gh->gh_owner != gh->gh_owner)
|
||||
continue;
|
||||
|
||||
gfs2_assert_warn(sdp,
|
||||
test_bit(HIF_RECURSE, &tmp_gh->gh_iflags));
|
||||
|
||||
if (found)
|
||||
return;
|
||||
|
||||
found = 1;
|
||||
last_gh = tmp_gh;
|
||||
}
|
||||
|
||||
if (!gfs2_assert_warn(sdp, found))
|
||||
clear_bit(HIF_RECURSE, &last_gh->gh_iflags);
|
||||
}
|
||||
|
||||
/**
|
||||
* rq_mutex - process a mutex request in the queue
|
||||
* @gh: the glock holder
|
||||
|
@ -562,7 +482,6 @@ static int rq_promote(struct gfs2_holder *gh)
|
|||
struct gfs2_glock *gl = gh->gh_gl;
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
struct gfs2_glock_operations *glops = gl->gl_ops;
|
||||
int recurse;
|
||||
|
||||
if (!relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) {
|
||||
if (list_empty(&gl->gl_holders)) {
|
||||
|
@ -588,7 +507,6 @@ static int rq_promote(struct gfs2_holder *gh)
|
|||
if (list_empty(&gl->gl_holders)) {
|
||||
set_bit(HIF_FIRST, &gh->gh_iflags);
|
||||
set_bit(GLF_LOCK, &gl->gl_flags);
|
||||
recurse = 0;
|
||||
} else {
|
||||
struct gfs2_holder *next_gh;
|
||||
if (gh->gh_flags & GL_LOCAL_EXCL)
|
||||
|
@ -597,16 +515,12 @@ static int rq_promote(struct gfs2_holder *gh)
|
|||
gh_list);
|
||||
if (next_gh->gh_flags & GL_LOCAL_EXCL)
|
||||
return 1;
|
||||
recurse = test_bit(HIF_RECURSE, &gh->gh_iflags);
|
||||
}
|
||||
|
||||
list_move_tail(&gh->gh_list, &gl->gl_holders);
|
||||
gh->gh_error = 0;
|
||||
set_bit(HIF_HOLDER, &gh->gh_iflags);
|
||||
|
||||
if (recurse)
|
||||
handle_recurse(gh);
|
||||
|
||||
complete(&gh->gh_wait);
|
||||
|
||||
return 0;
|
||||
|
@ -897,8 +811,6 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
|
|||
spin_lock(&gl->gl_spin);
|
||||
list_del_init(&gh->gh_list);
|
||||
gh->gh_error = -EIO;
|
||||
if (test_bit(HIF_RECURSE, &gh->gh_iflags))
|
||||
do_unrecurse(gh);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
|
||||
} else if (test_bit(HIF_DEMOTE, &gh->gh_iflags)) {
|
||||
|
@ -922,8 +834,6 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
|
|||
spin_lock(&gl->gl_spin);
|
||||
list_del_init(&gh->gh_list);
|
||||
gh->gh_error = GLR_CANCELED;
|
||||
if (test_bit(HIF_RECURSE, &gh->gh_iflags))
|
||||
do_unrecurse(gh);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
|
||||
} else if (relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) {
|
||||
|
@ -941,8 +851,6 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
|
|||
spin_lock(&gl->gl_spin);
|
||||
list_del_init(&gh->gh_list);
|
||||
gh->gh_error = GLR_TRYFAILED;
|
||||
if (test_bit(HIF_RECURSE, &gh->gh_iflags))
|
||||
do_unrecurse(gh);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
|
||||
} else {
|
||||
|
@ -1161,8 +1069,6 @@ static int glock_wait_internal(struct gfs2_holder *gh)
|
|||
!list_empty(&gh->gh_list)) {
|
||||
list_del_init(&gh->gh_list);
|
||||
gh->gh_error = GLR_TRYFAILED;
|
||||
if (test_bit(HIF_RECURSE, &gh->gh_iflags))
|
||||
do_unrecurse(gh);
|
||||
run_queue(gl);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
return gh->gh_error;
|
||||
|
@ -1191,9 +1097,6 @@ static int glock_wait_internal(struct gfs2_holder *gh)
|
|||
if (gh->gh_error) {
|
||||
spin_lock(&gl->gl_spin);
|
||||
list_del_init(&gh->gh_list);
|
||||
if (test_and_clear_bit(HIF_RECURSE,
|
||||
&gh->gh_iflags))
|
||||
do_unrecurse(gh);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
}
|
||||
}
|
||||
|
@ -1202,8 +1105,6 @@ static int glock_wait_internal(struct gfs2_holder *gh)
|
|||
gl->gl_req_gh = NULL;
|
||||
gl->gl_req_bh = NULL;
|
||||
clear_bit(GLF_LOCK, &gl->gl_flags);
|
||||
if (test_bit(HIF_RECURSE, &gh->gh_iflags))
|
||||
handle_recurse(gh);
|
||||
run_queue(gl);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
}
|
||||
|
@ -1224,40 +1125,6 @@ find_holder_by_owner(struct list_head *head, struct task_struct *owner)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* recurse_check -
|
||||
*
|
||||
* Make sure the new holder is compatible with the pre-existing one.
|
||||
*
|
||||
*/
|
||||
|
||||
static int recurse_check(struct gfs2_holder *existing, struct gfs2_holder *new,
|
||||
unsigned int state)
|
||||
{
|
||||
struct gfs2_sbd *sdp = existing->gh_gl->gl_sbd;
|
||||
|
||||
if (gfs2_assert_warn(sdp, (new->gh_flags & LM_FLAG_ANY) ||
|
||||
!(existing->gh_flags & LM_FLAG_ANY)))
|
||||
goto fail;
|
||||
|
||||
if (gfs2_assert_warn(sdp, (existing->gh_flags & GL_LOCAL_EXCL) ||
|
||||
!(new->gh_flags & GL_LOCAL_EXCL)))
|
||||
goto fail;
|
||||
|
||||
if (gfs2_assert_warn(sdp, relaxed_state_ok(state, new->gh_state,
|
||||
new->gh_flags)))
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
print_symbol(KERN_WARNING "GFS2: Existing holder from %s\n",
|
||||
existing->gh_ip);
|
||||
print_symbol(KERN_WARNING "GFS2: New holder from %s\n", new->gh_ip);
|
||||
set_bit(HIF_ABORTED, &new->gh_iflags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* add_to_queue - Add a holder to the wait queue (but look for recursion)
|
||||
* @gh: the holder structure to add
|
||||
|
@ -1271,37 +1138,20 @@ static void add_to_queue(struct gfs2_holder *gh)
|
|||
|
||||
BUG_ON(!gh->gh_owner);
|
||||
|
||||
if (!gh->gh_owner)
|
||||
goto out;
|
||||
|
||||
existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner);
|
||||
if (existing) {
|
||||
if (recurse_check(existing, gh, gl->gl_state))
|
||||
return;
|
||||
|
||||
list_add_tail(&gh->gh_list, &gl->gl_holders);
|
||||
set_bit(HIF_HOLDER, &gh->gh_iflags);
|
||||
|
||||
gh->gh_error = 0;
|
||||
complete(&gh->gh_wait);
|
||||
|
||||
return;
|
||||
print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip);
|
||||
print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip);
|
||||
BUG();
|
||||
}
|
||||
|
||||
existing = find_holder_by_owner(&gl->gl_waiters3, gh->gh_owner);
|
||||
if (existing) {
|
||||
if (recurse_check(existing, gh, existing->gh_state))
|
||||
return;
|
||||
|
||||
set_bit(HIF_RECURSE, &gh->gh_iflags);
|
||||
set_bit(HIF_RECURSE, &existing->gh_iflags);
|
||||
|
||||
list_add_tail(&gh->gh_list, &gl->gl_waiters3);
|
||||
|
||||
return;
|
||||
print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip);
|
||||
print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip);
|
||||
BUG();
|
||||
}
|
||||
|
||||
out:
|
||||
if (gh->gh_flags & LM_FLAG_PRIORITY)
|
||||
list_add(&gh->gh_list, &gl->gl_waiters3);
|
||||
else
|
||||
|
|
|
@ -146,7 +146,6 @@ enum {
|
|||
HIF_DEALLOC = 5,
|
||||
HIF_HOLDER = 6,
|
||||
HIF_FIRST = 7,
|
||||
HIF_RECURSE = 8,
|
||||
HIF_ABORTED = 9,
|
||||
};
|
||||
|
||||
|
|
|
@ -436,30 +436,35 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
|
|||
unsigned int pass;
|
||||
int error;
|
||||
|
||||
fs_info(sdp, "jid=%u: Trying to acquire journal lock...\n", jd->jd_jid);
|
||||
if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) {
|
||||
fs_info(sdp, "jid=%u: Trying to acquire journal lock...\n",
|
||||
jd->jd_jid);
|
||||
|
||||
/* Aquire the journal lock so we can do recovery */
|
||||
/* Aquire the journal lock so we can do recovery */
|
||||
|
||||
error = gfs2_glock_nq_num(sdp, jd->jd_jid, &gfs2_journal_glops,
|
||||
LM_ST_EXCLUSIVE,
|
||||
LM_FLAG_NOEXP | LM_FLAG_TRY | GL_NOCACHE,
|
||||
&j_gh);
|
||||
switch (error) {
|
||||
case 0:
|
||||
break;
|
||||
error = gfs2_glock_nq_num(sdp, jd->jd_jid, &gfs2_journal_glops,
|
||||
LM_ST_EXCLUSIVE,
|
||||
LM_FLAG_NOEXP | LM_FLAG_TRY | GL_NOCACHE,
|
||||
&j_gh);
|
||||
switch (error) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case GLR_TRYFAILED:
|
||||
fs_info(sdp, "jid=%u: Busy\n", jd->jd_jid);
|
||||
error = 0;
|
||||
case GLR_TRYFAILED:
|
||||
fs_info(sdp, "jid=%u: Busy\n", jd->jd_jid);
|
||||
error = 0;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
};
|
||||
default:
|
||||
goto fail;
|
||||
};
|
||||
|
||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
|
||||
LM_FLAG_NOEXP, &ji_gh);
|
||||
if (error)
|
||||
goto fail_gunlock_j;
|
||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
|
||||
LM_FLAG_NOEXP, &ji_gh);
|
||||
if (error)
|
||||
goto fail_gunlock_j;
|
||||
} else {
|
||||
fs_info(sdp, "jid=%u, already locked for use\n", jd->jd_jid);
|
||||
}
|
||||
|
||||
fs_info(sdp, "jid=%u: Looking at journal...\n", jd->jd_jid);
|
||||
|
||||
|
@ -481,10 +486,8 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
|
|||
|
||||
error = gfs2_glock_nq_init(sdp->sd_trans_gl,
|
||||
LM_ST_SHARED,
|
||||
LM_FLAG_NOEXP |
|
||||
LM_FLAG_PRIORITY |
|
||||
GL_NEVER_RECURSE |
|
||||
GL_NOCANCEL |
|
||||
LM_FLAG_NOEXP | LM_FLAG_PRIORITY |
|
||||
GL_NEVER_RECURSE | GL_NOCANCEL |
|
||||
GL_NOCACHE,
|
||||
&t_gh);
|
||||
if (error)
|
||||
|
@ -521,37 +524,35 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
|
|||
goto fail_gunlock_tr;
|
||||
|
||||
gfs2_glock_dq_uninit(&t_gh);
|
||||
|
||||
t = DIV_ROUND_UP(jiffies - t, HZ);
|
||||
|
||||
fs_info(sdp, "jid=%u: Journal replayed in %lus\n",
|
||||
jd->jd_jid, t);
|
||||
}
|
||||
|
||||
gfs2_glock_dq_uninit(&ji_gh);
|
||||
if (jd->jd_jid != sdp->sd_lockstruct.ls_jid)
|
||||
gfs2_glock_dq_uninit(&ji_gh);
|
||||
|
||||
gfs2_lm_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS);
|
||||
|
||||
gfs2_glock_dq_uninit(&j_gh);
|
||||
if (jd->jd_jid != sdp->sd_lockstruct.ls_jid)
|
||||
gfs2_glock_dq_uninit(&j_gh);
|
||||
|
||||
fs_info(sdp, "jid=%u: Done\n", jd->jd_jid);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_gunlock_tr:
|
||||
fail_gunlock_tr:
|
||||
gfs2_glock_dq_uninit(&t_gh);
|
||||
|
||||
fail_gunlock_ji:
|
||||
gfs2_glock_dq_uninit(&ji_gh);
|
||||
|
||||
fail_gunlock_j:
|
||||
gfs2_glock_dq_uninit(&j_gh);
|
||||
fail_gunlock_ji:
|
||||
if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) {
|
||||
gfs2_glock_dq_uninit(&ji_gh);
|
||||
fail_gunlock_j:
|
||||
gfs2_glock_dq_uninit(&j_gh);
|
||||
}
|
||||
|
||||
fs_info(sdp, "jid=%u: %s\n", jd->jd_jid, (error) ? "Failed" : "Done");
|
||||
|
||||
fail:
|
||||
fail:
|
||||
gfs2_lm_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue