提交 484adff8 编写于 作者: S Steven Whitehouse

[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: NSteven Whitehouse <swhiteho@redhat.com>
上级 7aabffca
...@@ -611,10 +611,6 @@ struct gfs2_sbd { ...@@ -611,10 +611,6 @@ struct gfs2_sbd {
/* Log stuff */ /* Log stuff */
spinlock_t sd_log_lock; 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_blks_reserved;
unsigned int sd_log_commited_buf; unsigned int sd_log_commited_buf;
...@@ -643,7 +639,7 @@ struct gfs2_sbd { ...@@ -643,7 +639,7 @@ struct gfs2_sbd {
int sd_log_idle; int sd_log_idle;
unsigned long sd_log_flush_time; 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; struct list_head sd_log_flush_list;
unsigned int sd_log_flush_head; unsigned int sd_log_flush_head;
......
...@@ -29,32 +29,6 @@ ...@@ -29,32 +29,6 @@
#define PULL 1 #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 * gfs2_struct2blk - compute stuff
* @sdp: the filesystem * @sdp: the filesystem
...@@ -109,9 +83,8 @@ void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags) ...@@ -109,9 +83,8 @@ void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags)
first = NULL; first = NULL;
for (;;) { for (;;) {
if (first && if (first && (head->prev != first ||
(head->prev != first || gfs2_ail1_empty_one(sdp, first_ai, 0)))
gfs2_ail1_empty_one(sdp, first_ai, 0)))
break; break;
for (tmp = head->prev; tmp != head; tmp = tmp->prev) { 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,23 +167,21 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
return -EINVAL; return -EINVAL;
mutex_lock(&sdp->sd_log_reserve_mutex); mutex_lock(&sdp->sd_log_reserve_mutex);
for (;;) { gfs2_log_lock(sdp);
gfs2_log_lock(sdp); while(sdp->sd_log_blks_free <= blks) {
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_unlock(sdp); gfs2_log_unlock(sdp);
gfs2_ail1_empty(sdp, 0); gfs2_ail1_empty(sdp, 0);
gfs2_log_flush(sdp); gfs2_log_flush(sdp);
if (try++) if (try++)
gfs2_ail1_start(sdp, 0); 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; return 0;
} }
...@@ -224,7 +195,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) ...@@ -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) 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); gfs2_log_lock(sdp);
sdp->sd_log_blks_free += blks; sdp->sd_log_blks_free += blks;
...@@ -474,20 +445,20 @@ void gfs2_log_flush_i(struct gfs2_sbd *sdp, struct gfs2_glock *gl) ...@@ -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); ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL);
INIT_LIST_HEAD(&ai->ai_ail1_list); INIT_LIST_HEAD(&ai->ai_ail1_list);
INIT_LIST_HEAD(&ai->ai_ail2_list); INIT_LIST_HEAD(&ai->ai_ail2_list);
gfs2_lock_for_flush(sdp);
down_write(&sdp->sd_log_flush_lock);
if (gl) { if (gl) {
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
if (list_empty(&gl->gl_le.le_list)) { if (list_empty(&gl->gl_le.le_list)) {
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
gfs2_unlock_from_flush(sdp); up_write(&sdp->sd_log_flush_lock);
kfree(ai); kfree(ai);
return; return;
} }
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
} }
mutex_lock(&sdp->sd_log_flush_lock);
gfs2_assert_withdraw(sdp, gfs2_assert_withdraw(sdp,
sdp->sd_log_num_buf == sdp->sd_log_commited_buf); 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,9 +490,8 @@ void gfs2_log_flush_i(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
} }
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
mutex_unlock(&sdp->sd_log_flush_lock);
sdp->sd_vfs->s_dirt = 0; sdp->sd_vfs->s_dirt = 0;
gfs2_unlock_from_flush(sdp); up_write(&sdp->sd_log_flush_lock);
kfree(ai); kfree(ai);
} }
...@@ -573,7 +543,7 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) ...@@ -573,7 +543,7 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
lops_incore_commit(sdp, tr); lops_incore_commit(sdp, tr);
sdp->sd_vfs->s_dirt = 1; sdp->sd_vfs->s_dirt = 1;
unlock_from_trans(sdp); up_read(&sdp->sd_log_flush_lock);
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
if (sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks)) { 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,9 +561,8 @@ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
void gfs2_log_shutdown(struct gfs2_sbd *sdp) 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_blks_reserved);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_gl); gfs2_assert_withdraw(sdp, !sdp->sd_log_num_gl);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf); gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf);
...@@ -618,6 +587,6 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp) ...@@ -618,6 +587,6 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
sdp->sd_log_wraps++; sdp->sd_log_wraps++;
sdp->sd_log_tail = sdp->sd_log_head; sdp->sd_log_tail = sdp->sd_log_head;
mutex_unlock(&sdp->sd_log_flush_lock); up_write(&sdp->sd_log_flush_lock);
} }
...@@ -88,8 +88,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) ...@@ -88,8 +88,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
mutex_init(&sdp->sd_quota_mutex); mutex_init(&sdp->sd_quota_mutex);
spin_lock_init(&sdp->sd_log_lock); 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_gl);
INIT_LIST_HEAD(&sdp->sd_log_le_buf); INIT_LIST_HEAD(&sdp->sd_log_le_buf);
...@@ -101,7 +99,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) ...@@ -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_ail1_list);
INIT_LIST_HEAD(&sdp->sd_ail2_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_log_flush_list);
INIT_LIST_HEAD(&sdp->sd_revoke_list); INIT_LIST_HEAD(&sdp->sd_revoke_list);
......
...@@ -74,10 +74,10 @@ int gfs2_trans_begin_i(struct gfs2_sbd *sdp, unsigned int blocks, ...@@ -74,10 +74,10 @@ int gfs2_trans_begin_i(struct gfs2_sbd *sdp, unsigned int blocks,
return 0; return 0;
fail_gunlock: fail_gunlock:
gfs2_glock_dq(&tr->tr_t_gh); gfs2_glock_dq(&tr->tr_t_gh);
fail_holder_uninit: fail_holder_uninit:
gfs2_holder_uninit(&tr->tr_t_gh); gfs2_holder_uninit(&tr->tr_t_gh);
kfree(tr); kfree(tr);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册