diff options
Diffstat (limited to 'fs/gfs2/glock.c')
-rw-r--r-- | fs/gfs2/glock.c | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 27cb9cca9c08..4ddf3bd55dda 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "quota.h" | 40 | #include "quota.h" |
41 | #include "super.h" | 41 | #include "super.h" |
42 | #include "util.h" | 42 | #include "util.h" |
43 | #include "bmap.h" | ||
43 | 44 | ||
44 | struct gfs2_gl_hash_bucket { | 45 | struct gfs2_gl_hash_bucket { |
45 | struct hlist_head hb_list; | 46 | struct hlist_head hb_list; |
@@ -289,7 +290,8 @@ static void gfs2_holder_wake(struct gfs2_holder *gh) | |||
289 | * do_promote - promote as many requests as possible on the current queue | 290 | * do_promote - promote as many requests as possible on the current queue |
290 | * @gl: The glock | 291 | * @gl: The glock |
291 | * | 292 | * |
292 | * Returns: true if there is a blocked holder at the head of the list | 293 | * Returns: 1 if there is a blocked holder at the head of the list, or 2 |
294 | * if a type specific operation is underway. | ||
293 | */ | 295 | */ |
294 | 296 | ||
295 | static int do_promote(struct gfs2_glock *gl) | 297 | static int do_promote(struct gfs2_glock *gl) |
@@ -312,6 +314,8 @@ restart: | |||
312 | ret = glops->go_lock(gh); | 314 | ret = glops->go_lock(gh); |
313 | spin_lock(&gl->gl_spin); | 315 | spin_lock(&gl->gl_spin); |
314 | if (ret) { | 316 | if (ret) { |
317 | if (ret == 1) | ||
318 | return 2; | ||
315 | gh->gh_error = ret; | 319 | gh->gh_error = ret; |
316 | list_del_init(&gh->gh_list); | 320 | list_del_init(&gh->gh_list); |
317 | gfs2_holder_wake(gh); | 321 | gfs2_holder_wake(gh); |
@@ -416,6 +420,7 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret) | |||
416 | const struct gfs2_glock_operations *glops = gl->gl_ops; | 420 | const struct gfs2_glock_operations *glops = gl->gl_ops; |
417 | struct gfs2_holder *gh; | 421 | struct gfs2_holder *gh; |
418 | unsigned state = ret & LM_OUT_ST_MASK; | 422 | unsigned state = ret & LM_OUT_ST_MASK; |
423 | int rv; | ||
419 | 424 | ||
420 | spin_lock(&gl->gl_spin); | 425 | spin_lock(&gl->gl_spin); |
421 | state_change(gl, state); | 426 | state_change(gl, state); |
@@ -470,7 +475,6 @@ retry: | |||
470 | gfs2_demote_wake(gl); | 475 | gfs2_demote_wake(gl); |
471 | if (state != LM_ST_UNLOCKED) { | 476 | if (state != LM_ST_UNLOCKED) { |
472 | if (glops->go_xmote_bh) { | 477 | if (glops->go_xmote_bh) { |
473 | int rv; | ||
474 | spin_unlock(&gl->gl_spin); | 478 | spin_unlock(&gl->gl_spin); |
475 | rv = glops->go_xmote_bh(gl, gh); | 479 | rv = glops->go_xmote_bh(gl, gh); |
476 | if (rv == -EAGAIN) | 480 | if (rv == -EAGAIN) |
@@ -481,10 +485,13 @@ retry: | |||
481 | goto out; | 485 | goto out; |
482 | } | 486 | } |
483 | } | 487 | } |
484 | do_promote(gl); | 488 | rv = do_promote(gl); |
489 | if (rv == 2) | ||
490 | goto out_locked; | ||
485 | } | 491 | } |
486 | out: | 492 | out: |
487 | clear_bit(GLF_LOCK, &gl->gl_flags); | 493 | clear_bit(GLF_LOCK, &gl->gl_flags); |
494 | out_locked: | ||
488 | spin_unlock(&gl->gl_spin); | 495 | spin_unlock(&gl->gl_spin); |
489 | gfs2_glock_put(gl); | 496 | gfs2_glock_put(gl); |
490 | } | 497 | } |
@@ -584,6 +591,7 @@ __releases(&gl->gl_spin) | |||
584 | __acquires(&gl->gl_spin) | 591 | __acquires(&gl->gl_spin) |
585 | { | 592 | { |
586 | struct gfs2_holder *gh = NULL; | 593 | struct gfs2_holder *gh = NULL; |
594 | int ret; | ||
587 | 595 | ||
588 | if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) | 596 | if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) |
589 | return; | 597 | return; |
@@ -602,8 +610,11 @@ __acquires(&gl->gl_spin) | |||
602 | } else { | 610 | } else { |
603 | if (test_bit(GLF_DEMOTE, &gl->gl_flags)) | 611 | if (test_bit(GLF_DEMOTE, &gl->gl_flags)) |
604 | gfs2_demote_wake(gl); | 612 | gfs2_demote_wake(gl); |
605 | if (do_promote(gl) == 0) | 613 | ret = do_promote(gl); |
614 | if (ret == 0) | ||
606 | goto out; | 615 | goto out; |
616 | if (ret == 2) | ||
617 | return; | ||
607 | gh = find_first_waiter(gl); | 618 | gh = find_first_waiter(gl); |
608 | gl->gl_target = gh->gh_state; | 619 | gl->gl_target = gh->gh_state; |
609 | if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) | 620 | if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) |
@@ -1556,6 +1567,20 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) | |||
1556 | } | 1567 | } |
1557 | } | 1568 | } |
1558 | 1569 | ||
1570 | void gfs2_glock_finish_truncate(struct gfs2_inode *ip) | ||
1571 | { | ||
1572 | struct gfs2_glock *gl = ip->i_gl; | ||
1573 | int ret; | ||
1574 | |||
1575 | ret = gfs2_truncatei_resume(ip); | ||
1576 | gfs2_assert_withdraw(gl->gl_sbd, ret == 0); | ||
1577 | |||
1578 | spin_lock(&gl->gl_spin); | ||
1579 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
1580 | run_queue(gl, 1); | ||
1581 | spin_unlock(&gl->gl_spin); | ||
1582 | } | ||
1583 | |||
1559 | static const char *state2str(unsigned state) | 1584 | static const char *state2str(unsigned state) |
1560 | { | 1585 | { |
1561 | switch(state) { | 1586 | switch(state) { |