diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-03-29 09:12:12 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-03-29 09:12:12 -0500 |
commit | 484adff8a06cb5d952832f5487ae863f54c0fb69 (patch) | |
tree | e43a9387a3a313cfdb4a34298d532dc7a1b7391c /fs/gfs2/log.c | |
parent | 7aabffcab47a0f881c7640f5c108e8d3f2e35ebf (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>
Diffstat (limited to 'fs/gfs2/log.c')
-rw-r--r-- | fs/gfs2/log.c | 67 |
1 files changed, 18 insertions, 49 deletions
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 | ||
32 | static 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 | |||
38 | static 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 | |||
45 | static 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 | |||
51 | static 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 | ||
225 | void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks) | 196 | void 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 | ||
592 | void gfs2_log_shutdown(struct gfs2_sbd *sdp) | 562 | void 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 | ||