diff options
-rw-r--r-- | fs/gfs2/glock.c | 52 | ||||
-rw-r--r-- | fs/gfs2/glock.h | 1 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 1 | ||||
-rw-r--r-- | fs/gfs2/ops_super.c | 8 |
4 files changed, 48 insertions, 14 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index b3ed58551e74..384cae623ed3 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -422,11 +422,11 @@ void gfs2_holder_uninit(struct gfs2_holder *gh) | |||
422 | static void gfs2_holder_wake(struct gfs2_holder *gh) | 422 | static void gfs2_holder_wake(struct gfs2_holder *gh) |
423 | { | 423 | { |
424 | clear_bit(HIF_WAIT, &gh->gh_iflags); | 424 | clear_bit(HIF_WAIT, &gh->gh_iflags); |
425 | smp_mb(); | 425 | smp_mb__after_clear_bit(); |
426 | wake_up_bit(&gh->gh_iflags, HIF_WAIT); | 426 | wake_up_bit(&gh->gh_iflags, HIF_WAIT); |
427 | } | 427 | } |
428 | 428 | ||
429 | static int holder_wait(void *word) | 429 | static int just_schedule(void *word) |
430 | { | 430 | { |
431 | schedule(); | 431 | schedule(); |
432 | return 0; | 432 | return 0; |
@@ -435,7 +435,20 @@ static int holder_wait(void *word) | |||
435 | static void wait_on_holder(struct gfs2_holder *gh) | 435 | static void wait_on_holder(struct gfs2_holder *gh) |
436 | { | 436 | { |
437 | might_sleep(); | 437 | might_sleep(); |
438 | wait_on_bit(&gh->gh_iflags, HIF_WAIT, holder_wait, TASK_UNINTERRUPTIBLE); | 438 | wait_on_bit(&gh->gh_iflags, HIF_WAIT, just_schedule, TASK_UNINTERRUPTIBLE); |
439 | } | ||
440 | |||
441 | static void gfs2_demote_wake(struct gfs2_glock *gl) | ||
442 | { | ||
443 | clear_bit(GLF_DEMOTE, &gl->gl_flags); | ||
444 | smp_mb__after_clear_bit(); | ||
445 | wake_up_bit(&gl->gl_flags, GLF_DEMOTE); | ||
446 | } | ||
447 | |||
448 | static void wait_on_demote(struct gfs2_glock *gl) | ||
449 | { | ||
450 | might_sleep(); | ||
451 | wait_on_bit(&gl->gl_flags, GLF_DEMOTE, just_schedule, TASK_UNINTERRUPTIBLE); | ||
439 | } | 452 | } |
440 | 453 | ||
441 | /** | 454 | /** |
@@ -528,7 +541,7 @@ static int rq_demote(struct gfs2_glock *gl) | |||
528 | 541 | ||
529 | if (gl->gl_state == gl->gl_demote_state || | 542 | if (gl->gl_state == gl->gl_demote_state || |
530 | gl->gl_state == LM_ST_UNLOCKED) { | 543 | gl->gl_state == LM_ST_UNLOCKED) { |
531 | clear_bit(GLF_DEMOTE, &gl->gl_flags); | 544 | gfs2_demote_wake(gl); |
532 | return 0; | 545 | return 0; |
533 | } | 546 | } |
534 | set_bit(GLF_LOCK, &gl->gl_flags); | 547 | set_bit(GLF_LOCK, &gl->gl_flags); |
@@ -666,12 +679,22 @@ static void gfs2_glmutex_unlock(struct gfs2_glock *gl) | |||
666 | * practise: LM_ST_SHARED and LM_ST_UNLOCKED | 679 | * practise: LM_ST_SHARED and LM_ST_UNLOCKED |
667 | */ | 680 | */ |
668 | 681 | ||
669 | static void handle_callback(struct gfs2_glock *gl, unsigned int state) | 682 | static void handle_callback(struct gfs2_glock *gl, unsigned int state, int remote) |
670 | { | 683 | { |
671 | spin_lock(&gl->gl_spin); | 684 | spin_lock(&gl->gl_spin); |
672 | if (test_and_set_bit(GLF_DEMOTE, &gl->gl_flags) == 0) { | 685 | if (test_and_set_bit(GLF_DEMOTE, &gl->gl_flags) == 0) { |
673 | gl->gl_demote_state = state; | 686 | gl->gl_demote_state = state; |
674 | gl->gl_demote_time = jiffies; | 687 | gl->gl_demote_time = jiffies; |
688 | if (remote && gl->gl_ops->go_type == LM_TYPE_IOPEN && | ||
689 | gl->gl_object) { | ||
690 | struct inode *inode = igrab(gl->gl_object); | ||
691 | spin_unlock(&gl->gl_spin); | ||
692 | if (inode) { | ||
693 | d_prune_aliases(inode); | ||
694 | iput(inode); | ||
695 | } | ||
696 | return; | ||
697 | } | ||
675 | } else if (gl->gl_demote_state != LM_ST_UNLOCKED) { | 698 | } else if (gl->gl_demote_state != LM_ST_UNLOCKED) { |
676 | gl->gl_demote_state = state; | 699 | gl->gl_demote_state = state; |
677 | } | 700 | } |
@@ -740,7 +763,7 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) | |||
740 | if (ret & LM_OUT_CANCELED) | 763 | if (ret & LM_OUT_CANCELED) |
741 | op_done = 0; | 764 | op_done = 0; |
742 | else | 765 | else |
743 | clear_bit(GLF_DEMOTE, &gl->gl_flags); | 766 | gfs2_demote_wake(gl); |
744 | } else { | 767 | } else { |
745 | spin_lock(&gl->gl_spin); | 768 | spin_lock(&gl->gl_spin); |
746 | list_del_init(&gh->gh_list); | 769 | list_del_init(&gh->gh_list); |
@@ -848,7 +871,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret) | |||
848 | gfs2_assert_warn(sdp, !ret); | 871 | gfs2_assert_warn(sdp, !ret); |
849 | 872 | ||
850 | state_change(gl, LM_ST_UNLOCKED); | 873 | state_change(gl, LM_ST_UNLOCKED); |
851 | clear_bit(GLF_DEMOTE, &gl->gl_flags); | 874 | gfs2_demote_wake(gl); |
852 | 875 | ||
853 | if (glops->go_inval) | 876 | if (glops->go_inval) |
854 | glops->go_inval(gl, DIO_METADATA); | 877 | glops->go_inval(gl, DIO_METADATA); |
@@ -1174,7 +1197,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh) | |||
1174 | const struct gfs2_glock_operations *glops = gl->gl_ops; | 1197 | const struct gfs2_glock_operations *glops = gl->gl_ops; |
1175 | 1198 | ||
1176 | if (gh->gh_flags & GL_NOCACHE) | 1199 | if (gh->gh_flags & GL_NOCACHE) |
1177 | handle_callback(gl, LM_ST_UNLOCKED); | 1200 | handle_callback(gl, LM_ST_UNLOCKED, 0); |
1178 | 1201 | ||
1179 | gfs2_glmutex_lock(gl); | 1202 | gfs2_glmutex_lock(gl); |
1180 | 1203 | ||
@@ -1196,6 +1219,13 @@ void gfs2_glock_dq(struct gfs2_holder *gh) | |||
1196 | spin_unlock(&gl->gl_spin); | 1219 | spin_unlock(&gl->gl_spin); |
1197 | } | 1220 | } |
1198 | 1221 | ||
1222 | void gfs2_glock_dq_wait(struct gfs2_holder *gh) | ||
1223 | { | ||
1224 | struct gfs2_glock *gl = gh->gh_gl; | ||
1225 | gfs2_glock_dq(gh); | ||
1226 | wait_on_demote(gl); | ||
1227 | } | ||
1228 | |||
1199 | /** | 1229 | /** |
1200 | * gfs2_glock_dq_uninit - dequeue a holder from a glock and initialize it | 1230 | * gfs2_glock_dq_uninit - dequeue a holder from a glock and initialize it |
1201 | * @gh: the holder structure | 1231 | * @gh: the holder structure |
@@ -1456,7 +1486,7 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name, | |||
1456 | if (!gl) | 1486 | if (!gl) |
1457 | return; | 1487 | return; |
1458 | 1488 | ||
1459 | handle_callback(gl, state); | 1489 | handle_callback(gl, state, 1); |
1460 | 1490 | ||
1461 | spin_lock(&gl->gl_spin); | 1491 | spin_lock(&gl->gl_spin); |
1462 | run_queue(gl); | 1492 | run_queue(gl); |
@@ -1596,7 +1626,7 @@ void gfs2_reclaim_glock(struct gfs2_sbd *sdp) | |||
1596 | if (gfs2_glmutex_trylock(gl)) { | 1626 | if (gfs2_glmutex_trylock(gl)) { |
1597 | if (list_empty(&gl->gl_holders) && | 1627 | if (list_empty(&gl->gl_holders) && |
1598 | gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl)) | 1628 | gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl)) |
1599 | handle_callback(gl, LM_ST_UNLOCKED); | 1629 | handle_callback(gl, LM_ST_UNLOCKED, 0); |
1600 | gfs2_glmutex_unlock(gl); | 1630 | gfs2_glmutex_unlock(gl); |
1601 | } | 1631 | } |
1602 | 1632 | ||
@@ -1709,7 +1739,7 @@ static void clear_glock(struct gfs2_glock *gl) | |||
1709 | if (gfs2_glmutex_trylock(gl)) { | 1739 | if (gfs2_glmutex_trylock(gl)) { |
1710 | if (list_empty(&gl->gl_holders) && | 1740 | if (list_empty(&gl->gl_holders) && |
1711 | gl->gl_state != LM_ST_UNLOCKED) | 1741 | gl->gl_state != LM_ST_UNLOCKED) |
1712 | handle_callback(gl, LM_ST_UNLOCKED); | 1742 | handle_callback(gl, LM_ST_UNLOCKED, 0); |
1713 | gfs2_glmutex_unlock(gl); | 1743 | gfs2_glmutex_unlock(gl); |
1714 | } | 1744 | } |
1715 | } | 1745 | } |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index b3e152db70c8..7721ca3fff9e 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
@@ -87,6 +87,7 @@ int gfs2_glock_nq(struct gfs2_holder *gh); | |||
87 | int gfs2_glock_poll(struct gfs2_holder *gh); | 87 | int gfs2_glock_poll(struct gfs2_holder *gh); |
88 | int gfs2_glock_wait(struct gfs2_holder *gh); | 88 | int gfs2_glock_wait(struct gfs2_holder *gh); |
89 | void gfs2_glock_dq(struct gfs2_holder *gh); | 89 | void gfs2_glock_dq(struct gfs2_holder *gh); |
90 | void gfs2_glock_dq_wait(struct gfs2_holder *gh); | ||
90 | 91 | ||
91 | void gfs2_glock_dq_uninit(struct gfs2_holder *gh); | 92 | void gfs2_glock_dq_uninit(struct gfs2_holder *gh); |
92 | int gfs2_glock_nq_num(struct gfs2_sbd *sdp, | 93 | int gfs2_glock_nq_num(struct gfs2_sbd *sdp, |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 366235d6a5b5..792d64f69cc2 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -114,6 +114,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, u64 no_addr, unsigned in | |||
114 | error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); | 114 | error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); |
115 | if (unlikely(error)) | 115 | if (unlikely(error)) |
116 | goto fail_iopen; | 116 | goto fail_iopen; |
117 | ip->i_iopen_gh.gh_gl->gl_object = ip; | ||
117 | 118 | ||
118 | gfs2_glock_put(io_gl); | 119 | gfs2_glock_put(io_gl); |
119 | 120 | ||
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 485ce3d49923..603d940f1159 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c | |||
@@ -326,8 +326,10 @@ static void gfs2_clear_inode(struct inode *inode) | |||
326 | gfs2_glock_schedule_for_reclaim(ip->i_gl); | 326 | gfs2_glock_schedule_for_reclaim(ip->i_gl); |
327 | gfs2_glock_put(ip->i_gl); | 327 | gfs2_glock_put(ip->i_gl); |
328 | ip->i_gl = NULL; | 328 | ip->i_gl = NULL; |
329 | if (ip->i_iopen_gh.gh_gl) | 329 | if (ip->i_iopen_gh.gh_gl) { |
330 | ip->i_iopen_gh.gh_gl->gl_object = NULL; | ||
330 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 331 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
332 | } | ||
331 | } | 333 | } |
332 | } | 334 | } |
333 | 335 | ||
@@ -422,13 +424,13 @@ static void gfs2_delete_inode(struct inode *inode) | |||
422 | if (!inode->i_private) | 424 | if (!inode->i_private) |
423 | goto out; | 425 | goto out; |
424 | 426 | ||
425 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB, &gh); | 427 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
426 | if (unlikely(error)) { | 428 | if (unlikely(error)) { |
427 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 429 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
428 | goto out; | 430 | goto out; |
429 | } | 431 | } |
430 | 432 | ||
431 | gfs2_glock_dq(&ip->i_iopen_gh); | 433 | gfs2_glock_dq_wait(&ip->i_iopen_gh); |
432 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); | 434 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); |
433 | error = gfs2_glock_nq(&ip->i_iopen_gh); | 435 | error = gfs2_glock_nq(&ip->i_iopen_gh); |
434 | if (error) | 436 | if (error) |