mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 05:48:40 +00:00
gfs2: conversion deadlock do_promote bypass
Consider the following case: 1. A glock is held in shared mode. 2. A process requests the glock in exclusive mode (rename). 3. Before the lock is granted, more processes (read / ls) request the glock in shared mode again. 4. gfs2 sends a request to dlm for the lock in exclusive mode because that holder is at the head of the queue. 5. Somehow the dlm request gets canceled, so dlm sends us back a response with state == LM_ST_SHARED and LM_OUT_CANCELED. So at that point, the glock is still held in shared mode. 6. finish_xmote gets called to process the response from dlm. It detects that the glock is not in the requested mode and no demote is in progress, so it moves the canceled holder to the tail of the queue and finds the new holder at the head of the queue. That holder is requesting the glock in shared mode. 7. finish_xmote calls do_xmote to transition the glock into shared mode, but the glock is already in shared mode and so do_xmote complains about that with: GLOCK_BUG_ON(gl, gl->gl_state == gl->gl_target); Instead, in finish_xmote, after moving the canceled holder to the tail of the queue, check if any new holders can be granted. Only call do_xmote to repeat the dlm request if the holder at the head of the queue is requesting the glock in a mode that is incompatible with the mode the glock is currently held in. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
This commit is contained in:
parent
0b93bac227
commit
66fa9912ec
1 changed files with 2 additions and 0 deletions
|
@ -594,6 +594,8 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
|
|||
list_move_tail(&gh->gh_list, &gl->gl_holders);
|
||||
gh = find_first_waiter(gl);
|
||||
gl->gl_target = gh->gh_state;
|
||||
if (do_promote(gl))
|
||||
goto out;
|
||||
goto retry;
|
||||
}
|
||||
/* Some error or failed "try lock" - report it */
|
||||
|
|
Loading…
Reference in a new issue