diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2007-09-17 11:59:52 +0200 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2007-10-10 09:56:24 +0200 |
commit | 16615be18cadf53ee6f8a4f0bdd647f0753421b1 (patch) | |
tree | 670c75e931e6d606211f338ee5e8b1d603c96521 /fs/gfs2/meta_io.c | |
parent | [GFS2] GFS2: chmod hung - fix race in thread creation (diff) | |
download | linux-16615be18cadf53ee6f8a4f0bdd647f0753421b1.tar.xz linux-16615be18cadf53ee6f8a4f0bdd647f0753421b1.zip |
[GFS2] Clean up journaled data writing
This patch cleans up the code for writing journaled data into the log.
It also removes the need to allocate a small "tag" structure for each
block written into the log. Instead we just keep count of the outstanding
I/O so that we can be sure that its all been written at the correct time.
Another result of this patch is that a number of ll_rw_block() calls
have become submit_bh() calls, closing some races at the same time.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/meta_io.c')
-rw-r--r-- | fs/gfs2/meta_io.c | 55 |
1 files changed, 32 insertions, 23 deletions
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 19097bc7c81d..1d80f2d42122 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -297,6 +297,37 @@ void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, unlock_page(bh->b_page); } +void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta) +{ + struct gfs2_sbd *sdp = GFS2_SB(bh->b_page->mapping->host); + struct gfs2_bufdata *bd = bh->b_private; + if (test_clear_buffer_pinned(bh)) { + list_del_init(&bd->bd_le.le_list); + if (meta) { + gfs2_assert_warn(sdp, sdp->sd_log_num_buf); + sdp->sd_log_num_buf--; + tr->tr_num_buf_rm++; + } else { + gfs2_assert_warn(sdp, sdp->sd_log_num_databuf); + sdp->sd_log_num_databuf--; + tr->tr_num_databuf_rm++; + } + tr->tr_touched = 1; + brelse(bh); + } + if (bd) { + if (bd->bd_ail) { + gfs2_remove_from_ail(NULL, bd); + bh->b_private = NULL; + bd->bd_bh = NULL; + bd->bd_blkno = bh->b_blocknr; + gfs2_trans_add_revoke(sdp, bd); + } + } + clear_buffer_dirty(bh); + clear_buffer_uptodate(bh); +} + /** * gfs2_meta_wipe - make inode's buffers so they aren't dirty/pinned anymore * @ip: the inode who owns the buffers @@ -313,33 +344,11 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen) while (blen) { bh = getbuf(ip->i_gl, bstart, NO_CREATE); if (bh) { - struct gfs2_bufdata *bd; - lock_buffer(bh); gfs2_log_lock(sdp); - bd = bh->b_private; - if (test_clear_buffer_pinned(bh)) { - struct gfs2_trans *tr = current->journal_info; - list_del_init(&bd->bd_le.le_list); - gfs2_assert_warn(sdp, sdp->sd_log_num_buf); - sdp->sd_log_num_buf--; - tr->tr_num_buf_rm++; - brelse(bh); - } - if (bd) { - if (bd->bd_ail) { - gfs2_remove_from_ail(NULL, bd); - bh->b_private = NULL; - bd->bd_bh = NULL; - bd->bd_blkno = bh->b_blocknr; - gfs2_trans_add_revoke(sdp, bd); - } - } - clear_buffer_dirty(bh); - clear_buffer_uptodate(bh); + gfs2_remove_from_journal(bh, current->journal_info, 1); gfs2_log_unlock(sdp); unlock_buffer(bh); - brelse(bh); } |