UPSTREAM: gfs2: Clean up function may_grant
commit 6144464937fe1e6135b13a30502a339d549bf093 upstream
Pass the first current glock holder into function may_grant and
deobfuscate the logic there.
While at it, switch from BUG_ON to GLOCK_BUG_ON in may_grant. To make
that build cleanly, de-constify the may_grant arguments.
We're now using function find_first_holder in do_promote, so move the
function's definition above do_promote.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit b25cfbc0e7)
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Ib02a752cdf8da470494fa06782bc92ca3f047a6f
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
3b46c843f2
commit
d0e98c116d
117
fs/gfs2/glock.c
117
fs/gfs2/glock.c
@@ -301,46 +301,59 @@ void gfs2_glock_put(struct gfs2_glock *gl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* may_grant - check if its ok to grant a new lock
|
* may_grant - check if it's ok to grant a new lock
|
||||||
* @gl: The glock
|
* @gl: The glock
|
||||||
|
* @current_gh: One of the current holders of @gl
|
||||||
* @gh: The lock request which we wish to grant
|
* @gh: The lock request which we wish to grant
|
||||||
*
|
*
|
||||||
* Returns: true if its ok to grant the lock
|
* With our current compatibility rules, if a glock has one or more active
|
||||||
|
* holders (HIF_HOLDER flag set), any of those holders can be passed in as
|
||||||
|
* @current_gh; they are all the same as far as compatibility with the new @gh
|
||||||
|
* goes.
|
||||||
|
*
|
||||||
|
* Returns true if it's ok to grant the lock.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline int may_grant(const struct gfs2_glock *gl, const struct gfs2_holder *gh)
|
static inline bool may_grant(struct gfs2_glock *gl,
|
||||||
|
struct gfs2_holder *current_gh,
|
||||||
|
struct gfs2_holder *gh)
|
||||||
{
|
{
|
||||||
const struct gfs2_holder *gh_head = list_first_entry(&gl->gl_holders, const struct gfs2_holder, gh_list);
|
if (current_gh) {
|
||||||
|
GLOCK_BUG_ON(gl, !test_bit(HIF_HOLDER, ¤t_gh->gh_iflags));
|
||||||
|
|
||||||
if (gh != gh_head) {
|
switch(current_gh->gh_state) {
|
||||||
/**
|
case LM_ST_EXCLUSIVE:
|
||||||
* Here we make a special exception to grant holders who agree
|
/*
|
||||||
* to share the EX lock with other holders who also have the
|
* Here we make a special exception to grant holders
|
||||||
* bit set. If the original holder has the LM_FLAG_NODE_SCOPE bit
|
* who agree to share the EX lock with other holders
|
||||||
* is set, we grant more holders with the bit set.
|
* who also have the bit set. If the original holder
|
||||||
*/
|
* has the LM_FLAG_NODE_SCOPE bit set, we grant more
|
||||||
if (gh_head->gh_state == LM_ST_EXCLUSIVE &&
|
* holders with the bit set.
|
||||||
(gh_head->gh_flags & LM_FLAG_NODE_SCOPE) &&
|
*/
|
||||||
gh->gh_state == LM_ST_EXCLUSIVE &&
|
return gh->gh_state == LM_ST_EXCLUSIVE &&
|
||||||
(gh->gh_flags & LM_FLAG_NODE_SCOPE))
|
(current_gh->gh_flags & LM_FLAG_NODE_SCOPE) &&
|
||||||
return 1;
|
(gh->gh_flags & LM_FLAG_NODE_SCOPE);
|
||||||
if ((gh->gh_state == LM_ST_EXCLUSIVE ||
|
|
||||||
gh_head->gh_state == LM_ST_EXCLUSIVE))
|
case LM_ST_SHARED:
|
||||||
return 0;
|
case LM_ST_DEFERRED:
|
||||||
|
return gh->gh_state == current_gh->gh_state;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gl->gl_state == gh->gh_state)
|
if (gl->gl_state == gh->gh_state)
|
||||||
return 1;
|
return true;
|
||||||
if (gh->gh_flags & GL_EXACT)
|
if (gh->gh_flags & GL_EXACT)
|
||||||
return 0;
|
return false;
|
||||||
if (gl->gl_state == LM_ST_EXCLUSIVE) {
|
if (gl->gl_state == LM_ST_EXCLUSIVE) {
|
||||||
if (gh->gh_state == LM_ST_SHARED && gh_head->gh_state == LM_ST_SHARED)
|
return gh->gh_state == LM_ST_SHARED ||
|
||||||
return 1;
|
gh->gh_state == LM_ST_DEFERRED;
|
||||||
if (gh->gh_state == LM_ST_DEFERRED && gh_head->gh_state == LM_ST_DEFERRED)
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
if (gl->gl_state != LM_ST_UNLOCKED && (gh->gh_flags & LM_FLAG_ANY))
|
if (gh->gh_flags & LM_FLAG_ANY)
|
||||||
return 1;
|
return gl->gl_state != LM_ST_UNLOCKED;
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gfs2_holder_wake(struct gfs2_holder *gh)
|
static void gfs2_holder_wake(struct gfs2_holder *gh)
|
||||||
@@ -380,6 +393,24 @@ static void do_error(struct gfs2_glock *gl, const int ret)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_first_holder - find the first "holder" gh
|
||||||
|
* @gl: the glock
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline struct gfs2_holder *find_first_holder(const struct gfs2_glock *gl)
|
||||||
|
{
|
||||||
|
struct gfs2_holder *gh;
|
||||||
|
|
||||||
|
if (!list_empty(&gl->gl_holders)) {
|
||||||
|
gh = list_first_entry(&gl->gl_holders, struct gfs2_holder,
|
||||||
|
gh_list);
|
||||||
|
if (test_bit(HIF_HOLDER, &gh->gh_iflags))
|
||||||
|
return gh;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* do_promote - promote as many requests as possible on the current queue
|
* do_promote - promote as many requests as possible on the current queue
|
||||||
* @gl: The glock
|
* @gl: The glock
|
||||||
@@ -393,14 +424,15 @@ __releases(&gl->gl_lockref.lock)
|
|||||||
__acquires(&gl->gl_lockref.lock)
|
__acquires(&gl->gl_lockref.lock)
|
||||||
{
|
{
|
||||||
const struct gfs2_glock_operations *glops = gl->gl_ops;
|
const struct gfs2_glock_operations *glops = gl->gl_ops;
|
||||||
struct gfs2_holder *gh, *tmp;
|
struct gfs2_holder *gh, *tmp, *first_gh;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
|
first_gh = find_first_holder(gl);
|
||||||
list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
|
list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
|
||||||
if (test_bit(HIF_HOLDER, &gh->gh_iflags))
|
if (test_bit(HIF_HOLDER, &gh->gh_iflags))
|
||||||
continue;
|
continue;
|
||||||
if (may_grant(gl, gh)) {
|
if (may_grant(gl, first_gh, gh)) {
|
||||||
if (gh->gh_list.prev == &gl->gl_holders &&
|
if (gh->gh_list.prev == &gl->gl_holders &&
|
||||||
glops->go_lock) {
|
glops->go_lock) {
|
||||||
spin_unlock(&gl->gl_lockref.lock);
|
spin_unlock(&gl->gl_lockref.lock);
|
||||||
@@ -722,23 +754,6 @@ out:
|
|||||||
spin_lock(&gl->gl_lockref.lock);
|
spin_lock(&gl->gl_lockref.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* find_first_holder - find the first "holder" gh
|
|
||||||
* @gl: the glock
|
|
||||||
*/
|
|
||||||
|
|
||||||
static inline struct gfs2_holder *find_first_holder(const struct gfs2_glock *gl)
|
|
||||||
{
|
|
||||||
struct gfs2_holder *gh;
|
|
||||||
|
|
||||||
if (!list_empty(&gl->gl_holders)) {
|
|
||||||
gh = list_first_entry(&gl->gl_holders, struct gfs2_holder, gh_list);
|
|
||||||
if (test_bit(HIF_HOLDER, &gh->gh_iflags))
|
|
||||||
return gh;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* run_queue - do all outstanding tasks related to a glock
|
* run_queue - do all outstanding tasks related to a glock
|
||||||
* @gl: The glock in question
|
* @gl: The glock in question
|
||||||
@@ -1354,8 +1369,12 @@ __acquires(&gl->gl_lockref.lock)
|
|||||||
GLOCK_BUG_ON(gl, true);
|
GLOCK_BUG_ON(gl, true);
|
||||||
|
|
||||||
if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) {
|
if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) {
|
||||||
if (test_bit(GLF_LOCK, &gl->gl_flags))
|
if (test_bit(GLF_LOCK, &gl->gl_flags)) {
|
||||||
try_futile = !may_grant(gl, gh);
|
struct gfs2_holder *first_gh;
|
||||||
|
|
||||||
|
first_gh = find_first_holder(gl);
|
||||||
|
try_futile = !may_grant(gl, first_gh, gh);
|
||||||
|
}
|
||||||
if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags))
|
if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user