From 484adff8a06cb5d952832f5487ae863f54c0fb69 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 29 Mar 2006 09:12:12 -0500 Subject: [PATCH] [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 --- fs/gfs2/incore.h | 6 +--- fs/gfs2/log.c | 67 ++++++++++++-------------------------------- fs/gfs2/ops_fstype.c | 4 +-- fs/gfs2/trans.c | 4 +-- 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 { /* Log stuff */ spinlock_t sd_log_lock; - atomic_t sd_log_trans_count; - wait_queue_head_t sd_log_trans_wq; - atomic_t sd_log_flush_count; - wait_queue_head_t sd_log_flush_wq; unsigned int sd_log_blks_reserved; unsigned int sd_log_commited_buf; @@ -643,7 +639,7 @@ struct gfs2_sbd { int sd_log_idle; unsigned long sd_log_flush_time; - struct mutex sd_log_flush_lock; + struct rw_semaphore sd_log_flush_lock; struct list_head sd_log_flush_list; 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 @@ #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); } 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) mutex_init(&sdp->sd_quota_mutex); spin_lock_init(&sdp->sd_log_lock); - init_waitqueue_head(&sdp->sd_log_trans_wq); - init_waitqueue_head(&sdp->sd_log_flush_wq); INIT_LIST_HEAD(&sdp->sd_log_le_gl); INIT_LIST_HEAD(&sdp->sd_log_le_buf); @@ -101,7 +99,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) INIT_LIST_HEAD(&sdp->sd_ail1_list); INIT_LIST_HEAD(&sdp->sd_ail2_list); - mutex_init(&sdp->sd_log_flush_lock); + init_rwsem(&sdp->sd_log_flush_lock); INIT_LIST_HEAD(&sdp->sd_log_flush_list); 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, return 0; - fail_gunlock: +fail_gunlock: gfs2_glock_dq(&tr->tr_t_gh); - fail_holder_uninit: +fail_holder_uninit: gfs2_holder_uninit(&tr->tr_t_gh); kfree(tr); -- GitLab