mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
gfs2: sanitize the gdlm_ast -> finish_xmote interface
When gdlm_ast() is called with a non-zero status code, this means that the requested operation did not succeed and the current lock state didn't change. Turn that into a non-zero LM_OUT_* status code (with ret & ~LM_OUT_ST_MASK != 0) instead of pretending that dlm returned the current lock state. That way, we can easily change finish_xmote() to only update gl->gl_state when the state has actually changed. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: Andrew Price <anprice@redhat.com>
This commit is contained in:
parent
75bb2ddea9
commit
6e417b3eb8
@ -590,20 +590,25 @@ static void gfs2_demote_wake(struct gfs2_glock *gl)
|
||||
static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
|
||||
{
|
||||
const struct gfs2_glock_operations *glops = gl->gl_ops;
|
||||
struct gfs2_holder *gh;
|
||||
unsigned state = ret & LM_OUT_ST_MASK;
|
||||
|
||||
trace_gfs2_glock_state_change(gl, state);
|
||||
state_change(gl, state);
|
||||
gh = find_first_waiter(gl);
|
||||
if (!(ret & ~LM_OUT_ST_MASK)) {
|
||||
unsigned state = ret & LM_OUT_ST_MASK;
|
||||
|
||||
trace_gfs2_glock_state_change(gl, state);
|
||||
state_change(gl, state);
|
||||
}
|
||||
|
||||
|
||||
/* Demote to UN request arrived during demote to SH or DF */
|
||||
if (test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags) &&
|
||||
state != LM_ST_UNLOCKED && gl->gl_demote_state == LM_ST_UNLOCKED)
|
||||
gl->gl_state != LM_ST_UNLOCKED &&
|
||||
gl->gl_demote_state == LM_ST_UNLOCKED)
|
||||
gl->gl_target = LM_ST_UNLOCKED;
|
||||
|
||||
/* Check for state != intended state */
|
||||
if (unlikely(state != gl->gl_target)) {
|
||||
if (unlikely(gl->gl_state != gl->gl_target)) {
|
||||
struct gfs2_holder *gh = find_first_waiter(gl);
|
||||
|
||||
if (gh && (ret & LM_OUT_CANCELED))
|
||||
gfs2_holder_wake(gh);
|
||||
if (gh && !test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)) {
|
||||
@ -629,7 +634,7 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
switch(state) {
|
||||
switch(gl->gl_state) {
|
||||
/* Unlocked due to conversion deadlock, try again */
|
||||
case LM_ST_UNLOCKED:
|
||||
do_xmote(gl, gh, gl->gl_target);
|
||||
@ -640,8 +645,10 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
|
||||
do_xmote(gl, gh, LM_ST_UNLOCKED);
|
||||
break;
|
||||
default: /* Everything else */
|
||||
fs_err(gl->gl_name.ln_sbd, "wanted %u got %u\n",
|
||||
gl->gl_target, state);
|
||||
fs_err(gl->gl_name.ln_sbd,
|
||||
"glock %u:%llu requested=%u ret=%u\n",
|
||||
gl->gl_name.ln_type, gl->gl_name.ln_number,
|
||||
gl->gl_req, ret);
|
||||
GLOCK_BUG_ON(gl, 1);
|
||||
}
|
||||
return;
|
||||
@ -650,7 +657,7 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
|
||||
/* Fast path - we got what we asked for */
|
||||
if (test_and_clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags))
|
||||
gfs2_demote_wake(gl);
|
||||
if (state != LM_ST_UNLOCKED) {
|
||||
if (gl->gl_state != LM_ST_UNLOCKED) {
|
||||
if (glops->go_xmote_bh) {
|
||||
int rv;
|
||||
|
||||
|
@ -92,12 +92,22 @@ enum {
|
||||
* LM_OUT_ST_MASK
|
||||
* Masks the lower two bits of lock state in the returned value.
|
||||
*
|
||||
* LM_OUT_TRY_AGAIN
|
||||
* The trylock request failed.
|
||||
*
|
||||
* LM_OUT_DEADLOCK
|
||||
* The lock request failed because it would deadlock.
|
||||
*
|
||||
* LM_OUT_CANCELED
|
||||
* The lock request was canceled.
|
||||
*
|
||||
* LM_OUT_ERROR
|
||||
* The lock request timed out or failed.
|
||||
*/
|
||||
|
||||
#define LM_OUT_ST_MASK 0x00000003
|
||||
#define LM_OUT_TRY_AGAIN 0x00000020
|
||||
#define LM_OUT_DEADLOCK 0x00000010
|
||||
#define LM_OUT_CANCELED 0x00000008
|
||||
#define LM_OUT_ERROR 0x00000004
|
||||
|
||||
|
@ -119,7 +119,7 @@ static inline void gfs2_update_request_times(struct gfs2_glock *gl)
|
||||
static void gdlm_ast(void *arg)
|
||||
{
|
||||
struct gfs2_glock *gl = arg;
|
||||
unsigned ret = gl->gl_state;
|
||||
unsigned ret;
|
||||
|
||||
/* If the glock is dead, we only react to a dlm_unlock() reply. */
|
||||
if (__lockref_is_dead(&gl->gl_lockref) &&
|
||||
@ -139,13 +139,16 @@ static void gdlm_ast(void *arg)
|
||||
gfs2_glock_free(gl);
|
||||
return;
|
||||
case -DLM_ECANCEL: /* Cancel while getting lock */
|
||||
ret |= LM_OUT_CANCELED;
|
||||
ret = LM_OUT_CANCELED;
|
||||
goto out;
|
||||
case -EAGAIN: /* Try lock fails */
|
||||
ret = LM_OUT_TRY_AGAIN;
|
||||
goto out;
|
||||
case -EDEADLK: /* Deadlock detected */
|
||||
ret = LM_OUT_DEADLOCK;
|
||||
goto out;
|
||||
case -ETIMEDOUT: /* Canceled due to timeout */
|
||||
ret |= LM_OUT_ERROR;
|
||||
ret = LM_OUT_ERROR;
|
||||
goto out;
|
||||
case 0: /* Success */
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user