[GFS2] Update locking in log.c
authorSteven Whitehouse <swhiteho@redhat.com>
Wed, 29 Mar 2006 14:12:12 +0000 (09:12 -0500)
committerSteven Whitehouse <swhiteho@redhat.com>
Wed, 29 Mar 2006 14:12:12 +0000 (09:12 -0500)
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>
fs/gfs2/incore.h
fs/gfs2/log.c
fs/gfs2/ops_fstype.c
fs/gfs2/trans.c

index be30718..35163b5 100644 (file)
@@ -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;
index 16c1444..b103d9a 100644 (file)
 
 #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);
 }
 
index 2628bf3..5166455 100644 (file)
@@ -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);
index 63e7fed..aa1a619 100644 (file)
@@ -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);