Skip to content

Commit 0befb85

Browse files
AstralBobAndreas Gruenbacher
authored andcommitted
gfs2: do_promote glock holder stealing fix
In do_promote(), when the glock had no strong holders, we were accidentally calling demote_incompat_holders() with new_gh == NULL, so no weak holders were considered incompatible. Instead, the new holder should have been passed in. For doing that, the HIF_HOLDER flag needs to be set in new_gh to prevent may_grant() from complaining. This means that the new holder will now be recognized as a current holder, so skip over it explicitly in demote_incompat_holders() to prevent it from being dequeued. To further clarify things, we can now rename new_gh to current_gh in demote_incompat_holders(); after all, the HIF_HOLDER flag is already set, which means the new holder is already a current holder. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
1 parent 8f0028f commit 0befb85

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

fs/gfs2/glock.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -405,10 +405,13 @@ static void do_error(struct gfs2_glock *gl, const int ret)
405405
/**
406406
* demote_incompat_holders - demote incompatible demoteable holders
407407
* @gl: the glock we want to promote
408-
* @new_gh: the new holder to be promoted
408+
* @current_gh: the newly promoted holder
409+
*
410+
* We're passing the newly promoted holder in @current_gh, but actually, any of
411+
* the strong holders would do.
409412
*/
410413
static void demote_incompat_holders(struct gfs2_glock *gl,
411-
struct gfs2_holder *new_gh)
414+
struct gfs2_holder *current_gh)
412415
{
413416
struct gfs2_holder *gh, *tmp;
414417

@@ -424,8 +427,10 @@ static void demote_incompat_holders(struct gfs2_glock *gl,
424427
*/
425428
if (!test_bit(HIF_HOLDER, &gh->gh_iflags))
426429
return;
430+
if (gh == current_gh)
431+
continue;
427432
if (test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags) &&
428-
!may_grant(gl, new_gh, gh)) {
433+
!may_grant(gl, current_gh, gh)) {
429434
/*
430435
* We should not recurse into do_promote because
431436
* __gfs2_glock_dq only calls handle_callback,
@@ -547,14 +552,14 @@ static int do_promote(struct gfs2_glock *gl)
547552
do_error(gl, 0);
548553
break;
549554
}
555+
set_bit(HIF_HOLDER, &gh->gh_iflags);
556+
trace_gfs2_promote(gh);
557+
gfs2_holder_wake(gh);
550558
if (!incompat_holders_demoted) {
559+
current_gh = gh;
551560
demote_incompat_holders(gl, current_gh);
552561
incompat_holders_demoted = true;
553-
current_gh = gh;
554562
}
555-
set_bit(HIF_HOLDER, &gh->gh_iflags);
556-
trace_gfs2_promote(gh);
557-
gfs2_holder_wake(gh);
558563
}
559564
return 0;
560565
}

0 commit comments

Comments
 (0)