summaryrefslogtreecommitdiff
path: root/fs/gfs2/log.c
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 /fs/gfs2/log.c
parent7aabffcab47a0f881c7640f5c108e8d3f2e35ebf (diff)
downloadlwn-484adff8a06cb5d952832f5487ae863f54c0fb69.tar.gz
lwn-484adff8a06cb5d952832f5487ae863f54c0fb69.zip
[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.c67
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 @@
#define PULL 1
-static void lock_for_trans(struct gfs2_sbd *sdp)
-{
- wait_event(sdp->sd_log_trans_wq, atomic_read(&sdp->sd_log_flush_count) ? 0 : 1);
- atomic_inc(&sdp->sd_log_trans_count);
-}
-
-static void unlock_from_trans(struct gfs2_sbd *sdp)
-{
- gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_trans_count));
- if (atomic_dec_and_test(&sdp->sd_log_trans_count))
- wake_up(&sdp->sd_log_flush_wq);
-}
-
-static void gfs2_lock_for_flush(struct gfs2_sbd *sdp)
-{
- atomic_inc(&sdp->sd_log_flush_count);
- wait_event(sdp->sd_log_flush_wq, atomic_read(&sdp->sd_log_trans_count) ? 0 : 1);
-}
-
-static void gfs2_unlock_from_flush(struct gfs2_sbd *sdp)
-{
- gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_flush_count));
- if (atomic_dec_and_test(&sdp->sd_log_flush_count))
- wake_up(&sdp->sd_log_trans_wq);
-}
-
/**
* gfs2_struct2blk - compute stuff
* @sdp: the filesystem
@@ -109,9 +83,8 @@ void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags)
first = NULL;
for (;;) {
- if (first &&
- (head->prev != first ||
- gfs2_ail1_empty_one(sdp, first_ai, 0)))
+ if (first && (head->prev != first ||
+ gfs2_ail1_empty_one(sdp, first_ai, 0)))
break;
for (tmp = head->prev; tmp != head; tmp = tmp->prev) {
@@ -194,23 +167,21 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
return -EINVAL;
mutex_lock(&sdp->sd_log_reserve_mutex);
- for (;;) {
- gfs2_log_lock(sdp);
- if (sdp->sd_log_blks_free > blks) {
- sdp->sd_log_blks_free -= blks;
- gfs2_log_unlock(sdp);
- mutex_unlock(&sdp->sd_log_reserve_mutex);
- break;
- }
-
+ gfs2_log_lock(sdp);
+ while(sdp->sd_log_blks_free <= blks) {
gfs2_log_unlock(sdp);
gfs2_ail1_empty(sdp, 0);
gfs2_log_flush(sdp);
if (try++)
gfs2_ail1_start(sdp, 0);
+ gfs2_log_lock(sdp);
}
- lock_for_trans(sdp);
+ sdp->sd_log_blks_free -= blks;
+ gfs2_log_unlock(sdp);
+ mutex_unlock(&sdp->sd_log_reserve_mutex);
+
+ down_read(&sdp->sd_log_flush_lock);
return 0;
}
@@ -224,7 +195,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
{
- unlock_from_trans(sdp);
+ up_read(&sdp->sd_log_flush_lock);
gfs2_log_lock(sdp);
sdp->sd_log_blks_free += blks;
@@ -474,20 +445,20 @@ void gfs2_log_flush_i(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL);
INIT_LIST_HEAD(&ai->ai_ail1_list);
INIT_LIST_HEAD(&ai->ai_ail2_list);
- gfs2_lock_for_flush(sdp);
+
+ down_write(&sdp->sd_log_flush_lock);
if (gl) {
gfs2_log_lock(sdp);
if (list_empty(&gl->gl_le.le_list)) {
gfs2_log_unlock(sdp);
- gfs2_unlock_from_flush(sdp);
+ up_write(&sdp->sd_log_flush_lock);
kfree(ai);
return;
}
gfs2_log_unlock(sdp);
}
- mutex_lock(&sdp->sd_log_flush_lock);
gfs2_assert_withdraw(sdp,
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)
}
gfs2_log_unlock(sdp);
- mutex_unlock(&sdp->sd_log_flush_lock);
sdp->sd_vfs->s_dirt = 0;
- gfs2_unlock_from_flush(sdp);
+ up_write(&sdp->sd_log_flush_lock);
kfree(ai);
}
@@ -573,7 +543,7 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
lops_incore_commit(sdp, tr);
sdp->sd_vfs->s_dirt = 1;
- unlock_from_trans(sdp);
+ up_read(&sdp->sd_log_flush_lock);
gfs2_log_lock(sdp);
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)
void gfs2_log_shutdown(struct gfs2_sbd *sdp)
{
- mutex_lock(&sdp->sd_log_flush_lock);
+ down_write(&sdp->sd_log_flush_lock);
- gfs2_assert_withdraw(sdp, !atomic_read(&sdp->sd_log_trans_count));
gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_gl);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf);
@@ -618,6 +587,6 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
sdp->sd_log_wraps++;
sdp->sd_log_tail = sdp->sd_log_head;
- mutex_unlock(&sdp->sd_log_flush_lock);
+ up_write(&sdp->sd_log_flush_lock);
}