aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-03-29 09:12:12 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-03-29 09:12:12 -0500
commit484adff8a06cb5d952832f5487ae863f54c0fb69 (patch)
treee43a9387a3a313cfdb4a34298d532dc7a1b7391c
parent7aabffcab47a0f881c7640f5c108e8d3f2e35ebf (diff)
[GFS2] Update locking in log.c
Replace the lock_for_trans()/lock_for_flush() functions with an rwsem. In fact the sd_log_flush_lock becomes an rwsem (the write part of it) and is extended slightly to cover everything that the lock_for_flush() used to cover. The read part of the lock is instead of lock_for_trans(). This corrects the races in the original code and reduces the code size. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/incore.h6
-rw-r--r--fs/gfs2/log.c67
-rw-r--r--fs/gfs2/ops_fstype.c4
-rw-r--r--fs/gfs2/trans.c4
4 files changed, 22 insertions, 59 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index be307185f492..35163b562460 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -611,10 +611,6 @@ struct gfs2_sbd {
611 /* Log stuff */ 611 /* Log stuff */
612 612
613 spinlock_t sd_log_lock; 613 spinlock_t sd_log_lock;
614 atomic_t sd_log_trans_count;
615 wait_queue_head_t sd_log_trans_wq;
616 atomic_t sd_log_flush_count;
617 wait_queue_head_t sd_log_flush_wq;
618 614
619 unsigned int sd_log_blks_reserved; 615 unsigned int sd_log_blks_reserved;
620 unsigned int sd_log_commited_buf; 616 unsigned int sd_log_commited_buf;
@@ -643,7 +639,7 @@ struct gfs2_sbd {
643 int sd_log_idle; 639 int sd_log_idle;
644 640
645 unsigned long sd_log_flush_time; 641 unsigned long sd_log_flush_time;
646 struct mutex sd_log_flush_lock; 642 struct rw_semaphore sd_log_flush_lock;
647 struct list_head sd_log_flush_list; 643 struct list_head sd_log_flush_list;
648 644
649 unsigned int sd_log_flush_head; 645 unsigned int sd_log_flush_head;
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 16c14441a371..b103d9acf40d 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -29,32 +29,6 @@
29 29
30#define PULL 1 30#define PULL 1
31 31
32static void lock_for_trans(struct gfs2_sbd *sdp)
33{
34 wait_event(sdp->sd_log_trans_wq, atomic_read(&sdp->sd_log_flush_count) ? 0 : 1);
35 atomic_inc(&sdp->sd_log_trans_count);
36}
37
38static void unlock_from_trans(struct gfs2_sbd *sdp)
39{
40 gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_trans_count));
41 if (atomic_dec_and_test(&sdp->sd_log_trans_count))
42 wake_up(&sdp->sd_log_flush_wq);
43}
44
45static void gfs2_lock_for_flush(struct gfs2_sbd *sdp)
46{
47 atomic_inc(&sdp->sd_log_flush_count);
48 wait_event(sdp->sd_log_flush_wq, atomic_read(&sdp->sd_log_trans_count) ? 0 : 1);
49}
50
51static void gfs2_unlock_from_flush(struct gfs2_sbd *sdp)
52{
53 gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_flush_count));
54 if (atomic_dec_and_test(&sdp->sd_log_flush_count))
55 wake_up(&sdp->sd_log_trans_wq);
56}
57
58/** 32/**
59 * gfs2_struct2blk - compute stuff 33 * gfs2_struct2blk - compute stuff
60 * @sdp: the filesystem 34 * @sdp: the filesystem
@@ -109,9 +83,8 @@ void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags)
109 first = NULL; 83 first = NULL;
110 84
111 for (;;) { 85 for (;;) {
112 if (first && 86 if (first && (head->prev != first ||
113 (head->prev != first || 87 gfs2_ail1_empty_one(sdp, first_ai, 0)))
114 gfs2_ail1_empty_one(sdp, first_ai, 0)))
115 break; 88 break;
116 89
117 for (tmp = head->prev; tmp != head; tmp = tmp->prev) { 90 for (tmp = head->prev; tmp != head; tmp = tmp->prev) {
@@ -194,23 +167,21 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
194 return -EINVAL; 167 return -EINVAL;
195 168
196 mutex_lock(&sdp->sd_log_reserve_mutex); 169 mutex_lock(&sdp->sd_log_reserve_mutex);
197 for (;;) { 170 gfs2_log_lock(sdp);
198 gfs2_log_lock(sdp); 171 while(sdp->sd_log_blks_free <= blks) {
199 if (sdp->sd_log_blks_free > blks) {
200 sdp->sd_log_blks_free -= blks;
201 gfs2_log_unlock(sdp);
202 mutex_unlock(&sdp->sd_log_reserve_mutex);
203 break;
204 }
205
206 gfs2_log_unlock(sdp); 172 gfs2_log_unlock(sdp);
207 gfs2_ail1_empty(sdp, 0); 173 gfs2_ail1_empty(sdp, 0);
208 gfs2_log_flush(sdp); 174 gfs2_log_flush(sdp);
209 175
210 if (try++) 176 if (try++)
211 gfs2_ail1_start(sdp, 0); 177 gfs2_ail1_start(sdp, 0);
178 gfs2_log_lock(sdp);
212 } 179 }
213 lock_for_trans(sdp); 180 sdp->sd_log_blks_free -= blks;
181 gfs2_log_unlock(sdp);
182 mutex_unlock(&sdp->sd_log_reserve_mutex);
183
184 down_read(&sdp->sd_log_flush_lock);
214 185
215 return 0; 186 return 0;
216} 187}
@@ -224,7 +195,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
224 195
225void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks) 196void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
226{ 197{
227 unlock_from_trans(sdp); 198 up_read(&sdp->sd_log_flush_lock);
228 199
229 gfs2_log_lock(sdp); 200 gfs2_log_lock(sdp);
230 sdp->sd_log_blks_free += blks; 201 sdp->sd_log_blks_free += blks;
@@ -474,20 +445,20 @@ void gfs2_log_flush_i(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
474 ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL); 445 ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL);
475 INIT_LIST_HEAD(&ai->ai_ail1_list); 446 INIT_LIST_HEAD(&ai->ai_ail1_list);
476 INIT_LIST_HEAD(&ai->ai_ail2_list); 447 INIT_LIST_HEAD(&ai->ai_ail2_list);
477 gfs2_lock_for_flush(sdp); 448
449 down_write(&sdp->sd_log_flush_lock);
478 450
479 if (gl) { 451 if (gl) {
480 gfs2_log_lock(sdp); 452 gfs2_log_lock(sdp);
481 if (list_empty(&gl->gl_le.le_list)) { 453 if (list_empty(&gl->gl_le.le_list)) {
482 gfs2_log_unlock(sdp); 454 gfs2_log_unlock(sdp);
483 gfs2_unlock_from_flush(sdp); 455 up_write(&sdp->sd_log_flush_lock);
484 kfree(ai); 456 kfree(ai);
485 return; 457 return;
486 } 458 }
487 gfs2_log_unlock(sdp); 459 gfs2_log_unlock(sdp);
488 } 460 }
489 461
490 mutex_lock(&sdp->sd_log_flush_lock);
491 462
492 gfs2_assert_withdraw(sdp, 463 gfs2_assert_withdraw(sdp,
493 sdp->sd_log_num_buf == sdp->sd_log_commited_buf); 464 sdp->sd_log_num_buf == sdp->sd_log_commited_buf);
@@ -519,9 +490,8 @@ void gfs2_log_flush_i(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
519 } 490 }
520 gfs2_log_unlock(sdp); 491 gfs2_log_unlock(sdp);
521 492
522 mutex_unlock(&sdp->sd_log_flush_lock);
523 sdp->sd_vfs->s_dirt = 0; 493 sdp->sd_vfs->s_dirt = 0;
524 gfs2_unlock_from_flush(sdp); 494 up_write(&sdp->sd_log_flush_lock);
525 495
526 kfree(ai); 496 kfree(ai);
527} 497}
@@ -573,7 +543,7 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
573 lops_incore_commit(sdp, tr); 543 lops_incore_commit(sdp, tr);
574 544
575 sdp->sd_vfs->s_dirt = 1; 545 sdp->sd_vfs->s_dirt = 1;
576 unlock_from_trans(sdp); 546 up_read(&sdp->sd_log_flush_lock);
577 547
578 gfs2_log_lock(sdp); 548 gfs2_log_lock(sdp);
579 if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks)) { 549 if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks)) {
@@ -591,9 +561,8 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
591 561
592void gfs2_log_shutdown(struct gfs2_sbd *sdp) 562void gfs2_log_shutdown(struct gfs2_sbd *sdp)
593{ 563{
594 mutex_lock(&sdp->sd_log_flush_lock); 564 down_write(&sdp->sd_log_flush_lock);
595 565
596 gfs2_assert_withdraw(sdp, !atomic_read(&sdp->sd_log_trans_count));
597 gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved); 566 gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved);
598 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_gl); 567 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_gl);
599 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf); 568 gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf);
@@ -618,6 +587,6 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
618 sdp->sd_log_wraps++; 587 sdp->sd_log_wraps++;
619 sdp->sd_log_tail = sdp->sd_log_head; 588 sdp->sd_log_tail = sdp->sd_log_head;
620 589
621 mutex_unlock(&sdp->sd_log_flush_lock); 590 up_write(&sdp->sd_log_flush_lock);
622} 591}
623 592
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 2628bf326334..5166455b9fdd 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -88,8 +88,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
88 mutex_init(&sdp->sd_quota_mutex); 88 mutex_init(&sdp->sd_quota_mutex);
89 89
90 spin_lock_init(&sdp->sd_log_lock); 90 spin_lock_init(&sdp->sd_log_lock);
91 init_waitqueue_head(&sdp->sd_log_trans_wq);
92 init_waitqueue_head(&sdp->sd_log_flush_wq);
93 91
94 INIT_LIST_HEAD(&sdp->sd_log_le_gl); 92 INIT_LIST_HEAD(&sdp->sd_log_le_gl);
95 INIT_LIST_HEAD(&sdp->sd_log_le_buf); 93 INIT_LIST_HEAD(&sdp->sd_log_le_buf);
@@ -101,7 +99,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
101 INIT_LIST_HEAD(&sdp->sd_ail1_list); 99 INIT_LIST_HEAD(&sdp->sd_ail1_list);
102 INIT_LIST_HEAD(&sdp->sd_ail2_list); 100 INIT_LIST_HEAD(&sdp->sd_ail2_list);
103 101
104 mutex_init(&sdp->sd_log_flush_lock); 102 init_rwsem(&sdp->sd_log_flush_lock);
105 INIT_LIST_HEAD(&sdp->sd_log_flush_list); 103 INIT_LIST_HEAD(&sdp->sd_log_flush_list);
106 104
107 INIT_LIST_HEAD(&sdp->sd_revoke_list); 105 INIT_LIST_HEAD(&sdp->sd_revoke_list);
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index 63e7fed2bd47..aa1a619f0854 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -74,10 +74,10 @@ int gfs2_trans_begin_i(struct gfs2_sbd *sdp, unsigned int blocks,
74 74
75 return 0; 75 return 0;
76 76
77 fail_gunlock: 77fail_gunlock:
78 gfs2_glock_dq(&tr->tr_t_gh); 78 gfs2_glock_dq(&tr->tr_t_gh);
79 79
80 fail_holder_uninit: 80fail_holder_uninit:
81 gfs2_holder_uninit(&tr->tr_t_gh); 81 gfs2_holder_uninit(&tr->tr_t_gh);
82 kfree(tr); 82 kfree(tr);
83 83